diff --git a/src/events-listener.ts b/src/events-listener.ts index 7264158..873837c 100644 --- a/src/events-listener.ts +++ b/src/events-listener.ts @@ -139,16 +139,21 @@ export default class EventsListener { } } + private isWorkspaceFile(filePath: string): boolean { + return ( + filePath === `${this.vault.configDir}/workspace.json` || + filePath === `${this.vault.configDir}/workspace-mobile.json` + ); + } + private async isSyncable(filePath: string) { if (filePath === `${this.vault.configDir}/${MANIFEST_FILE_NAME}`) { // Manifest file must always be synced return true; - } else if ( - filePath === `${this.vault.configDir}/workspace.json` || - filePath === `${this.vault.configDir}/workspace-mobile.json` - ) { - // Obsidian recommends not syncing the workspace files - return false; + } else if (this.isWorkspaceFile(filePath)) { + // Workspace files are synced only when config directory sync is enabled + // and the dedicated workspace-files option is enabled too. + return this.settings.syncConfigDir && this.settings.syncWorkspaceFiles; } else if (filePath === `${this.vault.configDir}/${LOG_FILE_NAME}`) { // Don't sync the log file, doesn't make sense return false; diff --git a/src/settings/settings.ts b/src/settings/settings.ts index 681cbe8..b112ce3 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -9,6 +9,7 @@ export interface GitHubSyncSettings { syncInterval: number; syncOnStartup: boolean; syncConfigDir: boolean; + syncWorkspaceFiles: boolean; conflictHandling: "overwriteLocal" | "ask" | "overwriteRemote"; autoResolveLogConflicts: boolean; conflictViewMode: "default" | "unified" | "split"; @@ -29,6 +30,7 @@ export const DEFAULT_SETTINGS: GitHubSyncSettings = { syncInterval: 1, syncOnStartup: false, syncConfigDir: false, + syncWorkspaceFiles: false, conflictHandling: "ask", autoResolveLogConflicts: true, conflictViewMode: "default", diff --git a/src/settings/tab.ts b/src/settings/tab.ts index 24b3414..b550037 100644 --- a/src/settings/tab.ts +++ b/src/settings/tab.ts @@ -180,6 +180,23 @@ export default class GitHubSyncSettingsTab extends PluginSettingTab { }); }); + new Setting(containerEl) + .setName("Sync workspace files") + .setDesc("Sync workspace.json and workspace-mobile.json files") + .addToggle((toggle) => { + toggle + .setValue(this.plugin.settings.syncWorkspaceFiles) + .onChange(async (value) => { + this.plugin.settings.syncWorkspaceFiles = value; + if (value && this.plugin.settings.syncConfigDir) { + await this.plugin.syncManager.addConfigDirToMetadata(); + } else if (!value) { + await this.plugin.syncManager.removeWorkspaceFilesFromMetadata(); + } + await this.plugin.saveSettings(); + }); + }); + const conflictHandlingOptions = { overwriteLocal: "Overwrite local file", ask: "Ask", diff --git a/src/sync-manager.ts b/src/sync-manager.ts index 7944bb6..bd077bc 100644 --- a/src/sync-manager.ts +++ b/src/sync-manager.ts @@ -312,11 +312,8 @@ export default class SyncManager { return; } - if (targetPath === `${this.vault.configDir}/${LOG_FILE_NAME}`) { - // We don't want to download the log file if the user synced it in the past. - // This is necessary because in the past we forgot to ignore the log file - // from syncing if the user enabled configs sync. - // To avoid downloading it we ignore it if still present in the remote repo. + if (this.isVolatileSyncArtifact(targetPath)) { + await this.logger.info("Skipping volatile sync artifact", targetPath); return; } @@ -714,8 +711,23 @@ export default class SyncManager { return filePath === `${this.vault.configDir}/${LOG_FILE_NAME}`; } + private isWorkspaceFile(filePath: string): boolean { + return ( + filePath === `${this.vault.configDir}/workspace.json` || + filePath === `${this.vault.configDir}/workspace-mobile.json` + ); + } + + private shouldSyncWorkspaceFiles(): boolean { + return this.settings.syncConfigDir && this.settings.syncWorkspaceFiles; + } + private isVolatileSyncArtifact(filePath: string): boolean { - return this.isLogFile(filePath); + // Keep these files out of metadata when they should not be synced. + return ( + this.isLogFile(filePath) || + (this.isWorkspaceFile(filePath) && !this.shouldSyncWorkspaceFiles()) + ); } private filterRemoteMetadataFiles(filesMetadata: { @@ -736,7 +748,7 @@ export default class SyncManager { } /** - * Remove artefactos volateis do metadata local para evitar conflitos recorrentes. + * Removes volatile artifacts from local metadata to prevent recurring conflicts. */ private async removeVolatileArtifactsFromLocalMetadata() { let changed = false; @@ -752,7 +764,7 @@ export default class SyncManager { } /** - * Reconcilia SHAs do metadata remoto com a tree atual para remover referencias obsoletas. + * Reconciles remote metadata SHAs with the current tree to remove stale references. */ private async reconcileRemoteMetadataWithTree( remoteMetadataFiles: { @@ -788,7 +800,7 @@ export default class SyncManager { } /** - * Tenta obter o blob pelo SHA do metadata e, em caso de 404, tenta pelo SHA atual da tree. + * Tries to load a blob by metadata SHA and, on 404, retries with the current tree SHA. */ private async getRemoteFileContentWithFallback( filePath: string, @@ -1273,10 +1285,6 @@ export default class SyncManager { folders.push(...res.folders); } files.forEach((filePath: string) => { - if (filePath === `${this.vault.configDir}/workspace.json`) { - // Obsidian recommends not syncing the workspace file - return; - } if ( isGitignored(gitignoreMatcher, filePath) || this.isVolatileSyncArtifact(filePath) @@ -1388,6 +1396,21 @@ export default class SyncManager { this.metadataStore.save(); } + /** + * Removes workspace files from local metadata. + * Useful when the user disables workspace files synchronization. + */ + async removeWorkspaceFilesFromMetadata() { + await this.logger.info("Removing workspace files from metadata"); + [ + `${this.vault.configDir}/workspace.json`, + `${this.vault.configDir}/workspace-mobile.json`, + ].forEach((filePath: string) => { + delete this.metadataStore.data.files[filePath]; + }); + this.metadataStore.save(); + } + getFileMetadata(filePath: string): FileMetadata { return this.metadataStore.data.files[filePath]; }