Add database for representing the data.json instead of just settings

This commit is contained in:
Andras Schmelczer 2024-12-10 21:37:19 +00:00
commit a38c15db95
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
3 changed files with 178 additions and 78 deletions

View file

@ -0,0 +1,153 @@
import { Logger } from "src/logger";
export type DocumentId = string;
export type DocumentVersionId = number;
export type RelativePath = string;
export interface SyncSettings {
remoteUri: string;
token: string;
fullScanIntervalInSeconds: number;
fullScanEnabled: boolean;
}
export const DEFAULT_SETTINGS: SyncSettings = {
remoteUri: "",
token: "",
fullScanIntervalInSeconds: 60,
fullScanEnabled: true,
};
export interface DocumentMetadata {
documentId: DocumentId;
parentVersionId: DocumentVersionId;
}
interface StoredDatabase {
documents: Map<RelativePath, DocumentMetadata>;
settings: SyncSettings;
}
export class Database {
private _documents: Map<RelativePath, DocumentMetadata> = new Map();
private _settings: SyncSettings;
private onSettingsChangeHandlers: Array<(settings: SyncSettings) => void> =
[];
public constructor(
initialState: Partial<StoredDatabase> | undefined,
private saveData: (data: any) => Promise<void>
) {
initialState = initialState || {};
if (
Object.prototype.hasOwnProperty.call(initialState, "documents") &&
initialState.documents
) {
for (const [relativePath, metadata] of Object.entries(
initialState.documents
)) {
this._documents.set(relativePath, metadata as DocumentMetadata);
}
}
Logger.getInstance().debug(
`Loaded documents ${JSON.stringify(
Object.fromEntries(this._documents.entries()),
null,
2
)}`
);
this._settings = Object.assign(
{},
DEFAULT_SETTINGS,
initialState.settings || {}
);
Logger.getInstance().debug(
`Loaded settings ${JSON.stringify(this._settings, null, 2)}`
);
}
public getSettings(): SyncSettings {
return this._settings;
}
public async setSettings(value: SyncSettings): Promise<void> {
this._settings = value;
this.onSettingsChangeHandlers.forEach((handler) => handler(value));
await this.save();
}
public addOnSettingsChangeHandlers(
handler: (settings: SyncSettings) => void
) {
this.onSettingsChangeHandlers.push(handler);
}
public async setSetting<T extends keyof SyncSettings>(
key: T,
value: SyncSettings[T]
): Promise<void> {
this._settings[key] = value;
Logger.getInstance().debug(
`Setting ${key} to ${value}, new settings: ${JSON.stringify(
this._settings
)}`
);
await this.setSettings(this._settings);
}
public async setDocument({
relativePath,
documentId,
parentVersionId,
}: {
relativePath: RelativePath;
documentId: DocumentId;
parentVersionId: DocumentVersionId;
}): Promise<void> {
this._documents.set(relativePath, {
documentId,
parentVersionId,
});
await this.save();
}
public async moveDocument({
oldRelativePath,
relativePath,
documentId,
parentVersionId,
}: {
oldRelativePath: RelativePath;
relativePath: RelativePath;
documentId: DocumentId;
parentVersionId: DocumentVersionId;
}): Promise<void> {
this._documents.delete(oldRelativePath);
this._documents.set(relativePath, {
documentId,
parentVersionId,
});
await this.save();
}
public async removeDocument(relativePath: RelativePath): Promise<void> {
this._documents.delete(relativePath);
await this.save();
}
public getDocument(
relativePath: RelativePath
): DocumentMetadata | undefined {
return this._documents.get(relativePath);
}
private async save(): Promise<void> {
await this.saveData({
documents: Object.fromEntries(this._documents.entries()),
settings: this._settings,
});
}
}

View file

