From 574573cad8432ad831e070000bd5f20c7d46dd41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=8C=85=E5=B0=94=E4=BF=8A?=
Date: Sun, 1 Feb 2026 11:20:34 +0800
Subject: [PATCH] =?UTF-8?q?=E7=AC=94=E8=AE=B0=E7=BC=96=E8=BE=91=E9=A1=B5?=
=?UTF-8?q?=E9=9D=A2=E4=BC=98=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/net/micode/notes/data/Notes.java | 5 +
.../notes/data/NotesDatabaseHelper.java | 14 +-
.../net/micode/notes/data/NotesProvider.java | 2 +-
.../micode/notes/data/NotesRepository.java | 27 +-
.../net/micode/notes/model/WorkingNote.java | 60 +-
.../java/net/micode/notes/tool/DataUtils.java | 16 +-
.../net/micode/notes/tool/ResourceParser.java | 16 +-
.../net/micode/notes/ui/NoteEditActivity.java | 215 +++---
.../net/micode/notes/ui/NoteItemData.java | 4 +-
.../micode/notes/ui/NoteSearchActivity.java | 38 +-
.../micode/notes/ui/NotesListFragment.java | 24 +
.../net/micode/notes/ui/NotesListItem.java | 6 +-
.../micode/notes/ui/NotesRecyclerAdapter.java | 2 +-
.../notes/viewmodel/NotesListViewModel.java | 80 ++-
.../src/main/res/drawable/bg_bottom_sheet.xml | 7 +
.../src/main/res/drawable/preset_forest.xml | 5 +
.../src/main/res/drawable/preset_lavender.xml | 5 +
.../src/main/res/drawable/preset_ocean.xml | 5 +
.../src/main/res/drawable/preset_sunset.xml | 5 +
.../res/layout/dialog_background_selector.xml | 69 ++
.../app/src/main/res/layout/note_edit.xml | 658 ++++++------------
.../app/src/main/res/values/colors.xml | 10 +
22 files changed, 667 insertions(+), 606 deletions(-)
create mode 100644 src/Notesmaster/app/src/main/res/drawable/bg_bottom_sheet.xml
create mode 100644 src/Notesmaster/app/src/main/res/drawable/preset_forest.xml
create mode 100644 src/Notesmaster/app/src/main/res/drawable/preset_lavender.xml
create mode 100644 src/Notesmaster/app/src/main/res/drawable/preset_ocean.xml
create mode 100644 src/Notesmaster/app/src/main/res/drawable/preset_sunset.xml
create mode 100644 src/Notesmaster/app/src/main/res/layout/dialog_background_selector.xml
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/data/Notes.java b/src/Notesmaster/app/src/main/java/net/micode/notes/data/Notes.java
index ea474ab..479e78e 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/data/Notes.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/data/Notes.java
@@ -62,6 +62,11 @@ public class Notes {
*/
public static final int TYPE_TASK = 3;
+ /**
+ * 模板笔记类型
+ */
+ public static final int TYPE_TEMPLATE = 4;
+
/**
* 以下ID是系统文件夹的标识符
* {@link Notes#ID_ROOT_FOLDER } 是默认文件夹
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java b/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
index 92bfc6c..b130c5b 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesDatabaseHelper.java
@@ -982,21 +982,21 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
// 工作模板
long workFolderId = insertFolder(db, Notes.ID_TEMPLATE_FOLDER, "工作");
if (workFolderId > 0) {
- insertNote(db, workFolderId, "会议记录", "会议主题:\n时间:\n地点:\n参会人:\n\n会议内容:\n\n行动项:\n");
- insertNote(db, workFolderId, "周报", "本周工作总结:\n1. \n2. \n\n下周工作计划:\n1. \n2. \n\n需要协调的问题:\n");
+ insertNote(db, workFolderId, "会议记录", "会议主题:\n时间:\n地点:\n参会人:\n\n会议内容:\n\n行动项:\n", Notes.TYPE_TEMPLATE);
+ insertNote(db, workFolderId, "周报", "本周工作总结:\n1. \n2. \n\n下周工作计划:\n1. \n2. \n\n需要协调的问题:\n", Notes.TYPE_TEMPLATE);
}
// 生活模板
long lifeFolderId = insertFolder(db, Notes.ID_TEMPLATE_FOLDER, "生活");
if (lifeFolderId > 0) {
- insertNote(db, lifeFolderId, "日记", "日期:\n天气:\n心情:\n\n正文:\n");
- insertNote(db, lifeFolderId, "购物清单", "1. \n2. \n3. \n");
+ insertNote(db, lifeFolderId, "日记", "日期:\n天气:\n心情:\n\n正文:\n", Notes.TYPE_TEMPLATE);
+ insertNote(db, lifeFolderId, "购物清单", "1. \n2. \n3. \n", Notes.TYPE_TEMPLATE);
}
// 学习模板
long studyFolderId = insertFolder(db, Notes.ID_TEMPLATE_FOLDER, "学习");
if (studyFolderId > 0) {
- insertNote(db, studyFolderId, "读书笔记", "书名:\n作者:\n\n核心观点:\n\n精彩摘录:\n\n读后感:\n");
+ insertNote(db, studyFolderId, "读书笔记", "书名:\n作者:\n\n核心观点:\n\n精彩摘录:\n\n读后感:\n", Notes.TYPE_TEMPLATE);
}
}
@@ -1012,10 +1012,10 @@ public class NotesDatabaseHelper extends SQLiteOpenHelper {
return db.insert(TABLE.NOTE, null, values);
}
- private void insertNote(SQLiteDatabase db, long parentId, String title, String content) {
+ private void insertNote(SQLiteDatabase db, long parentId, String title, String content, int type) {
ContentValues values = new ContentValues();
values.put(NoteColumns.PARENT_ID, parentId);
- values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
+ values.put(NoteColumns.TYPE, type);
values.put(NoteColumns.CREATED_DATE, System.currentTimeMillis());
values.put(NoteColumns.MODIFIED_DATE, System.currentTimeMillis());
values.put(NoteColumns.SNIPPET, content); // SNIPPET acts as content preview or full content for simple notes
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesProvider.java b/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesProvider.java
index aa2cf34..084d09a 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesProvider.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesProvider.java
@@ -168,7 +168,7 @@ public class NotesProvider extends ContentProvider {
+ " FROM " + TABLE.NOTE
+ " WHERE " + NoteColumns.SNIPPET + " LIKE ?"
+ " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER
- + " AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
+ + " AND (" + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " OR " + NoteColumns.TYPE + "=" + Notes.TYPE_TEMPLATE + ")";
/**
* 创建Content Provider
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesRepository.java b/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesRepository.java
index c4282fc..169d437 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesRepository.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/data/NotesRepository.java
@@ -88,6 +88,10 @@ public class NotesRepository {
return parentId;
}
+ public void setParentId(long parentId) {
+ this.parentId = parentId;
+ }
+
public String getNoteDataValue() {
return snippet;
}
@@ -308,11 +312,17 @@ public class NotesRepository {
selection = NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " AND " +
NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
selectionArgs = null;
+ } else if (folderId == Notes.ID_TEMPLATE_FOLDER) {
+ // Special case for template folder: show all templates regardless of category
+ selection = NoteColumns.TYPE + "=" + Notes.TYPE_TEMPLATE;
+ selectionArgs = null;
} else if (folderId == Notes.ID_ROOT_FOLDER) {
selection = "(" + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE + " AND " + NoteColumns.PARENT_ID + "=?)";
selectionArgs = new String[]{String.valueOf(Notes.ID_ROOT_FOLDER)};
} else {
- selection = NoteColumns.PARENT_ID + "=? AND " + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE;
+ // In a sub-folder, show both normal notes and templates if they exist there
+ selection = NoteColumns.PARENT_ID + "=? AND (" + NoteColumns.TYPE + "=" + Notes.TYPE_NOTE +
+ " OR " + NoteColumns.TYPE + "=" + Notes.TYPE_TEMPLATE + ")";
selectionArgs = new String[]{String.valueOf(folderId)};
}
@@ -605,8 +615,19 @@ public class NotesRepository {
ContentValues values = new ContentValues();
long currentTime = System.currentTimeMillis();
+ int type = Notes.TYPE_NOTE;
+ if (folderId == Notes.ID_TEMPLATE_FOLDER) {
+ type = Notes.TYPE_TEMPLATE;
+ } else if (folderId > 0) {
+ // Check if folder is under templates
+ NoteInfo folder = getFolderInfo(folderId);
+ if (folder != null && folder.parentId == Notes.ID_TEMPLATE_FOLDER) {
+ type = Notes.TYPE_TEMPLATE;
+ }
+ }
+
values.put(NoteColumns.PARENT_ID, folderId);
- values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
+ values.put(NoteColumns.TYPE, type);
values.put(NoteColumns.CREATED_DATE, currentTime);
values.put(NoteColumns.MODIFIED_DATE, currentTime);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
@@ -1482,7 +1503,7 @@ public class NotesRepository {
long currentTime = System.currentTimeMillis();
values.put(NoteColumns.PARENT_ID, categoryId);
- values.put(NoteColumns.TYPE, Notes.TYPE_NOTE);
+ values.put(NoteColumns.TYPE, Notes.TYPE_TEMPLATE);
values.put(NoteColumns.CREATED_DATE, currentTime);
values.put(NoteColumns.MODIFIED_DATE, currentTime);
values.put(NoteColumns.LOCAL_MODIFIED, 1);
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/model/WorkingNote.java b/src/Notesmaster/app/src/main/java/net/micode/notes/model/WorkingNote.java
index 63f7173..9a8976f 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/model/WorkingNote.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/model/WorkingNote.java
@@ -115,6 +115,7 @@ public class WorkingNote {
DataColumns.DATA2,
DataColumns.DATA3,
DataColumns.DATA4,
+ DataColumns.DATA5,
};
/** 数据查询投影 - 笔记元数据 */
@@ -190,7 +191,36 @@ public class WorkingNote {
mMode = 0;
mWidgetType = Notes.TYPE_WIDGET_INVALIDE;
mLocalModified = 1; // 新建笔记需要同步
- mType = Notes.TYPE_NOTE; // 默认为普通笔记类型
+
+ // Determine type based on folder
+ if (folderId == Notes.ID_TEMPLATE_FOLDER) {
+ mType = Notes.TYPE_TEMPLATE;
+ } else if (folderId > 0) {
+ // Check if parent is template folder
+ int parentType = net.micode.notes.tool.DataUtils.getNoteTypeById(context.getContentResolver(), folderId);
+ if (parentType == Notes.TYPE_FOLDER) {
+ // We need to check the folder's parent
+ long parentId = 0;
+ android.database.Cursor c = context.getContentResolver().query(
+ android.content.ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, folderId),
+ new String[] { NoteColumns.PARENT_ID }, null, null, null);
+ if (c != null) {
+ if (c.moveToFirst()) {
+ parentId = c.getLong(0);
+ }
+ c.close();
+ }
+ if (parentId == Notes.ID_TEMPLATE_FOLDER) {
+ mType = Notes.TYPE_TEMPLATE;
+ } else {
+ mType = Notes.TYPE_NOTE;
+ }
+ } else {
+ mType = Notes.TYPE_NOTE;
+ }
+ } else {
+ mType = Notes.TYPE_NOTE;
+ }
}
/**
@@ -287,6 +317,12 @@ public class WorkingNote {
mContent = cursor.getString(DATA_CONTENT_COLUMN);
mMode = cursor.getInt(DATA_MODE_COLUMN);
mNote.setTextDataId(cursor.getLong(DATA_ID_COLUMN));
+
+ // 加载壁纸路径
+ int wallpaperIndex = cursor.getColumnIndex(DataColumns.DATA5);
+ if (wallpaperIndex != -1) {
+ mWallpaperPath = cursor.getString(wallpaperIndex);
+ }
} else if (DataConstants.CALL_NOTE.equals(type)) {
// 加载通话记录数据
mNote.setCallDataId(cursor.getLong(DATA_ID_COLUMN));
@@ -366,9 +402,9 @@ public class WorkingNote {
public synchronized boolean saveNote() {
if (isWorthSaving()) {
if (!existInDatabase()) {
- // 创建新笔记
- if ((mNoteId = Note.getNewNoteId(mContext, mFolderId)) == 0) {
- Log.e(TAG, "Create new note fail with id:" + mNoteId);
+ // 创建新笔记
+ if ((mNoteId = Note.getNewNoteId(mContext, mFolderId, mType)) == 0) {
+ Log.e(TAG, "Create new note fail with id:" + mNoteId);
return false;
}
}
@@ -501,16 +537,12 @@ public class WorkingNote {
private String mWallpaperPath;
public void setWallpaper(String path) {
- mWallpaperPath = path;
- // Ideally we should save this to DB, but for now we might use shared prefs or a separate table
- // Or reuse bg_color_id with a special flag if we want to stick to existing schema strictly?
- // Better: store in a new column or reuse a data column if possible.
- // Given existing schema, let's use DataColumns.DATA5 if available? No DATA5.
- // Let's use a SharedPreference for mapping noteId -> wallpaperPath for now to avoid schema migration complexity in this step.
- // Or just use a special negative color ID range for wallpapers?
- // Actually, let's use a separate storage for wallpapers map: note_id -> uri string
- if (mNoteSettingStatusListener != null) {
- mNoteSettingStatusListener.onBackgroundColorChanged(); // Reuse this to trigger refresh
+ if (!TextUtils.equals(mWallpaperPath, path)) {
+ mWallpaperPath = path;
+ mNote.setTextData(DataColumns.DATA5, mWallpaperPath);
+ if (mNoteSettingStatusListener != null) {
+ mNoteSettingStatusListener.onBackgroundColorChanged(); // Reuse this to trigger refresh
+ }
}
}
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/tool/DataUtils.java b/src/Notesmaster/app/src/main/java/net/micode/notes/tool/DataUtils.java
index d237122..46fd4c6 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/tool/DataUtils.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/tool/DataUtils.java
@@ -182,10 +182,22 @@ public class DataUtils {
* @return 如果笔记可见返回 true,否则返回 false
*/
public static boolean visibleInNoteDatabase(ContentResolver resolver, long noteId, int type) {
+ String selection;
+ String[] selectionArgs;
+
+ if (type == Notes.TYPE_NOTE) {
+ // If checking for a regular note, also allow templates as they are essentially notes
+ selection = "(" + NoteColumns.TYPE + "=? OR " + NoteColumns.TYPE + "=?) AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
+ selectionArgs = new String[] {String.valueOf(Notes.TYPE_NOTE), String.valueOf(Notes.TYPE_TEMPLATE)};
+ } else {
+ selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER;
+ selectionArgs = new String [] {String.valueOf(type)};
+ }
+
Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
null,
- NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLER,
- new String [] {String.valueOf(type)},
+ selection,
+ selectionArgs,
null);
boolean exist = false;
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/tool/ResourceParser.java b/src/Notesmaster/app/src/main/java/net/micode/notes/tool/ResourceParser.java
index 595d7a5..3743336 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/tool/ResourceParser.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/tool/ResourceParser.java
@@ -51,6 +51,12 @@ public class ResourceParser {
public static final int EYE_CARE_GREEN = 6;
public static final int WARM = 7;
public static final int COOL = 8;
+
+ // Gradient Presets
+ public static final int SUNSET = 9;
+ public static final int OCEAN = 10;
+ public static final int FOREST = 11;
+ public static final int LAVENDER = 12;
/** 自定义颜色按钮 ID (用于 UI 显示) */
public static final int CUSTOM_COLOR_BUTTON_ID = -100;
@@ -108,7 +114,15 @@ public class ResourceParser {
R.drawable.edit_blue,
R.drawable.edit_white,
R.drawable.edit_green,
- R.drawable.edit_red
+ R.drawable.edit_red,
+ R.color.bg_midnight_black,
+ R.color.bg_eye_care_green,
+ R.color.bg_warm,
+ R.color.bg_cool,
+ R.drawable.preset_sunset,
+ R.drawable.preset_ocean,
+ R.drawable.preset_forest,
+ R.drawable.preset_lavender
};
/** 标题栏背景资源数组 */
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java
index efdb3e1..b19c795 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteEditActivity.java
@@ -77,7 +77,10 @@ import java.util.regex.Pattern;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.appbar.MaterialToolbar;
+import com.google.android.material.bottomsheet.BottomSheetDialog;
+import net.micode.notes.databinding.DialogBackgroundSelectorBinding;
+import net.micode.notes.databinding.DialogColorPickerBinding;
import net.micode.notes.databinding.NoteEditBinding;
import net.micode.notes.tool.RichTextHelper;
@@ -162,7 +165,6 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
private UndoRedoManager mUndoRedoManager;
private boolean mInUndoRedo = false;
- private androidx.recyclerview.widget.RecyclerView mColorSelectorRv;
private NoteColorAdapter mColorAdapter;
/**
@@ -331,7 +333,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
*
*/
private void initResources() {
- mHeadViewPanel = binding.noteTitle;
+ mHeadViewPanel = binding.cvEditorSurface;
mNoteHeaderHolder = new HeadViewHolder();
mNoteHeaderHolder.tvModified = binding.tvModifiedDate;
mNoteHeaderHolder.ivAlertIcon = binding.ivAlertIcon;
@@ -342,9 +344,8 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
mNoteHeaderHolder.etTitle = binding.etTitle;
mNoteEditor = binding.noteEditView;
- mNoteEditorPanel = binding.svNoteEdit;
+ mNoteEditorPanel = binding.cvEditorSurface;
mNoteBgColorSelector = binding.noteBgColorSelector;
- mColorSelectorRv = binding.rvBgColorSelector;
mNoteEditor.addTextChangedListener(new TextWatcher() {
private CharSequence mBeforeText;
@@ -406,6 +407,10 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
ResourceParser.EYE_CARE_GREEN,
ResourceParser.WARM,
ResourceParser.COOL,
+ ResourceParser.SUNSET,
+ ResourceParser.OCEAN,
+ ResourceParser.FOREST,
+ ResourceParser.LAVENDER,
ResourceParser.CUSTOM_COLOR_BUTTON_ID,
ResourceParser.WALLPAPER_BUTTON_ID
);
@@ -418,11 +423,11 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
pickWallpaper();
} else {
mWorkingNote.setBgColorId(colorId);
+ mWorkingNote.setWallpaper(null);
mNoteBgColorSelector.setVisibility(View.GONE);
}
}
});
- mColorSelectorRv.setAdapter(mColorAdapter);
mFontSizeSelector = binding.fontSizeSelector;
for (int id : sFontSizeBtnsMap.keySet()) {
@@ -680,8 +685,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
public void onClick(View v) {
int id = v.getId();
if (id == R.id.btn_set_bg_color) {
- mNoteBgColorSelector.setVisibility(View.VISIBLE);
- // Note: Adapter selection is already set in onBackgroundColorChanged or init
+ showBackgroundSelector();
} else if (sFontSizeBtnsMap.containsKey(id)) {
View fontView = getFontSelectorView(sFontSelectorSelectionMap.get(mFontSizeId));
if (fontView != null) {
@@ -764,27 +768,14 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
String wallpaperPath = mWorkingNote.getWallpaperPath();
if (wallpaperPath != null) {
- // Load wallpaper
+ binding.ivNoteWallpaper.setVisibility(View.VISIBLE);
+ binding.viewBgMask.setVisibility(View.VISIBLE);
+
android.net.Uri uri = android.net.Uri.parse(wallpaperPath);
try {
java.io.InputStream inputStream = getContentResolver().openInputStream(uri);
android.graphics.Bitmap bitmap = android.graphics.BitmapFactory.decodeStream(inputStream);
- android.graphics.drawable.BitmapDrawable drawable = new android.graphics.drawable.BitmapDrawable(getResources(), bitmap);
-
- // Tiling mode (can be configurable later)
- drawable.setTileModeXY(android.graphics.Shader.TileMode.REPEAT, android.graphics.Shader.TileMode.REPEAT);
-
- // Add Blur Effect for Android 12+
- if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
- mNoteEditorPanel.setBackground(drawable);
- mNoteEditorPanel.setRenderEffect(android.graphics.RenderEffect.createBlurEffect(
- 20f, 20f, android.graphics.Shader.TileMode.CLAMP));
- } else {
- mNoteEditorPanel.setBackground(drawable);
- }
-
- // Header always uses original wallpaper (or maybe slightly darker?)
- mHeadViewPanel.setBackground(drawable.getConstantState().newDrawable());
+ binding.ivNoteWallpaper.setImageBitmap(bitmap);
// Dynamic Coloring with Palette
androidx.palette.graphics.Palette.from(bitmap).generate(palette -> {
@@ -795,12 +786,14 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
} catch (Exception e) {
Log.e(TAG, "Failed to load wallpaper", e);
- // Fallback to color
+ binding.ivNoteWallpaper.setVisibility(View.GONE);
+ binding.viewBgMask.setVisibility(View.GONE);
applyColorBackground(colorId);
}
} else {
+ binding.ivNoteWallpaper.setVisibility(View.GONE);
+ binding.viewBgMask.setVisibility(View.GONE);
applyColorBackground(colorId);
- // Reset toolbar colors to default/theme
resetToolbarColors();
}
updateTextColor(colorId);
@@ -809,30 +802,47 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
private void applyPaletteColors(androidx.palette.graphics.Palette palette) {
int primaryColor = palette.getDominantColor(getResources().getColor(R.color.primary_color));
int onPrimaryColor = getResources().getColor(R.color.on_primary_color);
+ int mutedColor = palette.getMutedColor(android.graphics.Color.WHITE);
// Ensure contrast for onPrimaryColor
if (androidx.core.graphics.ColorUtils.calculateContrast(onPrimaryColor, primaryColor) < 3.0) {
- onPrimaryColor = android.graphics.Color.WHITE;
+ onPrimaryColor = isColorDark(primaryColor) ? android.graphics.Color.WHITE : android.graphics.Color.BLACK;
}
- binding.toolbar.setBackgroundColor(primaryColor);
binding.toolbar.setTitleTextColor(onPrimaryColor);
if (binding.toolbar.getNavigationIcon() != null) {
binding.toolbar.getNavigationIcon().setTint(onPrimaryColor);
}
getWindow().setStatusBarColor(primaryColor);
+
+ // Update Card Surface - semi-transparent glass effect
+ int surfaceColor = androidx.core.graphics.ColorUtils.setAlphaComponent(mutedColor, 230); // 90% opacity
+ binding.cvEditorSurface.setCardBackgroundColor(surfaceColor);
+
+ // Update input text color based on surface color
+ int textColor = isColorDark(surfaceColor) ? android.graphics.Color.WHITE : android.graphics.Color.BLACK;
+ mNoteEditor.setTextColor(textColor);
+ if (mNoteHeaderHolder != null && mNoteHeaderHolder.etTitle != null) {
+ mNoteHeaderHolder.etTitle.setTextColor(textColor);
+ mNoteHeaderHolder.etTitle.setHintTextColor(androidx.core.graphics.ColorUtils.setAlphaComponent(textColor, 128));
+ }
+ binding.tvCharCount.setTextColor(textColor);
+ binding.tvModifiedDate.setTextColor(textColor);
}
private void resetToolbarColors() {
int primaryColor = getResources().getColor(R.color.primary_color);
int onPrimaryColor = getResources().getColor(R.color.on_primary_color);
- binding.toolbar.setBackgroundColor(primaryColor);
+ binding.toolbar.setBackgroundColor(android.graphics.Color.TRANSPARENT);
binding.toolbar.setTitleTextColor(onPrimaryColor);
if (binding.toolbar.getNavigationIcon() != null) {
binding.toolbar.getNavigationIcon().setTint(onPrimaryColor);
}
getWindow().setStatusBarColor(primaryColor);
+
+ // Reset Card Surface
+ binding.cvEditorSurface.setCardBackgroundColor(android.graphics.Color.parseColor("#CCFFFFFF"));
}
private void updateTextColor(int colorId) {
@@ -843,20 +853,27 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
textColor = android.graphics.Color.WHITE;
} else if (colorId < 0) {
// Custom color: Calculate luminance
- // colorId is the ARGB value for custom colors
if (isColorDark(colorId)) {
textColor = android.graphics.Color.WHITE;
}
}
- // For wallpaper, we might want to check palette, but for now default to black or keep current
- // If wallpaper is set, this method is called with the underlying colorId.
- // We should probably rely on the underlying color or default to white/black.
-
- mNoteEditor.setTextColor(textColor);
- // Also update title color if needed
- if (mNoteHeaderHolder != null && mNoteHeaderHolder.etTitle != null) {
- mNoteHeaderHolder.etTitle.setTextColor(textColor);
+ // If wallpaper is set, applyPaletteColors already handled text color.
+ if (mWorkingNote.getWallpaperPath() == null) {
+ mNoteEditor.setTextColor(textColor);
+ if (mNoteHeaderHolder != null && mNoteHeaderHolder.etTitle != null) {
+ mNoteHeaderHolder.etTitle.setTextColor(textColor);
+ mNoteHeaderHolder.etTitle.setHintTextColor(androidx.core.graphics.ColorUtils.setAlphaComponent(textColor, 128));
+ }
+ binding.tvCharCount.setTextColor(textColor);
+ binding.tvModifiedDate.setTextColor(textColor);
+
+ // Adjust card surface opacity for pure colors
+ if (colorId == ResourceParser.WHITE) {
+ binding.cvEditorSurface.setCardBackgroundColor(android.graphics.Color.WHITE);
+ } else {
+ binding.cvEditorSurface.setCardBackgroundColor(android.graphics.Color.parseColor("#CCFFFFFF"));
+ }
}
}
@@ -868,27 +885,10 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
}
private void applyColorBackground(int colorId) {
- mNoteEditorPanel.setBackgroundResource(mWorkingNote.getBgColorResId());
- mHeadViewPanel.setBackgroundResource(mWorkingNote.getTitleBgResId());
-
- if (colorId >= ResourceParser.MIDNIGHT_BLACK || colorId < 0) {
- int color = ResourceParser.getNoteBgColor(this, colorId);
- if (mNoteEditorPanel.getBackground() != null) {
- mNoteEditorPanel.getBackground().setTint(color);
- mNoteEditorPanel.getBackground().setTintMode(android.graphics.PorterDuff.Mode.MULTIPLY);
- }
- if (mHeadViewPanel.getBackground() != null) {
- mHeadViewPanel.getBackground().setTint(color);
- mHeadViewPanel.getBackground().setTintMode(android.graphics.PorterDuff.Mode.MULTIPLY);
- }
+ if (colorId < 0) {
+ binding.noteEditRoot.setBackgroundColor(colorId);
} else {
- // Clear tint for legacy resources
- if (mNoteEditorPanel.getBackground() != null) {
- mNoteEditorPanel.getBackground().clearColorFilter();
- }
- if (mHeadViewPanel.getBackground() != null) {
- mHeadViewPanel.getBackground().clearColorFilter();
- }
+ binding.noteEditRoot.setBackgroundResource(ResourceParser.NoteBgResources.getNoteBgResource(colorId));
}
}
@@ -1535,13 +1535,50 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
SHORTCUT_ICON_TITLE_MAX_LEN) : content;
}
- private void showColorPickerDialog() {
- final View dialogView = LayoutInflater.from(this).inflate(R.layout.dialog_color_picker, null);
- final View colorPreview = dialogView.findViewById(R.id.view_color_preview);
- android.widget.SeekBar sbRed = dialogView.findViewById(R.id.sb_red);
- android.widget.SeekBar sbGreen = dialogView.findViewById(R.id.sb_green);
- android.widget.SeekBar sbBlue = dialogView.findViewById(R.id.sb_blue);
+ private void showBackgroundSelector() {
+ BottomSheetDialog dialog = new BottomSheetDialog(this);
+ DialogBackgroundSelectorBinding dialogBinding = DialogBackgroundSelectorBinding.inflate(getLayoutInflater());
+
+ java.util.List colors = java.util.Arrays.asList(
+ ResourceParser.YELLOW,
+ ResourceParser.BLUE,
+ ResourceParser.WHITE,
+ ResourceParser.GREEN,
+ ResourceParser.RED,
+ ResourceParser.MIDNIGHT_BLACK,
+ ResourceParser.EYE_CARE_GREEN,
+ ResourceParser.WARM,
+ ResourceParser.COOL,
+ ResourceParser.SUNSET,
+ ResourceParser.OCEAN,
+ ResourceParser.FOREST,
+ ResourceParser.LAVENDER
+ );
+
+ NoteColorAdapter adapter = new NoteColorAdapter(colors, mWorkingNote.getBgColorId(), colorId -> {
+ mWorkingNote.setBgColorId(colorId);
+ mWorkingNote.setWallpaper(null); // Clear wallpaper when color selected
+ dialog.dismiss();
+ });
+ dialogBinding.rvBackgroundOptions.setAdapter(adapter);
+
+ dialogBinding.btnPickWallpaper.setOnClickListener(v -> {
+ pickWallpaper();
+ dialog.dismiss();
+ });
+
+ dialogBinding.btnCustomColor.setOnClickListener(v -> {
+ showColorPickerDialog();
+ dialog.dismiss();
+ });
+
+ dialog.setContentView(dialogBinding.getRoot());
+ dialog.show();
+ }
+ private void showColorPickerDialog() {
+ DialogColorPickerBinding dialogBinding = DialogColorPickerBinding.inflate(getLayoutInflater());
+
int currentColor = android.graphics.Color.WHITE;
if (mWorkingNote.getBgColorId() < 0) {
currentColor = mWorkingNote.getBgColorId();
@@ -1553,10 +1590,10 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
android.graphics.Color.blue(currentColor)
};
- colorPreview.setBackgroundColor(android.graphics.Color.rgb(rgb[0], rgb[1], rgb[2]));
- sbRed.setProgress(rgb[0]);
- sbGreen.setProgress(rgb[1]);
- sbBlue.setProgress(rgb[2]);
+ dialogBinding.viewColorPreview.setBackgroundColor(android.graphics.Color.rgb(rgb[0], rgb[1], rgb[2]));
+ dialogBinding.sbRed.setProgress(rgb[0]);
+ dialogBinding.sbGreen.setProgress(rgb[1]);
+ dialogBinding.sbBlue.setProgress(rgb[2]);
android.widget.SeekBar.OnSeekBarChangeListener listener = new android.widget.SeekBar.OnSeekBarChangeListener() {
@Override
@@ -1564,7 +1601,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
if (seekBar.getId() == R.id.sb_red) rgb[0] = progress;
else if (seekBar.getId() == R.id.sb_green) rgb[1] = progress;
else if (seekBar.getId() == R.id.sb_blue) rgb[2] = progress;
- colorPreview.setBackgroundColor(android.graphics.Color.rgb(rgb[0], rgb[1], rgb[2]));
+ dialogBinding.viewColorPreview.setBackgroundColor(android.graphics.Color.rgb(rgb[0], rgb[1], rgb[2]));
}
@Override
@@ -1574,21 +1611,18 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
public void onStopTrackingTouch(android.widget.SeekBar seekBar) {}
};
- sbRed.setOnSeekBarChangeListener(listener);
- sbGreen.setOnSeekBarChangeListener(listener);
- sbBlue.setOnSeekBarChangeListener(listener);
+ dialogBinding.sbRed.setOnSeekBarChangeListener(listener);
+ dialogBinding.sbGreen.setOnSeekBarChangeListener(listener);
+ dialogBinding.sbBlue.setOnSeekBarChangeListener(listener);
new AlertDialog.Builder(this)
.setTitle("Custom Color")
- .setView(dialogView)
+ .setView(dialogBinding.getRoot())
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
int newColor = android.graphics.Color.rgb(rgb[0], rgb[1], rgb[2]);
- // Use negative integer for custom color. Ensure it's negative.
- // ARGB color with alpha 255 is negative in Java int.
- // If alpha is 0, it might be positive. We assume full opacity.
newColor |= 0xFF000000;
mWorkingNote.setBgColorId(newColor);
- mNoteBgColorSelector.setVisibility(View.GONE);
+ mWorkingNote.setWallpaper(null);
})
.setNegativeButton(android.R.string.cancel, null)
.show();
@@ -1695,27 +1729,26 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
}
private void initRichTextToolbar() {
- mRichTextSelector = findViewById(R.id.rich_text_selector);
- findViewById(R.id.btn_bold).setOnClickListener(new OnClickListener() {
+ mRichTextSelector = binding.richTextSelector;
+ binding.btnBold.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.applyBold(mNoteEditor); }
});
- findViewById(R.id.btn_italic).setOnClickListener(new OnClickListener() {
+ binding.btnItalic.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.applyItalic(mNoteEditor); }
});
- findViewById(R.id.btn_underline).setOnClickListener(new OnClickListener() {
+ binding.btnUnderline.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.applyUnderline(mNoteEditor); }
});
- findViewById(R.id.btn_strikethrough).setOnClickListener(new OnClickListener() {
+ binding.btnStrikethrough.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.applyStrikethrough(mNoteEditor); }
});
- findViewById(R.id.btn_header).setOnClickListener(new OnClickListener() {
+ binding.btnHeader.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final CharSequence[] items = {"H1 (Largest)", "H2", "H3", "H4", "H5", "H6 (Smallest)", "Normal"};
AlertDialog.Builder builder = new AlertDialog.Builder(NoteEditActivity.this);
builder.setTitle("Header Level");
builder.setItems(items, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
- // item index maps to level: 0->1, 1->2, ..., 5->6, 6->0 (Normal)
int level = (item == 6) ? 0 : (item + 1);
RichTextHelper.applyHeading(mNoteEditor, level);
}
@@ -1723,22 +1756,22 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
builder.show();
}
});
- findViewById(R.id.btn_list).setOnClickListener(new OnClickListener() {
+ binding.btnList.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.applyBullet(mNoteEditor); }
});
- findViewById(R.id.btn_quote).setOnClickListener(new OnClickListener() {
+ binding.btnQuote.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.applyQuote(mNoteEditor); }
});
- findViewById(R.id.btn_code).setOnClickListener(new OnClickListener() {
+ binding.btnCode.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.applyCode(mNoteEditor); }
});
- findViewById(R.id.btn_link).setOnClickListener(new OnClickListener() {
+ binding.btnLink.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.insertLink(NoteEditActivity.this, mNoteEditor); }
});
- findViewById(R.id.btn_divider).setOnClickListener(new OnClickListener() {
+ binding.btnDivider.setOnClickListener(new OnClickListener() {
public void onClick(View v) { RichTextHelper.insertDivider(mNoteEditor); }
});
- findViewById(R.id.btn_color_text).setOnClickListener(new OnClickListener() {
+ binding.btnColorText.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final CharSequence[] items = {"Black", "Red", "Blue"};
final int[] colors = {android.graphics.Color.BLACK, android.graphics.Color.RED, android.graphics.Color.BLUE};
@@ -1752,7 +1785,7 @@ public class NoteEditActivity extends AppCompatActivity implements OnClickListen
builder.show();
}
});
- findViewById(R.id.btn_color_fill).setOnClickListener(new OnClickListener() {
+ binding.btnColorFill.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
final CharSequence[] items = {"None", "Yellow", "Green", "Cyan"};
final int[] colors = {android.graphics.Color.TRANSPARENT, android.graphics.Color.YELLOW, android.graphics.Color.GREEN, android.graphics.Color.CYAN};
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteItemData.java b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteItemData.java
index 5e60636..5ca30f1 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteItemData.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteItemData.java
@@ -196,8 +196,8 @@ public class NoteItemData {
mIsMultiNotesFollowingFolder = false;
mIsOneNoteFollowingFolder = false;
- // 如果是普通笔记且不是第一项,检查前一项是否为文件夹
- if (mType == Notes.TYPE_NOTE && !mIsFirstItem) {
+ // 如果是普通笔记或模板且不是第一项,检查前一项是否为文件夹
+ if ((mType == Notes.TYPE_NOTE || mType == Notes.TYPE_TEMPLATE) && !mIsFirstItem) {
int position = cursor.getPosition();
if (cursor.moveToPrevious()) {
// 前一项是文件夹或系统文件夹
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteSearchActivity.java b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteSearchActivity.java
index 523120b..9fc2d88 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteSearchActivity.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NoteSearchActivity.java
@@ -154,14 +154,36 @@ public class NoteSearchActivity extends AppCompatActivity implements SearchView.
mHistoryManager.addHistory(query);
}
- Intent intent = new Intent(this, NoteEditActivity.class);
- intent.setAction(Intent.ACTION_VIEW);
- intent.putExtra(Intent.EXTRA_UID, note.getId());
- // Pass search keyword for highlighting in editor
- // NoteEditActivity uses SearchManager.EXTRA_DATA_KEY for ID and USER_QUERY for keyword
- intent.putExtra(android.app.SearchManager.EXTRA_DATA_KEY, String.valueOf(note.getId()));
- intent.putExtra(android.app.SearchManager.USER_QUERY, mSearchView.getQuery().toString());
- startActivity(intent);
+ if (note.type == Notes.TYPE_TEMPLATE) {
+ // Apply template: create a new note based on this template
+ mRepository.applyTemplate(note.getId(), Notes.ID_ROOT_FOLDER, new NotesRepository.Callback() {
+ @Override
+ public void onSuccess(Long newNoteId) {
+ runOnUiThread(() -> {
+ Intent intent = new Intent(NoteSearchActivity.this, NoteEditActivity.class);
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.putExtra(Intent.EXTRA_UID, newNoteId);
+ startActivity(intent);
+ Toast.makeText(NoteSearchActivity.this, "已根据模板创建新笔记", Toast.LENGTH_SHORT).show();
+ });
+ }
+
+ @Override
+ public void onError(Exception e) {
+ runOnUiThread(() -> {
+ Toast.makeText(NoteSearchActivity.this, "应用模板失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
+ });
+ }
+ });
+ } else {
+ Intent intent = new Intent(this, NoteEditActivity.class);
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.putExtra(Intent.EXTRA_UID, note.getId());
+ // Pass search keyword for highlighting in editor
+ intent.putExtra(android.app.SearchManager.EXTRA_DATA_KEY, String.valueOf(note.getId()));
+ intent.putExtra(android.app.SearchManager.USER_QUERY, query);
+ startActivity(intent);
+ }
}
@Override
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListFragment.java b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListFragment.java
index 260f015..2fca2c1 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListFragment.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListFragment.java
@@ -148,6 +148,30 @@ public class NotesListFragment extends Fragment implements
NotesRepository.NoteInfo note = viewModel.getNotesLiveData().getValue().get(position);
if (note.type == Notes.TYPE_FOLDER) {
viewModel.enterFolder(note.getId());
+ } else if (note.type == Notes.TYPE_TEMPLATE) {
+ // Apply template: create a new note based on this template
+ viewModel.applyTemplate(note.getId(), new net.micode.notes.data.NotesRepository.Callback() {
+ @Override
+ public void onSuccess(Long newNoteId) {
+ // Create a temporary NoteInfo to open the editor
+ net.micode.notes.data.NotesRepository.NoteInfo newNote = new net.micode.notes.data.NotesRepository.NoteInfo();
+ newNote.setId(newNoteId);
+ newNote.setParentId(Notes.ID_ROOT_FOLDER);
+ newNote.type = Notes.TYPE_NOTE;
+
+ requireActivity().runOnUiThread(() -> {
+ openNoteEditor(newNote);
+ Toast.makeText(requireContext(), "已根据模板创建新笔记", Toast.LENGTH_SHORT).show();
+ });
+ }
+
+ @Override
+ public void onError(Exception e) {
+ requireActivity().runOnUiThread(() -> {
+ Toast.makeText(requireContext(), "应用模板失败: " + e.getMessage(), Toast.LENGTH_SHORT).show();
+ });
+ }
+ });
} else {
if (note.isLocked) {
pendingNote = note;
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListItem.java b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListItem.java
index 9a6d238..38ee421 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListItem.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesListItem.java
@@ -69,7 +69,7 @@ public class NotesListItem extends LinearLayout {
* @param checked 该项是否被选中(仅在多选模式下有意义)
*/
public void bind(Context context, NoteItemData data, boolean choiceMode, boolean checked) {
- if (choiceMode && data.getType() == Notes.TYPE_NOTE) {
+ if (choiceMode && (data.getType() == Notes.TYPE_NOTE || data.getType() == Notes.TYPE_TEMPLATE)) {
mCheckBox.setVisibility(View.VISIBLE);
mCheckBox.setChecked(checked);
} else {
@@ -136,7 +136,7 @@ public class NotesListItem extends LinearLayout {
private void setBackground(NoteItemData data) {
int id = data.getBgColorId();
int resId;
- if (data.getType() == Notes.TYPE_NOTE) {
+ if (data.getType() == Notes.TYPE_NOTE || data.getType() == Notes.TYPE_TEMPLATE) {
if (data.isSingle() || data.isOneFollowingFolder()) {
resId = NoteItemBgResources.getNoteBgSingleRes(id);
} else if (data.isLast()) {
@@ -153,7 +153,7 @@ public class NotesListItem extends LinearLayout {
setBackgroundResource(resId);
// Apply tint for new colors
- if (data.getType() == Notes.TYPE_NOTE && (id >= net.micode.notes.tool.ResourceParser.MIDNIGHT_BLACK || id < 0)) {
+ if ((data.getType() == Notes.TYPE_NOTE || data.getType() == Notes.TYPE_TEMPLATE) && (id >= net.micode.notes.tool.ResourceParser.MIDNIGHT_BLACK || id < 0)) {
int color = net.micode.notes.tool.ResourceParser.getNoteBgColor(getContext(), id);
if (getBackground() != null) {
getBackground().setTint(color);
diff --git a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesRecyclerAdapter.java b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesRecyclerAdapter.java
index 5dadec7..3a5c484 100644
--- a/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesRecyclerAdapter.java
+++ b/src/Notesmaster/app/src/main/java/net/micode/notes/ui/NotesRecyclerAdapter.java
@@ -105,7 +105,7 @@ public class NotesRecyclerAdapter extends RecyclerView.Adapter path) {
folderPathLiveData.postValue(path);
- }
-
- @Override
- public void onError(Exception error) {
- Log.e(TAG, "Failed to load folder path", error);
- }
- });
-
- // 加载子文件夹 (Category Tabs) - Always load root folders to keep tabs visible
- repository.getSubFolders(Notes.ID_ROOT_FOLDER, new NotesRepository.Callback>() {
- @Override
- public void onSuccess(List folders) {
- // Construct the display list with "All" and "Uncategorized"
- List displayFolders = new ArrayList<>();
-
- // 1. "All" Folder (Virtual)
- NotesRepository.NoteInfo allFolder = new NotesRepository.NoteInfo();
- allFolder.setId(Notes.ID_ALL_NOTES_FOLDER);
- allFolder.snippet = "所有"; // Name
- displayFolders.add(allFolder);
- // 2. Real Folders (from DB)
- if (folders != null) {
- displayFolders.addAll(folders);
+ // Determine if we are in template mode
+ boolean isTemplate = (folderId == Notes.ID_TEMPLATE_FOLDER);
+ if (!isTemplate && path != null) {
+ for (NotesRepository.NoteInfo info : path) {
+ if (info.getId() == Notes.ID_TEMPLATE_FOLDER) {
+ isTemplate = true;
+ break;
+ }
+ }
}
- // 3. "Uncategorized" Folder (Actually Root Folder)
- NotesRepository.NoteInfo uncategorizedFolder = new NotesRepository.NoteInfo();
- uncategorizedFolder.setId(Notes.ID_ROOT_FOLDER);
- uncategorizedFolder.snippet = "未分类"; // Custom Name for Root
- displayFolders.add(uncategorizedFolder);
-
- foldersLiveData.postValue(displayFolders);
+ final boolean templateMode = isTemplate;
+ long tabParentId = templateMode ? Notes.ID_TEMPLATE_FOLDER : Notes.ID_ROOT_FOLDER;
+
+ // 加载子文件夹 (Category Tabs)
+ repository.getSubFolders(tabParentId, new NotesRepository.Callback>() {
+ @Override
+ public void onSuccess(List folders) {
+ // Construct the display list with "All" and "Uncategorized"
+ List displayFolders = new ArrayList<>();
+
+ // 1. "All" / "All Templates" Folder (Virtual)
+ NotesRepository.NoteInfo allFolder = new NotesRepository.NoteInfo();
+ allFolder.setId(templateMode ? Notes.ID_TEMPLATE_FOLDER : Notes.ID_ALL_NOTES_FOLDER);
+ allFolder.snippet = templateMode ? "所有模板" : "所有"; // Name
+ displayFolders.add(allFolder);
+
+ // 2. Real Folders (from DB)
+ if (folders != null) {
+ displayFolders.addAll(folders);
+ }
+
+ // 3. "Uncategorized" Folder (only for normal notes)
+ if (!templateMode) {
+ NotesRepository.NoteInfo uncategorizedFolder = new NotesRepository.NoteInfo();
+ uncategorizedFolder.setId(Notes.ID_ROOT_FOLDER);
+ uncategorizedFolder.snippet = "未分类"; // Custom Name for Root
+ displayFolders.add(uncategorizedFolder);
+ }
+
+ foldersLiveData.postValue(displayFolders);
+ }
+
+ @Override
+ public void onError(Exception error) {
+ Log.e(TAG, "Failed to load sub-folders", error);
+ }
+ });
}
-
+
@Override
public void onError(Exception error) {
- Log.e(TAG, "Failed to load sub-folders", error);
+ Log.e(TAG, "Failed to load folder path", error);
}
});
diff --git a/src/Notesmaster/app/src/main/res/drawable/bg_bottom_sheet.xml b/src/Notesmaster/app/src/main/res/drawable/bg_bottom_sheet.xml
new file mode 100644
index 0000000..a91aca0
--- /dev/null
+++ b/src/Notesmaster/app/src/main/res/drawable/bg_bottom_sheet.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Notesmaster/app/src/main/res/drawable/preset_forest.xml b/src/Notesmaster/app/src/main/res/drawable/preset_forest.xml
new file mode 100644
index 0000000..aced12d
--- /dev/null
+++ b/src/Notesmaster/app/src/main/res/drawable/preset_forest.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/src/Notesmaster/app/src/main/res/drawable/preset_lavender.xml b/src/Notesmaster/app/src/main/res/drawable/preset_lavender.xml
new file mode 100644
index 0000000..b9803bb
--- /dev/null
+++ b/src/Notesmaster/app/src/main/res/drawable/preset_lavender.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/src/Notesmaster/app/src/main/res/drawable/preset_ocean.xml b/src/Notesmaster/app/src/main/res/drawable/preset_ocean.xml
new file mode 100644
index 0000000..dd2e1ee
--- /dev/null
+++ b/src/Notesmaster/app/src/main/res/drawable/preset_ocean.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/src/Notesmaster/app/src/main/res/drawable/preset_sunset.xml b/src/Notesmaster/app/src/main/res/drawable/preset_sunset.xml
new file mode 100644
index 0000000..802f1ca
--- /dev/null
+++ b/src/Notesmaster/app/src/main/res/drawable/preset_sunset.xml
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/src/Notesmaster/app/src/main/res/layout/dialog_background_selector.xml b/src/Notesmaster/app/src/main/res/layout/dialog_background_selector.xml
new file mode 100644
index 0000000..3f50cf6
--- /dev/null
+++ b/src/Notesmaster/app/src/main/res/layout/dialog_background_selector.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Notesmaster/app/src/main/res/layout/note_edit.xml b/src/Notesmaster/app/src/main/res/layout/note_edit.xml
index aba7781..5bacd39 100644
--- a/src/Notesmaster/app/src/main/res/layout/note_edit.xml
+++ b/src/Notesmaster/app/src/main/res/layout/note_edit.xml
@@ -15,482 +15,258 @@
limitations under the License.
-->
-
-
+ android:background="@color/background_color">
-
-
+
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ android:visibility="gone" />
-
-
-
-
+ android:layout_height="match_parent"
+ android:background="#1A000000"
+ android:visibility="gone" />
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+ android:layout_height="?attr/actionBarSize"
+ android:background="@android:color/transparent"
+ app:navigationIcon="@android:drawable/ic_menu_close_clear_cancel"
+ app:title="@string/menu_edit_note"
+ app:titleTextAppearance="@style/TextAppearance.Material3.TitleMedium" />
+
+
+
+
-
-
-
-
+
+
+
+ android:layout_height="wrap_content"
+ app:cardCornerRadius="24dp"
+ app:cardElevation="0dp"
+ app:cardBackgroundColor="#CCFFFFFF"
+ app:strokeWidth="0dp">
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="24dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:textSize="18sp"
+ android:textColor="@color/text_color_primary"
+ android:lineSpacingMultiplier="1.5"
+ android:fontFamily="sans-serif" />
-
-
-
+
+
-
-
+
+
+
+
+
+ android:layout_height="56dp"
+ android:scrollbars="none">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:gravity="center_vertical"
+ android:paddingHorizontal="12dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Notesmaster/app/src/main/res/values/colors.xml b/src/Notesmaster/app/src/main/res/values/colors.xml
index 8c4a5a3..6405010 100644
--- a/src/Notesmaster/app/src/main/res/values/colors.xml
+++ b/src/Notesmaster/app/src/main/res/values/colors.xml
@@ -43,6 +43,16 @@
#FFE0B2
#E1BEE7
+
+ #FF512F
+ #DD2476
+ #2193B0
+ #6DD5ED
+ #11998E
+ #38EF7D
+ #834D9B
+ #D04ED6
+
#1976D2
#2196F3