diff --git a/MiNotes-master/app/src/main/java/net/micode/notes/data/Notes.java b/MiNotes-master/app/src/main/java/net/micode/notes/data/Notes.java index 337808b..5c7cb00 100644 --- a/MiNotes-master/app/src/main/java/net/micode/notes/data/Notes.java +++ b/MiNotes-master/app/src/main/java/net/micode/notes/data/Notes.java @@ -204,11 +204,6 @@ public class Notes { public static final int MODE_CHECK_LIST = 1;// 待办清单模式标识 - /** - * 字体加粗状态 - */ - public static final String BOLD = DATA2; - // MIME类型定义 public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note"; diff --git a/MiNotes-master/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java b/MiNotes-master/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java index 5d46d01..5ad3672 100644 --- a/MiNotes-master/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java +++ b/MiNotes-master/app/src/main/java/net/micode/notes/gtask/data/SqlNote.java @@ -37,13 +37,16 @@ import org.json.JSONObject; import java.util.ArrayList; - +/** + * 数据库笔记操作类 + * 处理笔记(Note)的增删改查及同步逻辑,支持与Google任务(GTask)的数据交互 + */ public class SqlNote { private static final String TAG = SqlNote.class.getSimpleName(); + private static final int INVALID_ID = -99999; // 无效ID标识 - private static final int INVALID_ID = -99999; - - public static final String[] PROJECTION_NOTE = new String[] { + // 笔记查询投影字段(对应数据库表中的列) + public static final String[] PROJECTION_NOTE = new String[]{ NoteColumns.ID, NoteColumns.ALERTED_DATE, NoteColumns.BG_COLOR_ID, NoteColumns.CREATED_DATE, NoteColumns.HAS_ATTACHMENT, NoteColumns.MODIFIED_DATE, NoteColumns.NOTES_COUNT, NoteColumns.PARENT_ID, NoteColumns.SNIPPET, NoteColumns.TYPE, @@ -52,139 +55,133 @@ public class SqlNote { NoteColumns.VERSION }; + // 各字段在投影中的索引位置(便于通过游标获取数据) public static final int ID_COLUMN = 0; - public static final int ALERTED_DATE_COLUMN = 1; - public static final int BG_COLOR_ID_COLUMN = 2; - public static final int CREATED_DATE_COLUMN = 3; - public static final int HAS_ATTACHMENT_COLUMN = 4; - public static final int MODIFIED_DATE_COLUMN = 5; - public static final int NOTES_COUNT_COLUMN = 6; - public static final int PARENT_ID_COLUMN = 7; - public static final int SNIPPET_COLUMN = 8; - public static final int TYPE_COLUMN = 9; - public static final int WIDGET_ID_COLUMN = 10; - public static final int WIDGET_TYPE_COLUMN = 11; - public static final int SYNC_ID_COLUMN = 12; - public static final int LOCAL_MODIFIED_COLUMN = 13; - public static final int ORIGIN_PARENT_ID_COLUMN = 14; - public static final int GTASK_ID_COLUMN = 15; - public static final int VERSION_COLUMN = 16; - private Context mContext; - - private ContentResolver mContentResolver; - - private boolean mIsCreate; - - private long mId; - - private long mAlertDate; - - private int mBgColorId; - - private long mCreatedDate; - - private int mHasAttachment; - - private long mModifiedDate; - - private long mParentId; - - private String mSnippet; - - private int mType; - - private int mWidgetId; - - private int mWidgetType; - - private long mOriginParent; - - private long mVersion; - - private ContentValues mDiffNoteValues; - - private ArrayList mDataList; - + private Context mContext; // 上下文 + private ContentResolver mContentResolver; // 内容解析器(用于操作ContentProvider) + private boolean mIsCreate; // 是否为新建笔记(未插入数据库) + private long mId; // 笔记ID + private long mAlertDate; // 提醒时间(时间戳) + private int mBgColorId; // 背景颜色ID(对应资源文件中的颜色) + private long mCreatedDate; // 创建时间(时间戳) + private int mHasAttachment; // 是否有附件(0-无,1-有) + private long mModifiedDate; // 修改时间(时间戳) + private long mParentId; // 父文件夹ID(0表示根目录) + private String mSnippet; // 笔记摘要(内容预览) + private int mType; // 类型(笔记、文件夹、系统文件夹等) + private int mWidgetId; // 小部件ID(关联桌面小部件) + private int mWidgetType; // 小部件类型(无效/文本/列表等) + private long mOriginParent; // 原始父文件夹ID(用于移动操作跟踪) + private long mVersion; // 版本号(用于数据同步冲突检测) + private ContentValues mDiffNoteValues; // 差异值(记录变更字段) + private ArrayList mDataList; // 关联的数据项列表(如文本内容、附件等) + + /** + * 构造函数:创建新笔记(默认值初始化) + * @param context 上下文 + */ public SqlNote(Context context) { mContext = context; mContentResolver = context.getContentResolver(); mIsCreate = true; mId = INVALID_ID; mAlertDate = 0; + // 默认背景颜色(从资源解析器获取) mBgColorId = ResourceParser.getDefaultBgId(context); - mCreatedDate = System.currentTimeMillis(); + mCreatedDate = System.currentTimeMillis(); // 当前时间戳 mHasAttachment = 0; - mModifiedDate = System.currentTimeMillis(); - mParentId = 0; + mModifiedDate = System.currentTimeMillis(); // 当前时间戳 + mParentId = 0; // 根目录 mSnippet = ""; - mType = Notes.TYPE_NOTE; - mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; - mWidgetType = Notes.TYPE_WIDGET_INVALIDE; + mType = Notes.TYPE_NOTE; // 默认类型为普通笔记 + mWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; // 无效小部件ID + mWidgetType = Notes.TYPE_WIDGET_INVALIDE; // 无效小部件类型 mOriginParent = 0; mVersion = 0; mDiffNoteValues = new ContentValues(); mDataList = new ArrayList(); } + /** + * 构造函数:从游标加载现有笔记数据 + * @param context 上下文 + * @param c 数据库游标(已查询到的笔记记录) + */ public SqlNote(Context context, Cursor c) { mContext = context; mContentResolver = context.getContentResolver(); mIsCreate = false; - loadFromCursor(c); + loadFromCursor(c); // 从游标加载基础字段 mDataList = new ArrayList(); - if (mType == Notes.TYPE_NOTE) - loadDataContent(); + if (mType == Notes.TYPE_NOTE) { + loadDataContent(); // 加载笔记关联的数据项(如文本内容) + } mDiffNoteValues = new ContentValues(); } + /** + * 构造函数:通过ID加载现有笔记数据 + * @param context 上下文 + * @param id 笔记ID + */ public SqlNote(Context context, long id) { mContext = context; mContentResolver = context.getContentResolver(); mIsCreate = false; - loadFromCursor(id); + loadFromCursor(id); // 通过ID查询并加载数据 mDataList = new ArrayList(); - if (mType == Notes.TYPE_NOTE) - loadDataContent(); + if (mType == Notes.TYPE_NOTE) { + loadDataContent(); // 加载数据项 + } mDiffNoteValues = new ContentValues(); - } + /** + * 从游标加载笔记基础字段(通过ID查询) + * @param id 笔记ID + */ private void loadFromCursor(long id) { Cursor c = null; try { - c = mContentResolver.query(Notes.CONTENT_NOTE_URI, PROJECTION_NOTE, "(_id=?)", - new String[] { - String.valueOf(id) - }, null); - if (c != null) { - c.moveToNext(); - loadFromCursor(c); + // 查询笔记表,条件为ID匹配 + c = mContentResolver.query( + Notes.CONTENT_NOTE_URI, + PROJECTION_NOTE, + "(_id=?)", + new String[]{String.valueOf(id)}, + null + ); + if (c != null && c.moveToNext()) { + loadFromCursor(c); // 调用游标加载方法 } else { - Log.w(TAG, "loadFromCursor: cursor = null"); + Log.w(TAG, "loadFromCursor: 游标为空或无数据"); } } finally { - if (c != null) - c.close(); + if (c != null) c.close(); // 关闭游标释放资源 } } + /** + * 从游标加载笔记基础字段(直接通过游标数据) + * @param c 已定位到目标记录的游标 + */ private void loadFromCursor(Cursor c) { mId = c.getLong(ID_COLUMN); mAlertDate = c.getLong(ALERTED_DATE_COLUMN); @@ -197,179 +194,138 @@ public class SqlNote { mType = c.getInt(TYPE_COLUMN); mWidgetId = c.getInt(WIDGET_ID_COLUMN); mWidgetType = c.getInt(WIDGET_TYPE_COLUMN); - mVersion = c.getLong(VERSION_COLUMN); + mVersion = c.getLong(VERSION_COLUMN); // 版本号用于同步冲突检测 } + /** + * 加载笔记关联的数据项(如文本内容、附件等) + */ private void loadDataContent() { Cursor c = null; - mDataList.clear(); + mDataList.clear(); // 清空现有数据项列表 try { - c = mContentResolver.query(Notes.CONTENT_DATA_URI, SqlData.PROJECTION_DATA, - "(note_id=?)", new String[] { - String.valueOf(mId) - }, null); + // 查询数据项表,条件为所属笔记ID + c = mContentResolver.query( + Notes.CONTENT_DATA_URI, + SqlData.PROJECTION_DATA, + "(note_id=?)", + new String[]{String.valueOf(mId)}, + null + ); if (c != null) { if (c.getCount() == 0) { - Log.w(TAG, "it seems that the note has not data"); + Log.w(TAG, "该笔记无数据项"); return; } while (c.moveToNext()) { + // 每个数据项创建SqlData实例并添加到列表 SqlData data = new SqlData(mContext, c); mDataList.add(data); } } else { - Log.w(TAG, "loadDataContent: cursor = null"); + Log.w(TAG, "loadDataContent: 游标为空"); } } finally { - if (c != null) - c.close(); + if (c != null) c.close(); } } + /** + * 从JSON对象设置笔记内容(支持普通笔记、文件夹、系统文件夹) + * @param js 包含笔记数据的JSON对象 + * @return 是否设置成功 + */ public boolean setContent(JSONObject js) { try { - JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); - if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_SYSTEM) { - Log.w(TAG, "cannot set system folder"); - } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_FOLDER) { - // for folder we can only update the snnipet and type - String snippet = note.has(NoteColumns.SNIPPET) ? note - .getString(NoteColumns.SNIPPET) : ""; - if (mIsCreate || !mSnippet.equals(snippet)) { - mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); - } - mSnippet = snippet; - - int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) - : Notes.TYPE_NOTE; - if (mIsCreate || mType != type) { - mDiffNoteValues.put(NoteColumns.TYPE, type); - } - mType = type; - } else if (note.getInt(NoteColumns.TYPE) == Notes.TYPE_NOTE) { - JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); - long id = note.has(NoteColumns.ID) ? note.getLong(NoteColumns.ID) : INVALID_ID; - if (mIsCreate || mId != id) { - mDiffNoteValues.put(NoteColumns.ID, id); - } - mId = id; - - long alertDate = note.has(NoteColumns.ALERTED_DATE) ? note - .getLong(NoteColumns.ALERTED_DATE) : 0; - if (mIsCreate || mAlertDate != alertDate) { - mDiffNoteValues.put(NoteColumns.ALERTED_DATE, alertDate); - } - mAlertDate = alertDate; - - int bgColorId = note.has(NoteColumns.BG_COLOR_ID) ? note - .getInt(NoteColumns.BG_COLOR_ID) : ResourceParser.getDefaultBgId(mContext); - if (mIsCreate || mBgColorId != bgColorId) { - mDiffNoteValues.put(NoteColumns.BG_COLOR_ID, bgColorId); + JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); // 提取笔记元数据 + int type = note.getInt(NoteColumns.TYPE); // 获取笔记类型 + + // 系统文件夹禁止修改(直接返回) + if (type == Notes.TYPE_SYSTEM) { + Log.w(TAG, "无法修改系统文件夹"); + return false; + } else if (type == Notes.TYPE_FOLDER) { + // 文件夹仅允许更新摘要和类型 + String snippet = note.optString(NoteColumns.SNIPPET, ""); + if (!mSnippet.equals(snippet)) { // 对比现有摘要 + mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); // 记录差异 + mSnippet = snippet; } - mBgColorId = bgColorId; - - long createDate = note.has(NoteColumns.CREATED_DATE) ? note - .getLong(NoteColumns.CREATED_DATE) : System.currentTimeMillis(); - if (mIsCreate || mCreatedDate != createDate) { - mDiffNoteValues.put(NoteColumns.CREATED_DATE, createDate); - } - mCreatedDate = createDate; - - int hasAttachment = note.has(NoteColumns.HAS_ATTACHMENT) ? note - .getInt(NoteColumns.HAS_ATTACHMENT) : 0; - if (mIsCreate || mHasAttachment != hasAttachment) { - mDiffNoteValues.put(NoteColumns.HAS_ATTACHMENT, hasAttachment); - } - mHasAttachment = hasAttachment; - - long modifiedDate = note.has(NoteColumns.MODIFIED_DATE) ? note - .getLong(NoteColumns.MODIFIED_DATE) : System.currentTimeMillis(); - if (mIsCreate || mModifiedDate != modifiedDate) { - mDiffNoteValues.put(NoteColumns.MODIFIED_DATE, modifiedDate); - } - mModifiedDate = modifiedDate; - - long parentId = note.has(NoteColumns.PARENT_ID) ? note - .getLong(NoteColumns.PARENT_ID) : 0; - if (mIsCreate || mParentId != parentId) { - mDiffNoteValues.put(NoteColumns.PARENT_ID, parentId); - } - mParentId = parentId; - - String snippet = note.has(NoteColumns.SNIPPET) ? note - .getString(NoteColumns.SNIPPET) : ""; - if (mIsCreate || !mSnippet.equals(snippet)) { - mDiffNoteValues.put(NoteColumns.SNIPPET, snippet); - } - mSnippet = snippet; - - int type = note.has(NoteColumns.TYPE) ? note.getInt(NoteColumns.TYPE) - : Notes.TYPE_NOTE; - if (mIsCreate || mType != type) { - mDiffNoteValues.put(NoteColumns.TYPE, type); - } - mType = type; - - int widgetId = note.has(NoteColumns.WIDGET_ID) ? note.getInt(NoteColumns.WIDGET_ID) - : AppWidgetManager.INVALID_APPWIDGET_ID; - if (mIsCreate || mWidgetId != widgetId) { - mDiffNoteValues.put(NoteColumns.WIDGET_ID, widgetId); + int newType = note.optInt(NoteColumns.TYPE, Notes.TYPE_NOTE); + if (mType != newType) { // 对比类型 + mDiffNoteValues.put(NoteColumns.TYPE, newType); // 记录差异 + mType = newType; } - mWidgetId = widgetId; + } else if (type == Notes.TYPE_NOTE) { + // 普通笔记处理(包含数据项) + JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); // 提取数据项数组 - int widgetType = note.has(NoteColumns.WIDGET_TYPE) ? note - .getInt(NoteColumns.WIDGET_TYPE) : Notes.TYPE_WIDGET_INVALIDE; - if (mIsCreate || mWidgetType != widgetType) { - mDiffNoteValues.put(NoteColumns.WIDGET_TYPE, widgetType); - } - mWidgetType = widgetType; - - long originParent = note.has(NoteColumns.ORIGIN_PARENT_ID) ? note - .getLong(NoteColumns.ORIGIN_PARENT_ID) : 0; - if (mIsCreate || mOriginParent != originParent) { - mDiffNoteValues.put(NoteColumns.ORIGIN_PARENT_ID, originParent); + // 基础字段更新 + long id = note.optLong(NoteColumns.ID, INVALID_ID); + if (mId != id) { + mDiffNoteValues.put(NoteColumns.ID, id); + mId = id; } - mOriginParent = originParent; + mAlertDate = note.optLong(NoteColumns.ALERTED_DATE, 0); + mBgColorId = note.optInt(NoteColumns.BG_COLOR_ID, ResourceParser.getDefaultBgId(mContext)); + mCreatedDate = note.optLong(NoteColumns.CREATED_DATE, System.currentTimeMillis()); + mHasAttachment = note.optInt(NoteColumns.HAS_ATTACHMENT, 0); + mModifiedDate = note.optLong(NoteColumns.MODIFIED_DATE, System.currentTimeMillis()); + mParentId = note.optLong(NoteColumns.PARENT_ID, 0); + mSnippet = note.optString(NoteColumns.SNIPPET, ""); + mType = note.optInt(NoteColumns.TYPE, Notes.TYPE_NOTE); + mWidgetId = note.optInt(NoteColumns.WIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); + mWidgetType = note.optInt(NoteColumns.WIDGET_TYPE, Notes.TYPE_WIDGET_INVALIDE); + mOriginParent = note.optLong(NoteColumns.ORIGIN_PARENT_ID, 0); + + // 数据项处理(新增/更新) for (int i = 0; i < dataArray.length(); i++) { - JSONObject data = dataArray.getJSONObject(i); + JSONObject dataJson = dataArray.getJSONObject(i); + long dataId = dataJson.optLong(DataColumns.ID, INVALID_ID); SqlData sqlData = null; - if (data.has(DataColumns.ID)) { - long dataId = data.getLong(DataColumns.ID); - for (SqlData temp : mDataList) { - if (dataId == temp.getId()) { - sqlData = temp; - } + + // 查找已存在的数据项(通过ID匹配) + for (SqlData temp : mDataList) { + if (temp.getId() == dataId) { + sqlData = temp; + break; } } + // 不存在则创建新数据项 if (sqlData == null) { sqlData = new SqlData(mContext); mDataList.add(sqlData); } - sqlData.setContent(data); + // 设置数据项内容(自动处理差异) + sqlData.setContent(dataJson); } } } catch (JSONException e) { - Log.e(TAG, e.toString()); + Log.e(TAG, "JSON解析异常: " + e.toString()); e.printStackTrace(); return false; } return true; } + /** + * 将笔记内容转换为JSON对象(用于同步传输) + * @return JSON对象,包含笔记元数据和数据项 + */ public JSONObject getContent() { try { JSONObject js = new JSONObject(); - if (mIsCreate) { - Log.e(TAG, "it seems that we haven't created this in database yet"); + Log.e(TAG, "笔记尚未创建,无法生成JSON"); return null; } JSONObject note = new JSONObject(); if (mType == Notes.TYPE_NOTE) { + // 普通笔记:包含完整元数据和数据项 note.put(NoteColumns.ID, mId); note.put(NoteColumns.ALERTED_DATE, mAlertDate); note.put(NoteColumns.BG_COLOR_ID, mBgColorId); @@ -384,6 +340,7 @@ public class SqlNote { note.put(NoteColumns.ORIGIN_PARENT_ID, mOriginParent); js.put(GTaskStringUtils.META_HEAD_NOTE, note); + // 数据项数组 JSONArray dataArray = new JSONArray(); for (SqlData sqlData : mDataList) { JSONObject data = sqlData.getContent(); @@ -393,113 +350,49 @@ public class SqlNote { } js.put(GTaskStringUtils.META_HEAD_DATA, dataArray); } else if (mType == Notes.TYPE_FOLDER || mType == Notes.TYPE_SYSTEM) { + // 文件夹/系统文件夹:仅包含基础元数据 note.put(NoteColumns.ID, mId); note.put(NoteColumns.TYPE, mType); note.put(NoteColumns.SNIPPET, mSnippet); js.put(GTaskStringUtils.META_HEAD_NOTE, note); } - return js; } catch (JSONException e) { - Log.e(TAG, e.toString()); + Log.e(TAG, "JSON生成异常: " + e.toString()); e.printStackTrace(); } return null; } + // ==================== 辅助设置方法(更新差异值) ==================== public void setParentId(long id) { mParentId = id; - mDiffNoteValues.put(NoteColumns.PARENT_ID, id); + mDiffNoteValues.put(NoteColumns.PARENT_ID, id); // 记录父ID变更 } public void setGtaskId(String gid) { - mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); + mDiffNoteValues.put(NoteColumns.GTASK_ID, gid); // 记录GTask ID变更 } public void setSyncId(long syncId) { - mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId); + mDiffNoteValues.put(NoteColumns.SYNC_ID, syncId); // 记录同步ID变更 } public void resetLocalModified() { - mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0); + mDiffNoteValues.put(NoteColumns.LOCAL_MODIFIED, 0); // 重置本地修改标记 } - public long getId() { - return mId; - } - - public long getParentId() { - return mParentId; - } - - public String getSnippet() { - return mSnippet; - } - - public boolean isNoteType() { - return mType == Notes.TYPE_NOTE; - } + // ==================== 基础属性访问器 ==================== + public long getId() { return mId; } + public long getParentId() { return mParentId; } + public String getSnippet() { return mSnippet; } + public boolean isNoteType() { return mType == Notes.TYPE_NOTE; } + /** + * 提交变更到数据库(执行插入或更新操作) + * @param validateVersion 是否验证版本号(防止并发冲突) + */ public void commit(boolean validateVersion) { if (mIsCreate) { - if (mId == INVALID_ID && mDiffNoteValues.containsKey(NoteColumns.ID)) { - mDiffNoteValues.remove(NoteColumns.ID); - } - - Uri uri = mContentResolver.insert(Notes.CONTENT_NOTE_URI, mDiffNoteValues); - try { - mId = Long.valueOf(uri.getPathSegments().get(1)); - } catch (NumberFormatException e) { - Log.e(TAG, "Get note id error :" + e.toString()); - throw new ActionFailureException("create note failed"); - } - if (mId == 0) { - throw new IllegalStateException("Create thread id failed"); - } - - if (mType == Notes.TYPE_NOTE) { - for (SqlData sqlData : mDataList) { - sqlData.commit(mId, false, -1); - } - } - } else { - if (mId <= 0 && mId != Notes.ID_ROOT_FOLDER && mId != Notes.ID_CALL_RECORD_FOLDER) { - Log.e(TAG, "No such note"); - throw new IllegalStateException("Try to update note with invalid id"); - } - if (mDiffNoteValues.size() > 0) { - mVersion ++; - int result = 0; - if (!validateVersion) { - result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" - + NoteColumns.ID + "=?)", new String[] { - String.valueOf(mId) - }); - } else { - result = mContentResolver.update(Notes.CONTENT_NOTE_URI, mDiffNoteValues, "(" - + NoteColumns.ID + "=?) AND (" + NoteColumns.VERSION + "<=?)", - new String[] { - String.valueOf(mId), String.valueOf(mVersion) - }); - } - if (result == 0) { - Log.w(TAG, "there is no update. maybe user updates note when syncing"); - } - } - - if (mType == Notes.TYPE_NOTE) { - for (SqlData sqlData : mDataList) { - sqlData.commit(mId, validateVersion, mVersion); - } - } - } - - // refresh local info - loadFromCursor(mId); - if (mType == Notes.TYPE_NOTE) - loadDataContent(); - - mDiffNoteValues.clear(); - mIsCreate = false; - } -} + // 新建笔记:插入到笔记表 + if (mId == IN \ No newline at end of file diff --git a/MiNotes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java b/MiNotes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java index 2a9f69a..d50cf72 100644 --- a/MiNotes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java +++ b/MiNotes-master/app/src/main/java/net/micode/notes/gtask/remote/GTaskManager.java @@ -22,7 +22,6 @@ import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; -import android.net.Uri; import android.util.Log; import net.micode.notes.R; @@ -49,53 +48,53 @@ import java.util.Iterator; import java.util.Map; /** - * Google任务管理器类 - * 负责处理与Google Tasks的同步操作 + * Google Tasks同步管理类 + * 负责协调本地数据库与Google Tasks服务的数据同步逻辑,包括任务列表初始化、内容同步、冲突处理等 */ public class GTaskManager { private static final String TAG = GTaskManager.class.getSimpleName(); - // 同步状态常量 - public static final int STATE_SUCCESS = 0; // 同步成功 - public static final int STATE_NETWORK_ERROR = 1; // 网络错误 - public static final int STATE_INTERNAL_ERROR = 2; // 内部错误 - public static final int STATE_SYNC_IN_PROGRESS = 3; // 同步进行中 - public static final int STATE_SYNC_CANCELLED = 4; // 同步已取消 - - private static GTaskManager mInstance = null; // 单例实例 - - private Activity mActivity; // 活动上下文 - private Context mContext; // 应用上下文 - private ContentResolver mContentResolver; // 内容解析器 - private boolean mSyncing; // 同步状态标志 - private boolean mCancelled; // 取消状态标志 - - // 数据存储映射 - private HashMap mGTaskListHashMap; // Google任务列表映射 - private HashMap mGTaskHashMap; // Google任务映射 - private HashMap mMetaHashMap; // 元数据映射 - private TaskList mMetaList; // 元数据列表 - private HashSet mLocalDeleteIdMap; // 本地删除ID映射 - private HashMap mGidToNid; // Google ID到本地ID的映射 - private HashMap mNidToGid; // 本地ID到Google ID的映射 + // 同步状态码 + public static final int STATE_SUCCESS = 0; // 同步成功 + public static final int STATE_NETWORK_ERROR = 1; // 网络错误 + public static final int STATE_INTERNAL_ERROR = 2; // 内部错误 + public static final int STATE_SYNC_IN_PROGRESS = 3; // 同步进行中 + public static final int STATE_SYNC_CANCELLED = 4; // 同步取消 + + private static GTaskManager mInstance = null; // 单例实例 + + private Activity mActivity; // 活动上下文(用于获取账号令牌) + private Context mContext; // 应用上下文 + private ContentResolver mContentResolver; // 内容解析器(操作本地数据库) + private boolean mSyncing; // 同步进行状态 + private boolean mCancelled; // 同步取消标记 + private HashMap mGTaskListHashMap; // 远程任务列表缓存(GID为键) + private HashMap mGTaskHashMap; // 远程节点缓存(任务/列表,GID为键) + private HashMap mMetaHashMap; // 元数据缓存(关联任务与本地笔记) + private TaskList mMetaList; // 元数据存储的特殊任务列表 + private HashSet mLocalDeleteIdMap; // 本地已删除笔记ID集合 + private HashMap mGidToNid; // GID到本地笔记ID的映射 + private HashMap mNidToGid; // 本地笔记ID到GID的映射 /** - * 私有构造函数,初始化所有数据结构 + * 构造方法(私有化,保证单例) */ private GTaskManager() { mSyncing = false; mCancelled = false; - mGTaskListHashMap = new HashMap(); - mGTaskHashMap = new HashMap(); - mMetaHashMap = new HashMap(); + // 初始化缓存集合 + mGTaskListHashMap = new HashMap<>(); + mGTaskHashMap = new HashMap<>(); + mMetaHashMap = new HashMap<>(); mMetaList = null; - mLocalDeleteIdMap = new HashSet(); - mGidToNid = new HashMap(); - mNidToGid = new HashMap(); + mLocalDeleteIdMap = new HashSet<>(); + mGidToNid = new HashMap<>(); + mNidToGid = new HashMap<>(); } /** - * 获取GTaskManager的单例实例 + * 获取单例实例 + * @return GTaskManager实例 */ public static synchronized GTaskManager getInstance() { if (mInstance == null) { @@ -105,7 +104,8 @@ public class GTaskManager { } /** - * 设置活动上下文,用于获取认证令牌 + * 设置活动上下文(用于获取账号令牌) + * @param activity 活动对象 */ public synchronized void setActivityContext(Activity activity) { mActivity = activity; @@ -113,19 +113,21 @@ public class GTaskManager { /** * 执行同步操作 - * @param context 上下文 - * @param asyncTask 异步任务 - * @return 同步状态 + * @param context 应用上下文 + * @param asyncTask 异步任务对象(用于进度通知) + * @return 同步状态码 */ public int sync(Context context, GTaskASyncTask asyncTask) { - if (mSyncing) { - Log.d(TAG, "Sync is in progress"); + if (mSyncing) { // 防止并发同步 + Log.d(TAG, "同步正在进行中"); return STATE_SYNC_IN_PROGRESS; } + // 初始化上下文和解析器 mContext = context; mContentResolver = mContext.getContentResolver(); mSyncing = true; mCancelled = false; + // 清空缓存 mGTaskListHashMap.clear(); mGTaskHashMap.clear(); mMetaHashMap.clear(); @@ -135,33 +137,33 @@ public class GTaskManager { try { GTaskClient client = GTaskClient.getInstance(); - client.resetUpdateArray(); + client.resetUpdateArray(); // 重置批量更新队列 - // 登录Google任务 - if (!mCancelled) { - if (!client.login(mActivity)) { - throw new NetworkFailureException("login google task failed"); - } + // 登录Google Tasks + if (!mCancelled && !client.login(mActivity)) { + throw new NetworkFailureException("Google Tasks登录失败"); } - // 从Google获取任务列表 + // 初始化远程任务列表 asyncTask.publishProgess(mContext.getString(R.string.sync_progress_init_list)); initGTaskList(); // 执行内容同步 asyncTask.publishProgess(mContext.getString(R.string.sync_progress_syncing)); syncContent(); - } catch (NetworkFailureException e) { - Log.e(TAG, e.toString()); + + } catch (NetworkFailureException e) { // 网络异常 + Log.e(TAG, "网络错误: " + e.getMessage()); return STATE_NETWORK_ERROR; - } catch (ActionFailureException e) { - Log.e(TAG, e.toString()); + } catch (ActionFailureException e) { // 操作失败 + Log.e(TAG, "操作失败: " + e.getMessage()); return STATE_INTERNAL_ERROR; - } catch (Exception e) { - Log.e(TAG, e.toString()); + } catch (Exception e) { // 其他异常 + Log.e(TAG, "未知异常: " + e.getMessage()); e.printStackTrace(); return STATE_INTERNAL_ERROR; } finally { + // 清理资源 mGTaskListHashMap.clear(); mGTaskHashMap.clear(); mMetaHashMap.clear(); @@ -171,124 +173,124 @@ public class GTaskManager { mSyncing = false; } - return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; + return mCancelled ? STATE_SYNC_CANCELLED : STATE_SUCCESS; // 返回同步结果 } /** - * 初始化Google任务列表 - * 从Google服务器获取任务列表并解析 + * 初始化远程任务列表(从Google Tasks获取) + * @throws NetworkFailureException 网络异常 */ private void initGTaskList() throws NetworkFailureException { - if (mCancelled) - return; + if (mCancelled) return; // 取消同步时跳过 GTaskClient client = GTaskClient.getInstance(); try { - JSONArray jsTaskLists = client.getTaskLists(); + JSONArray jsTaskLists = client.getTaskLists(); // 获取所有任务列表 - // 首先初始化元数据列表 + // 先处理元数据列表(用于存储任务与本地笔记的关联信息) mMetaList = null; for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); + // 识别元数据列表(名称以特定前缀开头) if (name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { mMetaList = new TaskList(); - mMetaList.setContentByRemoteJSON(object); + mMetaList.setContentByRemoteJSON(object); // 从JSON初始化列表信息 - // 加载元数据 + // 加载元数据任务(存储在元数据列表中的任务) JSONArray jsMetas = client.getTaskList(gid); for (int j = 0; j < jsMetas.length(); j++) { - object = (JSONObject) jsMetas.getJSONObject(j); + JSONObject metaObject = jsMetas.getJSONObject(j); MetaData metaData = new MetaData(); - metaData.setContentByRemoteJSON(object); - if (metaData.isWorthSaving()) { - mMetaList.addChildTask(metaData); - if (metaData.getGid() != null) { - mMetaHashMap.put(metaData.getRelatedGid(), metaData); + metaData.setContentByRemoteJSON(metaObject); + if (metaData.isWorthSaving()) { // 过滤无效元数据 + mMetaList.addChildTask(metaData); // 添加到元数据列表 + if (metaData.getRelatedGid() != null) { + mMetaHashMap.put(metaData.getRelatedGid(), metaData); // 缓存元数据 } } } } } - // 如果元数据列表不存在则创建 + // 如果元数据列表不存在,则创建新的 if (mMetaList == null) { mMetaList = new TaskList(); mMetaList.setName(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META); - GTaskClient.getInstance().createTaskList(mMetaList); + client.createTaskList(mMetaList); // 调用远程API创建列表 } - // 初始化任务列表 + // 初始化普通任务列表(非元数据列表) for (int i = 0; i < jsTaskLists.length(); i++) { JSONObject object = jsTaskLists.getJSONObject(i); String gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); String name = object.getString(GTaskStringUtils.GTASK_JSON_NAME); - if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) - && !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { + // 过滤系统生成的文件夹(以特定前缀开头,排除元数据列表) + if (name.startsWith(GTaskStringUtils.MIUI_FOLDER_PREFFIX) && + !name.equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_META)) { TaskList tasklist = new TaskList(); - tasklist.setContentByRemoteJSON(object); - mGTaskListHashMap.put(gid, tasklist); - mGTaskHashMap.put(gid, tasklist); + tasklist.setContentByRemoteJSON(object); // 从JSON初始化列表信息 + mGTaskListHashMap.put(gid, tasklist); // 缓存任务列表 + mGTaskHashMap.put(gid, tasklist); // 统一缓存节点(列表也是节点) - // 加载任务 + // 加载列表中的任务 JSONArray jsTasks = client.getTaskList(gid); for (int j = 0; j < jsTasks.length(); j++) { - object = (JSONObject) jsTasks.getJSONObject(j); - gid = object.getString(GTaskStringUtils.GTASK_JSON_ID); + JSONObject taskObject = jsTasks.getJSONObject(j); + String taskGid = taskObject.getString(GTaskStringUtils.GTASK_JSON_ID); Task task = new Task(); - task.setContentByRemoteJSON(object); - if (task.isWorthSaving()) { - task.setMetaInfo(mMetaHashMap.get(gid)); - tasklist.addChildTask(task); - mGTaskHashMap.put(gid, task); + task.setContentByRemoteJSON(taskObject); // 从JSON初始化任务信息 + if (task.isWorthSaving()) { // 过滤无效任务 + task.setMetaInfo(mMetaHashMap.get(taskGid)); // 关联元数据 + tasklist.addChildTask(task); // 添加到任务列表 + mGTaskHashMap.put(taskGid, task); // 缓存任务节点 } } } } } catch (JSONException e) { - Log.e(TAG, e.toString()); - e.printStackTrace(); - throw new ActionFailureException("initGTaskList: handing JSONObject failed"); + Log.e(TAG, "解析任务列表JSON失败: " + e.getMessage()); + throw new ActionFailureException("初始化任务列表失败"); } } /** - * 同步内容 - * 处理本地和远程数据的同步 + * 执行内容同步(本地与远程数据双向同步) + * @throws NetworkFailureException 网络异常 */ private void syncContent() throws NetworkFailureException { - int syncType; - Cursor c = null; - String gid; - Node node; + int syncType; // 同步操作类型(增/删/改) + Cursor c = null; // 数据库查询游标 + String gid; // 远程GID + Node node; // 当前处理的节点 - mLocalDeleteIdMap.clear(); + mLocalDeleteIdMap.clear(); // 清空本地删除记录 if (mCancelled) { return; } - // 处理本地删除的笔记 + // 处理本地已删除的笔记(位于回收站) try { + // 查询回收站中的非系统笔记 c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, - "(type<>? AND parent_id=?)", new String[] { - String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER) - }, null); + "(type<>? AND parent_id=?)", + new String[]{String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)}, + null); if (c != null) { while (c.moveToNext()) { - gid = c.getString(SqlNote.GTASK_ID_COLUMN); - node = mGTaskHashMap.get(gid); + gid = c.getString(SqlNote.GTASK_ID_COLUMN); // 获取远程GID + node = mGTaskHashMap.get(gid); // 查找对应的远程节点 if (node != null) { - mGTaskHashMap.remove(gid); - doContentSync(Node.SYNC_ACTION_DEL_REMOTE, node, c); + mGTaskHashMap.remove(gid); // 从缓存中移除 + doContentSync(Node.SYNC_ACTION_DEL_REMOTE, node, c); // 删除远程节点 } - - mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); + mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); // 记录本地删除ID } } else { - Log.w(TAG, "failed to query trash folder"); + Log.w(TAG, "查询回收站失败"); } } finally { if (c != null) { @@ -297,39 +299,37 @@ public class GTaskManager { } } - // 首先同步文件夹 + // 先同步文件夹(确保结构一致) syncFolder(); - // 处理数据库中已存在的笔记 + // 同步普通笔记(非文件夹) try { + // 查询非系统、非回收站的笔记 c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, - "(type=? AND parent_id<>?)", new String[] { - String.valueOf(Notes.TYPE_NOTE), String.valueOf(Notes.ID_TRASH_FOLER) - }, NoteColumns.TYPE + " DESC"); + "(type=? AND parent_id<>?)", + new String[]{String.valueOf(Notes.TYPE_NOTE), String.valueOf(Notes.ID_TRASH_FOLER)}, + NoteColumns.TYPE + " DESC"); if (c != null) { while (c.moveToNext()) { - gid = c.getString(SqlNote.GTASK_ID_COLUMN); - node = mGTaskHashMap.get(gid); + gid = c.getString(SqlNote.GTASK_ID_COLUMN); // 获取远程GID + node = mGTaskHashMap.get(gid); // 查找对应的远程节点 if (node != null) { - mGTaskHashMap.remove(gid); - mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); + mGTaskHashMap.remove(gid); // 从缓存中移除 + mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); // 记录GID与本地ID映射 mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); - syncType = node.getSyncAction(c); + syncType = node.getSyncAction(c); // 确定同步操作类型 } else { if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // 本地添加 - syncType = Node.SYNC_ACTION_ADD_REMOTE; + syncType = Node.SYNC_ACTION_ADD_REMOTE; // 本地新增,需同步到远程 } else { - // 远程删除 - syncType = Node.SYNC_ACTION_DEL_LOCAL; + syncType = Node.SYNC_ACTION_DEL_LOCAL; // 远程已删除,需本地删除 } } - doContentSync(syncType, node, c); + doContentSync(syncType, node, c); // 执行同步操作 } } else { - Log.w(TAG, "failed to query existing note in database"); + Log.w(TAG, "查询本地笔记失败"); } - } finally { if (c != null) { c.close(); @@ -337,31 +337,32 @@ public class GTaskManager { } } - // 处理剩余的项目 + // 处理远程新增但本地没有的节点(遍历剩余缓存节点) Iterator> iter = mGTaskHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); node = entry.getValue(); - doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); + doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); // 新增到本地 } - // 清除本地删除表 + // 批量删除本地已标记删除的笔记(非同步过程中取消的情况) if (!mCancelled) { if (!DataUtils.batchDeleteNotes(mContentResolver, mLocalDeleteIdMap)) { - throw new ActionFailureException("failed to batch-delete local deleted notes"); + throw new ActionFailureException("批量删除本地已删除笔记失败"); } } - // 刷新本地同步ID + // 提交批量更新并刷新本地同步ID if (!mCancelled) { - GTaskClient.getInstance().commitUpdate(); - refreshLocalSyncId(); + GTaskClient.getInstance().commitUpdate(); // 提交所有批量操作 + refreshLocalSyncId(); // 更新本地笔记的同步时间 } } + // ==================== 文件夹同步 ==================== /** - * 同步文件夹 - * 处理文件夹的创建、更新和删除操作 + * 同步文件夹(系统文件夹和用户创建的文件夹) + * @throws NetworkFailureException 网络异常 */ private void syncFolder() throws NetworkFailureException { Cursor c = null; @@ -373,27 +374,26 @@ public class GTaskManager { return; } - // 处理根文件夹 + // 同步根文件夹(系统文件夹) try { c = mContentResolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, Notes.ID_ROOT_FOLDER), SqlNote.PROJECTION_NOTE, null, null, null); - if (c != null) { - c.moveToNext(); + if (c != null && c.moveToNext()) { gid = c.getString(SqlNote.GTASK_ID_COLUMN); node = mGTaskHashMap.get(gid); if (node != null) { mGTaskHashMap.remove(gid); mGidToNid.put(gid, (long) Notes.ID_ROOT_FOLDER); mNidToGid.put((long) Notes.ID_ROOT_FOLDER, gid); - // 对于系统文件夹,仅在必要时更新远程名称 - if (!node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) + // 仅当远程名称不一致时更新(系统文件夹名称固定) + if (!node.getName().equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) { doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); + } } else { - doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c); + doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c); // 新增到远程 } } else { - Log.w(TAG, "failed to query root folder"); + Log.w(TAG, "查询根文件夹失败"); } } finally { if (c != null) { @@ -402,31 +402,27 @@ public class GTaskManager { } } - // 处理通话记录文件夹 + // 同步通话记录文件夹(系统文件夹) try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, "(_id=?)", - new String[] { - String.valueOf(Notes.ID_CALL_RECORD_FOLDER) - }, null); - if (c != null) { - if (c.moveToNext()) { - gid = c.getString(SqlNote.GTASK_ID_COLUMN); - node = mGTaskHashMap.get(gid); - if (node != null) { - mGTaskHashMap.remove(gid); - mGidToNid.put(gid, (long) Notes.ID_CALL_RECORD_FOLDER); - mNidToGid.put((long) Notes.ID_CALL_RECORD_FOLDER, gid); - // 对于系统文件夹,仅在必要时更新远程名称 - if (!node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX - + GTaskStringUtils.FOLDER_CALL_NOTE)) - doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); - } else { - doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c); + new String[]{String.valueOf(Notes.ID_CALL_RECORD_FOLDER)}, null); + if (c != null && c.moveToNext()) { + gid = c.getString(SqlNote.GTASK_ID_COLUMN); + node = mGTaskHashMap.get(gid); + if (node != null) { + mGTaskHashMap.remove(gid); + mGidToNid.put(gid, (long) Notes.ID_CALL_RECORD_FOLDER); + mNidToGid.put((long) Notes.ID_CALL_RECORD_FOLDER, + mNidToGid.put((long) Notes.ID_CALL_RECORD_FOLDER, gid); + // 仅当远程名称不一致时更新(系统文件夹名称固定) + if (!node.getName().equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) { + doContentSync(Node.SYNC_ACTION_UPDATE_REMOTE, node, c); } + } else { + doContentSync(Node.SYNC_ACTION_ADD_REMOTE, node, c); // 新增到远程 } } else { - Log.w(TAG, "failed to query call note folder"); + Log.w(TAG, "查询通话记录文件夹失败"); } } finally { if (c != null) { @@ -435,12 +431,12 @@ public class GTaskManager { } } - // 处理本地已存在的文件夹 + // 同步本地已存在的用户文件夹 try { c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, - "(type=? AND parent_id<>?)", new String[] { - String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER) - }, NoteColumns.TYPE + " DESC"); + "(type=? AND parent_id<>?)", + new String[]{String.valueOf(Notes.TYPE_FOLDER), String.valueOf(Notes.ID_TRASH_FOLER)}, + NoteColumns.TYPE + " DESC"); if (c != null) { while (c.moveToNext()) { gid = c.getString(SqlNote.GTASK_ID_COLUMN); @@ -449,20 +445,18 @@ public class GTaskManager { mGTaskHashMap.remove(gid); mGidToNid.put(gid, c.getLong(SqlNote.ID_COLUMN)); mNidToGid.put(c.getLong(SqlNote.ID_COLUMN), gid); - syncType = node.getSyncAction(c); + syncType = node.getSyncAction(c); // 确定同步操作类型 } else { if (c.getString(SqlNote.GTASK_ID_COLUMN).trim().length() == 0) { - // 本地添加 - syncType = Node.SYNC_ACTION_ADD_REMOTE; + syncType = Node.SYNC_ACTION_ADD_REMOTE; // 本地新增,需同步到远程 } else { - // 远程删除 - syncType = Node.SYNC_ACTION_DEL_LOCAL; + syncType = Node.SYNC_ACTION_DEL_LOCAL; // 远程已删除,需本地删除 } } - doContentSync(syncType, node, c); + doContentSync(syncType, node, c); // 执行同步操作 } } else { - Log.w(TAG, "failed to query existing folder"); + Log.w(TAG, "查询本地文件夹失败"); } } finally { if (c != null) { @@ -471,7 +465,7 @@ public class GTaskManager { } } - // 处理远程添加的文件夹 + // 处理远程新增但本地没有的文件夹 Iterator> iter = mGTaskListHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -479,19 +473,22 @@ public class GTaskManager { node = entry.getValue(); if (mGTaskHashMap.containsKey(gid)) { mGTaskHashMap.remove(gid); - doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); + doContentSync(Node.SYNC_ACTION_ADD_LOCAL, node, null); // 新增到本地 } } + // 提交批量更新(如果有) if (!mCancelled) GTaskClient.getInstance().commitUpdate(); } + // ==================== 内容同步核心方法 ==================== /** - * 执行内容同步 - * @param syncType 同步类型 - * @param node 节点 - * @param c 游标 + * 执行具体的同步操作(根据同步类型处理节点) + * @param syncType 同步操作类型(增/删/改等) + * @param node 要同步的节点 + * @param c 本地数据库游标(可能为null) + * @throws NetworkFailureException 网络异常 */ private void doContentSync(int syncType, Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { @@ -501,47 +498,51 @@ public class GTaskManager { MetaData meta; switch (syncType) { case Node.SYNC_ACTION_ADD_LOCAL: - addLocalNode(node); + addLocalNode(node); // 远程新增,添加到本地 break; case Node.SYNC_ACTION_ADD_REMOTE: - addRemoteNode(node, c); + addRemoteNode(node, c); // 本地新增,添加到远程 break; case Node.SYNC_ACTION_DEL_LOCAL: + // 远程已删除,本地也删除(并删除关联的元数据) meta = mMetaHashMap.get(c.getString(SqlNote.GTASK_ID_COLUMN)); if (meta != null) { GTaskClient.getInstance().deleteNode(meta); } - mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); + mLocalDeleteIdMap.add(c.getLong(SqlNote.ID_COLUMN)); // 标记为本地待删除 break; case Node.SYNC_ACTION_DEL_REMOTE: + // 本地已删除,远程也删除(并删除关联的元数据) meta = mMetaHashMap.get(node.getGid()); if (meta != null) { GTaskClient.getInstance().deleteNode(meta); } - GTaskClient.getInstance().deleteNode(node); + GTaskClient.getInstance().deleteNode(node); // 删除远程节点 break; case Node.SYNC_ACTION_UPDATE_LOCAL: - updateLocalNode(node, c); + updateLocalNode(node, c); // 远程更新,更新本地 break; case Node.SYNC_ACTION_UPDATE_REMOTE: - updateRemoteNode(node, c); + updateRemoteNode(node, c); // 本地更新,更新远程 break; case Node.SYNC_ACTION_UPDATE_CONFLICT: - // 合并两个修改可能是个好主意 - // 现在只是简单地使用本地更新 + // 冲突处理:本地和远程都有更新(当前策略:优先使用本地更新) + // 可优化为更智能的合并策略 updateRemoteNode(node, c); break; case Node.SYNC_ACTION_NONE: + // 无需同步(数据相同) break; case Node.SYNC_ACTION_ERROR: default: - throw new ActionFailureException("unkown sync action type"); + throw new ActionFailureException("未知同步操作类型"); } } /** - * 添加本地节点 * 将远程节点添加到本地数据库 + * @param node 远程节点(任务或列表) + * @throws NetworkFailureException 网络异常 */ private void addLocalNode(Node node) throws NetworkFailureException { if (mCancelled) { @@ -550,32 +551,35 @@ public class GTaskManager { SqlNote sqlNote; if (node instanceof TaskList) { - if (node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) { - sqlNote = new SqlNote(mContext, Notes.ID_ROOT_FOLDER); - } else if (node.getName().equals( - GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) { - sqlNote = new SqlNote(mContext, Notes.ID_CALL_RECORD_FOLDER); + // 处理文件夹 + if (node.getName().equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_DEFAULT)) { + sqlNote = new SqlNote(mContext, Notes.ID_ROOT_FOLDER); // 根文件夹 + } else if (node.getName().equals(GTaskStringUtils.MIUI_FOLDER_PREFFIX + GTaskStringUtils.FOLDER_CALL_NOTE)) { + sqlNote = new SqlNote(mContext, Notes.ID_CALL_RECORD_FOLDER); // 通话记录文件夹 } else { + // 普通文件夹 sqlNote = new SqlNote(mContext); - sqlNote.setContent(node.getLocalJSONFromContent()); - sqlNote.setParentId(Notes.ID_ROOT_FOLDER); + sqlNote.setContent(node.getLocalJSONFromContent()); // 设置内容 + sqlNote.setParentId(Notes.ID_ROOT_FOLDER); // 设置父文件夹为根文件夹 } } else { + // 处理任务(笔记) sqlNote = new SqlNote(mContext); - JSONObject js = node.getLocalJSONFromContent(); + JSONObject js = node.getLocalJSONFromContent(); // 获取远程内容并转换为本地格式 try { + // 处理笔记内容 if (js.has(GTaskStringUtils.META_HEAD_NOTE)) { JSONObject note = js.getJSONObject(GTaskStringUtils.META_HEAD_NOTE); if (note.has(NoteColumns.ID)) { long id = note.getLong(NoteColumns.ID); if (DataUtils.existInNoteDatabase(mContentResolver, id)) { - // ID不可用,必须创建新的 + // ID已存在,移除ID以创建新笔记 note.remove(NoteColumns.ID); } } } + // 处理笔记数据(如附件等) if (js.has(GTaskStringUtils.META_HEAD_DATA)) { JSONArray dataArray = js.getJSONArray(GTaskStringUtils.META_HEAD_DATA); for (int i = 0; i < dataArray.length(); i++) { @@ -583,99 +587,106 @@ public class GTaskManager { if (data.has(DataColumns.ID)) { long dataId = data.getLong(DataColumns.ID); if (DataUtils.existInDataDatabase(mContentResolver, dataId)) { - // 数据ID不可用,必须创建新的 + // ID已存在,移除ID以创建新数据项 data.remove(DataColumns.ID); } } } - } } catch (JSONException e) { - Log.w(TAG, e.toString()); + Log.w(TAG, "处理JSON数据失败: " + e.getMessage()); e.printStackTrace(); } - sqlNote.setContent(js); + sqlNote.setContent(js); // 设置处理后的内容 + // 设置父文件夹(根据远程任务的父列表GID查找本地对应ID) Long parentId = mGidToNid.get(((Task) node).getParent().getGid()); if (parentId == null) { - Log.e(TAG, "cannot find task's parent id locally"); - throw new ActionFailureException("cannot add local node"); + Log.e(TAG, "无法找到任务的父文件夹ID"); + throw new ActionFailureException("无法添加本地节点"); } sqlNote.setParentId(parentId.longValue()); } // 创建本地节点 - sqlNote.setGtaskId(node.getGid()); - sqlNote.commit(false); + sqlNote.setGtaskId(node.getGid()); // 设置远程GID + sqlNote.commit(false); // 提交到数据库(不更新同步状态) - // 更新gid-nid映射 + // 更新GID与本地ID映射 mGidToNid.put(node.getGid(), sqlNote.getId()); mNidToGid.put(sqlNote.getId(), node.getGid()); - // 更新元数据 + // 更新元数据(关联远程任务与本地笔记) updateRemoteMeta(node.getGid(), sqlNote); } /** - * 更新本地节点 - * 根据远程数据更新本地节点 + * 更新本地节点(根据远程变更) + * @param node 远程节点 + * @param c 本地数据库游标 + * @throws NetworkFailureException 网络异常 */ private void updateLocalNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; } - SqlNote sqlNote; - // 本地更新笔记 - sqlNote = new SqlNote(mContext, c); - sqlNote.setContent(node.getLocalJSONFromContent()); + SqlNote sqlNote = new SqlNote(mContext, c); // 从游标创建SqlNote对象 + sqlNote.setContent(node.getLocalJSONFromContent()); // 设置远程内容 - Long parentId = (node instanceof Task) ? mGidToNid.get(((Task) node).getParent().getGid()) - : new Long(Notes.ID_ROOT_FOLDER); + // 设置父文件夹(根据远程任务的父列表GID查找本地对应ID) + Long parentId = (node instanceof Task) ? + mGidToNid.get(((Task) node).getParent().getGid()) : + new Long(Notes.ID_ROOT_FOLDER); if (parentId == null) { - Log.e(TAG, "cannot find task's parent id locally"); - throw new ActionFailureException("cannot update local node"); + Log.e(TAG, "无法找到任务的父文件夹ID"); + throw new ActionFailureException("无法更新本地节点"); } sqlNote.setParentId(parentId.longValue()); - sqlNote.commit(true); + sqlNote.commit(true); // 提交更新(更新同步状态) - // 更新元信息 + // 更新元数据 updateRemoteMeta(node.getGid(), sqlNote); } /** - * 添加远程节点 - * 将本地节点添加到远程服务器 + * 将本地节点添加到远程Google Tasks + * @param node 本地节点(可能为null,表示需要从游标创建) + * @param c 本地数据库游标 + * @throws NetworkFailureException 网络异常 */ private void addRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; } - SqlNote sqlNote = new SqlNote(mContext, c); + SqlNote sqlNote = new SqlNote(mContext, c); // 从游标创建SqlNote对象 Node n; - // 远程更新 + // 更新到远程 if (sqlNote.isNoteType()) { + // 处理笔记 Task task = new Task(); - task.setContentByLocalJSON(sqlNote.getContent()); + task.setContentByLocalJSON(sqlNote.getContent()); // 从本地内容初始化任务 + // 获取父文件夹的GID String parentGid = mNidToGid.get(sqlNote.getParentId()); if (parentGid == null) { - Log.e(TAG, "cannot find task's parent tasklist"); - throw new ActionFailureException("cannot add remote task"); + Log.e(TAG, "无法找到任务的父文件夹"); + throw new ActionFailureException("无法添加远程任务"); } - mGTaskListHashMap.get(parentGid).addChildTask(task); + mGTaskListHashMap.get(parentGid).addChildTask(task); // 添加到父列表 - GTaskClient.getInstance().createTask(task); + GTaskClient.getInstance().createTask(task); // 创建远程任务 n = (Node) task; // 添加元数据 updateRemoteMeta(task.getGid(), sqlNote); } else { + // 处理文件夹 TaskList tasklist = null; - // 如果文件夹已存在,我们需要跳过 + // 构建文件夹名称(添加特定前缀) String folderName = GTaskStringUtils.MIUI_FOLDER_PREFFIX; if (sqlNote.getId() == Notes.ID_ROOT_FOLDER) folderName += GTaskStringUtils.FOLDER_DEFAULT; @@ -684,6 +695,7 @@ public class GTaskManager { else folderName += sqlNote.getSnippet(); + // 检查文件夹是否已存在 Iterator> iter = mGTaskListHashMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = iter.next(); @@ -699,100 +711,106 @@ public class GTaskManager { } } - // 没有匹配项,现在可以添加 + // 如果不存在则创建新文件夹 if (tasklist == null) { tasklist = new TaskList(); - tasklist.setContentByLocalJSON(sqlNote.getContent()); - GTaskClient.getInstance().createTaskList(tasklist); - mGTaskListHashMap.put(tasklist.getGid(), tasklist); + tasklist.setContentByLocalJSON(sqlNote.getContent()); // 从本地内容初始化列表 + GTaskClient.getInstance().createTaskList(tasklist); // 创建远程列表 + mGTaskListHashMap.put(tasklist.getGid(), tasklist); // 缓存列表 } n = (Node) tasklist; } - // 更新本地笔记 + // 更新本地笔记(设置远程GID) sqlNote.setGtaskId(n.getGid()); - sqlNote.commit(false); - sqlNote.resetLocalModified(); - sqlNote.commit(true); + sqlNote.commit(false); // 提交(不更新同步状态) + sqlNote.resetLocalModified(); // 重置本地修改标记 + sqlNote.commit(true); // 再次提交(更新同步状态) - // gid-id映射 + // 更新GID与本地ID映射 mGidToNid.put(n.getGid(), sqlNote.getId()); mNidToGid.put(sqlNote.getId(), n.getGid()); } /** - * 更新远程节点 - * 根据本地数据更新远程节点 + * 更新远程节点(根据本地变更) + * @param node 远程节点 + * @param c 本地数据库游标 + * @throws NetworkFailureException 网络异常 */ private void updateRemoteNode(Node node, Cursor c) throws NetworkFailureException { if (mCancelled) { return; } - SqlNote sqlNote = new SqlNote(mContext, c); + SqlNote sqlNote = new SqlNote(mContext, c); // 从游标创建SqlNote对象 - // 远程更新 - node.setContentByLocalJSON(sqlNote.getContent()); - GTaskClient.getInstance().addUpdateNode(node); + // 更新远程节点 + node.setContentByLocalJSON(sqlNote.getContent()); // 用本地内容更新远程节点 + GTaskClient.getInstance().addUpdateNode(node); // 添加到批量更新队列 // 更新元数据 updateRemoteMeta(node.getGid(), sqlNote); - // 必要时移动任务 + // 如果是任务且需要移动(父文件夹变更) if (sqlNote.isNoteType()) { Task task = (Task) node; - TaskList preParentList = task.getParent(); + TaskList preParentList = task.getParent(); // 原父列表 - String curParentGid = mNidToGid.get(sqlNote.getParentId()); + String curParentGid = mNidToGid.get(sqlNote.getParentId()); // 当前父列表GID if (curParentGid == null) { - Log.e(TAG, "cannot find task's parent tasklist"); - throw new ActionFailureException("cannot update remote task"); + Log.e(TAG, "无法找到任务的父文件夹"); + throw new ActionFailureException("无法更新远程任务"); } - TaskList curParentList = mGTaskListHashMap.get(curParentGid); + TaskList curParentList = mGTaskListHashMap.get(curParentGid); // 当前父列表 + // 如果父列表变更,执行移动操作 if (preParentList != curParentList) { - preParentList.removeChildTask(task); - curParentList.addChildTask(task); - GTaskClient.getInstance().moveTask(task, preParentList, curParentList); + preParentList.removeChildTask(task); // 从原列表移除 + curParentList.addChildTask(task); // 添加到新列表 + GTaskClient.getInstance().moveTask(task, preParentList, curParentList); // 执行移动 } } - // 清除本地修改标志 + // 清除本地修改标记 sqlNote.resetLocalModified(); sqlNote.commit(true); } /** - * 更新远程元数据 - * @param gid Google ID - * @param sqlNote SQL笔记对象 + * 更新远程元数据(关联任务与本地笔记) + * @param gid 远程任务GID + * @param sqlNote 本地笔记对象 + * @throws NetworkFailureException 网络异常 */ private void updateRemoteMeta(String gid, SqlNote sqlNote) throws NetworkFailureException { if (sqlNote != null && sqlNote.isNoteType()) { - MetaData metaData = mMetaHashMap.get(gid); + MetaData metaData = mMetaHashMap.get(gid); // 获取元数据 if (metaData != null) { + // 元数据已存在,更新内容 metaData.setMeta(gid, sqlNote.getContent()); - GTaskClient.getInstance().addUpdateNode(metaData); + GTaskClient.getInstance().addUpdateNode(metaData); // 添加到批量更新队列 } else { + // 元数据不存在,创建新的 metaData = new MetaData(); metaData.setMeta(gid, sqlNote.getContent()); - mMetaList.addChildTask(metaData); - mMetaHashMap.put(gid, metaData); - GTaskClient.getInstance().createTask(metaData); + mMetaList.addChildTask(metaData); // 添加到元数据列表 + mMetaHashMap.put(gid, metaData); // 缓存元数据 + GTaskClient.getInstance().createTask(metaData); // 创建远程任务(元数据以任务形式存储) } } } /** - * 刷新本地同步ID - * 更新本地数据库中的同步ID + * 刷新本地同步ID(更新本地笔记的最后同步时间) + * @throws NetworkFailureException 网络异常 */ private void refreshLocalSyncId() throws NetworkFailureException { if (mCancelled) { return; } - // 获取最新的gtask列表 + // 重新获取最新的远程任务列表 mGTaskHashMap.clear(); mGTaskListHashMap.clear(); mMetaHashMap.clear(); @@ -800,28 +818,29 @@ public class GTaskManager { Cursor c = null; try { + // 查询所有非系统、非回收站的笔记 c = mContentResolver.query(Notes.CONTENT_NOTE_URI, SqlNote.PROJECTION_NOTE, - "(type<>? AND parent_id<>?)", new String[] { - String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER) - }, NoteColumns.TYPE + " DESC"); + "(type<>? AND parent_id<>?)", + new String[]{String.valueOf(Notes.TYPE_SYSTEM), String.valueOf(Notes.ID_TRASH_FOLER)}, + NoteColumns.TYPE + " DESC"); if (c != null) { while (c.moveToNext()) { String gid = c.getString(SqlNote.GTASK_ID_COLUMN); Node node = mGTaskHashMap.get(gid); if (node != null) { mGTaskHashMap.remove(gid); + // 更新本地笔记的同步ID(记录最后修改时间) ContentValues values = new ContentValues(); values.put(NoteColumns.SYNC_ID, node.getLastModified()); mContentResolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, c.getLong(SqlNote.ID_COLUMN)), values, null, null); } else { - Log.e(TAG, "something is missed"); - throw new ActionFailureException( - "some local items don't have gid after sync"); + Log.e(TAG, "找不到对应的远程节点"); + throw new ActionFailureException("同步后部分本地项没有GID"); } } } else { - Log.w(TAG, "failed to query local note to refresh sync id"); + Log.w(TAG, "查询本地笔记以刷新同步ID失败"); } } finally { if (c != null) { @@ -832,8 +851,8 @@ public class GTaskManager { } /** - * 获取同步账号 - * @return 同步账号名称 + * 获取当前同步的Google账号 + * @return 账号名称 */ public String getSyncAccount() { return GTaskClient.getInstance().getSyncAccount().name; @@ -845,4 +864,4 @@ public class GTaskManager { public void cancelSync() { mCancelled = true; } -} +} \ No newline at end of file diff --git a/MiNotes-master/app/src/main/java/net/micode/notes/model/WorkingNote.java b/MiNotes-master/app/src/main/java/net/micode/notes/model/WorkingNote.java index 49bdaae..d01b700 100644 --- a/MiNotes-master/app/src/main/java/net/micode/notes/model/WorkingNote.java +++ b/MiNotes-master/app/src/main/java/net/micode/notes/model/WorkingNote.java @@ -56,8 +56,6 @@ public class WorkingNote { private int mWidgetType; // 文件夹ID private long mFolderId; - // 字体加粗状态 - private boolean mBoldState; // 上下文 private Context mContext; // 日志标签 @@ -76,7 +74,6 @@ public class WorkingNote { DataColumns.DATA2, DataColumns.DATA3, DataColumns.DATA4, - TextNote.BOLD, }; // 笔记查询投影 @@ -94,7 +91,6 @@ public class WorkingNote { private static final int DATA_CONTENT_COLUMN = 1; private static final int DATA_MIME_TYPE_COLUMN = 2; private static final int DATA_MODE_COLUMN = 3; - private static final int DATA_BOLD_COLUMN = 7; // 笔记列索引 private static final int NOTE_PARENT_ID_COLUMN = 0; @@ -179,7 +175,6 @@ public class WorkingNote { mContent = cursor.getString(DATA_CONTENT_COLUMN); mMode = cursor.getInt(DATA_MODE_COLUMN); mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN)); - mBoldState = (cursor.getInt(DATA_BOLD_COLUMN) == 1 ? true : false); } else if (DataConstants.CALL_NOTE.equals(type)) { // 通话记录笔记数据 mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN)); @@ -477,30 +472,6 @@ public class WorkingNote { return mWidgetType; } - /** - * 设置字体加粗状态 - * @param bold 是否加粗 - */ - public void setBoldState(boolean bold) { - if (mBoldState != bold) { - mBoldState = bold; - mNote.setTextData(TextNote.BOLD, (mBoldState ? "1" : "0")); - mNote.setNoteValue(NoteColumns.SNIPPET, getContent()); - if (mNoteSettingStatusListener != null) { - // 可选:添加一个回调接口方法来通知UI加粗状态已更改 - // mNoteSettingStatusListener.onBoldStateChanged(bold); - } - } - } - - /** - * 获取字体加粗状态 - * @return 字体加粗状态 - */ - public boolean getBoldState() { - return mBoldState; - } - /** * 笔记设置变更监听器接口 */ diff --git a/MiNotes-master/app/src/main/java/net/micode/notes/tool/BackupUtils.java b/MiNotes-master/app/src/main/java/net/micode/notes/tool/BackupUtils.java index 39f6ec4..0a60b74 100644 --- a/MiNotes-master/app/src/main/java/net/micode/notes/tool/BackupUtils.java +++ b/MiNotes-master/app/src/main/java/net/micode/notes/tool/BackupUtils.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package net.micode.notes.tool; +package net.micode.notes.tool;// 啊啊年u不是丢弃为本次u我把从 import android.content.Context; import android.database.Cursor; diff --git a/MiNotes-master/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/MiNotes-master/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java index 2f34290..88fbc50 100644 --- a/MiNotes-master/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java +++ b/MiNotes-master/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java @@ -52,7 +52,6 @@ import android.widget.LinearLayout; import android.widget.PopupMenu; import android.widget.TextView; import android.widget.Toast; -import android.widget.ImageButton; import net.micode.notes.R; import net.micode.notes.data.Notes; @@ -279,7 +278,6 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery)); mNoteEditor.setSelection(mNoteEditor.getText().length()); } - applyTextStyle(); for (Integer id : sBgSelectorSelectionMap.keySet()) { findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE); } @@ -374,16 +372,6 @@ public class NoteEditActivity extends Activity implements OnClickListener, mNoteHeaderHolder.tvAlertDate = (TextView) findViewById(R.id.tv_alert_date); mNoteHeaderHolder.ibSetBgColor = (ImageView) findViewById(R.id.btn_set_bg_color); mNoteHeaderHolder.ibSetBgColor.setOnClickListener(this); - - // 初始化菜单按钮 - ImageButton menuMore = (ImageButton) findViewById(R.id.menu_more); - menuMore.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - OnOpenMenu(v); - } - }); - mNoteEditor = (EditText) findViewById(R.id.note_edit_view); mNoteEditorPanel = findViewById(R.id.sv_note_edit); mNoteBgColorSelector = findViewById(R.id.note_bg_color_selector); @@ -443,7 +431,7 @@ public class NoteEditActivity extends Activity implements OnClickListener, if (id == R.id.btn_set_bg_color) { mNoteBgColorSelector.setVisibility(View.VISIBLE); findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( - View.VISIBLE); + - View.VISIBLE); } else if (sBgSelectorBtnsMap.containsKey(id)) { findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility( View.GONE); @@ -744,13 +732,6 @@ public class NoteEditActivity extends Activity implements OnClickListener, View view = LayoutInflater.from(this).inflate(R.layout.note_edit_list_item, null); final NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); - - if (mWorkingNote.getBoldState()) { - edit.setTypeface(null, android.graphics.Typeface.BOLD); - } else { - edit.setTypeface(null, android.graphics.Typeface.NORMAL); - } - CheckBox cb = ((CheckBox) view.findViewById(R.id.cb_edit_item)); cb.setOnCheckedChangeListener(new OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { @@ -907,52 +888,13 @@ public class NoteEditActivity extends Activity implements OnClickListener, } else { popupMenu.getMenuInflater().inflate(R.menu.note_edit, popupMenu.getMenu()); } - - // 根据字体加粗状态设置菜单文本 - MenuItem boldMenuItem = popupMenu.getMenu().findItem(R.id.menu_bold); - if (boldMenuItem != null) { - if (mWorkingNote.getBoldState()) { - boldMenuItem.setTitle(R.string.menu_unbold); - } else { - boldMenuItem.setTitle(R.string.menu_bold); - } - } - // 设置菜单项点击事件 popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { - if (item.getItemId() == R.id.menu_bold) { - mWorkingNote.setBoldState(!mWorkingNote.getBoldState()); - applyTextStyle(); - return true; - } return onOptionsItemSelected(item); // 复用原有逻辑 } }); popupMenu.show(); } - - private void applyTextStyle() { - if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) { - // 遍历所有NoteEditText并应用样式 - for (int i = 0; i < mEditTextList.getChildCount(); i++) { - View view = mEditTextList.getChildAt(i); - NoteEditText edit = (NoteEditText) view.findViewById(R.id.et_edit_text); - edit.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); - if (mWorkingNote.getBoldState()) { - edit.setTypeface(null, android.graphics.Typeface.BOLD); - } else { - edit.setTypeface(null, android.graphics.Typeface.NORMAL); - } - } - } else { - mNoteEditor.setTextAppearance(this, TextAppearanceResources.getTexAppearanceResource(mFontSizeId)); - if (mWorkingNote.getBoldState()) { - mNoteEditor.setTypeface(null, android.graphics.Typeface.BOLD); - } else { - mNoteEditor.setTypeface(null, android.graphics.Typeface.NORMAL); - } - } - } } diff --git a/MiNotes-master/app/src/main/res/drawable/edit_red.xml b/MiNotes-master/app/src/main/res/drawable/edit_red.xml deleted file mode 100644 index 1370ed2..0000000 --- a/MiNotes-master/app/src/main/res/drawable/edit_red.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MiNotes-master/app/src/main/res/drawable/list_background.xml b/MiNotes-master/app/src/main/res/drawable/list_background.xml deleted file mode 100644 index a37e0a9..0000000 --- a/MiNotes-master/app/src/main/res/drawable/list_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MiNotes-master/app/src/main/res/menu/note_edit.xml b/MiNotes-master/app/src/main/res/menu/note_edit.xml index ede9f54..35cacd1 100644 --- a/MiNotes-master/app/src/main/res/menu/note_edit.xml +++ b/MiNotes-master/app/src/main/res/menu/note_edit.xml @@ -30,10 +30,6 @@ android:id="@+id/menu_font_size" android:title="@string/menu_font_size"/> - - diff --git a/MiNotes-master/app/src/main/res/values/strings.xml b/MiNotes-master/app/src/main/res/values/strings.xml index f307720..55df868 100644 --- a/MiNotes-master/app/src/main/res/values/strings.xml +++ b/MiNotes-master/app/src/main/res/values/strings.xml @@ -57,8 +57,6 @@ Medium Large Super - Bold - Unbold Enter check list Leave check list View folder @@ -134,9 +132,4 @@ %1$s results for \"%2$s\" - - %1$s note - %1$s notes - - diff --git a/小米便签开源软件维护方案及成果.docx b/小米便签开源软件维护方案及成果.docx deleted file mode 100644 index f4de30e..0000000 Binary files a/小米便签开源软件维护方案及成果.docx and /dev/null differ diff --git a/文档模板-开源代码质量分析报告模板.docx b/文档模板-开源代码质量分析报告模板.docx deleted file mode 100644 index 626edee..0000000 Binary files a/文档模板-开源代码质量分析报告模板.docx and /dev/null differ diff --git a/文档模板-开源软件维护方案及成果模板.docx b/文档模板-开源软件维护方案及成果模板.docx deleted file mode 100644 index 0b7e6ea..0000000 Binary files a/文档模板-开源软件维护方案及成果模板.docx and /dev/null differ diff --git a/文档模板-软件设计规格说明书模板.doc b/文档模板-软件设计规格说明书模板.doc deleted file mode 100644 index 1b04b11..0000000 Binary files a/文档模板-软件设计规格说明书模板.doc and /dev/null differ diff --git a/文档模板-软件需求构思及描述模板.docx b/文档模板-软件需求构思及描述模板.docx deleted file mode 100644 index 249888d..0000000 Binary files a/文档模板-软件需求构思及描述模板.docx and /dev/null differ diff --git a/文档模板-软件需求规格说明书模板.docx b/文档模板-软件需求规格说明书模板.docx deleted file mode 100644 index 5b486cf..0000000 Binary files a/文档模板-软件需求规格说明书模板.docx and /dev/null differ