Compare commits

..

40 Commits

Author SHA1 Message Date
vorotamoroz
1ad5dcc1cc bump 2022-12-16 18:56:28 +09:00
vorotamoroz
a512566e5b New feature
- We can merge conflicted documents automatically if sensible.

Fixed:
- Writing to the storage will be pended while they have conflicts after replication.

Minor changes included.
2022-12-16 18:55:04 +09:00
vorotamoroz
02de82af46 bump 2022-12-06 18:03:31 +09:00
vorotamoroz
840e03a2d3 Fixed:
- Now we can verify and repair database again.
2022-12-06 17:59:48 +09:00
vorotamoroz
96b676caf3 bump 2022-12-05 19:53:24 +09:00
vorotamoroz
a8219de375 Improved:
- Splitting markdown
- Saving chunks

Changed:
- Chunk ID numbering rules

Fixed:
- Just weed.
2022-12-05 19:37:24 +09:00
vorotamoroz
db3eb7e1a0 bump 2022-11-24 14:14:27 +09:00
vorotamoroz
50f51393fc upgrade lib. 2022-11-24 14:14:17 +09:00
vorotamoroz
8a04e332d6 Fix check warning for max_document_size, max_http_request_size as like as #145 2022-11-23 15:41:09 +09:00
vorotamoroz
12ae17aa2f Merge pull request #145 from Bpazy/patch-1
Fix check warning for max_document_size, max_http_request_size
2022-11-23 15:37:32 +09:00
Ziyuan Han
657f12f966 Fix check warning 2022-11-23 14:12:50 +08:00
Ziyuan Han
15a7bed448 Fix check warning 2022-11-23 14:11:44 +08:00
vorotamoroz
420c3b94df bump 2022-11-23 10:34:04 +09:00
vorotamoroz
239c087132 framework and dependency upgraded. 2022-11-23 10:27:12 +09:00
vorotamoroz
d1a633c799 bump 2022-11-07 17:26:40 +09:00
vorotamoroz
1c07cd92fc - Fixed
- Automatic (temporary) batch size adjustment has been restored to work correctly.
  - Chunk splitting has been backed to the previous behaviour for saving them correctly.
- Improved
  - Corrupted chunks will be detected automatically.
  - Now on the case-insensitive system, `aaa.md` and `AAA.md` will be treated as the same file or path at applying changesets.
2022-11-07 17:26:33 +09:00
vorotamoroz
adc84d53b1 bump again 2022-10-27 17:43:00 +09:00
vorotamoroz
c3a762ceed bump 2022-10-27 17:42:15 +09:00
vorotamoroz
5945638633 Fixed:
- Conflict detection and merging of deleted files.
- Fixed wrong logs.
- Fix redundant logs.

Implemented
- Automatically deletion of old metadata.
2022-10-27 17:41:26 +09:00
vorotamoroz
331acd463d bump 2022-10-25 11:48:21 +09:00
vorotamoroz
9d4f41bbf9 Fixed failure of detection 2022-10-25 11:47:02 +09:00
vorotamoroz
8831165965 bump 2022-10-25 11:34:09 +09:00
vorotamoroz
ed62e9331b Implemented:
- A configuration information reporting tools has been implemented.

Improved:
- Fixed detection of IBM Cloudant
2022-10-25 11:33:37 +09:00
vorotamoroz
799e604eb2 bump 2022-10-21 18:22:02 +09:00
vorotamoroz
d9b69d9a1b Fixed:
- Fixed the Infinity loop
2022-10-21 18:20:03 +09:00
vorotamoroz
c18b5c24b4 bump 2022-10-14 17:39:16 +09:00
vorotamoroz
07f16e3d7d Added missing log updates. 2022-10-14 17:37:25 +09:00
vorotamoroz
486f1aa4a0 Bump 2022-10-05 17:14:52 +09:00
vorotamoroz
075c6beb68 New feature:
- Monitor hidden files, Now we can use internal file sync without scan.
Fixed:
- Periodic synchronisation sometimes failed.
- Status-display had not been cleared in some cases.
- `Skip patterns default` has been changed to more clear name.
2022-10-05 17:14:32 +09:00
vorotamoroz
d6121b0c1e bump 2022-10-03 10:57:39 +09:00
vorotamoroz
3292a48054 Fixed
- The boot sequence has been corrected and now boots smoothly.
- Auto applying of batch save will be processed earlier than before.
2022-10-03 10:52:31 +09:00
vorotamoroz
ee37764040 bump 2022-10-02 01:48:50 +09:00
vorotamoroz
b6f7fced22 Use new library for batching the chunk retrieving 2022-10-02 01:45:44 +09:00
vorotamoroz
13456c0854 Fixed: deleted debug message 2022-10-02 01:44:39 +09:00
vorotamoroz
2663a52fd7 bump 2022-09-29 16:58:53 +09:00
vorotamoroz
d4bbf79514 Fixed:
- Fixed a bug about deleting empty directory
- Weird behaviour on boot-sequence on mobile devices.
2022-09-29 16:58:39 +09:00
vorotamoroz
5f96cc6b82 bump 2022-09-28 17:57:23 +09:00
vorotamoroz
8c8f5d045f Fixed:
- Fixed bug about renaming file
2022-09-28 17:56:34 +09:00
vorotamoroz
40cf8be890 Bump 2022-09-28 16:17:11 +09:00
vorotamoroz
6b03dbbe75 Fixed:
- File tracking logic has been refined.
2022-09-28 16:17:04 +09:00
14 changed files with 1992 additions and 1973 deletions

