第六次合并 #6

Merged
m6omickaf merged 3 commits from dev into master 2 years ago

@ -10,10 +10,13 @@
- 2023/4/21 完成新功能需求文档
- 2023/4/28 新体系结构初稿设计完成
- 2023/4/28 新功能UI雏形设计完成
- 2023/5/26 久违的更新了readme文件
- 2023/5/26 完成了回收站的雏形
## TODO
- [x] 新功能需求分析
- [ ] 新功能实现
- [ ] 回收站
- [ ] BUG修复
- [x] 体系结构
- [ ] UI设计
- [ ] 背景切换
- [ ] 代码质量分析报告
- [ ] 需求与设计方案
- [ ] 汇报PPT

@ -12,6 +12,6 @@
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-04-10T13:04:51.122769700Z" />
<timeTargetWasSelectedWithDropDown value="2023-05-26T06:09:38.060917300Z" />
</component>
</project>

@ -40,17 +40,27 @@
android:configChanges="keyboardHidden|orientation|screenSize"
android:label="@string/app_name"
android:launchMode="singleTop"
android:theme="@style/Theme.AppCompat"
android:uiOptions="splitActionBarWhenNarrow"
android:theme="@style/NoteTheme"
android:windowSoftInputMode="adjustPan"
android:exported="true" >
<!-- android:theme="@style/Theme.AppCompat"-->
<!-- android:uiOptions="splitActionBarWhenNarrow"-->
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ui.RecycleBinActivity"
android:configChanges="keyboardHidden|orientation|screenLayout"
android:launchMode="singleTop"
android:theme="@style/NoteTheme"
android:exported="true">
</activity>
<activity
android:name=".ui.NoteEditActivity"
android:configChanges="keyboardHidden|orientation|screenSize"

@ -17,6 +17,7 @@
package net.micode.notes.ui;
import android.app.Activity;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlarmManager;
import android.app.AlertDialog;
import android.app.PendingIntent;

@ -80,7 +80,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
public class NotesListActivity extends AppCompatActivity implements OnClickListener, OnItemLongClickListener {
public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
@ -472,24 +472,35 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
}
private void batchDelete() {
new AsyncTask<Void, Void, HashSet<AppWidgetAttribute>>() {
protected HashSet<AppWidgetAttribute> doInBackground(Void... unused) {
HashSet<AppWidgetAttribute> widgets = mNotesListAdapter.getSelectedWidget();
if (!isSyncMode()) {
// if not synced, delete notes directly
if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
.getSelectedItemIds())) {
} else {
Log.e(TAG, "Delete notes error, should not happens");
}
} else {
// in sync mode, we'll move the deleted note into the trash
// folder
// if (!isSyncMode()) {
// // if not synced, delete notes directly
// if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
// .getSelectedItemIds())) {
// } else {
// Log.e(TAG, "Delete notes error, should not happens");
// }
// } else {
// // in sync mode, we'll move the deleted note into the trash
// // folder
// if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter
// .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) {
// Log.e(TAG, "Move notes to trash folder error, should not happens");
// }
// }
// return widgets;
mCurrentFolderId = mFocusNoteDataItem.getFolderId();
//move to trash
if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter
.getSelectedItemIds(), Notes.ID_TRASH_FOLER)) {
Log.e(TAG, "Move notes to trash folder error, should not happens");
}
}
return widgets;
}
@ -814,12 +825,31 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
case R.id.menu_search:
onSearchRequested();
break;
case R.id.RecycleBin:
recycleBin();
break;
default:
break;
}
return true;
}
// private void recycleBin(){
// mState = ListEditState.SUB_FOLDER;
// mCurrentFolderId = Notes.ID_TRASH_FOLER;
// startAsyncNotesListQuery();
// mTitleBar.setText("trash folder");
// mTitleBar.setVisibility(View.VISIBLE);
// }
private void recycleBin() {
Intent intent=new Intent(NotesListActivity.this,RecycleBinActivity.class);
startActivity(intent);
mTitleBar.setText("trash folder");
mTitleBar.setVisibility(View.VISIBLE);
finish();
}
@Override
public boolean onSearchRequested() {
startSearch(null, false, null /* appData */, false);

@ -0,0 +1,247 @@
package net.micode.notes.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.tool.DataUtils;
public class RecycleBinActivity extends Activity {
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
private BackgroundQueryHandler mBackgroundQueryHandler;
private NotesListAdapter mNotesListAdapter;
private ListView mNotesListView;
private long mCurrentFolderId;
private ContentResolver mContentResolver;
private static final String TAG = "RecycleActivity";
private MenuItem menuItem;
private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=?";
private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>"
+ Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?)" + " OR ("
+ NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND "
+ NoteColumns.NOTES_COUNT + ">0)";
private final static int REQUEST_CODE_OPEN_NODE = 102;
private final static int REQUEST_CODE_NEW_NODE = 103;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycle_bin);
initResources();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK
&& (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) {
mNotesListAdapter.changeCursor(null);
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
protected void onStart() {
super.onStart();
startAsyncNotesListQuery();
}
@SuppressLint("InflateParams")
private void initResources() {
mContentResolver = this.getContentResolver();
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
mCurrentFolderId = Notes.ID_TRASH_FOLER;
mNotesListView = findViewById(R.id.recycle_list);
mNotesListView.addFooterView(LayoutInflater.from(this).inflate(R.layout.note_list_footer, null),
null, false);
mNotesListView.setOnItemClickListener(new OnListItemClickListener());
mNotesListAdapter = new NotesListAdapter(this);
mNotesListAdapter.setChoiceMode(true);
mNotesListView.setAdapter(mNotesListAdapter);
}
/**
*
*/
private void reset_ChoiseMode() {
mNotesListAdapter.setChoiceMode(false);
mNotesListAdapter.setChoiceMode(true);
}
private void startAsyncNotesListQuery() {
String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
: NORMAL_SELECTION;
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, new String[]{
String.valueOf(mCurrentFolderId)
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
@SuppressLint("HandlerLeak")
private final class BackgroundQueryHandler extends AsyncQueryHandler {
public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
}
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
switch (token) {
case FOLDER_NOTE_LIST_QUERY_TOKEN:
mNotesListAdapter.changeCursor(cursor);
break;
case FOLDER_LIST_QUERY_TOKEN:
if (cursor != null && cursor.getCount() > 0) {
showFolderListMenu(cursor);
} else {
Log.e(TAG, "Query folder failed");
}
break;
default:
}
}
}
private void showFolderListMenu(Cursor cursor) {
AlertDialog.Builder builder = new AlertDialog.Builder(RecycleBinActivity.this);
builder.setTitle(R.string.menu_title_select_folder);
final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor);
builder.setAdapter(adapter, (dialog, which) -> {
DataUtils.batchMoveToFolder(mContentResolver,
mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which));
Toast.makeText(
RecycleBinActivity.this,
getString(R.string.format_move_notes_to_folder,
mNotesListAdapter.getSelectedCount(),
adapter.getFolderName(RecycleBinActivity.this, which)),
Toast.LENGTH_SHORT).show();
});
builder.show();
}
// TODO: 2023/5/26 修改一下删除函数
private void batchDelete() {
// delete notes directly
if (!DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
.getSelectedItemIds())) {
Log.e(TAG, "Delete notes error, should not happens");
}
}
@Override
public void onBackPressed() {
Intent intent = new Intent(RecycleBinActivity.this, NotesListActivity.class);
startActivity(intent);
finish();
}
@Override
public void onContextMenuClosed(Menu menu) {
super.onContextMenuClosed(menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.recyclebin_options, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
getMenuInflater().inflate(R.menu.recyclebin_options, menu);
menuItem = menu.findItem(R.id.select_all);
return true;
}
/**
*
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO: 2023/5/26 为这两个选项加入弹窗
if (item.getItemId() == R.id.recover) {
if (!DataUtils.batchMoveToFolder(mContentResolver,
mNotesListAdapter.getSelectedItemIds(), Notes.ID_ROOT_FOLDER))
Log.e(TAG, "Recover error, should not happens");
} else if (item.getItemId() == R.id.realdelete) {
batchDelete();
} else if (item.getItemId() == R.id.select_all) {
if (!mNotesListAdapter.isAllSelected()) {
item.setTitle("deselect_all");
mNotesListAdapter.selectAll(true);
} else {
item.setTitle("selected_all");
mNotesListAdapter.selectAll(false);
}
return true;
}
reset_ChoiseMode();
return true;
}
@Override
public boolean onSearchRequested() {
startSearch(null, false, null /* appData */, false);
return true;
}
// TODO: 2023/5/26 将title改成一个icon
private class OnListItemClickListener implements OnItemClickListener {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (view instanceof NotesListItem) {
NoteItemData item = ((NotesListItem) view).getItemData();
if (item.getType() == Notes.TYPE_NOTE) {
position = position - mNotesListView.getHeaderViewsCount();
mNotesListAdapter.setCheckedItem(position, !mNotesListAdapter.isSelectedItem(position));
if (mNotesListAdapter.isAllSelected())
menuItem.setTitle("deselected_all");
else if (menuItem.getTitle() == "deselected_all")
menuItem.setTitle("selected_all");
}
}
}
}
}

