diff --git a/src/CmdConfigSync.ts b/src/CmdConfigSync.ts index 6b7a1e7..1926873 100644 --- a/src/CmdConfigSync.ts +++ b/src/CmdConfigSync.ts @@ -12,7 +12,6 @@ import { runWithLock } from "./lib/src/lock"; import { LiveSyncCommands } from "./LiveSyncCommands"; import { stripAllPrefixes } from "./lib/src/path"; import { PeriodicProcessor, askYesNo, disposeMemoObject, memoIfNotExist, memoObject, retrieveMemoObject, scheduleTask } from "./utils"; -import { Semaphore } from "./lib/src/semaphore"; import { PluginDialogModal } from "./dialogs"; import { JsonResolveModal } from "./JsonResolveModal"; @@ -180,77 +179,70 @@ export class ConfigSync extends LiveSyncCommands { pluginList.set(this.pluginList) return; } - - await runWithLock("update-plugin-list", false, async () => { - // if (updatedDocumentPath != "") pluginList.update(e => e.filter(ee => ee.documentPath != updatedDocumentPath)); - // const work: Record>>> = {}; - const entries = [] as PluginDataExDisplay[] - const plugins = this.localDatabase.findEntries(ICXHeader + "", `${ICXHeader}\u{10ffff}`, { include_docs: true }); - const semaphore = Semaphore(4); - const para = Parallels(); - let count = 0; - pluginIsEnumerating.set(true); - let processed = false; - try { - for await (const plugin of plugins) { - const path = plugin.path || this.getPath(plugin); - if (updatedDocumentPath && updatedDocumentPath != path) { - continue; - } - processed = true; - const oldEntry = (this.pluginList.find(e => e.documentPath == path)); - if (oldEntry && oldEntry.mtime == plugin.mtime) continue; - await para.wait(5); - para.add((async (v) => { - - const release = await semaphore.acquire(1); - try { - count++; - if (count % 10 == 0) Logger(`Enumerating files... ${count}`, logLevel, "get-plugins"); - - Logger(`plugin-${path}`, LOG_LEVEL.VERBOSE); - const wx = await this.localDatabase.getDBEntry(path, null, false, false); - if (wx) { - const data = deserialize(getDocData(wx.data), {}) as PluginDataEx; - const xFiles = [] as PluginDataExFile[]; - for (const file of data.files) { - const work = { ...file }; - const tempStr = getDocData(work.data); - work.data = [await hashString(tempStr)]; - xFiles.push(work); - } - entries.push({ - ...data, - documentPath: this.getPath(wx), - files: xFiles - }); - } - } catch (ex) { - //TODO - Logger(`Something happened at enumerating customization :${v.path}`, LOG_LEVEL.NOTICE); - console.warn(ex); - } finally { - release(); + scheduleTask("update-plugin-list-task", 200, async () => { + await runWithLock("update-plugin-list", false, async () => { + const entries = [] as PluginDataExDisplay[] + const plugins = this.localDatabase.findEntries(ICXHeader + "", `${ICXHeader}\u{10ffff}`, { include_docs: true }); + const para = Parallels(); + let count = 0; + pluginIsEnumerating.set(true); + let processed = false; + try { + for await (const plugin of plugins) { + const path = plugin.path || this.getPath(plugin); + if (updatedDocumentPath && updatedDocumentPath != path) { + continue; } + processed = true; + const oldEntry = (this.pluginList.find(e => e.documentPath == path)); + if (oldEntry && oldEntry.mtime == plugin.mtime) continue; + await para.wait(15); + para.add((async (v) => { + try { + count++; + if (count % 10 == 0) Logger(`Enumerating files... ${count}`, logLevel, "get-plugins"); + Logger(`plugin-${path}`, LOG_LEVEL.VERBOSE); + const wx = await this.localDatabase.getDBEntry(path, null, false, false); + if (wx) { + const data = deserialize(getDocData(wx.data), {}) as PluginDataEx; + const xFiles = [] as PluginDataExFile[]; + for (const file of data.files) { + const work = { ...file }; + const tempStr = getDocData(work.data); + work.data = [await hashString(tempStr)]; + xFiles.push(work); + } + entries.push({ + ...data, + documentPath: this.getPath(wx), + files: xFiles + }); + } + } catch (ex) { + //TODO + Logger(`Something happened at enumerating customization :${v.path}`, LOG_LEVEL.NOTICE); + console.warn(ex); + } + } + )(plugin)); } - )(plugin)); + await para.all(); + let newList = [...this.pluginList]; + for (const item of entries) { + newList = newList.filter(x => x.documentPath != item.documentPath); + newList.push(item) + } + if (updatedDocumentPath != "" && !processed) newList = newList.filter(e => e.documentPath != updatedDocumentPath); + + this.pluginList = newList; + pluginList.set(newList); + + + Logger(`All files enumerated`, logLevel, "get-plugins"); + } finally { + pluginIsEnumerating.set(false); } - await para.all(); - let newList = [...this.pluginList]; - for (const item of entries) { - newList = newList.filter(x => x.documentPath != item.documentPath); - newList.push(item) - } - if (updatedDocumentPath != "" && !processed) newList = newList.filter(e => e.documentPath != updatedDocumentPath); - - this.pluginList = newList; - pluginList.set(newList); - - - Logger(`All files enumerated`, logLevel, "get-plugins"); - } finally { - pluginIsEnumerating.set(false); - } + }); }); // return entries; } diff --git a/src/ObsidianLiveSyncSettingTab.ts b/src/ObsidianLiveSyncSettingTab.ts index efff42b..cb42730 100644 --- a/src/ObsidianLiveSyncSettingTab.ts +++ b/src/ObsidianLiveSyncSettingTab.ts @@ -1,5 +1,5 @@ import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, TextAreaComponent, MarkdownRenderer, stringifyYaml } from "./deps"; -import { DEFAULT_SETTINGS, LOG_LEVEL, type ObsidianLiveSyncSettings, type ConfigPassphraseStore, type RemoteDBSettings } from "./lib/src/types"; +import { DEFAULT_SETTINGS, LOG_LEVEL, type ObsidianLiveSyncSettings, type ConfigPassphraseStore, type RemoteDBSettings, type FilePathWithPrefix } from "./lib/src/types"; import { delay } from "./lib/src/utils"; import { Semaphore } from "./lib/src/semaphore"; import { versionNumberString2Number } from "./lib/src/strbin"; @@ -111,7 +111,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { } - MarkdownRenderer.renderMarkdown(updateInformation, informationDivEl, "/", null); + MarkdownRenderer.renderMarkdown(updateInformation, informationDivEl, "/", this.plugin); addScreenElement("100", containerInformationEl); @@ -1536,7 +1536,65 @@ ${stringifyYaml(pluginConfig)}`; Logger("done", LOG_LEVEL.NOTICE, "verify"); }) ); - + new Setting(containerHatchEl) + .setName("Check and convert non-path-obfuscated files") + .setDesc("") + .addButton((button) => + button + .setButtonText("Perform") + .setDisabled(false) + .setWarning() + .onClick(async () => { + for await (const docName of this.plugin.localDatabase.findAllDocNames()) { + if (!docName.startsWith("f:")) { + const idEncoded = await this.plugin.path2id(docName as FilePathWithPrefix); + const doc = await this.plugin.localDatabase.getDBEntry(docName as FilePathWithPrefix); + if (!doc) continue; + if (doc.type != "newnote" && doc.type != "plain") { + continue; + } + const newDoc = { ...doc }; + //Prepare converted data + newDoc._id = idEncoded; + newDoc.path = this.plugin.getPath(newDoc); + try { + const obfuscatedDoc = await this.plugin.localDatabase.getRaw(idEncoded, { revs_info: true }); + // Unfortunately we have to delete one of them. + // Just now, save it as a conflicted document. + obfuscatedDoc._revs_info?.shift(); // Drop latest revision. + const previousRev = obfuscatedDoc._revs_info?.shift(); // Use second revision. + newDoc._rev = previousRev.rev; + const ret = await this.plugin.localDatabase.putRaw(newDoc, { force: true }); + if (ret.ok) { + Logger(`${docName} has been converted as conflicted document`, LOG_LEVEL.NOTICE); + doc._deleted = true; + if ((await this.plugin.localDatabase.putRaw(doc)).ok) { + Logger(`Old ${docName} has been deleted`, LOG_LEVEL.NOTICE); + } + await this.plugin.showIfConflicted(docName as FilePathWithPrefix); + } else { + Logger(`Converting ${docName} Failed!`, LOG_LEVEL.NOTICE); + Logger(ret, LOG_LEVEL.VERBOSE); + } + } catch (ex) { + if (ex?.status == 404) { + // We can perform this safely + if ((await this.plugin.localDatabase.putRaw(newDoc)).ok) { + Logger(`${docName} has been converted`, LOG_LEVEL.NOTICE); + doc._deleted = true; + if ((await this.plugin.localDatabase.putRaw(doc)).ok) { + Logger(`Old ${docName} has been deleted`, LOG_LEVEL.NOTICE); + } + } + } else { + Logger(`Something went wrong on converting ${docName}`, LOG_LEVEL.NOTICE); + Logger(ex, LOG_LEVEL.VERBOSE); + // Something wrong. + } + } + } + } + })); new Setting(containerHatchEl) .setName("Suspend file watching") .setDesc("Stop watching for file change.")