feat(settings,docs): vault subpath becomes the chats folder, panel screenshots in the readme

This commit is contained in:
hh
2026-09-05 04:56:03 +02:00
parent 223560c8da
commit 43d1e1a4a3
10 changed files with 43 additions and 26 deletions
+15 -6
View File
@@ -230,7 +230,16 @@ export default class BeaverPlugin extends Plugin {
}
async loadSettings(): Promise<void> {
this.settings = { ...DEFAULT_SETTINGS, ...(await this.loadData()) };
const stored = ((await this.loadData()) ??
{}) as Partial<BeaverSettings> & {
vaultSubpath?: string;
};
// The setting used to be called "vault subpath"; carry the value over.
const { vaultSubpath, ...rest } = stored;
this.settings = { ...DEFAULT_SETTINGS, ...rest };
if (vaultSubpath && !rest.chatsFolder) {
this.settings.chatsFolder = vaultSubpath;
}
}
async saveSettings(): Promise<void> {
@@ -431,16 +440,16 @@ export default class BeaverPlugin extends Plugin {
}
private gatewayFilename(file: TFile): string | null {
const subpath = this.settings.vaultSubpath;
if (!subpath) {
const folder = this.settings.chatsFolder;
if (!folder) {
return file.path;
}
const prefix = `${subpath}/`;
if (file.path === subpath || file.path.startsWith(prefix)) {
const prefix = `${folder}/`;
if (file.path === folder || file.path.startsWith(prefix)) {
return file.path.slice(prefix.length);
}
new Notice(
`Beaver: file ${file.path} is outside the configured vault subpath (${subpath})`,
`Beaver: file ${file.path} is outside the chats folder (${folder})`,
8000
);
return null;
+11 -8
View File
@@ -5,18 +5,20 @@ import type BeaverPlugin from "./main";
export interface BeaverSettings {
apiBaseUrl: string;
baseUrl: string;
// Folder in this vault where the deep chats live: the gateway's markdown
// frontend reads and writes there, so paths it hands out are relative to it.
chatsFolder: string;
token: string;
vaultSubpath: string;
}
export const DEFAULT_SETTINGS: BeaverSettings = {
apiBaseUrl: "",
baseUrl: "http://localhost:62993",
chatsFolder: "",
token: "",
vaultSubpath: "",
};
export function normalizeSubpath(raw: string): string {
export function normalizeFolder(raw: string): string {
return raw.trim().replace(/^\/+|\/+$/g, "");
}
@@ -93,17 +95,18 @@ export class BeaverSettingsTab extends PluginSettingTab {
});
new Setting(containerEl)
.setName("Vault subpath")
.setName("Chats folder")
.setDesc(
"Folder in this Obsidian vault that maps to the gateway's vault root. " +
"Leave empty if the two vault roots match. Example: `💬 чаты`."
"Folder in this vault where the deep chats live - the one the gateway's " +
"markdown frontend writes to. Leave empty if the chats sit at the vault root. " +
"Example: `💬 чаты`."
)
.addText((text) =>
text
.setPlaceholder("")
.setValue(this.plugin.settings.vaultSubpath)
.setValue(this.plugin.settings.chatsFolder)
.onChange(async (value) => {
this.plugin.settings.vaultSubpath = normalizeSubpath(value);
this.plugin.settings.chatsFolder = normalizeFolder(value);
await this.plugin.saveSettings();
})
);
+3 -3
View File
@@ -14,14 +14,14 @@
interface Props {
app: ObsidianApp;
chatsFolder: () => string;
client: ApiClient | null;
component: Component;
onOpenSettings: () => void;
state: PanelState;
vaultSubpath: () => string;
}
let { app, client, component, onOpenSettings, state, vaultSubpath }: Props =
let { app, client, component, onOpenSettings, state, chatsFolder }: Props =
$props();
// Menus hang off body, not off the view: Obsidian's sidedocks paint above
@@ -41,9 +41,9 @@
const host = providePanelHost({
...obsidianHost({
app,
chatsFolder,
component,
sourcePath: () => state.sourcePath,
vaultSubpath,
}),
cache,
});
+5 -4
View File
@@ -4,11 +4,12 @@ import type { PanelHost } from "$lib/panel/host";
export interface HostOptions {
app: App;
// Folder in this vault that maps to the gateway's vault root.
// Where the deep chats live in this vault; gateway paths are relative to it.
chatsFolder: () => string;
component: Component;
// The note the panel currently follows; link resolution starts from it.
sourcePath: () => string;
// Folder in this vault that maps to the gateway's vault root.
vaultSubpath: () => string;
}
// The Obsidian side of the panel: markdown through the app's own renderer,
@@ -47,8 +48,8 @@ export function obsidianHost(options: HostOptions): PanelHost {
window.open(target);
},
openNote(path) {
const subpath = options.vaultSubpath();
const full = subpath ? `${subpath}/${path}` : path;
const folder = options.chatsFolder();
const full = folder ? `${folder}/${path}` : path;
app.workspace.openLinkText(full, "", false).catch(() => undefined);
},
touch: Platform.isMobile,
+1 -1
View File
@@ -231,11 +231,11 @@ export class PanelView extends ItemView {
this.root = mount(App, {
props: {
app: this.app,
chatsFolder: () => this.plugin.settings.chatsFolder,
client: this.plugin.apiClient(),
component: this,
onOpenSettings: () => this.plugin.openSettings(),
state: this.state,
vaultSubpath: () => this.plugin.settings.vaultSubpath,
},
target: this.contentEl,
});