隐私锁功能维护 #20

Merged
p7tupf26b merged 1 commits from jiangtianxiang_branch into master 1 month ago

@ -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();
}
/**

@ -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());
}
/**
*
* <p>
@ -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<Boolean>() {
@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();
// 跳转到设置密码界面

@ -64,9 +64,6 @@ public class NotesListViewModel extends ViewModel {
// 侧栏刷新通知LiveData删除等操作后通知侧栏刷新
private final MutableLiveData<Boolean> sidebarRefreshNeeded = new MutableLiveData<>(false);
// 多选模式状态LiveData
private final MutableLiveData<Boolean> isMultiSelectMode = new MutableLiveData<>(false);
// 文件夹导航历史(用于返回上一级)
private final List<Long> 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<Boolean> getIsMultiSelectMode() {
return isMultiSelectMode;
}
/**
*
*
* @param multiSelectMode
*/
public void setMultiSelectMode(boolean multiSelectMode) {
this.isMultiSelectMode.setValue(multiSelectMode);
}
/**
*
*/
public void enterMultiSelectMode() {
isMultiSelectMode.setValue(true);
}
/**
* 退
* <p>
* Activity
* </p>
*/
public void exitMultiSelectMode() {
isMultiSelectMode.setValue(false);
selectedNoteIds.clear();
}
/**
*
* <p>
@ -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");
}

Loading…
Cancel
Save