mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-03-25 11:15:18 +00:00
### Fixed
- No longer conflicted files are handled in the boot-up process. No more unexpected overwriting.
- It ignores `Always overwrite with a newer file`, and always be prevented for the safety. Please pick it manually or open the file.
- Some log messages on conflict resolution has been corrected.
- Automatic merge notifications, displayed on the grounds of `same`, have been degraded to logs.
### Improved
- Now we can fetch the remote database with keeping local files completely intact.
- In new option, all files are stored into the local database before the fetching, and will be merged automatically or detected as conflicts.
- The dialogue presenting options when performing `Fetch` are now more informative.
### Refactored
- Some class methods have been fixed its arguments to be more consistent.
- Types have been defined for some conditional results.
173 lines
7.7 KiB
TypeScript
173 lines
7.7 KiB
TypeScript
import { LOG_LEVEL_NOTICE, LOG_LEVEL_VERBOSE } from "octagonal-wheels/common/logger";
|
|
import { normalizePath } from "../../deps.ts";
|
|
import {
|
|
FLAGMD_REDFLAG,
|
|
FLAGMD_REDFLAG2,
|
|
FLAGMD_REDFLAG2_HR,
|
|
FLAGMD_REDFLAG3,
|
|
FLAGMD_REDFLAG3_HR,
|
|
} from "../../lib/src/common/types.ts";
|
|
import { AbstractModule } from "../AbstractModule.ts";
|
|
import type { ICoreModule } from "../ModuleTypes.ts";
|
|
import { $msg } from "../../lib/src/common/i18n.ts";
|
|
|
|
export class ModuleRedFlag extends AbstractModule implements ICoreModule {
|
|
async isFlagFileExist(path: string) {
|
|
const redflag = await this.core.storageAccess.isExists(normalizePath(path));
|
|
if (redflag) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
async deleteFlagFile(path: string) {
|
|
try {
|
|
const isFlagged = await this.core.storageAccess.isExists(normalizePath(path));
|
|
if (isFlagged) {
|
|
await this.core.storageAccess.delete(path, true);
|
|
}
|
|
} catch (ex) {
|
|
this._log(`Could not delete ${path}`);
|
|
this._log(ex, LOG_LEVEL_VERBOSE);
|
|
}
|
|
}
|
|
|
|
isRedFlagRaised = async () => await this.isFlagFileExist(FLAGMD_REDFLAG);
|
|
isRedFlag2Raised = async () =>
|
|
(await this.isFlagFileExist(FLAGMD_REDFLAG2)) || (await this.isFlagFileExist(FLAGMD_REDFLAG2_HR));
|
|
isRedFlag3Raised = async () =>
|
|
(await this.isFlagFileExist(FLAGMD_REDFLAG3)) || (await this.isFlagFileExist(FLAGMD_REDFLAG3_HR));
|
|
|
|
async deleteRedFlag2() {
|
|
await this.deleteFlagFile(FLAGMD_REDFLAG2);
|
|
await this.deleteFlagFile(FLAGMD_REDFLAG2_HR);
|
|
}
|
|
|
|
async deleteRedFlag3() {
|
|
await this.deleteFlagFile(FLAGMD_REDFLAG3);
|
|
await this.deleteFlagFile(FLAGMD_REDFLAG3_HR);
|
|
}
|
|
async $everyOnLayoutReady(): Promise<boolean> {
|
|
try {
|
|
const isRedFlagRaised = await this.isRedFlagRaised();
|
|
const isRedFlag2Raised = await this.isRedFlag2Raised();
|
|
const isRedFlag3Raised = await this.isRedFlag3Raised();
|
|
|
|
if (isRedFlagRaised || isRedFlag2Raised || isRedFlag3Raised) {
|
|
if (isRedFlag2Raised) {
|
|
if (
|
|
(await this.core.confirm.askYesNoDialog(
|
|
"Rebuild everything has been scheduled! Are you sure to rebuild everything?",
|
|
{ defaultOption: "Yes", timeout: 0 }
|
|
)) !== "yes"
|
|
) {
|
|
await this.deleteRedFlag2();
|
|
await this.core.$$performRestart();
|
|
return false;
|
|
}
|
|
}
|
|
if (isRedFlag3Raised) {
|
|
if (
|
|
(await this.core.confirm.askYesNoDialog("Fetch again has been scheduled! Are you sure?", {
|
|
defaultOption: "Yes",
|
|
timeout: 0,
|
|
})) !== "yes"
|
|
) {
|
|
await this.deleteRedFlag3();
|
|
await this.core.$$performRestart();
|
|
return false;
|
|
}
|
|
}
|
|
this.settings.batchSave = false;
|
|
await this.core.$allSuspendAllSync();
|
|
await this.core.$allSuspendExtraSync();
|
|
this.settings.suspendFileWatching = true;
|
|
await this.saveSettings();
|
|
if (isRedFlag2Raised) {
|
|
this._log(
|
|
`${FLAGMD_REDFLAG2} or ${FLAGMD_REDFLAG2_HR} has been detected! Self-hosted LiveSync suspends all sync and rebuild everything.`,
|
|
LOG_LEVEL_NOTICE
|
|
);
|
|
await this.core.rebuilder.$rebuildEverything();
|
|
await this.deleteRedFlag2();
|
|
if (
|
|
(await this.core.confirm.askYesNoDialog(
|
|
"Do you want to resume file and database processing, and restart obsidian now?",
|
|
{ defaultOption: "Yes", timeout: 15 }
|
|
)) == "yes"
|
|
) {
|
|
this.settings.suspendFileWatching = false;
|
|
await this.saveSettings();
|
|
this.core.$$performRestart();
|
|
return false;
|
|
}
|
|
} else if (isRedFlag3Raised) {
|
|
this._log(
|
|
`${FLAGMD_REDFLAG3} or ${FLAGMD_REDFLAG3_HR} has been detected! Self-hosted LiveSync will discard the local database and fetch everything from the remote once again.`,
|
|
LOG_LEVEL_NOTICE
|
|
);
|
|
const method1 = $msg("RedFlag.Fetch.Method.FetchSafer");
|
|
const method2 = $msg("RedFlag.Fetch.Method.FetchSmoother");
|
|
const method3 = $msg("RedFlag.Fetch.Method.FetchTraditional");
|
|
|
|
const methods = [method1, method2, method3] as const;
|
|
const chunkMode = await this.core.confirm.askSelectStringDialogue(
|
|
$msg("RedFlag.Fetch.Method.Desc"),
|
|
methods,
|
|
{
|
|
defaultAction: method1,
|
|
timeout: 0,
|
|
title: $msg("RedFlag.Fetch.Method.Title"),
|
|
}
|
|
);
|
|
let makeLocalChunkBeforeSync = false;
|
|
let preventMakeLocalFilesBeforeSync = false;
|
|
if (chunkMode === method1) {
|
|
preventMakeLocalFilesBeforeSync = true;
|
|
} else if (chunkMode === method2) {
|
|
makeLocalChunkBeforeSync = true;
|
|
} else if (chunkMode === method3) {
|
|
// Do nothing.
|
|
} else {
|
|
this._log("Cancelled the fetch operation", LOG_LEVEL_NOTICE);
|
|
return false;
|
|
}
|
|
|
|
await this.core.rebuilder.$fetchLocal(makeLocalChunkBeforeSync, preventMakeLocalFilesBeforeSync);
|
|
|
|
await this.deleteRedFlag3();
|
|
if (this.settings.suspendFileWatching) {
|
|
if (
|
|
(await this.core.confirm.askYesNoDialog(
|
|
"Do you want to resume file and database processing, and restart obsidian now?",
|
|
{ defaultOption: "Yes", timeout: 15 }
|
|
)) == "yes"
|
|
) {
|
|
this.settings.suspendFileWatching = false;
|
|
await this.saveSettings();
|
|
this.core.$$performRestart();
|
|
return false;
|
|
}
|
|
} else {
|
|
this._log(
|
|
"Your content of files will be synchronised gradually. Please wait for the completion.",
|
|
LOG_LEVEL_NOTICE
|
|
);
|
|
}
|
|
} else {
|
|
// Case of FLAGMD_REDFLAG.
|
|
this.settings.writeLogToTheFile = true;
|
|
// await this.plugin.openDatabase();
|
|
const warningMessage =
|
|
"The red flag is raised! The whole initialize steps are skipped, and any file changes are not captured.";
|
|
this._log(warningMessage, LOG_LEVEL_NOTICE);
|
|
}
|
|
}
|
|
} catch (ex) {
|
|
this._log("Something went wrong on FlagFile Handling", LOG_LEVEL_NOTICE);
|
|
this._log(ex, LOG_LEVEL_VERBOSE);
|
|
}
|
|
return true;
|
|
}
|
|
}
|