0.4.0 convex及界面修改

This commit is contained in:
liaibo
2026-02-01 08:47:40 +08:00
parent d1f055f51a
commit af92c4b149
636 changed files with 7522 additions and 1815 deletions
+112
View File
@@ -0,0 +1,112 @@
"use client";
import { create } from "zustand";
export type ThemeMode = "system" | "light" | "dark";
type PersistedPreferences = {
theme: ThemeMode;
showStructure: boolean;
spellCheck: boolean;
flightMode: boolean;
};
const STORAGE_KEY = "mnote:preferences:v1";
const loadPersisted = (): PersistedPreferences | null => {
if (typeof window === "undefined") return null;
try {
const raw = window.localStorage.getItem(STORAGE_KEY);
if (!raw) return null;
const parsed = JSON.parse(raw) as Partial<PersistedPreferences>;
const theme = parsed.theme === "light" || parsed.theme === "dark" || parsed.theme === "system" ? parsed.theme : "system";
return {
theme,
showStructure: typeof parsed.showStructure === "boolean" ? parsed.showStructure : false,
spellCheck: typeof parsed.spellCheck === "boolean" ? parsed.spellCheck : false,
flightMode: typeof parsed.flightMode === "boolean" ? parsed.flightMode : false,
};
} catch {
return null;
}
};
const persist = (value: PersistedPreferences) => {
if (typeof window === "undefined") return;
try {
window.localStorage.setItem(STORAGE_KEY, JSON.stringify(value));
} catch {
// ignore
}
};
interface AppPreferencesState extends PersistedPreferences {
hydrated: boolean;
hydrate: () => void;
setTheme: (theme: ThemeMode) => void;
setShowStructure: (showStructure: boolean) => void;
setSpellCheck: (spellCheck: boolean) => void;
setFlightMode: (flightMode: boolean) => void;
}
export const useAppPreferencesStore = create<AppPreferencesState>((set, get) => ({
hydrated: false,
theme: "system",
showStructure: false,
spellCheck: false,
flightMode: false,
hydrate: () => {
const current = get();
if (current.hydrated) return;
const persisted = loadPersisted();
if (persisted) {
set({ ...persisted, hydrated: true });
} else {
set({ hydrated: true });
}
},
setTheme: (theme) =>
set((state) => {
const next = { ...state, theme };
persist({
theme: next.theme,
showStructure: next.showStructure,
spellCheck: next.spellCheck,
flightMode: next.flightMode,
});
return next;
}),
setShowStructure: (showStructure) =>
set((state) => {
const next = { ...state, showStructure };
persist({
theme: next.theme,
showStructure: next.showStructure,
spellCheck: next.spellCheck,
flightMode: next.flightMode,
});
return next;
}),
setSpellCheck: (spellCheck) =>
set((state) => {
const next = { ...state, spellCheck };
persist({
theme: next.theme,
showStructure: next.showStructure,
spellCheck: next.spellCheck,
flightMode: next.flightMode,
});
return next;
}),
setFlightMode: (flightMode) =>
set((state) => {
const next = { ...state, flightMode };
persist({
theme: next.theme,
showStructure: next.showStructure,
spellCheck: next.spellCheck,
flightMode: next.flightMode,
});
return next;
}),
}));
+34
View File
@@ -0,0 +1,34 @@
"use client";
import { create } from "zustand";
export type CommentTarget = {
workspaceId: string;
documentId: string;
blockId: string | null;
};
interface CommentsUiState {
open: boolean;
target: CommentTarget | null;
openForPage: (args: { workspaceId: string; documentId: string }) => void;
openForBlock: (args: { workspaceId: string; documentId: string; blockId: string }) => void;
close: () => void;
}
export const useCommentsUiStore = create<CommentsUiState>((set) => ({
open: false,
target: null,
openForPage: ({ workspaceId, documentId }) =>
set({
open: true,
target: { workspaceId, documentId, blockId: null },
}),
openForBlock: ({ workspaceId, documentId, blockId }) =>
set({
open: true,
target: { workspaceId, documentId, blockId },
}),
close: () => set({ open: false }),
}));
+13
View File
@@ -12,11 +12,24 @@ export interface EditorReferenceBridgeResult {
export interface EditorReferenceBridge {
insertInlineReference: (target: ReferenceTarget, alias?: string) => EditorReferenceBridgeResult;
insertEmbedReference: (target: ReferenceTarget) => EditorReferenceBridgeResult;
undo?: () => void;
redo?: () => void;
getCursorBlockId?: () => string | null;
/**
* 向当前打开的文档插入一个“附件/媒体”块。
* 主要用于侧边栏文件树拖拽上传后,把文件显示到主编辑区。
*/
insertMediaAsset?: (asset: MediaAsset) => void;
/**
* 向当前打开的文档插入一个“思维导图”块(使用 mindmapId 作为 block.id)。
* 主要用于侧边栏垃圾桶“恢复思维导图”后,把导图重新显示到主编辑区。
*/
insertMindmapAsset?: (args: { documentId: string; mindmapId: string }) => void;
/**
* 向当前打开的文档插入一个“在线表格(luckysheet)”块。
* 主要用于侧边栏垃圾桶“恢复表格”后,把表格重新显示到主编辑区。
*/
insertOnlineTableAsset?: (args: { documentId: string; tableId: string }) => void;
replaceWithSnapshot: (blocks: Json) => void;
openTableFullScreen?: (tableId: string) => void;
}