You've already forked obsidian-livesync
mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2025-08-10 22:11:45 +02:00
- Fixed:
- Fixed a bug on `fetch chunks on demand` that could not fetch the chunks on demand. - Improved: - `fetch chunks on demand` works more smoothly. - Initialisation `Fetch` is now more efficient. - Tidied: - Removed some meaningless codes.
This commit is contained in:
@@ -178,9 +178,7 @@ export class ConfigSync extends LiveSyncCommands {
|
||||
get kvDB() {
|
||||
return this.plugin.kvDB;
|
||||
}
|
||||
ensureDirectoryEx(fullPath: string) {
|
||||
return this.plugin.ensureDirectoryEx(fullPath);
|
||||
}
|
||||
|
||||
pluginDialog: PluginDialogModal = null;
|
||||
periodicPluginSweepProcessor = new PeriodicProcessor(this.plugin, async () => await this.scanAllConfigFiles(false));
|
||||
|
||||
@@ -433,7 +431,7 @@ export class ConfigSync extends LiveSyncCommands {
|
||||
try {
|
||||
// console.dir(f);
|
||||
const path = `${baseDir}/${f.filename}`;
|
||||
await this.ensureDirectoryEx(path);
|
||||
await this.vaultAccess.ensureDirectory(path);
|
||||
if (!content) {
|
||||
const dt = decodeBinary(f.data);
|
||||
await this.vaultAccess.adapterWrite(path, dt);
|
||||
|
@@ -20,9 +20,6 @@ export class HiddenFileSync extends LiveSyncCommands {
|
||||
get kvDB() {
|
||||
return this.plugin.kvDB;
|
||||
}
|
||||
ensureDirectoryEx(fullPath: string) {
|
||||
return this.plugin.ensureDirectoryEx(fullPath);
|
||||
}
|
||||
getConflictedDoc(path: FilePathWithPrefix, rev: string) {
|
||||
return this.plugin.getConflictedDoc(path, rev);
|
||||
}
|
||||
@@ -202,7 +199,7 @@ export class HiddenFileSync extends LiveSyncCommands {
|
||||
const filename = stripAllPrefixes(path);
|
||||
const isExists = await this.plugin.vaultAccess.adapterExists(filename);
|
||||
if (!isExists) {
|
||||
await this.ensureDirectoryEx(filename);
|
||||
await this.vaultAccess.ensureDirectory(filename);
|
||||
}
|
||||
await this.plugin.vaultAccess.adapterWrite(filename, result);
|
||||
const stat = await this.vaultAccess.adapterStat(filename);
|
||||
@@ -498,7 +495,7 @@ export class HiddenFileSync extends LiveSyncCommands {
|
||||
type: "newnote",
|
||||
};
|
||||
}
|
||||
const ret = await this.localDatabase.putDBEntry(saveData, true);
|
||||
const ret = await this.localDatabase.putDBEntry(saveData);
|
||||
Logger(`STORAGE --> DB:${file.path}: (hidden) Done`);
|
||||
return ret;
|
||||
} catch (ex) {
|
||||
@@ -599,7 +596,7 @@ export class HiddenFileSync extends LiveSyncCommands {
|
||||
return true;
|
||||
}
|
||||
if (!isExists) {
|
||||
await this.ensureDirectoryEx(filename);
|
||||
await this.vaultAccess.ensureDirectory(filename);
|
||||
await this.plugin.vaultAccess.adapterWrite(filename, decodeBinary(fileOnDB.data), { mtime: fileOnDB.mtime, ctime: fileOnDB.ctime });
|
||||
try {
|
||||
//@ts-ignore internalAPI
|
||||
@@ -668,7 +665,7 @@ export class HiddenFileSync extends LiveSyncCommands {
|
||||
if (!keep && result) {
|
||||
const isExists = await this.plugin.vaultAccess.adapterExists(filename);
|
||||
if (!isExists) {
|
||||
await this.ensureDirectoryEx(filename);
|
||||
await this.vaultAccess.ensureDirectory(filename);
|
||||
}
|
||||
await this.plugin.vaultAccess.adapterWrite(filename, result);
|
||||
const stat = await this.plugin.vaultAccess.adapterStat(filename);
|
||||
|
@@ -359,7 +359,7 @@ Of course, we are able to disable these features.`
|
||||
Logger(`Fetching chunks done`, LOG_LEVEL_NOTICE);
|
||||
}
|
||||
}
|
||||
async fetchLocal() {
|
||||
async fetchLocal(makeLocalChunkBeforeSync?: boolean) {
|
||||
this.suspendExtraSync();
|
||||
await this.askUseNewAdapter();
|
||||
this.plugin.settings.isConfigured = true;
|
||||
@@ -368,8 +368,11 @@ Of course, we are able to disable these features.`
|
||||
await this.resetLocalDatabase();
|
||||
await delay(1000);
|
||||
await this.plugin.openDatabase();
|
||||
await this.plugin.markRemoteResolved();
|
||||
this.plugin.isReady = true;
|
||||
if (makeLocalChunkBeforeSync) {
|
||||
await this.plugin.initializeDatabase(true);
|
||||
}
|
||||
await this.plugin.markRemoteResolved();
|
||||
await delay(500);
|
||||
await this.plugin.replicateAllFromServer(true);
|
||||
await delay(1000);
|
||||
@@ -379,24 +382,7 @@ Of course, we are able to disable these features.`
|
||||
await this.askHiddenFileConfiguration({ enableFetch: true });
|
||||
}
|
||||
async fetchLocalWithKeepLocal() {
|
||||
this.suspendExtraSync();
|
||||
await this.askUseNewAdapter();
|
||||
this.plugin.settings.isConfigured = true;
|
||||
await this.suspendReflectingDatabase();
|
||||
await this.plugin.realizeSettingSyncMode();
|
||||
await this.resetLocalDatabase();
|
||||
await delay(1000);
|
||||
await this.plugin.initializeDatabase(true);
|
||||
await this.plugin.openDatabase();
|
||||
await this.plugin.markRemoteResolved();
|
||||
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 });
|
||||
return await this.fetchLocal(true);
|
||||
}
|
||||
async rebuildRemote() {
|
||||
this.suspendExtraSync();
|
||||
|
@@ -663,7 +663,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
||||
.setWarning()
|
||||
.setDisabled(false)
|
||||
.onClick(async () => {
|
||||
await rebuildDB("localOnly");
|
||||
await rebuildDB("localOnlyWithChunks");
|
||||
})
|
||||
)
|
||||
.addButton((button) =>
|
||||
@@ -732,7 +732,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
||||
}
|
||||
};
|
||||
|
||||
const rebuildDB = async (method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice") => {
|
||||
const rebuildDB = async (method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice" | "localOnlyWithChunks") => {
|
||||
if (encrypt && passphrase == "") {
|
||||
Logger("If you enable encryption, you have to set the passphrase", LOG_LEVEL_NOTICE);
|
||||
return;
|
||||
@@ -1053,9 +1053,9 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
||||
if (!this.plugin.settings.isConfigured) {
|
||||
this.plugin.settings.isConfigured = true;
|
||||
await this.plugin.saveSettings();
|
||||
await rebuildDB("localOnly");
|
||||
await rebuildDB("localOnlyWithChunks");
|
||||
Logger("All done! Please set up subsequent devices with 'Copy current settings as a new setup URI' and 'Use the copied setup URI'.", LOG_LEVEL_NOTICE);
|
||||
await this.plugin.addOnSetup.command_openSetupURI();
|
||||
await this.plugin.addOnSetup.command_copySetupURI();
|
||||
} else {
|
||||
this.askReload();
|
||||
}
|
||||
@@ -1922,7 +1922,7 @@ ${stringifyYaml(pluginConfig)}`;
|
||||
toggle.setValue(!this.plugin.settings.useIndexedDBAdapter).onChange(async (value) => {
|
||||
this.plugin.settings.useIndexedDBAdapter = !value;
|
||||
await this.plugin.saveSettings();
|
||||
await rebuildDB("localOnly");
|
||||
await rebuildDB("localOnlyWithChunks");
|
||||
})
|
||||
);
|
||||
|
||||
@@ -2119,6 +2119,19 @@ ${stringifyYaml(pluginConfig)}`;
|
||||
.setButtonText("Fetch")
|
||||
.setWarning()
|
||||
.setDisabled(false)
|
||||
.onClick(async () => {
|
||||
await rebuildDB("localOnlyWithChunks");
|
||||
})
|
||||
)
|
||||
|
||||
new Setting(containerMaintenanceEl)
|
||||
.setName("Fetch rebuilt DB with all remote chunks")
|
||||
.setDesc("Restore or reconstruct local database from remote database but use remote chunk .")
|
||||
.addButton((button) =>
|
||||
button
|
||||
.setButtonText("Fetch all")
|
||||
.setWarning()
|
||||
.setDisabled(false)
|
||||
.onClick(async () => {
|
||||
await rebuildDB("localOnly");
|
||||
})
|
||||
|
@@ -1,5 +1,6 @@
|
||||
import { type App, TFile, type DataWriteOptions, TFolder, TAbstractFile } from "./deps";
|
||||
import { serialized } from "./lib/src/lock";
|
||||
import { Logger } from "./lib/src/logger";
|
||||
import type { FilePath } from "./lib/src/types";
|
||||
import { createBinaryBlob, isDocContentSame } from "./lib/src/utils";
|
||||
import type { InternalFileInfo } from "./types";
|
||||
@@ -107,6 +108,15 @@ export class SerializedFileAccess {
|
||||
return await processWriteFile(path, () => this.app.vault.createBinary(path, toArrayBuffer(data), options));
|
||||
}
|
||||
}
|
||||
|
||||
trigger(name: string, ...data: any[]) {
|
||||
return this.app.vault.trigger(name, ...data);
|
||||
}
|
||||
|
||||
async adapterAppend(normalizedPath: string, data: string, options?: DataWriteOptions) {
|
||||
return await this.app.vault.adapter.append(normalizedPath, data, options)
|
||||
}
|
||||
|
||||
async delete(file: TFile | TFolder, force = false) {
|
||||
return await processWriteFile(file, () => this.app.vault.delete(file, force));
|
||||
}
|
||||
@@ -127,6 +137,31 @@ export class SerializedFileAccess {
|
||||
// }
|
||||
}
|
||||
|
||||
getFiles() {
|
||||
return this.app.vault.getFiles();
|
||||
}
|
||||
|
||||
async ensureDirectory(fullPath: string) {
|
||||
const pathElements = fullPath.split("/");
|
||||
pathElements.pop();
|
||||
let c = "";
|
||||
for (const v of pathElements) {
|
||||
c += v;
|
||||
try {
|
||||
await this.app.vault.adapter.mkdir(c);
|
||||
} catch (ex) {
|
||||
// basically skip exceptions.
|
||||
if (ex.message && ex.message == "Folder already exists.") {
|
||||
// especially this message is.
|
||||
} else {
|
||||
Logger("Folder Create Error");
|
||||
Logger(ex);
|
||||
}
|
||||
}
|
||||
c += "/";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
touchedFiles: string[] = [];
|
||||
|
||||
|
2
src/lib
2
src/lib
Submodule src/lib updated: 1a3488339e...8a8177c1f0
168
src/main.ts
168
src/main.ts
@@ -84,7 +84,6 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
||||
this._suspended = value;
|
||||
}
|
||||
deviceAndVaultName = "";
|
||||
isMobile = false;
|
||||
isReady = false;
|
||||
packageVersion = "";
|
||||
manifestVersion = "";
|
||||
@@ -248,6 +247,22 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
||||
}
|
||||
}
|
||||
|
||||
get isMobile() {
|
||||
// @ts-ignore: internal API
|
||||
return this.app.isMobile
|
||||
}
|
||||
|
||||
get vaultName() {
|
||||
return this.app.vault.getName()
|
||||
}
|
||||
getActiveFile() {
|
||||
return this.app.workspace.getActiveFile();
|
||||
}
|
||||
|
||||
get appId() {
|
||||
return `${("appId" in this.app ? this.app.appId : "")}`;
|
||||
}
|
||||
|
||||
id2path(id: DocumentID, entry?: EntryHasPath, stripPrefix?: boolean): FilePathWithPrefix {
|
||||
const tempId = id2path(id, entry);
|
||||
if (stripPrefix && isInternalMetadata(tempId)) {
|
||||
@@ -309,13 +324,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
||||
// end interfaces
|
||||
|
||||
getVaultName(): string {
|
||||
return this.app.vault.getName() + (this.settings?.additionalSuffixOfDatabaseName ? ("-" + this.settings.additionalSuffixOfDatabaseName) : "");
|
||||
}
|
||||
|
||||
setInterval(handler: () => any, timeout?: number): number {
|
||||
const timer = window.setInterval(handler, timeout);
|
||||
this.registerInterval(timer);
|
||||
return timer;
|
||||
return this.vaultName + (this.settings?.additionalSuffixOfDatabaseName ? ("-" + this.settings.additionalSuffixOfDatabaseName) : "");
|
||||
}
|
||||
|
||||
isFlagFileExist(path: string) {
|
||||
@@ -361,7 +370,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
||||
}
|
||||
notes.sort((a, b) => b.mtime - a.mtime);
|
||||
const notesList = notes.map(e => e.dispPath);
|
||||
const target = await askSelectString(this.app, "File to view History", notesList);
|
||||
const target = await this.askSelectString("File to view History", notesList);
|
||||
if (target) {
|
||||
const targetId = notes.find(e => e.dispPath == target);
|
||||
this.showHistory(targetId.path, targetId.id);
|
||||
@@ -379,7 +388,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin
|
||||
Logger("There are no conflicted documents", LOG_LEVEL_NOTICE);
|
||||
return false;
|
||||
}
|
||||
const target = await askSelectString(this.app, "File to resolve conflict", notesList);
|
||||
const target = await this.askSelectString("File to resolve conflict", notesList);
|
||||
if (target) {
|
||||
const targetItem = notes.find(e => e.dispPath == target);
|
||||
this.resolveConflicted(targetItem.path);
|
||||
@@ -458,10 +467,7 @@ Click anywhere to stop counting down.
|
||||
const ret = await confirmWithMessage(this, "Welcome to Self-hosted LiveSync", message, [USE_SETUP, OPEN_SETUP, DISMISS], DISMISS, 40);
|
||||
if (ret === OPEN_SETUP) {
|
||||
try {
|
||||
//@ts-ignore: undocumented api
|
||||
this.app.setting.open();
|
||||
//@ts-ignore: undocumented api
|
||||
this.app.setting.openTabById("obsidian-livesync");
|
||||
this.openSetting();
|
||||
} catch (ex) {
|
||||
Logger("Something went wrong on opening setting dialog, please open it manually", LOG_LEVEL_NOTICE);
|
||||
}
|
||||
@@ -482,22 +488,20 @@ Click anywhere to stop counting down.
|
||||
Logger(`${FLAGMD_REDFLAG2} or ${FLAGMD_REDFLAG2_HR} has been detected! Self-hosted LiveSync suspends all sync and rebuild everything.`, LOG_LEVEL_NOTICE);
|
||||
await this.addOnSetup.rebuildEverything();
|
||||
await this.deleteRedFlag2();
|
||||
if (await askYesNo(this.app, "Do you want to disable Suspend file watching and restart obsidian now?") == "yes") {
|
||||
if (await this.askYesNo("Do you want to disable Suspend file watching and restart obsidian now?") == "yes") {
|
||||
this.settings.suspendFileWatching = false;
|
||||
await this.saveSettings();
|
||||
// @ts-ignore
|
||||
this.app.commands.executeCommandById("app:reload")
|
||||
this.performAppReload();
|
||||
}
|
||||
} else if (this.isRedFlag3Raised()) {
|
||||
Logger(`${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);
|
||||
await this.addOnSetup.fetchLocal();
|
||||
await this.deleteRedFlag3();
|
||||
if (this.settings.suspendFileWatching) {
|
||||
if (await askYesNo(this.app, "Do you want to disable Suspend file watching and restart obsidian now?") == "yes") {
|
||||
if (await this.askYesNo("Do you want to disable Suspend file watching and restart obsidian now?") == "yes") {
|
||||
this.settings.suspendFileWatching = false;
|
||||
await this.saveSettings();
|
||||
// @ts-ignore
|
||||
this.app.commands.executeCommandById("app:reload")
|
||||
this.performAppReload();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -546,8 +550,7 @@ Click anywhere to stop counting down.
|
||||
this.askInPopup(`conflicting-detected-on-safety`, `Some files have been left conflicted! Press {HERE} to resolve them, or you can do it later by "Pick a file to resolve conflict`, (anchor) => {
|
||||
anchor.text = "HERE";
|
||||
anchor.addEventListener("click", () => {
|
||||
// @ts-ignore
|
||||
this.app.commands.executeCommandById("obsidian-livesync:livesync-all-conflictcheck");
|
||||
this.performCommand("obsidian-livesync:livesync-all-conflictcheck");
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -629,7 +632,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
// this.localDatabase.getDBEntry(getPathFromTFile(file), {}, true, false);
|
||||
// },
|
||||
callback: () => {
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
const file = this.getActiveFile();
|
||||
if (!file) return;
|
||||
this.localDatabase.getDBEntry(getPathFromTFile(file), {}, true, false);
|
||||
},
|
||||
@@ -678,7 +681,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
id: "livesync-history",
|
||||
name: "Show history",
|
||||
callback: () => {
|
||||
const file = this.app.workspace.getActiveFile();
|
||||
const file = this.getActiveFile();
|
||||
if (file) this.showHistory(file, null);
|
||||
}
|
||||
});
|
||||
@@ -791,8 +794,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
if (this.app.isMobile) {
|
||||
this.isMobile = true;
|
||||
if (this.isMobile) {
|
||||
this.settings.disableRequestURI = true;
|
||||
}
|
||||
if (last_version && Number(last_version) < VER) {
|
||||
@@ -869,8 +871,6 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
}
|
||||
const vaultName = this.getVaultName();
|
||||
Logger("Waiting for ready...");
|
||||
//@ts-ignore
|
||||
this.isMobile = this.app.isMobile;
|
||||
this.localDatabase = new LiveSyncLocalDB(vaultName, this);
|
||||
initializeStores(vaultName);
|
||||
return await this.localDatabase.initializeDatabase();
|
||||
@@ -933,7 +933,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
if (JSON.stringify(settings) !== JSON.stringify(DEFAULT_SETTINGS)) {
|
||||
settings.isConfigured = true;
|
||||
} else {
|
||||
settings.additionalSuffixOfDatabaseName = `${("appId" in this.app ? this.app.appId : "")}`
|
||||
settings.additionalSuffixOfDatabaseName = this.appId;
|
||||
settings.isConfigured = false;
|
||||
}
|
||||
}
|
||||
@@ -1057,7 +1057,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
}
|
||||
|
||||
async parseSettingFromMarkdown(filename: string, data?: string) {
|
||||
const file = this.app.vault.getAbstractFileByPath(filename);
|
||||
const file = this.vaultAccess.getAbstractFileByPath(filename);
|
||||
if (!(file instanceof TFile)) return {
|
||||
preamble: "",
|
||||
body: "",
|
||||
@@ -1066,7 +1066,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
if (data) {
|
||||
return this.extractSettingFromWholeText(data);
|
||||
}
|
||||
const parseData = data ?? await this.app.vault.read(file);
|
||||
const parseData = data ?? await this.vaultAccess.vaultRead(file);
|
||||
return this.extractSettingFromWholeText(parseData);
|
||||
}
|
||||
|
||||
@@ -1115,7 +1115,7 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
const APPLY_AND_REBUILD = "Apply settings and restart obsidian with red_flag_rebuild.md";
|
||||
const APPLY_AND_FETCH = "Apply settings and restart obsidian with red_flag_fetch.md";
|
||||
const CANCEL = "Cancel";
|
||||
const result = await askSelectString(this.app, "Ready for apply the setting.", [APPLY_AND_RESTART, APPLY_ONLY, APPLY_AND_FETCH, APPLY_AND_REBUILD, CANCEL]);
|
||||
const result = await this.askSelectString("Ready for apply the setting.", [APPLY_AND_RESTART, APPLY_ONLY, APPLY_AND_FETCH, APPLY_AND_REBUILD, CANCEL]);
|
||||
if (result == APPLY_ONLY || result == APPLY_AND_RESTART || result == APPLY_AND_REBUILD || result == APPLY_AND_FETCH) {
|
||||
this.settings = settingToApply;
|
||||
await this.saveSettingData();
|
||||
@@ -1124,13 +1124,12 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
return;
|
||||
}
|
||||
if (result == APPLY_AND_REBUILD) {
|
||||
await this.app.vault.create(FLAGMD_REDFLAG2_HR, "");
|
||||
await this.vaultAccess.vaultCreate(FLAGMD_REDFLAG2_HR, "");
|
||||
}
|
||||
if (result == APPLY_AND_FETCH) {
|
||||
await this.app.vault.create(FLAGMD_REDFLAG3_HR, "");
|
||||
await this.vaultAccess.vaultCreate(FLAGMD_REDFLAG3_HR, "");
|
||||
}
|
||||
// @ts-ignore
|
||||
this.app.commands.executeCommandById("app:reload");
|
||||
this.performAppReload();
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -1150,11 +1149,11 @@ Note: We can always able to read V1 format. It will be progressively converted.
|
||||
|
||||
async saveSettingToMarkdown(filename: string) {
|
||||
const saveData = this.generateSettingForMarkdown();
|
||||
let file = this.app.vault.getAbstractFileByPath(filename);
|
||||
let file = this.vaultAccess.getAbstractFileByPath(filename);
|
||||
|
||||
|
||||
if (!file) {
|
||||
await this.ensureDirectoryEx(filename);
|
||||
await this.vaultAccess.ensureDirectory(filename);
|
||||
const initialContent = `This file contains Self-hosted LiveSync settings as YAML.
|
||||
Except for the \`livesync-setting\` code block, we can add a note for free.
|
||||
|
||||
@@ -1167,21 +1166,21 @@ We can perform a command in this file.
|
||||
|
||||
|
||||
`
|
||||
file = await this.app.vault.create(filename, initialContent + SETTING_HEADER + "\n" + SETTING_FOOTER);
|
||||
file = await this.vaultAccess.vaultCreate(filename, initialContent + SETTING_HEADER + "\n" + SETTING_FOOTER);
|
||||
}
|
||||
if (!(file instanceof TFile)) {
|
||||
Logger(`Markdown Setting: ${filename} already exists as a folder`, LOG_LEVEL_NOTICE);
|
||||
return;
|
||||
}
|
||||
|
||||
const data = await this.app.vault.read(file);
|
||||
const data = await this.vaultAccess.vaultRead(file);
|
||||
const { preamble, body, postscript } = this.extractSettingFromWholeText(data);
|
||||
const newBody = stringifyYaml(saveData);
|
||||
|
||||
if (newBody == body) {
|
||||
Logger("Markdown setting: Nothing had been changed", LOG_LEVEL_VERBOSE);
|
||||
} else {
|
||||
await this.app.vault.modify(file, preamble + SETTING_HEADER + newBody + SETTING_FOOTER + postscript);
|
||||
await this.vaultAccess.vaultModify(file, preamble + SETTING_HEADER + newBody + SETTING_FOOTER + postscript);
|
||||
Logger(`Markdown setting: ${filename} has been updated!`, LOG_LEVEL_VERBOSE);
|
||||
}
|
||||
}
|
||||
@@ -1224,8 +1223,7 @@ We can perform a command in this file.
|
||||
const _this = this;
|
||||
//@ts-ignore
|
||||
window.CodeMirrorAdapter.commands.save = () => {
|
||||
//@ts-ignore
|
||||
_this.app.commands.executeCommandById('editor:save-file');
|
||||
_this.performCommand('editor:save-file');
|
||||
};
|
||||
}
|
||||
registerWatchEvents() {
|
||||
@@ -1235,7 +1233,6 @@ We can perform a command in this file.
|
||||
this.registerDomEvent(window, "offline", this.watchOnline);
|
||||
}
|
||||
|
||||
|
||||
watchOnline() {
|
||||
scheduleTask("watch-online", 500, () => fireAndForget(() => this.watchOnlineAsync()));
|
||||
}
|
||||
@@ -1456,9 +1453,9 @@ We can perform a command in this file.
|
||||
const logDate = `${PREFIXMD_LOGFILE}${time}.md`;
|
||||
const file = this.vaultAccess.getAbstractFileByPath(normalizePath(logDate));
|
||||
if (!file) {
|
||||
this.app.vault.adapter.append(normalizePath(logDate), "```\n");
|
||||
this.vaultAccess.adapterAppend(normalizePath(logDate), "```\n");
|
||||
}
|
||||
this.app.vault.adapter.append(normalizePath(logDate), vaultName + ":" + newMessage + "\n");
|
||||
this.vaultAccess.adapterAppend(normalizePath(logDate), vaultName + ":" + newMessage + "\n");
|
||||
}
|
||||
recentLogProcessor.enqueue(newMessage);
|
||||
|
||||
@@ -1496,28 +1493,6 @@ We can perform a command in this file.
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async ensureDirectory(fullPath: string) {
|
||||
const pathElements = fullPath.split("/");
|
||||
pathElements.pop();
|
||||
let c = "";
|
||||
for (const v of pathElements) {
|
||||
c += v;
|
||||
try {
|
||||
await this.app.vault.createFolder(c);
|
||||
} catch (ex) {
|
||||
// basically skip exceptions.
|
||||
if (ex.message && ex.message == "Folder already exists.") {
|
||||
// especially this message is.
|
||||
} else {
|
||||
Logger("Folder Create Error");
|
||||
Logger(ex);
|
||||
}
|
||||
}
|
||||
c += "/";
|
||||
}
|
||||
}
|
||||
|
||||
async processEntryDoc(docEntry: EntryBody, file: TFile | undefined, force?: boolean) {
|
||||
const mode = file == undefined ? "create" : "modify";
|
||||
|
||||
@@ -1577,7 +1552,7 @@ We can perform a command in this file.
|
||||
return;
|
||||
}
|
||||
const writeData = doc.datatype == "newnote" ? decodeBinary(doc.data) : getDocData(doc.data);
|
||||
await this.ensureDirectoryEx(path);
|
||||
await this.vaultAccess.ensureDirectory(path);
|
||||
try {
|
||||
let outFile;
|
||||
let isChanged = true;
|
||||
@@ -1592,7 +1567,7 @@ We can perform a command in this file.
|
||||
if (isChanged) {
|
||||
Logger(msg + path);
|
||||
this.vaultAccess.touch(outFile);
|
||||
this.app.vault.trigger(mode, outFile);
|
||||
this.vaultAccess.trigger(mode, outFile);
|
||||
} else {
|
||||
Logger(msg + "Skipped, the file is the same: " + path, LOG_LEVEL_VERBOSE);
|
||||
}
|
||||
@@ -1626,7 +1601,7 @@ We can perform a command in this file.
|
||||
queueConflictCheck(file: FilePathWithPrefix | TFile) {
|
||||
const path = file instanceof TFile ? getPathFromTFile(file) : file;
|
||||
if (this.settings.checkConflictOnlyOnOpen) {
|
||||
const af = this.app.workspace.getActiveFile();
|
||||
const af = this.getActiveFile();
|
||||
if (af && af.path != path) {
|
||||
Logger(`${file} is conflicted, merging process has been postponed.`, LOG_LEVEL_NOTICE);
|
||||
return;
|
||||
@@ -1927,7 +1902,7 @@ Even if you choose to clean up, you will see this option again if you exit Obsid
|
||||
const CHOICE_DISMISS = "Dismiss";
|
||||
const ret = await confirmWithMessage(this, "Cleaned", message, [CHOICE_FETCH, CHOICE_CLEAN, CHOICE_DISMISS], CHOICE_DISMISS, 30);
|
||||
if (ret == CHOICE_FETCH) {
|
||||
await performRebuildDB(this, "localOnly");
|
||||
await performRebuildDB(this, "localOnlyWithChunks");
|
||||
}
|
||||
if (ret == CHOICE_CLEAN) {
|
||||
const remoteDB = await this.getReplicator().connectRemoteCouchDBWithSetting(this.settings, this.getIsMobile(), true);
|
||||
@@ -1961,7 +1936,7 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
const CHOICE_DISMISS = "Dismiss";
|
||||
const ret = await confirmWithMessage(this, "Locked", message, [CHOICE_FETCH, CHOICE_DISMISS], CHOICE_DISMISS, 10);
|
||||
if (ret == CHOICE_FETCH) {
|
||||
await performRebuildDB(this, "localOnly");
|
||||
await performRebuildDB(this, "localOnlyWithChunks");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2036,7 +2011,7 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
await this.collectDeletedFiles();
|
||||
|
||||
Logger("Collecting local files on the storage", LOG_LEVEL_VERBOSE);
|
||||
const filesStorageSrc = this.app.vault.getFiles();
|
||||
const filesStorageSrc = this.vaultAccess.getFiles();
|
||||
|
||||
const filesStorage = [] as typeof filesStorageSrc;
|
||||
for (const f of filesStorageSrc) {
|
||||
@@ -2534,7 +2509,7 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
return;
|
||||
}
|
||||
if (this.settings.showMergeDialogOnlyOnActive) {
|
||||
const af = this.app.workspace.getActiveFile();
|
||||
const af = this.getActiveFile();
|
||||
if (af && af.path != filename) {
|
||||
Logger(`${filename} is conflicted. Merging process has been postponed to the file have got opened.`, LOG_LEVEL_NOTICE);
|
||||
return;
|
||||
@@ -2820,27 +2795,6 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
await this.replicator.tryCreateRemoteDatabase(this.settings);
|
||||
}
|
||||
|
||||
async ensureDirectoryEx(fullPath: string) {
|
||||
const pathElements = fullPath.split("/");
|
||||
pathElements.pop();
|
||||
let c = "";
|
||||
for (const v of pathElements) {
|
||||
c += v;
|
||||
try {
|
||||
await this.app.vault.adapter.mkdir(c);
|
||||
} catch (ex) {
|
||||
// basically skip exceptions.
|
||||
if (ex.message && ex.message == "Folder already exists.") {
|
||||
// especially this message is.
|
||||
} else {
|
||||
Logger("Folder Create Error");
|
||||
Logger(ex);
|
||||
}
|
||||
}
|
||||
c += "/";
|
||||
}
|
||||
}
|
||||
|
||||
filterTargetFiles(files: InternalFileInfo[], targetFiles: string[] | false = false) {
|
||||
const ignorePatterns = this.settings.syncInternalFilesIgnorePatterns
|
||||
.replace(/\n| /g, "")
|
||||
@@ -2949,6 +2903,12 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
});
|
||||
}
|
||||
|
||||
askYesNo(message: string): Promise<"yes" | "no"> {
|
||||
return askYesNo(this.app, message);
|
||||
}
|
||||
askSelectString(message: string, items: string[]): Promise<string> {
|
||||
return askSelectString(this.app, message, items);
|
||||
}
|
||||
|
||||
askInPopup(key: string, dialogText: string, anchorCallback: (anchor: HTMLAnchorElement) => void) {
|
||||
|
||||
@@ -2967,7 +2927,6 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
const popupKey = "popup-" + key;
|
||||
scheduleTask(popupKey, 1000, async () => {
|
||||
const popup = await memoIfNotExist(popupKey, () => new Notice(fragment, 0));
|
||||
//@ts-ignore
|
||||
const isShown = popup?.noticeEl?.isShown();
|
||||
if (!isShown) {
|
||||
memoObject(popupKey, new Notice(fragment, 0));
|
||||
@@ -2976,7 +2935,6 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
const popup = retrieveMemoObject<Notice>(popupKey);
|
||||
if (!popup)
|
||||
return;
|
||||
//@ts-ignore
|
||||
if (popup?.noticeEl?.isShown()) {
|
||||
popup.hide();
|
||||
}
|
||||
@@ -2984,5 +2942,19 @@ Or if you are sure know what had been happened, we can unlock the database from
|
||||
});
|
||||
});
|
||||
}
|
||||
openSetting() {
|
||||
//@ts-ignore: undocumented api
|
||||
this.app.setting.open();
|
||||
//@ts-ignore: undocumented api
|
||||
this.app.setting.openTabById("obsidian-livesync");
|
||||
}
|
||||
|
||||
performAppReload() {
|
||||
this.performCommand("app:reload");
|
||||
}
|
||||
performCommand(id: string) {
|
||||
// @ts-ignore
|
||||
this.app.commands.executeCommandById(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -405,10 +405,13 @@ export const requestToCouchDB = async (baseUri: string, username: string, passwo
|
||||
return await _requestToCouchDB(baseUri, username, password, origin, uri, body, method);
|
||||
};
|
||||
|
||||
export async function performRebuildDB(plugin: ObsidianLiveSyncPlugin, method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice") {
|
||||
export async function performRebuildDB(plugin: ObsidianLiveSyncPlugin, method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice" | "localOnlyWithChunks") {
|
||||
if (method == "localOnly") {
|
||||
await plugin.addOnSetup.fetchLocal();
|
||||
}
|
||||
if (method == "localOnlyWithChunks") {
|
||||
await plugin.addOnSetup.fetchLocal(true);
|
||||
}
|
||||
if (method == "remoteOnly") {
|
||||
await plugin.addOnSetup.rebuildRemote();
|
||||
}
|
||||
|
Reference in New Issue
Block a user