@ -31,11 +31,11 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/title_bar_bg"
android:visibility="gone"
android:gravity="center_vertical"
android:singleLine="true"
android:textColor="#FFEAD1AE"
android:textSize="@dimen/text_font_size_medium" />
android:textSize="@dimen/text_font_size_medium"
android:visibility="gone" />
<ListView
android:id="@+id/notes_list"

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/list_background">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
tools:ignore="UselessParent">
<ListView
android:id="@+id/recycle_list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:cacheColorHint="@null"
android:listSelector="@android:color/transparent"
android:divider="@null"
android:fadingEdge="none" />
</LinearLayout>
</FrameLayout>

@ -36,4 +36,8 @@
<item
android:id="@+id/menu_search"
android:title="@string/menu_search"/>
<item
android:id='@+id/RecycleBin'
android:title="RecycleBin"/>
</menu>

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/select_all"
android:title="@android:string/selectAll"
android:showAsAction="always"/>
<item
android:id="@+id/recover"
android:title="@string/recover"
android:icon="@drawable/menu_move"
android:showAsAction="always" />
<item
android:id="@+id/realdelete"
android:title="@string/realdelete"
android:icon="@drawable/menu_delete"
android:showAsAction="always" />
</menu>

@ -126,6 +126,8 @@
<string name="search">Notes</string>
<string name="datetime_dialog_ok">set</string>
<string name="datetime_dialog_cancel">cancel</string>
<string name="realdelete">realdelete</string>
<string name="recover">recover</string>
<plurals name="search_results_title">
<item quantity="one"><xliff:g id="number" example="1">%1$s</xliff:g> result for \"<xliff:g id="search" example="???">%2$s</xliff:g>\"</item>
<!-- Case of 0 or 2 or more results. -->

@ -64,6 +64,6 @@
<style name="NoteActionBarStyle" parent="@android:style/Widget.Holo.Light.ActionBar.Solid">
<item name="android:displayOptions" />
<item name="android:visibility">gone</item>
<item name="android:visibility">visible</item>
</style>
</resources>
Loading…
Cancel
Save