mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-02-20 11:08:47 +00:00
Fixed
- Vault History can show the correct information of match-or-not for each file and database even if it is a binary file.
- `Sync settings via markdown` is now hidden during the setup wizard.
- Verify and Fix will ignore the hidden files if the hidden file sync is disabled.
New feature
- Now we can fetch the tweaks from the remote database while the setting dialogue and wizard are processing.
Improved
- More things are moved to the modules.
- Includes the Main codebase. Now `main.ts` is almost stub.
- EventHub is now more robust and typesafe.
This commit is contained in:
@@ -133,6 +133,10 @@ export class ModuleDatabaseFileAccess extends AbstractModule implements IObsidia
|
||||
//upsert should locked
|
||||
const msg = `STORAGE -> DB (${datatype}) `;
|
||||
const isNotChanged = await serialized("file-" + fullPath, async () => {
|
||||
if (force) {
|
||||
this._log(msg + "Force writing " + fullPath, LOG_LEVEL_VERBOSE);
|
||||
return false;
|
||||
}
|
||||
// Commented out temporarily: this checks that the file was made ourself.
|
||||
// if (this.core.storageAccess.recentlyTouched(file)) {
|
||||
// return true;
|
||||
|
||||
@@ -223,12 +223,9 @@ export class ModuleFileHandler extends AbstractModule implements ICoreModule {
|
||||
}
|
||||
const docData = readContent(docRead);
|
||||
|
||||
if (!existOnStorage) {
|
||||
// The file is not exist on the storage. We do not care about the differences.
|
||||
await this.storage.ensureDir(path);
|
||||
return await this.storage.writeFileAuto(path, docData, { ctime: docRead.ctime, mtime: docRead.mtime });
|
||||
}
|
||||
if (!force) {
|
||||
if (existOnStorage && !force) {
|
||||
// The file is exist on the storage. Let's check the difference between the file and the entry.
|
||||
// But, if force is true, then it should be updated.
|
||||
// Ok, we have to compare.
|
||||
let shouldApplied = false;
|
||||
// 1. if the time stamp is far different, then it should be updated.
|
||||
@@ -257,6 +254,8 @@ export class ModuleFileHandler extends AbstractModule implements ICoreModule {
|
||||
return true;
|
||||
}
|
||||
// Let's apply the changes.
|
||||
} else {
|
||||
this._log(`File ${docRead.path} ${existOnStorage ? "(new) " : ""} ${force ? " (forced)" : ""}`, LOG_LEVEL_VERBOSE);
|
||||
}
|
||||
await this.storage.ensureDir(path);
|
||||
const ret = await this.storage.writeFileAuto(path, docData, { ctime: docRead.ctime, mtime: docRead.mtime });
|
||||
|
||||
@@ -20,4 +20,8 @@ export class ModuleLocalDatabaseObsidian extends AbstractModule implements ICore
|
||||
return await this.localDatabase.initializeDatabase();
|
||||
}
|
||||
|
||||
$$isDatabaseReady(): boolean {
|
||||
return this.localDatabase != null && this.localDatabase.isReady;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,7 +40,7 @@ export class ModuleRebuilder extends AbstractModule implements ICoreModule, Rebu
|
||||
await this.core.$allSuspendExtraSync();
|
||||
this.core.settings.isConfigured = true;
|
||||
|
||||
await this.core.realizeSettingSyncMode();
|
||||
await this.core.$$realizeSettingSyncMode();
|
||||
await this.core.$$markRemoteLocked();
|
||||
await this.core.$$tryResetRemoteDatabase();
|
||||
await this.core.$$markRemoteLocked();
|
||||
@@ -60,7 +60,7 @@ export class ModuleRebuilder extends AbstractModule implements ICoreModule, Rebu
|
||||
await this.core.$allSuspendExtraSync();
|
||||
await this.askUseNewAdapter();
|
||||
this.core.settings.isConfigured = true;
|
||||
await this.core.realizeSettingSyncMode();
|
||||
await this.core.$$realizeSettingSyncMode();
|
||||
await this.resetLocalDatabase();
|
||||
await delay(1000);
|
||||
await this.core.$$initializeDatabase(true);
|
||||
@@ -164,11 +164,12 @@ export class ModuleRebuilder extends AbstractModule implements ICoreModule, Rebu
|
||||
await this.askUseNewAdapter();
|
||||
this.core.settings.isConfigured = true;
|
||||
await this.suspendReflectingDatabase();
|
||||
await this.core.realizeSettingSyncMode();
|
||||
await this.core.$$realizeSettingSyncMode();
|
||||
await this.resetLocalDatabase();
|
||||
await delay(1000);
|
||||
await this.core.$$openDatabase();
|
||||
this.core.isReady = true;
|
||||
// this.core.isReady = true;
|
||||
this.core.$$markIsReady();
|
||||
if (makeLocalChunkBeforeSync) {
|
||||
await this.core.fileHandler.createAllChunks(true);
|
||||
}
|
||||
@@ -201,8 +202,8 @@ export class ModuleRebuilder extends AbstractModule implements ICoreModule, Rebu
|
||||
async fetchRemoteChunks() {
|
||||
if (!this.core.settings.doNotSuspendOnFetching && this.core.settings.readChunksOnline && this.core.settings.remoteType == REMOTE_COUCHDB) {
|
||||
this._log(`Fetching chunks`, LOG_LEVEL_NOTICE);
|
||||
const replicator = this.core.getReplicator() as LiveSyncCouchDBReplicator;
|
||||
const remoteDB = await replicator.connectRemoteCouchDBWithSetting(this.settings, this.core.getIsMobile(), true);
|
||||
const replicator = this.core.$$getReplicator() as LiveSyncCouchDBReplicator;
|
||||
const remoteDB = await replicator.connectRemoteCouchDBWithSetting(this.settings, this.core.$$isMobile(), true);
|
||||
if (typeof remoteDB == "string") {
|
||||
this._log(remoteDB, LOG_LEVEL_NOTICE);
|
||||
} else {
|
||||
|
||||
@@ -14,12 +14,13 @@ import { getPath, isChunk, isValidPath, scheduleTask } from "../../common/utils"
|
||||
import { sendValue } from "octagonal-wheels/messagepassing/signal";
|
||||
import { isAnyNote } from "../../lib/src/common/utils";
|
||||
import { EVENT_FILE_SAVED, eventHub } from "../../common/events";
|
||||
import type { LiveSyncAbstractReplicator } from "../../lib/src/replication/LiveSyncAbstractReplicator";
|
||||
|
||||
export class ModuleReplicator extends AbstractModule implements ICoreModule {
|
||||
|
||||
$everyOnloadAfterLoadSettings(): Promise<boolean> {
|
||||
eventHub.onEvent(EVENT_FILE_SAVED, () => {
|
||||
if (this.settings.syncOnSave && !this.core.suspended) {
|
||||
if (this.settings.syncOnSave && !this.core.$$isSuspended()) {
|
||||
scheduleTask("perform-replicate-after-save", 250, () => this.core.$$waitForReplicationOnce());
|
||||
}
|
||||
})
|
||||
@@ -36,6 +37,11 @@ export class ModuleReplicator extends AbstractModule implements ICoreModule {
|
||||
await yieldMicrotask();
|
||||
return true;
|
||||
}
|
||||
|
||||
$$getReplicator(): LiveSyncAbstractReplicator {
|
||||
return this.core.replicator;
|
||||
}
|
||||
|
||||
$everyOnInitializeDatabase(db: LiveSyncLocalDB): Promise<boolean> {
|
||||
return this.setReplicator();
|
||||
}
|
||||
@@ -51,7 +57,7 @@ export class ModuleReplicator extends AbstractModule implements ICoreModule {
|
||||
}
|
||||
async $$replicate(showMessage: boolean = false): Promise<boolean | void> {
|
||||
//--?
|
||||
if (!this.core.isReady) return;
|
||||
if (!this.core.$$isReady()) return;
|
||||
if (isLockAcquired("cleanup")) {
|
||||
Logger("Database cleaning up is in process. replication has been cancelled", LOG_LEVEL_NOTICE);
|
||||
return;
|
||||
@@ -97,9 +103,9 @@ Even if you choose to clean up, you will see this option again if you exit Obsid
|
||||
await this.core.rebuilder.$performRebuildDB("localOnly");
|
||||
}
|
||||
if (ret == CHOICE_CLEAN) {
|
||||
const replicator = this.core.getReplicator();
|
||||
const replicator = this.core.$$getReplicator();
|
||||
if (!(replicator instanceof LiveSyncCouchDBReplicator)) return;
|
||||
const remoteDB = await replicator.connectRemoteCouchDBWithSetting(this.settings, this.core.getIsMobile(), true);
|
||||
const remoteDB = await replicator.connectRemoteCouchDBWithSetting(this.settings, this.core.$$isMobile(), true);
|
||||
if (typeof remoteDB == "string") {
|
||||
Logger(remoteDB, LOG_LEVEL_NOTICE);
|
||||
return false;
|
||||
@@ -112,7 +118,7 @@ Even if you choose to clean up, you will see this option again if you exit Obsid
|
||||
await balanceChunkPurgedDBs(this.localDatabase.localDatabase, remoteDB.db);
|
||||
await purgeUnreferencedChunks(this.localDatabase.localDatabase, false);
|
||||
this.localDatabase.hashCaches.clear();
|
||||
await this.core.getReplicator().markRemoteResolved(this.settings);
|
||||
await this.core.$$getReplicator().markRemoteResolved(this.settings);
|
||||
Logger("The local database has been cleaned up.", showMessage ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO)
|
||||
} else {
|
||||
Logger("Replication has been cancelled. Please try it again.", showMessage ? LOG_LEVEL_NOTICE : LOG_LEVEL_INFO)
|
||||
@@ -315,7 +321,7 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
}
|
||||
|
||||
async $$replicateAllToServer(showingNotice: boolean = false, sendChunksInBulkDisabled: boolean = false): Promise<boolean> {
|
||||
if (!this.core.isReady) return false;
|
||||
if (!this.core.$$isReady()) return false;
|
||||
if (!await this.core.$everyBeforeReplicate(showingNotice)) {
|
||||
Logger(`Replication has been cancelled by some module failure`, LOG_LEVEL_NOTICE);
|
||||
return false;
|
||||
@@ -334,7 +340,7 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
return !checkResult;
|
||||
}
|
||||
async $$replicateAllFromServer(showingNotice: boolean = false): Promise<boolean> {
|
||||
if (!this.core.isReady) return false;
|
||||
if (!this.core.$$isReady()) return false;
|
||||
const ret = await this.core.replicator.replicateAllFromServer(this.settings, showingNotice);
|
||||
if (ret) return true;
|
||||
const checkResult = await this.core.$anyAfterConnectCheckFailed();
|
||||
|
||||
@@ -13,10 +13,10 @@ export class ModuleTargetFilter extends AbstractModule implements ICoreModule {
|
||||
|
||||
}
|
||||
$everyOnload(): Promise<boolean> {
|
||||
eventHub.onEvent(EVENT_SETTING_SAVED, (evt: CustomEvent<ObsidianLiveSyncSettings>) => {
|
||||
eventHub.onEvent(EVENT_SETTING_SAVED, (evt: ObsidianLiveSyncSettings) => {
|
||||
this.reloadIgnoreFiles();
|
||||
});
|
||||
eventHub.onEvent(EVENT_REQUEST_RELOAD_SETTING_TAB, (evt: CustomEvent<ObsidianLiveSyncSettings>) => {
|
||||
eventHub.onEvent(EVENT_REQUEST_RELOAD_SETTING_TAB, () => {
|
||||
this.reloadIgnoreFiles();
|
||||
});
|
||||
return Promise.resolve(true);
|
||||
@@ -45,8 +45,13 @@ export class ModuleTargetFilter extends AbstractModule implements ICoreModule {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$$markFileListPossiblyChanged(): void {
|
||||
this.totalFileEventCount++;
|
||||
}
|
||||
totalFileEventCount = 0;
|
||||
get fileListPossiblyChanged() {
|
||||
if (isDirty("totalFileEventCount", this.core.totalFileEventCount)) {
|
||||
if (isDirty("totalFileEventCount", this.totalFileEventCount)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -88,7 +93,7 @@ export class ModuleTargetFilter extends AbstractModule implements ICoreModule {
|
||||
|
||||
const filepath = getPathFromUXFileInfo(file);
|
||||
const lc = filepath.toLowerCase();
|
||||
if (this.core.shouldCheckCaseInsensitive) {
|
||||
if (this.core.$$shouldCheckCaseInsensitive()) {
|
||||
if (lc in fileCount && fileCount[lc] > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user