@ -1,57 +0,0 @@
import { Logger } from "src/logger";
import SyncPlugin from "src/plugin";
export interface SyncSettings {
remoteUri: string;
token: string;
fullScanIntervalInSeconds: number;
fullScanEnabled: boolean;
}
export const DEFAULT_SETTINGS: SyncSettings = {
remoteUri: "",
token: "",
fullScanIntervalInSeconds: 60,
fullScanEnabled: true,
};
export class SettingsContainer {
private _settings: SyncSettings;
private onChangeHandlers: Array<(settings: SyncSettings) => void> = [];
public constructor(private plugin: SyncPlugin, loadedSettings: any) {
Logger.getInstance().debug(
"Loaded settings " + JSON.stringify(loadedSettings, null, 2)
);
this._settings = Object.assign({}, DEFAULT_SETTINGS, loadedSettings);
}
public onChange(handler: (settings: SyncSettings) => void) {
this.onChangeHandlers.push(handler);
}
public getSettings(): SyncSettings {
return this._settings;
}
public async setSettings(value: SyncSettings): Promise<void> {
this._settings = value;
await this.plugin.saveData(value);
this.onChangeHandlers.forEach((handler) => handler(value));
}
public async setSetting<T extends keyof SyncSettings>(
key: T,
value: SyncSettings[T]
): Promise<void> {
this._settings[key] = value;
Logger.getInstance().debug(
`Setting ${key} to ${value}, new settings: ${JSON.stringify(
this._settings
)}`
);
await this.plugin.saveData(this._settings);
this.onChangeHandlers.forEach((handler) => handler(this._settings));
}
}

View file

@ -10,18 +10,17 @@ import {
} from "obsidian"; } from "obsidian";
import SyncPlugin from "src/plugin.js"; import SyncPlugin from "src/plugin.js";
import { SettingsContainer } from "./settings"; import { Database } from "src/database/database";
import { SyncServer } from "src/services/sync_service";
export class SyncSettingsTab extends PluginSettingTab { export class SyncSettingsTab extends PluginSettingTab {
plugin: SyncPlugin;
constructor( constructor(
app: App, app: App,
plugin: SyncPlugin, plugin: SyncPlugin,
private settingsContainer: SettingsContainer private database: Database,
private syncServer: SyncServer
) { ) {
super(app, plugin); super(app, plugin);
this.plugin = plugin;
} }
display(): void { display(): void {
@ -38,25 +37,36 @@ export class SyncSettingsTab extends PluginSettingTab {
.addText((text) => .addText((text) =>
text text
.setPlaceholder("https://example.com:8080/obsidian") .setPlaceholder("https://example.com:8080/obsidian")
.setValue(this.settingsContainer.getSettings().remoteUri) .setValue(this.database.getSettings().remoteUri)
.onChange((value) => .onChange((value) =>
this.settingsContainer.setSetting("remoteUri", value) this.database.setSetting("remoteUri", value)
) )
) )
.addButton((button) => button.setButtonText("Test Connection")); .addButton((button) =>
button.setButtonText("Test Connection").onClick(async () => {
try {
const result = await this.syncServer.ping();
new Notice(
`Successfully connected to server! (server version: ${result.serverVersion})`
);
} catch (e) {
new Notice("Failed to connect to server: " + e);
}
})
);
new Setting(containerEl) new Setting(containerEl)
.setName("Access token") .setName("Access token")
.setDesc( .setDesc(
"Set the access token for the server that you can get from the server" "Set the access token for the server that you can get from the server"
) )
.setTooltip("todo, links to docs") .setTooltip("todo, links to dcocs")
.addTextArea((text) => .addTextArea((text) =>
text text
.setPlaceholder("ey...") .setPlaceholder("ey...")
.setValue(this.settingsContainer.getSettings().token) .setValue(this.database.getSettings().token)
.onChange((value) => .onChange((value) =>
this.settingsContainer.setSetting("token", value) this.database.setSetting("token", value)
) )
); );
@ -68,14 +78,9 @@ export class SyncSettingsTab extends PluginSettingTab {
.setTooltip("todo, links to docs") .setTooltip("todo, links to docs")
.addToggle((toggle) => .addToggle((toggle) =>
toggle toggle
.setValue( .setValue(this.database.getSettings().fullScanEnabled)
this.settingsContainer.getSettings().fullScanEnabled
)
.onChange((value) => .onChange((value) =>
this.settingsContainer.setSetting( this.database.setSetting("fullScanEnabled", value)
"fullScanEnabled",
value
)
) )
) )
.addSlider((text) => .addSlider((text) =>
@ -83,11 +88,10 @@ export class SyncSettingsTab extends PluginSettingTab {
.setLimits(1, 3600, 1) .setLimits(1, 3600, 1)
.setDynamicTooltip() .setDynamicTooltip()
.setValue( .setValue(
this.settingsContainer.getSettings() this.database.getSettings().fullScanIntervalInSeconds
.fullScanIntervalInSeconds
) )
.onChange((value) => .onChange((value) =>
this.settingsContainer.setSetting( this.database.setSetting(
"fullScanIntervalInSeconds", "fullScanIntervalInSeconds",
value value
) )