mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2025-12-15 18:55:57 +00:00
Fixed:
- Resolving conflicted revision has become more robust. - LiveSync now try to keep local changes when fetching from the rebuilt remote database. - Now, all files will be restored after performing `fetch` immediately.
This commit is contained in:
@@ -99,6 +99,7 @@ export class SetupLiveSync extends LiveSyncCommands {
|
|||||||
newSettingW.encryptedCouchDBConnection = "";
|
newSettingW.encryptedCouchDBConnection = "";
|
||||||
const setupJustImport = "Just import setting";
|
const setupJustImport = "Just import setting";
|
||||||
const setupAsNew = "Set it up as secondary or subsequent device";
|
const setupAsNew = "Set it up as secondary or subsequent device";
|
||||||
|
const setupAsMerge = "Secondary device but try keeping local changes";
|
||||||
const setupAgain = "Reconfigure and reconstitute the data";
|
const setupAgain = "Reconfigure and reconstitute the data";
|
||||||
const setupManually = "Leave everything to me";
|
const setupManually = "Leave everything to me";
|
||||||
newSettingW.syncInternalFiles = false;
|
newSettingW.syncInternalFiles = false;
|
||||||
@@ -108,7 +109,7 @@ export class SetupLiveSync extends LiveSyncCommands {
|
|||||||
newSettingW.useIndexedDBAdapter = true;
|
newSettingW.useIndexedDBAdapter = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const setupType = await askSelectString(this.app, "How would you like to set it up?", [setupAsNew, setupAgain, setupJustImport, setupManually]);
|
const setupType = await askSelectString(this.app, "How would you like to set it up?", [setupAsNew, setupAgain, setupAsMerge, setupJustImport, setupManually]);
|
||||||
if (setupType == setupJustImport) {
|
if (setupType == setupJustImport) {
|
||||||
this.plugin.settings = newSettingW;
|
this.plugin.settings = newSettingW;
|
||||||
this.plugin.usedPassphrase = "";
|
this.plugin.usedPassphrase = "";
|
||||||
@@ -117,6 +118,10 @@ export class SetupLiveSync extends LiveSyncCommands {
|
|||||||
this.plugin.settings = newSettingW;
|
this.plugin.settings = newSettingW;
|
||||||
this.plugin.usedPassphrase = "";
|
this.plugin.usedPassphrase = "";
|
||||||
await this.fetchLocal();
|
await this.fetchLocal();
|
||||||
|
} else if (setupType == setupAsMerge) {
|
||||||
|
this.plugin.settings = newSettingW;
|
||||||
|
this.plugin.usedPassphrase = "";
|
||||||
|
await this.fetchLocalWithKeepLocal();
|
||||||
} else if (setupType == setupAgain) {
|
} else if (setupType == setupAgain) {
|
||||||
const confirm = "I know this operation will rebuild all my databases with files on this device, and files that are on the remote database and I didn't synchronize to any other devices will be lost and want to proceed indeed.";
|
const confirm = "I know this operation will rebuild all my databases with files on this device, and files that are on the remote database and I didn't synchronize to any other devices will be lost and want to proceed indeed.";
|
||||||
if (await askSelectString(this.app, "Do you really want to do this?", ["Cancel", confirm]) != confirm) {
|
if (await askSelectString(this.app, "Do you really want to do this?", ["Cancel", confirm]) != confirm) {
|
||||||
@@ -302,13 +307,11 @@ Of course, we are able to disable these features.`
|
|||||||
Logger(`Database and storage reflection has been resumed!`, LOG_LEVEL_NOTICE);
|
Logger(`Database and storage reflection has been resumed!`, LOG_LEVEL_NOTICE);
|
||||||
this.plugin.settings.suspendParseReplicationResult = false;
|
this.plugin.settings.suspendParseReplicationResult = false;
|
||||||
this.plugin.settings.suspendFileWatching = false;
|
this.plugin.settings.suspendFileWatching = false;
|
||||||
await this.plugin.saveSettings();
|
|
||||||
if (this.plugin.settings.readChunksOnline) {
|
|
||||||
await this.plugin.syncAllFiles(true);
|
await this.plugin.syncAllFiles(true);
|
||||||
await this.plugin.loadQueuedFiles();
|
await this.plugin.loadQueuedFiles();
|
||||||
// Start processing
|
|
||||||
this.plugin.procQueuedFiles();
|
this.plugin.procQueuedFiles();
|
||||||
}
|
await this.plugin.saveSettings();
|
||||||
|
|
||||||
}
|
}
|
||||||
async askUseNewAdapter() {
|
async askUseNewAdapter() {
|
||||||
if (!this.plugin.settings.useIndexedDBAdapter) {
|
if (!this.plugin.settings.useIndexedDBAdapter) {
|
||||||
@@ -353,6 +356,25 @@ Of course, we are able to disable these features.`
|
|||||||
await this.resumeReflectingDatabase();
|
await this.resumeReflectingDatabase();
|
||||||
await this.askHiddenFileConfiguration({ enableFetch: true });
|
await this.askHiddenFileConfiguration({ enableFetch: true });
|
||||||
}
|
}
|
||||||
|
async fetchLocalWithKeepLocal() {
|
||||||
|
this.suspendExtraSync();
|
||||||
|
this.askUseNewAdapter();
|
||||||
|
await this.suspendReflectingDatabase();
|
||||||
|
await this.plugin.realizeSettingSyncMode();
|
||||||
|
await this.plugin.resetLocalDatabase();
|
||||||
|
await delay(1000);
|
||||||
|
await this.plugin.initializeDatabase(true);
|
||||||
|
await this.plugin.markRemoteResolved();
|
||||||
|
await this.plugin.openDatabase();
|
||||||
|
this.plugin.isReady = true;
|
||||||
|
await delay(500);
|
||||||
|
await this.plugin.replicateAllFromServer(true);
|
||||||
|
await delay(1000);
|
||||||
|
await this.plugin.replicateAllFromServer(true);
|
||||||
|
await this.fetchRemoteChunks();
|
||||||
|
await this.resumeReflectingDatabase();
|
||||||
|
await this.askHiddenFileConfiguration({ enableFetch: true });
|
||||||
|
}
|
||||||
async rebuildRemote() {
|
async rebuildRemote() {
|
||||||
this.suspendExtraSync();
|
this.suspendExtraSync();
|
||||||
await this.plugin.realizeSettingSyncMode();
|
await this.plugin.realizeSettingSyncMode();
|
||||||
|
|||||||
2
src/lib
2
src/lib
Submodule src/lib updated: 8872807f47...70eb916288
50
src/main.ts
50
src/main.ts
@@ -1167,17 +1167,25 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
|||||||
if (docEntry._deleted || docEntry.deleted) {
|
if (docEntry._deleted || docEntry.deleted) {
|
||||||
// This occurs not only when files are deleted, but also when conflicts are resolved.
|
// This occurs not only when files are deleted, but also when conflicts are resolved.
|
||||||
// We have to check no other revisions are left.
|
// We have to check no other revisions are left.
|
||||||
const lastDocs = await this.localDatabase.getDBEntry(path);
|
const existDoc = await this.localDatabase.getDBEntry(path, { conflicts: true });
|
||||||
if (path != file.path) {
|
if (path != file.path) {
|
||||||
Logger(`delete skipped: ${file.path} :Not exactly matched`, LOG_LEVEL_VERBOSE);
|
Logger(`delete skipped: ${file.path} :Not exactly matched`, LOG_LEVEL_VERBOSE);
|
||||||
}
|
}
|
||||||
if (lastDocs === false) {
|
if (existDoc === false) {
|
||||||
await this.deleteVaultItem(file);
|
await this.deleteVaultItem(file);
|
||||||
} else {
|
} else {
|
||||||
// it perhaps delete some revisions.
|
if (existDoc._conflicts) {
|
||||||
// may be we have to reload this
|
if (this.settings.writeDocumentsIfConflicted) {
|
||||||
|
Logger(`Delete: ${file.path}: Conflicted revision has been deleted, but there were more conflicts. `, LOG_LEVEL_INFO);
|
||||||
await this.pullFile(path, null, true);
|
await this.pullFile(path, null, true);
|
||||||
Logger(`delete skipped:${file.path}`, LOG_LEVEL_VERBOSE);
|
} else {
|
||||||
|
Logger(`Delete: ${file.path}: Conflicted revision has been deleted, but there were more conflicts...`);
|
||||||
|
this.queueConflictedOnlyActiveFile(file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger(`Delete: ${file.path}: Conflict revision has been deleted and resolved`);
|
||||||
|
await this.pullFile(path, null, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1274,6 +1282,19 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
|||||||
this.dbChangeProcRunning = false;
|
this.dbChangeProcRunning = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
queueConflictedOnlyActiveFile(file: TFile) {
|
||||||
|
if (!this.settings.checkConflictOnlyOnOpen) {
|
||||||
|
this.queueConflictedCheck(file);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
const af = this.app.workspace.getActiveFile();
|
||||||
|
if (af && af.path == file.path) {
|
||||||
|
this.queueConflictedCheck(file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
async handleDBChangedAsync(change: EntryBody) {
|
async handleDBChangedAsync(change: EntryBody) {
|
||||||
|
|
||||||
const targetFile = getAbstractFileByPath(this.getPathWithoutPrefix(change));
|
const targetFile = getAbstractFileByPath(this.getPathWithoutPrefix(change));
|
||||||
@@ -1286,29 +1307,16 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
|||||||
} else if (targetFile instanceof TFile) {
|
} else if (targetFile instanceof TFile) {
|
||||||
const doc = change;
|
const doc = change;
|
||||||
const file = targetFile;
|
const file = targetFile;
|
||||||
const queueConflictCheck = () => {
|
|
||||||
if (!this.settings.checkConflictOnlyOnOpen) {
|
|
||||||
this.queueConflictedCheck(file);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
const af = app.workspace.getActiveFile();
|
|
||||||
if (af && af.path == file.path) {
|
|
||||||
this.queueConflictedCheck(file);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.settings.writeDocumentsIfConflicted) {
|
if (this.settings.writeDocumentsIfConflicted) {
|
||||||
await this.doc2storage(doc, file);
|
await this.doc2storage(doc, file);
|
||||||
queueConflictCheck();
|
this.queueConflictedOnlyActiveFile(file);
|
||||||
} else {
|
} else {
|
||||||
const d = await this.localDatabase.getDBEntryMeta(this.getPath(change), { conflicts: true }, true);
|
const d = await this.localDatabase.getDBEntryMeta(this.getPath(change), { conflicts: true }, true);
|
||||||
if (d && !d._conflicts) {
|
if (d && !d._conflicts) {
|
||||||
await this.doc2storage(doc, file);
|
await this.doc2storage(doc, file);
|
||||||
} else {
|
} else {
|
||||||
if (!queueConflictCheck()) {
|
if (!this.queueConflictedOnlyActiveFile(file)) {
|
||||||
Logger(`${this.getPath(change)} is conflicted, write to the storage has been pended.`, LOG_LEVEL_NOTICE);
|
Logger(`${this.getPath(change)} is conflicted, write to the storage has been postponed.`, LOG_LEVEL_NOTICE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -477,7 +477,7 @@ export const requestToCouchDB = async (baseUri: string, username: string, passwo
|
|||||||
|
|
||||||
export async function performRebuildDB(plugin: ObsidianLiveSyncPlugin, method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice") {
|
export async function performRebuildDB(plugin: ObsidianLiveSyncPlugin, method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice") {
|
||||||
if (method == "localOnly") {
|
if (method == "localOnly") {
|
||||||
await plugin.addOnSetup.fetchLocal();
|
await plugin.addOnSetup.fetchLocalWithKeepLocal();
|
||||||
}
|
}
|
||||||
if (method == "remoteOnly") {
|
if (method == "remoteOnly") {
|
||||||
await plugin.addOnSetup.rebuildRemote();
|
await plugin.addOnSetup.rebuildRemote();
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
// "importsNotUsedAsValues": "error",
|
// "importsNotUsedAsValues": "error",
|
||||||
"importHelpers": false,
|
"importHelpers": false,
|
||||||
"alwaysStrict": true,
|
"alwaysStrict": true,
|
||||||
|
"allowImportingTsExtensions": true,
|
||||||
"lib": [
|
"lib": [
|
||||||
"es2018",
|
"es2018",
|
||||||
"DOM",
|
"DOM",
|
||||||
|
|||||||
Reference in New Issue
Block a user