针对背景修改疑修 #26

Merged
p82feo7wg merged 2 commits from wangjiaqi_branch into master 2 months ago

@ -90,7 +90,7 @@ public class Notes {
// 查询数据表的URI
public static final Uri CONTENT_DATA_URI = Uri.parse("content://" + AUTHORITY + "/data");
/**
/**
* Uri to query trash notes
*/
public static final Uri CONTENT_TRASH_URI = Uri.parse("content://" + AUTHORITY + "/trash");
@ -153,13 +153,19 @@ public class Notes {
// 版本号
public static final String VERSION = "version";
/**
/**
* Whether the note is encrypted
* <P> Type : INTEGER (0 = not encrypted, 1 = encrypted) </P>
*/
public static final String IS_ENCRYPTED = "is_encrypted";
/**
* Background image URI for the note
* <P> Type : TEXT </P>
*/
public static final String BACKGROUND_IMAGE_URI = "background_image_uri";
}
public interface TrashColumns extends NoteColumns {
public interface TrashColumns extends NoteColumns {
/**
* Deleted date for trash note
* <P> Type: INTEGER (long) </P>

@ -30,7 +30,7 @@ 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 = 8;
private static final int DB_VERSION = 9;
public interface TABLE {
public static final String NOTE = "note";
@ -38,9 +38,9 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
public static final String DATA = "data";
public static final String TRASH = "trash_note";
public static final String TRASH_DATA = "trash_data";
public static final String ENCRYPTED_NOTE_PASSWORD = "encrypted_note_password";
}
@ -49,214 +49,216 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
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.IS_ENCRYPTED + " INTEGER NOT NULL DEFAULT 0" +
")";
"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.IS_ENCRYPTED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BACKGROUND_IMAGE_URI + " TEXT NOT NULL DEFAULT ''" +
")";
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 ''" +
")";
"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 + ");";
"CREATE INDEX IF NOT EXISTS note_id_index ON " +
TABLE.DATA + "(" + DataColumns.NOTE_ID + ");";
private static final String CREATE_TRASH_TABLE_SQL =
"CREATE TABLE " + TABLE.TRASH + "(" +
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.IS_ENCRYPTED + " INTEGER NOT NULL DEFAULT 0," +
"deleted_date INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)" +
")";
"CREATE TABLE " + TABLE.TRASH + "(" +
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.IS_ENCRYPTED + " INTEGER NOT NULL DEFAULT 0," +
NoteColumns.BACKGROUND_IMAGE_URI + " TEXT NOT NULL DEFAULT ''," +
"deleted_date INTEGER NOT NULL DEFAULT (strftime('%s','now') * 1000)" +
")";
private static final String CREATE_TRASH_DATA_TABLE_SQL =
"CREATE TABLE " + TABLE.TRASH_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 ''" +
")";
"CREATE TABLE " + TABLE.TRASH_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_ENCRYPTED_NOTE_PASSWORD_TABLE_SQL =
"CREATE TABLE " + TABLE.ENCRYPTED_NOTE_PASSWORD + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
"password TEXT NOT NULL," +
"FOREIGN KEY(" + NoteColumns.ID + ") REFERENCES " + TABLE.NOTE + "(" + NoteColumns.ID + ") ON DELETE CASCADE" +
")";
"CREATE TABLE " + TABLE.ENCRYPTED_NOTE_PASSWORD + "(" +
NoteColumns.ID + " INTEGER PRIMARY KEY," +
"password TEXT NOT NULL," +
"FOREIGN KEY(" + NoteColumns.ID + ") REFERENCES " + TABLE.NOTE + "(" + NoteColumns.ID + ") ON DELETE CASCADE" +
")";
/**
* 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";
"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";
"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";
"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";
"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";
"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";
"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";
"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";
"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";
"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";
"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);
@ -409,6 +411,11 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
oldVersion++;
}
if (oldVersion == 8) {
upgradeToV9(db);
oldVersion++;
}
if (reCreateTriggers) {
reCreateNoteTableTriggers(db);
reCreateDataTableTriggers(db);
@ -474,13 +481,22 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
createTrashDataTable(db);
Log.d(TAG, "Upgraded to version 7: created trash_data table");
}
private void upgradeToV8(SQLiteDatabase db) {
// 升级到版本8添加标签支持
// 标签数据将存储在现有的data表中使用新的MIME类型
Log.d(TAG, "Upgraded to version 8: added tag support");
}
private void upgradeToV9(SQLiteDatabase db) {
// 升级到版本9添加背景图片URI字段
db.execSQL("ALTER TABLE " + TABLE.NOTE + " ADD COLUMN " + NoteColumns.BACKGROUND_IMAGE_URI
+ " TEXT NOT NULL DEFAULT ''");
db.execSQL("ALTER TABLE " + TABLE.TRASH + " ADD COLUMN " + NoteColumns.BACKGROUND_IMAGE_URI
+ " TEXT NOT NULL DEFAULT ''");
Log.d(TAG, "Upgraded to version 9: added background_image_uri column");
}
public void createEncryptedNotePasswordTable(SQLiteDatabase db) {
db.execSQL(CREATE_ENCRYPTED_NOTE_PASSWORD_TABLE_SQL);
Log.d(TAG, "encrypted_note_password table has been created");

@ -58,6 +58,7 @@ public class WorkingNote {
private NoteSettingChangedListener mNoteSettingStatusListener; // 笔记设置变化监听器
private String mPassword; // 密码(仅在创建时使用)
private int mNoteType; // 笔记类型(普通笔记/清单)
private String mCustomBackgroundPath; // 自定义背景图片路径
@ -81,7 +82,8 @@ public class WorkingNote {
NoteColumns.BG_COLOR_ID, // 背景颜色ID
NoteColumns.WIDGET_ID, // 小部件ID
NoteColumns.WIDGET_TYPE, // 小部件类型
NoteColumns.MODIFIED_DATE // 修改日期
NoteColumns.MODIFIED_DATE, // 修改日期
NoteColumns.BACKGROUND_IMAGE_URI // 背景图片URI
};
// 数据查询结果列索引
@ -97,6 +99,7 @@ public class WorkingNote {
private static final int NOTE_WIDGET_ID_COLUMN = 3; // 小部件ID列索引
private static final int NOTE_WIDGET_TYPE_COLUMN = 4; // 小部件类型列索引
private static final int NOTE_MODIFIED_DATE_COLUMN = 5; // 修改日期列索引
private static final int NOTE_BACKGROUND_IMAGE_URI_COLUMN = 6; // 背景图片URI列索引
@ -151,6 +154,9 @@ public class WorkingNote {
mWidgetType = cursor.getInt(NOTE_WIDGET_TYPE_COLUMN);
mAlertDate = cursor.getLong(NOTE_ALERTED_DATE_COLUMN);
mModifiedDate = cursor.getLong(NOTE_MODIFIED_DATE_COLUMN);
if (!cursor.isNull(NOTE_BACKGROUND_IMAGE_URI_COLUMN)) {
mCustomBackgroundPath = cursor.getString(NOTE_BACKGROUND_IMAGE_URI_COLUMN);
}
}
cursor.close();
} else {
@ -533,7 +539,26 @@ public class WorkingNote {
}
return encrypted;
}
/**
*
* @param path
*/
public void setCustomBackgroundPath(String path) {
if (!TextUtils.equals(mCustomBackgroundPath, path)) {
mCustomBackgroundPath = path;
mNote.setNoteValue(NoteColumns.BACKGROUND_IMAGE_URI, path);
}
}
/**
*
* @return
*/
public String getCustomBackgroundPath() {
return mCustomBackgroundPath;
}
/**
*
* @param tagName
@ -541,7 +566,7 @@ public class WorkingNote {
public void addTag(String tagName) {
mNote.addTagData(tagName);
}
/**
*
*/

@ -0,0 +1,263 @@
/*
* 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.tool;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
*
*
*/
public class BackgroundManager {
private static final String TAG = "BackgroundManager";
private static final String BACKGROUND_DIR = "note_backgrounds";
private static final String IMAGE_DIR = "note_images";
private Context mContext;
/**
*
* @param context
*/
public BackgroundManager(Context context) {
mContext = context;
// 初始化目录
initDirectories();
}
/**
*
*/
private void initDirectories() {
// 创建背景图片目录
File backgroundDir = getBackgroundDir();
if (!backgroundDir.exists()) {
if (!backgroundDir.mkdirs()) {
Log.e(TAG, "Failed to create background directory");
}
}
// 创建插入图片目录
File imageDir = getImageDir();
if (!imageDir.exists()) {
if (!imageDir.mkdirs()) {
Log.e(TAG, "Failed to create image directory");
}
}
}
/**
*
* @return
*/
public File getBackgroundDir() {
return new File(mContext.getFilesDir(), BACKGROUND_DIR);
}
/**
*
* @return
*/
public File getImageDir() {
return new File(mContext.getFilesDir(), IMAGE_DIR);
}
/**
*
* @param sourceUri URI
* @return
*/
public String saveBackgroundImage(Uri sourceUri) {
try {
// 创建目标文件
String fileName = generateUniqueFileName();
File destFile = new File(getBackgroundDir(), fileName);
// 复制文件
copyFile(sourceUri, destFile);
// 返回文件路径
return destFile.getAbsolutePath();
} catch (IOException e) {
Log.e(TAG, "Error saving background image: " + e.getMessage());
return null;
}
}
/**
*
* @param sourceUri URI
* @return
*/
public String saveInsertedImage(Uri sourceUri) {
try {
// 创建目标文件
String fileName = generateUniqueFileName();
File destFile = new File(getImageDir(), fileName);
// 复制文件
copyFile(sourceUri, destFile);
// 返回文件路径
return destFile.getAbsolutePath();
} catch (IOException e) {
Log.e(TAG, "Error saving inserted image: " + e.getMessage());
return null;
}
}
/**
*
* @param sourceUri URI
* @param destFile
* @throws IOException IO
*/
private void copyFile(Uri sourceUri, File destFile) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = mContext.getContentResolver().openInputStream(sourceUri);
os = new FileOutputStream(destFile);
byte[] buffer = new byte[4096];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
}
}
/**
*
* @return
*/
private String generateUniqueFileName() {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
return "IMG_" + timeStamp + ".jpg";
}
/**
*
* @param path
* @return Drawable
*/
public Drawable loadBackground(String path) {
if (path == null || path.isEmpty()) {
return null;
}
try {
File file = new File(path);
if (!file.exists()) {
Log.e(TAG, "Background image file not found: " + path);
return null;
}
Bitmap bitmap = BitmapFactory.decodeFile(path);
if (bitmap == null) {
Log.e(TAG, "Failed to decode background image: " + path);
return null;
}
return new BitmapDrawable(mContext.getResources(), bitmap);
} catch (Exception e) {
Log.e(TAG, "Error loading background: " + e.getMessage());
return null;
}
}
/**
*
* @param path
* @return
*/
public boolean cleanupBackgroundImage(String path) {
if (path == null || path.isEmpty()) {
return false;
}
File file = new File(path);
if (file.exists()) {
if (file.delete()) {
Log.d(TAG, "Background image deleted: " + path);
return true;
} else {
Log.e(TAG, "Failed to delete background image: " + path);
return false;
}
}
return false;
}
/**
*
* @param path
* @return
*/
public boolean cleanupInsertedImage(String path) {
if (path == null || path.isEmpty()) {
return false;
}
File file = new File(path);
if (file.exists()) {
if (file.delete()) {
Log.d(TAG, "Inserted image deleted: " + path);
return true;
} else {
Log.e(TAG, "Failed to delete inserted image: " + path);
return false;
}
}
return false;
}
/**
*
* @param path
* @return
*/
public boolean isImageExists(String path) {
if (path == null || path.isEmpty()) {
return false;
}
File file = new File(path);
return file.exists() && file.isFile();
}
}

@ -105,6 +105,7 @@ 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.tool.BackgroundManager;
import net.micode.notes.ui.DateTimePickerDialog.OnDateTimeSetListener;
import net.micode.notes.ui.NoteEditText.OnTextViewChangeListener;
import net.micode.notes.widget.NoteWidgetProvider_2x;
@ -140,6 +141,7 @@ 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_bg_custom, -1); // 自定义背景
}
/**
@ -153,6 +155,7 @@ 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(-1, R.id.iv_bg_custom_select); // 自定义背景
}
/**
@ -180,8 +183,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
private static final String TAG = "NoteEditActivity"; // 日志标签
private static final int REQUEST_CODE_PICK_IMAGE = 100; // 图片选择请求码 OMO
private static final int PHOTO_REQUEST = 100; // 请求照片
private static final int REQUEST_CODE_PICK_IMAGE = 100; // 插入图片请求码
private static final int REQUEST_CODE_PICK_BACKGROUND = 101; // 背景图片请求码
private static final int PHOTO_REQUEST = REQUEST_CODE_PICK_IMAGE; // 保持兼容性
private HeadViewHolder mNoteHeaderHolder; // 头部视图持有者
private View mHeadViewPanel; // 头部视图面板
@ -193,7 +197,8 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private WorkingNote mWorkingNote; // 工作笔记对象
private SharedPreferences mSharedPrefs; // 共享偏好设置
private int mFontSizeId; // 字体大小ID
private ImageButton mBtnInsertImage; // 插入图片按钮 OMO
private ImageButton mBtnInsertImage; // 插入图片按钮
private BackgroundManager mBackgroundManager; // 背景管理器
private String mText; // 用于存储富文本内容
private int mNoteLength; // 文本长度
@ -207,7 +212,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private String mUserQuery; // 用户查询字符串
private Pattern mPattern; // 正则表达式模式(用于高亮查询结果)
private ChecklistManager mChecklistManager; // 清单管理器OMO
// 标签管理相关控件
private LinearLayout mTagManagementSection; // 标签管理区域
private LinearLayout mExistingTagsContainer; // 现有标签容器
@ -215,7 +220,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
private EditText mTagInput; // 标签输入框
private Button mAddTagButton; // 添加标签按钮
private ArrayList<String> mTagsList; // 标签列表
// 搜索历史相关
private static final String PREFERENCE_SEARCH_HISTORY = "search_history"; // 搜索历史偏好设置键
private static final int MAX_SEARCH_HISTORY = 20; // 最大搜索历史记录数
@ -296,7 +301,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
return false;
}
}
// 保存搜索历史
if (!TextUtils.isEmpty(mUserQuery)) {
saveSearchHistory(mUserQuery);
@ -514,9 +519,22 @@ public class NoteEditActivity extends Activity implements OnClickListener,
findViewById(sBgSelectorSelectionMap.get(id)).setVisibility(View.GONE);
}
// 设置头部视图和编辑器面板的背景
// 加载自定义背景图片
String backgroundPath = mWorkingNote.getCustomBackgroundPath();
if (backgroundPath != null && !backgroundPath.isEmpty()) {
Drawable background = mBackgroundManager.loadBackground(backgroundPath);
if (background != null) {
mNoteEditorPanel.setBackground(background);
} else {
// 如果背景图片加载失败,使用默认背景颜色
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
}
} else {
// 如果没有自定义背景,使用默认背景颜色
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
}
// 设置头部视图的背景
mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
// 设置最后修改时间
mNoteHeaderHolder.tvModified.setText(DateUtils.formatDateTime(this,
@ -529,7 +547,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
* is not ready
*/
showAlertHeader(); // 显示提醒头部
// 加载现有标签
loadExistingTags();
}
@ -765,7 +783,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Log.e(TAG, "RichEditor is null! Check layout file.");
return;
}
// 初始化浮动富文本工具栏
mFloatingToolbar = findViewById(R.id.floating_editor_toolbar);
if (mFloatingToolbar != null) {
@ -838,6 +856,9 @@ public class NoteEditActivity extends Activity implements OnClickListener,
// 初始化富文本功能按钮
initRichEditorButtons();
// 初始化背景管理器
mBackgroundManager = new BackgroundManager(this);
}
/**
@ -892,10 +913,18 @@ public class NoteEditActivity extends Activity implements OnClickListener,
View.VISIBLE);
} else if (sBgSelectorBtnsMap.containsKey(id)) {
// 处理背景颜色选择
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
mWorkingNote.setBgColorId(sBgSelectorBtnsMap.get(id));
mNoteBgColorSelector.setVisibility(View.GONE);
Integer bgColorId = sBgSelectorBtnsMap.get(id);
if (bgColorId == -1) {
// 处理自定义背景图片选择
mNoteBgColorSelector.setVisibility(View.GONE);
pickBackgroundImageFromGallery();
} else {
// 处理普通背景颜色选择
findViewById(sBgSelectorSelectionMap.get(mWorkingNote.getBgColorId())).setVisibility(
View.GONE);
mWorkingNote.setBgColorId(bgColorId);
mNoteBgColorSelector.setVisibility(View.GONE);
}
} else if (sFontSizeBtnsMap.containsKey(id)) {
// 处理字体大小选择
findViewById(sFontSelectorSelectionMap.get(mFontSizeId)).setVisibility(View.GONE);
@ -913,7 +942,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
mFontSizeSelector.setVisibility(View.GONE);
} else if (id == R.id.btn_insert_image) {
// 处理插入图片按钮点击事件 OMO
// 处理插入图片按钮点击事件
pickImageFromGallery();
}
}
@ -1048,7 +1077,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return true;
}
/**
* /
*/
@ -1458,10 +1487,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
*/
private boolean saveNote() {
getWorkingText(); // 获取当前工作文本
// 保存标签数据
saveTagsToNote();
boolean saved = mWorkingNote.saveNote(); // 保存笔记到数据库
if (saved) {
/**
@ -1475,20 +1504,20 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
return saved;
}
/**
*
*/
private void saveTagsToNote() {
// 清空现有标签
mWorkingNote.clearTags();
// 添加所有标签
for (String tag : mTagsList) {
mWorkingNote.addTag(tag);
}
}
/**
*
* @param query
@ -1497,13 +1526,13 @@ public class NoteEditActivity extends Activity implements OnClickListener,
if (TextUtils.isEmpty(query)) {
return;
}
// 获取SharedPreferences
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
// 获取现有的搜索历史
String historyString = sp.getString(PREFERENCE_SEARCH_HISTORY, "");
// 将搜索历史拆分为列表
ArrayList<String> historyList = new ArrayList<>();
if (!TextUtils.isEmpty(historyString)) {
@ -1514,18 +1543,18 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
}
}
// 如果搜索关键词已存在,先移除
historyList.remove(query);
// 将新的搜索关键词添加到列表开头
historyList.add(0, query);
// 限制搜索历史记录数量
if (historyList.size() > MAX_SEARCH_HISTORY) {
historyList = new ArrayList<>(historyList.subList(0, MAX_SEARCH_HISTORY));
}
// 将搜索历史列表转换为字符串,用逗号分隔
StringBuilder sb = new StringBuilder();
for (int i = 0; i < historyList.size(); i++) {
@ -1534,7 +1563,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
sb.append(historyList.get(i));
}
// 保存到SharedPreferences
sp.edit().putString(PREFERENCE_SEARCH_HISTORY, sb.toString()).apply();
}
@ -1627,13 +1656,44 @@ public class NoteEditActivity extends Activity implements OnClickListener,
// 意图:打开系统相册选择图片
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*"); // 只显示图片类型
startActivityForResult(intent, PHOTO_REQUEST); // 启动相册,等待返回结果
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE); // 启动相册,等待返回结果
} catch (ActivityNotFoundException e) {
// 如果没有相册应用,尝试使用通用选择器
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
try {
startActivityForResult(intent, PHOTO_REQUEST);
startActivityForResult(intent, REQUEST_CODE_PICK_IMAGE);
} catch (ActivityNotFoundException ex) {
showToast(R.string.error_permission_denied);
Log.e(TAG, "No image picker available", ex);
}
}
}
/**
*
*/
private void pickBackgroundImageFromGallery() {
// 检查运行时权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
// 请求权限
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_PERMISSION_STORAGE);
return;
}
}
try {
// 意图:打开系统相册选择图片
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*"); // 只显示图片类型
startActivityForResult(intent, REQUEST_CODE_PICK_BACKGROUND); // 启动相册,等待返回结果
} catch (ActivityNotFoundException e) {
// 如果没有相册应用,尝试使用通用选择器
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
try {
startActivityForResult(intent, REQUEST_CODE_PICK_BACKGROUND);
} catch (ActivityNotFoundException ex) {
showToast(R.string.error_permission_denied);
Log.e(TAG, "No image picker available", ex);
@ -1662,79 +1722,103 @@ public class NoteEditActivity extends Activity implements OnClickListener,
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PHOTO_REQUEST && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
String imageBase64 = saveImageToBase64(uri);
if (imageBase64 == null) return; // 转换失败就退出
// 1. 拼接RichEditor支持的<img>标签使用Base64编码的图片数据
String imgHtmlTag = "<img src=\"" + imageBase64 + "\" width=\"200\" height=\"200\"/><br/>";
// 2. 直接保存到笔记内容中(结合原有插入逻辑)
String originalContent = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
Log.d(TAG, "Original note content: " + originalContent);
// 3. 插入图片到RichEditor兼容空内容情况
String curHtml = mNoteEditor.getHtml();
if (curHtml == null || curHtml.isEmpty()) {
// 对于空内容,直接使用图片标签
mNoteEditor.setHtml(imgHtmlTag);
} else {
// 对于已有内容,追加图片标签
String newHtml = curHtml + imgHtmlTag;
mNoteEditor.setHtml(newHtml);
}
// 4. 同时更新工作笔记内容,确保新建笔记也能正确保存
String updatedHtml = mNoteEditor.getHtml();
mWorkingNote.setWorkingText(updatedHtml);
// 弹窗依然保留
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("图片选择成功!");
ImageView imageView = new ImageView(this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); // 加布局参数,避免图片显示不全
imageView.setImageURI(uri); // 弹窗显示原始图片
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); // 适配图片大小
builder.setView(imageView);
builder.setPositiveButton("确认", (dialog, which) -> {
// 保存HTML内容包含Base64编码的图片
String currentHtml = mNoteEditor.getHtml();
Log.d("NoteDebug", "准备保存的HTML内容" + currentHtml);
// 执行保存操作
mWorkingNote.setWorkingText(currentHtml);
boolean isSaved = mWorkingNote.saveNote();
// 根据保存结果提示(更友好)
if (isSaved) {
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
if (resultCode == RESULT_OK && data != null) {
if (requestCode == PHOTO_REQUEST || requestCode == REQUEST_CODE_PICK_IMAGE) {
Uri uri = data.getData();
String imageBase64 = saveImageToBase64(uri);
if (imageBase64 == null) return; // 转换失败就退出
// 1. 拼接RichEditor支持的<img>标签使用Base64编码的图片数据
String imgHtmlTag = "<img src=\"" + imageBase64 + "\" width=\"200\" height=\"200\"/><br/>";
// 2. 直接保存到笔记内容中(结合原有插入逻辑)
String originalContent = mWorkingNote.getContent() == null ? "" : mWorkingNote.getContent();
Log.d(TAG, "Original note content: " + originalContent);
// 3. 插入图片到RichEditor兼容空内容情况
String curHtml = mNoteEditor.getHtml();
if (curHtml == null || curHtml.isEmpty()) {
// 对于空内容,直接使用图片标签
mNoteEditor.setHtml(imgHtmlTag);
} else {
// 如果保存返回false可能是因为内容未变化而不是真正的失败
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Note save returned false, but image was successfully inserted");
// 对于已有内容,追加图片标签
String newHtml = curHtml + imgHtmlTag;
mNoteEditor.setHtml(newHtml);
}
});
builder.setNegativeButton("取消", (dialog, which) -> {
// 如果用户取消,移除刚才插入的图片
String currentHtml = mNoteEditor.getHtml();
if (currentHtml != null && currentHtml.endsWith(imgHtmlTag)) {
String cancelNewHtml = currentHtml.substring(0, currentHtml.length() - imgHtmlTag.length());
mNoteEditor.setHtml(cancelNewHtml);
// 同时更新工作笔记
mWorkingNote.setWorkingText(cancelNewHtml);
} else if (currentHtml != null && currentHtml.equals(imgHtmlTag)) {
// 如果只有这一张图片,取消后清空内容
mNoteEditor.setHtml("");
mWorkingNote.setWorkingText("");
// 4. 同时更新工作笔记内容,确保新建笔记也能正确保存
String updatedHtml = mNoteEditor.getHtml();
mWorkingNote.setWorkingText(updatedHtml);
// 弹窗依然保留
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("图片选择成功!");
ImageView imageView = new ImageView(this);
imageView.setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)); // 加布局参数,避免图片显示不全
imageView.setImageURI(uri); // 弹窗显示原始图片
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER); // 适配图片大小
builder.setView(imageView);
builder.setPositiveButton("确认", (dialog, which) -> {
// 保存HTML内容包含Base64编码的图片
String currentHtml = mNoteEditor.getHtml();
Log.d("NoteDebug", "准备保存的HTML内容" + currentHtml);
// 执行保存操作
mWorkingNote.setWorkingText(currentHtml);
boolean isSaved = mWorkingNote.saveNote();
// 根据保存结果提示(更友好)
if (isSaved) {
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
} else {
// 如果保存返回false可能是因为内容未变化而不是真正的失败
Toast.makeText(this, "图片信息已保存!", Toast.LENGTH_SHORT).show();
Log.d(TAG, "Note save returned false, but image was successfully inserted");
}
});
builder.setNegativeButton("取消", (dialog, which) -> {
// 如果用户取消,移除刚才插入的图片
String currentHtml = mNoteEditor.getHtml();
if (currentHtml != null && currentHtml.endsWith(imgHtmlTag)) {
String cancelNewHtml = currentHtml.substring(0, currentHtml.length() - imgHtmlTag.length());
mNoteEditor.setHtml(cancelNewHtml);
// 同时更新工作笔记
mWorkingNote.setWorkingText(cancelNewHtml);
} else if (currentHtml != null && currentHtml.equals(imgHtmlTag)) {
// 如果只有这一张图片,取消后清空内容
mNoteEditor.setHtml("");
mWorkingNote.setWorkingText("");
}
});
builder.show();
}
else if (requestCode == REQUEST_CODE_PICK_BACKGROUND) {
// 处理背景图片选择的情况
Uri uri = data.getData();
String backgroundPath = mBackgroundManager.saveBackgroundImage(uri);
if (backgroundPath != null) {
// 设置自定义背景路径
mWorkingNote.setCustomBackgroundPath(backgroundPath);
// 应用背景图片
Drawable background = mBackgroundManager.loadBackground(backgroundPath);
if (background != null) {
mNoteEditorPanel.setBackground(background);
mHeadViewPanel.setBackground(background);
}
// 隐藏背景选择器
mNoteBgColorSelector.setVisibility(View.GONE);
// 显示保存成功提示
Toast.makeText(this, "背景图片设置成功!", Toast.LENGTH_SHORT).show();
} else {
// 显示保存失败提示
Toast.makeText(this, "背景图片设置失败!", Toast.LENGTH_SHORT).show();
}
});
builder.show();
}
}
}
@ -1807,7 +1891,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.setEditorFontSize(18); // 默认值
}
}
/**
*
*/
@ -1817,10 +1901,10 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mExistingTagsContainer = findViewById(R.id.existing_tags_container);
mTagInput = findViewById(R.id.et_tag_input);
mAddTagButton = findViewById(R.id.btn_add_tag);
// 初始化标签列表
mTagsList = new ArrayList<>();
// 设置添加标签按钮的点击事件
mAddTagButton.setOnClickListener(new OnClickListener() {
@Override
@ -1828,30 +1912,30 @@ public class NoteEditActivity extends Activity implements OnClickListener,
addTag();
}
});
// 加载现有标签
loadExistingTags();
}
/**
*
*/
private void addTag() {
String tagName = mTagInput.getText().toString().trim();
// 检查标签是否有效
if (isValidTag(tagName)) {
// 添加标签到列表
mTagsList.add(tagName);
// 更新UI显示
updateTagsDisplay();
// 清空输入框
mTagInput.setText("");
}
}
/**
*
* @param tagName
@ -1863,41 +1947,41 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Toast.makeText(this, "标签不能为空", Toast.LENGTH_SHORT).show();
return false;
}
// 检查标签长度
if (tagName.length() < 1 || tagName.length() > 15) {
Toast.makeText(this, "标签长度必须在1-15个字符之间", Toast.LENGTH_SHORT).show();
return false;
}
// 检查标签数量是否超过限制
if (mTagsList.size() >= 5) {
Toast.makeText(this, "每个笔记最多只能添加5个标签", Toast.LENGTH_SHORT).show();
return false;
}
// 检查标签是否已存在
if (mTagsList.contains(tagName)) {
Toast.makeText(this, "该标签已存在", Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
/**
*
*/
private void updateTagsDisplay() {
// 清空现有标签容器
mExistingTagsContainer.removeAllViews();
// 添加所有标签到容器
for (final String tag : mTagsList) {
// 创建标签管理区域的标签视图
LinearLayout tagView = new LinearLayout(this);
LinearLayout.LayoutParams tagViewParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT,
36);
tagViewParams.setMargins(0, 0, 8, 0);
tagView.setLayoutParams(tagViewParams);
@ -1907,7 +1991,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
tagView.setBackgroundResource(R.drawable.bg_color_btn_mask);
tagView.setClickable(true);
tagView.setFocusable(true);
// 创建标签文本
TextView tagText = new TextView(this);
tagText.setText(tag);
@ -1916,7 +2000,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
tagText.setPadding(0, 0, 8, 0);
tagText.setSingleLine(true);
tagText.setTextSize(14);
// 创建删除按钮
ImageView deleteButton = new ImageView(this);
LinearLayout.LayoutParams deleteParams = new LinearLayout.LayoutParams(
@ -1927,7 +2011,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
deleteButton.setClickable(true);
deleteButton.setFocusable(true);
deleteButton.setTag(tag);
// 设置删除按钮点击事件
deleteButton.setOnClickListener(new OnClickListener() {
@Override
@ -1936,16 +2020,16 @@ public class NoteEditActivity extends Activity implements OnClickListener,
removeTag(tagToRemove);
}
});
// 添加控件到标签视图
tagView.addView(tagText);
tagView.addView(deleteButton);
// 添加标签视图到容器
mExistingTagsContainer.addView(tagView);
}
}
/**
*
* @param tagName
@ -1954,7 +2038,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mTagsList.remove(tagName);
updateTagsDisplay();
}
/**
*
*/
@ -1963,14 +2047,14 @@ public class NoteEditActivity extends Activity implements OnClickListener,
final boolean[] isDragging = {false};
final int[] lastX = {0};
final int[] lastY = {0};
// 设置触摸监听器
mFloatingToolbar.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 记录初始触摸位置
@ -1982,44 +2066,44 @@ public class NoteEditActivity extends Activity implements OnClickListener,
// 计算移动距离
int deltaX = x - lastX[0];
int deltaY = y - lastY[0];
// 判断是否开始拖拽
if (Math.abs(deltaX) > 5 || Math.abs(deltaY) > 5) {
isDragging[0] = true;
}
if (isDragging[0]) {
// 更新工具栏位置
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
// 计算新的位置
int newLeftMargin = params.leftMargin + deltaX;
int newTopMargin = params.topMargin + deltaY;
// 限制位置在屏幕范围内
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int screenWidth = displayMetrics.widthPixels;
int screenHeight = displayMetrics.heightPixels;
// 计算工具栏宽度和高度
int toolbarWidth = v.getWidth();
int toolbarHeight = v.getHeight();
// 限制左边界
newLeftMargin = Math.max(0, Math.min(newLeftMargin, screenWidth - toolbarWidth));
// 限制上边界
newTopMargin = Math.max(0, Math.min(newTopMargin, screenHeight - toolbarHeight));
// 更新布局参数
params.leftMargin = newLeftMargin;
params.topMargin = newTopMargin;
v.setLayoutParams(params);
// 更新最后触摸位置
lastX[0] = x;
lastY[0] = y;
return true; // 消耗事件
}
break;
@ -2031,12 +2115,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
break;
}
return false; // 不消耗事件,允许其他触摸事件处理
}
});
}
/**
*
*/
@ -2049,7 +2133,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
Notes.DataColumns.NOTE_ID + "=? AND " + Notes.DataColumns.MIME_TYPE + "=?",
new String[]{String.valueOf(mWorkingNote.getNoteId()), Notes.DataConstants.TAG},
null);
if (cursor != null) {
while (cursor.moveToNext()) {
String tagName = cursor.getString(0);
@ -2059,12 +2143,12 @@ public class NoteEditActivity extends Activity implements OnClickListener,
}
cursor.close();
}
// 更新UI显示
updateTagsDisplay();
}
}
// 初始化富文本编辑器配置
private void initRichEditor() {
mNoteEditor.setEditorHeight(600); // 设置编辑器高度
@ -2073,6 +2157,7 @@ public class NoteEditActivity extends Activity implements OnClickListener,
mNoteEditor.setPadding(10, 10, 10, 10); // 内边距
mNoteEditor.setPlaceholder("请输入笔记内容..."); // 占位提示
mNoteEditor.setInputEnabled(true); // 允许输入
mNoteEditor.setEditorBackgroundColor(0x00000000); // 设置背景透明
}
// 添加富文本功能按钮初始化方法

@ -373,7 +373,7 @@ public class NotesListActivity extends Activity implements OnClickListener, OnIt
});
// 搜索输入框编辑器动作监听器(处理虚拟键盘上的搜索按钮)
mSearchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
mSearchEditText.setOnEditorActionListener(new OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
// 检查是否是搜索动作

Loading…
Cancel
Save