mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-02-03 02:47:12 +00:00
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:
@@ -68,14 +68,23 @@ import type ObsidianLiveSyncPlugin from "../../main.ts";
|
||||
import { base64ToArrayBuffer, base64ToString } from "octagonal-wheels/binary/base64";
|
||||
import { ConflictResolveModal } from "../../modules/features/InteractiveConflictResolving/ConflictResolveModal.ts";
|
||||
import { Semaphore } from "octagonal-wheels/concurrency/semaphore";
|
||||
import type { IObsidianModule } from "../../modules/AbstractObsidianModule.ts";
|
||||
import { EVENT_REQUEST_OPEN_PLUGIN_SYNC_DIALOG, eventHub } from "../../common/events.ts";
|
||||
import { PluginDialogModal } from "./PluginDialogModal.ts";
|
||||
import { $msg } from "src/lib/src/common/i18n.ts";
|
||||
import type { InjectableServiceHub } from "../../lib/src/services/InjectableServices.ts";
|
||||
import type { LiveSyncCore } from "../../main.ts";
|
||||
|
||||
const d = "\u200b";
|
||||
const d2 = "\n";
|
||||
|
||||
declare global {
|
||||
interface OPTIONAL_SYNC_FEATURES {
|
||||
DISABLE: "DISABLE";
|
||||
CUSTOMIZE: "CUSTOMIZE";
|
||||
DISABLE_CUSTOM: "DISABLE_CUSTOM";
|
||||
}
|
||||
}
|
||||
|
||||
function serialize(data: PluginDataEx): string {
|
||||
// For higher performance, create custom plug-in data strings.
|
||||
// Self-hosted LiveSync uses `\n` to split chunks. Therefore, grouping together those with similar entropy would work nicely.
|
||||
@@ -384,7 +393,7 @@ export type PluginDataEx = {
|
||||
mtime: number;
|
||||
};
|
||||
|
||||
export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
export class ConfigSync extends LiveSyncCommands {
|
||||
constructor(plugin: ObsidianLiveSyncPlugin) {
|
||||
super(plugin);
|
||||
pluginScanningCount.onChanged((e) => {
|
||||
@@ -482,7 +491,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
// Idea non-filter option?
|
||||
return this.getFileCategory(filePath) != "";
|
||||
}
|
||||
async $everyOnDatabaseInitialized(showNotice: boolean) {
|
||||
private async _everyOnDatabaseInitialized(showNotice: boolean) {
|
||||
if (!this._isThisModuleEnabled()) return true;
|
||||
try {
|
||||
this._log("Scanning customizations...");
|
||||
@@ -494,7 +503,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async $everyBeforeReplicate(showNotice: boolean) {
|
||||
async _everyBeforeReplicate(showNotice: boolean) {
|
||||
if (!this._isThisModuleEnabled()) return true;
|
||||
if (this.settings.autoSweepPlugins) {
|
||||
await this.scanAllConfigFiles(showNotice);
|
||||
@@ -502,7 +511,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async $everyOnResumeProcess(): Promise<boolean> {
|
||||
async _everyOnResumeProcess(): Promise<boolean> {
|
||||
if (!this._isThisModuleEnabled()) return true;
|
||||
if (this._isMainSuspended()) {
|
||||
return true;
|
||||
@@ -517,7 +526,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
);
|
||||
return true;
|
||||
}
|
||||
$everyAfterResumeProcess(): Promise<boolean> {
|
||||
_everyAfterResumeProcess(): Promise<boolean> {
|
||||
const q = activeDocument.querySelector(`.livesync-ribbon-showcustom`);
|
||||
q?.toggleClass("sls-hidden", !this._isThisModuleEnabled());
|
||||
return Promise.resolve(true);
|
||||
@@ -633,7 +642,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
).startPipeline();
|
||||
|
||||
filenameToUnifiedKey(path: string, termOverRide?: string) {
|
||||
const term = termOverRide || this.plugin.$$getDeviceAndVaultName();
|
||||
const term = termOverRide || this.services.setting.getDeviceAndVaultName();
|
||||
const category = this.getFileCategory(path);
|
||||
const name =
|
||||
category == "CONFIG" || category == "SNIPPET"
|
||||
@@ -645,7 +654,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
|
||||
filenameWithUnifiedKey(path: string, termOverRide?: string) {
|
||||
const term = termOverRide || this.plugin.$$getDeviceAndVaultName();
|
||||
const term = termOverRide || this.services.setting.getDeviceAndVaultName();
|
||||
const category = this.getFileCategory(path);
|
||||
const name =
|
||||
category == "CONFIG" || category == "SNIPPET" ? path.split("/").slice(-1)[0] : path.split("/").slice(-2)[0];
|
||||
@@ -654,7 +663,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
|
||||
unifiedKeyPrefixOfTerminal(termOverRide?: string) {
|
||||
const term = termOverRide || this.plugin.$$getDeviceAndVaultName();
|
||||
const term = termOverRide || this.services.setting.getDeviceAndVaultName();
|
||||
return `${ICXHeader}${term}/` as FilePathWithPrefix;
|
||||
}
|
||||
|
||||
@@ -831,7 +840,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
const v2Path = (prefixPath + relativeFilename) as FilePathWithPrefix;
|
||||
// console.warn(`Migrating ${v1Path} / ${relativeFilename} to ${v2Path}`);
|
||||
this._log(`Migrating ${v1Path} / ${relativeFilename} to ${v2Path}`, LOG_LEVEL_VERBOSE);
|
||||
const newId = await this.plugin.$$path2id(v2Path);
|
||||
const newId = await this.services.path.path2id(v2Path);
|
||||
// const buf =
|
||||
|
||||
const data = createBlob([DUMMY_HEAD, DUMMY_END, ...getDocDataAsArray(f.data)]);
|
||||
@@ -999,7 +1008,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
await this.plugin.storageAccess.ensureDir(path);
|
||||
// If the content has applied, modified time will be updated to the current time.
|
||||
await this.plugin.storageAccess.writeHiddenFileAuto(path, content);
|
||||
await this.storeCustomisationFileV2(path, this.plugin.$$getDeviceAndVaultName());
|
||||
await this.storeCustomisationFileV2(path, this.services.setting.getDeviceAndVaultName());
|
||||
} else {
|
||||
const files = data.files;
|
||||
for (const f of files) {
|
||||
@@ -1042,7 +1051,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
await this.plugin.storageAccess.writeHiddenFileAuto(path, content, stat);
|
||||
}
|
||||
this._log(`Applied ${f.filename} of ${data.displayName || data.name}..`);
|
||||
await this.storeCustomisationFileV2(path, this.plugin.$$getDeviceAndVaultName());
|
||||
await this.storeCustomisationFileV2(path, this.services.setting.getDeviceAndVaultName());
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
@@ -1114,7 +1123,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
);
|
||||
}
|
||||
} else if (data.category == "CONFIG") {
|
||||
this.plugin.$$askReload();
|
||||
this.services.appLifecycle.askRestart();
|
||||
}
|
||||
return true;
|
||||
} catch (ex) {
|
||||
@@ -1157,8 +1166,8 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async $anyModuleParsedReplicationResultItem(docs: PouchDB.Core.ExistingDocument<EntryDoc>) {
|
||||
if (!docs._id.startsWith(ICXHeader)) return undefined;
|
||||
async _anyModuleParsedReplicationResultItem(docs: PouchDB.Core.ExistingDocument<EntryDoc>) {
|
||||
if (!docs._id.startsWith(ICXHeader)) return false;
|
||||
if (this._isThisModuleEnabled()) {
|
||||
await this.updatePluginList(
|
||||
false,
|
||||
@@ -1205,7 +1214,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async $everyRealizeSettingSyncMode(): Promise<boolean> {
|
||||
async _everyRealizeSettingSyncMode(): Promise<boolean> {
|
||||
this.periodicPluginSweepProcessor?.disable();
|
||||
if (!this._isMainReady) return true;
|
||||
if (!this._isMainSuspended()) return true;
|
||||
@@ -1345,7 +1354,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
});
|
||||
}
|
||||
async storeCustomizationFiles(path: FilePath, termOverRide?: string) {
|
||||
const term = termOverRide || this.plugin.$$getDeviceAndVaultName();
|
||||
const term = termOverRide || this.services.setting.getDeviceAndVaultName();
|
||||
if (term == "") {
|
||||
this._log("We have to configure the device name", LOG_LEVEL_NOTICE);
|
||||
return;
|
||||
@@ -1488,7 +1497,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
});
|
||||
}
|
||||
async $anyProcessOptionalFileEvent(path: FilePath): Promise<boolean | undefined> {
|
||||
async _anyProcessOptionalFileEvent(path: FilePath): Promise<boolean> {
|
||||
return await this.watchVaultRawEventsAsync(path);
|
||||
}
|
||||
|
||||
@@ -1535,7 +1544,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
await shareRunningResult("scanAllConfigFiles", async () => {
|
||||
const logLevel = showMessage ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO;
|
||||
this._log("Scanning customizing files.", logLevel, "scan-all-config");
|
||||
const term = this.plugin.$$getDeviceAndVaultName();
|
||||
const term = this.services.setting.getDeviceAndVaultName();
|
||||
if (term == "") {
|
||||
this._log("We have to configure the device name", LOG_LEVEL_NOTICE);
|
||||
return;
|
||||
@@ -1673,7 +1682,10 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
return filenames as FilePath[];
|
||||
}
|
||||
|
||||
async $allAskUsingOptionalSyncFeature(opt: { enableFetch?: boolean; enableOverwrite?: boolean }): Promise<boolean> {
|
||||
private async _allAskUsingOptionalSyncFeature(opt: {
|
||||
enableFetch?: boolean;
|
||||
enableOverwrite?: boolean;
|
||||
}): Promise<boolean> {
|
||||
await this._askHiddenFileConfiguration(opt);
|
||||
return true;
|
||||
}
|
||||
@@ -1707,7 +1719,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
}
|
||||
|
||||
$anyGetOptionalConflictCheckMethod(path: FilePathWithPrefix): Promise<boolean | "newer"> {
|
||||
_anyGetOptionalConflictCheckMethod(path: FilePathWithPrefix): Promise<boolean | "newer"> {
|
||||
if (isPluginMetadata(path)) {
|
||||
return Promise.resolve("newer");
|
||||
}
|
||||
@@ -1717,7 +1729,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
$allSuspendExtraSync(): Promise<boolean> {
|
||||
private _allSuspendExtraSync(): Promise<boolean> {
|
||||
if (this.plugin.settings.usePluginSync || this.plugin.settings.autoSweepPlugins) {
|
||||
this._log(
|
||||
"Customisation sync have been temporarily disabled. Please enable them after the fetching, if you need them.",
|
||||
@@ -1729,10 +1741,11 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
async $anyConfigureOptionalSyncFeature(mode: "CUSTOMIZE" | "DISABLE" | "DISABLE_CUSTOM") {
|
||||
private async _anyConfigureOptionalSyncFeature(mode: keyof OPTIONAL_SYNC_FEATURES) {
|
||||
await this.configureHiddenFileSync(mode);
|
||||
return true;
|
||||
}
|
||||
async configureHiddenFileSync(mode: "CUSTOMIZE" | "DISABLE" | "DISABLE_CUSTOM") {
|
||||
async configureHiddenFileSync(mode: keyof OPTIONAL_SYNC_FEATURES) {
|
||||
if (mode == "DISABLE") {
|
||||
this.plugin.settings.usePluginSync = false;
|
||||
await this.plugin.saveSettings();
|
||||
@@ -1740,7 +1753,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
|
||||
if (mode == "CUSTOMIZE") {
|
||||
if (!this.plugin.$$getDeviceAndVaultName()) {
|
||||
if (!this.services.setting.getDeviceAndVaultName()) {
|
||||
let name = await this.plugin.confirm.askString("Device name", "Please set this device name", `desktop`);
|
||||
if (!name) {
|
||||
if (Platform.isAndroidApp) {
|
||||
@@ -1764,7 +1777,7 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
name = name + Math.random().toString(36).slice(-4);
|
||||
}
|
||||
this.plugin.$$setDeviceAndVaultName(name);
|
||||
this.services.setting.setDeviceAndVaultName(name);
|
||||
}
|
||||
this.plugin.settings.usePluginSync = true;
|
||||
this.plugin.settings.useAdvancedMode = true;
|
||||
@@ -1789,4 +1802,17 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
|
||||
}
|
||||
return files;
|
||||
}
|
||||
onBindFunction(core: LiveSyncCore, services: InjectableServiceHub): void {
|
||||
services.fileProcessing.handleOptionalFileEvent(this._anyProcessOptionalFileEvent.bind(this));
|
||||
services.conflict.handleGetOptionalConflictCheckMethod(this._anyGetOptionalConflictCheckMethod.bind(this));
|
||||
services.replication.handleProcessVirtualDocuments(this._anyModuleParsedReplicationResultItem.bind(this));
|
||||
services.setting.handleOnRealiseSetting(this._everyRealizeSettingSyncMode.bind(this));
|
||||
services.appLifecycle.handleOnResuming(this._everyOnResumeProcess.bind(this));
|
||||
services.appLifecycle.handleOnResumed(this._everyAfterResumeProcess.bind(this));
|
||||
services.replication.handleBeforeReplicate(this._everyBeforeReplicate.bind(this));
|
||||
services.databaseEvents.handleDatabaseInitialised(this._everyOnDatabaseInitialized.bind(this));
|
||||
services.setting.handleSuspendExtraSync(this._allSuspendExtraSync.bind(this));
|
||||
services.setting.handleSuggestOptionalFeatures(this._allAskUsingOptionalSyncFeature.bind(this));
|
||||
services.setting.handleEnableOptionalFeature(this._anyConfigureOptionalSyncFeature.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
export let plugin: ObsidianLiveSyncPlugin;
|
||||
|
||||
$: hideNotApplicable = false;
|
||||
$: thisTerm = plugin.$$getDeviceAndVaultName();
|
||||
$: thisTerm = plugin.services.setting.getDeviceAndVaultName();
|
||||
|
||||
const addOn = plugin.getAddOn(ConfigSync.name) as ConfigSync;
|
||||
if (!addOn) {
|
||||
@@ -98,7 +98,7 @@
|
||||
await requestUpdate();
|
||||
}
|
||||
async function replicate() {
|
||||
await plugin.$$replicate(true);
|
||||
await plugin.services.replication.replicate(true);
|
||||
}
|
||||
function selectAllNewest(selectMode: boolean) {
|
||||
selectNewestPulse++;
|
||||
@@ -237,7 +237,7 @@
|
||||
plugin.settings.pluginSyncExtendedSetting[key].files = files;
|
||||
plugin.settings.pluginSyncExtendedSetting[key].mode = mode;
|
||||
}
|
||||
plugin.$$saveSettingData();
|
||||
plugin.services.setting.saveSettingData();
|
||||
}
|
||||
function getIcon(mode: SYNC_MODE) {
|
||||
if (mode in ICONS) {
|
||||
|
||||
@@ -51,12 +51,20 @@ import { LiveSyncCommands } from "../LiveSyncCommands.ts";
|
||||
import { addPrefix, stripAllPrefixes } from "../../lib/src/string_and_binary/path.ts";
|
||||
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
|
||||
import { hiddenFilesEventCount, hiddenFilesProcessingCount } from "../../lib/src/mock_and_interop/stores.ts";
|
||||
import type { IObsidianModule } from "../../modules/AbstractObsidianModule.ts";
|
||||
import { EVENT_SETTING_SAVED, eventHub } from "../../common/events.ts";
|
||||
import type { LiveSyncLocalDB } from "../../lib/src/pouchdb/LiveSyncLocalDB.ts";
|
||||
import { Semaphore } from "octagonal-wheels/concurrency/semaphore";
|
||||
import type { LiveSyncCore } from "../../main.ts";
|
||||
type SyncDirection = "push" | "pull" | "safe" | "pullForce" | "pushForce";
|
||||
|
||||
declare global {
|
||||
interface OPTIONAL_SYNC_FEATURES {
|
||||
FETCH: "FETCH";
|
||||
OVERWRITE: "OVERWRITE";
|
||||
MERGE: "MERGE";
|
||||
DISABLE: "DISABLE";
|
||||
DISABLE_HIDDEN: "DISABLE_HIDDEN";
|
||||
}
|
||||
}
|
||||
function getComparingMTime(
|
||||
doc: (MetaEntry | LoadedEntry | false) | UXFileInfo | UXStat | null | undefined,
|
||||
includeDeleted = false
|
||||
@@ -72,7 +80,7 @@ function getComparingMTime(
|
||||
return doc.mtime ?? 0;
|
||||
}
|
||||
|
||||
export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule {
|
||||
export class HiddenFileSync extends LiveSyncCommands {
|
||||
_isThisModuleEnabled() {
|
||||
return this.plugin.settings.syncInternalFiles;
|
||||
}
|
||||
@@ -132,13 +140,17 @@ export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule
|
||||
this.updateSettingCache();
|
||||
});
|
||||
}
|
||||
async $everyOnInitializeDatabase(db: LiveSyncLocalDB): Promise<boolean> {
|
||||
// We cannot initialise autosaveCache because kvDB is not ready yet
|
||||
// async _everyOnInitializeDatabase(db: LiveSyncLocalDB): Promise<boolean> {
|
||||
// this._fileInfoLastProcessed = await autosaveCache(this.kvDB, "hidden-file-lastProcessed");
|
||||
// this._databaseInfoLastProcessed = await autosaveCache(this.kvDB, "hidden-file-lastProcessed-database");
|
||||
// this._fileInfoLastKnown = await autosaveCache(this.kvDB, "hidden-file-lastKnown");
|
||||
// return true;
|
||||
// }
|
||||
private async _everyOnDatabaseInitialized(showNotice: boolean) {
|
||||
this._fileInfoLastProcessed = await autosaveCache(this.kvDB, "hidden-file-lastProcessed");
|
||||
this._databaseInfoLastProcessed = await autosaveCache(this.kvDB, "hidden-file-lastProcessed-database");
|
||||
this._fileInfoLastKnown = await autosaveCache(this.kvDB, "hidden-file-lastKnown");
|
||||
return true;
|
||||
}
|
||||
async $everyOnDatabaseInitialized(showNotice: boolean) {
|
||||
if (this._isThisModuleEnabled()) {
|
||||
if (this._fileInfoLastProcessed.size == 0 && this._fileInfoLastProcessed.size == 0) {
|
||||
this._log(`No cache found. Performing startup scan.`, LOG_LEVEL_VERBOSE);
|
||||
@@ -149,7 +161,7 @@ export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async $everyBeforeReplicate(showNotice: boolean) {
|
||||
async _everyBeforeReplicate(showNotice: boolean) {
|
||||
if (
|
||||
this._isThisModuleEnabled() &&
|
||||
this._isDatabaseReady() &&
|
||||
@@ -161,7 +173,7 @@ export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule
|
||||
return true;
|
||||
}
|
||||
|
||||
$everyOnloadAfterLoadSettings(): Promise<boolean> {
|
||||
private _everyOnloadAfterLoadSettings(): Promise<boolean> {
|
||||
this.updateSettingCache();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
@@ -197,7 +209,7 @@ export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule
|
||||
await this.applyOfflineChanges(showNotice);
|
||||
}
|
||||
|
||||
async $everyOnResumeProcess(): Promise<boolean> {
|
||||
async _everyOnResumeProcess(): Promise<boolean> {
|
||||
this.periodicInternalFileScanProcessor?.disable();
|
||||
if (this._isMainSuspended()) return true;
|
||||
if (this._isThisModuleEnabled()) {
|
||||
@@ -211,10 +223,10 @@ export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule
|
||||
return true;
|
||||
}
|
||||
|
||||
$everyRealizeSettingSyncMode(): Promise<boolean> {
|
||||
_everyRealizeSettingSyncMode(): Promise<boolean> {
|
||||
this.periodicInternalFileScanProcessor?.disable();
|
||||
if (this._isMainSuspended()) return Promise.resolve(true);
|
||||
if (!this.plugin.$$isReady()) return Promise.resolve(true);
|
||||
if (!this.services.appLifecycle.isReady()) return Promise.resolve(true);
|
||||
this.periodicInternalFileScanProcessor.enable(
|
||||
this._isThisModuleEnabled() && this.settings.syncInternalFilesInterval
|
||||
? this.settings.syncInternalFilesInterval * 1000
|
||||
@@ -227,13 +239,14 @@ export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
async $anyProcessOptionalFileEvent(path: FilePath): Promise<boolean | undefined> {
|
||||
async _anyProcessOptionalFileEvent(path: FilePath): Promise<boolean> {
|
||||
if (this.isReady()) {
|
||||
return await this.trackStorageFileModification(path);
|
||||
return (await this.trackStorageFileModification(path)) || false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$anyGetOptionalConflictCheckMethod(path: FilePathWithPrefix): Promise<boolean | "newer"> {
|
||||
_anyGetOptionalConflictCheckMethod(path: FilePathWithPrefix): Promise<boolean | "newer"> {
|
||||
if (isInternalMetadata(path)) {
|
||||
this.queueConflictCheck(path);
|
||||
return Promise.resolve(true);
|
||||
@@ -241,12 +254,12 @@ export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
async $anyProcessOptionalSyncFiles(doc: LoadedEntry): Promise<boolean | undefined> {
|
||||
async _anyProcessOptionalSyncFiles(doc: LoadedEntry): Promise<boolean> {
|
||||
if (isInternalMetadata(doc._id)) {
|
||||
if (this._isThisModuleEnabled()) {
|
||||
//system file
|
||||
const filename = getPath(doc);
|
||||
if (await this.plugin.$$isTargetFile(filename)) {
|
||||
if (await this.services.vault.isTargetFile(filename)) {
|
||||
// this.procInternalFile(filename);
|
||||
await this.processReplicationResult(doc);
|
||||
return true;
|
||||
@@ -1091,14 +1104,14 @@ Offline Changed files: ${files.length}`;
|
||||
|
||||
// If something changes left, notify for reloading Obsidian.
|
||||
if (updatedFolders.indexOf(this.plugin.app.vault.configDir) >= 0) {
|
||||
if (!this.plugin.$$isReloadingScheduled()) {
|
||||
if (!this.services.appLifecycle.isReloadingScheduled()) {
|
||||
this.plugin.confirm.askInPopup(
|
||||
`updated-any-hidden`,
|
||||
`Some setting files have been modified\nPress {HERE} to schedule a reload of Obsidian, or press elsewhere to dismiss this message.`,
|
||||
(anchor) => {
|
||||
anchor.text = "HERE";
|
||||
anchor.addEventListener("click", () => {
|
||||
this.plugin.$$scheduleAppReload();
|
||||
this.services.appLifecycle.scheduleRestart();
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -1318,7 +1331,7 @@ Offline Changed files: ${files.length}`;
|
||||
async storeInternalFileToDatabase(file: InternalFileInfo | UXFileInfo, forceWrite = false) {
|
||||
const storeFilePath = stripAllPrefixes(file.path as FilePath);
|
||||
const storageFilePath = file.path;
|
||||
if (await this.plugin.$$isIgnoredByIgnoreFiles(storageFilePath)) {
|
||||
if (await this.services.vault.isIgnoredByIgnoreFile(storageFilePath)) {
|
||||
return undefined;
|
||||
}
|
||||
const prefixedFileName = addPrefix(storeFilePath, ICHeader);
|
||||
@@ -1372,7 +1385,7 @@ Offline Changed files: ${files.length}`;
|
||||
const displayFileName = filenameSrc;
|
||||
const prefixedFileName = addPrefix(storeFilePath, ICHeader);
|
||||
const mtime = new Date().getTime();
|
||||
if (await this.plugin.$$isIgnoredByIgnoreFiles(storageFilePath)) {
|
||||
if (await this.services.vault.isIgnoredByIgnoreFile(storageFilePath)) {
|
||||
return undefined;
|
||||
}
|
||||
return await serialized("file-" + prefixedFileName, async () => {
|
||||
@@ -1432,7 +1445,7 @@ Offline Changed files: ${files.length}`;
|
||||
includeDeletion = true
|
||||
) {
|
||||
const prefixedFileName = addPrefix(storageFilePath, ICHeader);
|
||||
if (await this.plugin.$$isIgnoredByIgnoreFiles(storageFilePath)) {
|
||||
if (await this.services.vault.isIgnoredByIgnoreFile(storageFilePath)) {
|
||||
return undefined;
|
||||
}
|
||||
return await serialized("file-" + prefixedFileName, async () => {
|
||||
@@ -1582,7 +1595,7 @@ Offline Changed files: ${files.length}`;
|
||||
|
||||
// <-- Database To Storage Functions
|
||||
|
||||
async $allAskUsingOptionalSyncFeature(opt: { enableFetch?: boolean; enableOverwrite?: boolean }) {
|
||||
private async _allAskUsingOptionalSyncFeature(opt: { enableFetch?: boolean; enableOverwrite?: boolean }) {
|
||||
await this._askHiddenFileConfiguration(opt);
|
||||
return true;
|
||||
}
|
||||
@@ -1632,7 +1645,7 @@ ${messageFetch}${messageOverwrite}${messageMerge}
|
||||
}
|
||||
}
|
||||
|
||||
$allSuspendExtraSync(): Promise<boolean> {
|
||||
private _allSuspendExtraSync(): Promise<boolean> {
|
||||
if (this.plugin.settings.syncInternalFiles) {
|
||||
this._log(
|
||||
"Hidden file synchronization have been temporarily disabled. Please enable them after the fetching, if you need them.",
|
||||
@@ -1644,11 +1657,12 @@ ${messageFetch}${messageOverwrite}${messageMerge}
|
||||
}
|
||||
|
||||
// --> Configuration handling
|
||||
async $anyConfigureOptionalSyncFeature(mode: "FETCH" | "OVERWRITE" | "MERGE" | "DISABLE" | "DISABLE_HIDDEN") {
|
||||
private async _anyConfigureOptionalSyncFeature(mode: keyof OPTIONAL_SYNC_FEATURES) {
|
||||
await this.configureHiddenFileSync(mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
async configureHiddenFileSync(mode: "FETCH" | "OVERWRITE" | "MERGE" | "DISABLE" | "DISABLE_HIDDEN") {
|
||||
async configureHiddenFileSync(mode: keyof OPTIONAL_SYNC_FEATURES) {
|
||||
if (
|
||||
mode != "FETCH" &&
|
||||
mode != "OVERWRITE" &&
|
||||
@@ -1718,7 +1732,7 @@ ${messageFetch}${messageOverwrite}${messageMerge}
|
||||
const result: InternalFileInfo[] = [];
|
||||
for (const f of files) {
|
||||
const w = await f;
|
||||
if (await this.plugin.$$isIgnoredByIgnoreFiles(w.path)) {
|
||||
if (await this.services.vault.isIgnoredByIgnoreFile(w.path)) {
|
||||
continue;
|
||||
}
|
||||
const mtime = w.stat?.mtime ?? 0;
|
||||
@@ -1756,7 +1770,7 @@ ${messageFetch}${messageOverwrite}${messageMerge}
|
||||
if (ignoreFilter && ignoreFilter.some((ee) => ee.test(file))) {
|
||||
continue;
|
||||
}
|
||||
if (await this.plugin.$$isIgnoredByIgnoreFiles(file)) continue;
|
||||
if (await this.services.vault.isIgnoredByIgnoreFile(file)) continue;
|
||||
files.push(file);
|
||||
}
|
||||
L1: for (const v of w.folders) {
|
||||
@@ -1768,7 +1782,7 @@ ${messageFetch}${messageOverwrite}${messageMerge}
|
||||
if (ignoreFilter && ignoreFilter.some((e) => e.test(v))) {
|
||||
continue L1;
|
||||
}
|
||||
if (await this.plugin.$$isIgnoredByIgnoreFiles(v)) {
|
||||
if (await this.services.vault.isIgnoredByIgnoreFile(v)) {
|
||||
continue L1;
|
||||
}
|
||||
files = files.concat(await this.getFiles(v, ignoreList, filter, ignoreFilter));
|
||||
@@ -1777,4 +1791,20 @@ ${messageFetch}${messageOverwrite}${messageMerge}
|
||||
}
|
||||
|
||||
// <-- Local Storage SubFunctions
|
||||
|
||||
onBindFunction(core: LiveSyncCore, services: typeof core.services) {
|
||||
// No longer needed on initialisation
|
||||
// services.databaseEvents.handleOnDatabaseInitialisation(this._everyOnInitializeDatabase.bind(this));
|
||||
services.appLifecycle.handleOnSettingLoaded(this._everyOnloadAfterLoadSettings.bind(this));
|
||||
services.fileProcessing.handleOptionalFileEvent(this._anyProcessOptionalFileEvent.bind(this));
|
||||
services.conflict.handleGetOptionalConflictCheckMethod(this._anyGetOptionalConflictCheckMethod.bind(this));
|
||||
services.replication.handleProcessOptionalSynchroniseResult(this._anyProcessOptionalSyncFiles.bind(this));
|
||||
services.setting.handleOnRealiseSetting(this._everyRealizeSettingSyncMode.bind(this));
|
||||
services.appLifecycle.handleOnResuming(this._everyOnResumeProcess.bind(this));
|
||||
services.replication.handleBeforeReplicate(this._everyBeforeReplicate.bind(this));
|
||||
services.databaseEvents.handleDatabaseInitialised(this._everyOnDatabaseInitialized.bind(this));
|
||||
services.setting.handleSuspendExtraSync(this._allSuspendExtraSync.bind(this));
|
||||
services.setting.handleSuggestOptionalFeatures(this._allAskUsingOptionalSyncFeature.bind(this));
|
||||
services.setting.handleEnableOptionalFeature(this._anyConfigureOptionalSyncFeature.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ import {
|
||||
LOG_LEVEL_NOTICE,
|
||||
type AnyEntry,
|
||||
type DocumentID,
|
||||
type EntryHasPath,
|
||||
type FilePath,
|
||||
type FilePathWithPrefix,
|
||||
type LOG_LEVEL,
|
||||
} from "../lib/src/common/types.ts";
|
||||
import type ObsidianLiveSyncPlugin from "../main.ts";
|
||||
import { MARK_DONE } from "../modules/features/ModuleLog.ts";
|
||||
import type { LiveSyncCore } from "../main.ts";
|
||||
|
||||
let noticeIndex = 0;
|
||||
export abstract class LiveSyncCommands {
|
||||
@@ -25,12 +25,15 @@ export abstract class LiveSyncCommands {
|
||||
get localDatabase() {
|
||||
return this.plugin.localDatabase;
|
||||
}
|
||||
|
||||
id2path(id: DocumentID, entry?: EntryHasPath, stripPrefix?: boolean): FilePathWithPrefix {
|
||||
return this.plugin.$$id2path(id, entry, stripPrefix);
|
||||
get services() {
|
||||
return this.plugin.services;
|
||||
}
|
||||
|
||||
// id2path(id: DocumentID, entry?: EntryHasPath, stripPrefix?: boolean): FilePathWithPrefix {
|
||||
// return this.plugin.$$id2path(id, entry, stripPrefix);
|
||||
// }
|
||||
async path2id(filename: FilePathWithPrefix | FilePath, prefix?: string): Promise<DocumentID> {
|
||||
return await this.plugin.$$path2id(filename, prefix);
|
||||
return await this.services.path.path2id(filename, prefix);
|
||||
}
|
||||
getPath(entry: AnyEntry): FilePathWithPrefix {
|
||||
return getPath(entry);
|
||||
@@ -38,18 +41,19 @@ export abstract class LiveSyncCommands {
|
||||
|
||||
constructor(plugin: ObsidianLiveSyncPlugin) {
|
||||
this.plugin = plugin;
|
||||
this.onBindFunction(plugin, plugin.services);
|
||||
}
|
||||
abstract onunload(): void;
|
||||
abstract onload(): void | Promise<void>;
|
||||
|
||||
_isMainReady() {
|
||||
return this.plugin.$$isReady();
|
||||
return this.plugin.services.appLifecycle.isReady();
|
||||
}
|
||||
_isMainSuspended() {
|
||||
return this.plugin.$$isSuspended();
|
||||
return this.services.appLifecycle.isSuspended();
|
||||
}
|
||||
_isDatabaseReady() {
|
||||
return this.plugin.$$isDatabaseReady();
|
||||
return this.services.database.isDatabaseReady();
|
||||
}
|
||||
|
||||
_log = (msg: any, level: LOG_LEVEL = LOG_LEVEL_INFO, key?: string) => {
|
||||
@@ -89,4 +93,8 @@ export abstract class LiveSyncCommands {
|
||||
_debug = (msg: any, key?: string) => {
|
||||
this._log(msg, LOG_LEVEL_VERBOSE, key);
|
||||
};
|
||||
|
||||
onBindFunction(core: LiveSyncCore, services: typeof core.services) {
|
||||
// Override if needed.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
type MetaEntry,
|
||||
} from "../../lib/src/common/types";
|
||||
import { getNoFromRev } from "../../lib/src/pouchdb/LiveSyncLocalDB";
|
||||
import type { IObsidianModule } from "../../modules/AbstractObsidianModule";
|
||||
import { LiveSyncCommands } from "../LiveSyncCommands";
|
||||
import { serialized } from "octagonal-wheels/concurrency/lock_v2";
|
||||
import { arrayToChunkedArray } from "octagonal-wheels/collection";
|
||||
@@ -22,10 +21,7 @@ type NoteDocumentID = DocumentID;
|
||||
type Rev = string;
|
||||
|
||||
type ChunkUsageMap = Map<NoteDocumentID, Map<Rev, Set<ChunkID>>>;
|
||||
export class LocalDatabaseMaintenance extends LiveSyncCommands implements IObsidianModule {
|
||||
$everyOnload(): Promise<boolean> {
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
export class LocalDatabaseMaintenance extends LiveSyncCommands {
|
||||
onunload(): void {
|
||||
// NO OP.
|
||||
}
|
||||
|
||||
@@ -1,21 +1,27 @@
|
||||
import type { IObsidianModule } from "../../modules/AbstractObsidianModule";
|
||||
import { P2PReplicatorPaneView, VIEW_TYPE_P2P } from "./P2PReplicator/P2PReplicatorPaneView.ts";
|
||||
import {
|
||||
AutoAccepting,
|
||||
LOG_LEVEL_NOTICE,
|
||||
P2P_DEFAULT_SETTINGS,
|
||||
REMOTE_P2P,
|
||||
type EntryDoc,
|
||||
type P2PSyncSetting,
|
||||
type RemoteDBSettings,
|
||||
} from "../../lib/src/common/types.ts";
|
||||
import { LiveSyncCommands } from "../LiveSyncCommands.ts";
|
||||
import { LiveSyncTrysteroReplicator } from "../../lib/src/replication/trystero/LiveSyncTrysteroReplicator.ts";
|
||||
import {
|
||||
LiveSyncTrysteroReplicator,
|
||||
setReplicatorFunc,
|
||||
} from "../../lib/src/replication/trystero/LiveSyncTrysteroReplicator.ts";
|
||||
import { EVENT_REQUEST_OPEN_P2P, eventHub } from "../../common/events.ts";
|
||||
import type { LiveSyncAbstractReplicator } from "../../lib/src/replication/LiveSyncAbstractReplicator.ts";
|
||||
import { Logger } from "octagonal-wheels/common/logger";
|
||||
import { LOG_LEVEL_INFO, LOG_LEVEL_VERBOSE, Logger } from "octagonal-wheels/common/logger";
|
||||
import type { CommandShim } from "../../lib/src/replication/trystero/P2PReplicatorPaneCommon.ts";
|
||||
import {
|
||||
P2PReplicatorMixIn,
|
||||
addP2PEventHandlers,
|
||||
closeP2PReplicator,
|
||||
openP2PReplicator,
|
||||
P2PLogCollector,
|
||||
removeP2PReplicatorInstance,
|
||||
type P2PReplicatorBase,
|
||||
} from "../../lib/src/replication/trystero/P2PReplicatorCore.ts";
|
||||
@@ -24,8 +30,180 @@ import type { Confirm } from "../../lib/src/interfaces/Confirm.ts";
|
||||
import type ObsidianLiveSyncPlugin from "../../main.ts";
|
||||
import type { SimpleStore } from "octagonal-wheels/databases/SimpleStoreBase";
|
||||
import { getPlatformName } from "../../lib/src/PlatformAPIs/obsidian/Environment.ts";
|
||||
import type { LiveSyncCore } from "../../main.ts";
|
||||
import { TrysteroReplicator } from "../../lib/src/replication/trystero/TrysteroReplicator.ts";
|
||||
|
||||
class P2PReplicatorCommandBase extends LiveSyncCommands implements P2PReplicatorBase {
|
||||
// class P2PReplicatorCommandBase extends LiveSyncCommands implements P2PReplicatorBase {
|
||||
// storeP2PStatusLine = reactiveSource("");
|
||||
|
||||
// getSettings(): P2PSyncSetting {
|
||||
// return this.plugin.settings;
|
||||
// }
|
||||
// get settings() {
|
||||
// return this.plugin.settings;
|
||||
// }
|
||||
// getDB() {
|
||||
// return this.plugin.localDatabase.localDatabase;
|
||||
// }
|
||||
|
||||
// get confirm(): Confirm {
|
||||
// return this.plugin.confirm;
|
||||
// }
|
||||
// _simpleStore!: SimpleStore<any>;
|
||||
|
||||
// simpleStore(): SimpleStore<any> {
|
||||
// return this._simpleStore;
|
||||
// }
|
||||
|
||||
// constructor(plugin: ObsidianLiveSyncPlugin) {
|
||||
// super(plugin);
|
||||
// this.onBindFunction(plugin, plugin.services);
|
||||
// }
|
||||
|
||||
// async handleReplicatedDocuments(docs: EntryDoc[]): Promise<void> {
|
||||
// // console.log("Processing Replicated Docs", docs);
|
||||
// return await this.services.replication.parseSynchroniseResult(
|
||||
// docs as PouchDB.Core.ExistingDocument<EntryDoc>[]
|
||||
// );
|
||||
// }
|
||||
// onunload(): void {
|
||||
// throw new Error("Method not implemented.");
|
||||
// }
|
||||
// onload(): void | Promise<void> {
|
||||
// throw new Error("Method not implemented.");
|
||||
// }
|
||||
|
||||
// init() {
|
||||
// this._simpleStore = this.services.database.openSimpleStore("p2p-sync");
|
||||
// return Promise.resolve(this);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// export class P2PReplicator extends P2PReplicatorMixIn(P2PReplicatorCommandBase) implements CommandShim {
|
||||
// storeP2PStatusLine = reactiveSource("");
|
||||
// _anyNewReplicator(settingOverride: Partial<RemoteDBSettings> = {}): Promise<LiveSyncAbstractReplicator> {
|
||||
// const settings = { ...this.settings, ...settingOverride };
|
||||
// if (settings.remoteType == REMOTE_P2P) {
|
||||
// return Promise.resolve(new LiveSyncTrysteroReplicator(this.plugin));
|
||||
// }
|
||||
// return undefined!;
|
||||
// }
|
||||
// override getPlatform(): string {
|
||||
// return getPlatformName();
|
||||
// }
|
||||
|
||||
// override onunload(): void {
|
||||
// removeP2PReplicatorInstance();
|
||||
// void this.close();
|
||||
// }
|
||||
|
||||
// override onload(): void | Promise<void> {
|
||||
// eventHub.onEvent(EVENT_REQUEST_OPEN_P2P, () => {
|
||||
// void this.openPane();
|
||||
// });
|
||||
// this.p2pLogCollector.p2pReplicationLine.onChanged((line) => {
|
||||
// this.storeP2PStatusLine.value = line.value;
|
||||
// });
|
||||
// }
|
||||
// async _everyOnInitializeDatabase(): Promise<boolean> {
|
||||
// await this.initialiseP2PReplicator();
|
||||
// return Promise.resolve(true);
|
||||
// }
|
||||
|
||||
// private async _allSuspendExtraSync() {
|
||||
// this.plugin.settings.P2P_Enabled = false;
|
||||
// this.plugin.settings.P2P_AutoAccepting = AutoAccepting.NONE;
|
||||
// this.plugin.settings.P2P_AutoBroadcast = false;
|
||||
// this.plugin.settings.P2P_AutoStart = false;
|
||||
// this.plugin.settings.P2P_AutoSyncPeers = "";
|
||||
// this.plugin.settings.P2P_AutoWatchPeers = "";
|
||||
// return await Promise.resolve(true);
|
||||
// }
|
||||
|
||||
// // async $everyOnLoadStart() {
|
||||
// // return await Promise.resolve();
|
||||
// // }
|
||||
|
||||
// async openPane() {
|
||||
// await this.services.API.showWindow(VIEW_TYPE_P2P);
|
||||
// }
|
||||
|
||||
// async _everyOnloadStart(): Promise<boolean> {
|
||||
// // this.plugin.registerView(VIEW_TYPE_P2P, (leaf) => new P2PReplicatorPaneView(leaf, this.plugin));
|
||||
// this.plugin.addCommand({
|
||||
// id: "open-p2p-replicator",
|
||||
// name: "P2P Sync : Open P2P Replicator",
|
||||
// callback: async () => {
|
||||
// await this.openPane();
|
||||
// },
|
||||
// });
|
||||
// this.plugin.addCommand({
|
||||
// id: "p2p-establish-connection",
|
||||
// name: "P2P Sync : Connect to the Signalling Server",
|
||||
// checkCallback: (isChecking) => {
|
||||
// if (isChecking) {
|
||||
// return !(this._replicatorInstance?.server?.isServing ?? false);
|
||||
// }
|
||||
// void this.open();
|
||||
// },
|
||||
// });
|
||||
// this.plugin.addCommand({
|
||||
// id: "p2p-close-connection",
|
||||
// name: "P2P Sync : Disconnect from the Signalling Server",
|
||||
// checkCallback: (isChecking) => {
|
||||
// if (isChecking) {
|
||||
// return this._replicatorInstance?.server?.isServing ?? false;
|
||||
// }
|
||||
// Logger(`Closing P2P Connection`, LOG_LEVEL_NOTICE);
|
||||
// void this.close();
|
||||
// },
|
||||
// });
|
||||
// this.plugin.addCommand({
|
||||
// id: "replicate-now-by-p2p",
|
||||
// name: "Replicate now by P2P",
|
||||
// checkCallback: (isChecking) => {
|
||||
// if (isChecking) {
|
||||
// if (this.settings.remoteType == REMOTE_P2P) return false;
|
||||
// if (!this._replicatorInstance?.server?.isServing) return false;
|
||||
// return true;
|
||||
// }
|
||||
// void this._replicatorInstance?.replicateFromCommand(false);
|
||||
// },
|
||||
// });
|
||||
// this.plugin
|
||||
// .addRibbonIcon("waypoints", "P2P Replicator", async () => {
|
||||
// await this.openPane();
|
||||
// })
|
||||
// .addClass("livesync-ribbon-replicate-p2p");
|
||||
|
||||
// return await Promise.resolve(true);
|
||||
// }
|
||||
// _everyAfterResumeProcess(): Promise<boolean> {
|
||||
// if (this.settings.P2P_Enabled && this.settings.P2P_AutoStart) {
|
||||
// setTimeout(() => void this.open(), 100);
|
||||
// }
|
||||
// const rep = this._replicatorInstance;
|
||||
// rep?.allowReconnection();
|
||||
// return Promise.resolve(true);
|
||||
// }
|
||||
// _everyBeforeSuspendProcess(): Promise<boolean> {
|
||||
// const rep = this._replicatorInstance;
|
||||
// rep?.disconnectFromServer();
|
||||
// return Promise.resolve(true);
|
||||
// }
|
||||
|
||||
// override onBindFunction(core: LiveSyncCore, services: typeof core.services): void {
|
||||
// services.replicator.handleGetNewReplicator(this._anyNewReplicator.bind(this));
|
||||
// services.databaseEvents.handleOnDatabaseInitialisation(this._everyOnInitializeDatabase.bind(this));
|
||||
// services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
|
||||
// services.appLifecycle.handleOnSuspending(this._everyBeforeSuspendProcess.bind(this));
|
||||
// services.appLifecycle.handleOnResumed(this._everyAfterResumeProcess.bind(this));
|
||||
// services.setting.handleSuspendExtraSync(this._allSuspendExtraSync.bind(this));
|
||||
// }
|
||||
// }
|
||||
|
||||
export class P2PReplicator extends LiveSyncCommands implements P2PReplicatorBase, CommandShim {
|
||||
storeP2PStatusLine = reactiveSource("");
|
||||
|
||||
getSettings(): P2PSyncSetting {
|
||||
@@ -49,47 +227,126 @@ class P2PReplicatorCommandBase extends LiveSyncCommands implements P2PReplicator
|
||||
|
||||
constructor(plugin: ObsidianLiveSyncPlugin) {
|
||||
super(plugin);
|
||||
setReplicatorFunc(() => this._replicatorInstance);
|
||||
addP2PEventHandlers(this);
|
||||
this.afterConstructor();
|
||||
this.onBindFunction(plugin, plugin.services);
|
||||
}
|
||||
|
||||
async handleReplicatedDocuments(docs: EntryDoc[]): Promise<void> {
|
||||
// console.log("Processing Replicated Docs", docs);
|
||||
return await this.plugin.$$parseReplicationResult(docs as PouchDB.Core.ExistingDocument<EntryDoc>[]);
|
||||
}
|
||||
onunload(): void {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
onload(): void | Promise<void> {
|
||||
throw new Error("Method not implemented.");
|
||||
return await this.services.replication.parseSynchroniseResult(
|
||||
docs as PouchDB.Core.ExistingDocument<EntryDoc>[]
|
||||
);
|
||||
}
|
||||
|
||||
init() {
|
||||
this._simpleStore = this.plugin.$$getSimpleStore("p2p-sync");
|
||||
return Promise.resolve(this);
|
||||
}
|
||||
}
|
||||
|
||||
export class P2PReplicator
|
||||
extends P2PReplicatorMixIn(P2PReplicatorCommandBase)
|
||||
implements IObsidianModule, CommandShim
|
||||
{
|
||||
storeP2PStatusLine = reactiveSource("");
|
||||
$anyNewReplicator(settingOverride: Partial<RemoteDBSettings> = {}): Promise<LiveSyncAbstractReplicator> {
|
||||
_anyNewReplicator(settingOverride: Partial<RemoteDBSettings> = {}): Promise<LiveSyncAbstractReplicator> {
|
||||
const settings = { ...this.settings, ...settingOverride };
|
||||
if (settings.remoteType == REMOTE_P2P) {
|
||||
return Promise.resolve(new LiveSyncTrysteroReplicator(this.plugin));
|
||||
}
|
||||
return undefined!;
|
||||
}
|
||||
override getPlatform(): string {
|
||||
_replicatorInstance?: TrysteroReplicator;
|
||||
p2pLogCollector = new P2PLogCollector();
|
||||
|
||||
afterConstructor() {
|
||||
return;
|
||||
}
|
||||
|
||||
async open() {
|
||||
await openP2PReplicator(this);
|
||||
}
|
||||
async close() {
|
||||
await closeP2PReplicator(this);
|
||||
}
|
||||
|
||||
getConfig(key: string) {
|
||||
const vaultName = this.services.vault.getVaultName();
|
||||
const dbKey = `${vaultName}-${key}`;
|
||||
return localStorage.getItem(dbKey);
|
||||
}
|
||||
setConfig(key: string, value: string) {
|
||||
const vaultName = this.services.vault.getVaultName();
|
||||
const dbKey = `${vaultName}-${key}`;
|
||||
localStorage.setItem(dbKey, value);
|
||||
}
|
||||
enableBroadcastCastings() {
|
||||
return this?._replicatorInstance?.enableBroadcastChanges();
|
||||
}
|
||||
disableBroadcastCastings() {
|
||||
return this?._replicatorInstance?.disableBroadcastChanges();
|
||||
}
|
||||
|
||||
init() {
|
||||
this._simpleStore = this.services.database.openSimpleStore("p2p-sync");
|
||||
return Promise.resolve(this);
|
||||
}
|
||||
|
||||
async initialiseP2PReplicator(): Promise<TrysteroReplicator> {
|
||||
await this.init();
|
||||
try {
|
||||
if (this._replicatorInstance) {
|
||||
await this._replicatorInstance.close();
|
||||
this._replicatorInstance = undefined;
|
||||
}
|
||||
|
||||
if (!this.settings.P2P_AppID) {
|
||||
this.settings.P2P_AppID = P2P_DEFAULT_SETTINGS.P2P_AppID;
|
||||
}
|
||||
const getInitialDeviceName = () => this.getConfig("p2p_device_name") || this.services.vault.getVaultName();
|
||||
|
||||
const getSettings = () => this.settings;
|
||||
const store = () => this.simpleStore();
|
||||
const getDB = () => this.getDB();
|
||||
|
||||
const getConfirm = () => this.confirm;
|
||||
const getPlatform = () => this.getPlatform();
|
||||
const env = {
|
||||
get db() {
|
||||
return getDB();
|
||||
},
|
||||
get confirm() {
|
||||
return getConfirm();
|
||||
},
|
||||
get deviceName() {
|
||||
return getInitialDeviceName();
|
||||
},
|
||||
get platform() {
|
||||
return getPlatform();
|
||||
},
|
||||
get settings() {
|
||||
return getSettings();
|
||||
},
|
||||
processReplicatedDocs: async (docs: EntryDoc[]): Promise<void> => {
|
||||
await this.handleReplicatedDocuments(docs);
|
||||
// No op. This is a client and does not need to process the docs
|
||||
},
|
||||
get simpleStore() {
|
||||
return store();
|
||||
},
|
||||
};
|
||||
this._replicatorInstance = new TrysteroReplicator(env);
|
||||
return this._replicatorInstance;
|
||||
} catch (e) {
|
||||
this._log(
|
||||
e instanceof Error ? e.message : "Something occurred on Initialising P2P Replicator",
|
||||
LOG_LEVEL_INFO
|
||||
);
|
||||
this._log(e, LOG_LEVEL_VERBOSE);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
getPlatform(): string {
|
||||
return getPlatformName();
|
||||
}
|
||||
|
||||
override onunload(): void {
|
||||
onunload(): void {
|
||||
removeP2PReplicatorInstance();
|
||||
void this.close();
|
||||
}
|
||||
|
||||
override onload(): void | Promise<void> {
|
||||
onload(): void | Promise<void> {
|
||||
eventHub.onEvent(EVENT_REQUEST_OPEN_P2P, () => {
|
||||
void this.openPane();
|
||||
});
|
||||
@@ -97,12 +354,12 @@ export class P2PReplicator
|
||||
this.storeP2PStatusLine.value = line.value;
|
||||
});
|
||||
}
|
||||
async $everyOnInitializeDatabase(): Promise<boolean> {
|
||||
async _everyOnInitializeDatabase(): Promise<boolean> {
|
||||
await this.initialiseP2PReplicator();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
async $allSuspendExtraSync() {
|
||||
private async _allSuspendExtraSync() {
|
||||
this.plugin.settings.P2P_Enabled = false;
|
||||
this.plugin.settings.P2P_AutoAccepting = AutoAccepting.NONE;
|
||||
this.plugin.settings.P2P_AutoBroadcast = false;
|
||||
@@ -112,15 +369,15 @@ export class P2PReplicator
|
||||
return await Promise.resolve(true);
|
||||
}
|
||||
|
||||
async $everyOnLoadStart() {
|
||||
return await Promise.resolve();
|
||||
}
|
||||
// async $everyOnLoadStart() {
|
||||
// return await Promise.resolve();
|
||||
// }
|
||||
|
||||
async openPane() {
|
||||
await this.plugin.$$showView(VIEW_TYPE_P2P);
|
||||
await this.services.API.showWindow(VIEW_TYPE_P2P);
|
||||
}
|
||||
|
||||
async $everyOnloadStart(): Promise<boolean> {
|
||||
async _everyOnloadStart(): Promise<boolean> {
|
||||
this.plugin.registerView(VIEW_TYPE_P2P, (leaf) => new P2PReplicatorPaneView(leaf, this.plugin));
|
||||
this.plugin.addCommand({
|
||||
id: "open-p2p-replicator",
|
||||
@@ -170,7 +427,7 @@ export class P2PReplicator
|
||||
|
||||
return await Promise.resolve(true);
|
||||
}
|
||||
$everyAfterResumeProcess(): Promise<boolean> {
|
||||
_everyAfterResumeProcess(): Promise<boolean> {
|
||||
if (this.settings.P2P_Enabled && this.settings.P2P_AutoStart) {
|
||||
setTimeout(() => void this.open(), 100);
|
||||
}
|
||||
@@ -178,9 +435,18 @@ export class P2PReplicator
|
||||
rep?.allowReconnection();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
$everyBeforeSuspendProcess(): Promise<boolean> {
|
||||
_everyBeforeSuspendProcess(): Promise<boolean> {
|
||||
const rep = this._replicatorInstance;
|
||||
rep?.disconnectFromServer();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
|
||||
override onBindFunction(core: LiveSyncCore, services: typeof core.services): void {
|
||||
services.replicator.handleGetNewReplicator(this._anyNewReplicator.bind(this));
|
||||
services.databaseEvents.handleOnDatabaseInitialisation(this._everyOnInitializeDatabase.bind(this));
|
||||
services.appLifecycle.handleOnInitialise(this._everyOnloadStart.bind(this));
|
||||
services.appLifecycle.handleOnSuspending(this._everyBeforeSuspendProcess.bind(this));
|
||||
services.appLifecycle.handleOnResumed(this._everyAfterResumeProcess.bind(this));
|
||||
services.setting.handleSuspendExtraSync(this._allSuspendExtraSync.bind(this));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
const initialSettings = { ...plugin.settings };
|
||||
|
||||
let settings = $state<P2PSyncSetting>(initialSettings);
|
||||
// const vaultName = plugin.$$getVaultName();
|
||||
// const vaultName = service.vault.getVaultName();
|
||||
// const dbKey = `${vaultName}-p2p-device-name`;
|
||||
|
||||
const initialDeviceName = cmdSync.getConfig("p2p_device_name") ?? plugin.$$getVaultName();
|
||||
const initialDeviceName = cmdSync.getConfig("p2p_device_name") ?? plugin.services.vault.getVaultName();
|
||||
let deviceName = $state<string>(initialDeviceName);
|
||||
|
||||
let eP2PEnabled = $state<boolean>(initialSettings.P2P_Enabled);
|
||||
|
||||
@@ -95,7 +95,7 @@ And you can also drop the local database to rebuild from the remote device.`,
|
||||
if (yn === DROP) {
|
||||
await this.plugin.rebuilder.scheduleFetch();
|
||||
} else {
|
||||
await this.plugin.$$scheduleAppReload();
|
||||
this.plugin.services.appLifecycle.scheduleRestart();
|
||||
}
|
||||
} else {
|
||||
Logger(`Cancelled\nRemote config for ${peer.name} is not applied`, LOG_LEVEL_NOTICE);
|
||||
|
||||
Reference in New Issue
Block a user