View File

@@ -10,9 +10,11 @@ But some additional configurations are required in `local.ini` to use from Self-
``` ```
[couchdb] [couchdb]
single_node=true single_node=true
max_document_size = 50000000
[chttpd] [chttpd]
require_valid_user = true require_valid_user = true
max_http_request_size = 4294967296
[chttpd_auth] [chttpd_auth]
require_valid_user = true require_valid_user = true

View File

@@ -11,9 +11,11 @@
``` ```
[couchdb] [couchdb]
single_node=true single_node=true
max_document_size = 50000000
[chttpd] [chttpd]
require_valid_user = true require_valid_user = true
max_http_request_size = 4294967296
[chttpd_auth] [chttpd_auth]
require_valid_user = true require_valid_user = true

View File

@@ -8,12 +8,14 @@ CouchDBを構築するには、[Dockerのイメージ](https://hub.docker.com/_/
``` ```
[couchdb] [couchdb]
single_node=true single_node=true
max_document_size = 50000000
[chttpd] [chttpd]
require_valid_user = true require_valid_user = true
[chttpd_auth] [chttpd_auth]
require_valid_user = true require_valid_user = true
max_http_request_size = 4294967296
authentication_redirect = /_utils/session.html authentication_redirect = /_utils/session.html
[httpd] [httpd]

View File

@@ -1,7 +1,7 @@
{ {
"id": "obsidian-livesync", "id": "obsidian-livesync",
"name": "Self-hosted LiveSync", "name": "Self-hosted LiveSync",
"version": "0.15.5", "version": "0.17.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",

2755
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "obsidian-livesync", "name": "obsidian-livesync",
"version": "0.15.5", "version": "0.17.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",
@@ -13,34 +13,30 @@
"author": "vorotamoroz", "author": "vorotamoroz",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-node-resolve": "^11.2.1",
"@rollup/plugin-typescript": "^8.2.1",
"@types/diff-match-patch": "^1.0.32", "@types/diff-match-patch": "^1.0.32",
"@types/pouchdb": "^6.4.0", "@types/pouchdb": "^6.4.0",
"@types/pouchdb-browser": "^6.1.3", "@types/pouchdb-browser": "^6.1.3",
"@typescript-eslint/eslint-plugin": "^5.7.0", "@typescript-eslint/eslint-plugin": "^5.44.0",
"@typescript-eslint/parser": "^5.0.0", "@typescript-eslint/parser": "^5.44.0",
"builtin-modules": "^3.2.0", "builtin-modules": "^3.3.0",
"esbuild": "0.13.12", "esbuild": "0.15.15",
"esbuild-svelte": "^0.7.0", "esbuild-svelte": "^0.7.3",
"eslint": "^7.32.0", "eslint": "^8.28.0",
"eslint-config-airbnb-base": "^14.2.1", "eslint-config-airbnb-base": "^15.0.0",
"eslint-plugin-import": "^2.25.2", "eslint-plugin-import": "^2.26.0",
"obsidian": "^0.15.4", "obsidian": "^0.16.3",
"postcss": "^8.4.14", "postcss": "^8.4.19",
"postcss-load-config": "^3.1.4", "postcss-load-config": "^4.0.1",
"rollup": "^2.32.1", "svelte": "^3.53.1",
"svelte": "^3.49.0",
"svelte-preprocess": "^4.10.7", "svelte-preprocess": "^4.10.7",
"tslib": "^2.2.0", "tslib": "^2.4.1",
"typescript": "^4.2.4" "typescript": "^4.9.3"
}, },
"dependencies": { "dependencies": {
"diff-match-patch": "^1.0.5", "diff-match-patch": "^1.0.5",
"esbuild": "0.13.12", "esbuild": "0.15.15",
"esbuild-svelte": "^0.7.0", "esbuild-svelte": "^0.7.3",
"idb": "^7.0.2", "idb": "^7.1.1",
"xxhash-wasm": "^0.4.2" "xxhash-wasm": "^0.4.2"
} }
} }

