diff --git a/plugin/src/database/sync-settings.ts b/plugin/src/database/sync-settings.ts index ad6aa5cd..99e7d81b 100644 --- a/plugin/src/database/sync-settings.ts +++ b/plugin/src/database/sync-settings.ts @@ -9,6 +9,7 @@ export interface SyncSettings { isSyncEnabled: boolean; displayNoopSyncEvents: boolean; minimumLogLevel: LogLevel; + maxFileSizeMB: number; } export const DEFAULT_SETTINGS: SyncSettings = { @@ -19,5 +20,6 @@ export const DEFAULT_SETTINGS: SyncSettings = { syncConcurrency: 1, isSyncEnabled: false, displayNoopSyncEvents: false, - minimumLogLevel: LogLevel.INFO + minimumLogLevel: LogLevel.INFO, + maxFileSizeMB: 10 }; diff --git a/plugin/src/file-operations/file-operations.ts b/plugin/src/file-operations/file-operations.ts index 910b6d71..57d51877 100644 --- a/plugin/src/file-operations/file-operations.ts +++ b/plugin/src/file-operations/file-operations.ts @@ -5,6 +5,8 @@ export interface FileOperations { read: (path: RelativePath) => Promise; + getFileSize(path: RelativePath): Promise; + getModificationTime: (path: RelativePath) => Promise; // Create and write the file if it doesn't exist. Otherwise, it has the same behavior as write. diff --git a/plugin/src/file-operations/obsidian-file-operations.ts b/plugin/src/file-operations/obsidian-file-operations.ts index 5f68ce54..f92f3b24 100644 --- a/plugin/src/file-operations/obsidian-file-operations.ts +++ b/plugin/src/file-operations/obsidian-file-operations.ts @@ -8,41 +8,32 @@ export class ObsidianFileOperations implements FileOperations { public constructor(private readonly vault: Vault) {} public async listAllFiles(): Promise { - console.log(this.vault); - console.log("before getFiles"); - await sleep(1000); - const files = this.vault.getFiles(); - console.log("after getFiles"); - await sleep(1000); - - console.log(files); return files.map((file) => file.path); } public async read(path: RelativePath): Promise { - console.log("before readBinary"); - await sleep(1000); - const result = new Uint8Array( await this.vault.readBinary(this.getAbstractFile(path)) ); - console.log("after readBinary"); - await sleep(1000); return result; } - public async getModificationTime(path: RelativePath): Promise { - console.log("before stat"); - await sleep(1000); - + public async getFileSize(path: RelativePath): Promise { + const file = await this.vault.adapter.stat(normalizePath(path)); + if (!file) { + throw new Error(`File not found: ${path}`); + } + + return file.size; + } + + public async getModificationTime(path: RelativePath): Promise { const file = await this.vault.adapter.stat(normalizePath(path)); if (!file) { throw new Error(`File not found: ${path}`); } - console.log("after stat"); - await sleep(1000); return new Date(file.mtime); } @@ -51,19 +42,13 @@ export class ObsidianFileOperations implements FileOperations { path: RelativePath, newContent: Uint8Array ): Promise { - console.log("before create"); - await sleep(1000); if (await this.vault.adapter.exists(normalizePath(path))) { await this.write(path, new Uint8Array(0), newContent); - console.log("after create"); - await sleep(1000); return; } await this.createParentDirectories(normalizePath(path)); await this.vault.createBinary(normalizePath(path), newContent); - console.log("after create2"); - await sleep(1000); } public async write( diff --git a/plugin/src/sync-operations/syncer.ts b/plugin/src/sync-operations/syncer.ts index 2550f055..f5f48832 100644 --- a/plugin/src/sync-operations/syncer.ts +++ b/plugin/src/sync-operations/syncer.ts @@ -215,6 +215,21 @@ export class Syncer { SyncType.CREATE, SyncSource.PUSH, async () => { + if ( + (await this.operations.getFileSize(relativePath)) / + 1024 / + 1024 > + this.database.getSettings().maxFileSizeMB + ) { + this.history.addHistoryEntry({ + status: SyncStatus.ERROR, + relativePath, + message: `File size exceeds the maximum file size limit of ${this.database.getSettings().maxFileSizeMB}MB`, + type: SyncType.CREATE + }); + return; + } + const contentBytes = optimisations?.contentBytes ?? (await this.operations.read(relativePath)); @@ -301,10 +316,25 @@ export class Syncer { SyncType.UPDATE, SyncSource.PUSH, async () => { + if ( + (await this.operations.getFileSize(relativePath)) / + 1024 / + 1024 > + this.database.getSettings().maxFileSizeMB + ) { + this.history.addHistoryEntry({ + status: SyncStatus.ERROR, + relativePath, + message: `File size exceeds the maximum file size limit of ${this.database.getSettings().maxFileSizeMB}MB`, + type: SyncType.CREATE + }); + return; + } + const localMetadata = this.database.getDocument( oldPath ?? relativePath ); - console.log(JSON.stringify(localMetadata)); + if (!localMetadata) { if (this.database.getDocument(relativePath)) { this.history.addHistoryEntry({ @@ -320,21 +350,13 @@ export class Syncer { `Document metadata not found for ${relativePath}. This implies a corrupt local database. Consider resetting the plugin's sync history.` ); } - await sleep(1000); - console.log("about to read", relativePath); - await sleep(1000); const contentBytes = optimisations?.contentBytes ?? (await this.operations.read(relativePath)); - console.log("has read", relativePath); - await sleep(1000); - let contentHash = optimisations?.contentHash ?? hash(contentBytes); - console.log("has hashed", relativePath); - await sleep(1000); if ( localMetadata.hash === contentHash && @@ -349,9 +371,6 @@ export class Syncer { return; } - console.log("about to send", relativePath); - await sleep(1000); - const response = await this.syncService.put({ documentId: localMetadata.documentId, parentVersionId: localMetadata.parentVersionId, @@ -360,9 +379,6 @@ export class Syncer { createdDate: updateTime }); - console.log("has sent", relativePath); - await sleep(1000); - this.history.addHistoryEntry({ status: SyncStatus.SUCCESS, source: SyncSource.PUSH, @@ -403,22 +419,16 @@ export class Syncer { } if (response.type === "MergingUpdate") { - console.log( - "about to deserialize", - response.contentBase64 - ); const responseBytes = deserialize( response.contentBase64 ); - console.log("has deserialized", response.relativePath); contentHash = hash(responseBytes); - console.log("about to write", response.relativePath); + await this.operations.write( response.relativePath, contentBytes, responseBytes ); - console.log("has written", response.relativePath); this.history.addHistoryEntry({ status: SyncStatus.SUCCESS, diff --git a/plugin/src/views/settings-tab.ts b/plugin/src/views/settings-tab.ts index 535746c6..a629623d 100644 --- a/plugin/src/views/settings-tab.ts +++ b/plugin/src/views/settings-tab.ts @@ -252,6 +252,22 @@ export class SyncSettingsTab extends PluginSettingTab { ) ); + new Setting(containerEl) + .setName("Maximum file size to be uploaded (MB)") + .setDesc( + "Set the maximum file size that can be uploaded to the server. Files larger than this size will be ignored." + ) + .addSlider((slider) => + slider + .setLimits(0, 32, 1) + .setDynamicTooltip() + .setInstant(false) + .setValue(this.database.getSettings().maxFileSizeMB) + .onChange(async (value) => + this.database.setSetting("maxFileSizeMB", value) + ) + ); + new Setting(containerEl) .setName("Enable sync") .setDesc(