From e524c032d94361c6e9082c0ade5828ab5f08c4ef Mon Sep 17 00:00:00 2001
From: Joker21a <1095435669@qq.com>
Date: Thu, 18 Jan 2024 17:32:34 +0800
Subject: [PATCH] =?UTF-8?q?=E6=97=A0=E6=B3=A8=E9=87=8A=20=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=E5=AE=8C=E5=85=A8=E7=89=88?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/main/AndroidManifest.xml | 34 +-
.../java/net/micode/notes/data/Notes.java | 282 +++++++
.../notes/data/NotesDatabaseHelper.java | 372 +++++++++
.../notes/gtask/remote/GTaskASyncTask.java | 123 +++
.../net/micode/notes/model/WorkingNote.java | 143 +---
.../net/micode/notes/tool/ResourceParser.java | 21 +-
.../notes/ui/ChangeLoginPasswordActivity.java | 127 +++
.../net/micode/notes/ui/LoginActivity.java | 163 ++++
.../java/net/micode/notes/ui/LoginView.java | 76 ++
.../net/micode/notes/ui/NoteEditActivity.java | 17 +-
.../micode/notes/ui/NotesListActivity.java | 778 +++---------------
.../net/micode/notes/ui/NotesListItem.java | 2 +-
src/main/res/drawable-hdpi/lock_private.png | Bin 0 -> 11130 bytes
src/main/res/drawable-hdpi/login_photo.png | Bin 0 -> 1389 bytes
.../res/drawable-hdpi/login_view_photo.png | Bin 0 -> 166902 bytes
.../res/drawable-hdpi/login_view_photo_2.jpg | Bin 0 -> 19712 bytes
.../note_background_photo_duck.jpg | Bin 0 -> 807974 bytes
.../note_background_photo_wangyi.png | Bin 0 -> 413747 bytes
.../drawable-hdpi/note_bg_photo_wangyi.png | Bin 0 -> 12065 bytes
.../note_edit_color_selector_panel_test.png | Bin 0 -> 59611 bytes
.../layout/change_login_password_activity.xml | 72 ++
src/main/res/layout/login_activity.xml | 81 ++
src/main/res/layout/login_view.xml | 23 +
src/main/res/layout/model_insert.xml | 18 +
src/main/res/layout/note_edit.xml | 22 +-
src/main/res/layout/pwd.xml | 9 +
src/main/res/menu/sub_folder.xml | 5 +-
src/main/res/values/strings.xml | 12 +
src/main/res/values/styles.xml | 4 +-
29 files changed, 1603 insertions(+), 781 deletions(-)
create mode 100644 src/main/java/net/micode/notes/data/Notes.java
create mode 100644 src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
create mode 100644 src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
create mode 100644 src/main/java/net/micode/notes/ui/ChangeLoginPasswordActivity.java
create mode 100644 src/main/java/net/micode/notes/ui/LoginActivity.java
create mode 100644 src/main/java/net/micode/notes/ui/LoginView.java
create mode 100644 src/main/res/drawable-hdpi/lock_private.png
create mode 100644 src/main/res/drawable-hdpi/login_photo.png
create mode 100644 src/main/res/drawable-hdpi/login_view_photo.png
create mode 100644 src/main/res/drawable-hdpi/login_view_photo_2.jpg
create mode 100644 src/main/res/drawable-hdpi/note_background_photo_duck.jpg
create mode 100644 src/main/res/drawable-hdpi/note_background_photo_wangyi.png
create mode 100644 src/main/res/drawable-hdpi/note_bg_photo_wangyi.png
create mode 100644 src/main/res/drawable-hdpi/note_edit_color_selector_panel_test.png
create mode 100644 src/main/res/layout/change_login_password_activity.xml
create mode 100644 src/main/res/layout/login_activity.xml
create mode 100644 src/main/res/layout/login_view.xml
create mode 100644 src/main/res/layout/model_insert.xml
create mode 100644 src/main/res/layout/pwd.xml
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index e5c7d47..4c482c1 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -36,12 +36,12 @@
android:icon="@drawable/icon_app"
android:label="@string/app_name" >
@@ -50,6 +50,36 @@
+
+
+
+
+
+
+
+
+
Type: INTEGER (long)
+ */
+ public static final String ID = "_id";
+
+ /**
+ * The parent's id for note or folder
+ * Type: INTEGER (long)
+ */
+ public static final String PARENT_ID = "parent_id";
+
+ /**
+ * Created data for note or folder
+ * Type: INTEGER (long)
+ */
+ public static final String CREATED_DATE = "created_date";
+
+ /**
+ * Latest modified date
+ * Type: INTEGER (long)
+ */
+ public static final String MODIFIED_DATE = "modified_date";
+
+
+ /**
+ * Alert date
+ * Type: INTEGER (long)
+ */
+ public static final String ALERTED_DATE = "alert_date";
+
+ /**
+ * Folder's name or text content of note
+ * Type: TEXT
+ */
+ public static final String SNIPPET = "snippet";
+
+ /**
+ * Note's widget id
+ * Type: INTEGER (long)
+ */
+ public static final String WIDGET_ID = "widget_id";
+
+ /**
+ * Note's widget type
+ * Type: INTEGER (long)
+ */
+ public static final String WIDGET_TYPE = "widget_type";
+
+ /**
+ * Note's background color's id
+ * Type: INTEGER (long)
+ */
+ public static final String BG_COLOR_ID = "bg_color_id";
+
+ /**
+ * For text note, it doesn't has attachment, for multi-media
+ * note, it has at least one attachment
+ * Type: INTEGER
+ */
+ public static final String HAS_ATTACHMENT = "has_attachment";
+
+ /**
+ * Folder's count of notes
+ * Type: INTEGER (long)
+ */
+ public static final String NOTES_COUNT = "notes_count";
+
+ /**
+ * The file type: folder or note
+ * Type: INTEGER
+ */
+ public static final String TYPE = "type";
+
+ /**
+ * The last sync id
+ * Type: INTEGER (long)
+ */
+ public static final String SYNC_ID = "sync_id";
+
+ /**
+ * Sign to indicate local modified or not
+ * Type: INTEGER
+ */
+ public static final String LOCAL_MODIFIED = "local_modified";
+
+ /**
+ * Original parent id before moving into temporary folder
+ * Type : INTEGER
+ */
+ public static final String ORIGIN_PARENT_ID = "origin_parent_id";
+
+ /**
+ * The gtask id
+ * Type : TEXT
+ */
+ public static final String GTASK_ID = "gtask_id";
+
+ /**
+ * The version code
+ * Type : INTEGER (long)
+ */
+ public static final String VERSION = "version";
+
+ public static final String PASSWORD= "password";
+ }
+
+ public interface DataColumns {
+ /**
+ * The unique ID for a row
+ * Type: INTEGER (long)
+ */
+ public static final String ID = "_id";
+
+ /**
+ * The MIME type of the item represented by this row.
+ * Type: Text
+ */
+ public static final String MIME_TYPE = "mime_type";
+
+ /**
+ * The reference id to note that this data belongs to
+ * Type: INTEGER (long)
+ */
+ public static final String NOTE_ID = "note_id";
+
+ /**
+ * Created data for note or folder
+ * Type: INTEGER (long)
+ */
+ public static final String CREATED_DATE = "created_date";
+
+ /**
+ * Latest modified date
+ * Type: INTEGER (long)
+ */
+ public static final String MODIFIED_DATE = "modified_date";
+
+ /**
+ * Data's content
+ * Type: TEXT
+ */
+ public static final String CONTENT = "content";
+
+
+ /**
+ * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
+ * integer data type
+ * Type: INTEGER
+ */
+ public static final String DATA1 = "data1";
+
+ /**
+ * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
+ * integer data type
+ * Type: INTEGER
+ */
+ public static final String DATA2 = "data2";
+
+ /**
+ * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
+ * TEXT data type
+ * Type: TEXT
+ */
+ public static final String DATA3 = "data3";
+
+ /**
+ * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
+ * TEXT data type
+ * Type: TEXT
+ */
+ public static final String DATA4 = "data4";
+
+ /**
+ * Generic data column, the meaning is {@link #MIMETYPE} specific, used for
+ * TEXT data type
+ * Type: TEXT
+ */
+ public static final String DATA5 = "data5";
+ }
+
+ public static final class TextNote implements DataColumns {
+ /**
+ * Mode to indicate the text in check list mode or not
+ * Type: Integer 1:check list mode 0: normal mode
+ */
+ public static final String MODE = DATA1;
+
+ public static final int MODE_CHECK_LIST = 1;
+
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/text_note";
+
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/text_note";
+
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/text_note");
+ }
+
+ public static final class CallNote implements DataColumns {
+ /**
+ * Call date for this record
+ * Type: INTEGER (long)
+ */
+ public static final String CALL_DATE = DATA1;
+
+ /**
+ * Phone number for this record
+ * Type: TEXT
+ */
+ public static final String PHONE_NUMBER = DATA3;
+
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/call_note";
+
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/call_note";
+
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/call_note");
+ }
+}
diff --git a/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
new file mode 100644
index 0000000..4e1fa12
--- /dev/null
+++ b/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.micode.notes.data;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import net.micode.notes.data.Notes.DataColumns;
+import net.micode.notes.data.Notes.DataConstants;
+import net.micode.notes.data.Notes.NoteColumns;
+
+
+public class NotesDatabaseHelper extends SQLiteOpenHelper {
+ private static final String DB_NAME = "note.db";
+
+ private static final int DB_VERSION = 5;
+
+ public interface TABLE {
+ public static final String NOTE = "note";
+
+ public static final String DATA = "data";
+ }
+
+ private static final String TAG = "NotesDatabaseHelper";
+
+ private static NotesDatabaseHelper mInstance;
+
+ private static final String CREATE_NOTE_TABLE_SQL =
+ "CREATE TABLE " + TABLE.NOTE + "(" +
+ NoteColumns.ID + " INTEGER PRIMARY KEY," +
+ NoteColumns.PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.ALERTED_DATE + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.BG_COLOR_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
+ NoteColumns.HAS_ATTACHMENT + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
+ NoteColumns.NOTES_COUNT + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.SNIPPET + " TEXT NOT NULL DEFAULT ''," +
+ NoteColumns.TYPE + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.WIDGET_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.WIDGET_TYPE + " INTEGER NOT NULL DEFAULT -1," +
+ NoteColumns.SYNC_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.LOCAL_MODIFIED + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.ORIGIN_PARENT_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.GTASK_ID + " TEXT NOT NULL DEFAULT ''," +
+ NoteColumns.VERSION + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.PASSWORD + " TEXT DEFAULT NULL " +
+ ")";
+
+ private static final String CREATE_DATA_TABLE_SQL =
+ "CREATE TABLE " + TABLE.DATA + "(" +
+ DataColumns.ID + " INTEGER PRIMARY KEY," +
+ DataColumns.MIME_TYPE + " TEXT NOT NULL," +
+ DataColumns.NOTE_ID + " INTEGER NOT NULL DEFAULT 0," +
+ NoteColumns.CREATED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
+ NoteColumns.MODIFIED_DATE + " INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)," +
+ DataColumns.CONTENT + " TEXT NOT NULL DEFAULT ''," +
+ DataColumns.DATA1 + " INTEGER," +
+ DataColumns.DATA2 + " INTEGER," +
+ DataColumns.DATA3 + " TEXT NOT NULL DEFAULT ''," +
+ DataColumns.DATA4 + " TEXT NOT NULL DEFAULT ''," +
+ DataColumns.DATA5 + " TEXT NOT NULL DEFAULT ''" +
+ ")";
+
+ private static final String CREATE_DATA_NOTE_ID_INDEX_SQL =
+ "CREATE INDEX IF NOT EXISTS note_id_index ON " +
+ TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
+
+ /**
+ * Increase folder's note count when move note to the folder
+ */
+ private static final String NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
+ "CREATE TRIGGER increase_folder_count_on_update "+
+ " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
+ " BEGIN " +
+ " UPDATE " + TABLE.NOTE +
+ " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
+ " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
+ " END";
+
+ /**
+ * Decrease folder's note count when move note from folder
+ */
+ private static final String NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER =
+ "CREATE TRIGGER decrease_folder_count_on_update " +
+ " AFTER UPDATE OF " + NoteColumns.PARENT_ID + " ON " + TABLE.NOTE +
+ " BEGIN " +
+ " UPDATE " + TABLE.NOTE +
+ " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
+ " WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
+ " AND " + NoteColumns.NOTES_COUNT + ">0" + ";" +
+ " END";
+
+ /**
+ * Increase folder's note count when insert new note to the folder
+ */
+ private static final String NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER =
+ "CREATE TRIGGER increase_folder_count_on_insert " +
+ " AFTER INSERT ON " + TABLE.NOTE +
+ " BEGIN " +
+ " UPDATE " + TABLE.NOTE +
+ " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + " + 1" +
+ " WHERE " + NoteColumns.ID + "=new." + NoteColumns.PARENT_ID + ";" +
+ " END";
+
+ /**
+ * Decrease folder's note count when delete note from the folder
+ */
+ private static final String NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER =
+ "CREATE TRIGGER decrease_folder_count_on_delete " +
+ " AFTER DELETE ON " + TABLE.NOTE +
+ " BEGIN " +
+ " UPDATE " + TABLE.NOTE +
+ " SET " + NoteColumns.NOTES_COUNT + "=" + NoteColumns.NOTES_COUNT + "-1" +
+ " WHERE " + NoteColumns.ID + "=old." + NoteColumns.PARENT_ID +
+ " AND " + NoteColumns.NOTES_COUNT + ">0;" +
+ " END";
+
+ /**
+ * Update note's content when insert data with type {@link DataConstants#NOTE}
+ */
+ private static final String DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER =
+ "CREATE TRIGGER update_note_content_on_insert " +
+ " AFTER INSERT ON " + TABLE.DATA +
+ " WHEN new." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
+ " BEGIN" +
+ " UPDATE " + TABLE.NOTE +
+ " SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
+ " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
+ " END";
+
+ /**
+ * Update note's content when data with {@link DataConstants#NOTE} type has changed
+ */
+ private static final String DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER =
+ "CREATE TRIGGER update_note_content_on_update " +
+ " AFTER UPDATE ON " + TABLE.DATA +
+ " WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
+ " BEGIN" +
+ " UPDATE " + TABLE.NOTE +
+ " SET " + NoteColumns.SNIPPET + "=new." + DataColumns.CONTENT +
+ " WHERE " + NoteColumns.ID + "=new." + DataColumns.NOTE_ID + ";" +
+ " END";
+
+ /**
+ * Update note's content when data with {@link DataConstants#NOTE} type has deleted
+ */
+ private static final String DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER =
+ "CREATE TRIGGER update_note_content_on_delete " +
+ " AFTER delete ON " + TABLE.DATA +
+ " WHEN old." + DataColumns.MIME_TYPE + "='" + DataConstants.NOTE + "'" +
+ " BEGIN" +
+ " UPDATE " + TABLE.NOTE +
+ " SET " + NoteColumns.SNIPPET + "=''" +
+ " WHERE " + NoteColumns.ID + "=old." + DataColumns.NOTE_ID + ";" +
+ " END";
+
+ /**
+ * Delete datas belong to note which has been deleted
+ */
+ private static final String NOTE_DELETE_DATA_ON_DELETE_TRIGGER =
+ "CREATE TRIGGER delete_data_on_delete " +
+ " AFTER DELETE ON " + TABLE.NOTE +
+ " BEGIN" +
+ " DELETE FROM " + TABLE.DATA +
+ " WHERE " + DataColumns.NOTE_ID + "=old." + NoteColumns.ID + ";" +
+ " END";
+
+ /**
+ * Delete notes belong to folder which has been deleted
+ */
+ private static final String FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER =
+ "CREATE TRIGGER folder_delete_notes_on_delete " +
+ " AFTER DELETE ON " + TABLE.NOTE +
+ " BEGIN" +
+ " DELETE FROM " + TABLE.NOTE +
+ " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
+ " END";
+
+ /**
+ * Move notes belong to folder which has been moved to trash folder
+ */
+ private static final String FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER =
+ "CREATE TRIGGER folder_move_notes_on_trash " +
+ " AFTER UPDATE ON " + TABLE.NOTE +
+ " WHEN new." + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
+ " BEGIN" +
+ " UPDATE " + TABLE.NOTE +
+ " SET " + NoteColumns.PARENT_ID + "=" + Notes.ID_TRASH_FOLER +
+ " WHERE " + NoteColumns.PARENT_ID + "=old." + NoteColumns.ID + ";" +
+ " END";
+
+ public NotesDatabaseHelper(Context context) {
+ super(context, DB_NAME, null, DB_VERSION);
+ }
+
+ public void createNoteTable(SQLiteDatabase db) {
+ db.execSQL(CREATE_NOTE_TABLE_SQL);
+ reCreateNoteTableTriggers(db);
+ createSystemFolder(db);
+ Log.d(TAG, "note table has been created");
+ }
+
+ private void reCreateNoteTableTriggers(SQLiteDatabase db) {
+ db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_update");
+ db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_update");
+ db.execSQL("DROP TRIGGER IF EXISTS decrease_folder_count_on_delete");
+ db.execSQL("DROP TRIGGER IF EXISTS delete_data_on_delete");
+ db.execSQL("DROP TRIGGER IF EXISTS increase_folder_count_on_insert");
+ db.execSQL("DROP TRIGGER IF EXISTS folder_delete_notes_on_delete");
+ db.execSQL("DROP TRIGGER IF EXISTS folder_move_notes_on_trash");
+
+ db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
+ db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_UPDATE_TRIGGER);
+ db.execSQL(NOTE_DECREASE_FOLDER_COUNT_ON_DELETE_TRIGGER);
+ db.execSQL(NOTE_DELETE_DATA_ON_DELETE_TRIGGER);
+ db.execSQL(NOTE_INCREASE_FOLDER_COUNT_ON_INSERT_TRIGGER);
+ db.execSQL(FOLDER_DELETE_NOTES_ON_DELETE_TRIGGER);
+ db.execSQL(FOLDER_MOVE_NOTES_ON_TRASH_TRIGGER);
+ }
+
+ private void createSystemFolder(SQLiteDatabase db) {
+ ContentValues values = new ContentValues();
+
+ /**
+ * call record foler for call notes
+ */
+ values.put(NoteColumns.ID, Notes.ID_CALL_RECORD_FOLDER);
+ values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
+ db.insert(TABLE.NOTE, null, values);
+
+ /**
+ * root folder which is default folder
+ */
+ values.clear();
+ values.put(NoteColumns.ID, Notes.ID_ROOT_FOLDER);
+ values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
+ db.insert(TABLE.NOTE, null, values);
+
+ /**
+ * temporary folder which is used for moving note
+ */
+ values.clear();
+ values.put(NoteColumns.ID, Notes.ID_TEMPARAY_FOLDER);
+ values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
+ db.insert(TABLE.NOTE, null, values);
+
+ /**
+ * create trash folder
+ */
+ values.clear();
+ values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
+ values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
+ db.insert(TABLE.NOTE, null, values);
+ }
+
+ public void createDataTable(SQLiteDatabase db) {
+ db.execSQL(CREATE_DATA_TABLE_SQL);
+ reCreateDataTableTriggers(db);
+ db.execSQL(CREATE_DATA_NOTE_ID_INDEX_SQL);
+ Log.d(TAG, "data table has been created");
+ }
+
+ private void reCreateDataTableTriggers(SQLiteDatabase db) {
+ db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_insert");
+ db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_update");
+ db.execSQL("DROP TRIGGER IF EXISTS update_note_content_on_delete");
+
+ db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_INSERT_TRIGGER);
+ db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_UPDATE_TRIGGER);
+ db.execSQL(DATA_UPDATE_NOTE_CONTENT_ON_DELETE_TRIGGER);
+ }
+
+ static synchronized NotesDatabaseHelper getInstance(Context context) {
+ if (mInstance == null) {
+ mInstance = new NotesDatabaseHelper(context);
+ }
+ return mInstance;
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ createNoteTable(db);
+ createDataTable(db);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ boolean reCreateTriggers = false;
+ boolean skipV2 = false;
+
+ if (oldVersion == 1) {
+ upgradeToV2(db);
+ skipV2 = true; // this upgrade including the upgrade from v2 to v3
+ oldVersion++;
+ }
+
+ if (oldVersion == 2 && !skipV2) {
+ upgradeToV3(db);
+ reCreateTriggers = true;
+ oldVersion++;
+ }
+
+ if (oldVersion == 3) {
+ upgradeToV4(db);
+ oldVersion++;
+ }
+ if(oldVersion == 4){
+ upgradeToV5(db);
+ oldVersion++;
+ }
+
+ if (reCreateTriggers) {
+ reCreateNoteTableTriggers(db);
+ reCreateDataTableTriggers(db);
+ }
+
+ if (oldVersion != newVersion) {
+ throw new IllegalStateException("Upgrade notes database to version " + newVersion
+ + "fails");
+ }
+ }
+
+ private void upgradeToV2(SQLiteDatabase db) {
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE.NOTE);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE.DATA);
+ createNoteTable(db);
+ createDataTable(db);
+ }
+
+ private void upgradeToV3(SQLiteDatabase db) {
+ // drop unused triggers
+ db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_insert");
+ db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_delete");
+ db.execSQL("DROP TRIGGER IF EXISTS update_note_modified_date_on_update");
+ // add a column for gtask id
+ db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.GTASK_ID
+ + " TEXT NOT NULL DEFAULT ''");
+ // add a trash system folder
+ ContentValues values = new ContentValues();
+ values.put(NoteColumns.ID, Notes.ID_TRASH_FOLER);
+ values.put(NoteColumns.TYPE, Notes.TYPE_SYSTEM);
+ db.insert(TABLE.NOTE, null, values);
+ }
+
+ private void upgradeToV4(SQLiteDatabase db) {
+ db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.VERSION
+ + " INTEGER NOT NULL DEFAULT 0");
+ }
+ private void upgradeToV5(SQLiteDatabase db){
+ db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.PASSWORD
+ + " TEXT DEFAULT NULL ");
+ }
+
+}
diff --git a/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java b/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
new file mode 100644
index 0000000..0ea27b7
--- /dev/null
+++ b/src/main/java/net/micode/notes/gtask/remote/GTaskASyncTask.java
@@ -0,0 +1,123 @@
+
+/*
+ * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.micode.notes.gtask.remote;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.os.AsyncTask;
+
+import net.micode.notes.R;
+import net.micode.notes.ui.NotesListActivity;
+import net.micode.notes.ui.NotesPreferenceActivity;
+
+
+public class GTaskASyncTask extends AsyncTask {
+
+ private static int GTASK_SYNC_NOTIFICATION_ID = 5234235;
+
+ public interface OnCompleteListener {
+ void onComplete();
+ }
+
+ private Context mContext;
+
+ private NotificationManager mNotifiManager;
+
+ private GTaskManager mTaskManager;
+
+ private OnCompleteListener mOnCompleteListener;
+
+ public GTaskASyncTask(Context context, OnCompleteListener listener) {
+ mContext = context;
+ mOnCompleteListener = listener;
+ mNotifiManager = (NotificationManager) mContext
+ .getSystemService(Context.NOTIFICATION_SERVICE);
+ mTaskManager = GTaskManager.getInstance();
+ }
+
+ public void cancelSync() {
+ mTaskManager.cancelSync();
+ }
+
+ public void publishProgess(String message) {
+ publishProgress(new String[] {
+ message
+ });
+ }
+
+ private void showNotification(int tickerId, String content) {
+ Notification notification = new Notification(R.drawable.notification, mContext
+ .getString(tickerId), System.currentTimeMillis());
+ notification.defaults = Notification.DEFAULT_LIGHTS;
+ notification.flags = Notification.FLAG_AUTO_CANCEL;
+ PendingIntent pendingIntent;
+ if (tickerId != R.string.ticker_success) {
+ pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
+ NotesPreferenceActivity.class), 0);
+
+ } else {
+ pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(mContext,
+ NotesListActivity.class), 0);
+ }
+// notification.setLatestEventInfo(mContext, mContext.getString(R.string.app_name), content,
+// pendingIntent);
+ mNotifiManager.notify(GTASK_SYNC_NOTIFICATION_ID, notification);
+ }
+
+ @Override
+ protected Integer doInBackground(Void... unused) {
+ publishProgess(mContext.getString(R.string.sync_progress_login, NotesPreferenceActivity
+ .getSyncAccountName(mContext)));
+ return mTaskManager.sync(mContext, this);
+ }
+
+ @Override
+ protected void onProgressUpdate(String... progress) {
+ showNotification(R.string.ticker_syncing, progress[0]);
+ if (mContext instanceof GTaskSyncService) {
+ ((GTaskSyncService) mContext).sendBroadcast(progress[0]);
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Integer result) {
+ if (result == GTaskManager.STATE_SUCCESS) {
+ showNotification(R.string.ticker_success, mContext.getString(
+ R.string.success_sync_account, mTaskManager.getSyncAccount()));
+ NotesPreferenceActivity.setLastSyncTime(mContext, System.currentTimeMillis());
+ } else if (result == GTaskManager.STATE_NETWORK_ERROR) {
+ showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_network));
+ } else if (result == GTaskManager.STATE_INTERNAL_ERROR) {
+ showNotification(R.string.ticker_fail, mContext.getString(R.string.error_sync_internal));
+ } else if (result == GTaskManager.STATE_SYNC_CANCELLED) {
+ showNotification(R.string.ticker_cancel, mContext
+ .getString(R.string.error_sync_cancelled));
+ }
+ if (mOnCompleteListener != null) {
+ new Thread(new Runnable() {
+
+ public void run() {
+ mOnCompleteListener.onComplete();
+ }
+ }).start();
+ }
+ }
+}
diff --git a/src/main/java/net/micode/notes/model/WorkingNote.java b/src/main/java/net/micode/notes/model/WorkingNote.java
index 4fd3cf6..7733b4b 100644
--- a/src/main/java/net/micode/notes/model/WorkingNote.java
+++ b/src/main/java/net/micode/notes/model/WorkingNote.java
@@ -50,8 +50,9 @@ import net.micode.notes.tool.ResourceParser.NoteBgResources;
*/
public class WorkingNote {
// Note for the working note
- //这个在Note里面定义了Note类的基本类型,
- private Note mNote;
+
+ private String mPassword;
+ private Note mNote;//这个在Note里面定义了Note类的基本类型,
// Note Id
private long mNoteId;
// Note content
@@ -60,31 +61,25 @@ public class WorkingNote {
private int mMode;
private long mAlertDate;
- //最后的修改日期
- private long mModifiedDate;
- //定义的颜色的ID
+ private long mModifiedDate;//最后的修改日期
- private int mBgColorId;
+ private int mBgColorId;//定义的颜色的ID
- //定义了一个int类型,用来定位到哪一个小组件被使用
- private int mWidgetId;
+ private int mWidgetId;//定义了一个int类型,用来定位到哪一个小组件被使用
- //定义了一个int类型,用来区分使用了什么类型的小组件
- private int mWidgetType;
+ private int mWidgetType;//定义了一个int类型,用来区分使用了什么类型的小组件
- //用来定位便签放在哪个文件夹
- private long mFolderId;
+ private long mFolderId;//用来定位便签放在哪个文件夹
private Context mContext;
- //定义为静态变量,保证不能再被更改。防止数据出现异常
- private static final String TAG = "WorkingNote";
+ public boolean PRIVATE_MODE = false;
+ private static final String TAG = "WorkingNote"; //定义为静态变量,保证不能再被更改。防止数据出现异常
+
+ private boolean mIsDeleted; //定义一个布尔变量,用来保存是否要被删除。通过查看用法,发现在后面保存|修改的时候要进行判断。
- //定义一个布尔变量,用来保存是否要被删除。通过查看用法,发现在后面保存|修改的时候要进行判断。
- private boolean mIsDeleted;
- //定义了一个接口,具体是在NoteEditActivities中实现,实现对于便签是否修改的监听
- private NoteSettingChangedListener mNoteSettingStatusListener;
+ private NoteSettingChangedListener mNoteSettingStatusListener;//定义了一个接口,具体是在NoteEditActivities中实现,实现对于便签是否修改的监听
/**
* 定义一个数组,保存DataColumn数组当中的一些列变量。关于DataColumn的注解我写在了定义处。
* 之所以用一个字符串数组来调用DataColumn接口,是为了“方便在进行数据库操作时可以一次性指定需要查询的列”?
@@ -94,8 +89,7 @@ public class WorkingNote {
* 在按列查询时,在数据库访问到底,只需要在数组中继续访问即可。关于函数详解我会写在函数的定义处;
*/
public static final String[] DATA_PROJECTION = new String[] {
- //在Note里面定义一个接口类型
- DataColumns.ID,
+ DataColumns.ID,//在Note里面定义一个接口类型
DataColumns.CONTENT,
DataColumns.MIME_TYPE,
DataColumns.DATA1,
@@ -135,18 +129,12 @@ public class WorkingNote {
private static final int NOTE_MODIFIED_DATE_COLUMN = 5;
- /**
- * @method: WorkingNote
- * @description: 初始化一个新的操作的Note
- * @date: 2024/1/6 11:28
- * @author: 周石宇
- * @param: [android.content.Context, long]:[context, folderId]
- * @return:
- */
- private WorkingNote(Context context, long folderId) {
+ // New note construct
+ //初始化一个新的操作的Note
+ private WorkingNote(Context context, long folderId) {
mContext = context;
mAlertDate = 0;//这里为什么是0还存疑
mModifiedDate = System.currentTimeMillis();//获取系统时间,保存给最后修改时间
@@ -203,38 +191,23 @@ public class WorkingNote {
}
loadNoteData();
}
- /**
- * @method: loadNoteData
- * @description: 基本同上一个函数。值得注意的是这里对数据进行了筛选(通过selection),还对MIME进行了判断后加载
- * @date: 2024/1/6 11:29
- * @author: 周石宇
- * @param: []:[]
- * @return: void
- */
+ //基本同上一个函数。值得注意的是这里对数据进行了筛选(通过selection),还对MIME进行了判断后加载
private void loadNoteData() {
-
-
-
- Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
+ Cursor cursor = mContext.getContentResolver().query(Notes.CONTENT_DATA_URI, DATA_PROJECTION,
DataColumns.NOTE_ID + "=?", new String[] {
String.valueOf(mNoteId)
}, null);
if (cursor != null) {
- // 检查是否有数据
if (cursor.moveToFirst()) {
do {
- // 获取类型
String type = cursor.getString(DATA_MIME_TYPE_COLUMN);
if (DataConstants.NOTE.equals(type)) {
- // 获取内容
mContent = cursor.getString(DATA_CONTENT_COLUMN);
- // 获取模式
mMode = cursor.getInt(DATA_MODE_COLUMN);
- // 获取ID
mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN));
+
} else if (DataConstants.CALL_NOTE.equals(type)) {
- // 设置通话ID
mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN));
} else {
Log.d(TAG, "Wrong note type with type:" + type);
@@ -247,49 +220,23 @@ public class WorkingNote {
throw new IllegalArgumentException("Unable to find note's data with id " + mNoteId);
}
}
-
-
- /**
- * @method: createEmptyNote
- * @description: 创建一个空的笔记
- * @date: 2024/1/2 10:21
- * @author: 周石宇
- * @param: [android.content.Context, long, int, int, int]:[context, folderId, widgetId, widgetType, defaultBgColorId]
- * @return: net.micode.notes.model.WorkingNote
- */
-public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
-
+//简单的初始化函数,一会看一下用法
+ public static WorkingNote createEmptyNote(Context context, long folderId, int widgetId,
int widgetType, int defaultBgColorId) {
- // 创建一个新的WorkingNote实例
WorkingNote note = new WorkingNote(context, folderId);
- // 设置笔记的背景颜色
note.setBgColorId(defaultBgColorId);
- // 设置笔记的widgetId
note.setWidgetId(widgetId);
- // 设置笔记的widgetType
note.setWidgetType(widgetType);
- // 返回新的WorkingNote实例
return note;
}
public static WorkingNote load(Context context, long id) {
return new WorkingNote(context, id, 0);
}
- /**
- * @method: saveNote
- * @description: 保存笔记
- * @date: 2024/1/2 10:23
- * @author: 周石宇
- * @param: []:[]
- * @return: boolean
- */
-public synchronized boolean saveNote() {
-
- // 如果笔记 worth saving
+//这里涉及了多线程的操作。
+ public synchronized boolean saveNote() {
if (isWorthSaving()) {
- // 如果笔记不存在数据库中
if (!existInDatabase()) {
- // 获取新笔记id
if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {
Log.e(TAG, "Create new note fail with id:" + mNoteId);
return false;
@@ -322,18 +269,7 @@ public synchronized boolean saveNote() {
return mNoteId > 0;
}
- /**
- * @method: isWorthSaving
- * @description: 判断是否值得保存,即判断是否需要保存到数据库
- * @date: 2024/1/2 10:24
- * @author: 周石宇
- * @param: []:[]
- * @return: boolean
- */
private boolean isWorthSaving() {
-
-
-
if (mIsDeleted || (!existInDatabase() && TextUtils.isEmpty(mContent))
|| (existInDatabase() && !mNote.isLocalModified())) {
return false;
@@ -341,19 +277,8 @@ public synchronized boolean saveNote() {
return true;
}
}
- /**
- * @method: setOnSettingStatusChangedListener
- * @description: 用来记录状态设定是否有发生过更改。
- * @date: 2024/1/2 10:24
- * @author: 周石宇
- * @param: [net.micode.notes.model.WorkingNote.NoteSettingChangedListener]:[l]
- * @return: void
- */
-
+//这个变量设置是用来记录状态设定是否有发生过更改。
public void setOnSettingStatusChangedListener(NoteSettingChangedListener l) {
-
-
-
mNoteSettingStatusListener = l;
}
@@ -384,18 +309,8 @@ public synchronized boolean saveNote() {
mNote.setNoteValue(NoteColumns.BG_COLOR_ID, String.valueOf(id));
}
}
- /**
- * @method: setCheckListMode
- * @description: 在EditActivities中使用,用来设定在list时的状态
- * @date: 2024/1/6 11:30
- * @author: 周石宇
- * @param: [int]:[mode]
- * @return: void
- */
+//在EditActivities中使用,用来设定在list时的状态
public void setCheckListMode(int mode) {
-
-
-
if (mMode != mode) {
if (mNoteSettingStatusListener != null) {
mNoteSettingStatusListener.onCheckListModeChanged(mMode, mode);
@@ -439,6 +354,10 @@ public synchronized boolean saveNote() {
mNote.setCallData(CallNote.PHONE_NUMBER, phoneNumber);
mNote.setNoteValue(NoteColumns.PARENT_ID, String.valueOf(Notes.ID_CALL_RECORD_FOLDER));
}
+ public void setPassword(String password){
+// mPassword=password;
+ mNote.setNoteValue(NoteColumns.PASSWORD,password);
+ }
public boolean hasClockAlert() {
return (mAlertDate > 0 ? true : false);
@@ -487,6 +406,8 @@ public synchronized boolean saveNote() {
public int getWidgetType() {
return mWidgetType;
}
+
+ public String getPassword() { return mPassword; }
//声明了一个接口,具体都在EditActivies中进行实现。主要是一个监听(listener),来设置各个量的改变
public interface NoteSettingChangedListener {
/**
diff --git a/src/main/java/net/micode/notes/tool/ResourceParser.java b/src/main/java/net/micode/notes/tool/ResourceParser.java
index 1ad3ad6..6f8b4b0 100644
--- a/src/main/java/net/micode/notes/tool/ResourceParser.java
+++ b/src/main/java/net/micode/notes/tool/ResourceParser.java
@@ -30,6 +30,8 @@ public class ResourceParser {
public static final int GREEN = 3;
public static final int RED = 4;
+ public static final int DUCK = 5;
+
public static final int BG_DEFAULT_COLOR = YELLOW;
public static final int TEXT_SMALL = 0;
@@ -45,7 +47,10 @@ public class ResourceParser {
R.drawable.edit_blue,
R.drawable.edit_white,
R.drawable.edit_green,
- R.drawable.edit_red
+ R.drawable.edit_red,
+ R.drawable.note_bg_photo_wangyi
+
+
};
private final static int [] BG_EDIT_TITLE_RESOURCES = new int [] {
@@ -53,7 +58,9 @@ public class ResourceParser {
R.drawable.edit_title_blue,
R.drawable.edit_title_white,
R.drawable.edit_title_green,
- R.drawable.edit_title_red
+ R.drawable.edit_title_red,
+ R.drawable.note_bg_photo_wangyi
+
};
public static int getNoteBgResource(int id) {
@@ -80,7 +87,8 @@ public class ResourceParser {
R.drawable.list_blue_up,
R.drawable.list_white_up,
R.drawable.list_green_up,
- R.drawable.list_red_up
+ R.drawable.list_red_up,
+ R.drawable.note_bg_photo_wangyi
};
private final static int [] BG_NORMAL_RESOURCES = new int [] {
@@ -88,7 +96,8 @@ public class ResourceParser {
R.drawable.list_blue_middle,
R.drawable.list_white_middle,
R.drawable.list_green_middle,
- R.drawable.list_red_middle
+ R.drawable.list_red_middle,
+ R.drawable.note_bg_photo_wangyi
};
private final static int [] BG_LAST_RESOURCES = new int [] {
@@ -97,6 +106,7 @@ public class ResourceParser {
R.drawable.list_white_down,
R.drawable.list_green_down,
R.drawable.list_red_down,
+ R.drawable.note_bg_photo_wangyi
};
private final static int [] BG_SINGLE_RESOURCES = new int [] {
@@ -104,7 +114,8 @@ public class ResourceParser {
R.drawable.list_blue_single,
R.drawable.list_white_single,
R.drawable.list_green_single,
- R.drawable.list_red_single
+ R.drawable.list_red_single,
+ R.drawable.note_bg_photo_wangyi
};
public static int getNoteBgFirstRes(int id) {
diff --git a/src/main/java/net/micode/notes/ui/ChangeLoginPasswordActivity.java b/src/main/java/net/micode/notes/ui/ChangeLoginPasswordActivity.java
new file mode 100644
index 0000000..6925781
--- /dev/null
+++ b/src/main/java/net/micode/notes/ui/ChangeLoginPasswordActivity.java
@@ -0,0 +1,127 @@
+package net.micode.notes.ui;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.AlertDialog;
+import android.app.PendingIntent;
+import android.app.SearchManager;
+import android.appwidget.AppWidgetManager;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.preference.PreferenceManager;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.text.style.BackgroundColorSpan;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import net.micode.notes.R;
+import net.micode.notes.data.Notes;
+import net.micode.notes.data.Notes.TextNote;
+import net.micode.notes.model.WorkingNote;
+import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
+import net.micode.notes.tool.DataUtils;
+import net.micode.notes.tool.ResourceParser;
+import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
+import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
+import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
+import net.micode.notes.widget.NoteWidgetProvider_2x;
+import net.micode.notes.widget.NoteWidgetProvider_4x;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+public class ChangeLoginPasswordActivity extends Activity {
+ EditText OldPassword;
+ EditText NewPassword;
+ EditText ReWritePassword;
+ Button Acknowledged;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.change_login_password_activity);
+ getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
+ | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+ OldPassword=(EditText) findViewById(R.id.old_password);
+ NewPassword=(EditText) findViewById(R.id.new_password);
+ ReWritePassword=(EditText) findViewById(R.id.ack_password);
+ Acknowledged=(Button)findViewById(R.id.Bt_Acknowledged);
+ Acknowledged.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String old_password = OldPassword.getText().toString();
+ String new_password = NewPassword.getText().toString();
+ String ack_password = ReWritePassword.getText().toString();
+
+ SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
+
+ String login_password=pref.getString("password","");
+
+ if(old_password.equals("")==true || new_password.equals("")==true || ack_password.equals("")==true) {
+ Toast.makeText(ChangeLoginPasswordActivity.this, "密码不能为空", Toast.LENGTH_SHORT).show();
+ }else if (new_password.equals(ack_password) == false) {
+ Toast.makeText(ChangeLoginPasswordActivity.this, "新建密码与重复密码不匹配,请重新输入密码", Toast.LENGTH_SHORT).show();
+ ReWritePassword.setText("");
+ }else if(old_password.equals(login_password) == false){
+ Toast.makeText(ChangeLoginPasswordActivity.this, "原有密码错误,请重新输入密码", Toast.LENGTH_SHORT).show();
+ OldPassword.setText("");
+ }
+ else if (new_password.equals(ack_password) == true && old_password.equals(login_password) == true){
+ SharedPreferences.Editor editor=getSharedPreferences("user management", MODE_PRIVATE).edit();
+ editor.putString("password",new_password);
+ editor.apply();
+ Toast.makeText(ChangeLoginPasswordActivity.this, "修改密码成功", Toast.LENGTH_SHORT).show();
+ Intent intent=new Intent(ChangeLoginPasswordActivity.this, LoginActivity.class);
+ startActivity(intent);
+ finish();
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onBackPressed() {
+ Intent intent=new Intent(ChangeLoginPasswordActivity.this, LoginActivity.class);
+ startActivity(intent);
+ finish();
+ }
+}
+
diff --git a/src/main/java/net/micode/notes/ui/LoginActivity.java b/src/main/java/net/micode/notes/ui/LoginActivity.java
new file mode 100644
index 0000000..caae81f
--- /dev/null
+++ b/src/main/java/net/micode/notes/ui/LoginActivity.java
@@ -0,0 +1,163 @@
+package net.micode.notes.ui;
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.AlertDialog;
+import android.app.PendingIntent;
+import android.app.ProgressDialog;
+import android.app.SearchManager;
+import android.appwidget.AppWidgetManager;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.text.style.BackgroundColorSpan;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import net.micode.notes.R;
+import net.micode.notes.data.Notes;
+import net.micode.notes.data.Notes.TextNote;
+import net.micode.notes.model.WorkingNote;
+import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
+import net.micode.notes.tool.DataUtils;
+import net.micode.notes.tool.ResourceParser;
+import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
+import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
+import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
+import net.micode.notes.widget.NoteWidgetProvider_2x;
+import net.micode.notes.widget.NoteWidgetProvider_4x;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+public class LoginActivity extends Activity{
+ private EditText accountEdit;
+
+ private EditText passwordEdit;
+
+ private Button login;
+
+ private Button cancel;
+
+ private Button change;
+
+ private long last_login_time = 0 ;
+
+ public static final long MAX_LOGIN_TIME = 9999999;
+
+
+
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState){
+ super.onCreate(savedInstanceState);
+
+ SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
+ boolean user_boolean = pref.getBoolean("user",false);//获取用户是否设置了密码
+ if(!user_boolean) //User_boolean = false时,(没有设置密码),直接跳转到便签主界面
+ {
+ SharedPreferences.Editor editor=getSharedPreferences("user management", MODE_PRIVATE).edit();
+ editor.putString("password","123456");
+ editor.putBoolean("user",true);
+ editor.apply();
+ }
+
+ SharedPreferences login_time_get = getSharedPreferences("login time",MODE_PRIVATE);
+ boolean is_first_login = login_time_get.getBoolean("is_first_login",false);
+
+ setContentView(R.layout.login_activity);
+ accountEdit = (EditText) findViewById(R.id.account);
+ passwordEdit = (EditText) findViewById(R.id.password);
+ login = (Button) findViewById(R.id.login);
+ cancel = (Button) findViewById(R.id.cancel);
+ change = (Button) findViewById(R.id.change_password);
+
+
+ long current_time = System.currentTimeMillis();
+
+ cancel.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Toast.makeText(LoginActivity.this, R.string.app_already_quit, Toast.LENGTH_LONG).show();
+ finish();
+ }
+ });
+
+ Long current_login_time = login_time_get.getLong("current login time",0);
+ if((is_first_login)&&(current_time - current_login_time <= MAX_LOGIN_TIME)){
+ SharedPreferences.Editor editor=getSharedPreferences("login time", MODE_PRIVATE).edit();
+ editor.putLong("current login time",System.currentTimeMillis());
+ editor.apply();
+ Intent intent = new Intent(LoginActivity.this,NotesListActivity.class);
+ startActivity(intent);
+ finish();
+ }
+
+ else{
+ if(!is_first_login){
+ SharedPreferences.Editor editor=getSharedPreferences("login time", MODE_PRIVATE).edit();
+ editor.putLong("current login time",System.currentTimeMillis());
+ editor.putBoolean("is_first_login",true);
+ editor.apply();
+ }
+
+ login.setOnClickListener(new View.OnClickListener(){
+ public void onClick(View v) {
+ String account = accountEdit.getText().toString();
+ String password = passwordEdit.getText().toString();
+
+ SharedPreferences pref=getSharedPreferences("user management",MODE_PRIVATE);
+ String share_password=pref.getString("password","");
+
+ if(account.equals("hei") && password.equals(share_password)){
+ ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this);
+ progressDialog.setTitle(R.string.Loading);
+ progressDialog.setMessage("Loading...");
+ progressDialog.setCancelable(true);
+ progressDialog.show();;
+ Intent intent = new Intent(LoginActivity.this,NotesListActivity.class);
+ startActivity(intent);
+ finish();
+ }else {
+ Toast.makeText(LoginActivity.this, R.string.invalid,Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+
+ change.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(LoginActivity.this,ChangeLoginPasswordActivity.class);
+ startActivity(intent);
+ finish();
+ }
+ });
+ }
+ }
+}
diff --git a/src/main/java/net/micode/notes/ui/LoginView.java b/src/main/java/net/micode/notes/ui/LoginView.java
new file mode 100644
index 0000000..deca847
--- /dev/null
+++ b/src/main/java/net/micode/notes/ui/LoginView.java
@@ -0,0 +1,76 @@
+package net.micode.notes.ui;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.AlertDialog;
+import android.app.PendingIntent;
+import android.app.SearchManager;
+import android.appwidget.AppWidgetManager;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.graphics.Paint;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceManager;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.TextUtils;
+import android.text.format.DateUtils;
+import android.text.style.BackgroundColorSpan;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.CompoundButton.OnCheckedChangeListener;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import net.micode.notes.R;
+import net.micode.notes.data.Notes;
+import net.micode.notes.data.Notes.TextNote;
+import net.micode.notes.model.WorkingNote;
+import net.micode.notes.model.WorkingNote.NoteSettingChangedListener;
+import net.micode.notes.tool.DataUtils;
+import net.micode.notes.tool.ResourceParser;
+import net.micode.notes.tool.ResourceParser.TextAppearanceResources;
+import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
+import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
+import net.micode.notes.widget.NoteWidgetProvider_2x;
+import net.micode.notes.widget.NoteWidgetProvider_4x;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+public class LoginView extends Activity
+{
+ Handler mHandler=new Handler();
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.login_view);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ Intent intent = new Intent(LoginView.this, LoginActivity.class);
+ startActivity(intent);
+ finish();
+ }
+ },2000);
+ }
+}
diff --git a/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/src/main/java/net/micode/notes/ui/NoteEditActivity.java
index 99f2b4a..2242cb9 100644
--- a/src/main/java/net/micode/notes/ui/NoteEditActivity.java
+++ b/src/main/java/net/micode/notes/ui/NoteEditActivity.java
@@ -29,6 +29,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Paint;
+import android.graphics.Typeface;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.Spannable;
@@ -70,6 +71,7 @@ import net.micode.notes.widget.NoteWidgetProvider_4x;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -93,6 +95,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorBtnsMap.put(R.id.iv_bg_blue, ResourceParser.BLUE);
sBgSelectorBtnsMap.put(R.id.iv_bg_green, ResourceParser.GREEN);
sBgSelectorBtnsMap.put(R.id.iv_bg_white, ResourceParser.WHITE);
+ sBgSelectorBtnsMap.put(R.id.iv_ph_duck, ResourceParser.DUCK);
+
}
private static final Map sBgSelectorSelectionMap = new HashMap();
@@ -102,8 +106,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
sBgSelectorSelectionMap.put(ResourceParser.BLUE, R.id.iv_bg_blue_select);
sBgSelectorSelectionMap.put(ResourceParser.GREEN, R.id.iv_bg_green_select);
sBgSelectorSelectionMap.put(ResourceParser.WHITE, R.id.iv_bg_white_select);
- }
+ sBgSelectorSelectionMap.put(ResourceParser.DUCK, R.id.iv_ph_duck_select);
+ }//
+ //选择便签字体大小的界选择器的吧
private static final Map sFontSizeBtnsMap = new HashMap();
static {
sFontSizeBtnsMap.put(R.id.ll_font_large, ResourceParser.TEXT_LARGE);
@@ -271,11 +277,20 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private void initNoteScreen() {
+
+ String defaultText = getIntent().getStringExtra(Notes.INTENT_EXTRA_TEMPLE_TEXT);
+ if(defaultText!=null){
+ saveNote();//否则会增加一个null的奇怪现象
+ mWorkingNote.setWorkingText(mWorkingNote.getContent()+defaultText);
+ mNoteEditor.setText(mWorkingNote.getContent()); // 将defaultText的值写入到笔记编辑器中
+ }
+// Toast.makeText(getApplicationContext(), defaultText, Toast.LENGTH_SHORT).show();
mNoteEditor.setTextAppearance(this, TextAppearanceResources
.getTexAppearanceResource(mFontSizeId));
if (mWorkingNote.getCheckListMode() == TextNote.MODE_CHECK_LIST) {
switchToListMode(mWorkingNote.getContent());
} else {
+ ;
mNoteEditor.setText(getHighlightQueryResult(mWorkingNote.getContent(), mUserQuery));
mNoteEditor.setSelection(mNoteEditor.getText().length());
}
diff --git a/src/main/java/net/micode/notes/ui/NotesListActivity.java b/src/main/java/net/micode/notes/ui/NotesListActivity.java
index a3e347a..40f36ff 100644
--- a/src/main/java/net/micode/notes/ui/NotesListActivity.java
+++ b/src/main/java/net/micode/notes/ui/NotesListActivity.java
@@ -77,16 +77,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashSet;
-/**
- * @class: NotesListActivity
- * @extends: Activity
- * @implements: OnClickListener, OnItemLongClickListener
- * @description: 主要实现小米便签刚进入界面。该类为一种main Activity,(xml中有定义)覆盖点击事件监听及长按事件监听类。。
- * @author: 王毅
- * @date: 2024/1/5 16:17
- */
-public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
+public class NotesListActivity extends Activity implements OnClickListener, OnItemLongClickListener {
private static final int FOLDER_NOTE_LIST_QUERY_TOKEN = 0;
private static final int FOLDER_LIST_QUERY_TOKEN = 1;
@@ -143,19 +135,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
private final static int REQUEST_CODE_OPEN_NODE = 102;
private final static int REQUEST_CODE_NEW_NODE = 103;
- /**
- * @method: onCreate
- * @description: 创建Activity,启动其生命周期。完成设置界面样式、初始化资源、且在用户第一次使用App时进行介绍
- * @date: 2024/1/2 10:26
- * @author: 王毅
- * @param: [android.os.Bundle]:[savedInstanceState]
- * @return: void
- */
@Override
protected void onCreate(Bundle savedInstanceState) {
-
-
-
super.onCreate(savedInstanceState);
setContentView(R.layout.note_list);
initResources();
@@ -166,19 +147,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
setAppInfoFromRawRes();
}
- /**
- * @method: onActivityResult
- * @description: intent返回数据接收函数。形参为请求码、结果码、其他intent返回的数据。主要与NoteEditActivity交互
- * @date: 2024/1/2 10:27
- * @author: 高浏洋
- * @param: [int, int, android.content.Intent]:[requestCode, resultCode, data]
- * @return: void
- */
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-
-
-
if (resultCode == RESULT_OK
&& (requestCode == REQUEST_CODE_OPEN_NODE || requestCode == REQUEST_CODE_NEW_NODE)) {
mNotesListAdapter.changeCursor(null);
@@ -187,38 +157,19 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
- /**
- * @method: setAppInfoFromRawRes
- * @description: 第一次使用App时调用,显示introduction。
- * @date: 2024/1/5 16:18
- * @author: 高浏洋
- * @param: []:[]
- * @return: void
- */
private void setAppInfoFromRawRes() {
-
-
-
-
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (!sp.getBoolean(PREFERENCE_ADD_INTRODUCTION, false)) {
StringBuilder sb = new StringBuilder();
InputStream in = null;
try {
- // 获取资源文件
in = getResources().openRawResource(R.raw.introduction);
if (in != null) {
- // 创建输入流读取器
InputStreamReader isr = new InputStreamReader(in);
- // 创建缓冲流读取器
BufferedReader br = new BufferedReader(isr);
- // 创建字符数组
char [] buf = new char[1024];
- // 定义读取长度
int len = 0;
- // 循环读取
while ((len = br.read(buf)) > 0) {
- // 将读取的字符串添加到字符串缓冲区
sb.append(buf, 0, len);
}
} else {
@@ -244,7 +195,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
ResourceParser.RED);
note.setWorkingText(sb.toString());
if (note.saveNote()) {
- // 保存笔记成功,保存添加笔记的偏好设置
sp.edit().putBoolean(PREFERENCE_ADD_INTRODUCTION, true).commit();
} else {
Log.e(TAG, "Save introduction note error");
@@ -252,35 +202,14 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
}
- /**
- * @method: onStart
- * @description: onCreate调用后回调,此Activity对用户可见。
- * @date: 2024/1/5 16:19
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
+
@Override
protected void onStart() {
-
-
-
super.onStart();
startAsyncNotesListQuery();
}
- /**
- * @method: initResources
- * @description: 初始化资源
- * @date: 2024/1/5 16:20
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
private void initResources() {
-
-
-
mContentResolver = this.getContentResolver();
mBackgroundQueryHandler = new BackgroundQueryHandler(this.getContentResolver());
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
@@ -302,62 +231,30 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
mModeCallBack = new ModeCallback();
}
- /**
- * @class: ModeCallback
- * @implements: ListView.MultiChoiceModeListener, OnMenuItemClickListener
- * @description: 定义了ActionMode的使用。便签长按事件通过ActionMode执行。
- * 便签长按后出现选择(多个)便签删除的菜单栏,其在ActionBar中显示。
- * @author: 王毅
- * @date: 2024/1/5 16:21
- */
private class ModeCallback implements ListView.MultiChoiceModeListener, OnMenuItemClickListener {
-
private DropdownMenu mDropDownMenu;
private ActionMode mActionMode;
private MenuItem mMoveMenu;
- /**
- * @method: onCreateActionMode
- * @description: ActionMode创建函数,形参为创建的ActionMode及需要通过该ActionMode显示的Menu对象
- * @date: 2024/1/5 16:23
- * @author: 高浏阳
- * @param: [android.view.ActionMode, android.view.Menu]:[mode, menu]
- * @return: boolean
- */
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
-
-
-
getMenuInflater().inflate(R.menu.note_list_options, menu);
- // 设置菜单项的点击事件
menu.findItem(R.id.delete).setOnMenuItemClickListener(this);
- // 获取移动菜单
mMoveMenu = menu.findItem(R.id.move);
- // 如果当前文件夹是通话记录文件夹或者用户文件夹的数量为0,则隐藏移动菜单
if (mFocusNoteDataItem.getParentId() == Notes.ID_CALL_RECORD_FOLDER
|| DataUtils.getUserFolderCount(mContentResolver) == 0) {
mMoveMenu.setVisible(false);
} else {
- // 否则显示移动菜单
mMoveMenu.setVisible(true);
- // 设置移动菜单的点击事件
mMoveMenu.setOnMenuItemClickListener(this);
}
- // 保存当前模式
mActionMode = mode;
- // 设置列表选择模式
mNotesListAdapter.setChoiceMode(true);
- // 设置列表不可点击
mNotesListView.setLongClickable(false);
- // 隐藏添加新笔记按钮
mAddNewNote.setVisibility(View.GONE);
- // 创建自定义菜单
View customView = LayoutInflater.from(NotesListActivity.this).inflate(
R.layout.note_list_dropdown_menu, null);
- // 设置自定义菜单
mode.setCustomView(customView);
- // 创建下拉菜单
mDropDownMenu = new DropdownMenu(NotesListActivity.this,
(Button) customView.findViewById(R.id.selection_menu),
R.menu.note_list_dropdown);
@@ -372,31 +269,16 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
- /**
- * @method: updateMenu
- * @description: 用于进行多选(全选)时菜单栏界面的更新
- * @date: 2024/1/5 16:23
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
private void updateMenu() {
-
-
-
- //获取已选择的项数
int selectedCount = mNotesListAdapter.getSelectedCount();
- //根据已选择的项数,设置菜单标题
+ // Update dropdown menu
String format = getResources().getString(R.string.menu_select_title, selectedCount);
mDropDownMenu.setTitle(format);
- //设置菜单中的action_select_all的标题
MenuItem item = mDropDownMenu.findItem(R.id.action_select_all);
if (item != null) {
- //如果已选择全部,则设置action_select_all的标题为menu_deselect_all
if (mNotesListAdapter.isAllSelected()) {
item.setChecked(true);
item.setTitle(R.string.menu_deselect_all);
- //否则设置action_select_all的标题为menu_select_all
} else {
item.setChecked(false);
item.setTitle(R.string.menu_select_all);
@@ -404,100 +286,33 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
-
- /**
- * @method: onPrepareActionMode
- * @description: //重新刷新菜单栏时调用
- * @date: 2024/1/5 16:26
- * @author: 高浏阳
- * @param: [android.view.ActionMode, android.view.Menu]:[mode, menu]
- * @return: boolean
- */
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
-
-
-
// TODO Auto-generated method stub
return false;
}
- /**
- * @method: onActionItemClicked
- * @description: 菜单栏点击动作按钮时调用、形参为ActionMode与点击的菜单项
- * @date: 2024/1/5 16:26
- * @author: 高浏阳
- * @param: [android.view.ActionMode, android.view.MenuItem]:[mode, item]
- * @return: boolean
- */
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
-
-
-
// TODO Auto-generated method stub
return false;
}
- /**
- * @method: onDestroyActionMode
- * @description: 销毁或退出ActionMode时调用
- * @date: 2024/1/5 16:26
- * @author: 高浏阳
- * @param: [android.view.ActionMode]:[mode]
- * @return: void
- */
public void onDestroyActionMode(ActionMode mode) {
-
-
-
mNotesListAdapter.setChoiceMode(false);
mNotesListView.setLongClickable(true);
mAddNewNote.setVisibility(View.VISIBLE);
}
- /**
- * @method: finishActionMode
- * @description: 结束ActionMode时调用
- * @date: 2024/1/5 16:27
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
public void finishActionMode() {
-
-
-
mActionMode.finish();
}
- /**
- * @method: onItemCheckedStateChanged
- * @description: 描述一下方法的作用
- * @date: 2024/1/5 16:27
- * @author: 高浏阳
- * @param: [android.view.ActionMode, int, long, boolean]:[mode, position, id, checked]
- * @return: void
- */
public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
-
-
-
boolean checked) {
mNotesListAdapter.setCheckedItem(position, checked);
updateMenu();
}
- /**
- * @method: onMenuItemClick
- * @description: 菜单项点击时调用。
- * @date: 2024/1/6 11:04
- * @author: 高浏阳
- * @param: [android.view.MenuItem]:[item]
- * @return: boolean
- */
public boolean onMenuItemClick(MenuItem item) {
-
-
-
if (mNotesListAdapter.getSelectedCount() == 0) {
Toast.makeText(NotesListActivity.this, getString(R.string.menu_select_none),
Toast.LENGTH_SHORT).show();
@@ -506,29 +321,21 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
int itemId = item.getItemId();
if (itemId == R.id.delete) {
- // 创建一个AlertDialog.Builder对象,用于构建AlertDialog
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- // 设置标题
builder.setTitle(getString(R.string.alert_title_delete));
- // 设置图标
builder.setIcon(android.R.drawable.ic_dialog_alert);
- // 设置消息
builder.setMessage(getString(R.string.alert_message_delete_notes,
mNotesListAdapter.getSelectedCount()));
- // 设置确定按钮
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
- batchDelete();//批处理删除
+ batchDelete();
}
});
- // 设置取消按钮
builder.setNegativeButton(android.R.string.cancel, null);
- // 显示AlertDialog
builder.show();
} else if (itemId == R.id.move) {
- // 启动移动到文件夹查询
startQueryDestinationFolders();
} else {
return false;
@@ -537,77 +344,61 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
- /**
- * @class: NewNoteOnTouchListener
- * @implements: OnTouchListener
- * @description: 新便签触摸事件监听类。根据触摸事件(比如手在屏幕滑动)修正视图的位置参数
- * @author: 王毅
- * @date: 2024/1/6 11:05
- */
private class NewNoteOnTouchListener implements OnTouchListener {
-
-
-
public boolean onTouch(View v, MotionEvent event) {
- int action = event.getAction();
- if (action == MotionEvent.ACTION_DOWN) {
- //获取当前屏幕的高度
- Display display = getWindowManager().getDefaultDisplay();
- int screenHeight = display.getHeight();
- //获取新建笔记视图的高度
- int newNoteViewHeight = mAddNewNote.getHeight();
- //计算新建笔记视图的起始位置
- int start = screenHeight - newNoteViewHeight;
- //计算当前点击的y坐标
- int eventY = start + (int) event.getY();
- /**
- * Minus TitleBar's height
- */
- //如果当前状态是子文件夹,则减去标题栏的高度
- if (mState == ListEditState.SUB_FOLDER) {
- eventY -= mTitleBar.getHeight();
- start -= mTitleBar.getHeight();
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN: {
+ Display display = getWindowManager().getDefaultDisplay();
+ int screenHeight = display.getHeight();
+ int newNoteViewHeight = mAddNewNote.getHeight();
+ int start = screenHeight - newNoteViewHeight;
+ int eventY = start + (int) event.getY();
+ /**
+ * Minus TitleBar's height
+ */
+ if (mState == ListEditState.SUB_FOLDER) {
+ eventY -= mTitleBar.getHeight();
+ start -= mTitleBar.getHeight();
+ }
+ /**
+ * HACKME:When click the transparent part of "New Note" button, dispatch
+ * the event to the list view behind this button. The transparent part of
+ * "New Note" button could be expressed by formula y=-0.12x+94(Unit:pixel)
+ * and the line top of the button. The coordinate based on left of the "New
+ * Note" button. The 94 represents maximum height of the transparent part.
+ * Notice that, if the background of the button changes, the formula should
+ * also change. This is very bad, just for the UI designer's strong requirement.
+ */
+ if (event.getY() < (event.getX() * (-0.12) + 94)) {
+ View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
+ - mNotesListView.getFooterViewsCount());
+ if (view != null && view.getBottom() > start
+ && (view.getTop() < (start + 94))) {
+ mOriginY = (int) event.getY();
+ mDispatchY = eventY;
+ event.setLocation(event.getX(), mDispatchY);
+ mDispatch = true;
+ return mNotesListView.dispatchTouchEvent(event);
+ }
+ }
+ break;
}
- /**
- * HACKME:When click the transparent part of "New Note" button, dispatch
- * the event to the list view behind this button. The transparent part of
- * "New Note" button could be expressed by formula y=-0.12x+94(Unit:pixel)
- * and the line top of the button. The coordinate based on left of the "New
- * Note" button. The 94 represents maximum height of the transparent part.
- * Notice that, if the background of the button changes, the formula should
- * also change. This is very bad, just for the UI designer's strong requirement.
- */
- if (event.getY() < (event.getX() * (-0.12) + 94)) {
- // 获取最后一个可见的View
- View view = mNotesListView.getChildAt(mNotesListView.getChildCount() - 1
- - mNotesListView.getFooterViewsCount());
- if (view != null && view.getBottom() > start
- && (view.getTop() < (start + 94))) {
- // 记录Y轴的起始位置
- mOriginY = (int) event.getY();
- // 记录Y轴的偏移量
- mDispatchY = eventY;
- // 设置新的坐标
+ case MotionEvent.ACTION_MOVE: {
+ if (mDispatch) {
+ mDispatchY += (int) event.getY() - mOriginY;
event.setLocation(event.getX(), mDispatchY);
- // 设置偏移量
- mDispatch = true;
return mNotesListView.dispatchTouchEvent(event);
}
+ break;
}
- } else if (action == MotionEvent.ACTION_MOVE) {
- // 移动时,将Y坐标值增加
- if (mDispatch) {
- mDispatchY += (int) event.getY() - mOriginY;
- event.setLocation(event.getX(), mDispatchY);
- return mNotesListView.dispatchTouchEvent(event);
- }
- } else {
- // 结束时,将Y坐标值设置为0
- if (mDispatch) {
- event.setLocation(event.getX(), mDispatchY);
- mDispatch = false;
- return mNotesListView.dispatchTouchEvent(event);
+ default: {
+ if (mDispatch) {
+ event.setLocation(event.getX(), mDispatchY);
+ mDispatch = false;
+ return mNotesListView.dispatchTouchEvent(event);
+ }
+ break;
}
}
return false;
@@ -615,19 +406,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
};
- /**
- * @method: startAsyncNotesListQuery
- * @description: 已同步便签查询。当进入一个新文件夹时会向数据库发送查询当前文件夹下的便签请求。返回查询结果。这是一个异步查询进程
- * @date: 2024/1/6 11:06
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
-
private void startAsyncNotesListQuery() {
-
-
-
String selection = (mCurrentFolderId == Notes.ID_ROOT_FOLDER) ? ROOT_FOLDER_SELECTION
: NORMAL_SELECTION;
mBackgroundQueryHandler.startQuery(FOLDER_NOTE_LIST_QUERY_TOKEN, null,
@@ -636,41 +415,18 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}, NoteColumns.TYPE + " DESC," + NoteColumns.MODIFIED_DATE + " DESC");
}
- /**
- * @class: BackgroundQueryHandler
- * @extends: AsyncQueryHandler
- * @description: 背景查询消息处理类。主要功能是将查询后得到的便签在界面显示
- * @author: 王毅
- * @date: 2024/1/6 11:07
- */
-
- private final class BackgroundQueryHandler extends AsyncQueryHandler{
-
+ private final class BackgroundQueryHandler extends AsyncQueryHandler {
public BackgroundQueryHandler(ContentResolver contentResolver) {
super(contentResolver);
}
- /**
- * @method: onQueryComplete
- * @description: 下面就是查询结束后对返回数据的处理,完成界面更新
- * @date: 2024/1/6 11:08
- * @author: 高浏阳
- * @param: [int, java.lang.Object, android.database.Cursor]:[token, cookie, cursor]
- * @return: void
- */
@Override
-
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
-
-
-
switch (token) {
case FOLDER_NOTE_LIST_QUERY_TOKEN:
- // 更新笔记列表适配器
mNotesListAdapter.changeCursor(cursor);
break;
case FOLDER_LIST_QUERY_TOKEN:
- // 如果查询成功,则显示文件夹列表菜单
if (cursor != null && cursor.getCount() > 0) {
showFolderListMenu(cursor);
} else {
@@ -683,66 +439,47 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
-
- /**
- * @method: showFolderListMenu
- * @description: 通过游标显示文件夹列表菜单,功能为移动便签至某个文件件
- * @date: 2024/1/6 11:08
- * @author: 高浏阳
- * @param: [android.database.Cursor]:[cursor]
- * @return: void
- */
private void showFolderListMenu(Cursor cursor) {
-
-
-
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
- // 设置标题
builder.setTitle(R.string.menu_title_select_folder);
- // 创建一个FoldersListAdapter对象
final FoldersListAdapter adapter = new FoldersListAdapter(this, cursor);
- // 设置适配器,并设置点击事件
builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- // 移动选中的笔记到指定文件夹
DataUtils.batchMoveToFolder(mContentResolver,
mNotesListAdapter.getSelectedItemIds(), adapter.getItemId(which));
- // 弹出提示信息
Toast.makeText(
NotesListActivity.this,
getString(R.string.format_move_notes_to_folder,
mNotesListAdapter.getSelectedCount(),
adapter.getFolderName(NotesListActivity.this, which)),
Toast.LENGTH_SHORT).show();
- // 结束ActionMode
mModeCallBack.finishActionMode();
}
});
builder.show();
}
- //创建新便签。主要是创建intent并启动。
private void createNewNote() {
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
}
+ private void createTempelNote(int num){
+ String temple1="Time:\nClass:\nTeacher:\nScore:\n";
+ String temple2="Group:\nLeader:\nNumber:\nScore:\n";
+ String temple3="早操:\n早餐:\n第一节课:\n";
+ String[] temple= {temple1,temple2,temple2};
+ Intent intent = new Intent(this, NoteEditActivity.class);
+ intent.setAction(Intent.ACTION_INSERT_OR_EDIT);
+ intent.putExtra(Notes.INTENT_EXTRA_FOLDER_ID, mCurrentFolderId);
+ intent.putExtra(Notes.INTENT_EXTRA_TEMPLE_TEXT,temple[num-1]);
+ this.startActivityForResult(intent, REQUEST_CODE_NEW_NODE);
+ }
- /**
- * @method: batchDelete
- * @description: 批处理删除。用于多个标签删除时
- * @date: 2024/1/6 11:15
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
private void batchDelete() {
-
-
-
new AsyncTask>() {
protected HashSet doInBackground(Void... unused) {
HashSet widgets = mNotesListAdapter.getSelectedWidget();
@@ -779,18 +516,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}.execute();
}
- /**
- * @method: deleteFolder
- * @description: 文件夹删除功能
- * @date: 2024/1/6 11:16
- * @author: 高浏阳
- * @param: [long]:[folderId]
- * @return: void
- */
private void deleteFolder(long folderId) {
-
-
-
if (folderId == Notes.ID_ROOT_FOLDER) {
Log.e(TAG, "Wrong folder id, should not happen " + folderId);
return;
@@ -817,198 +543,118 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
- /**
- * @method: openNode
- * @description: 打开便签功能。形参为NoteItemData,其为文件夹或便签的实例。
- * @date: 2024/1/6 11:17
- * @author: 高浏阳
- * @param: [net.micode.notes.ui.NoteItemData]:[data]
- * @return: void
- */
private void openNode(NoteItemData data) {
-
-
-
Intent intent = new Intent(this, NoteEditActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(Intent.EXTRA_UID, data.getId());
this.startActivityForResult(intent, REQUEST_CODE_OPEN_NODE);
}
-/**
- * @method openFolder
- * @description 打开文件夹方法
- * @date: 2023/12/21 7:54
- * @author: 王毅
- * @param
- * @return
- */
- //打开文件夹功能
private void openFolder(NoteItemData data) {
- // 设置当前文件夹的ID
mCurrentFolderId = data.getId();
- // 开始异步查询笔记列表
startAsyncNotesListQuery();
- // 如果当前文件夹的ID等于Notes.ID_CALL_RECORD_FOLDER
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
- // 设置当前状态为CALL_RECORD_FOLDER
mState = ListEditState.CALL_RECORD_FOLDER;
- // 隐藏添加新笔记按钮
mAddNewNote.setVisibility(View.GONE);
} else {
- // 否则设置当前状态为SUB_FOLDER
mState = ListEditState.SUB_FOLDER;
}
- // 如果当前文件夹的ID等于Notes.ID_CALL_RECORD_FOLDER
if (data.getId() == Notes.ID_CALL_RECORD_FOLDER) {
- // 设置标题栏文本为call_record_folder_name
mTitleBar.setText(R.string.call_record_folder_name);
} else {
- // 否则设置标题栏文本为data.getSnippet()
mTitleBar.setText(data.getSnippet());
}
- // 设置标题栏可见
mTitleBar.setVisibility(View.VISIBLE);
}
- /**
- * @method: onClick
- * @description: 视图点击事件。实现创建便签。
- * @date: 2024/1/6 11:17
- * @author: 高浏阳
- * @param: [android.view.View]:[v]
- * @return: void
- */
-
public void onClick(View v) {
-
-
-
if (v.getId() == R.id.btn_new_note) {
- createNewNote();
+ selectCreatemode(this);
+// createNewNote();
}
}
- /**
- * @method: showSoftInput
- * @description: 显示软键盘
- * @date: 2024/1/6 11:17
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
private void showSoftInput() {
-
-
-
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
if (inputMethodManager != null) {
inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
}
- /**
- * @method: hideSoftInput
- * @description: 不显示软键盘
- * @date: 2024/1/6 11:18
- * @author: 高浏阳
- * @param: [android.view.View]:[view]
- * @return: void
- */
- private void hideSoftInput(View view) {
-
-
- //获取输入法管理服务
+ private void hideSoftInput(View view) {
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
- //隐藏输入法
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
- //文件夹新建、查看及重命名功能。
- /**
- * @method showCreateOrModifyFolderDialog
- * @description 显示创建或修改文件夹对话框
- * @date: 2023/12/21 9:44
- * @author: 王毅
- * @param :[boolean]:[create]
- * @return void
- */
private void showCreateOrModifyFolderDialog(final boolean create) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
View view = LayoutInflater.from(this).inflate(R.layout.dialog_edit_text, null);
final EditText etName = (EditText) view.findViewById(R.id.et_foler_name);
- // 显示输入框
showSoftInput();
if (!create) {
if (mFocusNoteDataItem != null) {
- // 设置文本框中的文本为当前文件夹的摘要
etName.setText(mFocusNoteDataItem.getSnippet());
- // 设置标题为修改文件夹名称
builder.setTitle(getString(R.string.menu_folder_change_name));
} else {
Log.e(TAG, "The long click data item is null");
return;
}
} else {
- // 创建文件夹,清空文本框
etName.setText("");
- // 设置标题为创建文件夹
builder.setTitle(this.getString(R.string.menu_create_folder));
}
- //设置确定按钮
+
builder.setPositiveButton(android.R.string.ok, null);
- //设置取消按钮
builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- //隐藏软键盘
hideSoftInput(etName);
}
});
- //创建对话框
final Dialog dialog = builder.setView(view).show();
- //获取确定按钮
final Button positive = (Button)dialog.findViewById(android.R.id.button1);
positive.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- //隐藏软键盘
hideSoftInput(etName);
- //获取输入框中的文本
String name = etName.getText().toString();
- //检查输入的文本是否已经存在
if (DataUtils.checkVisibleFolderName(mContentResolver, name)) {
- //如果存在,则提示用户
Toast.makeText(NotesListActivity.this, getString(R.string.folder_exist, name),
Toast.LENGTH_LONG).show();
- //将光标移动到输入框的末尾
etName.setSelection(0, etName.length());
return;
}
- //新建文件夹的关键
- //如果输入的文本不存在
if (!create) {
- //如果输入的文本不为空
if (!TextUtils.isEmpty(name)) {
- //创建一个ContentValues对象
ContentValues values = new ContentValues();
- //将输入的文本添加到ContentValues对象中
values.put(NoteColumns.SNIPPET, name);
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
- //更新指定id的记录
mContentResolver.update(Notes.CONTENT_NOTE_URI, values, NoteColumns.ID
+ "=?", new String[] {
String.valueOf(mFocusNoteDataItem.getId())
});
}
} else if (!TextUtils.isEmpty(name)) {
- //创建一个ContentValues对象
+ //如果在根文件夹中创建
+ if (mCurrentFolderId == Notes.ID_ROOT_FOLDER){
+ //创建一个ContentValues对象
ContentValues values = new ContentValues();
- //将输入的文本添加到ContentValues对象中
values.put(NoteColumns.SNIPPET, name);
values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
- //插入新记录
mContentResolver.insert(Notes.CONTENT_NOTE_URI, values);
+ }
+ //如果在子文件夹中创建
+ else {
+ //创建一个ContentValues对象
+ ContentValues values = new ContentValues();
+ //将输入的文本添加到ContentValues对象中
+ values.put(NoteColumns.SNIPPET, name);
+ values.put(NoteColumns.TYPE, Notes.TYPE_FOLDER);
+ values.put(NoteColumns.PARENT_ID, String.valueOf(mCurrentFolderId));
+ //插入新记录
+ mContentResolver.insert(Notes.CONTENT_NOTE_URI, values);
+ }
+
}
//关闭对话框
dialog.dismiss();
@@ -1028,7 +674,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
- // 当输入框内容发生变化时,判断输入框内容是否为空,如果为空,则禁用positive按钮,否则启用positive按钮
if (TextUtils.isEmpty(etName.getText())) {
positive.setEnabled(false);
} else {
@@ -1042,44 +687,24 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
});
}
- /**
- * @method: onBackPressed
- * @description: 用于处理子Acitivity返回父Activity。相当于对按下“返回箭头”的处理。即返回NotesListActivity活动。
- * @date: 2024/1/6 11:18
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
+
@Override
public void onBackPressed() {
-
-
-
switch (mState) {
case SUB_FOLDER:
- // 设置当前文件夹ID为根文件夹ID
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
- // 设置当前状态为NOTE_LIST
mState = ListEditState.NOTE_LIST;
- // 开始异步查询笔记列表
startAsyncNotesListQuery();
- // 设置标题栏不可见
mTitleBar.setVisibility(View.GONE);
break;
case CALL_RECORD_FOLDER:
- // 设置当前文件夹ID为根文件夹ID
mCurrentFolderId = Notes.ID_ROOT_FOLDER;
- // 设置当前状态为NOTE_LIST
mState = ListEditState.NOTE_LIST;
- // 设置添加新笔记按钮可见
mAddNewNote.setVisibility(View.VISIBLE);
- // 设置标题栏不可见
mTitleBar.setVisibility(View.GONE);
- // 开始异步查询笔记列表
startAsyncNotesListQuery();
break;
case NOTE_LIST:
- // 调用父类的onBackPressed方法
super.onBackPressed();
break;
default:
@@ -1087,158 +712,68 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
}
- /**
- * @method: updateWidget
- * @description: 更新小组件
- * @date: 2024/1/6 11:19
- * @author: 高浏阳
- * @param: [int, int]:[appWidgetId, appWidgetType]
- * @return: void
- */
private void updateWidget(int appWidgetId, int appWidgetType) {
-
-
-
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
- // 判断widget的类型
if (appWidgetType == Notes.TYPE_WIDGET_2X) {
- // 设置widget的更新类
intent.setClass(this, NoteWidgetProvider_2x.class);
} else if (appWidgetType == Notes.TYPE_WIDGET_4X) {
- // 设置widget的更新类
intent.setClass(this, NoteWidgetProvider_4x.class);
} else {
Log.e(TAG, "Unspported widget type");
return;
}
- // 设置更新widget的id
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, new int[] {
appWidgetId
});
- // 发送更新widget的广播
sendBroadcast(intent);
- // 设置更新结果
setResult(RESULT_OK, intent);
}
-
- /**
- * @class: NotesListActivity
- * @extends:
- * @description: 实现按文件夹item的上下文菜单的回调函数,查看、删除、修改文件夹名称的浮动菜单栏(ContextMenu)创建(就是长按后出现)
- * @author: 王毅
- * @date: 2023/12/23 9:28
- */
private final OnCreateContextMenuListener mFolderOnCreateContextMenuListener = new OnCreateContextMenuListener() {
- //创建ContextMenu,形参为创建的菜单、长按事件绑定的视图、视图元素信息
-
-
- /**
- * @method: onCreateContextMenu
- * @description: 构造长按文件夹item的上下文菜单
- * @date: 2023/12/23 9:12
- * @author: 王毅
- * @param: [android.view.ContextMenu, android.view.View, android.view.ContextMenu.ContextMenuInfo]:[menu, v, menuInfo]
- * @return: void
- */
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
-
-
-
- // 如果mFocusNoteDataItem不为空
if (mFocusNoteDataItem != null) {
- // 设置菜单的标题为mFocusNoteDataItem的摘要
menu.setHeaderTitle(mFocusNoteDataItem.getSnippet());
- // 添加菜单项,菜单项的ID为MENU_FOLDER_VIEW,文本为R.string.menu_folder_view
menu.add(0, MENU_FOLDER_VIEW, 0, R.string.menu_folder_view);
- // 添加菜单项,菜单项的ID为MENU_FOLDER_DELETE,文本为R.string.menu_folder_delete
menu.add(0, MENU_FOLDER_DELETE, 0, R.string.menu_folder_delete);
- // 添加菜单项,菜单项的ID为MENU_FOLDER_CHANGE_NAME,文本为R.string.menu_folder_change_name
menu.add(0, MENU_FOLDER_CHANGE_NAME, 0, R.string.menu_folder_change_name);
}
}
};
- //下面都是对浮动菜单栏的一些函数
-
- /**
- * @method onContextMenuClosed
- * @description 浮动菜单栏关闭
- * @date: 2023/12/21 8:32
- * @author: 王毅
- * param [android.view.Menu]:[menu]
- * @return void
- */
@Override
public void onContextMenuClosed(Menu menu) {
-
-
-
- // 移除对mNotesListView的监听
- // 否则,当用户在列表项上右键时,会调用onContextMenuClosed()方法
-
- // 移除对mNotesListView的监听
if (mNotesListView != null) {
mNotesListView.setOnCreateContextMenuListener(null);
}
super.onContextMenuClosed(menu);
}
- //浮动菜单栏点击按钮后事件处理。
-
- @Override
- public boolean dispatchGenericMotionEvent(MotionEvent ev) {
- return super.dispatchGenericMotionEvent(ev);
- }
- /**
- * @method onContextItemSelected
- * @description 长按文件夹图标后显示的菜单选项
- * @date: 2023/12/23 8:53
- * @author: 王毅
- * @param: [android.view.MenuItem]:[item]
- * @return: boolean
- */
@Override
public boolean onContextItemSelected(MenuItem item) {
-
-
- // 判断当前焦点数据项是否为空
if (mFocusNoteDataItem == null) {
Log.e(TAG, "The long click data item is null");
return false;
}
- // 根据根据点击菜单项id进行判断
switch (item.getItemId()) {
- // 打开文件夹
case MENU_FOLDER_VIEW:
openFolder(mFocusNoteDataItem);
break;
- // 删除文件夹
case MENU_FOLDER_DELETE:
- // 实例化一个Builder类
AlertDialog.Builder builder = new AlertDialog.Builder(this);
- // 设置标题
builder.setTitle(getString(R.string.alert_title_delete));
- // 设置图标
builder.setIcon(android.R.drawable.ic_dialog_alert);
- // 设置消息
builder.setMessage(getString(R.string.alert_message_delete_folder));
- // 设置确定按钮
builder.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
- // 删除文件夹
deleteFolder(mFocusNoteDataItem.getId());
}
});
- // 设置取消按钮
builder.setNegativeButton(android.R.string.cancel, null);
- // 显示对话框
builder.show();
break;
- // 修改文件夹名称
case MENU_FOLDER_CHANGE_NAME:
showCreateOrModifyFolderDialog(false);
break;
@@ -1249,111 +784,58 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return true;
}
- //下面是OptionsMenu菜单创建的有关函数。
- //
- /**
- * @method: onPrepareOptionsMenu
- * @description: 针对不同界面打开不同的选项菜单,OptionsMenu创建
- * @date: 2023/12/23 9:55
- * @author: 王毅
- * @param: [android.view.Menu]:[menu]
- * @return: boolean
- */
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.clear();
if (mState == ListEditState.NOTE_LIST) {
- // 加载note_list菜单
getMenuInflater().inflate(R.menu.note_list, menu);
// set sync or sync_cancel
- // 设置sync或sync_cancel
menu.findItem(R.id.menu_sync).setTitle(
GTaskSyncService.isSyncing() ? R.string.menu_sync_cancel : R.string.menu_sync);
} else if (mState == ListEditState.SUB_FOLDER) {
- // 加载sub_folder菜单
getMenuInflater().inflate(R.menu.sub_folder, menu);
} else if (mState == ListEditState.CALL_RECORD_FOLDER) {
- // 加载call_record_folder菜单
getMenuInflater().inflate(R.menu.call_record_folder, menu);
} else {
Log.e(TAG, "Wrong state:" + mState);
}
return true;
}
- /**
- * @method: onOptionsItemSelected
- * @description: 点击不同的选项菜单栏打开不同的界面
- * @date: 2023/12/24 10:07
- * @author: 王毅
- * @param: [android.view.MenuItem]:[item]
- * @return: boolean
- */
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.menu_new_folder) {
- // 创建或修改文件夹
showCreateOrModifyFolderDialog(true);
} else if (itemId == R.id.menu_export_text) {
- // 导出笔记到文本
exportNoteToText();
} else if (itemId == R.id.menu_sync) {
- // 同步笔记
if (isSyncMode()) {
if (TextUtils.equals(item.getTitle(), getString(R.string.menu_sync))) {
- // 开始同步
GTaskSyncService.startSync(this);
} else {
- // 取消同步
GTaskSyncService.cancelSync(this);
}
} else {
- // 开始偏好设置
startPreferenceActivity();
}
} else if (itemId == R.id.menu_setting) {
- // 开始偏好设置
startPreferenceActivity();
} else if (itemId == R.id.menu_new_note) {
- // 创建新笔记
createNewNote();
} else if (itemId == R.id.menu_search) {
- // 请求搜索
onSearchRequested();
}
return true;
}
- /**
- * @method: onSearchRequested
- * @description: 搜索栏功能实现(就是最上面那个搜索便签得的),调用了ui组件
- * @date: 2024/1/6 11:20
- * @author: 高浏阳
- * @param: []:[]
- * @return: boolean
- */
@Override
public boolean onSearchRequested() {
-
-
-
startSearch(null, false, null /* appData */, false);
return true;
}
- //下面使用了异步线程类AsynTask。可在类中可以直接进行UI操作,并将后台计算的结果及时的交给UI线程进行UI界面显示。
- /**
- * @method: exportNoteToText
- * @description: 将便签内容输出为文本
- * @date: 2024/1/6 11:21
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
private void exportNoteToText() {
-
-
-
final BackupUtils backup = BackupUtils.getInstance(NotesListActivity.this);
new AsyncTask() {
@@ -1365,7 +847,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
@Override
protected void onPostExecute(Integer result) {
if (result == BackupUtils.STATE_SD_CARD_UNMOUONTED) {
- // 弹出提示框,提示SD卡未卸载
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(NotesListActivity.this
.getString(R.string.failed_sdcard_export));
@@ -1374,7 +855,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
builder.setPositiveButton(android.R.string.ok, null);
builder.show();
} else if (result == BackupUtils.STATE_SUCCESS) {
- // 弹出提示框,提示SD卡导出成功
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(NotesListActivity.this
.getString(R.string.success_sdcard_export));
@@ -1384,7 +864,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
builder.setPositiveButton(android.R.string.ok, null);
builder.show();
} else if (result == BackupUtils.STATE_SYSTEM_ERROR) {
- // 弹出提示框,提示SD卡导出失败
AlertDialog.Builder builder = new AlertDialog.Builder(NotesListActivity.this);
builder.setTitle(NotesListActivity.this
.getString(R.string.failed_sdcard_export));
@@ -1402,52 +881,19 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return NotesPreferenceActivity.getSyncAccountName(this).trim().length() > 0;
}
- /**
- * @method: startPreferenceActivity
- * @description: 用于跳转到保存的设置界面。这个maybe在isSyncMode==0时调用。作用在没进行过保存设置时。
- * @date: 2024/1/6 11:22
- * @author: 高浏阳
- * @param: []:[]
- * @return: void
- */
private void startPreferenceActivity() {
-
-
-
Activity from = getParent() != null ? getParent() : this;
Intent intent = new Intent(from, NotesPreferenceActivity.class);
from.startActivityIfNeeded(intent, -1);
}
- /**
- * @class: OnListItemClickListener
- * @implements OnItemClickListener
- * @description: 点击事件监听类
- * @author: 王毅
- * @date: 2024/1/6 11:22
- */
private class OnListItemClickListener implements OnItemClickListener {
-
- /**
- * @method: onItemClick
- * @description: 点击事件处理。将点击事件其与视图绑定。
- * @date: 2024/1/6 11:23
- * @author: 高浏阳
- * @param: [android.widget.AdapterView>, android.view.View, int, long]:[parent, view, position, id]
- * @return: void
- */
public void onItemClick(AdapterView> parent, View view, int position, long id) {
-
-
-
if (view instanceof NotesListItem) {
NoteItemData item = ((NotesListItem) view).getItemData();
- // 判断是否处于选择模式
if (mNotesListAdapter.isInChoiceMode()) {
- // 如果当前是笔记,则调用选择回调函数
if (item.getType() == Notes.TYPE_NOTE) {
- // 减去头部视图的数量
position = position - mNotesListView.getHeaderViewsCount();
mModeCallBack.onItemCheckedStateChanged(null, position, id,
!mNotesListAdapter.isSelectedItem(position));
@@ -1457,11 +903,9 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
switch (mState) {
case NOTE_LIST:
- // 如果当前是文件夹或者系统文件夹,则打开文件夹
if (item.getType() == Notes.TYPE_FOLDER
|| item.getType() == Notes.TYPE_SYSTEM) {
openFolder(item);
- // 如果当前是笔记,则打开笔记
} else if (item.getType() == Notes.TYPE_NOTE) {
testNode(item);
} else {
@@ -1470,11 +914,13 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
break;
case SUB_FOLDER:
case CALL_RECORD_FOLDER:
- // 如果当前是笔记,则打开笔记
if (item.getType() == Notes.TYPE_NOTE) {
testNode(item);
// openNode(item);
- } else {
+ }else if (item.getType() == Notes.TYPE_FOLDER
+ || item.getType() == Notes.TYPE_SYSTEM) {
+ openFolder(item);}
+ else {
Log.e(TAG, "Wrong note type in SUB_FOLDER");
}
break;
@@ -1486,7 +932,6 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
}
-
private void startQueryDestinationFolders() {
String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>? AND " + NoteColumns.ID + "<>?";
selection = (mState == ListEditState.NOTE_LIST) ? selection:
@@ -1504,18 +949,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
},
NoteColumns.MODIFIED_DATE + " DESC");
}
- /**
- * @method onItemLongClick
- * @description 处理用户长按控件时的行为
- * @date: 2023/12/21 8:37
- * @author: 王毅
- * @param :[android.widget.AdapterView>, android.view.View, int, long]:[parent, view, position, id]
- * @return boolean
- */
- public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
-
-
+ public boolean onItemLongClick(AdapterView> parent, View view, int position, long id) {
if (view instanceof NotesListItem) {
mFocusNoteDataItem = ((NotesListItem) view).getItemData();
if (mFocusNoteDataItem.getType() == Notes.TYPE_NOTE && !mNotesListAdapter.isInChoiceMode()) {
@@ -1532,8 +967,8 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
return false;
}
public void testNode(final NoteItemData item){
- if (!item.getmPassword().equals("1"))//判断是否有密码,如果没有密码,直接打开即可
-// if(item.getmPassword()!=null && !item.getmPassword().equals(""))
+ //if (!item.getmPassword().equals("1"))//判断是否有密码,如果没有密码,直接打开即可
+ if(item.getmPassword()!=null && !item.getmPassword().equals(""))
{
final AlertDialog.Builder builder = new AlertDialog.Builder(this);//初始化对话框
builder.setTitle("验证密码");
@@ -1596,5 +1031,34 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
openNode(item);
}
}
+ public void selectCreatemode(Context context){
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("选择模板")
+ .setItems(new CharSequence[]{"创建空新模板", "创建模板 1", "创建模板 2", "创建模板 3"}, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case 0:
+ // 创建空的模板
+ createNewNote();
+ break;
+ case 1:
+ // 创建模板 1
+ createTempelNote(1);
+// createTemplate("模板 1");
+ break;
+ case 2:
+ // 创建模板 2
+ createTempelNote(2);
+// break;
+ case 3:
+ // 创建模板 3
+ createTempelNote(3);
+ break;
+ }
+ }
+ })
+ .show();
+
+ }
}
diff --git a/src/main/java/net/micode/notes/ui/NotesListItem.java b/src/main/java/net/micode/notes/ui/NotesListItem.java
index f0b64a5..9af4bd1 100644
--- a/src/main/java/net/micode/notes/ui/NotesListItem.java
+++ b/src/main/java/net/micode/notes/ui/NotesListItem.java
@@ -87,7 +87,7 @@ public class NotesListItem extends LinearLayout {
mAlert.setVisibility(View.GONE);
// if(data.has)
} else {
- if("1".equals(data.getmPassword())){
+ if(data.getmPassword()==null){
mTitle.setText(DataUtils.getFormattedSnippet(data.getSnippet()));
}else {
diff --git a/src/main/res/drawable-hdpi/lock_private.png b/src/main/res/drawable-hdpi/lock_private.png
new file mode 100644
index 0000000000000000000000000000000000000000..965c19d8282a827231bd83447ed743e165bb8a15
GIT binary patch
literal 11130
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
Pr5~*;x|fU9ZJ+!vN%nrU
literal 0
HcmV?d00001
diff --git a/src/main/res/drawable-hdpi/login_photo.png b/src/main/res/drawable-hdpi/login_photo.png
new file mode 100644
index 0000000000000000000000000000000000000000..bb6b8c9e25a69b038e2f93fb9a8cfd1ed84c9adf
GIT binary patch
literal 1389
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