View File

@@ -1,31 +0,0 @@
import typescript from "@rollup/plugin-typescript";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
const isProd = process.env.BUILD === "production";
const banner = `/*
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
if you want to view the source visit the plugins github repository
*/
`;
export default {
input: "./src/main.ts",
output: {
dir: ".",
sourcemap: "inline",
sourcemapExcludeSources: isProd,
format: "cjs",
exports: "default",
banner,
},
external: ["obsidian"],
plugins: [
typescript({ exclude: ["pouchdb-browser.js", "pouchdb-browser-webpack"] }),
nodeResolve({
browser: true,
}),
commonjs(),
],
};

View File

@@ -38,8 +38,8 @@ export class ConflictResolveModal extends Modal {
diff = diff.replace(/\n/g, "<br>"); diff = diff.replace(/\n/g, "<br>");
div.innerHTML = diff; div.innerHTML = diff;
const div2 = contentEl.createDiv(""); const div2 = contentEl.createDiv("");
const date1 = new Date(this.result.left.mtime).toLocaleString(); const date1 = new Date(this.result.left.mtime).toLocaleString() + (this.result.left.deleted ? " (Deleted)" : "");
const date2 = new Date(this.result.right.mtime).toLocaleString(); const date2 = new Date(this.result.right.mtime).toLocaleString() + (this.result.right.deleted ? " (Deleted)" : "");
div2.innerHTML = ` div2.innerHTML = `
<span class='deleted'>A:${date1}</span><br /><span class='added'>B:${date2}</span><br> <span class='deleted'>A:${date1}</span><br /><span class='added'>B:${date2}</span><br>
`; `;

View File

@@ -5,7 +5,7 @@ import { Logger } from "./lib/src/logger.js";
import { PouchDB } from "./lib/src/pouchdb-browser.js"; import { PouchDB } from "./lib/src/pouchdb-browser.js";
import { EntryDoc, LOG_LEVEL } from "./lib/src/types.js"; import { EntryDoc, LOG_LEVEL } from "./lib/src/types.js";
import { enableEncryption } from "./lib/src/utils.js"; import { enableEncryption } from "./lib/src/utils.js";
import { isValidRemoteCouchDBURI } from "./lib/src/utils_couchdb.js"; import { isCloudantURI, isValidRemoteCouchDBURI } from "./lib/src/utils_couchdb.js";
import { id2path, path2id } from "./utils.js"; import { id2path, path2id } from "./utils.js";
export class LocalPouchDB extends LocalPouchDBBase { export class LocalPouchDB extends LocalPouchDBBase {
@@ -35,7 +35,7 @@ export class LocalPouchDB extends LocalPouchDBBase {
last_successful_post = false; last_successful_post = false;
getLastPostFailedBySize() { getLastPostFailedBySize() {
return this.last_successful_post; return !this.last_successful_post;
} }
async fetchByAPI(request: RequestUrlParam): Promise<RequestUrlResponse> { async fetchByAPI(request: RequestUrlParam): Promise<RequestUrlResponse> {
const ret = await requestUrl(request); const ret = await requestUrl(request);
@@ -75,9 +75,9 @@ export class LocalPouchDB extends LocalPouchDBBase {
const method = opts.method ?? "GET"; const method = opts.method ?? "GET";
if (opts.body) { if (opts.body) {
const opts_length = opts.body.toString().length; const opts_length = opts.body.toString().length;
if (opts_length > 1024 * 1024 * 10) { if (opts_length > 1000 * 1000 * 10) {
// over 10MB // over 10MB
if (uri.contains(".cloudantnosqldb.")) { if (isCloudantURI(uri)) {
this.last_successful_post = false; this.last_successful_post = false;
Logger("This request should fail on IBM Cloudant.", LOG_LEVEL.VERBOSE); Logger("This request should fail on IBM Cloudant.", LOG_LEVEL.VERBOSE);
throw new Error("This request should fail on IBM Cloudant."); throw new Error("This request should fail on IBM Cloudant.");

View File

@@ -1,12 +1,29 @@
import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer } from "obsidian"; import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer, stringifyYaml } from "obsidian";
import { DEFAULT_SETTINGS, LOG_LEVEL, RemoteDBSettings } from "./lib/src/types"; import { DEFAULT_SETTINGS, LOG_LEVEL, ObsidianLiveSyncSettings, RemoteDBSettings } from "./lib/src/types";
import { path2id, id2path } from "./utils"; import { path2id, id2path } from "./utils";
import { delay, versionNumberString2Number } from "./lib/src/utils"; import { delay, Semaphore, versionNumberString2Number } from "./lib/src/utils";
import { Logger } from "./lib/src/logger"; import { Logger } from "./lib/src/logger";
import { checkSyncInfo } from "./lib/src/utils_couchdb.js"; import { checkSyncInfo, isCloudantURI } from "./lib/src/utils_couchdb.js";
import { testCrypt } from "./lib/src/e2ee_v2"; import { testCrypt } from "./lib/src/e2ee_v2";
import ObsidianLiveSyncPlugin from "./main"; import ObsidianLiveSyncPlugin from "./main";
const requestToCouchDB = async (baseUri: string, username: string, password: string, origin: string, key?: string, body?: string) => {
const utf8str = String.fromCharCode.apply(null, new TextEncoder().encode(`${username}:${password}`));
const encoded = window.btoa(utf8str);
const authHeader = "Basic " + encoded;
// const origin = "capacitor://localhost";
const transformedHeaders: Record<string, string> = { authorization: authHeader, origin: origin };
const uri = `${baseUri}/_node/_local/_config${key ? "/" + key : ""}`;
const requestParam: RequestUrlParam = {
url: uri,
method: body ? "PUT" : "GET",
headers: transformedHeaders,
contentType: "application/json",
body: body ? JSON.stringify(body) : undefined,
};
return await requestUrl(requestParam);
};
export class ObsidianLiveSyncSettingTab extends PluginSettingTab { export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
plugin: ObsidianLiveSyncPlugin; plugin: ObsidianLiveSyncPlugin;
@@ -67,9 +84,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
element.removeClass("selected"); element.removeClass("selected");
(element.querySelector("input[type=radio]") as HTMLInputElement).checked = false; (element.querySelector("input[type=radio]") as HTMLInputElement).checked = false;
}); });
console.log(`.sls-setting-label.c-${screen}`)
w.querySelectorAll(`.sls-setting-label.c-${screen}`).forEach((element) => { w.querySelectorAll(`.sls-setting-label.c-${screen}`).forEach((element) => {
console.log(element)
element.addClass("selected"); element.addClass("selected");
(element.querySelector("input[type=radio]") as HTMLInputElement).checked = true; (element.querySelector("input[type=radio]") as HTMLInputElement).checked = true;
}); });
@@ -381,15 +396,15 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}) })
) )
.addButton((button) => .addButton((button) =>
button button
.setButtonText("Apply w/o rebuilding") .setButtonText("Apply w/o rebuilding")
.setWarning() .setWarning()
.setDisabled(false) .setDisabled(false)
.setClass("sls-btn-right") .setClass("sls-btn-right")
.onClick(async () => { .onClick(async () => {
await applyEncryption(false); await applyEncryption(false);
}) })
); );
const rebuildDB = async (method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice") => { const rebuildDB = async (method: "localOnly" | "remoteOnly" | "rebuildBothByThisDevice") => {
@@ -476,23 +491,10 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
.onClick(async () => { .onClick(async () => {
const checkConfig = async () => { const checkConfig = async () => {
try { try {
const requestToCouchDB = async (baseUri: string, username: string, password: string, origin: string, key?: string, body?: string) => { if (isCloudantURI(this.plugin.settings.couchDB_URI)) {
const utf8str = String.fromCharCode.apply(null, new TextEncoder().encode(`${username}:${password}`)); Logger("This feature cannot be used with IBM Cloudant.", LOG_LEVEL.NOTICE);
const encoded = window.btoa(utf8str); return;
const authHeader = "Basic " + encoded; }
// const origin = "capacitor://localhost";
const transformedHeaders: Record<string, string> = { authorization: authHeader, origin: origin };
const uri = `${baseUri}/_node/_local/_config${key ? "/" + key : ""}`;
const requestParam: RequestUrlParam = {
url: uri,
method: body ? "PUT" : "GET",
headers: transformedHeaders,
contentType: "application/json",
body: body ? JSON.stringify(body) : undefined,
};
return await requestUrl(requestParam);
};
const r = await requestToCouchDB(this.plugin.settings.couchDB_URI, this.plugin.settings.couchDB_USER, this.plugin.settings.couchDB_PASSWORD, window.origin); const r = await requestToCouchDB(this.plugin.settings.couchDB_URI, this.plugin.settings.couchDB_USER, this.plugin.settings.couchDB_PASSWORD, window.origin);
@@ -575,7 +577,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
addResult("✔ httpd.enable_cors is ok."); addResult("✔ httpd.enable_cors is ok.");
} }
// If the server is not cloudant, configure request size // If the server is not cloudant, configure request size
if (!this.plugin.settings.couchDB_URI.contains(".cloudantnosqldb.")) { if (!isCloudantURI(this.plugin.settings.couchDB_URI)) {
// REQUEST SIZE // REQUEST SIZE
if (Number(responseConfig?.chttpd?.max_http_request_size ?? 0) < 4294967296) { if (Number(responseConfig?.chttpd?.max_http_request_size ?? 0) < 4294967296) {
addResult("❗ chttpd.max_http_request_size is low)"); addResult("❗ chttpd.max_http_request_size is low)");
@@ -639,7 +641,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
addResult("--Done--", ["ob-btn-config-head"]); addResult("--Done--", ["ob-btn-config-head"]);
addResult("If you have some trouble with Connection-check even though all Config-check has been passed, Please check your reverse proxy's configuration.", ["ob-btn-config-info"]); addResult("If you have some trouble with Connection-check even though all Config-check has been passed, Please check your reverse proxy's configuration.", ["ob-btn-config-info"]);
} catch (ex) { } catch (ex) {
Logger(`Checking configuration failed`); Logger(`Checking configuration failed`, LOG_LEVEL.NOTICE);
Logger(ex); Logger(ex);
} }
}; };
@@ -677,7 +679,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
if (!this.plugin.settings.encrypt) { if (!this.plugin.settings.encrypt) {
this.plugin.settings.passphrase = ""; this.plugin.settings.passphrase = "";
} }
if (this.plugin.settings.couchDB_URI.contains(".cloudantnosqldb.")) { if (isCloudantURI(this.plugin.settings.couchDB_URI)) {
this.plugin.settings.customChunkSize = 0; this.plugin.settings.customChunkSize = 0;
} else { } else {
this.plugin.settings.customChunkSize = 100; this.plugin.settings.customChunkSize = 100;
@@ -698,7 +700,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
if (!this.plugin.settings.encrypt) { if (!this.plugin.settings.encrypt) {
this.plugin.settings.passphrase = ""; this.plugin.settings.passphrase = "";
} }
if (this.plugin.settings.couchDB_URI.contains(".cloudantnosqldb.")) { if (isCloudantURI(this.plugin.settings.couchDB_URI)) {
this.plugin.settings.customChunkSize = 0; this.plugin.settings.customChunkSize = 0;
} else { } else {
this.plugin.settings.customChunkSize = 100; this.plugin.settings.customChunkSize = 100;
@@ -811,6 +813,24 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}) })
} }
); );
new Setting(containerGeneralSettingsEl)
.setName("Delete old metadata of deleted files on start-up")
.setClass("wizardHidden")
.setDesc("(Days passed, 0 to disable automatic-deletion)")
.addText((text) => {
text.setPlaceholder("")
.setValue(this.plugin.settings.automaticallyDeleteMetadataOfDeletedFiles + "")
.onChange(async (value) => {
let v = Number(value);
if (isNaN(v)) {
v = 0;
}
this.plugin.settings.automaticallyDeleteMetadataOfDeletedFiles = v;
await this.plugin.saveSettings();
});
text.inputEl.setAttribute("type", "number");
});
addScreenElement("20", containerGeneralSettingsEl); addScreenElement("20", containerGeneralSettingsEl);
const containerSyncSettingEl = containerEl.createDiv(); const containerSyncSettingEl = containerEl.createDiv();
@@ -954,6 +974,24 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
await this.plugin.saveSettings(); await this.plugin.saveSettings();
}) })
); );
new Setting(containerSyncSettingEl)
.setName("Disable sensible auto merging on markdown files")
.setDesc("If this switch is turned on, a merge dialog will be displayed, even if the sensible-merge is possible automatically. (Turn on to previous behavior)")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.disableMarkdownAutoMerge).onChange(async (value) => {
this.plugin.settings.disableMarkdownAutoMerge = value;
await this.plugin.saveSettings();
})
);
new Setting(containerSyncSettingEl)
.setName("Write documents after synchronization even if they have conflict")
.setDesc("Turn on to previous behavior")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.writeDocumentsIfConflicted).onChange(async (value) => {
this.plugin.settings.writeDocumentsIfConflicted = value;
await this.plugin.saveSettings();
})
);
new Setting(containerSyncSettingEl) new Setting(containerSyncSettingEl)
@@ -964,8 +1002,17 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
await this.plugin.saveSettings(); await this.plugin.saveSettings();
}) })
); );
new Setting(containerSyncSettingEl)
.setName("Monitor changes to internal files")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.watchInternalFileChanges).onChange(async (value) => {
this.plugin.settings.watchInternalFileChanges = value;
await this.plugin.saveSettings();
})
);
new Setting(containerSyncSettingEl) new Setting(containerSyncSettingEl)
.setName("Scan for hidden files before replication") .setName("Scan for hidden files before replication")
.setDesc("This configuration will be ignored if monitoring changes is enabled.")
.addToggle((toggle) => .addToggle((toggle) =>
toggle.setValue(this.plugin.settings.syncInternalFilesBeforeReplication).onChange(async (value) => { toggle.setValue(this.plugin.settings.syncInternalFilesBeforeReplication).onChange(async (value) => {
this.plugin.settings.syncInternalFilesBeforeReplication = value; this.plugin.settings.syncInternalFilesBeforeReplication = value;
@@ -974,7 +1021,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
); );
new Setting(containerSyncSettingEl) new Setting(containerSyncSettingEl)
.setName("Scan hidden files periodically") .setName("Scan hidden files periodically")
.setDesc("Seconds, 0 to disable.") .setDesc("Seconds, 0 to disable. This configuration will be ignored if monitoring changes is enabled.")
.addText((text) => { .addText((text) => {
text.setPlaceholder("") text.setPlaceholder("")
.setValue(this.plugin.settings.syncInternalFilesInterval + "") .setValue(this.plugin.settings.syncInternalFilesInterval + "")
@@ -990,7 +1037,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}); });
let skipPatternTextArea: TextAreaComponent = null; let skipPatternTextArea: TextAreaComponent = null;
const defaultSkipPattern = "\\/node_modules\\/, \\/\\.git\\/, \\/obsidian-livesync\\/"; const defaultSkipPattern = "\\/node_modules\\/, \\/\\.git\\/, \\/obsidian-livesync\\/";
const defaultSkipPatternXPlat = defaultSkipPattern + ",\\/workspace$"; const defaultSkipPatternXPlat = defaultSkipPattern + ",\\/workspace$ ,\\/workspace.json$";
new Setting(containerSyncSettingEl) new Setting(containerSyncSettingEl)
.setName("Skip patterns") .setName("Skip patterns")
.setDesc( .setDesc(
@@ -1009,7 +1056,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
} }
); );
new Setting(containerSyncSettingEl) new Setting(containerSyncSettingEl)
.setName("Skip patterns defaults") .setName("Restore the skip pattern to default")
.addButton((button) => { .addButton((button) => {
button.setButtonText("Default") button.setButtonText("Default")
.onClick(async () => { .onClick(async () => {
@@ -1256,6 +1303,49 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
containerHatchEl.createEl("h3", { text: "Hatch" }); containerHatchEl.createEl("h3", { text: "Hatch" });
new Setting(containerHatchEl)
.setName("Make report to inform the issue")
.addButton((button) =>
button
.setButtonText("Make report")
.setDisabled(false)
.onClick(async () => {
let responseConfig: any = {};
const REDACTED = "𝑅𝐸𝐷𝐴𝐶𝑇𝐸𝐷";
try {
const r = await requestToCouchDB(this.plugin.settings.couchDB_URI, this.plugin.settings.couchDB_USER, this.plugin.settings.couchDB_PASSWORD, window.origin);
Logger(JSON.stringify(r.json, null, 2));
responseConfig = r.json;
responseConfig["couch_httpd_auth"].secret = REDACTED;
responseConfig["couch_httpd_auth"].authentication_db = REDACTED;
responseConfig["couch_httpd_auth"].authentication_redirect = REDACTED;
responseConfig["couchdb"].uuid = REDACTED;
responseConfig["admins"] = REDACTED;
} catch (ex) {
responseConfig = "Requesting information to the remote CouchDB has been failed. If you are using IBM Cloudant, it is the normal behaviour."
}
const pluginConfig = JSON.parse(JSON.stringify(this.plugin.settings)) as ObsidianLiveSyncSettings;
pluginConfig.couchDB_DBNAME = REDACTED;
pluginConfig.couchDB_PASSWORD = REDACTED;
pluginConfig.couchDB_URI = isCloudantURI(pluginConfig.couchDB_URI) ? "cloudant" : "self-hosted";
pluginConfig.couchDB_USER = REDACTED;
pluginConfig.passphrase = REDACTED;
pluginConfig.workingPassphrase = REDACTED;
const msgConfig = `----remote config----
${stringifyYaml(responseConfig)}
---- Plug-in config ---
${stringifyYaml(pluginConfig)}`;
console.log(msgConfig);
await navigator.clipboard.writeText(msgConfig);
Logger(`Information has been copied to clipboard`, LOG_LEVEL.NOTICE);
})
);
if (this.plugin.localDatabase.remoteLockedAndDeviceNotAccepted) { if (this.plugin.localDatabase.remoteLockedAndDeviceNotAccepted) {
const c = containerHatchEl.createEl("div", { const c = containerHatchEl.createEl("div", {
text: "To prevent unwanted vault corruption, the remote database has been locked for synchronization, and this device was not marked as 'resolved'. it caused by some operations like this. re-initialized. Local database initialization should be required. please back your vault up, reset local database, and press 'Mark this device as resolved'. ", text: "To prevent unwanted vault corruption, the remote database has been locked for synchronization, and this device was not marked as 'resolved'. it caused by some operations like this. re-initialized. Local database initialization should be required. please back your vault up, reset local database, and press 'Mark this device as resolved'. ",
@@ -1295,21 +1385,28 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
.setDisabled(false) .setDisabled(false)
.setWarning() .setWarning()
.onClick(async () => { .onClick(async () => {
const semaphore = Semaphore(10);
const files = this.app.vault.getFiles(); const files = this.app.vault.getFiles();
Logger("Verify and repair all files started", LOG_LEVEL.NOTICE, "verify");
// const notice = NewNotice("", 0);
let i = 0; let i = 0;
for (const file of files) { const processes = files.map(e => (async (file) => {
i++; const releaser = await semaphore.acquire(1, "verifyAndRepair");
Logger(`Update into ${file.path}`);
Logger(`${i}/${files.length}\n${file.path}`, LOG_LEVEL.NOTICE, "verify");
try { try {
await this.plugin.updateIntoDB(file); Logger(`Update into ${file.path}`);
await this.plugin.updateIntoDB(file, false, null, true);
i++;
Logger(`${i}/${files.length}\n${file.path}`, LOG_LEVEL.NOTICE, "verify");
} catch (ex) { } catch (ex) {
Logger("could not update:"); i++;
Logger(`Error while verifyAndRepair`, LOG_LEVEL.NOTICE);
Logger(ex); Logger(ex);
} finally {
releaser();
} }
} }
)(e));
await Promise.all(processes);
Logger("done", LOG_LEVEL.NOTICE, "verify"); Logger("done", LOG_LEVEL.NOTICE, "verify");
}) })
); );

Submodule src/lib updated: d8d83b7f46...bf8ab8883d

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +1,55 @@
### 0.15.0 ### 0.17.0
- Outdated configuration items have been removed. - 0.17.0 has no surfaced changes but the design of saving chunks has been changed. They have compatibility but changing files after upgrading makes different chunks than before 0.16.x.
- Setup wizard has been implemented! Please rebuild databases once if you have been worried about storage usage.
I appreciate for reviewing and giving me advice @Pouhon158! - Improved:
- Splitting markdown
- Saving chunks
- Changed:
- Chunk ID numbering rules
#### Minors #### Minors
- 0.15.1 Missed the stylesheet. - 0.17.1
- 0.15.2 The wizard has been improved and documented! - Fixed: Now we can verify and repair the database.
- 0.15.3 Fixed the issue about locking/unlocking remote database while rebuilding in the wizard. - Refactored inside.
- 0.15.4 Fixed issues about asynchronous processing (e.g., Conflict check or hidden file detection)
- 0.15.5 Add new features for setting Self-hosted LiveSync up more easier.
### 0.14.1 - 0.17.2
- The target selecting filter was implemented. - New feature
Now we can set what files are synchronised by regular expression. - We can merge conflicted documents automatically if sensible.
- We can configure the size of chunks. - Fixed
We can use larger chunks to improve performance. - Writing to the storage will be pended while they have conflicts after replication.
(This feature can not be used with IBM Cloudant)
- Read chunks online.
Now we can synchronise only metadata and retrieve chunks on demand. It reduces local database size and time for replication.
- Added this note.
- Use local chunks in preference to remote them if present,
#### Recommended configuration for Self-hosted CouchDB ### 0.16.0
- Set chunk size to around 100 to 250 (10MB - 25MB per chunk) - Now hidden files need not be scanned. Changes will be detected automatically.
- *Set batch size to 100 and batch limit to 20 (0.14.2)* - If you want it to back to its previous behaviour, please disable `Monitor changes to internal files`.
- Be sure to `Read chunks online` checked. - Due to using an internal API, this feature may become unusable with a major update. If this happens, please disable this once.
#### Minors #### Minors
- 0.14.2 Fixed issue about retrieving files if synchronisation has been interrupted or failed
- 0.14.3 New test items have been added to `Check database configuration`.
- 0.14.4 Fixed issue of importing configurations.
- 0.14.5 Auto chunk size adjusting implemented.
- 0.14.6 Change Target to ES2018
- 0.14.7 Refactor and fix typos.
- 0.14.8 Refactored again. There should be no change in behaviour, but please let me know if there is any.
... To continue on to `updates_old.md`. - 0.16.1 Added missing log updates.
- 0.16.2 Fixed many problems caused by combinations of `Sync On Save` and the tracking logic that changed at 0.15.6.
- 0.16.3
- Fixed detection of IBM Cloudant (And if there are some issues, be fixed automatically).
- A configuration information reporting tool has been implemented.
- 0.16.4 Fixed detection failure. Please set the `Chunk size` again when using a self-hosted database.
- 0.16.5
- Fixed
- Conflict detection and merging now be able to treat deleted files.
- Logs while the boot-up sequence has been tidied up.
- Fixed incorrect log entries.
- New Feature
- The feature of automatically deleting old expired metadata has been implemented.
We can configure it in `Delete old metadata of deleted files on start-up` in the `General Settings` pane.
- 0.16.6
- Fixed
- Automatic (temporary) batch size adjustment has been restored to work correctly.
- Chunk splitting has been backed to the previous behaviour for saving them correctly.
- Improved
- Corrupted chunks will be detected automatically.
- Now on the case-insensitive system, `aaa.md` and `AAA.md` will be treated as the same file or path at applying changesets.
- 0.16.7 Nothing has been changed except toolsets, framework library, and as like them. Please inform me if something had been getting strange!
- 0.16.8 Now we can synchronise without `bad_request:invalid UTF-8 JSON` even while end-to-end encryption has been disabled.
Note:
Before 0.16.5, LiveSync had some issues making chunks. In this case, synchronisation had became been always failing after a corrupted one should be made. After 0.16.6, the corrupted chunk is automatically detected. Sorry for troubling you but please do `rebuild everything` when this plug-in notified so.

View File

@@ -1,3 +1,28 @@
### 0.14.1
- The target selecting filter was implemented.
Now we can set what files are synchronised by regular expression.
- We can configure the size of chunks.
We can use larger chunks to improve performance.
(This feature can not be used with IBM Cloudant)
- Read chunks online.
Now we can synchronise only metadata and retrieve chunks on demand. It reduces local database size and time for replication.
- Added this note.
- Use local chunks in preference to remote them if present,
#### Recommended configuration for Self-hosted CouchDB
- Set chunk size to around 100 to 250 (10MB - 25MB per chunk)
- *Set batch size to 100 and batch limit to 20 (0.14.2)*
- Be sure to `Read chunks online` checked.
#### Minors
- 0.14.2 Fixed issue about retrieving files if synchronisation has been interrupted or failed
- 0.14.3 New test items have been added to `Check database configuration`.
- 0.14.4 Fixed issue of importing configurations.
- 0.14.5 Auto chunk size adjusting implemented.
- 0.14.6 Change Target to ES2018
- 0.14.7 Refactor and fix typos.
- 0.14.8 Refactored again. There should be no change in behaviour, but please let me know if there is any.
### 0.13.0 ### 0.13.0
- The metadata of the deleted files will be kept on the database by default. If you want to delete this as the previous version, please turn on `Delete metadata of deleted files.`. And, if you have upgraded from the older version, please ensure every device has been upgraded. - The metadata of the deleted files will be kept on the database by default. If you want to delete this as the previous version, please turn on `Delete metadata of deleted files.`. And, if you have upgraded from the older version, please ensure every device has been upgraded.