disenchanting and dispelling from the nightmarish implicit something

Indeed, even though if this changeset is mostly another nightmare. It might be in beta for a while.
This commit is contained in:
vorotamoroz
2025-10-03 14:59:14 +01:00
parent ca5a7ae18c
commit 81362816d6
64 changed files with 1852 additions and 1245 deletions

View File

@@ -46,6 +46,9 @@ function readDocument(w: LoadedEntry) {
}
export class DocumentHistoryModal extends Modal {
plugin: ObsidianLiveSyncPlugin;
get services() {
return this.plugin.services;
}
range!: HTMLInputElement;
contentView!: HTMLDivElement;
info!: HTMLDivElement;
@@ -74,7 +77,7 @@ export class DocumentHistoryModal extends Modal {
this.id = id;
this.initialRev = revision;
if (!file && id) {
this.file = this.plugin.$$id2path(id);
this.file = this.services.path.id2path(id);
}
if (localStorage.getItem("ols-history-highlightdiff") == "1") {
this.showDiff = true;
@@ -83,7 +86,7 @@ export class DocumentHistoryModal extends Modal {
async loadFile(initialRev?: string) {
if (!this.id) {
this.id = await this.plugin.$$path2id(this.file);
this.id = await this.services.path.path2id(this.file);
}
const db = this.plugin.localDatabase;
try {
@@ -126,7 +129,7 @@ export class DocumentHistoryModal extends Modal {
}
this.BlobURLs.delete(key);
}
generateBlobURL(key: string, data: Uint8Array) {
generateBlobURL(key: string, data: Uint8Array<ArrayBuffer>) {
this.revokeURL(key);
const v = URL.createObjectURL(new Blob([data], { endings: "transparent", type: "application/octet-stream" }));
this.BlobURLs.set(key, v);
@@ -175,7 +178,10 @@ export class DocumentHistoryModal extends Modal {
result = result.replace(/\n/g, "<br>");
} else if (isImage(this.file)) {
const src = this.generateBlobURL("base", w1data);
const overlay = this.generateBlobURL("overlay", readDocument(w2) as Uint8Array);
const overlay = this.generateBlobURL(
"overlay",
readDocument(w2) as Uint8Array<ArrayBuffer>
);
result = `<div class='ls-imgdiff-wrap'>
<div class='overlay'>
<img class='img-base' src="${src}">

View File

@@ -1,8 +1,8 @@
import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule.ts";
import { AbstractObsidianModule } from "../AbstractObsidianModule.ts";
import { VIEW_TYPE_GLOBAL_HISTORY, GlobalHistoryView } from "./GlobalHistory/GlobalHistoryView.ts";
export class ModuleObsidianGlobalHistory extends AbstractObsidianModule implements IObsidianModule {
$everyOnloadStart(): Promise<boolean> {
export class ModuleObsidianGlobalHistory extends AbstractObsidianModule {
_everyOnloadStart(): Promise<boolean> {
this.addCommand({
id: "livesync-global-history",
name: "Show vault history",
@@ -17,6 +17,9 @@ export class ModuleObsidianGlobalHistory extends AbstractObsidianModule implemen
}
showGlobalHistory() {
void this.core.$$showView(VIEW_TYPE_GLOBAL_HISTORY);
void this.services.API.showWindow(VIEW_TYPE_GLOBAL_HISTORY);
}
onBindFunction(core: typeof this.core, services: typeof core.services): void {
services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
}
}

View File

@@ -10,13 +10,14 @@ import {
type diff_result,
} from "../../lib/src/common/types.ts";
import { ConflictResolveModal } from "./InteractiveConflictResolving/ConflictResolveModal.ts";
import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule.ts";
import { AbstractObsidianModule } from "../AbstractObsidianModule.ts";
import { displayRev, getPath, getPathWithoutPrefix } from "../../common/utils.ts";
import { fireAndForget } from "octagonal-wheels/promises";
import { serialized } from "octagonal-wheels/concurrency/lock";
import type { LiveSyncCore } from "../../main.ts";
export class ModuleInteractiveConflictResolver extends AbstractObsidianModule implements IObsidianModule {
$everyOnloadStart(): Promise<boolean> {
export class ModuleInteractiveConflictResolver extends AbstractObsidianModule {
_everyOnloadStart(): Promise<boolean> {
this.addCommand({
id: "livesync-conflictcheck",
name: "Pick a file to resolve conflict",
@@ -34,7 +35,7 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
return Promise.resolve(true);
}
async $anyResolveConflictByUI(filename: FilePathWithPrefix, conflictCheckResult: diff_result): Promise<boolean> {
async _anyResolveConflictByUI(filename: FilePathWithPrefix, conflictCheckResult: diff_result): Promise<boolean> {
// UI for resolving conflicts should one-by-one.
return await serialized(`conflict-resolve-ui`, async () => {
this._log("Merge:open conflict dialog", LOG_LEVEL_VERBOSE);
@@ -68,7 +69,7 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
}
// 2. As usual, delete the conflicted revision and if there are no conflicts, write the resolved content to the storage.
if (
(await this.core.$$resolveConflictByDeletingRev(filename, delRev, "UI Concatenated")) ==
(await this.services.conflict.resolveByDeletingRevision(filename, delRev, "UI Concatenated")) ==
MISSING_OR_ERROR
) {
this._log(
@@ -80,7 +81,7 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
} else if (typeof toDelete === "string") {
// Select one of the conflicted revision to delete.
if (
(await this.core.$$resolveConflictByDeletingRev(filename, toDelete, "UI Selected")) ==
(await this.services.conflict.resolveByDeletingRevision(filename, toDelete, "UI Selected")) ==
MISSING_OR_ERROR
) {
this._log(`Merge: Something went wrong: ${filename}, (${toDelete})`, LOG_LEVEL_NOTICE);
@@ -93,11 +94,11 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
// In here, some merge has been processed.
// So we have to run replication if configured.
// TODO: Make this is as a event request
if (this.settings.syncAfterMerge && !this.core.$$isSuspended()) {
await this.core.$$replicateByEvent();
if (this.settings.syncAfterMerge && !this.services.appLifecycle.isSuspended()) {
await this.services.replication.replicateByEvent();
}
// And, check it again.
await this.core.$$queueConflictCheck(filename);
await this.services.conflict.queueCheckFor(filename);
return false;
});
}
@@ -120,14 +121,14 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
const target = await this.core.confirm.askSelectString("File to resolve conflict", notesList);
if (target) {
const targetItem = notes.find((e) => e.dispPath == target)!;
await this.core.$$queueConflictCheck(targetItem.path);
await this.core.$$waitForAllConflictProcessed();
await this.services.conflict.queueCheckFor(targetItem.path);
await this.services.conflict.ensureAllProcessed();
return true;
}
return false;
}
async $allScanStat(): Promise<boolean> {
async _allScanStat(): Promise<boolean> {
const notes: { path: string; mtime: number }[] = [];
this._log(`Checking conflicted files`, LOG_LEVEL_VERBOSE);
for await (const doc of this.localDatabase.findAllDocs({ conflicts: true })) {
@@ -157,4 +158,9 @@ export class ModuleInteractiveConflictResolver extends AbstractObsidianModule im
}
return true;
}
onBindFunction(core: LiveSyncCore, services: typeof core.services): void {
services.appLifecycle.handleOnScanningStartupIssues(this._allScanStat.bind(this));
services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
services.conflict.handleResolveByUserInteraction(this._anyResolveConflictByUI.bind(this));
}
}

View File

@@ -20,7 +20,7 @@ import {
} from "../../lib/src/mock_and_interop/stores.ts";
import { eventHub } from "../../lib/src/hub/hub.ts";
import { EVENT_FILE_RENAMED, EVENT_LAYOUT_READY, EVENT_LEAF_ACTIVE_CHANGED } from "../../common/events.ts";
import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule.ts";
import { AbstractObsidianModule } from "../AbstractObsidianModule.ts";
import { addIcon, normalizePath, Notice } from "../../deps.ts";
import { LOG_LEVEL_NOTICE, setGlobalLogFunction } from "octagonal-wheels/common/logger";
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
@@ -28,6 +28,7 @@ import { LogPaneView, VIEW_TYPE_LOG } from "./Log/LogPaneView.ts";
import { serialized } from "octagonal-wheels/concurrency/lock";
import { $msg } from "src/lib/src/common/i18n.ts";
import { P2PLogCollector } from "../../lib/src/replication/trystero/P2PReplicatorCore.ts";
import type { LiveSyncCore } from "../../main.ts";
// This module cannot be a core module because it depends on the Obsidian UI.
@@ -50,7 +51,7 @@ const recentLogProcessor = new QueueProcessor(
const showDebugLog = false;
export const MARK_DONE = "\u{2009}\u{2009}";
export class ModuleLog extends AbstractObsidianModule implements IObsidianModule {
export class ModuleLog extends AbstractObsidianModule {
registerView = this.plugin.registerView.bind(this.plugin);
statusBar?: HTMLElement;
@@ -178,7 +179,7 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
});
const statusBarLabels = reactive(() => {
const scheduleMessage = this.core.$$isReloadingScheduled()
const scheduleMessage = this.services.appLifecycle.isReloadingScheduled()
? `WARNING! RESTARTING OBSIDIAN IS SCHEDULED!\n`
: "";
const { message } = statusLineLabel();
@@ -199,7 +200,7 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
statusBarLabels.onChanged((label) => applyToDisplay(label.value));
}
$everyOnload(): Promise<boolean> {
private _everyOnload(): Promise<boolean> {
eventHub.onEvent(EVENT_LEAF_ACTIVE_CHANGED, () => this.onActiveLeafChange());
eventHub.onceEvent(EVENT_LAYOUT_READY, () => this.onActiveLeafChange());
@@ -219,15 +220,15 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
const thisFile = this.app.workspace.getActiveFile();
if (!thisFile) return "";
// Case Sensitivity
if (this.core.$$shouldCheckCaseInsensitive()) {
if (this.services.setting.shouldCheckCaseInsensitively()) {
const f = this.core.storageAccess
.getFiles()
.map((e) => e.path)
.filter((e) => e.toLowerCase() == thisFile.path.toLowerCase());
if (f.length > 1) return "Not synchronised: There are multiple files with the same name";
}
if (!(await this.core.$$isTargetFile(thisFile.path))) return "Not synchronised: not a target file";
if (this.core.$$isFileSizeExceeded(thisFile.stat.size)) return "Not synchronised: File size exceeded";
if (!(await this.services.vault.isTargetFile(thisFile.path))) return "Not synchronised: not a target file";
if (this.services.vault.isFileSizeTooLarge(thisFile.stat.size)) return "Not synchronised: File size exceeded";
return "";
}
async setFileStatus() {
@@ -287,14 +288,14 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
});
}
$allStartOnUnload(): Promise<boolean> {
private _allStartOnUnload(): Promise<boolean> {
if (this.statusDiv) {
this.statusDiv.remove();
}
document.querySelectorAll(`.livesync-status`)?.forEach((e) => e.remove());
return Promise.resolve(true);
}
$everyOnloadStart(): Promise<boolean> {
_everyOnloadStart(): Promise<boolean> {
addIcon(
"view-log",
`<g transform="matrix(1.28 0 0 1.28 -131 -411)" fill="currentColor" fill-rule="evenodd">
@@ -303,23 +304,23 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
</g>`
);
this.addRibbonIcon("view-log", $msg("moduleLog.showLog"), () => {
void this.core.$$showView(VIEW_TYPE_LOG);
void this.services.API.showWindow(VIEW_TYPE_LOG);
}).addClass("livesync-ribbon-showlog");
this.addCommand({
id: "view-log",
name: "Show log",
callback: () => {
void this.core.$$showView(VIEW_TYPE_LOG);
void this.services.API.showWindow(VIEW_TYPE_LOG);
},
});
this.registerView(VIEW_TYPE_LOG, (leaf) => new LogPaneView(leaf, this.plugin));
return Promise.resolve(true);
}
$everyOnloadAfterLoadSettings(): Promise<boolean> {
private _everyOnloadAfterLoadSettings(): Promise<boolean> {
logStore
.pipeTo(
new QueueProcessor((logs) => logs.forEach((e) => this.core.$$addLog(e.message, e.level, e.key)), {
new QueueProcessor((logs) => logs.forEach((e) => this._addLog(e.message, e.level, e.key)), {
suspended: false,
batchSize: 20,
concurrentLimit: 1,
@@ -366,7 +367,7 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
})
);
}
$$addLog(message: any, level: LOG_LEVEL = LOG_LEVEL_INFO, key = ""): void {
_addLog(message: any, level: LOG_LEVEL = LOG_LEVEL_INFO, key = ""): void {
if (level == LOG_LEVEL_DEBUG && !showDebugLog) {
return;
}
@@ -376,7 +377,7 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
if (this.settings && !this.settings.showVerboseLog && level == LOG_LEVEL_VERBOSE) {
return;
}
const vaultName = this.core.$$getVaultName();
const vaultName = this.services.vault.getVaultName();
const now = new Date();
const timestamp = now.toLocaleString();
const messageContent =
@@ -437,4 +438,10 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
}
}
}
onBindFunction(core: LiveSyncCore, services: typeof core.services): void {
services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
services.appLifecycle.handleOnSettingLoaded(this._everyOnloadAfterLoadSettings.bind(this));
services.appLifecycle.handleOnLoaded(this._everyOnload.bind(this));
services.appLifecycle.handleOnBeforeUnload(this._allStartOnUnload.bind(this));
}
}

View File

@@ -2,18 +2,18 @@ import { type TFile } from "obsidian";
import { eventHub } from "../../common/events.ts";
import { EVENT_REQUEST_SHOW_HISTORY } from "../../common/obsidianEvents.ts";
import type { FilePathWithPrefix, LoadedEntry, DocumentID } from "../../lib/src/common/types.ts";
import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule.ts";
import { AbstractObsidianModule } from "../AbstractObsidianModule.ts";
import { DocumentHistoryModal } from "./DocumentHistory/DocumentHistoryModal.ts";
import { getPath } from "../../common/utils.ts";
import { fireAndForget } from "octagonal-wheels/promises";
export class ModuleObsidianDocumentHistory extends AbstractObsidianModule implements IObsidianModule {
$everyOnloadStart(): Promise<boolean> {
export class ModuleObsidianDocumentHistory extends AbstractObsidianModule {
_everyOnloadStart(): Promise<boolean> {
this.addCommand({
id: "livesync-history",
name: "Show history",
callback: () => {
const file = this.core.$$getActiveFilePath();
const file = this.services.vault.getActiveFilePath();
if (file) this.showHistory(file, undefined);
},
});
@@ -51,4 +51,7 @@ export class ModuleObsidianDocumentHistory extends AbstractObsidianModule implem
this.showHistory(targetId.path, targetId.id);
}
}
onBindFunction(core: typeof this.core, services: typeof core.services): void {
services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
}
}

View File

@@ -1,4 +1,4 @@
import { type IObsidianModule, AbstractObsidianModule } from "../AbstractObsidianModule.ts";
import { AbstractObsidianModule } from "../AbstractObsidianModule.ts";
// import { PouchDB } from "../../lib/src/pouchdb/pouchdb-browser";
import { EVENT_REQUEST_RELOAD_SETTING_TAB, EVENT_SETTING_SAVED, eventHub } from "../../common/events.ts";
import {
@@ -16,8 +16,9 @@ import { isCloudantURI } from "../../lib/src/pouchdb/utils_couchdb.ts";
import { getLanguage } from "obsidian";
import { SUPPORTED_I18N_LANGS, type I18N_LANGS } from "../../lib/src/common/rosetta.ts";
import { decryptString, encryptString } from "@/lib/src/encryption/stringEncryption.ts";
export class ModuleObsidianSettings extends AbstractObsidianModule implements IObsidianModule {
async $everyOnLayoutReady(): Promise<boolean> {
import type { LiveSyncCore } from "../../main.ts";
export class ModuleObsidianSettings extends AbstractObsidianModule {
async _everyOnLayoutReady(): Promise<boolean> {
let isChanged = false;
if (this.settings.displayLanguage == "") {
const obsidianLanguage = getLanguage();
@@ -32,7 +33,7 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
} else if (this.settings.displayLanguage == "") {
this.settings.displayLanguage = "def";
setLang(this.settings.displayLanguage);
await this.core.$$saveSettingData();
await this.services.setting.saveSettingData();
}
}
if (isChanged) {
@@ -46,7 +47,7 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
this.settings.displayLanguage = "def";
setLang(this.settings.displayLanguage);
}
await this.core.$$saveSettingData();
await this.services.setting.saveSettingData();
}
return true;
}
@@ -61,13 +62,13 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
return methodFunc();
}
$$saveDeviceAndVaultName(): void {
const lsKey = "obsidian-live-sync-vaultanddevicename-" + this.core.$$getVaultName();
localStorage.setItem(lsKey, this.core.$$getDeviceAndVaultName() || "");
_saveDeviceAndVaultName(): void {
const lsKey = "obsidian-live-sync-vaultanddevicename-" + this.services.vault.getVaultName();
localStorage.setItem(lsKey, this.services.setting.getDeviceAndVaultName() || "");
}
usedPassphrase = "";
$$clearUsedPassphrase(): void {
private _clearUsedPassphrase(): void {
this.usedPassphrase = "";
}
@@ -106,8 +107,8 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
return `${"appId" in this.app ? this.app.appId : ""}`;
}
async $$saveSettingData() {
this.core.$$saveDeviceAndVaultName();
async _saveSettingData() {
this.services.setting.saveDeviceAndVaultName();
const settings = { ...this.settings };
settings.deviceAndVaultName = "";
if (this.usedPassphrase == "" && !(await this.getPassphrase(settings))) {
@@ -174,7 +175,7 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
}
}
async $$decryptSettings(settings: ObsidianLiveSyncSettings): Promise<ObsidianLiveSyncSettings> {
async _decryptSettings(settings: ObsidianLiveSyncSettings): Promise<ObsidianLiveSyncSettings> {
const passphrase = await this.getPassphrase(settings);
if (passphrase === false) {
this._log("No passphrase found for data.json! Verify configuration before syncing.", LOG_LEVEL_URGENT);
@@ -234,7 +235,7 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
* @param settings
* @returns
*/
$$adjustSettings(settings: ObsidianLiveSyncSettings): Promise<ObsidianLiveSyncSettings> {
_adjustSettings(settings: ObsidianLiveSyncSettings): Promise<ObsidianLiveSyncSettings> {
// Adjust settings as needed
// Delete this feature to avoid problems on mobile.
@@ -264,7 +265,7 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
return Promise.resolve(settings);
}
async $$loadSettings(): Promise<void> {
async _loadSettings(): Promise<void> {
const settings = Object.assign({}, DEFAULT_SETTINGS, await this.core.loadData()) as ObsidianLiveSyncSettings;
if (typeof settings.isConfigured == "undefined") {
@@ -277,17 +278,17 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
}
}
this.settings = await this.core.$$decryptSettings(settings);
this.settings = await this.services.setting.decryptSettings(settings);
setLang(this.settings.displayLanguage);
await this.core.$$adjustSettings(this.settings);
await this.services.setting.adjustSettings(this.settings);
const lsKey = "obsidian-live-sync-vaultanddevicename-" + this.core.$$getVaultName();
const lsKey = "obsidian-live-sync-vaultanddevicename-" + this.services.vault.getVaultName();
if (this.settings.deviceAndVaultName != "") {
if (!localStorage.getItem(lsKey)) {
this.core.$$setDeviceAndVaultName(this.settings.deviceAndVaultName);
this.$$saveDeviceAndVaultName();
this.services.setting.setDeviceAndVaultName(this.settings.deviceAndVaultName);
this.services.setting.saveDeviceAndVaultName();
this.settings.deviceAndVaultName = "";
}
}
@@ -298,8 +299,8 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
);
this.settings.customChunkSize = 0;
}
this.core.$$setDeviceAndVaultName(localStorage.getItem(lsKey) || "");
if (this.core.$$getDeviceAndVaultName() == "") {
this.services.setting.setDeviceAndVaultName(localStorage.getItem(lsKey) || "");
if (this.services.setting.getDeviceAndVaultName() == "") {
if (this.settings.usePluginSync) {
this._log("Device name missing. Disabling plug-in sync.", LOG_LEVEL_NOTICE);
this.settings.usePluginSync = false;
@@ -309,4 +310,14 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
// this.core.ignoreFiles = this.settings.ignoreFiles.split(",").map(e => e.trim());
eventHub.emitEvent(EVENT_REQUEST_RELOAD_SETTING_TAB);
}
onBindFunction(core: LiveSyncCore, services: typeof core.services): void {
super.onBindFunction(core, services);
services.appLifecycle.handleLayoutReady(this._everyOnLayoutReady.bind(this));
services.setting.handleClearUsedPassphrase(this._clearUsedPassphrase.bind(this));
services.setting.handleDecryptSettings(this._decryptSettings.bind(this));
services.setting.handleAdjustSettings(this._adjustSettings.bind(this));
services.setting.handleLoadSettings(this._loadSettings.bind(this));
services.setting.handleSaveDeviceAndVaultName(this._saveDeviceAndVaultName.bind(this));
services.setting.handleSaveSettingData(this._saveSettingData.bind(this));
}
}

View File

@@ -1,4 +1,4 @@
import { type IObsidianModule, AbstractObsidianModule } from "../AbstractObsidianModule.ts";
import { AbstractObsidianModule } from "../AbstractObsidianModule.ts";
// import { PouchDB } from "../../lib/src/pouchdb/pouchdb-browser";
import { isObjectDifferent } from "octagonal-wheels/object";
import { EVENT_SETTING_SAVED, eventHub } from "../../common/events";
@@ -8,8 +8,8 @@ import { parseYaml, stringifyYaml } from "../../deps";
import { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger";
const SETTING_HEADER = "````yaml:livesync-setting\n";
const SETTING_FOOTER = "\n````";
export class ModuleObsidianSettingsAsMarkdown extends AbstractObsidianModule implements IObsidianModule {
$everyOnloadStart(): Promise<boolean> {
export class ModuleObsidianSettingsAsMarkdown extends AbstractObsidianModule {
_everyOnloadStart(): Promise<boolean> {
this.addCommand({
id: "livesync-export-config",
name: "Write setting markdown manually",
@@ -18,7 +18,7 @@ export class ModuleObsidianSettingsAsMarkdown extends AbstractObsidianModule imp
return this.settings.settingSyncFile != "";
}
fireAndForget(async () => {
await this.core.$$saveSettingData();
await this.services.setting.saveSettingData();
});
},
});
@@ -160,7 +160,7 @@ export class ModuleObsidianSettingsAsMarkdown extends AbstractObsidianModule imp
result == APPLY_AND_FETCH
) {
this.core.settings = settingToApply;
await this.core.$$saveSettingData();
await this.services.setting.saveSettingData();
if (result == APPLY_ONLY) {
this._log("Loaded settings have been applied!", LOG_LEVEL_NOTICE);
return;
@@ -171,7 +171,7 @@ export class ModuleObsidianSettingsAsMarkdown extends AbstractObsidianModule imp
if (result == APPLY_AND_FETCH) {
await this.core.rebuilder.scheduleFetch();
}
this.core.$$performRestart();
this.services.appLifecycle.performRestart();
}
});
});
@@ -242,4 +242,7 @@ We can perform a command in this file.
this._log(`Markdown setting: ${filename} has been updated!`, LOG_LEVEL_VERBOSE);
}
}
onBindFunction(core: typeof this.plugin, services: typeof core.services): void {
services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
}
}

View File

@@ -1,12 +1,12 @@
import { ObsidianLiveSyncSettingTab } from "./SettingDialogue/ObsidianLiveSyncSettingTab.ts";
import { type IObsidianModule, AbstractObsidianModule } from "../AbstractObsidianModule.ts";
import { AbstractObsidianModule } from "../AbstractObsidianModule.ts";
// import { PouchDB } from "../../lib/src/pouchdb/pouchdb-browser";
import { EVENT_REQUEST_OPEN_SETTING_WIZARD, EVENT_REQUEST_OPEN_SETTINGS, eventHub } from "../../common/events.ts";
export class ModuleObsidianSettingDialogue extends AbstractObsidianModule implements IObsidianModule {
export class ModuleObsidianSettingDialogue extends AbstractObsidianModule {
settingTab!: ObsidianLiveSyncSettingTab;
$everyOnloadStart(): Promise<boolean> {
_everyOnloadStart(): Promise<boolean> {
this.settingTab = new ObsidianLiveSyncSettingTab(this.app, this.plugin);
this.plugin.addSettingTab(this.settingTab);
eventHub.onEvent(EVENT_REQUEST_OPEN_SETTINGS, () => this.openSetting());
@@ -29,4 +29,7 @@ export class ModuleObsidianSettingDialogue extends AbstractObsidianModule implem
get appId() {
return `${"appId" in this.app ? this.app.appId : ""}`;
}
onBindFunction(core: typeof this.plugin, services: typeof core.services): void {
services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
}
}

View File

@@ -14,15 +14,16 @@ import {
EVENT_REQUEST_SHOW_SETUP_QR,
eventHub,
} from "../../common/events.ts";
import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule.ts";
import { AbstractObsidianModule } from "../AbstractObsidianModule.ts";
import { decodeAnyArray, encodeAnyArray } from "../../common/utils.ts";
import qrcode from "qrcode-generator";
import { $msg } from "../../lib/src/common/i18n.ts";
import { performDoctorConsultation, RebuildOptions } from "@/lib/src/common/configForDoc.ts";
import { encryptString, decryptString } from "@/lib/src/encryption/stringEncryption.ts";
import type { LiveSyncCore } from "../../main.ts";
export class ModuleSetupObsidian extends AbstractObsidianModule implements IObsidianModule {
$everyOnload(): Promise<boolean> {
export class ModuleSetupObsidian extends AbstractObsidianModule {
private _everyOnload(): Promise<boolean> {
this.registerObsidianProtocolHandler("setuplivesync", async (conf: any) => {
if (conf.settings) {
await this.setupWizard(conf.settings);
@@ -182,7 +183,7 @@ export class ModuleSetupObsidian extends AbstractObsidianModule implements IObsi
}
const newSettings = JSON.parse(JSON.stringify(tryingSettings)) as ObsidianLiveSyncSettings;
const remoteConfig = await this.core.$$fetchRemotePreferredTweakValues(newSettings);
const remoteConfig = await this.services.tweakValue.fetchRemotePreferred(newSettings);
if (remoteConfig) {
this._log("Remote configuration found.", LOG_LEVEL_NOTICE);
const resultSettings = {
@@ -282,16 +283,16 @@ export class ModuleSetupObsidian extends AbstractObsidianModule implements IObsi
);
if (setupType == setupJustImport) {
this.core.settings = newSettingW;
this.core.$$clearUsedPassphrase();
this.services.setting.clearUsedPassphrase();
await this.core.saveSettings();
} else if (setupType == setupAsNew) {
this.core.settings = newSettingW;
this.core.$$clearUsedPassphrase();
this.services.setting.clearUsedPassphrase();
await this.core.saveSettings();
await this.core.rebuilder.$fetchLocal();
} else if (setupType == setupAsMerge) {
this.core.settings = newSettingW;
this.core.$$clearUsedPassphrase();
this.services.setting.clearUsedPassphrase();
await this.core.saveSettings();
await this.core.rebuilder.$fetchLocal(true);
} else if (setupType == setupAgain) {
@@ -308,7 +309,7 @@ export class ModuleSetupObsidian extends AbstractObsidianModule implements IObsi
}
this.core.settings = newSettingW;
await this.core.saveSettings();
this.core.$$clearUsedPassphrase();
this.services.setting.clearUsedPassphrase();
await this.core.rebuilder.$rebuildEverything();
} else {
// Explicitly cancel the operation or the dialog was closed.
@@ -345,4 +346,7 @@ export class ModuleSetupObsidian extends AbstractObsidianModule implements IObsi
this._log(ex, LOG_LEVEL_VERBOSE);
}
}
onBindFunction(core: LiveSyncCore, services: typeof core.services): void {
services.appLifecycle.handleOnLoaded(this._everyOnload.bind(this));
}
}

View File

@@ -86,6 +86,9 @@ export function createStub(name: string, key: string, value: string, panel: stri
export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
plugin: ObsidianLiveSyncPlugin;
get services() {
return this.plugin.services;
}
selectedScreen = "";
_editingSettings?: AllSettings;
@@ -139,8 +142,8 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
return await Promise.resolve();
}
if (key == "deviceAndVaultName") {
this.plugin.$$setDeviceAndVaultName(this.editingSettings?.[key] ?? "");
this.plugin.$$saveDeviceAndVaultName();
this.services.setting.setDeviceAndVaultName(this.editingSettings?.[key] ?? "");
this.services.setting.saveDeviceAndVaultName();
return await Promise.resolve();
}
}
@@ -210,7 +213,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
const ret = { ...OnDialogSettingsDefault };
ret.configPassphrase = localStorage.getItem("ls-setting-passphrase") || "";
ret.preset = "";
ret.deviceAndVaultName = this.plugin.$$getDeviceAndVaultName();
ret.deviceAndVaultName = this.services.setting.getDeviceAndVaultName();
return ret;
}
computeAllLocalSettings(): Partial<OnDialogSettings> {
@@ -295,7 +298,11 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
async testConnection(settingOverride: Partial<ObsidianLiveSyncSettings> = {}): Promise<void> {
const trialSetting = { ...this.editingSettings, ...settingOverride };
const replicator = await this.plugin.$anyNewReplicator(trialSetting);
const replicator = await this.services.replicator.getNewReplicator(trialSetting);
if (!replicator) {
Logger("No replicator available for the current settings.", LOG_LEVEL_NOTICE);
return;
}
await replicator.tryConnectRemote(trialSetting);
const status = await replicator.getRemoteStatus(trialSetting);
if (status) {
@@ -546,10 +553,14 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
const settingForCheck: RemoteDBSettings = {
...this.editingSettings,
};
const replicator = this.plugin.$anyNewReplicator(settingForCheck);
const replicator = this.services.replicator.getNewReplicator(settingForCheck);
if (!(replicator instanceof LiveSyncCouchDBReplicator)) return true;
const db = await replicator.connectRemoteCouchDBWithSetting(settingForCheck, this.plugin.$$isMobile(), true);
const db = await replicator.connectRemoteCouchDBWithSetting(
settingForCheck,
this.services.API.isMobile(),
true
);
if (typeof db === "string") {
Logger($msg("obsidianLiveSyncSettingTab.logCheckPassphraseFailed", { db }), LOG_LEVEL_NOTICE);
return false;
@@ -588,8 +599,8 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
this.editingSettings.passphrase = "";
}
this.applyAllSettings();
await this.plugin.$allSuspendAllSync();
await this.plugin.$allSuspendExtraSync();
await this.services.setting.suspendAllSync();
await this.services.setting.suspendExtraSync();
this.reloadAllSettings();
this.editingSettings.isConfigured = true;
Logger($msg("obsidianLiveSyncSettingTab.logRebuildNote"), LOG_LEVEL_NOTICE);
@@ -638,12 +649,12 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
await this.applyAllSettings();
if (result == OPTION_FETCH) {
await this.plugin.storageAccess.writeFileAuto(FLAGMD_REDFLAG3_HR, "");
this.plugin.$$scheduleAppReload();
this.services.appLifecycle.scheduleRestart();
this.closeSetting();
// await rebuildDB("localOnly");
} else if (result == OPTION_REBUILD_BOTH) {
await this.plugin.storageAccess.writeFileAuto(FLAGMD_REDFLAG2_HR, "");
this.plugin.$$scheduleAppReload();
this.services.appLifecycle.scheduleRestart();
this.closeSetting();
} else if (result == OPTION_ONLY_SETTING) {
await this.plugin.saveSettings();

View File

@@ -156,7 +156,7 @@ export function paneHatch(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElement,
}
const obsidianInfo = {
navigator: navigator.userAgent,
fileSystem: this.plugin.$$isStorageInsensitive() ? "insensitive" : "sensitive",
fileSystem: this.plugin.services.vault.isStorageInsensitive() ? "insensitive" : "sensitive",
};
const msgConfig = `# ---- Obsidian info ----
${stringifyYaml(obsidianInfo)}
@@ -182,10 +182,10 @@ ${stringifyYaml({
void addPanel(paneEl, "Scram Switches").then((paneEl) => {
new Setting(paneEl).autoWireToggle("suspendFileWatching");
this.addOnSaved("suspendFileWatching", () => this.plugin.$$askReload());
this.addOnSaved("suspendFileWatching", () => this.services.appLifecycle.askRestart());
new Setting(paneEl).autoWireToggle("suspendParseReplicationResult");
this.addOnSaved("suspendParseReplicationResult", () => this.plugin.$$askReload());
this.addOnSaved("suspendParseReplicationResult", () => this.services.appLifecycle.askRestart());
});
void addPanel(paneEl, "Recovery and Repair").then((paneEl) => {
@@ -384,15 +384,16 @@ ${stringifyYaml({
? await this.plugin.storageAccess.statHidden(path)
: false;
const fileOnStorage = stat != null ? stat : false;
if (!(await this.plugin.$$isTargetFile(path))) return incProc();
if (!(await this.services.vault.isTargetFile(path))) return incProc();
const releaser = await semaphore.acquire(1);
if (fileOnStorage && this.plugin.$$isFileSizeExceeded(fileOnStorage.size))
if (fileOnStorage && this.services.vault.isFileSizeTooLarge(fileOnStorage.size))
return incProc();
try {
const isHiddenFile = path.startsWith(".");
const dbPath = isHiddenFile ? addPrefix(path, ICHeader) : path;
const fileOnDB = await this.plugin.localDatabase.getDBEntry(dbPath);
if (fileOnDB && this.plugin.$$isFileSizeExceeded(fileOnDB.size)) return incProc();
if (fileOnDB && this.services.vault.isFileSizeTooLarge(fileOnDB.size))
return incProc();
if (!fileOnDB && fileOnStorage) {
Logger(`Compare: Not found on the local database: ${path}`, LOG_LEVEL_NOTICE);
@@ -436,7 +437,7 @@ ${stringifyYaml({
.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 idEncoded = await this.services.path.path2id(docName as FilePathWithPrefix);
const doc = await this.plugin.localDatabase.getRaw(docName as DocumentID);
if (!doc) continue;
if (doc.type != "newnote" && doc.type != "plain") {
@@ -477,7 +478,7 @@ ${stringifyYaml({
if ((await this.plugin.localDatabase.putRaw(doc)).ok) {
Logger(`Old ${docName} has been deleted`, LOG_LEVEL_NOTICE);
}
await this.plugin.$$queueConflictCheckIfOpen(docName as FilePathWithPrefix);
await this.services.conflict.queueCheckForIfOpen(docName as FilePathWithPrefix);
} else {
Logger(`Converting ${docName} Failed!`, LOG_LEVEL_NOTICE);
Logger(ret, LOG_LEVEL_VERBOSE);
@@ -512,7 +513,7 @@ ${stringifyYaml({
.onClick(async () => {
this.editingSettings.isConfigured = false;
await this.saveAllDirtySettings();
this.plugin.$$askReload();
this.services.appLifecycle.askRestart();
})
);

View File

@@ -32,7 +32,7 @@ export function paneMaintenance(
(e) => {
e.addEventListener("click", () => {
fireAndForget(async () => {
await this.plugin.$$markRemoteResolved();
await this.services.remote.markResolved();
this.display();
});
});
@@ -59,7 +59,7 @@ export function paneMaintenance(
(e) => {
e.addEventListener("click", () => {
fireAndForget(async () => {
await this.plugin.$$markRemoteUnlocked();
await this.services.remote.markUnlocked();
this.display();
});
});
@@ -78,7 +78,7 @@ export function paneMaintenance(
.setDisabled(false)
.setWarning()
.onClick(async () => {
await this.plugin.$$markRemoteLocked();
await this.services.remote.markLocked();
})
)
.addOnUpdate(this.onlyOnCouchDBOrMinIO);
@@ -93,7 +93,7 @@ export function paneMaintenance(
.setWarning()
.onClick(async () => {
await this.plugin.storageAccess.writeFileAuto(FLAGMD_REDFLAG, "");
this.plugin.$$performRestart();
this.services.appLifecycle.performRestart();
})
);
});
@@ -255,7 +255,7 @@ export function paneMaintenance(
.setDisabled(false)
.onClick(async () => {
await this.plugin.storageAccess.writeFileAuto(FLAGMD_REDFLAG3_HR, "");
this.plugin.$$performRestart();
this.services.appLifecycle.performRestart();
})
)
.addButton((button) =>
@@ -294,7 +294,7 @@ export function paneMaintenance(
.setDisabled(false)
.onClick(async () => {
await this.plugin.storageAccess.writeFileAuto(FLAGMD_REDFLAG2_HR, "");
this.plugin.$$performRestart();
this.services.appLifecycle.performRestart();
})
)
.addButton((button) =>
@@ -405,8 +405,8 @@ export function paneMaintenance(
.setWarning()
.setDisabled(false)
.onClick(async () => {
await this.plugin.$$resetLocalDatabase();
await this.plugin.$$initializeDatabase();
await this.services.database.resetDatabase();
await this.services.databaseEvents.initialiseDatabase();
})
);
});

View File

@@ -63,7 +63,7 @@ export function panePatches(this: ObsidianLiveSyncSettingTab, paneEl: HTMLElemen
this.addOnSaved("additionalSuffixOfDatabaseName", async (key) => {
Logger("Suffix has been changed. Reopening database...", LOG_LEVEL_NOTICE);
await this.plugin.$$initializeDatabase();
await this.services.databaseEvents.initialiseDatabase();
});
new Setting(paneEl).autoWireDropDown("hashAlg", {

View File

@@ -403,7 +403,7 @@ The pane also can be launched by \`P2P Replicator\` command from the Command Pal
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleCouchDB"), undefined, this.onlyOnCouchDB).then(
(paneEl) => {
if (this.plugin.$$isMobile()) {
if (this.services.API.isMobile()) {
this.createEl(
paneEl,
"div",
@@ -630,7 +630,8 @@ The pane also can be launched by \`P2P Replicator\` command from the Command Pal
.setDisabled(false)
.onClick(async () => {
const trialSetting = { ...this.initialSettings, ...this.editingSettings };
const newTweaks = await this.plugin.$$checkAndAskUseRemoteConfiguration(trialSetting);
const newTweaks =
await this.services.tweakValue.checkAndAskUseRemoteConfiguration(trialSetting);
if (newTweaks.result !== false) {
if (this.inWizard) {
this.editingSettings = { ...this.editingSettings, ...newTweaks.result };
@@ -648,15 +649,15 @@ The pane also can be launched by \`P2P Replicator\` command from the Command Pal
}
)) == "no"
) {
await this.plugin.$$saveSettingData();
await this.services.setting.saveSettingData();
return;
}
await this.plugin.$$saveSettingData();
await this.services.setting.saveSettingData();
await this.plugin.rebuilder.scheduleFetch();
await this.plugin.$$scheduleAppReload();
this.services.appLifecycle.scheduleRestart();
return;
} else {
await this.plugin.$$saveSettingData();
await this.services.setting.saveSettingData();
}
}
}
@@ -727,7 +728,7 @@ The pane also can be launched by \`P2P Replicator\` command from the Command Pal
)) == "yes"
) {
const trialSetting = { ...this.initialSettings, ...this.editingSettings };
const newTweaks = await this.plugin.$$checkAndAskUseRemoteConfiguration(trialSetting);
const newTweaks = await this.services.tweakValue.checkAndAskUseRemoteConfiguration(trialSetting);
if (newTweaks.result !== false) {
this.editingSettings = { ...this.editingSettings, ...newTweaks.result };
this.requestUpdate();

View File

@@ -46,7 +46,7 @@ export function paneSetup(
text.setButtonText($msg("obsidianLiveSyncSettingTab.btnEnable")).onClick(async () => {
this.editingSettings.isConfigured = true;
await this.saveAllDirtySettings();
this.plugin.$$askReload();
this.services.appLifecycle.askRestart();
});
});
});
@@ -91,10 +91,10 @@ export function paneSetup(
this.editingSettings = { ...this.editingSettings, ...DEFAULT_SETTINGS };
await this.saveAllDirtySettings();
this.plugin.settings = { ...DEFAULT_SETTINGS };
await this.plugin.$$saveSettingData();
await this.plugin.$$resetLocalDatabase();
await this.services.setting.saveSettingData();
await this.services.database.resetDatabase();
// await this.plugin.initializeDatabase();
this.plugin.$$askReload();
this.services.appLifecycle.askRestart();
}
})
.setWarning();

View File

@@ -105,7 +105,7 @@ export function paneSyncSettings(
if (!this.editingSettings.isConfigured) {
this.editingSettings.isConfigured = true;
await this.saveAllDirtySettings();
await this.plugin.$$realizeSettingSyncMode();
await this.services.setting.onRealiseSetting();
await this.rebuildDB("localOnly");
// this.resetEditingSettings();
if (
@@ -124,13 +124,13 @@ export function paneSyncSettings(
await this.confirmRebuild();
} else {
await this.saveAllDirtySettings();
await this.plugin.$$realizeSettingSyncMode();
this.plugin.$$askReload();
await this.services.setting.onRealiseSetting();
this.services.appLifecycle.askRestart();
}
}
} else {
await this.saveAllDirtySettings();
await this.plugin.$$realizeSettingSyncMode();
await this.services.setting.onRealiseSetting();
}
});
});
@@ -169,7 +169,7 @@ export function paneSyncSettings(
}
await this.saveSettings(["liveSync", "periodicReplication"]);
await this.plugin.$$realizeSettingSyncMode();
await this.services.setting.onRealiseSetting();
});
new Setting(paneEl)
@@ -289,21 +289,21 @@ export function paneSyncSettings(
button.setButtonText("Merge").onClick(async () => {
this.closeSetting();
// this.resetEditingSettings();
await this.plugin.$anyConfigureOptionalSyncFeature("MERGE");
await this.services.setting.enableOptionalFeature("MERGE");
});
})
.addButton((button) => {
button.setButtonText("Fetch").onClick(async () => {
this.closeSetting();
// this.resetEditingSettings();
await this.plugin.$anyConfigureOptionalSyncFeature("FETCH");
await this.services.setting.enableOptionalFeature("FETCH");
});
})
.addButton((button) => {
button.setButtonText("Overwrite").onClick(async () => {
this.closeSetting();
// this.resetEditingSettings();
await this.plugin.$anyConfigureOptionalSyncFeature("OVERWRITE");
await this.services.setting.enableOptionalFeature("OVERWRITE");
});
});
}