diff --git a/res/layout/note_edit.xml b/res/layout/note_edit.xml index a8b58b6..115e6b7 100644 --- a/res/layout/note_edit.xml +++ b/res/layout/note_edit.xml @@ -57,6 +57,15 @@ android:textAppearance="@style/TextAppearanceSecondaryItem" /> + + + + diff --git a/res/menu/note_list.xml b/res/menu/note_list.xml index 34eb46e..22c3079 100644 --- a/res/menu/note_list.xml +++ b/res/menu/note_list.xml @@ -41,6 +41,10 @@ android:id="@+id/menu_setting" android:title="@string/menu_setting" /> + + diff --git a/res/menu/sub_folder.xml b/res/menu/sub_folder.xml index b00de26..3b5eb58 100644 --- a/res/menu/sub_folder.xml +++ b/res/menu/sub_folder.xml @@ -18,6 +18,10 @@ + + diff --git a/res/values/strings.xml b/res/values/strings.xml index bfaf531..ae67a17 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -139,4 +139,10 @@ %1$s 条符合"%2$s"的搜索结果 + + 清空回收站 + 确认要清空回收站中的所有便签吗?此操作不可恢复。 + 已恢复 %d 条便签 + 回收站已清空 + diff --git a/src/ui/NoteEditActivity.java b/src/ui/NoteEditActivity.java index 5798594..e26ac68 100644 --- a/src/ui/NoteEditActivity.java +++ b/src/ui/NoteEditActivity.java @@ -32,6 +32,7 @@ import android.view.WindowManager; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; @@ -70,6 +71,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, public TextView tvAlertDate; + public ImageButton btnSaveExit; + public ImageView ibSetBgColor; } //使用Map实现数据存储 @@ -431,6 +434,8 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteHeaderHolder.tvModified = (TextView) findViewById(R.id.tv_modified_date); mNoteHeaderHolder.ivAlertIcon = (ImageView) findViewById(R.id.iv_alert_icon); mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date); + mNoteHeaderHolder.btnSaveExit = (ImageButton) findViewById(R.id.btn_save_exit); + mNoteHeaderHolder.btnSaveExit.setOnClickListener(this); mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color); mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this); mNoteEditor = (NoteEditText) findViewById(R.id.note_edit_view); @@ -490,7 +495,10 @@ public class NoteEditActivity extends Activity implements OnClickListener, public void onClick(View v) { int id = v.getId(); - if (id == R.id.btn_set_bg_color) { + if (id == R.id.btn_save_exit) { + saveNote(); + finish(); + } else if (id == R.id.btn_set_bg_color) { mNoteBgColorSelector.setVisibility(View.VISIBLE); findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( - View.VISIBLE); @@ -587,6 +595,11 @@ public class NoteEditActivity extends Activity implements OnClickListener, public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { //根据菜单的id来编剧相关项目 + case R.id.menu_save_exit: + //保存并退出 + saveNote(); + finish(); + break; case R.id.menu_new_note: //创建一个新的便签 createNewNote(); @@ -784,18 +797,9 @@ public class NoteEditActivity extends Activity implements OnClickListener, Log.d(TAG, "Wrong note id, should not happen"); //否则报错 } - if (!isSyncMode()) { - //在非同步模式情况下 - //删除操作 - if (!DataUtils.batchDeleteNotes(getContentResolver(), ids)) { - Log.e(TAG, "Delete Note error"); - } - } else { - //同步模式 - //移动至垃圾文件夹的操作 - if (!DataUtils.batchMoveToFolder(getContentResolver(), ids, Notes.ID_TRASH_FOLER)) { - Log.e(TAG, "Move notes to trash folder error, should not happens"); - } + // 所有模式下都将便签移动到回收站 + if (!DataUtils.batchMoveToFolder(getContentResolver(), ids, Notes.ID_TRASH_FOLER)) { + Log.e(TAG, "Move notes to trash folder error, should not happens"); } } mWorkingNote.markDeleted(true); diff --git a/src/ui/NotesListActivity.java b/src/ui/NotesListActivity.java index bc8b619..d8da8d5 100644 --- a/src/ui/NotesListActivity.java +++ b/src/ui/NotesListActivity.java @@ -80,7 +80,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction"; //单行超过80个字符 private enum ListEditState { - NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER + NOTE_LIST, SUB_FOLDER, CALL_RECORD_FOLDER, TRASH_FOLDER }; private ListEditState mState; @@ -252,16 +252,24 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt private MenuItem mMoveMenu; public boolean onCreateActionMode(ActionMode mode, Menu menu) { - getMenuInflater().inflate(R.menu.note_list_options, menu); - menu.findItem(R.id.delete).setOnMenuItemClickListener(this); - menu.findItem(R.id.pin).setOnMenuItemClickListener(this); - mMoveMenu = menu.findItem(R.id.move); - if (mFocusNoteDataItem.getParentId() == Notes.ID_CALL_RECORD_FOLDER - || DataUtils.getUserFolderCount(mContentResolver) == 0) { - mMoveMenu.setVisible(false); + // 检查是否在回收站中 + if (mState == ListEditState.TRASH_FOLDER) { + // 在回收站中,显示恢复菜单 + getMenuInflater().inflate(R.menu.trash_list_options, menu); + menu.findItem(R.id.restore).setOnMenuItemClickListener(this); } else { - mMoveMenu.setVisible(true); - mMoveMenu.setOnMenuItemClickListener(this); + // 不在回收站中,显示普通菜单 + getMenuInflater().inflate(R.menu.note_list_options, menu); + menu.findItem(R.id.delete).setOnMenuItemClickListener(this); + menu.findItem(R.id.pin).setOnMenuItemClickListener(this); + mMoveMenu = menu.findItem(R.id.move); + if (mFocusNoteDataItem.getParentId() == Notes.ID_CALL_RECORD_FOLDER + || DataUtils.getUserFolderCount(mContentResolver) == 0) { + mMoveMenu.setVisible(false); + } else { + mMoveMenu.setVisible(true); + mMoveMenu.setOnMenuItemClickListener(this); + } } mActionMode = mode; mNotesListAdapter.setChoiceMode(true); @@ -365,6 +373,25 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt case R.id.move: startQueryDestinationFolders(); break; + case R.id.restore: + // 恢复选中的便签 + AlertDialog.Builder restoreBuilder = new AlertDialog.Builder(NotesListActivity.this); + restoreBuilder.setTitle("恢复便签"); + restoreBuilder.setMessage("确认要恢复选中的 " + mNotesListAdapter.getSelectedCount() + " 条便签吗?"); + restoreBuilder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + if (DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter.getSelectedItemIds(), Notes.ID_ROOT_FOLDER)) { + Toast.makeText(NotesListActivity.this, getString(R.string.format_restore_notes, mNotesListAdapter.getSelectedCount()), Toast.LENGTH_SHORT).show(); + startAsyncNotesListQuery(); + } else { + Log.e(TAG, "Restore notes error"); + } + mModeCallBack.finishActionMode(); + } + }); + restoreBuilder.setNegativeButton(android.R.string.cancel, null); + restoreBuilder.show(); + break; default: return false; } @@ -516,20 +543,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt new AsyncTask>() { protected HashSet doInBackground(Void... unused) { HashSet 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 (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter - .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) { - Log.e(TAG, "Move notes to trash folder error, should not happens"); - } + // 所有模式下都将便签移动到回收站 + if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter + .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) { + Log.e(TAG, "Move notes to trash folder error, should not happens"); } return widgets; } @@ -559,13 +576,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt ids.add(folderId); HashSet widgets = DataUtils.getFolderNoteWidget(mContentResolver, folderId); - if (!isSyncMode()) { - // if not synced, delete folder directly - DataUtils.batchDeleteNotes(mContentResolver, ids); - } else { - // in sync mode, we'll move the deleted folder into the trash folder - DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER); - } + // 所有模式下都将文件夹移动到回收站 + DataUtils.batchMoveToFolder(mContentResolver, ids, Notes.ID_TRASH_FOLER); if (widgets != null) { for (AppWidgetAttribute widget : widgets) { if (widget.widgetId != AppWidgetManager.INVALID_APPWIDGET_ID @@ -600,6 +612,15 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt mTitleBar.setVisibility(View.VISIBLE); } + private void openTrashFolder() { + mCurrentFolderId = Notes.ID_TRASH_FOLER; + mState = ListEditState.TRASH_FOLDER; + mAddNewNote.setVisibility(View.GONE); + mTitleBar.setText("回收站"); + mTitleBar.setVisibility(View.VISIBLE); + startAsyncNotesListQuery(); + } + public void onClick(View v) { switch (v.getId()) { case R.id.btn_new_note: @@ -714,10 +735,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt @Override public void onBackPressed() { switch (mState) { case SUB_FOLDER: + case TRASH_FOLDER: mCurrentFolderId = Notes.ID_ROOT_FOLDER; mState = ListEditState.NOTE_LIST; - startAsyncNotesListQuery(); + mAddNewNote.setVisibility(View.VISIBLE); mTitleBar.setVisibility(View.GONE); + startAsyncNotesListQuery(); break; case CALL_RECORD_FOLDER: mCurrentFolderId = Notes.ID_ROOT_FOLDER; @@ -830,6 +853,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt getMenuInflater().inflate(R.menu.sub_folder, menu); } else if (mState == ListEditState.CALL_RECORD_FOLDER) { getMenuInflater().inflate(R.menu.call_record_folder, menu); + } else if (mState == ListEditState.TRASH_FOLDER) { + getMenuInflater().inflate(R.menu.trash_folder, menu); } else { Log.e(TAG, "Wrong state:" + mState); } @@ -871,10 +896,30 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt startPreferenceActivity(); break; } + case R.id.menu_trash: + // 打开回收站 + openTrashFolder(); + break; case R.id.menu_new_note: { createNewNote(); break; } + case R.id.menu_exit_folder: + // 退至上一级文件夹,执行与返回键相同的逻辑 + mCurrentFolderId = Notes.ID_ROOT_FOLDER; + mState = ListEditState.NOTE_LIST; + mAddNewNote.setVisibility(View.VISIBLE); + mTitleBar.setVisibility(View.GONE); + startAsyncNotesListQuery(); + break; + case R.id.menu_restore: + // 恢复选中的便签 + restoreSelectedNotes(); + break; + case R.id.menu_empty_trash: + // 清空回收站 + emptyTrash(); + break; case R.id.menu_search: onSearchRequested(); break; @@ -1007,6 +1052,77 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); } + private void restoreSelectedNotes() { + if (mNotesListAdapter.getSelectedCount() == 0) { + Toast.makeText(this, "请先选择要恢复的便签", Toast.LENGTH_SHORT).show(); + // 进入选择模式 + if (mNotesListView != null && mModeCallBack != null) { + mNotesListView.setLongClickable(false); + mModeCallBack.finishActionMode(); + } + return; + } + + // 显示确认对话框 + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle("恢复便签"); + builder.setMessage("确认要恢复选中的 " + mNotesListAdapter.getSelectedCount() + " 条便签吗?"); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // 将选中的便签恢复到根文件夹 + if (DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter.getSelectedItemIds(), Notes.ID_ROOT_FOLDER)) { + Toast.makeText(NotesListActivity.this, getString(R.string.format_restore_notes, mNotesListAdapter.getSelectedCount()), Toast.LENGTH_SHORT).show(); + startAsyncNotesListQuery(); + } else { + Log.e(TAG, "Restore notes error"); + } + + if (mModeCallBack != null) { + mModeCallBack.finishActionMode(); + } + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show(); + } + + private void emptyTrash() { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.alert_title_empty_trash); + builder.setIcon(android.R.drawable.ic_dialog_alert); + builder.setMessage(R.string.alert_message_empty_trash); + builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // 直接删除回收站中的所有便签 + Cursor cursor = mContentResolver.query(Notes.CONTENT_NOTE_URI, + new String[] { NoteColumns.ID }, + NoteColumns.PARENT_ID + "=?", + new String[] { String.valueOf(Notes.ID_TRASH_FOLER) }, + null); + + if (cursor != null && cursor.moveToFirst()) { + HashSet ids = new HashSet(); + do { + ids.add(cursor.getLong(0)); + } while (cursor.moveToNext()); + + if (!ids.isEmpty()) { + if (DataUtils.batchDeleteNotes(mContentResolver, ids)) { + Toast.makeText(NotesListActivity.this, R.string.toast_empty_trash_success, Toast.LENGTH_SHORT).show(); + startAsyncNotesListQuery(); + } else { + Log.e(TAG, "Empty trash error"); + } + } + + cursor.close(); + } + } + }); + builder.setNegativeButton(android.R.string.cancel, null); + builder.show(); + } + /** * @author k * 函数功能:实现对便签列表项的点击事件(短按)