mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2025-12-13 17:55:56 +00:00
- New feature:
- If any conflicted files have been left, they will be reported. - Fixed: - Now the name of the conflicting file is shown on the conflict-resolving dialogue. - Hidden files are now able to be merged again. - No longer error caused at plug-in being loaded. - Improved: - Caching chunks are now limited in total size of cached chunks.
This commit is contained in:
@@ -22,7 +22,7 @@ export class ConflictResolveModal extends Modal {
|
||||
contentEl.empty();
|
||||
|
||||
contentEl.createEl("h2", { text: "This document has conflicted changes." });
|
||||
contentEl.createEl("span", this.filename);
|
||||
contentEl.createEl("span", { text: this.filename });
|
||||
const div = contentEl.createDiv("");
|
||||
div.addClass("op-scrollable");
|
||||
let diff = "";
|
||||
|
||||
@@ -1292,6 +1292,38 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
||||
return toggle;
|
||||
}
|
||||
);
|
||||
new Setting(containerSyncSettingEl)
|
||||
.setName("A number of hashes to be cached")
|
||||
.setDesc("")
|
||||
.addText((text) => {
|
||||
text.setPlaceholder("")
|
||||
.setValue(this.plugin.settings.hashCacheMaxCount + "")
|
||||
.onChange(async (value) => {
|
||||
let v = Number(value);
|
||||
if (isNaN(v) || v < 10) {
|
||||
v = 10;
|
||||
}
|
||||
this.plugin.settings.hashCacheMaxCount = v;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
text.inputEl.setAttribute("type", "number");
|
||||
});
|
||||
new Setting(containerSyncSettingEl)
|
||||
.setName("The total length of hashes to be cached")
|
||||
.setDesc("(Mega chars)")
|
||||
.addText((text) => {
|
||||
text.setPlaceholder("")
|
||||
.setValue(this.plugin.settings.hashCacheMaxAmount + "")
|
||||
.onChange(async (value) => {
|
||||
let v = Number(value);
|
||||
if (isNaN(v) || v < 1) {
|
||||
v = 1;
|
||||
}
|
||||
this.plugin.settings.hashCacheMaxAmount = v;
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
text.inputEl.setAttribute("type", "number");
|
||||
});
|
||||
|
||||
addScreenElement("30", containerSyncSettingEl);
|
||||
const containerMiscellaneousEl = containerEl.createDiv();
|
||||
|
||||
2
src/lib
2
src/lib
Submodule src/lib updated: 6c8d0b0c32...e4d825ae13
78
src/main.ts
78
src/main.ts
@@ -138,6 +138,8 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||
deviceAndVaultName: string;
|
||||
isMobile = false;
|
||||
isReady = false;
|
||||
packageVersion = "";
|
||||
manifestVersion = "";
|
||||
|
||||
watchedFileEventQueue = [] as FileEventItem[];
|
||||
|
||||
@@ -194,26 +196,10 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||
}
|
||||
|
||||
async fileHistory() {
|
||||
const pageLimit = 1000;
|
||||
let nextKey = "";
|
||||
const notes: { path: string, mtime: number }[] = [];
|
||||
do {
|
||||
const docs = await this.localDatabase.localDatabase.allDocs({ limit: pageLimit, startkey: nextKey, include_docs: true });
|
||||
nextKey = "";
|
||||
for (const row of docs.rows) {
|
||||
const doc = row.doc;
|
||||
nextKey = `${row.id}\u{10ffff}`;
|
||||
if (!("type" in doc)) continue;
|
||||
if (doc.type == "newnote" || doc.type == "plain") {
|
||||
notes.push({ path: id2path(doc._id), mtime: doc.mtime });
|
||||
}
|
||||
if (isChunk(nextKey)) {
|
||||
// skip the chunk zone.
|
||||
nextKey = CHeaderEnd;
|
||||
}
|
||||
}
|
||||
} while (nextKey != "");
|
||||
|
||||
for await (const doc of this.localDatabase.findAllDocs()) {
|
||||
notes.push({ path: id2path(doc._id), mtime: doc.mtime });
|
||||
}
|
||||
notes.sort((a, b) => b.mtime - a.mtime);
|
||||
const notesList = notes.map(e => e.path);
|
||||
const target = await askSelectString(this.app, "File to view History", notesList);
|
||||
@@ -222,31 +208,11 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||
}
|
||||
}
|
||||
async pickFileForResolve() {
|
||||
const pageLimit = 1000;
|
||||
let nextKey = "";
|
||||
const notes: { path: string, mtime: number }[] = [];
|
||||
do {
|
||||
const docs = await this.localDatabase.localDatabase.allDocs({ limit: pageLimit, startkey: nextKey, conflicts: true, include_docs: true });
|
||||
nextKey = "";
|
||||
for (const row of docs.rows) {
|
||||
const doc = row.doc;
|
||||
nextKey = `${row.id}\u{10ffff}`;
|
||||
if (isChunk(nextKey)) {
|
||||
// skip the chunk zone.
|
||||
nextKey = CHeaderEnd;
|
||||
}
|
||||
if (!("_conflicts" in doc)) continue;
|
||||
if (isInternalMetadata(row.id)) continue;
|
||||
// We have to check also deleted files.
|
||||
// if (doc._deleted) continue;
|
||||
// if ("deleted" in doc && doc.deleted) continue;
|
||||
if (doc.type == "newnote" || doc.type == "plain") {
|
||||
// const docId = doc._id.startsWith("i:") ? doc._id.substring("i:".length) : doc._id;
|
||||
notes.push({ path: id2path(doc._id), mtime: doc.mtime });
|
||||
}
|
||||
|
||||
}
|
||||
} while (nextKey != "");
|
||||
for await (const doc of this.localDatabase.findAllDocs({ conflicts: true })) {
|
||||
if (!("_conflicts" in doc)) continue;
|
||||
notes.push({ path: id2path(doc._id), mtime: doc.mtime });
|
||||
}
|
||||
notes.sort((a, b) => b.mtime - a.mtime);
|
||||
const notesList = notes.map(e => e.path);
|
||||
if (notesList.length == 0) {
|
||||
@@ -257,6 +223,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||
if (target) {
|
||||
if (isInternalMetadata(target)) {
|
||||
//NOP
|
||||
await this.resolveConflictOnInternalFile(target);
|
||||
} else {
|
||||
await this.showIfConflicted(target);
|
||||
}
|
||||
@@ -371,12 +338,33 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||
if (this.settings.syncOnStart) {
|
||||
this.localDatabase.openReplication(this.settings, false, false, this.parseReplicationResult);
|
||||
}
|
||||
this.scanStat();
|
||||
} catch (ex) {
|
||||
Logger("Error while loading Self-hosted LiveSync", LOG_LEVEL.NOTICE);
|
||||
Logger(ex, LOG_LEVEL.VERBOSE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan status
|
||||
*/
|
||||
async scanStat() {
|
||||
const notes: { path: string, mtime: number }[] = [];
|
||||
Logger(`Additional safety scan..`, LOG_LEVEL.VERBOSE);
|
||||
for await (const doc of this.localDatabase.findAllDocs({ conflicts: true })) {
|
||||
if (!("_conflicts" in doc)) continue;
|
||||
notes.push({ path: id2path(doc._id), mtime: doc.mtime });
|
||||
}
|
||||
if (notes.length > 0) {
|
||||
Logger(`Some files have been left conflicted! Please resolve them by "Pick a file to resolve conflict". The list is written in the log.`, LOG_LEVEL.NOTICE);
|
||||
for (const note of notes) {
|
||||
Logger(`Conflicted: ${note.path}`);
|
||||
}
|
||||
} else {
|
||||
Logger(`There are no conflicted files`, LOG_LEVEL.VERBOSE);
|
||||
}
|
||||
Logger(`Additional safety scan done`, LOG_LEVEL.VERBOSE);
|
||||
}
|
||||
async command_copySetupURI() {
|
||||
const encryptingPassphrase = await askString(this.app, "Encrypt your settings", "The passphrase to encrypt the setup URI", "");
|
||||
if (encryptingPassphrase === false) return;
|
||||
@@ -536,6 +524,8 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||
//@ts-ignore
|
||||
const packageVersion: string = PACKAGE_VERSION || "0.0.0";
|
||||
|
||||
this.manifestVersion = manifestVersion;
|
||||
this.packageVersion = packageVersion;
|
||||
|
||||
Logger(`Self-hosted LiveSync v${manifestVersion} ${packageVersion} `);
|
||||
const lsKey = "obsidian-live-sync-ver" + this.getVaultName();
|
||||
@@ -1315,7 +1305,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
|
||||
const newMessage = timestamp + "->" + messageContent;
|
||||
|
||||
console.log(vaultName + ":" + newMessage);
|
||||
if (this.settings.writeLogToTheFile) {
|
||||
if (this.settings?.writeLogToTheFile) {
|
||||
const time = now.toISOString().split("T")[0];
|
||||
const logDate = `${PREFIXMD_LOGFILE}${time}.md`;
|
||||
const file = this.app.vault.getAbstractFileByPath(normalizePath(logDate));
|
||||
|
||||
Reference in New Issue
Block a user