mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-07 14:52:39 +02:00
feat: update status handling and connection indicator in SurfSense plugin
- Changed initial status to "needs-setup" to prompt user configuration. - Added a refreshStatus method to SyncEngine for immediate status updates after settings changes. - Enhanced connection indicator logic in the settings tab to reflect the new status. - Introduced "needs-setup" status visual for improved user feedback on configuration requirements.
This commit is contained in:
parent
68156d2e74
commit
4f1c870987
5 changed files with 51 additions and 5 deletions
|
|
@ -20,7 +20,7 @@ export default class SurfSensePlugin extends Plugin {
|
||||||
queue!: PersistentQueue;
|
queue!: PersistentQueue;
|
||||||
engine!: SyncEngine;
|
engine!: SyncEngine;
|
||||||
private statusBar: StatusBar | null = null;
|
private statusBar: StatusBar | null = null;
|
||||||
lastStatus: StatusState = { kind: "idle", queueDepth: 0 };
|
lastStatus: StatusState = { kind: "needs-setup", queueDepth: 0 };
|
||||||
serverCapabilities: string[] = [];
|
serverCapabilities: string[] = [];
|
||||||
private settingTab: SurfSenseSettingTab | null = null;
|
private settingTab: SurfSenseSettingTab | null = null;
|
||||||
private statusListeners = new Set<() => void>();
|
private statusListeners = new Set<() => void>();
|
||||||
|
|
@ -265,6 +265,9 @@ export default class SurfSensePlugin extends Plugin {
|
||||||
|
|
||||||
async saveSettings() {
|
async saveSettings() {
|
||||||
await this.saveData(this.settings);
|
await this.saveData(this.settings);
|
||||||
|
// Ensures the indicator reacts to settings edits (token paste, search-space pick)
|
||||||
|
// without waiting for the next sync trigger.
|
||||||
|
this.engine?.refreshStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ export class SurfSenseSettingTab extends PluginSettingTab {
|
||||||
private readonly plugin: SurfSensePlugin;
|
private readonly plugin: SurfSensePlugin;
|
||||||
private searchSpaces: SearchSpace[] = [];
|
private searchSpaces: SearchSpace[] = [];
|
||||||
private loadingSpaces = false;
|
private loadingSpaces = false;
|
||||||
|
private connectionIndicator: HTMLElement | null = null;
|
||||||
|
private readonly onStatusChange = (): void => this.updateConnectionIndicator();
|
||||||
|
|
||||||
constructor(app: App, plugin: SurfSensePlugin) {
|
constructor(app: App, plugin: SurfSensePlugin) {
|
||||||
super(app, plugin);
|
super(app, plugin);
|
||||||
|
|
@ -29,6 +31,7 @@ export class SurfSenseSettingTab extends PluginSettingTab {
|
||||||
display(): void {
|
display(): void {
|
||||||
const { containerEl } = this;
|
const { containerEl } = this;
|
||||||
containerEl.empty();
|
containerEl.empty();
|
||||||
|
this.plugin.onStatusChange(this.onStatusChange);
|
||||||
|
|
||||||
const settings = this.plugin.settings;
|
const settings = this.plugin.settings;
|
||||||
|
|
||||||
|
|
@ -279,13 +282,26 @@ export class SurfSenseSettingTab extends PluginSettingTab {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hide(): void {
|
||||||
|
this.plugin.offStatusChange(this.onStatusChange);
|
||||||
|
this.connectionIndicator = null;
|
||||||
|
}
|
||||||
|
|
||||||
private renderConnectionHeading(containerEl: HTMLElement): void {
|
private renderConnectionHeading(containerEl: HTMLElement): void {
|
||||||
const heading = new Setting(containerEl).setName("Connection").setHeading();
|
const heading = new Setting(containerEl).setName("Connection").setHeading();
|
||||||
heading.nameEl.addClass("surfsense-connection-heading");
|
heading.nameEl.addClass("surfsense-connection-heading");
|
||||||
const indicator = heading.nameEl.createSpan({
|
this.connectionIndicator = heading.nameEl.createSpan({
|
||||||
cls: "surfsense-connection-indicator",
|
cls: "surfsense-connection-indicator",
|
||||||
});
|
});
|
||||||
|
this.updateConnectionIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateConnectionIndicator(): void {
|
||||||
|
const indicator = this.connectionIndicator;
|
||||||
|
if (!indicator) return;
|
||||||
const visual = STATUS_VISUALS[this.plugin.lastStatus.kind];
|
const visual = STATUS_VISUALS[this.plugin.lastStatus.kind];
|
||||||
|
indicator.empty();
|
||||||
|
indicator.removeClass("surfsense-connection-indicator--err");
|
||||||
if (visual.isError) {
|
if (visual.isError) {
|
||||||
indicator.addClass("surfsense-connection-indicator--err");
|
indicator.addClass("surfsense-connection-indicator--err");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ export const STATUS_VISUALS: Record<StatusKind, StatusVisual> = {
|
||||||
idle: { icon: "check-circle", label: "Synced", isError: false },
|
idle: { icon: "check-circle", label: "Synced", isError: false },
|
||||||
syncing: { icon: "refresh-ccw", label: "Syncing", isError: false },
|
syncing: { icon: "refresh-ccw", label: "Syncing", isError: false },
|
||||||
queued: { icon: "clock", label: "Queued", isError: false },
|
queued: { icon: "clock", label: "Queued", isError: false },
|
||||||
|
"needs-setup": { icon: "cloud-off", label: "Setup required", isError: false },
|
||||||
offline: { icon: "wifi-off", label: "Offline", isError: false },
|
offline: { icon: "wifi-off", label: "Offline", isError: false },
|
||||||
"auth-error": { icon: "user-x", label: "Reauthenticate", isError: true },
|
"auth-error": { icon: "alert-circle", label: "Reauthenticate", isError: true },
|
||||||
error: { icon: "alert-circle", label: "Error", isError: true },
|
error: { icon: "alert-circle", label: "Error", isError: true },
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ export interface SyncEngineDeps {
|
||||||
|
|
||||||
export interface SyncEngineSettings {
|
export interface SyncEngineSettings {
|
||||||
vaultId: string;
|
vaultId: string;
|
||||||
|
apiToken: string;
|
||||||
connectorId: number | null;
|
connectorId: number | null;
|
||||||
searchSpaceId: number | null;
|
searchSpaceId: number | null;
|
||||||
includeFolders: string[];
|
includeFolders: string[];
|
||||||
|
|
@ -103,7 +104,7 @@ export class SyncEngine {
|
||||||
this.handleStartupError(err);
|
this.handleStartupError(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.setStatus("idle", "Pick a search space in settings to start syncing.");
|
this.setStatus("idle");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,7 +124,7 @@ export class SyncEngine {
|
||||||
async ensureConnected(): Promise<boolean> {
|
async ensureConnected(): Promise<boolean> {
|
||||||
const settings = this.deps.getSettings();
|
const settings = this.deps.getSettings();
|
||||||
if (!settings.searchSpaceId) {
|
if (!settings.searchSpaceId) {
|
||||||
this.setStatus("idle", "Pick a search space in settings.");
|
this.setStatus("idle");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.setStatus("syncing", "Connecting to SurfSense");
|
this.setStatus("syncing", "Connecting to SurfSense");
|
||||||
|
|
@ -500,10 +501,34 @@ export class SyncEngine {
|
||||||
|
|
||||||
// ---- status helpers ---------------------------------------------------
|
// ---- status helpers ---------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recomputes status from settings + queue depth. Call from main.ts after
|
||||||
|
* settings change so the indicator reacts to token paste / search-space
|
||||||
|
* pick without waiting for the next sync trigger.
|
||||||
|
*/
|
||||||
|
refreshStatus(): void {
|
||||||
|
this.setStatus(this.queueStatusKind(), this.statusDetail());
|
||||||
|
}
|
||||||
|
|
||||||
private setStatus(kind: StatusKind, detail?: string): void {
|
private setStatus(kind: StatusKind, detail?: string): void {
|
||||||
|
// Errors carry meaningful signal; only "happy" kinds get downgraded
|
||||||
|
// to needs-setup when prerequisites are missing.
|
||||||
|
if (kind !== "auth-error" && kind !== "offline" && kind !== "error") {
|
||||||
|
const s = this.deps.getSettings();
|
||||||
|
if (!s.apiToken || !s.searchSpaceId || !s.connectorId) {
|
||||||
|
kind = "needs-setup";
|
||||||
|
detail = this.setupHint(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
this.deps.setStatus({ kind, detail, queueDepth: this.deps.queue.size });
|
this.deps.setStatus({ kind, detail, queueDepth: this.deps.queue.size });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private setupHint(s: SyncEngineSettings): string {
|
||||||
|
if (!s.apiToken) return "Paste your API token in settings.";
|
||||||
|
if (!s.searchSpaceId) return "Pick a search space in settings.";
|
||||||
|
return "Connecting…";
|
||||||
|
}
|
||||||
|
|
||||||
private queueStatusKind(): StatusKind {
|
private queueStatusKind(): StatusKind {
|
||||||
if (this.deps.queue.size > 0) return "queued";
|
if (this.deps.queue.size > 0) return "queued";
|
||||||
return "idle";
|
return "idle";
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,7 @@ export type StatusKind =
|
||||||
| "idle"
|
| "idle"
|
||||||
| "syncing"
|
| "syncing"
|
||||||
| "queued"
|
| "queued"
|
||||||
|
| "needs-setup"
|
||||||
| "offline"
|
| "offline"
|
||||||
| "auth-error"
|
| "auth-error"
|
||||||
| "error";
|
| "error";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue