mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2024-12-12 09:04:06 +02:00
Fixed:
- Document history is now displayed again. Reorganised: - Many files have been refactored.
This commit is contained in:
parent
5d1074065c
commit
6513c53c7e
@ -1,7 +1,7 @@
|
|||||||
import { App, Modal } from "obsidian";
|
import { App, Modal } from "obsidian";
|
||||||
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from "diff-match-patch";
|
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT } from "diff-match-patch";
|
||||||
import { diff_result } from "./lib/src/types";
|
import { diff_result } from "./lib/src/types";
|
||||||
import { escapeStringToHTML } from "./lib/src/utils";
|
import { escapeStringToHTML } from "./lib/src/strbin";
|
||||||
|
|
||||||
export class ConflictResolveModal extends Modal {
|
export class ConflictResolveModal extends Modal {
|
||||||
// result: Array<[number, string]>;
|
// result: Array<[number, string]>;
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
import { TFile, Modal, App } from "obsidian";
|
import { TFile, Modal, App } from "obsidian";
|
||||||
import { path2id } from "./utils";
|
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 ObsidianLiveSyncPlugin from "./main";
|
||||||
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch";
|
import { DIFF_DELETE, DIFF_EQUAL, DIFF_INSERT, diff_match_patch } from "diff-match-patch";
|
||||||
import { LoadedEntry, LOG_LEVEL } from "./lib/src/types";
|
import { LoadedEntry, LOG_LEVEL } from "./lib/src/types";
|
||||||
import { Logger } from "./lib/src/logger";
|
import { Logger } from "./lib/src/logger";
|
||||||
|
import { getDocData } from "./lib/src/utils";
|
||||||
|
|
||||||
export class DocumentHistoryModal extends Modal {
|
export class DocumentHistoryModal extends Modal {
|
||||||
plugin: ObsidianLiveSyncPlugin;
|
plugin: ObsidianLiveSyncPlugin;
|
||||||
@ -64,7 +66,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
this.currentDoc = w;
|
this.currentDoc = w;
|
||||||
this.info.innerHTML = `Modified:${new Date(w.mtime).toLocaleString()}`;
|
this.info.innerHTML = `Modified:${new Date(w.mtime).toLocaleString()}`;
|
||||||
let result = "";
|
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.currentDeleted = w.deleted;
|
||||||
this.currentText = w1data;
|
this.currentText = w1data;
|
||||||
if (this.showDiff) {
|
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);
|
const w2 = await db.getDBEntry(path2id(this.file), { rev: oldRev }, false, false, true);
|
||||||
if (w2 != false) {
|
if (w2 != false) {
|
||||||
const dmp = new diff_match_patch();
|
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);
|
const diff = dmp.diff_main(w2data, w1data);
|
||||||
dmp.diff_cleanupSemantic(diff);
|
dmp.diff_cleanupSemantic(diff);
|
||||||
for (const v of 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);
|
Logger("Path is not valid to write content.", LOG_LEVEL.INFO);
|
||||||
}
|
}
|
||||||
if (this.currentDoc?.datatype == "plain") {
|
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);
|
await focusFile(pathToWrite);
|
||||||
this.close();
|
this.close();
|
||||||
} else if (this.currentDoc?.datatype == "newnote") {
|
} else if (this.currentDoc?.datatype == "newnote") {
|
||||||
|
@ -4,7 +4,7 @@ import { LocalPouchDBBase } from "./lib/src/LocalPouchDBBase.js";
|
|||||||
import { Logger } from "./lib/src/logger.js";
|
import { Logger } from "./lib/src/logger.js";
|
||||||
import { PouchDB } from "./lib/src/pouchdb-browser.js";
|
import { PouchDB } from "./lib/src/pouchdb-browser.js";
|
||||||
import { EntryDoc, LOG_LEVEL } from "./lib/src/types.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 { isCloudantURI, isValidRemoteCouchDBURI } from "./lib/src/utils_couchdb.js";
|
||||||
import { id2path, path2id } from "./utils.js";
|
import { id2path, path2id } from "./utils.js";
|
||||||
|
|
||||||
|
@ -1,21 +1,17 @@
|
|||||||
import { App, Modal } from "obsidian";
|
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";
|
import ObsidianLiveSyncPlugin from "./main";
|
||||||
|
|
||||||
export class LogDisplayModal extends Modal {
|
export class LogDisplayModal extends Modal {
|
||||||
plugin: ObsidianLiveSyncPlugin;
|
plugin: ObsidianLiveSyncPlugin;
|
||||||
logEl: HTMLDivElement;
|
logEl: HTMLDivElement;
|
||||||
|
unsubscribe: () => void;
|
||||||
constructor(app: App, plugin: ObsidianLiveSyncPlugin) {
|
constructor(app: App, plugin: ObsidianLiveSyncPlugin) {
|
||||||
super(app);
|
super(app);
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
}
|
}
|
||||||
updateLog() {
|
|
||||||
let msg = "";
|
|
||||||
for (const v of this.plugin.logMessage) {
|
|
||||||
msg += escapeStringToHTML(v) + "<br>";
|
|
||||||
}
|
|
||||||
this.logEl.innerHTML = msg;
|
|
||||||
}
|
|
||||||
onOpen() {
|
onOpen() {
|
||||||
const { contentEl } = this;
|
const { contentEl } = this;
|
||||||
|
|
||||||
@ -25,13 +21,18 @@ export class LogDisplayModal extends Modal {
|
|||||||
div.addClass("op-scrollable");
|
div.addClass("op-scrollable");
|
||||||
div.addClass("op-pre");
|
div.addClass("op-pre");
|
||||||
this.logEl = div;
|
this.logEl = div;
|
||||||
this.updateLog = this.updateLog.bind(this);
|
this.unsubscribe = logMessageStore.observe((e) => {
|
||||||
this.plugin.addLogHook = this.updateLog;
|
let msg = "";
|
||||||
this.updateLog();
|
for (const v of e) {
|
||||||
|
msg += escapeStringToHTML(v) + "<br>";
|
||||||
|
}
|
||||||
|
this.logEl.innerHTML = msg;
|
||||||
|
})
|
||||||
|
logMessageStore.invalidate();
|
||||||
}
|
}
|
||||||
onClose() {
|
onClose() {
|
||||||
const { contentEl } = this;
|
const { contentEl } = this;
|
||||||
contentEl.empty();
|
contentEl.empty();
|
||||||
this.plugin.addLogHook = null;
|
if (this.unsubscribe) this.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer, stringifyYaml } from "obsidian";
|
import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer, stringifyYaml } from "obsidian";
|
||||||
import { DEFAULT_SETTINGS, LOG_LEVEL, ObsidianLiveSyncSettings, RemoteDBSettings } from "./lib/src/types";
|
import { DEFAULT_SETTINGS, LOG_LEVEL, ObsidianLiveSyncSettings, RemoteDBSettings } from "./lib/src/types";
|
||||||
import { path2id, id2path } from "./utils";
|
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 { Logger } from "./lib/src/logger";
|
||||||
import { checkSyncInfo, isCloudantURI } from "./lib/src/utils_couchdb.js";
|
import { checkSyncInfo, isCloudantURI } from "./lib/src/utils_couchdb.js";
|
||||||
import { testCrypt } from "./lib/src/e2ee_v2";
|
import { testCrypt } from "./lib/src/e2ee_v2";
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import ObsidianLiveSyncPlugin from "./main";
|
import ObsidianLiveSyncPlugin from "./main";
|
||||||
import { onMount } from "svelte";
|
import { onMount } from "svelte";
|
||||||
import { DevicePluginList, PluginDataEntry } from "./types";
|
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";
|
type JudgeResult = "" | "NEWER" | "EVEN" | "EVEN_BUT_DIFFERENT" | "OLDER" | "REMOTE_ONLY";
|
||||||
|
|
||||||
|
2
src/lib
2
src/lib
@ -1 +1 @@
|
|||||||
Subproject commit 39628ac8e6e4ba4298757f22bbc50b1efd26d6a5
|
Subproject commit 133bae360798ee1513082cf728a59d96392bae6f
|
44
src/main.ts
44
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 { 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 { 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 { PluginDataEntry, PERIODIC_PLUGIN_SWEEP, PluginList, DevicePluginList, InternalFileInfo, queueItem } from "./types";
|
||||||
import {
|
import { getDocData, isDocContentSame } from "./lib/src/utils";
|
||||||
base64ToString,
|
import { Logger } from "./lib/src/logger";
|
||||||
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 { LocalPouchDB } from "./LocalPouchDB";
|
import { LocalPouchDB } from "./LocalPouchDB";
|
||||||
import { LogDisplayModal } from "./LogDisplayModal";
|
import { LogDisplayModal } from "./LogDisplayModal";
|
||||||
import { ConflictResolveModal } from "./ConflictResolveModal";
|
import { ConflictResolveModal } from "./ConflictResolveModal";
|
||||||
import { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab";
|
import { ObsidianLiveSyncSettingTab } from "./ObsidianLiveSyncSettingTab";
|
||||||
import { DocumentHistoryModal } from "./DocumentHistoryModal";
|
import { DocumentHistoryModal } from "./DocumentHistoryModal";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { applyPatch, clearAllPeriodic, clearAllTriggers, clearTrigger, disposeMemoObject, generatePatchObj, id2path, isObjectMargeApplicable, isSensibleMargeApplicable, memoIfNotExist, memoObject, path2id, retrieveMemoObject, setTrigger, tryParseJSON } from "./utils";
|
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";
|
import { decrypt, encrypt } from "./lib/src/e2ee_v2";
|
||||||
|
|
||||||
@ -36,7 +17,12 @@ const isDebug = false;
|
|||||||
import { InputStringDialog, PluginDialogModal, PopoverSelectString } from "./dialogs";
|
import { InputStringDialog, PluginDialogModal, PopoverSelectString } from "./dialogs";
|
||||||
import { isCloudantURI } from "./lib/src/utils_couchdb";
|
import { isCloudantURI } from "./lib/src/utils_couchdb";
|
||||||
import { getGlobalStore, observeStores } from "./lib/src/store";
|
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);
|
setNoticeClass(Notice);
|
||||||
|
|
||||||
@ -47,6 +33,7 @@ const FileWatchEventQueueMax = 10;
|
|||||||
|
|
||||||
function getAbstractFileByPath(path: string): TAbstractFile | null {
|
function getAbstractFileByPath(path: string): TAbstractFile | null {
|
||||||
// Hidden API but so useful.
|
// Hidden API but so useful.
|
||||||
|
// @ts-ignore
|
||||||
if ("getAbstractFileByPathInsensitive" in app.vault && (app.vault.adapter?.insensitive ?? false)) {
|
if ("getAbstractFileByPathInsensitive" in app.vault && (app.vault.adapter?.insensitive ?? false)) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return app.vault.getAbstractFileByPathInsensitive(path);
|
return app.vault.getAbstractFileByPathInsensitive(path);
|
||||||
@ -134,10 +121,10 @@ type FileEventItem = {
|
|||||||
type: FileEventType,
|
type: FileEventType,
|
||||||
args: FileEventArgs
|
args: FileEventArgs
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ObsidianLiveSyncPlugin extends Plugin {
|
export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||||
settings: ObsidianLiveSyncSettings;
|
settings: ObsidianLiveSyncSettings;
|
||||||
localDatabase: LocalPouchDB;
|
localDatabase: LocalPouchDB;
|
||||||
logMessage: string[] = [];
|
|
||||||
statusBar: HTMLElement;
|
statusBar: HTMLElement;
|
||||||
statusBar2: HTMLElement;
|
statusBar2: HTMLElement;
|
||||||
suspended: boolean;
|
suspended: boolean;
|
||||||
@ -284,7 +271,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onload() {
|
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");
|
Logger("loading plugin");
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const manifestVersion: string = MANIFEST_VERSION || "0.0.0";
|
const manifestVersion: string = MANIFEST_VERSION || "0.0.0";
|
||||||
@ -1062,7 +1049,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addLogHook: () => void = null;
|
|
||||||
//--> Basic document Functions
|
//--> Basic document Functions
|
||||||
notifies: { [key: string]: { notice: Notice; timer: NodeJS.Timeout; count: number } } = {};
|
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 messageContent = typeof message == "string" ? message : message instanceof Error ? `${message.name}:${message.message}` : JSON.stringify(message, null, 2);
|
||||||
const newMessage = timestamp + "->" + messageContent;
|
const newMessage = timestamp + "->" + messageContent;
|
||||||
|
|
||||||
this.logMessage = [].concat(this.logMessage).concat([newMessage]).slice(-100);
|
|
||||||
console.log(vaultName + ":" + newMessage);
|
console.log(vaultName + ":" + newMessage);
|
||||||
|
logMessageStore.apply(e => [...e, newMessage].slice(-100));
|
||||||
this.setStatusBarText(null, messageContent.substring(0, 30));
|
this.setStatusBarText(null, messageContent.substring(0, 30));
|
||||||
// if (message instanceof Error) {
|
|
||||||
// console.trace(message);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (level >= LOG_LEVEL.NOTICE) {
|
if (level >= LOG_LEVEL.NOTICE) {
|
||||||
if (!key) key = messageContent;
|
if (!key) key = messageContent;
|
||||||
@ -1127,7 +1110,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.addLogHook != null) this.addLogHook();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async ensureDirectory(fullPath: string) {
|
async ensureDirectory(fullPath: string) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { normalizePath } from "obsidian";
|
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.
|
// For backward compatibility, using the path for determining id.
|
||||||
// Only CouchDB unacceptable ID (that starts with an underscore) has been prefixed with "/".
|
// Only CouchDB unacceptable ID (that starts with an underscore) has been prefixed with "/".
|
||||||
|
Loading…
Reference in New Issue
Block a user