diff --git a/src/ConflictResolveModal.ts b/src/ConflictResolveModal.ts index 3f17e64..df47cf6 100644 --- a/src/ConflictResolveModal.ts +++ b/src/ConflictResolveModal.ts @@ -1,7 +1,7 @@ import { App, Modal } from "obsidian"; import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from "diff-match-patch"; import { diff_result } from "./lib/src/types"; -import { escapeStringToHTML } from "./lib/src/utils"; +import { escapeStringToHTML } from "./lib/src/strbin"; export class ConflictResolveModal extends Modal { // result: Array<[number, string]>; diff --git a/src/DocumentHistoryModal.ts b/src/DocumentHistoryModal.ts index 18ace06..372760c 100644 --- a/src/DocumentHistoryModal.ts +++ b/src/DocumentHistoryModal.ts @@ -1,10 +1,12 @@ import { TFile, Modal, App } from "obsidian"; import { path2id } from "./utils"; -import { base64ToArrayBuffer, base64ToString, escapeStringToHTML, isValidPath } from "./lib/src/utils"; +import { base64ToArrayBuffer, base64ToString, escapeStringToHTML } from "./lib/src/strbin"; +import { isValidPath } from "./lib/src/path"; import ObsidianLiveSyncPlugin from "./main"; import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch"; import { LoadedEntry, LOG_LEVEL } from "./lib/src/types"; import { Logger } from "./lib/src/logger"; +import { getDocData } from "./lib/src/utils"; export class DocumentHistoryModal extends Modal { plugin: ObsidianLiveSyncPlugin; @@ -64,7 +66,7 @@ export class DocumentHistoryModal extends Modal { this.currentDoc = w; this.info.innerHTML = `Modified:${new Date(w.mtime).toLocaleString()}`; let result = ""; - const w1data = w.datatype == "plain" ? w.data : base64ToString(w.data); + const w1data = w.datatype == "plain" ? getDocData(w.data) : base64ToString(w.data); this.currentDeleted = w.deleted; this.currentText = w1data; if (this.showDiff) { @@ -74,7 +76,7 @@ export class DocumentHistoryModal extends Modal { const w2 = await db.getDBEntry(path2id(this.file), { rev: oldRev }, false, false, true); if (w2 != false) { const dmp = new diff_match_patch(); - const w2data = w2.datatype == "plain" ? w2.data : base64ToString(w2.data); + const w2data = w2.datatype == "plain" ? getDocData(w2.data) : base64ToString(w2.data); const diff = dmp.diff_main(w2data, w1data); dmp.diff_cleanupSemantic(diff); for (const v of diff) { @@ -176,7 +178,7 @@ export class DocumentHistoryModal extends Modal { Logger("Path is not valid to write content.", LOG_LEVEL.INFO); } if (this.currentDoc?.datatype == "plain") { - await this.app.vault.adapter.write(pathToWrite, this.currentDoc.data); + await this.app.vault.adapter.write(pathToWrite, getDocData(this.currentDoc.data)); await focusFile(pathToWrite); this.close(); } else if (this.currentDoc?.datatype == "newnote") { diff --git a/src/LocalPouchDB.ts b/src/LocalPouchDB.ts index f994693..5bf443a 100644 --- a/src/LocalPouchDB.ts +++ b/src/LocalPouchDB.ts @@ -4,7 +4,7 @@ import { LocalPouchDBBase } from "./lib/src/LocalPouchDBBase.js"; import { Logger } from "./lib/src/logger.js"; import { PouchDB } from "./lib/src/pouchdb-browser.js"; import { EntryDoc, LOG_LEVEL } from "./lib/src/types.js"; -import { enableEncryption } from "./lib/src/utils.js"; +import { enableEncryption } from "./lib/src/utils_couchdb.js"; import { isCloudantURI, isValidRemoteCouchDBURI } from "./lib/src/utils_couchdb.js"; import { id2path, path2id } from "./utils.js"; diff --git a/src/LogDisplayModal.ts b/src/LogDisplayModal.ts index 08d65df..8dcb1b2 100644 --- a/src/LogDisplayModal.ts +++ b/src/LogDisplayModal.ts @@ -1,21 +1,17 @@ import { App, Modal } from "obsidian"; -import { escapeStringToHTML } from "./lib/src/utils"; +import { logMessageStore } from "./lib/src/stores"; +import { escapeStringToHTML } from "./lib/src/strbin"; import ObsidianLiveSyncPlugin from "./main"; export class LogDisplayModal extends Modal { plugin: ObsidianLiveSyncPlugin; logEl: HTMLDivElement; + unsubscribe: () => void; constructor(app: App, plugin: ObsidianLiveSyncPlugin) { super(app); this.plugin = plugin; } - updateLog() { - let msg = ""; - for (const v of this.plugin.logMessage) { - msg += escapeStringToHTML(v) + "
"; - } - this.logEl.innerHTML = msg; - } + onOpen() { const { contentEl } = this; @@ -25,13 +21,18 @@ export class LogDisplayModal extends Modal { div.addClass("op-scrollable"); div.addClass("op-pre"); this.logEl = div; - this.updateLog = this.updateLog.bind(this); - this.plugin.addLogHook = this.updateLog; - this.updateLog(); + this.unsubscribe = logMessageStore.observe((e) => { + let msg = ""; + for (const v of e) { + msg += escapeStringToHTML(v) + "
"; + } + this.logEl.innerHTML = msg; + }) + logMessageStore.invalidate(); } onClose() { const { contentEl } = this; contentEl.empty(); - this.plugin.addLogHook = null; + if (this.unsubscribe) this.unsubscribe(); } } diff --git a/src/ObsidianLiveSyncSettingTab.ts b/src/ObsidianLiveSyncSettingTab.ts index a280fa3..d132c97 100644 --- a/src/ObsidianLiveSyncSettingTab.ts +++ b/src/ObsidianLiveSyncSettingTab.ts @@ -1,7 +1,9 @@ import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer, stringifyYaml } from "obsidian"; import { DEFAULT_SETTINGS, LOG_LEVEL, ObsidianLiveSyncSettings, RemoteDBSettings } from "./lib/src/types"; import { path2id, id2path } from "./utils"; -import { delay, Semaphore, versionNumberString2Number } from "./lib/src/utils"; +import { delay } from "./lib/src/utils"; +import { Semaphore } from "./lib/src/semaphore"; +import { versionNumberString2Number } from "./lib/src/strbin"; import { Logger } from "./lib/src/logger"; import { checkSyncInfo, isCloudantURI } from "./lib/src/utils_couchdb.js"; import { testCrypt } from "./lib/src/e2ee_v2"; diff --git a/src/PluginPane.svelte b/src/PluginPane.svelte index 01f90cb..3a6aaac 100644 --- a/src/PluginPane.svelte +++ b/src/PluginPane.svelte @@ -2,7 +2,7 @@ import ObsidianLiveSyncPlugin from "./main"; import { onMount } from "svelte"; import { DevicePluginList, PluginDataEntry } from "./types"; - import { versionNumberString2Number } from "./lib/src/utils"; + import { versionNumberString2Number } from "./lib/src/strbin"; type JudgeResult = "" | "NEWER" | "EVEN" | "EVEN_BUT_DIFFERENT" | "OLDER" | "REMOTE_ONLY"; diff --git a/src/lib b/src/lib index 39628ac..133bae3 160000 --- a/src/lib +++ b/src/lib @@ -1 +1 @@ -Subproject commit 39628ac8e6e4ba4298757f22bbc50b1efd26d6a5 +Subproject commit 133bae360798ee1513082cf728a59d96392bae6f diff --git a/src/main.ts b/src/main.ts index 95ca11f..e9b21f9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,33 +1,14 @@ -import { debounce, Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, PluginManifest, App, } from "obsidian"; +import { debounce, Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, PluginManifest, App } from "obsidian"; import { Diff, DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch"; - import { EntryDoc, LoadedEntry, ObsidianLiveSyncSettings, diff_check_result, diff_result_leaf, EntryBody, LOG_LEVEL, VER, DEFAULT_SETTINGS, diff_result, FLAGMD_REDFLAG, SYNCINFO_ID, InternalFileEntry } from "./lib/src/types"; import { PluginDataEntry, PERIODIC_PLUGIN_SWEEP, PluginList, DevicePluginList, InternalFileInfo, queueItem } from "./types"; -import { - base64ToString, - arrayBufferToBase64, - base64ToArrayBuffer, - isValidPath, - versionNumberString2Number, - runWithLock, - shouldBeIgnored, - isPlainText, - setNoticeClass, - NewNotice, - WrappedNotice, - Semaphore, - getDocData, - isDocContentSame, -} from "./lib/src/utils"; -import { Logger, setLogger } from "./lib/src/logger"; +import { getDocData, isDocContentSame } from "./lib/src/utils"; +import { Logger } from "./lib/src/logger"; import { LocalPouchDB } from "./LocalPouchDB"; import { LogDisplayModal } from "./LogDisplayModal"; import { ConflictResolveModal } from "./ConflictResolveModal"; import { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab"; import { DocumentHistoryModal } from "./DocumentHistoryModal"; - - - import { applyPatch, clearAllPeriodic, clearAllTriggers, clearTrigger, disposeMemoObject, generatePatchObj, id2path, isObjectMargeApplicable, isSensibleMargeApplicable, memoIfNotExist, memoObject, path2id, retrieveMemoObject, setTrigger, tryParseJSON } from "./utils"; import { decrypt, encrypt } from "./lib/src/e2ee_v2"; @@ -36,7 +17,12 @@ const isDebug = false; import { InputStringDialog, PluginDialogModal, PopoverSelectString } from "./dialogs"; import { isCloudantURI } from "./lib/src/utils_couchdb"; import { getGlobalStore, observeStores } from "./lib/src/store"; -import { lockStore } from "./lib/src/stores"; +import { lockStore, logMessageStore, logStore } from "./lib/src/stores"; +import { NewNotice, setNoticeClass, WrappedNotice } from "./lib/src/wrapper"; +import { base64ToString, versionNumberString2Number, base64ToArrayBuffer, arrayBufferToBase64 } from "./lib/src/strbin"; +import { isPlainText, isValidPath, shouldBeIgnored } from "./lib/src/path"; +import { runWithLock } from "./lib/src/lock"; +import { Semaphore } from "./lib/src/semaphore"; setNoticeClass(Notice); @@ -47,6 +33,7 @@ const FileWatchEventQueueMax = 10; function getAbstractFileByPath(path: string): TAbstractFile | null { // Hidden API but so useful. + // @ts-ignore if ("getAbstractFileByPathInsensitive" in app.vault && (app.vault.adapter?.insensitive ?? false)) { // @ts-ignore return app.vault.getAbstractFileByPathInsensitive(path); @@ -134,10 +121,10 @@ type FileEventItem = { type: FileEventType, args: FileEventArgs } + export default class ObsidianLiveSyncPlugin extends Plugin { settings: ObsidianLiveSyncSettings; localDatabase: LocalPouchDB; - logMessage: string[] = []; statusBar: HTMLElement; statusBar2: HTMLElement; suspended: boolean; @@ -284,7 +271,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } async onload() { - setLogger(this.addLog.bind(this)); // Logger moved to global. + logStore.subscribe(e => this.addLog(e.message, e.level, e.key)); Logger("loading plugin"); //@ts-ignore const manifestVersion: string = MANIFEST_VERSION || "0.0.0"; @@ -1062,7 +1049,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin { } } - addLogHook: () => void = null; //--> Basic document Functions notifies: { [key: string]: { notice: Notice; timer: NodeJS.Timeout; count: number } } = {}; @@ -1083,12 +1069,9 @@ export default class ObsidianLiveSyncPlugin extends Plugin { const messageContent = typeof message == "string" ? message : message instanceof Error ? `${message.name}:${message.message}` : JSON.stringify(message, null, 2); const newMessage = timestamp + "->" + messageContent; - this.logMessage = [].concat(this.logMessage).concat([newMessage]).slice(-100); console.log(vaultName + ":" + newMessage); + logMessageStore.apply(e => [...e, newMessage].slice(-100)); this.setStatusBarText(null, messageContent.substring(0, 30)); - // if (message instanceof Error) { - // console.trace(message); - // } if (level >= LOG_LEVEL.NOTICE) { if (!key) key = messageContent; @@ -1127,7 +1110,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin { }; } } - if (this.addLogHook != null) this.addLogHook(); } async ensureDirectory(fullPath: string) { diff --git a/src/utils.ts b/src/utils.ts index a515f7b..3a60b35 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,6 @@ import { normalizePath } from "obsidian"; -import { path2id_base, id2path_base } from "./lib/src/utils"; +import { path2id_base, id2path_base } from "./lib/src/path"; // For backward compatibility, using the path for determining id. // Only CouchDB unacceptable ID (that starts with an underscore) has been prefixed with "/".