@ -67,10 +67,6 @@ import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity ;
import androidx.appcompat.widget.Toolbar ;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout ;
import net.micode.notes.cloud.SyncManager ;
import net.micode.notes.cloud.SyncDialogManager ;
import net.micode.notes.R ;
import net.micode.notes.data.Notes ;
@ -106,8 +102,8 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
private static final int MENU_FOLDER_CHANGE_NAME = 2 ; // 文件夹改名菜单项
private static final int MENU_LOCK_NOTE = 3 ; // 便签加锁菜单项
private static final int MENU_UNLOCK_NOTE = 4 ; // 便签解锁菜单项
private static final int MENU_FOLDER_ENCRYPT = 5 ; // 文件夹加密菜单项
private static final int MENU_FOLDER_DECRYPT = 6 ; // 文件夹取消加密菜单项
private static final int MENU_FOLDER_ENCRYPT = 3 ; // 文件夹加密菜单项
private static final int MENU_FOLDER_DECRYPT = 4 ; // 文件夹取消加密菜单项
// 首次使用引导标记的偏好设置键
private static final String PREFERENCE_ADD_INTRODUCTION = "net.micode.notes.introduction" ;
@ -118,8 +114,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
private enum ListEditState {
NOTE_LIST , // 普通笔记列表状态
SUB_FOLDER , // 子文件夹浏览状态
CALL_RECORD_FOLDER , // 通话记录文件夹浏览状态
SEARCH // 搜索状态
CALL_RECORD_FOLDER // 通话记录文件夹浏览状态
} ;
// 当前列表状态
@ -152,14 +147,6 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
public static final int NOTES_LISTVIEW_SCROLL_RATE = 30 ;
// 长按焦点笔记数据项
private NoteItemData mFocusNoteDataItem ;
// 下拉刷新布局
private SwipeRefreshLayout mSwipeRefreshLayout ;
// 搜索相关变量
private String mSearchKey = "" ; // 搜索关键词
private View mSearchContainer ; // 搜索容器视图
private EditText mSearchEditText ; // 搜索输入框
// 普通查询条件(非根文件夹)
private static final String NORMAL_SELECTION = NoteColumns . PARENT_ID + "=?" ;
@ -213,35 +200,19 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
if ( itemData = = null | | itemData . getType ( ) ! = Notes . TYPE_NOTE ) {
return ;
}
// 查询笔记的原始父文件夹ID
long originParentId = Notes . ID_ROOT_FOLDER ; // 默认恢复到根文件夹
Cursor cursor = mContentResolver . query ( ContentUris . withAppendedId ( Notes . CONTENT_NOTE_URI , itemData . getId ( ) ) ,
new String [ ] { NoteColumns . ORIGIN_PARENT_ID } , null , null , null ) ;
if ( cursor ! = null ) {
if ( cursor . moveToFirst ( ) ) {
originParentId = cursor . getLong ( 0 ) ;
// 如果原始文件夹ID无效或者是回收站, 则恢复到根文件夹
if ( originParentId < = 0 | | originParentId = = Notes . ID_TRASH_FOLDER ) {
originParentId = Notes . ID_ROOT_FOLDER ;
}
}
cursor . close ( ) ;
}
// 显示确认对话框
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( "恢复笔记" ) ;
builder . setMessage ( "确定要恢复这条笔记吗?" ) ;
builder . setIcon ( android . R . drawable . ic_dialog_info ) ;
final long targetFolderId = originParentId ;
builder . setPositiveButton ( android . R . string . ok , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
// 恢复笔记到 原始 文件夹
// 恢复笔记到根文件夹
HashSet < Long > ids = new HashSet < Long > ( ) ;
ids . add ( itemData . getId ( ) ) ;
if ( DataUtils . batchMoveToFolder ( mContentResolver , ids , targetFolderId ) ) {
if ( DataUtils . batchMoveToFolder ( mContentResolver , ids , Notes . ID_ROOT_FOLDER ) ) {
Toast . makeText ( NotesListActivity . this , "笔记已恢复" , Toast . LENGTH_SHORT ) . show ( ) ;
} else {
Toast . makeText ( NotesListActivity . this , "恢复失败" , Toast . LENGTH_SHORT ) . show ( ) ;
@ -347,25 +318,6 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
mState = ListEditState . NOTE_LIST ; // 初始状态为普通笔记列表
mModeCallBack = new ModeCallback ( ) ; // 多选模式回调
// 初始化下拉刷新布局
mSwipeRefreshLayout = findViewById ( R . id . swipe_refresh_layout ) ;
if ( mSwipeRefreshLayout ! = null ) {
mSwipeRefreshLayout . setOnRefreshListener ( new SwipeRefreshLayout . OnRefreshListener ( ) {
@Override
public void onRefresh ( ) {
// 下拉刷新时只执行下载操作
executeDownload ( ) ;
}
} ) ;
// 设置刷新颜色
mSwipeRefreshLayout . setColorSchemeResources (
android . R . color . holo_blue_light ,
android . R . color . holo_green_light ,
android . R . color . holo_orange_light ,
android . R . color . holo_red_light
) ;
}
// 应用老年人模式
ElderModeUtils . applyElderMode ( this , findViewById ( android . R . id . content ) ) ;
}
@ -598,11 +550,10 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
// 根据当前文件夹选择查询条件
String selection = ( mCurrentFolderId = = Notes . ID_ROOT_FOLDER ) ? ROOT_FOLDER_SELECTION
: NORMAL_SELECTION ;
// 修改排序规则: 先按类型降序( 系统文件夹在前) , 再按alerted_date降序( 置顶便签在前) , 最后按修改时间降序
mBackgroundQueryHandler . startQuery ( FOLDER_NOTE_LIST_QUERY_TOKEN , null ,
Notes . CONTENT_NOTE_URI , NoteItemData . PROJECTION , selection , new String [ ] {
String . valueOf ( mCurrentFolderId )
} , NoteColumns . TYPE + " DESC," + NoteColumns . ALERTED_DATE + " DESC," + NoteColumns . MODIFIED_DATE + " DESC" ) ;
} , NoteColumns . TYPE + " DESC," + NoteColumns . MODIFIED_DATE + " DESC" ) ;
}
/ * *
@ -678,19 +629,10 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
protected HashSet < AppWidgetAttribute > doInBackground ( Void . . . unused ) {
// 获取选中笔记的小部件属性
HashSet < AppWidgetAttribute > widgets = mNotesListAdapter . getSelectedWidget ( ) ;
HashSet < Long > selectedIds = mNotesListAdapter . getSelectedItemIds ( ) ;
// 根据当前文件夹决定删除方式
if ( mCurrentFolderId = = Notes . ID_TRASH_FOLDER ) {
// 在回收站中,彻底删除笔记
if ( ! DataUtils . batchDeleteNotes ( mContentResolver , selectedIds ) ) {
Log . e ( TAG , "Delete notes error, should not happens" ) ;
}
} else {
// 不在回收站中,将笔记移动到回收站
if ( ! DataUtils . batchMoveToFolder ( mContentResolver , selectedIds , Notes . ID_TRASH_FOLDER ) ) {
Log . e ( TAG , "Move notes to trash folder error, should not happens" ) ;
}
// 无论是否同步模式,都将笔记移动到回收站
if ( ! DataUtils . batchMoveToFolder ( mContentResolver , mNotesListAdapter
. getSelectedItemIds ( ) , Notes . ID_TRASH_FOLDER ) ) {
Log . e ( TAG , "Move notes to trash folder error, should not happens" ) ;
}
return widgets ;
}
@ -716,51 +658,25 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
* /
private void batchPinNotes ( ) {
new AsyncTask < Void , Void , HashSet < AppWidgetAttribute > > ( ) {
private int pinnedCount = 0 ;
private int unpinnedCount = 0 ;
@Override
protected HashSet < AppWidgetAttribute > doInBackground ( Void . . . unused ) {
// 获取选中笔记的小部件属性
HashSet < AppWidgetAttribute > widgets = mNotesListAdapter . getSelectedWidget ( ) ;
HashSet < Long > selectedIds = mNotesListAdapter . getSelectedItemIds ( ) ;
// 批量更新笔记的alerted_date字段
// 批量更新笔记的alerted_date字段 为一个很大的值,表示置顶
for ( Long noteId : selectedIds ) {
ContentValues values = new ContentValues ( ) ;
values . put ( NoteColumns . ALERTED_DATE , 9999999999999L ) ; // 很大的值,表示置顶
values . put ( NoteColumns . LOCAL_MODIFIED , 1 ) ;
values . put ( NoteColumns . MODIFIED_DATE , System . currentTimeMillis ( ) ) ;
try {
// 查询笔记当前的alerted_date值
Cursor cursor = getContentResolver ( ) . query (
ContentUris . withAppendedId ( Notes . CONTENT_NOTE_URI , noteId ) ,
new String [ ] { NoteColumns . ALERTED_DATE } ,
null , null , null ) ;
long currentAlertedDate = 0 ;
if ( cursor ! = null & & cursor . moveToFirst ( ) ) {
currentAlertedDate = cursor . getLong ( 0 ) ;
cursor . close ( ) ;
}
ContentValues values = new ContentValues ( ) ;
// 判断是否已经置顶( alerted_date大于当前时间)
if ( currentAlertedDate > System . currentTimeMillis ( ) ) {
// 已经置顶,取消置顶
values . put ( NoteColumns . ALERTED_DATE , 0 ) ; // 0表示未置顶
unpinnedCount + + ;
} else {
// 未置顶,设置置顶
values . put ( NoteColumns . ALERTED_DATE , 9999999999999L ) ; // 很大的值,表示置顶
pinnedCount + + ;
}
values . put ( NoteColumns . LOCAL_MODIFIED , 1 ) ;
values . put ( NoteColumns . MODIFIED_DATE , System . currentTimeMillis ( ) ) ;
getContentResolver ( ) . update (
ContentUris . withAppendedId ( Notes . CONTENT_NOTE_URI , noteId ) ,
values , null , null ) ;
} catch ( Exception e ) {
Log . e ( TAG , "Error toggling pin status : " + noteId , e ) ;
Log . e ( TAG , "Error pinning note: " + noteId , e ) ;
}
}
return widgets ;
@ -777,16 +693,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
}
}
}
// 显示相应的提示信息
if ( pinnedCount > 0 & & unpinnedCount > 0 ) {
Toast . makeText ( NotesListActivity . this , "已置顶" + pinnedCount + "条笔记,已取消置顶" + unpinnedCount + "条笔记" , Toast . LENGTH_SHORT ) . show ( ) ;
} else if ( pinnedCount > 0 ) {
Toast . makeText ( NotesListActivity . this , "已置顶" + pinnedCount + "条笔记" , Toast . LENGTH_SHORT ) . show ( ) ;
} else if ( unpinnedCount > 0 ) {
Toast . makeText ( NotesListActivity . this , "已取消置顶" + unpinnedCount + "条笔记" , Toast . LENGTH_SHORT ) . show ( ) ;
}
Toast . makeText ( NotesListActivity . this , "已置顶" + mNotesListAdapter . getSelectedCount ( ) + "条笔记" , Toast . LENGTH_SHORT ) . show ( ) ;
mModeCallBack . finishActionMode ( ) ; // 结束多选模式
}
} . execute ( ) ;
@ -995,9 +902,6 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
public void onBackPressed ( ) {
// 处理返回键,根据当前状态返回上一级或退出
switch ( mState ) {
case SEARCH :
exitSearch ( ) ;
break ;
case SUB_FOLDER :
mCurrentFolderId = Notes . ID_ROOT_FOLDER ;
mState = ListEditState . NOTE_LIST ;
@ -1150,8 +1054,6 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
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 . SEARCH ) {
// 搜索状态下不显示菜单,因为搜索框已经占据了工具栏
} else {
Log . e ( TAG , "Wrong state:" + mState ) ;
}
@ -1168,8 +1070,8 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
exportNoteToText ( ) ; // 导出笔记为文本
break ;
case R . id . menu_sync :
// 触发 同步功能
triggerSync ( ) ;
// 同步功能已移除,显示提示信息
Toast. makeText ( this , R . string . error_sync_not_available , Toast . LENGTH_SHORT ) . show ( ) ;
break ;
case R . id . menu_setting :
startPreferenceActivity ( ) ; // 打开设置
@ -1188,128 +1090,10 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
@Override
public boolean onSearchRequested ( ) {
toggleToSearch( ) ;
startSearch( null , false , null /* appData */ , false ) ;
return true ;
}
/ * *
* 显 示 搜 索 框
* 在 根 目 录 时 , 显 示 顶 部 搜 索 框 ; 在 子 目 录 时 , 切 换 到 根 目 录 再 显 示 搜 索 框
* /
private void showSearch ( ) {
if ( mState ! = ListEditState . SEARCH ) {
// 切换到搜索状态
mState = ListEditState . SEARCH ;
// 隐藏新建笔记按钮
mAddNewNote . setVisibility ( View . GONE ) ;
// 隐藏标题栏,显示搜索容器
mTitleBar . setVisibility ( View . GONE ) ;
mSearchContainer = findViewById ( R . id . search_container ) ;
mSearchContainer . setVisibility ( View . VISIBLE ) ;
mSearchEditText = ( EditText ) mSearchContainer . findViewById ( R . id . search_input ) ;
// 设置搜索输入框监听器
mSearchEditText . addTextChangedListener ( new TextWatcher ( ) {
@Override
public void onTextChanged ( CharSequence s , int start , int before , int count ) {
}
@Override
public void beforeTextChanged ( CharSequence s , int start , int count , int after ) {
}
@Override
public void afterTextChanged ( Editable s ) {
mSearchKey = s . toString ( ) ;
// 根据搜索关键字刷新列表
startSearchQuery ( ) ;
}
} ) ;
// 监听搜索框软键盘的"完成"键
mSearchEditText . setOnEditorActionListener ( ( v , actionId , event ) - > {
if ( actionId = = android . view . inputmethod . EditorInfo . IME_ACTION_SEARCH ) {
mSearchKey = mSearchEditText . getText ( ) . toString ( ) ;
startSearchQuery ( ) ;
return true ;
}
return false ;
} ) ;
mSearchEditText . requestFocus ( ) ;
showSoftInput ( ) ;
// 设置取消按钮点击监听器
Button cancelButton = ( Button ) mSearchContainer . findViewById ( R . id . search_cancel ) ;
cancelButton . setOnClickListener ( new OnClickListener ( ) {
@Override
public void onClick ( View v ) {
exitSearch ( ) ;
}
} ) ;
}
}
/ * *
* 启 动 搜 索 查 询
* /
private void startSearchQuery ( ) {
// 只搜索SNIPPET列, 因为CONTENT列在DataColumns中
String selection = NoteColumns . SNIPPET + " LIKE ?" ;
mBackgroundQueryHandler . startQuery ( FOLDER_NOTE_LIST_QUERY_TOKEN , null ,
Notes . CONTENT_NOTE_URI , NoteItemData . PROJECTION , selection ,
new String [ ] { "%" + mSearchKey + "%" } ,
NoteColumns . MODIFIED_DATE + " DESC" ) ;
}
/ * *
* 切 换 到 搜 索 状 态
* 如 果 当 前 不 在 搜 索 状 态 , 调 用 showSearch ; 如 果 已 经 在 搜 索 状 态 但 有 新 的 搜 索 关 键 字 ,
* 则 直 接 刷 新 搜 索 结 果
* /
private void toggleToSearch ( ) {
if ( mState ! = ListEditState . SEARCH ) {
// 如果当前不在根目录,先切换到根目录
if ( mCurrentFolderId ! = Notes . ID_ROOT_FOLDER ) {
mCurrentFolderId = Notes . ID_ROOT_FOLDER ;
mState = ListEditState . NOTE_LIST ;
startAsyncNotesListQuery ( ) ;
}
showSearch ( ) ;
} else {
if ( ! mSearchKey . equals ( mSearchEditText . getText ( ) . toString ( ) ) ) {
startSearchQuery ( ) ;
}
}
}
/ * *
* 退 出 搜 索 状 态
* /
private void exitSearch ( ) {
if ( mState = = ListEditState . SEARCH ) {
// 切换回普通笔记列表状态
mState = ListEditState . NOTE_LIST ;
// 清空搜索关键字
mSearchKey = "" ;
// 隐藏搜索容器,显示标题栏
if ( mSearchContainer ! = null ) {
mSearchContainer . setVisibility ( View . GONE ) ;
}
mTitleBar . setVisibility ( View . VISIBLE ) ;
mTitleBar . setText ( R . string . app_name ) ;
// 显示新建笔记按钮
mAddNewNote . setVisibility ( View . VISIBLE ) ;
// 隐藏软键盘
if ( mSearchEditText ! = null ) {
hideSoftInput ( mSearchEditText ) ;
}
// 刷新笔记列表
startAsyncNotesListQuery ( ) ;
// 重新创建菜单,确保设置图标显示
invalidateOptionsMenu ( ) ;
}
}
/ * *
* 导 出 笔 记 为 文 本 文 件
* /
@ -1419,13 +1203,6 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
Log . e ( TAG , "Wrong note type in CALL_RECORD_FOLDER" ) ;
}
break ;
case SEARCH :
if ( item . getType ( ) = = Notes . TYPE_NOTE ) {
openNode ( item ) ; // 打开笔记
} else {
Log . e ( TAG , "Wrong note type in SEARCH" ) ;
}
break ;
default :
break ;
}
@ -1458,140 +1235,6 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
}
}
/ * *
* 触 发 同 步 操 作
* /
private void triggerSync ( ) {
SyncDialogManager . showSyncOptionsDialog ( this , new SyncDialogManager . SyncOptionListener ( ) {
@Override
public void onUploadSelected ( ) {
SyncDialogManager . showUploadConfirmDialog ( NotesListActivity . this , new SyncDialogManager . ConfirmListener ( ) {
@Override
public void onConfirm ( ) {
executeUpload ( ) ;
}
@Override
public void onCancel ( ) {
// 取消操作,返回选择对话框
}
} ) ;
}
@Override
public void onDownloadSelected ( ) {
executeDownload ( ) ;
}
@Override
public void onCanceled ( ) {
// 取消操作
}
} ) ;
}
/ * *
* 执 行 上 传 操 作
* /
private void executeUpload ( ) {
SyncManager . getInstance ( this ) . triggerUpload ( new SyncManager . SyncCallback ( ) {
@Override
public void onSyncStart ( ) {
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
Toast . makeText ( NotesListActivity . this , "正在上传..." , Toast . LENGTH_SHORT ) . show ( ) ;
// 开始刷新动画
if ( mSwipeRefreshLayout ! = null ) {
mSwipeRefreshLayout . setRefreshing ( true ) ;
}
}
} ) ;
}
@Override
public void onSyncSuccess ( ) {
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
Toast . makeText ( NotesListActivity . this , "上传成功" , Toast . LENGTH_SHORT ) . show ( ) ;
// 停止刷新动画
if ( mSwipeRefreshLayout ! = null ) {
mSwipeRefreshLayout . setRefreshing ( false ) ;
}
// 刷新笔记列表
startAsyncNotesListQuery ( ) ;
}
} ) ;
}
@Override
public void onSyncFailed ( final String errorMessage ) {
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
Toast . makeText ( NotesListActivity . this , errorMessage , Toast . LENGTH_SHORT ) . show ( ) ;
// 停止刷新动画
if ( mSwipeRefreshLayout ! = null ) {
mSwipeRefreshLayout . setRefreshing ( false ) ;
}
}
} ) ;
}
} ) ;
}
/ * *
* 执 行 下 载 操 作
* /
private void executeDownload ( ) {
SyncManager . getInstance ( this ) . triggerDownload ( new SyncManager . SyncCallback ( ) {
@Override
public void onSyncStart ( ) {
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
Toast . makeText ( NotesListActivity . this , "正在下载..." , Toast . LENGTH_SHORT ) . show ( ) ;
// 开始刷新动画
if ( mSwipeRefreshLayout ! = null ) {
mSwipeRefreshLayout . setRefreshing ( true ) ;
}
}
} ) ;
}
@Override
public void onSyncSuccess ( ) {
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
Toast . makeText ( NotesListActivity . this , "下载成功" , Toast . LENGTH_SHORT ) . show ( ) ;
// 停止刷新动画
if ( mSwipeRefreshLayout ! = null ) {
mSwipeRefreshLayout . setRefreshing ( false ) ;
}
// 刷新笔记列表
startAsyncNotesListQuery ( ) ;
}
} ) ;
}
@Override
public void onSyncFailed ( final String errorMessage ) {
runOnUiThread ( new Runnable ( ) {
@Override
public void run ( ) {
Toast . makeText ( NotesListActivity . this , errorMessage , Toast . LENGTH_SHORT ) . show ( ) ;
// 停止刷新动画
if ( mSwipeRefreshLayout ! = null ) {
mSwipeRefreshLayout . setRefreshing ( false ) ;
}
}
} ) ;
}
} ) ;
}
/ * *
* 处 理 单 条 便 签 解 锁
* /
@ -1776,17 +1419,17 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
* /
private void showEncryptFolderDialog ( final long folderId ) {
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( R . string . title_encrypt_folder ) ;
builder . setTitle ( "加密文件夹" ) ;
builder . setIcon ( android . R . drawable . ic_lock_idle_lock ) ;
// 创建密码输入框
final EditText passwordInput = new EditText ( this ) ;
passwordInput . setInputType ( InputType . TYPE_CLASS_TEXT | InputType . TYPE_TEXT_VARIATION_PASSWORD ) ;
passwordInput . setHint ( R . string . hint_set_folder_password ) ;
passwordInput . setHint ( "请设置密码" ) ;
builder . setView ( passwordInput ) ;
// 设置确定按钮
builder . setPositiveButton ( android . R . string . ok , new DialogInterface . OnClickListener ( ) {
builder . setPositiveButton ( "确定" , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
String password = passwordInput . getText ( ) . toString ( ) ;
@ -1798,16 +1441,16 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
editor . apply ( ) ;
// 显示提示
Toast . makeText ( NotesListActivity . this , R . string . toast_folder_encrypted , Toast . LENGTH_SHORT ) . show ( ) ;
Toast . makeText ( NotesListActivity . this , "文件夹已加密" , Toast . LENGTH_SHORT ) . show ( ) ;
} else {
// 密码为空,显示提示
Toast . makeText ( NotesListActivity . this , R . string . error_folder_password_empty , Toast . LENGTH_SHORT ) . show ( ) ;
Toast . makeText ( NotesListActivity . this , "密码不能为空" , Toast . LENGTH_SHORT ) . show ( ) ;
}
}
} ) ;
// 设置取消按钮
builder . setNegativeButton ( android . R . string . cancel , null ) ;
builder . setNegativeButton ( "取消" , null ) ;
// 添加忘记密码按钮
builder . setNeutralButton ( "忘记密码" , new DialogInterface . OnClickListener ( ) {
@ -1829,17 +1472,17 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
private void decryptFolder ( final long folderId ) {
// 显示密码输入对话框,验证身份
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( R . string . title_decrypt_folder ) ;
builder . setTitle ( "取消加密" ) ;
builder . setIcon ( android . R . drawable . ic_lock_idle_lock ) ;
// 创建密码输入框
final EditText passwordInput = new EditText ( this ) ;
passwordInput . setInputType ( InputType . TYPE_CLASS_TEXT | InputType . TYPE_TEXT_VARIATION_PASSWORD ) ;
passwordInput . setHint ( R . string . hint_enter_folder_password ) ;
passwordInput . setHint ( "请输入密码" ) ;
builder . setView ( passwordInput ) ;
// 设置确定按钮
builder . setPositiveButton ( android . R . string . ok , new DialogInterface . OnClickListener ( ) {
builder . setPositiveButton ( "确定" , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
String password = passwordInput . getText ( ) . toString ( ) ;
@ -1851,16 +1494,16 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
editor . apply ( ) ;
// 显示提示
Toast . makeText ( NotesListActivity . this , R . string . toast_folder_decrypted , Toast . LENGTH_SHORT ) . show ( ) ;
Toast . makeText ( NotesListActivity . this , "文件夹已取消加密" , Toast . LENGTH_SHORT ) . show ( ) ;
} else {
// 密码错误,显示提示
Toast . makeText ( NotesListActivity . this , R . string . error_folder_password_wrong , Toast . LENGTH_SHORT ) . show ( ) ;
Toast . makeText ( NotesListActivity . this , "密码错误" , Toast . LENGTH_SHORT ) . show ( ) ;
}
}
} ) ;
// 设置取消按钮
builder . setNegativeButton ( android . R . string . cancel , null ) ;
builder . setNegativeButton ( "取消" , null ) ;
// 添加忘记密码按钮
builder . setNeutralButton ( "忘记密码" , new DialogInterface . OnClickListener ( ) {
@ -1899,12 +1542,9 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
/ * *
* 显 示 文 件 夹 密 码 输 入 对 话 框
* 支 持 密 码 验 证 和 忘 记 密 码 功 能 ( 通 过 密 保 问 题 重 置 密 码 )
* @param folderId 文 件 夹 ID
* /
private void showFolderPasswordDialog ( final long folderId ) {
Log . d ( TAG , "Showing folder password dialog for folderId: " + folderId ) ;
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( "输入密码" ) ;
builder . setIcon ( android . R . drawable . ic_lock_idle_lock ) ;
@ -1919,15 +1559,11 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
builder . setPositiveButton ( "确定" , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
String password = passwordInput . getText ( ) . toString ( ) . trim ( ) ;
Log . d ( TAG , "User entered password for folder: " + folderId ) ;
String password = passwordInput . getText ( ) . toString ( ) ;
if ( checkFolderPassword ( folderId , password ) ) {
Log . i ( TAG , "Folder password verified successfully, entering folder: " + folderId ) ;
// 密码正确,进入文件夹
enterEncryptedFolder ( folderId ) ;
} else {
Log . w ( TAG , "Folder password verification failed for folder: " + folderId ) ;
// 密码错误,显示提示
Toast . makeText ( NotesListActivity . this , "密码错误,请重新输入" , Toast . LENGTH_SHORT ) . show ( ) ;
// 重新显示密码输入对话框
@ -1939,37 +1575,23 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
// 设置取消按钮
builder . setNegativeButton ( "取消" , null ) ;
// 添加"忘记密码"按钮,点击后通过密保问题验证重置密码
builder . setNeutralButton ( R . string . btn_forgot_password , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
Log . d ( TAG , "User clicked forgot password button for folder: " + folderId ) ;
// 显示通过密保问题重置密码的对话框
showResetPasswordWithSecurityQuestionsDialog ( folderId ) ;
}
} ) ;
// 显示对话框
builder . show ( ) ;
}
/ * *
* 通 过 密 保 问 题 重 置 文 件 夹 密 码
* 验 证 成 功 后 允 许 用 户 设 置 新 密 码
* @param folderId 文 件 夹 ID
* /
private void showResetPasswordWithSecurityQuestionsDialog ( final long folderId ) {
Log . d ( TAG , "Showing reset password with security questions dialog for folder: " + folderId ) ;
// 检查是否设置了密保问题
if ( ! NotesPreferenceActivity . hasSecurityQuestionsSet ( this ) ) {
Log . w ( TAG , "Security questions not set, cannot reset folder password" ) ;
Toast . makeText ( this , "请先在设置中设置密保问题" , Toast . LENGTH_SHORT ) . show ( ) ;
return ;
}
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( R . string . title_forgot_password ) ;
builder . setTitle ( "忘记密码" ) ;
builder . setIcon ( android . R . drawable . ic_dialog_alert ) ;
builder . setMessage ( "请回答密保问题以重置密码" ) ;
@ -1991,20 +1613,15 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
builder . setView ( layout ) ;
// 设置确定按钮
builder . setPositiveButton ( android . R . string . ok , new DialogInterface . OnClickListener ( ) {
builder . setPositiveButton ( "确定" , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
String name = nameInput . getText ( ) . toString ( ) . trim ( ) ;
String birthday = birthdayInput . getText ( ) . toString ( ) . trim ( ) ;
Log . d ( TAG , "Verifying security questions for folder password reset - name: " + name ) ;
String name = nameInput . getText ( ) . toString ( ) ;
String birthday = birthdayInput . getText ( ) . toString ( ) ;
if ( NotesPreferenceActivity . verifySecurityQuestions ( NotesListActivity . this , name , birthday ) ) {
Log . i ( TAG , "Security questions verified successfully for folder: " + folderId ) ;
// 验证成功,显示设置新密码的对话框
showSetNewFolderPasswordDialog ( folderId ) ;
} else {
Log . w ( TAG , "Security questions verification failed for folder password reset" ) ;
// 验证失败,显示提示
Toast . makeText ( NotesListActivity . this , "密保问题回答错误" , Toast . LENGTH_SHORT ) . show ( ) ;
}
@ -2012,7 +1629,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
} ) ;
// 设置取消按钮
builder . setNegativeButton ( android . R . string . cancel , null ) ;
builder . setNegativeButton ( "取消" , null ) ;
// 显示对话框
builder . show ( ) ;
@ -2020,35 +1637,25 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
/ * *
* 显 示 设 置 新 文 件 夹 密 码 的 对 话 框
* 用 户 设 置 新 密 码 后 , 需 要 重 新 输 入 密 码 才 能 进 入 文 件 夹
* @param folderId 文 件 夹 ID
* /
private void showSetNewFolderPasswordDialog ( final long folderId ) {
Log . d ( TAG , "Showing set new folder password dialog for folder: " + folderId ) ;
AlertDialog . Builder builder = new AlertDialog . Builder ( this ) ;
builder . setTitle ( "设置新密码" ) ;
builder . setIcon ( android . R . drawable . ic_dialog_info ) ;
builder . setMessage ( "验证成功,请设置新密码" ) ;
// 创建密码输入框
final EditText passwordInput = new EditText ( this ) ;
passwordInput . setInputType ( InputType . TYPE_CLASS_TEXT | InputType . TYPE_TEXT_VARIATION_PASSWORD ) ;
passwordInput . setHint ( "请输入新密码" ) ;
LinearLayout layout = new LinearLayout ( this ) ;
layout . setOrientation ( LinearLayout . VERTICAL ) ;
layout . setPadding ( 40 , 20 , 40 , 20 ) ;
layout . addView ( passwordInput ) ;
builder . setView ( layout ) ;
builder . setView ( passwordInput ) ;
// 设置确定按钮
builder . setPositiveButton ( android . R . string . ok , new DialogInterface . OnClickListener ( ) {
builder . setPositiveButton ( "确定" , new DialogInterface . OnClickListener ( ) {
@Override
public void onClick ( DialogInterface dialog , int which ) {
String newPassword = passwordInput . getText ( ) . toString ( ) . trim ( ) ;
String newPassword = passwordInput . getText ( ) . toString ( ) ;
if ( ! newPassword . isEmpty ( ) ) {
Log . i ( TAG , "Setting new password for folder: " + folderId ) ;
// 保存新密码
SharedPreferences preferences = getSharedPreferences ( "notes_prefs" , Context . MODE_PRIVATE ) ;
SharedPreferences . Editor editor = preferences . edit ( ) ;
@ -2056,10 +1663,8 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
editor . apply ( ) ;
// 显示提示
Toast . makeText ( NotesListActivity . this , "密码重置成功,请使用新密码进入文件夹" , Toast . LENGTH_SHORT ) . show ( ) ;
Log . i ( TAG , "Folder password reset successfully for folder: " + folderId ) ;
Toast . makeText ( NotesListActivity . this , "密码重置成功" , Toast . LENGTH_SHORT ) . show ( ) ;
} else {
Log . w ( TAG , "New folder password is empty" ) ;
// 密码为空,显示提示
Toast . makeText ( NotesListActivity . this , "密码不能为空" , Toast . LENGTH_SHORT ) . show ( ) ;
}
@ -2067,7 +1672,7 @@ public class NotesListActivity extends AppCompatActivity implements OnClickListe
} ) ;
// 设置取消按钮
builder . setNegativeButton ( android . R . string . cancel , null ) ;
builder . setNegativeButton ( "取消" , null ) ;
// 显示对话框
builder . show ( ) ;