mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-05-09 17:21:54 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c000a02f4a | ||
|
|
79754f48d6 | ||
|
|
dd7a40630b | ||
|
|
14406f8213 |
@@ -48,7 +48,9 @@ const terserOpt = {
|
|||||||
lhs_constants: true,
|
lhs_constants: true,
|
||||||
hoist_props: true,
|
hoist_props: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
// if_return: true,
|
if_return: true,
|
||||||
|
ecma: 2018,
|
||||||
|
unused: true,
|
||||||
},
|
},
|
||||||
// mangle: {
|
// mangle: {
|
||||||
// // mangle options
|
// // mangle options
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"id": "obsidian-livesync",
|
"id": "obsidian-livesync",
|
||||||
"name": "Self-hosted LiveSync",
|
"name": "Self-hosted LiveSync",
|
||||||
"version": "0.20.0",
|
"version": "0.20.2",
|
||||||
"minAppVersion": "0.9.12",
|
"minAppVersion": "0.9.12",
|
||||||
"description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
"description": "Community implementation of self-hosted livesync. Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
||||||
"author": "vorotamoroz",
|
"author": "vorotamoroz",
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.20.0",
|
"version": "0.20.2",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.20.0",
|
"version": "0.20.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"diff-match-patch": "^1.0.5",
|
"diff-match-patch": "^1.0.5",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-livesync",
|
"name": "obsidian-livesync",
|
||||||
"version": "0.20.0",
|
"version": "0.20.2",
|
||||||
"description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
"description": "Reflect your vault changes to some other devices immediately. Please make sure to disable other synchronize solutions to avoid content corruption or duplication.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@@ -16,22 +16,108 @@ import { PluginDialogModal } from "./dialogs";
|
|||||||
import { JsonResolveModal } from "./JsonResolveModal";
|
import { JsonResolveModal } from "./JsonResolveModal";
|
||||||
import { pipeGeneratorToGenerator, processAllGeneratorTasksWithConcurrencyLimit } from './lib/src/task';
|
import { pipeGeneratorToGenerator, processAllGeneratorTasksWithConcurrencyLimit } from './lib/src/task';
|
||||||
|
|
||||||
|
const d = "\u200b";
|
||||||
|
const d2 = "\n";
|
||||||
|
|
||||||
function serialize(data: PluginDataEx): string {
|
function serialize(data: PluginDataEx): string {
|
||||||
// To improve performance, make JSON manually.
|
// For higher performance, create custom plug-in data strings.
|
||||||
// Self-hosted LiveSync uses `\n` to split chunks. Therefore, grouping together those with similar entropy would work nicely.
|
// Self-hosted LiveSync uses `\n` to split chunks. Therefore, grouping together those with similar entropy would work nicely.
|
||||||
return `{"category":"${data.category}","name":"${data.name}","term":${JSON.stringify(data.term)}
|
let ret = "";
|
||||||
${data.version ? `,"version":"${data.version}"` : ""},
|
ret += ":";
|
||||||
"mtime":${data.mtime},
|
ret += data.category + d + data.name + d + data.term + d2;
|
||||||
"files":[
|
ret += (data.version ?? "") + d2;
|
||||||
${data.files.map(file => `{"filename":"${file.filename}"${file.displayName ? `,"displayName":"${file.displayName}"` : ""}${file.version ? `,"version":"${file.version}"` : ""},
|
ret += data.mtime + d2;
|
||||||
"mtime":${file.mtime},"size":${file.size}
|
for (const file of data.files) {
|
||||||
,"data":[${file.data.map(e => `"${e}"`).join(",")
|
ret += file.filename + d + (file.displayName ?? "") + d + (file.version ?? "") + d2;
|
||||||
}]}`).join(",")
|
ret += file.mtime + d + file.size + d2;
|
||||||
}]}`
|
for (const data of file.data ?? []) {
|
||||||
|
ret += data + d
|
||||||
|
}
|
||||||
|
ret += d2;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
function fetchToken(source: string, from: number): [next: number, token: string] {
|
||||||
|
const limitIdx = source.indexOf(d2, from);
|
||||||
|
const limit = limitIdx == -1 ? source.length : limitIdx;
|
||||||
|
const delimiterIdx = source.indexOf(d, from);
|
||||||
|
const delimiter = delimiterIdx == -1 ? source.length : delimiterIdx;
|
||||||
|
const tokenEnd = Math.min(limit, delimiter);
|
||||||
|
let next = tokenEnd;
|
||||||
|
if (limit < delimiter) {
|
||||||
|
next = tokenEnd;
|
||||||
|
} else {
|
||||||
|
next = tokenEnd + 1
|
||||||
|
}
|
||||||
|
return [next, source.substring(from, tokenEnd)];
|
||||||
|
}
|
||||||
|
function getTokenizer(source: string) {
|
||||||
|
const t = {
|
||||||
|
pos: 1,
|
||||||
|
next() {
|
||||||
|
const [next, token] = fetchToken(source, this.pos);
|
||||||
|
this.pos = next;
|
||||||
|
return token;
|
||||||
|
},
|
||||||
|
nextLine() {
|
||||||
|
const nextPos = source.indexOf(d2, this.pos);
|
||||||
|
if (nextPos == -1) {
|
||||||
|
this.pos = source.length;
|
||||||
|
} else {
|
||||||
|
this.pos = nextPos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deserialize2(str: string): PluginDataEx {
|
||||||
|
const tokens = getTokenizer(str);
|
||||||
|
const ret = {} as PluginDataEx;
|
||||||
|
const category = tokens.next();
|
||||||
|
const name = tokens.next();
|
||||||
|
const term = tokens.next();
|
||||||
|
tokens.nextLine();
|
||||||
|
const version = tokens.next();
|
||||||
|
tokens.nextLine();
|
||||||
|
const mtime = Number(tokens.next());
|
||||||
|
tokens.nextLine();
|
||||||
|
const result: PluginDataEx = Object.assign(ret,
|
||||||
|
{ category, name, term, version, mtime, files: [] as PluginDataExFile[] })
|
||||||
|
let filename = "";
|
||||||
|
do {
|
||||||
|
filename = tokens.next();
|
||||||
|
if (!filename) break;
|
||||||
|
const displayName = tokens.next();
|
||||||
|
const version = tokens.next();
|
||||||
|
tokens.nextLine();
|
||||||
|
const mtime = Number(tokens.next());
|
||||||
|
const size = Number(tokens.next());
|
||||||
|
tokens.nextLine();
|
||||||
|
const data = [] as string[];
|
||||||
|
let piece = "";
|
||||||
|
do {
|
||||||
|
piece = tokens.next();
|
||||||
|
if (piece == "") break;
|
||||||
|
data.push(piece);
|
||||||
|
} while (piece != "");
|
||||||
|
result.files.push(
|
||||||
|
{
|
||||||
|
filename,
|
||||||
|
displayName,
|
||||||
|
version,
|
||||||
|
mtime,
|
||||||
|
size,
|
||||||
|
data
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} while (filename);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function deserialize<T>(str: string, def: T) {
|
function deserialize<T>(str: string, def: T) {
|
||||||
try {
|
try {
|
||||||
|
if (str[0] == ":") return deserialize2(str);
|
||||||
return JSON.parse(str) as T;
|
return JSON.parse(str) as T;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export class DocumentHistoryModal extends Modal {
|
|||||||
const w2 = await db.getDBEntry(this.file, { rev: oldRev }, false, false, true);
|
const w2 = await db.getDBEntry(this.file, { rev: oldRev }, false, false, true);
|
||||||
if (w2 != false) {
|
if (w2 != false) {
|
||||||
const dmp = new diff_match_patch();
|
const dmp = new diff_match_patch();
|
||||||
const w2data = w2.datatype == "plain" ? getDocData(w2.data) : readString(new Uint8Array(decodeBinary(w.data)));
|
const w2data = w2.datatype == "plain" ? getDocData(w2.data) : readString(new Uint8Array(decodeBinary(w2.data)));
|
||||||
const diff = dmp.diff_main(w2data, w1data);
|
const diff = dmp.diff_main(w2data, w1data);
|
||||||
dmp.diff_cleanupSemantic(diff);
|
dmp.diff_cleanupSemantic(diff);
|
||||||
for (const v of diff) {
|
for (const v of diff) {
|
||||||
|
|||||||
@@ -1657,6 +1657,22 @@ ${stringifyYaml(pluginConfig)}`;
|
|||||||
}
|
}
|
||||||
Logger(`Converting finished`, LOG_LEVEL_NOTICE);
|
Logger(`Converting finished`, LOG_LEVEL_NOTICE);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
new Setting(containerHatchEl)
|
||||||
|
.setName("Delete all customization sync data")
|
||||||
|
.addButton((button) =>
|
||||||
|
button
|
||||||
|
.setButtonText("Delete")
|
||||||
|
.setDisabled(false)
|
||||||
|
.setWarning()
|
||||||
|
.onClick(async () => {
|
||||||
|
Logger(`Deleting customization sync data`, LOG_LEVEL_NOTICE);
|
||||||
|
const entriesToDelete = (await this.plugin.localDatabase.allDocsRaw({ startkey: "ix:", endkey: "ix:\u{10ffff}", include_docs: true }));
|
||||||
|
const newData = entriesToDelete.rows.map(e => ({ ...e.doc, _deleted: true }));
|
||||||
|
const r = await this.plugin.localDatabase.bulkDocsRaw(newData as any[]);
|
||||||
|
// Do not care about the result.
|
||||||
|
Logger(`${r.length} items have been removed, to confirm how many items are left, please perform it again.`, LOG_LEVEL_NOTICE);
|
||||||
|
}))
|
||||||
new Setting(containerHatchEl)
|
new Setting(containerHatchEl)
|
||||||
.setName("Suspend file watching")
|
.setName("Suspend file watching")
|
||||||
.setDesc("Stop watching for file change.")
|
.setDesc("Stop watching for file change.")
|
||||||
|
|||||||
@@ -274,7 +274,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<span class="spacer" />
|
<span class="spacer" />
|
||||||
<span class="message even">All devices are even</span>
|
<span class="message even">All the same or non-existent</span>
|
||||||
<button disabled />
|
<button disabled />
|
||||||
<button disabled />
|
<button disabled />
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
2
src/lib
2
src/lib
Submodule src/lib updated: 4a955add9c...609c7aecf3
25
updates.md
25
updates.md
@@ -15,7 +15,21 @@ This format change gives us the ability to detect some `marks` in the binary fil
|
|||||||
Now only a few chunks are transferred, even if we add a comment to the PDF or put new files into the ZIP archives.
|
Now only a few chunks are transferred, even if we add a comment to the PDF or put new files into the ZIP archives.
|
||||||
|
|
||||||
#### Version history
|
#### Version history
|
||||||
|
- 0.20.2
|
||||||
|
- New feature:
|
||||||
|
- We can delete all data of customization sync from the `Delete all customization sync data` on the `Hatch` pane.
|
||||||
|
- Fixed:
|
||||||
|
- Prevent keep restarting on iOS by yielding microtasks.
|
||||||
|
- 0.20.1
|
||||||
|
- Fixed:
|
||||||
|
- No more UI freezing and keep restarting on iOS.
|
||||||
|
- Diff of Non-markdown documents are now shown correctly.
|
||||||
|
- Improved:
|
||||||
|
- Performance has been a bit improved.
|
||||||
|
- Customization sync has gotten faster.
|
||||||
|
- However, We lost forward compatibility again (only for this feature). Please update all devices.
|
||||||
|
- Misc
|
||||||
|
- Terser configuration has been more aggressive.
|
||||||
- 0.20.0
|
- 0.20.0
|
||||||
- Improved:
|
- Improved:
|
||||||
- A New binary file handling implemented
|
- A New binary file handling implemented
|
||||||
@@ -27,12 +41,3 @@ Now only a few chunks are transferred, even if we add a comment to the PDF or pu
|
|||||||
- Some Lint warnings have been suppressed.
|
- Some Lint warnings have been suppressed.
|
||||||
|
|
||||||
... To continue on to `updates_old.md`.
|
... To continue on to `updates_old.md`.
|
||||||
|
|
||||||
- Improved:
|
|
||||||
- A New binary file handling implemented
|
|
||||||
- A new encrypted format has been implemented
|
|
||||||
- Now the chunk sizes will be adjusted for efficient sync
|
|
||||||
- Fixed:
|
|
||||||
- levels of exception in some logs have been fixed
|
|
||||||
- Tidied:
|
|
||||||
- Some Lint warnings have been suppressed.
|
|
||||||
Reference in New Issue
Block a user