|
|
|
@ -16,6 +16,7 @@
|
|
|
|
|
|
|
|
|
|
package net.micode.notes.ui;
|
|
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint;
|
|
|
|
|
import android.app.Activity;
|
|
|
|
|
import android.app.AlertDialog;
|
|
|
|
|
import android.app.Dialog;
|
|
|
|
@ -92,8 +93,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction";
|
|
|
|
|
|
|
|
|
|
private enum ListEditState {
|
|
|
|
|
NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER
|
|
|
|
|
}; //NOTE: 三种编辑状态@zhoukexing 2024/1/2 19:31
|
|
|
|
|
NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER, TRASH_FOLDER
|
|
|
|
|
}; //NOTE: 三种编辑状态@zhoukexing 2024/1/2 19:31 新增一个
|
|
|
|
|
|
|
|
|
|
private ListEditState mState;
|
|
|
|
|
|
|
|
|
@ -135,6 +136,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
private final static int REQUEST_CODE_OPEN_NODE = 102;
|
|
|
|
|
private final static int REQUEST_CODE_NEW_NODE = 103;
|
|
|
|
|
|
|
|
|
|
private String mTitle;
|
|
|
|
|
private String mMessage;
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
protected void onCreate(Bundle savedInstanceState) {
|
|
|
|
|
super.onCreate(savedInstanceState);
|
|
|
|
@ -321,11 +325,26 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
|
|
|
|
|
int itemId = item.getItemId();
|
|
|
|
|
if (itemId == R.id.delete) {
|
|
|
|
|
switch (mState) {
|
|
|
|
|
case SUB_FOLDER:
|
|
|
|
|
case CALL_RECORD_FOLDER:
|
|
|
|
|
case NOTE_LIST:
|
|
|
|
|
mTitle = getString(R.string.alert_title_delete);
|
|
|
|
|
mMessage = getString(R.string.alert_message_delete_notes,
|
|
|
|
|
mNotesListAdapter.getSelectedCount());
|
|
|
|
|
break;
|
|
|
|
|
case TRASH_FOLDER:
|
|
|
|
|
mTitle = getString(R.string.alert_title_delete_true);
|
|
|
|
|
mMessage = getString(R.string.alert_message_delete_notes_true,
|
|
|
|
|
mNotesListAdapter.getSelectedCount());
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
|
|
|
|
|
builder.setTitle(getString(R.string.alert_title_delete));
|
|
|
|
|
builder.setTitle(mTitle);
|
|
|
|
|
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
|
|
|
|
builder.setMessage(getString(R.string.alert_message_delete_notes,
|
|
|
|
|
mNotesListAdapter.getSelectedCount()));
|
|
|
|
|
builder.setMessage(mMessage);
|
|
|
|
|
builder.setPositiveButton(android.R.string.ok,
|
|
|
|
|
new DialogInterface.OnClickListener() {
|
|
|
|
|
public void onClick(DialogInterface dialog,
|
|
|
|
@ -357,7 +376,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
/**
|
|
|
|
|
* Minus TitleBar's height
|
|
|
|
|
*/
|
|
|
|
|
if (mState == ListEditState.SUB_FOLDER) {
|
|
|
|
|
if (mState == ListEditState.SUB_FOLDER |
|
|
|
|
|
mState == ListEditState.TRASH_FOLDER) {
|
|
|
|
|
// 回收站的ui显示 @zkx
|
|
|
|
|
eventY -= mTitleBar.getHeight();
|
|
|
|
|
start -= mTitleBar.getHeight();
|
|
|
|
|
}
|
|
|
|
@ -473,34 +494,34 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @method: batchDelete
|
|
|
|
|
* @description: 删除若干个选中的便签。
|
|
|
|
|
* 根据NotesListAdapter里的mSelectedIndex数据成员里的标记,为真表示选中,予以删除。
|
|
|
|
|
* @date: 2024/1/3 23:02
|
|
|
|
|
* @author: zhoukexing
|
|
|
|
|
* @param: []
|
|
|
|
|
* @return: void
|
|
|
|
|
*/
|
|
|
|
|
private void batchDelete() {
|
|
|
|
|
new AsyncTask<Void, Void, HashSet<AppWidgetAttribute>>() {
|
|
|
|
|
@SuppressLint("StaticFieldLeak")
|
|
|
|
|
protected HashSet<AppWidgetAttribute> doInBackground(Void... unused) {
|
|
|
|
|
HashSet<AppWidgetAttribute> widgets = mNotesListAdapter.getSelectedWidget();
|
|
|
|
|
// if (!isSyncMode()) { //在AS的虚拟机里,不能联网,不在同步模式下
|
|
|
|
|
// // if not synced, delete notes directly
|
|
|
|
|
// if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
|
|
|
|
|
// .getSelectedItemIds())) {
|
|
|
|
|
// } else {
|
|
|
|
|
// Log.e(TAG, "Delete notes error, should not happens");
|
|
|
|
|
// }
|
|
|
|
|
// } else {
|
|
|
|
|
if (mCurrentFolderId == Notes.ID_TRASH_FOLER){
|
|
|
|
|
// if in trash, really delete notes
|
|
|
|
|
if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
|
|
|
|
|
.getSelectedItemIds())) {
|
|
|
|
|
} else {
|
|
|
|
|
Log.e(TAG, "Delete notes error, should not happens");
|
|
|
|
|
}
|
|
|
|
|
if (mCurrentFolderId == Notes.ID_TRASH_FOLER){
|
|
|
|
|
// if in trash, really delete notes
|
|
|
|
|
if (DataUtils.batchDeleteNotes(mContentResolver, mNotesListAdapter
|
|
|
|
|
.getSelectedItemIds())) {
|
|
|
|
|
} else {
|
|
|
|
|
// move notes to trash
|
|
|
|
|
if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter
|
|
|
|
|
.getSelectedItemIds(), Notes.ID_TRASH_FOLER)) {
|
|
|
|
|
Log.e(TAG, "Move notes to trash folder error, should not happens");
|
|
|
|
|
}
|
|
|
|
|
Log.e(TAG, "Delete notes error, should not happens");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
} else {
|
|
|
|
|
// move notes 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -508,8 +529,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
protected void onPostExecute(HashSet<AppWidgetAttribute> widgets) {
|
|
|
|
|
if (widgets != null) {
|
|
|
|
|
for (AppWidgetAttribute widget : widgets) {
|
|
|
|
|
// widget挂件的Id和Type都不是非法的《==》存在这个widget挂件 @zkx
|
|
|
|
|
if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID
|
|
|
|
|
&& widget.widgetType != Notes.TYPE_WIDGET_INVALIDE) {
|
|
|
|
|
// ==》 删除这个挂件
|
|
|
|
|
updateWidget(widget.widgetId, widget.widgetType);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -538,11 +561,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
// 所有与要删除文件夹相关的 widgets
|
|
|
|
|
HashSet<AppWidgetAttribute> widgets = DataUtils.getFolderNoteWidget(mContentResolver,
|
|
|
|
|
folderId);
|
|
|
|
|
if (!isSyncMode()) {
|
|
|
|
|
// if not synced, delete folder directly
|
|
|
|
|
if (mCurrentFolderId == Notes.ID_TRASH_FOLER) {
|
|
|
|
|
// if in trash, delete folder directly
|
|
|
|
|
DataUtils.batchDeleteNotes(mContentResolver, ids);
|
|
|
|
|
} else {
|
|
|
|
|
// in sync mode, we'll move the deleted folder into the trash folder
|
|
|
|
|
// move the deleted folder into the trash folder
|
|
|
|
|
DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER);
|
|
|
|
|
}
|
|
|
|
|
// 更新 widgets
|
|
|
|
@ -726,7 +749,13 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
// 特殊情况:子文件夹是“回收站”,要显式地说明展示底部栏(模仿下面的call_record_folder) @zkx
|
|
|
|
|
// 添加mAddNewNote.setVisibility(View.VISIBLE);此行后,
|
|
|
|
|
// sub_folder 和 call_record_folder 两种情况无差别,无需分开处理
|
|
|
|
|
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
|
|
|
|
|
mState = ListEditState.NOTE_LIST;
|
|
|
|
|
mTitleBar.setVisibility(View.GONE);
|
|
|
|
|
startAsyncNotesListQuery();
|
|
|
|
|
break;
|
|
|
|
|
case CALL_RECORD_FOLDER:
|
|
|
|
|
case TRASH_FOLDER:
|
|
|
|
|
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
|
|
|
|
|
mState = ListEditState.NOTE_LIST;
|
|
|
|
|
mAddNewNote.setVisibility(View.VISIBLE);
|
|
|
|
@ -840,6 +869,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
GTaskSyncService.isSyncing() ? R.string.menu_sync_cancel : R.string.menu_sync);
|
|
|
|
|
} else if (mState == ListEditState.SUB_FOLDER) {
|
|
|
|
|
getMenuInflater().inflate(R.menu.sub_folder, menu);
|
|
|
|
|
} else if (mState == ListEditState.TRASH_FOLDER) {
|
|
|
|
|
getMenuInflater().inflate(R.menu.trash_folder, menu);
|
|
|
|
|
} else if (mState == ListEditState.CALL_RECORD_FOLDER) {
|
|
|
|
|
getMenuInflater().inflate(R.menu.call_record_folder, menu);
|
|
|
|
|
} else {
|
|
|
|
@ -881,10 +912,45 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
onSearchRequested();
|
|
|
|
|
} else if (itemId == R.id.menu_trash) {
|
|
|
|
|
openTrashFolder();
|
|
|
|
|
} else if (itemId == R.id.menu_empty_trash) {
|
|
|
|
|
emptyTrashFolder();
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @method: emptyTrashFolder
|
|
|
|
|
* @description: 通过“选中”回收站下所有便签,清空整个回收站
|
|
|
|
|
* @date: 2024/1/3 22:59
|
|
|
|
|
* @author: zhoukexing
|
|
|
|
|
* @param: []
|
|
|
|
|
* @return: void
|
|
|
|
|
*/
|
|
|
|
|
private void emptyTrashFolder() {
|
|
|
|
|
// 利用已有函数,在数据结构上“选中”所有便签 @zkx
|
|
|
|
|
mNotesListAdapter.selectAll(true);
|
|
|
|
|
// 模仿选中R.id.delete,构建对话框
|
|
|
|
|
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
|
|
|
|
|
builder.setTitle(getString(R.string.alert_title_delete_true));
|
|
|
|
|
builder.setIcon(android.R.drawable.ic_dialog_alert);
|
|
|
|
|
builder.setMessage(getString(R.string.alert_message_delete_notes_true,
|
|
|
|
|
mNotesListAdapter.getMNotesCount()));
|
|
|
|
|
builder.setPositiveButton(android.R.string.ok,
|
|
|
|
|
new DialogInterface.OnClickListener() {
|
|
|
|
|
public void onClick(DialogInterface dialog,
|
|
|
|
|
int which) {
|
|
|
|
|
// 这里体现了【层次化/模块化】的软件哲学。
|
|
|
|
|
// 当时实现这个功能有两条路可以走,
|
|
|
|
|
// 一条是:修改已有batchDelete里的select函数,改为选中所有,实现一个alldelete函数
|
|
|
|
|
// 一条是:利用batchDelete的功能(删除选中的便签),在进入batchDelete前选中所有
|
|
|
|
|
// 后者是更好的。前者需要修改方法,是侵入式的,而且会造成许多代码的重复,没有做到方法与方法之间的低耦合。
|
|
|
|
|
batchDelete();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
builder.setNegativeButton(android.R.string.cancel, null);
|
|
|
|
|
builder.show();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @method: openTrashFolder
|
|
|
|
|
* @description: 打开回收站 todo:添加30天后自动删除【时间】
|
|
|
|
@ -897,7 +963,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
mCurrentFolderId = Notes.ID_TRASH_FOLER;
|
|
|
|
|
startAsyncNotesListQuery();
|
|
|
|
|
// 正常打开文件夹
|
|
|
|
|
mState = ListEditState.SUB_FOLDER;
|
|
|
|
|
mState = ListEditState.TRASH_FOLDER;
|
|
|
|
|
// 将顶部栏设置为 data.getSnippet 文件夹名称
|
|
|
|
|
mTitleBar.setText(NotesListActivity.this
|
|
|
|
|
.getString(R.string.menu_trash));
|
|
|
|
@ -1012,6 +1078,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
|
|
|
|
|
break;
|
|
|
|
|
case SUB_FOLDER:
|
|
|
|
|
case CALL_RECORD_FOLDER:
|
|
|
|
|
case TRASH_FOLDER:
|
|
|
|
|
if (item.getType() == Notes.TYPE_NOTE) {
|
|
|
|
|
openNode(item);
|
|
|
|
|
} else {
|
|
|
|
|