From 554d5ec8e9ad41d2685f0875d9585183199d53b0 Mon Sep 17 00:00:00 2001
From: chroe <454604461@qq.com>
Date: Fri, 30 Jan 2026 17:11:13 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E4=BE=A7=E8=BE=B9=E6=A0=8F?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6?=
=?UTF-8?q?=E5=A4=B9=E6=98=BE=E7=A4=BA=E6=96=B9=E5=BC=8F=EF=BC=8C=E5=AE=8C?=
=?UTF-8?q?=E5=96=84=E5=A4=9A=E7=BA=A7=E6=96=87=E4=BB=B6=E5=A4=B9=E7=9A=84?=
=?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E5=AE=8C=E5=96=84=E5=A4=9A=E7=BA=A7?=
=?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=B9=E5=92=8C=E4=BE=BF=E7=AD=BE=E5=90=8C?=
=?UTF-8?q?=E6=97=B6=E6=98=BE=E7=8E=B0=E7=9A=84=E9=97=AE=E9=A2=98=EF=BC=8C?=
=?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=9C=A8=E4=BE=A7=E8=BE=B9=E6=A0=8F=E5=88=A0?=
=?UTF-8?q?=E9=99=A4=E6=96=87=E4=BB=B6=E5=A4=B9=E7=9A=84=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/net/micode/notes/tool/DataUtils.java | 84 +-
.../micode/notes/ui/NotesListActivity.java | 784 +++++++++++++++---
.../net/micode/notes/ui/SidebarAdapter.java | 142 ++++
src/main/res/drawable/count_badge.xml | 10 +
src/main/res/drawable/ic_folder_add.xml | 9 +
.../res/drawable/ic_format_color_bold.jpg | Bin 0 -> 1696 bytes
.../res/drawable/ic_format_color_bold.png | Bin 733 -> 0 bytes
.../res/drawable/ic_format_color_fill.jpg | Bin 0 -> 2337 bytes
.../res/drawable/ic_format_color_fill.png | Bin 848 -> 0 bytes
.../res/drawable/ic_format_color_text.jpg | Bin 0 -> 2099 bytes
.../res/drawable/ic_format_color_text.png | Bin 726 -> 0 bytes
src/main/res/drawable/ic_format_italic.jpg | Bin 0 -> 1717 bytes
src/main/res/drawable/ic_format_italic.png | Bin 614 -> 0 bytes
.../res/drawable/ic_format_underlined.jpg | Bin 0 -> 1779 bytes
.../res/drawable/ic_format_underlined.png | Bin 597 -> 0 bytes
src/main/res/layout/note_list.xml | 336 ++++----
src/main/res/layout/sidebar_item.xml | 32 +
src/main/res/layout/sidebar_layout.xml | 155 ++++
src/main/res/values/colors.xml | 2 +
src/main/res/values/strings.xml | 1 +
20 files changed, 1293 insertions(+), 262 deletions(-)
create mode 100644 src/main/java/net/micode/notes/ui/SidebarAdapter.java
create mode 100644 src/main/res/drawable/count_badge.xml
create mode 100644 src/main/res/drawable/ic_folder_add.xml
create mode 100644 src/main/res/drawable/ic_format_color_bold.jpg
delete mode 100644 src/main/res/drawable/ic_format_color_bold.png
create mode 100644 src/main/res/drawable/ic_format_color_fill.jpg
delete mode 100644 src/main/res/drawable/ic_format_color_fill.png
create mode 100644 src/main/res/drawable/ic_format_color_text.jpg
delete mode 100644 src/main/res/drawable/ic_format_color_text.png
create mode 100644 src/main/res/drawable/ic_format_italic.jpg
delete mode 100644 src/main/res/drawable/ic_format_italic.png
create mode 100644 src/main/res/drawable/ic_format_underlined.jpg
delete mode 100644 src/main/res/drawable/ic_format_underlined.png
create mode 100644 src/main/res/layout/sidebar_item.xml
create mode 100644 src/main/res/layout/sidebar_layout.xml
diff --git a/src/main/java/net/micode/notes/tool/DataUtils.java b/src/main/java/net/micode/notes/tool/DataUtils.java
index 82e8d10..42b64f7 100644
--- a/src/main/java/net/micode/notes/tool/DataUtils.java
+++ b/src/main/java/net/micode/notes/tool/DataUtils.java
@@ -131,21 +131,33 @@ public class DataUtils {
}
// 检查目标ID是否是一个文件夹(TYPE_FOLDER或TYPE_SYSTEM)
- Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, folderId),
- new String[] { NoteColumns.TYPE },
- null,
- null,
- null);
-
boolean isFolder = false;
- if (cursor != null) {
- if (cursor.moveToFirst()) {
- int type = cursor.getInt(0);
- if (type == Notes.TYPE_FOLDER || type == Notes.TYPE_SYSTEM) {
- isFolder = true;
+
+ // 特殊处理系统文件夹ID,它们是逻辑ID,不是实际的数据库记录ID
+ if (folderId == Notes.ID_ROOT_FOLDER ||
+ folderId == Notes.ID_TEMPARAY_FOLDER ||
+ folderId == Notes.ID_CALL_RECORD_FOLDER ||
+ folderId == Notes.ID_TRASH_FOLER ||
+ folderId == Notes.ID_PRIVACY_SPACE_FOLDER) {
+ isFolder = true;
+ Log.d(TAG, "Target is a system folder: " + folderId);
+ } else {
+ // 对于非系统文件夹,查询数据库验证
+ Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, folderId),
+ new String[] { NoteColumns.TYPE },
+ null,
+ null,
+ null);
+
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ int type = cursor.getInt(0);
+ if (type == Notes.TYPE_FOLDER || type == Notes.TYPE_SYSTEM) {
+ isFolder = true;
+ }
}
+ cursor.close();
}
- cursor.close();
}
if (!isFolder) {
@@ -456,4 +468,52 @@ public class DataUtils {
}
return snippet;
}
+
+ /**
+ * 获取指定文件夹中的便签数量
+ *
+ * 查询指定文件夹中包含的便签数量
+ *
+ *
+ * @param resolver ContentResolver对象
+ * @param folderId 文件夹ID
+ * @return 便签数量
+ */
+ public static int getNoteCount(ContentResolver resolver, long folderId) {
+ Cursor cursor = resolver.query(
+ Notes.CONTENT_NOTE_URI,
+ new String[] { "COUNT(*)" },
+ NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "=?",
+ new String[] { String.valueOf(Notes.TYPE_NOTE), String.valueOf(folderId) },
+ null
+ );
+
+ int count = 0;
+ if (cursor != null) {
+ if (cursor.moveToFirst()) {
+ try {
+ count = cursor.getInt(0);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "get note count failed:" + e.toString());
+ } finally {
+ cursor.close();
+ }
+ }
+ }
+ return count;
+ }
+
+ /**
+ * 获取未分类的便签数量
+ *
+ * 查询直接在根文件夹中的便签数量,即未分类的便签
+ *
+ *
+ * @param resolver ContentResolver对象
+ * @return 未分类的便签数量
+ */
+ public static int getUncategorizedNoteCount(ContentResolver resolver) {
+ // 未分类的便签就是直接在根文件夹中的便签
+ return getNoteCount(resolver, Notes.ID_ROOT_FOLDER);
+ }
}
diff --git a/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/main/java/net/micode/notes/ui/NotesListActivity.java
index 29f4275..6ffe5f4 100644
--- a/src/main/java/net/micode/notes/ui/NotesListActivity.java
+++ b/src/main/java/net/micode/notes/ui/NotesListActivity.java
@@ -70,6 +70,12 @@ import android.widget.Toast;
import android.widget.GridView;
import android.widget.BaseAdapter;
import android.view.ViewGroup;
+import android.widget.ScrollView;
+import androidx.drawerlayout.widget.DrawerLayout;
+import android.view.Gravity;
+import androidx.core.view.GravityCompat;
+import java.util.List;
+import java.util.ArrayList;
import net.micode.notes.R;
import net.micode.notes.data.Notes;
@@ -115,10 +121,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
// 背景选项
private static final String[] BACKGROUND_OPTIONS = {
- "高山流水", "风中树叶", "长河落日"
+ "高山流水", "风中树叶", "长河落日"
};
private static final int[] BACKGROUND_RESOURCES = {
- R.drawable.background_mountain, R.drawable.background_leaves, R.drawable.background_sunset
+ R.drawable.background_mountain, R.drawable.background_leaves, R.drawable.background_sunset
};
private ListEditState mState;
@@ -152,9 +158,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private NoteItemData mFocusNoteDataItem;
- private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO;
+ private static final String NORMAL_SELECTION = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER;
- private static final String ROOT_FOLDER_SELECTION = "(" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.PARENT_ID + "=?) OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0)";
+ private static final String ROOT_FOLDER_SELECTION = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=?";
// 隐私空间相关常量
private static final int REQUEST_CODE_PRIVACY_SPACE = 104;
@@ -179,11 +185,39 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private int mCurrentBackgroundResource = R.drawable.list_background;
private String mCurrentBackgroundPath = "";
+ // 侧边栏相关变量
+ private Button mSidebarToggleButton;
+ private ListView mFolderListView;
+ private SidebarAdapter mFolderAdapter;
+ private ListView mUserFolderListView;
+ private SidebarAdapter mUserFolderAdapter;
+ private ImageView mAddFolderButton;
+
+ // 标签选择相关
+ private String mSelectedTag = "";
+
+ // 分类侧边栏相关
+ private SidebarAdapter mCategoryAdapter = null;
+ private ListView mCategoryListView = null;
+
+ // 标签侧边栏相关
+ private SidebarAdapter mTagAdapter = null;
+ private ListView mTagListView = null;
+
+ // 快速视图相关
+ private SidebarAdapter mQuickViewAdapter = null;
+ private ListView mQuickViewListView = null;
+
+ // 统计相关
+ private TextView mTotalNotesTextView = null;
+ private TextView mPinnedNotesTextView = null;
+ private TextView mTodoNotesTextView = null;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.note_list);
-
+
// 获取隐私空间ID
Intent intent = getIntent();
if (intent != null) {
@@ -192,8 +226,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mCurrentPrivacySpaceId = "";
}
}
-
+
initResources();
+ initSidebar();
initBackground();
/**
@@ -370,13 +405,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mAddNewNote.setOnTouchListener(new NewNoteOnTouchListener());
mPrivacyBackButton = (Button) findViewById(R.id.btn_privacy_back);
mPrivacyBackButton.setOnClickListener(this);
+ mSidebarToggleButton = (Button) findViewById(R.id.btn_sidebar_toggle);
+ mSidebarToggleButton.setOnClickListener(this);
mDispatch = false;
mDispatchY = 0;
mOriginY = 0;
- mTitleBar = (TextView) findViewById(R.id.tv_title_bar);
mMainContent = (LinearLayout) findViewById(R.id.main_content);
// 获取根视图作为背景容器
- mBackgroundContainer = (RelativeLayout) findViewById(R.id.note_list_root);
+ mBackgroundContainer = (RelativeLayout) findViewById(R.id.main_content_container);
if (mBackgroundContainer == null) {
// 如果找不到,使用content view
View contentView = getWindow().getDecorView().findViewById(android.R.id.content);
@@ -404,7 +440,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
mState = ListEditState.NOTE_LIST;
mModeCallBack = new ModeCallback();
-
+
// 检查是否处于隐私空间中
updatePrivacySpaceUI();
@@ -747,8 +783,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
- // 当前选中的标签,用于筛选
- private String mSelectedTag = "";
+
private void startAsyncNotesListQuery() {
// 临时删除功能:输入"delete:1"删除ID为1的项目
@@ -766,45 +801,69 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
String baseSelection = "";
ArrayList argsList = new ArrayList<>();
- // 根据是否有搜索关键词构建不同的查询条件
- if (!TextUtils.isEmpty(mSearchQuery)) {
- // 有搜索关键词的情况
- if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
- // 根文件夹:需要将搜索条件应用到两个部分
- baseSelection = "((" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=? AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?))"
- + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0 AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)))";
- argsList.add(String.valueOf(mCurrentFolderId));
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
+ // 处理未分类情况
+ if (mCurrentFolderId == -1) {
+ // 未分类:查询所有不在文件夹中的便签
+ if (!TextUtils.isEmpty(mSearchQuery)) {
+ // 有搜索关键词的情况
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=" + Notes.ID_ROOT_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)";
argsList.add("%" + mSearchQuery + "%");
argsList.add("%" + mSearchQuery + "%");
argsList.add("%" + mSearchQuery + "%");
} else {
- // 普通文件夹
- baseSelection = NORMAL_SELECTION + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)";
- argsList.add(String.valueOf(mCurrentFolderId));
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
+ // 没有搜索关键词的情况
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=" + Notes.ID_ROOT_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
}
} else {
- // 没有搜索关键词的情况
- baseSelection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION : NORMAL_SELECTION;
- argsList.add(String.valueOf(mCurrentFolderId));
+ // 普通文件夹或根文件夹
+ // 根据是否有搜索关键词构建不同的查询条件
+ if (!TextUtils.isEmpty(mSearchQuery)) {
+ // 有搜索关键词的情况
+ if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ // 全部:查询所有文件夹中的便签,包括多级文件夹,但排除回收站
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)";
+ argsList.add("%" + mSearchQuery + "%");
+ argsList.add("%" + mSearchQuery + "%");
+ argsList.add("%" + mSearchQuery + "%");
+ } else {
+ // 普通文件夹:同时查询下一级文件夹和当前文件夹中的便签
+ baseSelection = "(" + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " OR " + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + ") AND " + NoteColumns.PARENT_ID + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)";
+ argsList.add(String.valueOf(mCurrentFolderId));
+ argsList.add("%" + mSearchQuery + "%");
+ argsList.add("%" + mSearchQuery + "%");
+ argsList.add("%" + mSearchQuery + "%");
+ }
+ } else {
+ // 没有搜索关键词的情况
+ if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ // 全部:查询所有文件夹中的便签,包括多级文件夹,但排除回收站
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
+ } else {
+ // 普通文件夹:同时查询下一级文件夹和当前文件夹中的便签
+ baseSelection = "(" + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " OR " + NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER + ") AND " + NoteColumns.PARENT_ID + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
+ argsList.add(String.valueOf(mCurrentFolderId));
+ }
+ }
}
// 添加标签筛选条件
if (!TextUtils.isEmpty(mSelectedTag)) {
- if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ if (mCurrentFolderId == -1) {
+ // 未分类情况
+ if (baseSelection.contains("AND")) {
+ baseSelection += " AND " + NoteColumns.TAGS + " LIKE ?";
+ } else {
+ baseSelection += " AND " + NoteColumns.TAGS + " LIKE ?";
+ }
+ argsList.add("%" + mSelectedTag + "%");
+ } else if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
// 根文件夹需要特殊处理
String tagCondition = " AND " + NoteColumns.TAGS + " LIKE ?";
// 根据是否有搜索关键词构建不同的标签筛选条件
if (!TextUtils.isEmpty(mSearchQuery)) {
// 有搜索关键词的情况
- baseSelection = "((" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=? AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)" + tagCondition + ")"
- + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0 AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)" + tagCondition + "))";
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + " AND (" + NoteColumns.TITLE + " LIKE ? OR " + NoteColumns.SNIPPET + " LIKE ? OR " + NoteColumns.TAGS + " LIKE ?)" + tagCondition;
// 重新构建参数列表
argsList.clear();
@@ -813,20 +872,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
argsList.add("%" + mSearchQuery + "%");
argsList.add("%" + mSearchQuery + "%");
argsList.add("%" + mSelectedTag + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSearchQuery + "%");
- argsList.add("%" + mSelectedTag + "%");
} else {
// 没有搜索关键词的情况
- baseSelection = "((" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=?" + tagCondition + ")"
- + " OR (" + NoteColumns.ID + "=" + Notes.ID_CALL_RECORD_FOLDER + " AND " + NoteColumns.NOTES_COUNT + ">0" + tagCondition + "))";
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER + tagCondition;
// 重新构建参数列表
argsList.clear();
argsList.add(String.valueOf(mCurrentFolderId));
argsList.add("%" + mSelectedTag + "%");
- argsList.add("%" + mSelectedTag + "%");
}
} else {
// 普通文件夹
@@ -843,19 +896,27 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
if (!TextUtils.isEmpty(mCurrentPrivacySpaceId)) {
// 在隐私空间中,只显示该隐私空间的便签
String privacyCondition = NoteColumns.PRIVACY_SPACE_ID + "=?";
- if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ if (mCurrentFolderId == -1) {
+ // 未分类情况
+ baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
+ argsList.add(mCurrentPrivacySpaceId);
+ } else if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
// 根文件夹需要特殊处理
if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
// 有搜索关键词或标签的情况
baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
} else {
// 没有搜索关键词和标签的情况
- baseSelection = "(" + NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.PARENT_ID + "=? AND " + privacyCondition + ")";
+ baseSelection = NoteColumns.TYPE + "<>" + Notes.TYPE_SYSTEM + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + NoteColumns.PARENT_ID + "=? AND " + privacyCondition;
// 重新构建参数列表
argsList.clear();
argsList.add(String.valueOf(mCurrentFolderId));
argsList.add(mCurrentPrivacySpaceId);
}
+ if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
+ // 有搜索关键词或标签的情况,需要添加隐私空间ID参数
+ argsList.add(mCurrentPrivacySpaceId);
+ }
} else {
// 普通文件夹
if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
@@ -863,40 +924,39 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
} else {
// 没有搜索关键词和标签的情况
- baseSelection = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + privacyCondition;
+ baseSelection = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_TODO + " AND " + NoteColumns.TYPE + "<>" + Notes.TYPE_FOLDER + " AND " + privacyCondition;
// 重新构建参数列表
argsList.clear();
argsList.add(String.valueOf(mCurrentFolderId));
argsList.add(mCurrentPrivacySpaceId);
}
- }
- if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
- // 有搜索关键词或标签的情况,需要添加隐私空间ID参数
- argsList.add(mCurrentPrivacySpaceId);
+ if (!TextUtils.isEmpty(mSearchQuery) || !TextUtils.isEmpty(mSelectedTag)) {
+ // 有搜索关键词或标签的情况,需要添加隐私空间ID参数
+ argsList.add(mCurrentPrivacySpaceId);
+ }
}
} else {
// 不在隐私空间中,只显示非隐私空间的便签
String privacyCondition = "(" + NoteColumns.PRIVACY_SPACE_ID + "='' OR " + NoteColumns.PRIVACY_SPACE_ID + " IS NULL)";
- if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
- // 根文件夹需要特殊处理
- baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
- } else {
- // 普通文件夹
- if (baseSelection.contains("AND")) {
- baseSelection += " AND " + privacyCondition;
- } else {
- baseSelection += " WHERE " + privacyCondition;
- }
- }
+ baseSelection = "(" + baseSelection + ") AND " + privacyCondition;
}
selection = baseSelection;
selectionArgs = argsList.toArray(new String[argsList.size()]);
+ // 修改排序方式,确保文件夹显示在便签之前
+ String sortOrder = "";
+ if (mCurrentFolderId != Notes.ID_ROOT_FOLDER && mCurrentFolderId != -1) {
+ // 普通文件夹:先按类型排序(文件夹在前),再按修改日期排序
+ sortOrder = NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC";
+ } else {
+ // 根文件夹或未分类:按原排序方式
+ sortOrder = NoteColumns.IS_PINNED + " DESC," + NoteColumns.PIN_PRIORITY + " DESC," +
+ NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC";
+ }
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
Notes.CONTENT_NOTE_URI, NoteItemData.PROJECTION, selection, selectionArgs,
- NoteColumns.IS_PINNED + " DESC," + NoteColumns.PIN_PRIORITY + " DESC," +
- NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
+ sortOrder);
}
private final class BackgroundQueryHandler extends AsyncQueryHandler {
@@ -953,12 +1013,24 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
private void batchDelete() {
+ if (mNotesListAdapter == null) {
+ Log.e(TAG, "mNotesListAdapter is null in batchDelete");
+ Toast.makeText(this, "删除失败:适配器为空", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
+ final HashSet selectedIds = mNotesListAdapter.getSelectedItemIds();
+ if (selectedIds == null || selectedIds.isEmpty()) {
+ Log.e(TAG, "No items selected for deletion");
+ Toast.makeText(this, "删除失败:未选择便签", Toast.LENGTH_SHORT).show();
+ return;
+ }
+
new AsyncTask>() {
protected HashSet doInBackground(Void... unused) {
HashSet widgets = mNotesListAdapter.getSelectedWidget();
// Always move notes to trash folder for better user experience
- if (!DataUtils.batchMoveToFolder(mContentResolver, mNotesListAdapter
- .getSelectedItemIds(), Notes.ID_TRASH_FOLER)) {
+ if (!DataUtils.batchMoveToFolder(mContentResolver, selectedIds, Notes.ID_TRASH_FOLER)) {
Log.e(TAG, "Move notes to trash folder error, should not happens");
}
return widgets;
@@ -974,7 +1046,15 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
- mModeCallBack.finishActionMode();
+ if (mModeCallBack != null) {
+ mModeCallBack.finishActionMode();
+ }
+ // 重新加载侧边栏数据,更新数量显示
+ loadSidebarData();
+ // 重新加载便签列表,让删除的便签立即消失
+ startAsyncNotesListQuery();
+ // 显示删除成功的提示
+ Toast.makeText(NotesListActivity.this, "已移至回收站", Toast.LENGTH_SHORT).show();
}
}.execute();
}
@@ -988,10 +1068,10 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
values.put(NoteColumns.PARENT_ID, Notes.ID_TRASH_FOLER);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
values.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
-
- int rows = mContentResolver.update(Notes.CONTENT_NOTE_URI, values,
+
+ int rows = mContentResolver.update(Notes.CONTENT_NOTE_URI, values,
NoteColumns.ID + "=?", new String[] { String.valueOf(itemId) });
-
+
if (rows > 0) {
Log.d(TAG, "Successfully moved item " + itemId + " to trash");
Toast.makeText(this, "项目已移至回收站", Toast.LENGTH_SHORT).show();
@@ -999,7 +1079,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
Log.e(TAG, "Failed to move item " + itemId + " to trash");
Toast.makeText(this, "删除失败,请重试", Toast.LENGTH_SHORT).show();
}
-
+
startAsyncNotesListQuery();
}
@@ -1067,9 +1147,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mCurrentPrivacySpaceId = "";
updatePrivacySpaceUI();
startAsyncNotesListQuery();
+ } else if (v.getId() == R.id.btn_sidebar_toggle) {
+ // 切换侧边栏显示/隐藏
+ toggleSidebar();
}
}
-
+
/**
* 更新隐私空间相关的UI元素
*/
@@ -1162,6 +1245,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
values.put(NoteColumns.PARENT_ID, mCurrentFolderId);
mContentResolver.insert(Notes.CONTENT_NOTE_URI, values);
+ // 重新加载侧边栏数据,确保新建的文件夹能显示出来
+ loadSidebarData();
}
dialog.dismiss();
}
@@ -1208,11 +1293,11 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
new String[] { String.valueOf(mCurrentFolderId) },
null
);
-
+
if (cursor != null && cursor.moveToFirst()) {
long parentId = cursor.getLong(0);
String folderName = cursor.getString(1);
-
+
if (parentId == Notes.ID_ROOT_FOLDER) {
// 返回到根文件夹
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
@@ -1255,7 +1340,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
-
+
startAsyncNotesListQuery();
break;
case CALL_RECORD_FOLDER:
@@ -1471,6 +1556,504 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
from.startActivityIfNeeded(intent, -1);
}
+ private View mAllItemView;
+ private TextView mAllTitleView;
+ private TextView mAllCountView;
+ private View mUncategorizedItemView;
+ private TextView mUncategorizedTitleView;
+ private TextView mUncategorizedCountView;
+
+ private void initSidebar() {
+ mAllItemView = findViewById(R.id.all_item);
+ mAllTitleView = findViewById(R.id.all_title);
+ mAllCountView = findViewById(R.id.all_count);
+ mUncategorizedItemView = findViewById(R.id.uncategorized_item);
+ mUncategorizedTitleView = findViewById(R.id.uncategorized_title);
+ mUncategorizedCountView = findViewById(R.id.uncategorized_count);
+ mUserFolderListView = findViewById(R.id.user_folder_list);
+ mAddFolderButton = findViewById(R.id.add_folder_button);
+
+ // 加载侧边栏数据
+ loadSidebarData();
+
+ // 设置全部项点击事件
+ mAllItemView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 更新选中状态
+ updateTopItemSelection(true);
+ // 切换到全部
+ mCurrentFolderId = Notes.ID_ROOT_FOLDER;
+ startAsyncNotesListQuery();
+ // 关闭侧边栏
+ toggleSidebar();
+ }
+ });
+
+ // 设置未分类项点击事件
+ mUncategorizedItemView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // 更新选中状态
+ updateTopItemSelection(false);
+ // 切换到未分类
+ mCurrentFolderId = -1;
+ startAsyncNotesListQuery();
+ // 关闭侧边栏
+ toggleSidebar();
+ }
+ });
+
+ // 设置用户文件夹列表点击事件
+ mUserFolderListView.setOnItemClickListener(new OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(position);
+ if (item != null) {
+ // 更新选中状态
+ updateUserFolderSelection(position);
+ // 切换到对应的文件夹
+ mCurrentFolderId = item.getCategoryId();
+ startAsyncNotesListQuery();
+ // 关闭侧边栏
+ toggleSidebar();
+ }
+ }
+ });
+
+ // 设置用户文件夹列表长按事件,实现删除文件夹功能
+ mUserFolderListView.setOnItemLongClickListener(new OnItemLongClickListener() {
+ @Override
+ public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(position);
+ if (item != null) {
+ final long folderId = item.getCategoryId();
+ if (folderId == Notes.ID_ROOT_FOLDER) {
+ // 根文件夹不能删除
+ Toast.makeText(NotesListActivity.this, "根文件夹不能删除", Toast.LENGTH_SHORT).show();
+ return true;
+ }
+
+ // 显示确认删除对话框
+ AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
+ builder.setTitle("确认删除");
+ builder.setMessage("确定要删除文件夹 \"" + item.getTitle() + "\" 吗?");
+ builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // 删除文件夹
+ deleteFolder(folderId);
+ // 重新加载侧边栏数据
+ loadSidebarData();
+ // 显示删除成功提示
+ Toast.makeText(NotesListActivity.this, "文件夹已删除", Toast.LENGTH_SHORT).show();
+ }
+ });
+ builder.setNegativeButton("取消", null);
+ builder.show();
+ return true;
+ }
+ return false;
+ }
+ });
+
+ // 设置添加文件夹按钮点击事件
+ mAddFolderButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showCreateOrModifyFolderDialog(true);
+ // 关闭侧边栏
+ toggleSidebar();
+ }
+ });
+ }
+
+ private void loadSidebarData() {
+ // 加载全部项数据
+ int totalNotesCount = getTotalNoteCount();
+ mAllCountView.setText(String.valueOf(totalNotesCount));
+ if (totalNotesCount > 0) {
+ mAllCountView.setVisibility(View.VISIBLE);
+ } else {
+ mAllCountView.setVisibility(View.GONE);
+ }
+
+ // 加载未分类项数据
+ int uncategorizedCount = DataUtils.getUncategorizedNoteCount(mContentResolver);
+ mUncategorizedCountView.setText(String.valueOf(uncategorizedCount));
+ if (uncategorizedCount > 0) {
+ mUncategorizedCountView.setVisibility(View.VISIBLE);
+ } else {
+ mUncategorizedCountView.setVisibility(View.GONE);
+ }
+
+ // 加载用户文件夹(递归加载,显示层级结构)
+ List userFolderItems = new ArrayList<>();
+ loadFoldersRecursive(Notes.ID_ROOT_FOLDER, userFolderItems, 0);
+
+ // 创建并设置用户文件夹适配器
+ mUserFolderAdapter = new SidebarAdapter(this, userFolderItems);
+ mUserFolderListView.setAdapter(mUserFolderAdapter);
+
+ // 默认选中全部项
+ updateTopItemSelection(true);
+ }
+
+ private void updateFolderSelection(int position) {
+ // 取消所有顶部选项的选中状态
+ if (mFolderAdapter != null) {
+ for (int i = 0; i < mFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mFolderAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ // 设置当前选项为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mFolderAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mFolderAdapter.notifyDataSetChanged();
+ }
+ // 取消所有用户文件夹的选中状态
+ if (mUserFolderAdapter != null) {
+ for (int i = 0; i < mUserFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ mUserFolderAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void updateTopItemSelection(boolean selectAll) {
+ // 重置所有顶部选项的状态
+ mAllItemView.setBackgroundColor(getResources().getColor(R.color.surface, null));
+ mAllTitleView.setTextColor(getResources().getColor(R.color.onSurface, null));
+ mAllCountView.setTextColor(getResources().getColor(R.color.primary, null));
+ mUncategorizedItemView.setBackgroundColor(getResources().getColor(R.color.surface, null));
+ mUncategorizedTitleView.setTextColor(getResources().getColor(R.color.onSurface, null));
+ mUncategorizedCountView.setTextColor(getResources().getColor(R.color.primary, null));
+
+ // 取消所有用户文件夹的选中状态
+ if (mUserFolderAdapter != null) {
+ for (int i = 0; i < mUserFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ mUserFolderAdapter.notifyDataSetChanged();
+ }
+
+ // 设置选中状态
+ if (selectAll) {
+ mAllItemView.setBackgroundColor(getResources().getColor(R.color.primary, null));
+ mAllTitleView.setTextColor(getResources().getColor(R.color.onPrimary, null));
+ mAllCountView.setTextColor(getResources().getColor(R.color.onPrimary, null));
+ } else {
+ mUncategorizedItemView.setBackgroundColor(getResources().getColor(R.color.primary, null));
+ mUncategorizedTitleView.setTextColor(getResources().getColor(R.color.onPrimary, null));
+ mUncategorizedCountView.setTextColor(getResources().getColor(R.color.onPrimary, null));
+ }
+ }
+
+ private void updateUserFolderSelection(int position) {
+ // 重置所有顶部选项的状态
+ mAllItemView.setBackgroundColor(getResources().getColor(R.color.surface, null));
+ mAllTitleView.setTextColor(getResources().getColor(R.color.onSurface, null));
+ mAllCountView.setTextColor(getResources().getColor(R.color.primary, null));
+ mUncategorizedItemView.setBackgroundColor(getResources().getColor(R.color.surface, null));
+ mUncategorizedTitleView.setTextColor(getResources().getColor(R.color.onSurface, null));
+ mUncategorizedCountView.setTextColor(getResources().getColor(R.color.primary, null));
+
+ // 取消所有用户文件夹的选中状态
+ if (mUserFolderAdapter != null) {
+ for (int i = 0; i < mUserFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+
+ // 设置当前文件夹为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mUserFolderAdapter.notifyDataSetChanged();
+ }
+ }
+
+ /**
+ * 更新侧边栏的选中状态,根据当前文件夹ID选择对应的侧边栏项
+ */
+ private void updateSidebarSelection() {
+ if (mCurrentFolderId == Notes.ID_ROOT_FOLDER) {
+ // 当前在根文件夹,选中全部项
+ updateTopItemSelection(true);
+ } else if (mCurrentFolderId == -1) {
+ // 当前在未分类,选中未分类项
+ updateTopItemSelection(false);
+ } else {
+ // 当前在用户文件夹,找到并选中对应的文件夹项
+ if (mUserFolderAdapter != null) {
+ for (int i = 0; i < mUserFolderAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mUserFolderAdapter.getItem(i);
+ if (item != null && item.getCategoryId() == mCurrentFolderId) {
+ updateUserFolderSelection(i);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 获取所有文件夹中的便签总数,包括多级文件夹
+ */
+ private int getTotalNoteCount() {
+ // 递归获取所有文件夹中的便签数量
+ return getNoteCountRecursive(Notes.ID_ROOT_FOLDER);
+ }
+
+ /**
+ * 递归获取文件夹及其子文件夹中的便签数量
+ */
+ private int getNoteCountRecursive(long folderId) {
+ int count = 0;
+
+ // 获取当前文件夹中的便签数量(只统计普通便签,不统计待办事项)
+ Cursor noteCursor = mContentResolver.query(
+ Notes.CONTENT_NOTE_URI,
+ new String[] { "COUNT(*)" },
+ NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "=?",
+ new String[] { String.valueOf(Notes.TYPE_NOTE), String.valueOf(folderId) },
+ null
+ );
+
+ if (noteCursor != null) {
+ if (noteCursor.moveToFirst()) {
+ try {
+ count = noteCursor.getInt(0);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "get note count failed:" + e.toString());
+ } finally {
+ noteCursor.close();
+ }
+ }
+ }
+
+ // 获取当前文件夹中的子文件夹
+ Cursor folderCursor = mContentResolver.query(
+ Notes.CONTENT_NOTE_URI,
+ new String[] { NoteColumns.ID },
+ NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "=?",
+ new String[] { String.valueOf(Notes.TYPE_FOLDER), String.valueOf(folderId) },
+ null
+ );
+
+ if (folderCursor != null) {
+ while (folderCursor.moveToNext()) {
+ try {
+ long childFolderId = folderCursor.getLong(0);
+ // 递归获取子文件夹中的便签数量
+ count += getNoteCountRecursive(childFolderId);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "get folder id failed:" + e.toString());
+ }
+ }
+ folderCursor.close();
+ }
+
+ return count;
+ }
+
+ /**
+ * 递归加载文件夹及其子文件夹,显示层级结构
+ */
+ private void loadFoldersRecursive(long parentFolderId, List folderItems, int level) {
+ // 获取当前文件夹下的子文件夹
+ Cursor folderCursor = mContentResolver.query(
+ Notes.CONTENT_NOTE_URI,
+ new String[]{NoteColumns.ID, NoteColumns.SNIPPET, NoteColumns.NOTES_COUNT},
+ NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "=?",
+ new String[]{String.valueOf(Notes.TYPE_FOLDER), String.valueOf(parentFolderId)},
+ NoteColumns.MODIFIED_DATE + " DESC"
+ );
+
+ if (folderCursor != null) {
+ while (folderCursor.moveToNext()) {
+ try {
+ long folderId = folderCursor.getLong(0);
+ String folderName = folderCursor.getString(1);
+ int noteCount = folderCursor.getInt(2);
+
+ // 根据层级添加缩进
+ StringBuilder indentedName = new StringBuilder();
+ for (int i = 0; i < level; i++) {
+ indentedName.append(" "); // 每级添加两个空格的缩进
+ }
+ indentedName.append(folderName);
+
+ // 添加文件夹项
+ folderItems.add(new SidebarAdapter.SidebarItem(indentedName.toString(), noteCount, folderId));
+
+ // 递归加载子文件夹
+ loadFoldersRecursive(folderId, folderItems, level + 1);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(TAG, "load folder failed:" + e.toString());
+ }
+ }
+ folderCursor.close();
+ }
+ }
+
+ private void initCategoryData() {
+ // 模拟分类数据,实际应该从数据库获取
+ List categories = new ArrayList<>();
+ categories.add(new SidebarAdapter.SidebarItem("全部便签", 15, Notes.ID_ROOT_FOLDER));
+ categories.add(new SidebarAdapter.SidebarItem("工作", 8, 1));
+ categories.add(new SidebarAdapter.SidebarItem("生活", 5, 2));
+ categories.add(new SidebarAdapter.SidebarItem("学习", 2, 3));
+
+ mCategoryAdapter = new SidebarAdapter(this, categories);
+ mCategoryListView.setAdapter(mCategoryAdapter);
+
+ // 默认选中第一个分类
+ if (!categories.isEmpty()) {
+ categories.get(0).setSelected(true);
+ mCategoryAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void initTagData() {
+ // 模拟标签数据,实际应该从数据库获取
+ List tags = new ArrayList<>();
+ tags.add(new SidebarAdapter.SidebarItem("重要", 5, "重要"));
+ tags.add(new SidebarAdapter.SidebarItem("紧急", 3, "紧急"));
+ tags.add(new SidebarAdapter.SidebarItem("想法", 4, "想法"));
+ tags.add(new SidebarAdapter.SidebarItem("计划", 2, "计划"));
+
+ mTagAdapter = new SidebarAdapter(this, tags);
+ mTagListView.setAdapter(mTagAdapter);
+ }
+
+ private void initQuickViewData() {
+ // 初始化快捷视图数据
+ List quickViews = new ArrayList<>();
+ quickViews.add(new SidebarAdapter.SidebarItem("全部便签", 15, SidebarAdapter.SidebarItem.QuickViewType.ALL));
+ quickViews.add(new SidebarAdapter.SidebarItem("已置顶", 3, SidebarAdapter.SidebarItem.QuickViewType.PINNED));
+ quickViews.add(new SidebarAdapter.SidebarItem("今天", 2, SidebarAdapter.SidebarItem.QuickViewType.TODAY));
+ quickViews.add(new SidebarAdapter.SidebarItem("无标签", 6, SidebarAdapter.SidebarItem.QuickViewType.UNTAGGED));
+
+ mQuickViewAdapter = new SidebarAdapter(this, quickViews);
+ mQuickViewListView.setAdapter(mQuickViewAdapter);
+
+ // 默认选中第一个快捷视图
+ if (!quickViews.isEmpty()) {
+ quickViews.get(0).setSelected(true);
+ mQuickViewAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void initNoteStatistics() {
+ // 模拟统计数据,实际应该从数据库获取
+ mTotalNotesTextView.setText("15");
+ mPinnedNotesTextView.setText("3");
+ mTodoNotesTextView.setText("2");
+ }
+
+ private void updateCategorySelection(int position) {
+ // 取消所有分类的选中状态
+ if (mCategoryAdapter != null) {
+ for (int i = 0; i < mCategoryAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mCategoryAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ // 设置当前分类为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mCategoryAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mCategoryAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void updateTagSelection(int position) {
+ // 取消所有标签的选中状态
+ if (mTagAdapter != null) {
+ for (int i = 0; i < mTagAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mTagAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ // 设置当前标签为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mTagAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mTagAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void updateQuickViewSelection(int position) {
+ // 取消所有快捷视图的选中状态
+ if (mQuickViewAdapter != null) {
+ for (int i = 0; i < mQuickViewAdapter.getCount(); i++) {
+ SidebarAdapter.SidebarItem item = (SidebarAdapter.SidebarItem) mQuickViewAdapter.getItem(i);
+ if (item != null) {
+ item.setSelected(false);
+ }
+ }
+ // 设置当前快捷视图为选中状态
+ SidebarAdapter.SidebarItem currentItem = (SidebarAdapter.SidebarItem) mQuickViewAdapter.getItem(position);
+ if (currentItem != null) {
+ currentItem.setSelected(true);
+ }
+ mQuickViewAdapter.notifyDataSetChanged();
+ }
+ }
+
+ private void applyQuickViewFilter(SidebarAdapter.SidebarItem.QuickViewType type) {
+ // 根据快捷视图类型应用不同的筛选条件
+ switch (type) {
+ case ALL:
+ // 清除所有筛选条件
+ mCurrentFolderId = Notes.ID_ROOT_FOLDER;
+ mSelectedTag = "";
+ break;
+ case PINNED:
+ // 只显示已置顶的便签
+ // 这里需要在startAsyncNotesListQuery中添加置顶筛选逻辑
+ break;
+ case TODAY:
+ // 只显示今天创建或修改的便签
+ // 这里需要在startAsyncNotesListQuery中添加日期筛选逻辑
+ break;
+ case UNTAGGED:
+ // 只显示无标签的便签
+ mSelectedTag = "";
+ // 这里需要在startAsyncNotesListQuery中添加无标签筛选逻辑
+ break;
+ }
+ }
+
+ private void toggleSidebar() {
+ DrawerLayout drawerLayout = findViewById(R.id.drawer_layout);
+ if (drawerLayout != null) {
+ if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
+ drawerLayout.closeDrawer(GravityCompat.START);
+ } else {
+ drawerLayout.openDrawer(GravityCompat.START);
+ }
+ }
+ }
+
private class OnListItemClickListener implements OnItemClickListener {
public void onItemClick(AdapterView> parent, View view, int position, long id) {
@@ -1485,27 +2068,18 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return;
}
- switch (mState) {
- case NOTE_LIST:
- case SUB_FOLDER:
- if (item.getType() == Notes.TYPE_FOLDER
- || item.getType() == Notes.TYPE_SYSTEM) {
- openFolder(item);
- } else if (item.getType() == Notes.TYPE_NOTE) {
- openNode(item);
- } else {
- Log.e(TAG, "Wrong note type in NOTE_LIST or SUB_FOLDER");
- }
- break;
- case CALL_RECORD_FOLDER:
- if (item.getType() == Notes.TYPE_NOTE) {
- openNode(item);
- } else {
- Log.e(TAG, "Wrong note type in CALL_RECORD_FOLDER");
- }
- break;
- default:
- break;
+ // 处理便签点击
+ if (item.getType() == Notes.TYPE_NOTE) {
+ openNode(item);
+ }
+ // 处理文件夹点击
+ else if (item.getType() == Notes.TYPE_FOLDER) {
+ // 更新当前文件夹ID
+ mCurrentFolderId = item.getId();
+ // 重新加载便签列表,显示该文件夹的内容
+ startAsyncNotesListQuery();
+ // 更新侧边栏的选中状态
+ updateSidebarSelection();
}
}
}
@@ -1736,14 +2310,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
mCurrentBackgroundType = sp.getString(PREFERENCE_BACKGROUND + "_type", BACKGROUND_TYPE_DEFAULT);
mCurrentBackgroundPath = sp.getString(PREFERENCE_BACKGROUND + "_path", "");
-
+
if (BACKGROUND_TYPE_DEFAULT.equals(mCurrentBackgroundType)) {
int backgroundIndex = sp.getInt(PREFERENCE_BACKGROUND + "_index", 0);
if (backgroundIndex >= 0 && backgroundIndex < BACKGROUND_RESOURCES.length) {
mCurrentBackgroundResource = BACKGROUND_RESOURCES[backgroundIndex];
}
}
-
+
// 更新背景
updateBackground();
}
@@ -1755,7 +2329,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
if (mBackgroundContainer == null) {
return;
}
-
+
try {
if (BACKGROUND_TYPE_DEFAULT.equals(mCurrentBackgroundType)) {
// 使用默认背景
@@ -1773,23 +2347,23 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
// 如果是内部存储路径
bitmap = android.graphics.BitmapFactory.decodeFile(mCurrentBackgroundPath);
}
-
+
if (bitmap != null) {
// 计算屏幕尺寸
android.util.DisplayMetrics displayMetrics = new android.util.DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
-
+
// 缩放图片以适配屏幕
android.graphics.Bitmap scaledBitmap = android.graphics.Bitmap.createScaledBitmap(
bitmap, screenWidth, screenHeight, true);
-
+
android.graphics.drawable.BitmapDrawable drawable = new android.graphics.drawable.BitmapDrawable(getResources(), scaledBitmap);
// 设置背景图片的缩放方式
drawable.setTileModeXY(android.graphics.Shader.TileMode.CLAMP, android.graphics.Shader.TileMode.CLAMP);
mBackgroundContainer.setBackground(drawable);
-
+
// 释放原始 bitmap
if (bitmap != scaledBitmap) {
bitmap.recycle();
@@ -1817,7 +2391,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
SharedPreferences.Editor editor = sp.edit();
editor.putString(PREFERENCE_BACKGROUND + "_type", mCurrentBackgroundType);
editor.putString(PREFERENCE_BACKGROUND + "_path", mCurrentBackgroundPath);
-
+
if (BACKGROUND_TYPE_DEFAULT.equals(mCurrentBackgroundType)) {
// 找到当前背景资源的索引
int index = 0;
@@ -1829,7 +2403,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
editor.putInt(PREFERENCE_BACKGROUND + "_index", index);
}
-
+
editor.apply();
}
@@ -1839,12 +2413,12 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private void showBackgroundSelectorDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("选择背景");
-
+
// 创建背景选项数组,添加从相册选择的选项
String[] options = new String[BACKGROUND_OPTIONS.length + 1];
System.arraycopy(BACKGROUND_OPTIONS, 0, options, 0, BACKGROUND_OPTIONS.length);
options[BACKGROUND_OPTIONS.length] = "从相册选择";
-
+
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
@@ -1865,7 +2439,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
});
-
+
builder.show();
}
diff --git a/src/main/java/net/micode/notes/ui/SidebarAdapter.java b/src/main/java/net/micode/notes/ui/SidebarAdapter.java
new file mode 100644
index 0000000..060a3e1
--- /dev/null
+++ b/src/main/java/net/micode/notes/ui/SidebarAdapter.java
@@ -0,0 +1,142 @@
+package net.micode.notes.ui;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import net.micode.notes.R;
+
+import java.util.List;
+
+public class SidebarAdapter extends BaseAdapter {
+ private Context mContext;
+ private List mItems;
+
+ public SidebarAdapter(Context context, List items) {
+ mContext = context;
+ mItems = items;
+ }
+
+ @Override
+ public int getCount() {
+ return mItems != null ? mItems.size() : 0;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return mItems != null ? mItems.get(position) : null;
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = LayoutInflater.from(mContext).inflate(R.layout.sidebar_item, parent, false);
+ }
+
+ SidebarItem item = mItems.get(position);
+ TextView titleTextView = convertView.findViewById(R.id.item_title);
+ TextView countTextView = convertView.findViewById(R.id.item_count);
+
+ titleTextView.setText(item.getTitle());
+ if (item.getCount() > 0) {
+ countTextView.setVisibility(View.VISIBLE);
+ countTextView.setText(String.valueOf(item.getCount()));
+ } else {
+ countTextView.setVisibility(View.GONE);
+ }
+
+ if (item.isSelected()) {
+ convertView.setBackgroundColor(mContext.getResources().getColor(R.color.primary, null));
+ titleTextView.setTextColor(mContext.getResources().getColor(R.color.onPrimary, null));
+ countTextView.setTextColor(mContext.getResources().getColor(R.color.onPrimary, null));
+ } else {
+ convertView.setBackgroundColor(mContext.getResources().getColor(R.color.surface, null));
+ titleTextView.setTextColor(mContext.getResources().getColor(R.color.onSurface, null));
+ countTextView.setTextColor(mContext.getResources().getColor(R.color.primary, null));
+ }
+
+ return convertView;
+ }
+
+ public static class SidebarItem {
+ private String mTitle;
+ private int mCount;
+ private boolean mSelected;
+ private String mTag;
+ private long mCategoryId;
+ private QuickViewType mQuickViewType;
+
+ public SidebarItem(String title) {
+ mTitle = title;
+ mCount = 0;
+ mSelected = false;
+ }
+
+ public SidebarItem(String title, int count) {
+ mTitle = title;
+ mCount = count;
+ mSelected = false;
+ }
+
+ public SidebarItem(String title, int count, long categoryId) {
+ mTitle = title;
+ mCount = count;
+ mSelected = false;
+ mCategoryId = categoryId;
+ }
+
+ public SidebarItem(String title, int count, String tag) {
+ mTitle = title;
+ mCount = count;
+ mSelected = false;
+ mTag = tag;
+ }
+
+ public SidebarItem(String title, int count, QuickViewType type) {
+ mTitle = title;
+ mCount = count;
+ mSelected = false;
+ mQuickViewType = type;
+ }
+
+ public String getTitle() {
+ return mTitle;
+ }
+
+ public int getCount() {
+ return mCount;
+ }
+
+ public boolean isSelected() {
+ return mSelected;
+ }
+
+ public void setSelected(boolean selected) {
+ mSelected = selected;
+ }
+
+ public String getTag() {
+ return mTag;
+ }
+
+ public long getCategoryId() {
+ return mCategoryId;
+ }
+
+ public QuickViewType getQuickViewType() {
+ return mQuickViewType;
+ }
+
+ public enum QuickViewType {
+ ALL, PINNED, TODAY, UNTAGGED
+ }
+ }
+}
diff --git a/src/main/res/drawable/count_badge.xml b/src/main/res/drawable/count_badge.xml
new file mode 100644
index 0000000..6e5f178
--- /dev/null
+++ b/src/main/res/drawable/count_badge.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/drawable/ic_folder_add.xml b/src/main/res/drawable/ic_folder_add.xml
new file mode 100644
index 0000000..13f65ef
--- /dev/null
+++ b/src/main/res/drawable/ic_folder_add.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/src/main/res/drawable/ic_format_color_bold.jpg b/src/main/res/drawable/ic_format_color_bold.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..29c3985673b89dc19f7db7e3d9cfacee12f35f32
GIT binary patch
literal 1696
zcmb_ac~n$Y82{e98HPoSVNL1C$e!X9i-DSlhCyHy6;MOO0}cZWlcKXBipVGmnpm-@
z2xbJNpoN8~NhG@qW+j2_FpQAm(m4YJy=0izeNf`*^hYPV_uTh>_gjAV`+fJ49b`Y4
ztn}mi0fqr!Xaaek=E3LjB7;KK`tbu-OgU)w0*PcB9RT9DD`X-5KJ1NQo7hY>Fwryy
zOJECxatSvmC=i9fUw;bEjPW*#9iU|q#dUk`@l*$;$!f1WvwO{tEmCLV{t+2Q$H;}q
zqeUx5D3K{pvC#Ag}pP#SPoMK9n#&qX0%fSCg@nMslpMI<>{41o6l)NUuc
zfrp;T%MFU;ZeF!=L>heMAZ508xgIyU|r@%uAM7Y6wAmQ5@Bn=Tg8MWfSkI+N0c(Gn@)EIMPp
ztDY%0m?@B&*}Co5H}}aZEUz=La}Uv2M9G>BE$uzj4#SkRDP{joSn7XL_FUMEt}d8`
zW9ag57I=eB=Uh~isp?oZt|ZDPwrSZ!+5|5-jD*z6lwPG?@|uDZ`s^YpPn~
zGp(OwgmKPhiyhr;+P82AgRsc!hqPwy<1VPM<;haQX`sM5r87gbFIjYIpybA0&Vz?H
zRF|zjs5X7l^y#Bdyjsf?v})_SDICIS70cnuVEUM1qeE5n&eLZF`MQ=Tqq)~@G<+rD
z#5}6yeomA$7L=1v_q~5a`;H3`jO#w&;3nDpXIE!}tc`)C6Of<9D_5=4%-0;RMx(Z!`NNkM!AI
zsmi_CXG$avEIW0Yn^4ACqCOgV_zh0_Q2f{u&X`fgxiKTv&`F8+vq4=+PDG?8r@x@y
zW?%Iy6&hyUj`V5+BD}xKGCN#pOjtGKN2XsYmb&&z_ekT%`0#-P;O{#bZ0u8#ki`W&=h9f2?-;9_U5KDlIGK|Jbn)RyDwmJqeY}fZVjez~Pt`HQP
zDwX+T_86D4ZFPVRkR66DlG>ev=d@3ir$7|6yPniu2GX)+)<84>V;FNM=Doh}f_MVD
z(QT7Axch;`OO!dU@HL0rI?D3zkeR_}5M{fE@LqAdQ2l46llxKy&z5%BPUwdY2C)5r
zYYT2xaP@fDBP8XU_3D{_`j207*fxao?ZCbO000SaNLh0L02Uo#4->BD|-HH;zzsx0RICZF>1|b)3U7FISz$F
zgb+>BG)?0K2#j-(&*vXi%jL3Znmhp33jFT1T8$9mJD%qa27_+5+w1j;#bT*c`V+tx
zA%s$TeJvCU`~BXw?S8+{19)YVv)L>Ftk-Lv@GF4vcnkpXc$_C3{E6oC`Ssb~1KYL%
zpi-&42hizs?oC;ilgT6x;KhUHd7fby)9ExgijPGprIZeb!&~!oI!z`MUDqk4)oS&8
zJ~KKX;?pY-MNw7NR;vX7tJP{Yn+4>b1^7y(Qn6SJ05+S=M*xoFY`0qgNF);P2OJIu
z(=?CAV>B8~r_<~(YfJ?}K*V;t9S(=DCL%7EOUH2lpwVbZQox|I%DG%_G#V`yi~EwI
zDD`@s=PqJh*RJbYmbKgMZcSO1GntI4s*y+}uzLXDE&Bd{@(=I>d;#DBGAP+wu?}rN
P00000NkvXXu0mjf`vpUd
diff --git a/src/main/res/drawable/ic_format_color_fill.jpg b/src/main/res/drawable/ic_format_color_fill.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..4913d74ad280124cc4bc2165713d104e32c46595
GIT binary patch
literal 2337
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
literal 0
HcmV?d00001
diff --git a/src/main/res/drawable/ic_format_color_text.png b/src/main/res/drawable/ic_format_color_text.png
deleted file mode 100644
index 645e83f06981953b5faf4b9fac05ea7e2f8fbea3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 726
zcmV;{0xA88P)%`0#-P;O{#bZ0u8#ki`W&=h9f2?-;9_U5KDlIGK|Jbn)RyDwmJqeY}fZVjez~Pt`HQP
zDwX+T_86D4ZFPVRkR66DlG>ev=d@3ir$7|6yPniu2GX)+)<84>V;FNM=Doh}f_MVD
z(QT7Axch;`OO!dU@HL0rI?D3zkeR_}5M{fE@LqAdQ2l46llxKy&z5%BPUwdY2C)5r
zYYT2xaP@fDBP8XU_3D{_`j207*fxao?ZCbO000SaNLh0L02U|IF4zW%I2nNI*ya;
zTmZg@`pwRDE~v586MHLi5kK{__mHj57s_g`|96hx;J*+40?~|}y>6b4Gynhq07*qo
IM6N<$g0jy|+yDRo
diff --git a/src/main/res/drawable/ic_format_italic.jpg b/src/main/res/drawable/ic_format_italic.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..12c85d7618904e3fe7bded1b8f1d27ee3d4a9f41
GIT binary patch
literal 1717
zcmb_aX;f236uvJnAuKK=5UiplvI#1!Y@!^|0)hoMh+D;$G=wcK7?LQ&(~5u<(N;tR
zE8PwVwWUQ%6*NErYY>-ON)Zsy5Tq`}g+v4%kmPk0P+saD
z6OD;r16+YnD)tWxTY*yGuRn#yZLpPM2WWPqxUNpiO>;`IT)E)5RZCMZCv80MACY-<
zj8upsIy7U1Vu=i0HX31vB$=4P`w_O5pi3eADTU+4@OKoB8pBFs&RSj|%DIU!R~Roq
z92kM{+^84)aWCLM&qXO0T|20`mGSUGMxLqulh~na9Tz^!h7;Z>{
z@U^*Ik9qDs094J#PVEmj))KS%Y226I1>jdpl4RAmFSHh*4DB>mjQd;`0I)0oE-S|>S
zKwSda34y3pUd||zmt#P?$vR+}f+KKo%pPbg3}<1a670}JGsd{bN{H4poX#*|nwptg
zpoDTupkX*pqvH$)9d$bPK8gdK#bD2L_cyT$7clJ;tvyn+3rrmX$}VttO&UkfC`p=`
zxy_VUrcQHmp5@{?+sk{t&w_=%flGsem%SMhx@PUV^&3#(h0!swaq*(fQrV83Ny+kE
z>3cuem$5(dz>%Dzxp~JvKAvBAqNw=GlV5#Z^8J~!0%*WG&&upGbvpdEr}A&
zqBCZ?o3Q=EnSw+sdyiC8>wxTnvI}Moo;(dFO44L*j>-t1|sgm38Z*Zohp+_>Jh?yvX)dHe2Mpp!G0gB}X@`!}K4<5cjpCgSlD3`m;;a
zMV7l8?M%wIO;!)>i>=UC)-0+ixYKuVM7H{rZdFU^00~5h?paf{!^EMCYFEzQ@W-F5
z^KD-F`pBZhER`LN2=1(loTTYWck{005Jx&M`UZWTWm4O7n%!IDp*?hZ#?b($TJ5X@
z<<}0D^7$=K-0wwh-u02PZ3FMfQ-$*$-^$?)gH6Q49ix7R#>ES@KW9XDG#)x#`gqY)
zO~b{*dxj#NiDNy>FTdxb{%n%UPbKiFd~zZ_XZdugZSv9_uN706y(PLw+9Vx2#b9>5
zr_UxitKn4-efDm4az_2)Ij!Y(mPC3)O|!SByyRg-`8Cz%h}_O)C63#q@*Q(?mfvld
z{%!@^8$Ud`FeRFV)SX>tG9KwQUEMBKhSoMOx2XemwnS!ou|msNE@9ukh1gZD)#tO>
zTQUdwIK8_{M}DXi6;|Y_ZdAEd=8w#-o};#VbVXw^xJh%VSl!s(*UjH+up;;yTMku~
zJWyGk$!l#3Yq|dIeE#-I(f#xJqWa?Md9L!%qQpH16kA72!8$z1I8(^>-M816Q5{`W
T@J>JdQb}H|{ZU>LM?L%pih4?C
literal 0
HcmV?d00001
diff --git a/src/main/res/drawable/ic_format_italic.png b/src/main/res/drawable/ic_format_italic.png
deleted file mode 100644
index bdb9a04b36a1f9feac4e6b4c66fd2d7a216672c0..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 614
zcmV-s0-61ZP)%`0#-P;O{#bZ0u8#ki`W&=h9f2?-;9_U5KDlIGK|Jbn)RyDwmJqeY}fZVjez~Pt`HQP
zDwX+T_86D4ZFPVRkR66DlG>ev=d@3ir$7|6yPniu2GX)+)<84>V;FNM=Doh}f_MVD
z(QT7Axch;`OO!dU@HL0rI?D3zkeR_}5M{fE@LqAdQ2l46llxKy&z5%BPUwdY2C)5r
zYYT2xaP@fDBP8XU_3D{_`j207*fxao?ZCbO000SaNLh0L02U3dz4zfs;Xfa9z2i#o$@?imc_R1gXb|Ngb;*KQ525j$Vzox
zcU|W=&hZMS1R)dzK@>%@Qs4JgRXL7BQ50Dzj$@W(RaHIJIxQ{Bl4Y4?Su{Q=wOL~{|1=-KYGNY~T5&!@I07*qoM6N<$f_z~V
AC;$Ke
diff --git a/src/main/res/drawable/ic_format_underlined.jpg b/src/main/res/drawable/ic_format_underlined.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..6c6d44ac1641eb9e5dc267cf09cddbcc6162d5a3
GIT binary patch
literal 1779
zcmb_cYfw{16h1dMA%G|Z6co`!<<+X7AVM86LJ%6Tf#Q
zR(w@(#tKr@)>5n}v0k>iB05Rz7Z$c2rNCcr1D>*>Rs%ag^HKxXP5Z+NC%M&oKF4fYn)+ucrt5-Hm3HiQ=?OT`A9gYZlV+7!aa4OlpdzcXOLB(62)M22%vPCLS^
z=r{s#V0wg?2ww9GU&DW{i&9`(fGA14gOIVpJPpJD*Q7BiNCyDtBe6^(62?hceyB<@
zEN)`7+Y*+?vgO_YhMG^VI=InTOU(ACDPLw6fUlAy$sebD!AgK~G}F9l%IE3>z?cSb
zy-G|-2qPbko|M>FfPqqg>01D78qu7nq*zZ6V;r;a2cSJ5$w6lT`ayv4&q;E$h$P30
z0q~yzt|XG3z(H5#&CEdZW(;UHc?B4z;0O*lwh$-`3};|uEilnR(|-{L5=*g*Ry(
zJp~elnYpdq>^b&M&MvNRy}iO~rMJ&Jt2hDc0)yV=21i8lHf=_QkKPs&D~uCuPm=EX
zI5|c3N#^c7S=l*zbMp@#I(+2l7sm>Uicgh%ReJi&+4J9DsJM8kvg(Jc*J|tPRo8Fa
zyxV-QrM0bH-O=6i=<$q~%g#rGmWRuGNri+1eQK(d$N;l}j
zD9Hxl3@UBGauaL6jdWtC%|ee1)0zGUPL|i0E%FT4&JswP%xxW4bUWz`(u~UfoiN3J
zQua#Nl&%i2z%g`qI0M))F_K;&4JP--{0GxeQ4
z?pK-nI!gDi=9Q%=c}?v26CH&$BZ((_<^}ggUM|t~w>-@%~M^JBrK1!!n2XiRqVGQoWLUa(;W!HA8=t)0XJcT-@R=
zeHOLhP>@LGqWP?b+MrOqvurl|Jo6gG*J72L`R$ptcI+5s7Smz1d^BJzX#Ao)j!&u6
z3P03szLw|yu=FZ3<91o!0~Z}rk#5_bl99^$TBEe~%Cl+Ej_P~s(^(bGZp^^OUGpMB
zwGBs0N_H3IJ$cfiQj@@qgfC~9tV)xW?Wwkw*LadZurtzEH?46=bsaCLW~R8Ss_kWu
z8&g9{YR=9bcMB<$B?$BHeb8?cm7V`UL@d!>=Q$=6hFGU-9KhEVigJw|C)MfqBg_on
W!!4g%o#xMm#cmIqP)%`0#-P;O{#bZ0u8#ki`W&=h9f2?-;9_U5KDlIGK|Jbn)RyDwmJqeY}fZVjez~Pt`HQP
zDwX+T_86D4ZFPVRkR66DlG>ev=d@3ir$7|6yPniu2GX)+)<84>V;FNM=Doh}f_MVD
z(QT7Axch;`OO!dU@HL0rI?D3zkeR_}5M{fE@LqAdQ2l46llxKy&z5%BPUwdY2C)5r
zYYT2xaP@fDBP8XU_3D{_`j207*fxao?ZCbO000SaNLh0L02Uv?^h)7F2)#eTHem1pH-)na?Win=bTb{Twj)DT~}MXuIsWa$Ms*y
zOaFWNwrvM0CmljK41=xh`yN7gTo1#r>pG>>eWjGTUaw&o?&`o;GL9o5B+D|b_1C%9
zI!#kT$TUs1-CL}>F{Z9-j4@+O2qC4EQVJm$V;JMQu6Jo;%;oWYZ`-!2s(GGo6W{mq
zJa>8)0Csc$fY!Qcn$I5&f*^__&+}YpC;caRzaMeV%d&LbFNz|L<8SB)p(IHhb%fA^
j_S~0w)+_eX|EvB1=A890AL+&`00000NkvXXu0mjf`{)f#
diff --git a/src/main/res/layout/note_list.xml b/src/main/res/layout/note_list.xml
index 636abff..1ad1008 100644
--- a/src/main/res/layout/note_list.xml
+++ b/src/main/res/layout/note_list.xml
@@ -15,175 +15,221 @@
limitations under the License.
-->
-
-
+
+ android:layout_height="match_parent">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
+
+ android:fontFamily="sans-serif-medium" />
-
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/src/main/res/layout/sidebar_item.xml b/src/main/res/layout/sidebar_item.xml
new file mode 100644
index 0000000..f6b2d8d
--- /dev/null
+++ b/src/main/res/layout/sidebar_item.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/layout/sidebar_layout.xml b/src/main/res/layout/sidebar_layout.xml
new file mode 100644
index 0000000..80d181b
--- /dev/null
+++ b/src/main/res/layout/sidebar_layout.xml
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml
index 550310d..d967f9c 100644
--- a/src/main/res/values/colors.xml
+++ b/src/main/res/values/colors.xml
@@ -50,4 +50,6 @@
#FF9800
#E0E0E0
#BDBDBD
+ #E7E0EC
+ #49454F
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index e084a43..23739b7 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -242,6 +242,7 @@
Translation failed. Please check your network connection and try again.
Failed to load image
Extracted Content
+ 正在提取内容...
Insert
Cancel
Content inserted successfully
--
2.34.1