From 2cd0ed5bbcb69ad17d18b1d940e84e2283d46637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=92=8B=E5=A4=A9=E7=BF=94?= Date: Wed, 21 Jan 2026 20:57:41 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=B4=E6=8A=A4=E9=9A=90=E7=A7=81=E9=94=81?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../net/micode/notes/ui/NoteInfoAdapter.java | 7 +- .../micode/notes/ui/NotesListActivity.java | 129 ++++++++++++------ .../notes/viewmodel/NotesListViewModel.java | 47 +------ 3 files changed, 95 insertions(+), 88 deletions(-) diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteInfoAdapter.java b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteInfoAdapter.java index 4c8ea85..2b9c202 100644 --- a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteInfoAdapter.java +++ b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteInfoAdapter.java @@ -120,8 +120,7 @@ public class NoteInfoAdapter extends BaseAdapter { this.selectedIds.clear(); this.selectedIds.addAll(selectedIds); notifyDataSetChanged(); - } else { - // 清空选择状态(包括null和空集合的情况) + } else if (selectedIds == null) { this.selectedIds.clear(); notifyDataSetChanged(); } @@ -139,11 +138,11 @@ public class NoteInfoAdapter extends BaseAdapter { if (selectedIds != null && !selectedIds.isEmpty()) { this.selectedIds.clear(); this.selectedIds.addAll(selectedIds); + notifyDataSetChanged(); } else { - // 清空选择状态(包括null和空列表的情况) this.selectedIds.clear(); + notifyDataSetChanged(); } - notifyDataSetChanged(); } /** diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListActivity.java index 9908ee3..1c28720 100644 --- a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListActivity.java +++ b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListActivity.java @@ -60,7 +60,6 @@ import net.micode.notes.viewmodel.NotesListViewModel; import com.google.android.material.floatingactionbutton.FloatingActionButton; -import java.util.HashSet; import java.util.List; /** @@ -85,6 +84,7 @@ public class NotesListActivity extends AppCompatActivity private static final int REQUEST_CODE_OPEN_NODE = 102; private static final int REQUEST_CODE_NEW_NODE = 103; private static final int REQUEST_CODE_CHECK_PASSWORD_FOR_OPEN = 104; + private static final int REQUEST_CODE_CHECK_PASSWORD_FOR_LOCK = 105; private NotesListViewModel viewModel; private ListView notesListView; @@ -99,7 +99,11 @@ public class NotesListActivity extends AppCompatActivity private boolean isMultiSelectMode = false; // 待打开的受保护笔记 - private NotesRepository.NoteInfo mPendingNoteToOpen; + private long mPendingNodeIdToOpen = -1; + private int mPendingNodeTypeToOpen = -1; + private static final String KEY_PENDING_NODE_ID = "pending_node_id"; + private static final String KEY_PENDING_NODE_TYPE = "pending_node_type"; + private static final String KEY_CURRENT_FOLDER_ID = "current_folder_id"; /** * 活动创建时的初始化方法 @@ -128,10 +132,36 @@ public class NotesListActivity extends AppCompatActivity }); initViewModel(); + + // 恢复 pending 状态和当前文件夹 + if (savedInstanceState != null) { + mPendingNodeIdToOpen = savedInstanceState.getLong(KEY_PENDING_NODE_ID, -1); + mPendingNodeTypeToOpen = savedInstanceState.getInt(KEY_PENDING_NODE_TYPE, -1); + + long savedFolderId = savedInstanceState.getLong(KEY_CURRENT_FOLDER_ID, Notes.ID_ROOT_FOLDER); + if (savedFolderId != Notes.ID_ROOT_FOLDER) { + viewModel.setCurrentFolderId(savedFolderId); + } + + Log.d(TAG, "Restored pending node: " + mPendingNodeIdToOpen + ", type: " + mPendingNodeTypeToOpen + ", folder: " + savedFolderId); + } + initViews(); observeViewModel(); } + /** + * 保存 Activity 状态 + */ + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putLong(KEY_PENDING_NODE_ID, mPendingNodeIdToOpen); + outState.putInt(KEY_PENDING_NODE_TYPE, mPendingNodeTypeToOpen); + outState.putLong(KEY_CURRENT_FOLDER_ID, viewModel.getCurrentFolderId()); + Log.d(TAG, "Saved pending node: " + mPendingNodeIdToOpen + ", current folder: " + viewModel.getCurrentFolderId()); + } + /** * 活动启动时的回调方法 *

@@ -141,12 +171,10 @@ public class NotesListActivity extends AppCompatActivity @Override protected void onStart() { super.onStart(); - viewModel.loadNotes(Notes.ID_ROOT_FOLDER); + // 刷新当前文件夹的笔记,而不是强制加载根目录 + // 这样可以保证从 PasswordActivity 返回时,如果 onStart 先执行,不会重置为根目录 + viewModel.refreshNotes(); } - - /** - * 初始化ViewModel - */ private void initViewModel() { NotesRepository repository = new NotesRepository(getContentResolver()); viewModel = new ViewModelProvider(this, @@ -244,6 +272,15 @@ public class NotesListActivity extends AppCompatActivity // 普通模式 if (note.type == Notes.TYPE_FOLDER) { // 文件夹:进入该文件夹 + // 检查隐私锁 + if (note.isLocked && SecurityManager.getInstance(this).isPasswordSet()) { + mPendingNodeIdToOpen = note.getId(); + mPendingNodeTypeToOpen = note.type; + Intent intent = new Intent(this, PasswordActivity.class); + intent.setAction(PasswordActivity.ACTION_CHECK_PASSWORD); + startActivityForResult(intent, REQUEST_CODE_CHECK_PASSWORD_FOR_OPEN); + return; + } viewModel.enterFolder(note.getId()); } else { // 便签:打开编辑器 @@ -307,26 +344,6 @@ public class NotesListActivity extends AppCompatActivity } } }); - - // 观察多选模式状态 - viewModel.getIsMultiSelectMode().observe(this, new Observer() { - @Override - public void onChanged(Boolean isMultiSelectMode) { - if (isMultiSelectMode != null && !isMultiSelectMode) { - // 退出多选模式 - NotesListActivity.this.isMultiSelectMode = false; - updateToolbarForNormalMode(); - if (adapter != null) { - adapter.setSelectedIds(new HashSet<>()); - adapter.notifyDataSetChanged(); - } - // 显示FAB按钮 - if (fabNewNote != null) { - fabNewNote.setVisibility(View.VISIBLE); - } - } - } - }); } /** @@ -398,6 +415,16 @@ public class NotesListActivity extends AppCompatActivity * 打开笔记编辑器 */ private void openNoteEditor(NotesRepository.NoteInfo note) { + // 检查隐私锁 + if (note.isLocked && SecurityManager.getInstance(this).isPasswordSet()) { + mPendingNodeIdToOpen = note.getId(); + mPendingNodeTypeToOpen = note.type; + Intent intent = new Intent(this, PasswordActivity.class); + intent.setAction(PasswordActivity.ACTION_CHECK_PASSWORD); + startActivityForResult(intent, REQUEST_CODE_CHECK_PASSWORD_FOR_OPEN); + return; + } + Intent intent = new Intent(this, NoteEditActivity.class); intent.setAction(Intent.ACTION_VIEW); intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, note.getParentId()); @@ -449,6 +476,15 @@ public class NotesListActivity extends AppCompatActivity showTrashItemDialog(note); } else if (note.type == Notes.TYPE_FOLDER) { // 文件夹:进入该文件夹 + // 检查隐私锁 + if (note.isLocked && SecurityManager.getInstance(this).isPasswordSet()) { + mPendingNodeIdToOpen = note.getId(); + mPendingNodeTypeToOpen = note.type; + Intent intent = new Intent(this, PasswordActivity.class); + intent.setAction(PasswordActivity.ACTION_CHECK_PASSWORD); + startActivityForResult(intent, REQUEST_CODE_CHECK_PASSWORD_FOR_OPEN); + return; + } Log.d(TAG, "Folder clicked, entering folder: " + note.getId()); viewModel.enterFolder(note.getId()); } else { @@ -532,7 +568,6 @@ public class NotesListActivity extends AppCompatActivity */ private void enterMultiSelectMode() { isMultiSelectMode = true; - viewModel.enterMultiSelectMode(); // 隐藏FAB按钮 if (fabNewNote != null) { fabNewNote.setVisibility(View.GONE); @@ -546,12 +581,12 @@ public class NotesListActivity extends AppCompatActivity */ private void exitMultiSelectMode() { isMultiSelectMode = false; - viewModel.exitMultiSelectMode(); // 显示FAB按钮 if (fabNewNote != null) { fabNewNote.setVisibility(View.VISIBLE); } // 清除选中状态 + viewModel.clearSelection(); if (adapter != null) { adapter.setSelectedIds(new java.util.HashSet<>()); adapter.notifyDataSetChanged(); @@ -683,15 +718,33 @@ public class NotesListActivity extends AppCompatActivity if (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE) { viewModel.refreshNotes(); } else if (requestCode == REQUEST_CODE_CHECK_PASSWORD_FOR_OPEN) { - if (mPendingNoteToOpen != null) { - if (mPendingNoteToOpen.type == Notes.TYPE_FOLDER) { - viewModel.enterFolder(mPendingNoteToOpen.getId()); + if (mPendingNodeIdToOpen != -1) { + if (mPendingNodeTypeToOpen == Notes.TYPE_FOLDER) { + // 文件夹密码验证通过,直接进入文件夹 + Log.d(TAG, "Password verified for folder: " + mPendingNodeIdToOpen); + viewModel.enterFolder(mPendingNodeIdToOpen); } else { - openNoteEditor(mPendingNoteToOpen); + // 密码验证通过,直接打开编辑器 + Intent intent = new Intent(this, NoteEditActivity.class); + intent.setAction(Intent.ACTION_VIEW); + intent.putExtra(Intent.EXTRA_UID, mPendingNodeIdToOpen); + startActivityForResult(intent, REQUEST_CODE_OPEN_NODE); } - mPendingNoteToOpen = null; + mPendingNodeIdToOpen = -1; + mPendingNodeTypeToOpen = -1; } + } else if (requestCode == REQUEST_CODE_CHECK_PASSWORD_FOR_LOCK) { + // 加锁/解锁密码验证通过 + boolean wasLocked = viewModel.isAllSelectedLocked(); + viewModel.toggleSelectedNotesLock(); + String lockMsg = wasLocked ? getString(R.string.menu_unlock) + "成功" : getString(R.string.menu_lock) + "成功"; + Toast.makeText(this, lockMsg, Toast.LENGTH_SHORT).show(); } + } else if (requestCode == REQUEST_CODE_CHECK_PASSWORD_FOR_LOCK) { + // 加锁/解锁密码验证失败或取消 + boolean wasLocked = viewModel.isAllSelectedLocked(); + String lockMsg = wasLocked ? getString(R.string.menu_unlock) + "失败" : getString(R.string.menu_lock) + "失败"; + Toast.makeText(this, lockMsg, Toast.LENGTH_SHORT).show(); } } @@ -748,10 +801,10 @@ public class NotesListActivity extends AppCompatActivity case R.id.multi_select_lock: // 检查是否设置了隐私密码 if (SecurityManager.getInstance(this).isPasswordSet()) { - boolean wasLocked = viewModel.isAllSelectedLocked(); - viewModel.toggleSelectedNotesLock(); - String lockMsg = wasLocked ? getString(R.string.menu_unlock) + "成功" : getString(R.string.menu_lock) + "成功"; - Toast.makeText(this, lockMsg, Toast.LENGTH_SHORT).show(); + // 需要先验证密码 + Intent intent = new Intent(this, PasswordActivity.class); + intent.setAction(PasswordActivity.ACTION_CHECK_PASSWORD); + startActivityForResult(intent, REQUEST_CODE_CHECK_PASSWORD_FOR_LOCK); } else { Toast.makeText(this, "请先在设置中设置隐私密码", Toast.LENGTH_SHORT).show(); // 跳转到设置密码界面 diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/viewmodel/NotesListViewModel.java b/src/Notesmaster/app/src/main/java/net/micode/notes/viewmodel/NotesListViewModel.java index bd991ba..d6f854b 100644 --- a/src/Notesmaster/app/src/main/java/net/micode/notes/viewmodel/NotesListViewModel.java +++ b/src/Notesmaster/app/src/main/java/net/micode/notes/viewmodel/NotesListViewModel.java @@ -64,9 +64,6 @@ public class NotesListViewModel extends ViewModel { // 侧栏刷新通知LiveData(删除等操作后通知侧栏刷新) private final MutableLiveData sidebarRefreshNeeded = new MutableLiveData<>(false); - // 多选模式状态LiveData - private final MutableLiveData isMultiSelectMode = new MutableLiveData<>(false); - // 文件夹导航历史(用于返回上一级) private final List folderHistory = new ArrayList<>(); @@ -242,7 +239,6 @@ public class NotesListViewModel extends ViewModel { public void onSuccess(Integer rowsAffected) { isLoading.postValue(false); selectedNoteIds.clear(); - isMultiSelectMode.postValue(false); refreshNotes(); Log.d(TAG, "Successfully deleted " + rowsAffected + " notes"); } @@ -438,42 +434,6 @@ public class NotesListViewModel extends ViewModel { selectedNoteIds.clear(); } - /** - * 获取多选模式状态LiveData - * - * @return 多选模式状态LiveData - */ - public MutableLiveData getIsMultiSelectMode() { - return isMultiSelectMode; - } - - /** - * 更新多选模式状态 - * - * @param multiSelectMode 是否进入多选模式 - */ - public void setMultiSelectMode(boolean multiSelectMode) { - this.isMultiSelectMode.setValue(multiSelectMode); - } - - /** - * 进入多选模式 - */ - public void enterMultiSelectMode() { - isMultiSelectMode.setValue(true); - } - - /** - * 退出多选模式 - *

- * 公开方法,供Activity调用 - *

- */ - public void exitMultiSelectMode() { - isMultiSelectMode.setValue(false); - selectedNoteIds.clear(); - } - /** * 获取文件夹列表 *

@@ -573,8 +533,7 @@ public class NotesListViewModel extends ViewModel { @Override public void onSuccess(Integer rowsAffected) { isLoading.postValue(false); - selectedNoteIds.clear(); - isMultiSelectMode.postValue(false); + // 保持选中状态,方便用户查看 refreshNotes(); Log.d(TAG, "Successfully toggled pin state to " + newPinState); } @@ -630,8 +589,6 @@ public class NotesListViewModel extends ViewModel { @Override public void onSuccess(Integer rowsAffected) { isLoading.postValue(false); - selectedNoteIds.clear(); - isMultiSelectMode.postValue(false); refreshNotes(); Log.d(TAG, "Successfully toggled lock state to " + newLockState); } @@ -688,7 +645,6 @@ public class NotesListViewModel extends ViewModel { public void onSuccess(Integer rowsAffected) { isLoading.postValue(false); selectedNoteIds.clear(); - isMultiSelectMode.postValue(false); refreshNotes(); Log.d(TAG, "Successfully restored " + rowsAffected + " notes"); } @@ -724,7 +680,6 @@ public class NotesListViewModel extends ViewModel { public void onSuccess(Integer rowsAffected) { isLoading.postValue(false); selectedNoteIds.clear(); - isMultiSelectMode.postValue(false); refreshNotes(); Log.d(TAG, "Successfully permanently deleted " + rowsAffected + " notes"); } -- 2.34.1