feat: Notes core service + Notes API + router auto-detect notes context

- Add internal/core/notes/ service (Service, Layout, Normalize, tests)
- Register verstak/core/notes/v1 capability
- Inject NotesService into App, expose 8 Notes API endpoints
  (CreateNote, RenameNote, ReadNote, SaveNote, EnsureOverview,
   ListNotes, SearchNotes, NormalizeNoteTitle)
- Router: auto-detect Notes context via path (IsInsideNotes)
- PluginCard: show workspaceItems contribution count
- Regenerate Wails bindings (App.d.ts, App.js, models.ts with notes.NoteInfo)
- Fix .gitignore pattern for e2e-results/
This commit is contained in:
2026-06-21 23:22:36 +08:00
parent 0b6b0d0926
commit 03175aa46d
13 changed files with 1367 additions and 4 deletions
@@ -33,6 +33,7 @@
sidebar: (contributions.sidebarItems || []).filter(s => s.pluginId === pluginId).length,
statusbar: (contributions.statusBarItems || []).filter(s => s.pluginId === pluginId).length,
openProviders: (contributions.openProviders || []).filter(o => o.pluginId === pluginId).length,
workspaceItems: (contributions.workspaceItems || []).filter(w => w.pluginId === pluginId).length,
};
$: contribSummary = (() => {
@@ -42,6 +43,7 @@
if (contribCounts.sidebar > 0) parts.push(contribCounts.sidebar + ' sidebar' + (contribCounts.sidebar !== 1 ? 's' : ''));
if (contribCounts.statusbar > 0) parts.push(contribCounts.statusbar + ' statusbar' + (contribCounts.statusbar !== 1 ? 's' : ''));
if (contribCounts.openProviders > 0) parts.push(contribCounts.openProviders + ' openProvider' + (contribCounts.openProviders !== 1 ? 's' : ''));
if (contribCounts.workspaceItems > 0) parts.push(contribCounts.workspaceItems + ' workspace' + (contribCounts.workspaceItems !== 1 ? 's' : ''));
return parts.length > 0 ? parts.join(', ') : 'none';
})();
+17
View File
@@ -7,11 +7,14 @@ import {api} from '../models';
import {permissions} from '../models';
import {plugin} from '../models';
import {files} from '../models';
import {notes} from '../models';
export function ArchiveWorkspaceNode(arg1:string):Promise<string>;
export function CloseVault():Promise<void>;
export function CreateNote(arg1:string,arg2:string):Promise<Record<string, any>|string>;
export function CreateVault(arg1:string):Promise<void>;
export function CreateVaultFolder(arg1:string,arg2:string):Promise<string>;
@@ -26,6 +29,8 @@ export function EditWorkbenchResource(arg1:string,arg2:Record<string, any>):Prom
export function EnablePlugin(arg1:string):Promise<string>;
export function EnsureOverview(arg1:string):Promise<Record<string, any>|string>;
export function ExecutePluginCommand(arg1:string,arg2:string,arg3:Record<string, any>):Promise<Record<string, any>|string>;
export function GetAppSettings():Promise<Record<string, any>>;
@@ -62,6 +67,8 @@ export function GetWorkspaceMetadata(arg1:string):Promise<workspace.Metadata|str
export function GetWorkspaceTree():Promise<Record<string, any>>;
export function ListNotes(arg1:string):Promise<Array<notes.NoteInfo>|string>;
export function ListPluginCapabilities(arg1:string):Promise<Array<capability.Entry>|string>;
export function ListVaultFiles(arg1:string,arg2:string):Promise<Array<files.FileEntry>|string>;
@@ -72,12 +79,16 @@ export function MoveVaultPath(arg1:string,arg2:string,arg3:string,arg4:files.Mov
export function MoveWorkspaceNode(arg1:string,arg2:string):Promise<string>;
export function NormalizeNoteTitle(arg1:string):Promise<Record<string, any>|string>;
export function OpenVault(arg1:string):Promise<void>;
export function OpenWorkbenchResource(arg1:string,arg2:Record<string, any>):Promise<workbench.OpenResourceResult|string>;
export function PublishPluginEvent(arg1:string,arg2:string,arg3:Record<string, any>):Promise<string>;
export function ReadNote(arg1:string):Promise<Record<string, any>|string>;
export function ReadPluginDataJSON(arg1:string,arg2:string):Promise<Record<string, any>>;
export function ReadPluginSetting(arg1:string,arg2:string):Promise<any>;
@@ -90,12 +101,18 @@ export function RecordDesiredPlugin(arg1:string,arg2:string,arg3:string):Promise
export function ReloadPlugins():Promise<number|string>;
export function RenameNote(arg1:string,arg2:string):Promise<Record<string, any>|string>;
export function RenameWorkspace(arg1:string,arg2:string):Promise<string>;
export function RenameWorkspaceNode(arg1:string,arg2:string):Promise<string>;
export function ResetSyncKey():Promise<void>;
export function SaveNote(arg1:string,arg2:string):Promise<string>;
export function SearchNotes(arg1:string):Promise<Array<notes.NoteInfo>|string>;
export function SelectDirectory():Promise<string>;
export function SelectVaultForOpen():Promise<string>;
+32
View File
@@ -10,6 +10,10 @@ export function CloseVault() {
return window['go']['api']['App']['CloseVault']();
}
export function CreateNote(arg1, arg2) {
return window['go']['api']['App']['CreateNote'](arg1, arg2);
}
export function CreateVault(arg1) {
return window['go']['api']['App']['CreateVault'](arg1);
}
@@ -38,6 +42,10 @@ export function EnablePlugin(arg1) {
return window['go']['api']['App']['EnablePlugin'](arg1);
}
export function EnsureOverview(arg1) {
return window['go']['api']['App']['EnsureOverview'](arg1);
}
export function ExecutePluginCommand(arg1, arg2, arg3) {
return window['go']['api']['App']['ExecutePluginCommand'](arg1, arg2, arg3);
}
@@ -110,6 +118,10 @@ export function GetWorkspaceTree() {
return window['go']['api']['App']['GetWorkspaceTree']();
}
export function ListNotes(arg1) {
return window['go']['api']['App']['ListNotes'](arg1);
}
export function ListPluginCapabilities(arg1) {
return window['go']['api']['App']['ListPluginCapabilities'](arg1);
}
@@ -130,6 +142,10 @@ export function MoveWorkspaceNode(arg1, arg2) {
return window['go']['api']['App']['MoveWorkspaceNode'](arg1, arg2);
}
export function NormalizeNoteTitle(arg1) {
return window['go']['api']['App']['NormalizeNoteTitle'](arg1);
}
export function OpenVault(arg1) {
return window['go']['api']['App']['OpenVault'](arg1);
}
@@ -142,6 +158,10 @@ export function PublishPluginEvent(arg1, arg2, arg3) {
return window['go']['api']['App']['PublishPluginEvent'](arg1, arg2, arg3);
}
export function ReadNote(arg1) {
return window['go']['api']['App']['ReadNote'](arg1);
}
export function ReadPluginDataJSON(arg1, arg2) {
return window['go']['api']['App']['ReadPluginDataJSON'](arg1, arg2);
}
@@ -166,6 +186,10 @@ export function ReloadPlugins() {
return window['go']['api']['App']['ReloadPlugins']();
}
export function RenameNote(arg1, arg2) {
return window['go']['api']['App']['RenameNote'](arg1, arg2);
}
export function RenameWorkspace(arg1, arg2) {
return window['go']['api']['App']['RenameWorkspace'](arg1, arg2);
}
@@ -178,6 +202,14 @@ export function ResetSyncKey() {
return window['go']['api']['App']['ResetSyncKey']();
}
export function SaveNote(arg1, arg2) {
return window['go']['api']['App']['SaveNote'](arg1, arg2);
}
export function SearchNotes(arg1) {
return window['go']['api']['App']['SearchNotes'](arg1);
}
export function SelectDirectory() {
return window['go']['api']['App']['SelectDirectory']();
}
+25
View File
@@ -380,6 +380,31 @@ export namespace files {
}
export namespace notes {
export class NoteInfo {
title: string;
filename: string;
path: string;
parentPath: string;
isOverview: boolean;
static createFrom(source: any = {}) {
return new NoteInfo(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.title = source["title"];
this.filename = source["filename"];
this.path = source["path"];
this.parentPath = source["parentPath"];
this.isOverview = source["isOverview"];
}
}
}
export namespace permissions {
export class Entry {