mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-03-17 07:18:47 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a5371cdee | ||
|
|
466bb142e2 | ||
|
|
d394a4ce7f | ||
|
|
71ce76e502 | ||
|
|
ae7a7dd456 | ||
|
|
4048186bb5 | ||
|
|
2b94fd9139 | ||
|
|
ec72ece86d | ||
|
|
e394a994c5 | ||
|
|
aa23b6a39a | ||
|
|
58e328a591 | ||
|
|
1730c39d70 | ||
|
|
dfeac201a2 | ||
|
|
44b022f003 |
@@ -18,7 +18,7 @@ Additionally, it supports peer-to-peer synchronisation using WebRTC now (experim
|
||||
- Use open-source solutions for the server.
|
||||
- Compatible solutions are supported.
|
||||
- Support end-to-end encryption.
|
||||
- Synchronise settings, snippets, themes, and plug-ins via [Customisation Sync (Beta)](#customization-sync) or [Hidden File Sync](#hiddenfilesync).
|
||||
- Synchronise settings, snippets, themes, and plug-ins via [Customisation Sync (Beta)](docs/settings.md#6-customization-sync-advanced) or [Hidden File Sync](docs/settings.md#7-hidden-files-advanced).
|
||||
- Enable WebRTC peer-to-peer synchronisation without requiring a `host` (Experimental).
|
||||
- This feature is still in the experimental stage. Please exercise caution when using it.
|
||||
- WebRTC is a peer-to-peer synchronisation method, so **at least one device must be online to synchronise**.
|
||||
|
||||
@@ -132,6 +132,11 @@ If it results like the following:
|
||||
|
||||
Your CouchDB has been initialised successfully. If you want this manually, please read the script.
|
||||
|
||||
If you are using Docker Compose and the above command does not work or displays `ERROR: Hostname missing`, you can try running the following command, replacing the placeholders with your own values:
|
||||
```
|
||||
curl -s https://raw.githubusercontent.com/vrtmrz/obsidian-livesync/main/utils/couchdb/couchdb-init.sh | hostname=http://<YOUR SERVER IP>:5984 username=<INSERT USERNAME HERE> password=<INSERT PASSWORD HERE> bash
|
||||
```
|
||||
|
||||
## 3. Expose CouchDB to the Internet
|
||||
|
||||
- You can skip this instruction if you using only in intranet and only with desktop devices.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "obsidian-livesync",
|
||||
"name": "Self-hosted LiveSync",
|
||||
"version": "0.25.13",
|
||||
"version": "0.25.17",
|
||||
"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.",
|
||||
"author": "vorotamoroz",
|
||||
|
||||
54
package-lock.json
generated
54
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "obsidian-livesync",
|
||||
"version": "0.25.12",
|
||||
"version": "0.25.17",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "obsidian-livesync",
|
||||
"version": "0.25.12",
|
||||
"version": "0.25.17",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.808.0",
|
||||
@@ -23,7 +23,7 @@
|
||||
"octagonal-wheels": "^0.1.38",
|
||||
"qrcode-generator": "^1.4.4",
|
||||
"svelte-check": "^4.1.7",
|
||||
"trystero": "^0.21.7",
|
||||
"trystero": "github:vrtmrz/trystero#9e892a93ec14eeb57ce806d272fbb7c3935256d8",
|
||||
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -8752,9 +8752,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry/node_modules/lru-cache": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz",
|
||||
"integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==",
|
||||
"version": "11.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.1.tgz",
|
||||
"integrity": "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
@@ -10365,20 +10365,29 @@
|
||||
}
|
||||
},
|
||||
"node_modules/trystero": {
|
||||
"version": "0.21.7",
|
||||
"resolved": "https://registry.npmjs.org/trystero/-/trystero-0.21.7.tgz",
|
||||
"integrity": "sha512-SdpxC9Q29bDBUdIWvkELHvOlmpelHAbjgclXR6cPeUWeLkbyY8ku2ZCJjozO4L2CLOMiclOoMKdmtpYLAwZvIw==",
|
||||
"version": "0.21.8",
|
||||
"resolved": "git+ssh://git@github.com/vrtmrz/trystero.git#9e892a93ec14eeb57ce806d272fbb7c3935256d8",
|
||||
"integrity": "sha512-LUlmTTSxgomyYvU1K05snl18+GLAxqO4W8P9lePLbRnZVJyGZUVXMM4/aW9384GtIf0VLJquloWqz9PriJZg2w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@noble/secp256k1": "^1.7.1",
|
||||
"@noble/secp256k1": "^3.0.0",
|
||||
"@supabase/supabase-js": "^2.49.8",
|
||||
"@waku/discovery": "^0.0.8",
|
||||
"@waku/sdk": "^0.0.31",
|
||||
"firebase": "^12.0.0",
|
||||
"firebase": "^12.2.1",
|
||||
"libp2p": "^2.8.8",
|
||||
"mqtt": "^5.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/trystero/node_modules/@noble/secp256k1": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-3.0.0.tgz",
|
||||
"integrity": "sha512-NJBaR352KyIvj3t6sgT/+7xrNyF9Xk9QlLSIqUGVUYlsnDTAUqY8LOmwpcgEx4AMJXRITQ5XEVHD+mMaPfr3mg==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-api-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.0.1.tgz",
|
||||
@@ -17147,9 +17156,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz",
|
||||
"integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==",
|
||||
"version": "11.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.1.tgz",
|
||||
"integrity": "sha512-r8LA6i4LP4EeWOhqBaZZjDWwehd1xUJPCJd9Sv300H0ZmcUER4+JPh7bqqZeqs1o5pgtgvXm+d9UGrB5zZGDiQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
@@ -18229,17 +18238,24 @@
|
||||
}
|
||||
},
|
||||
"trystero": {
|
||||
"version": "0.21.7",
|
||||
"resolved": "https://registry.npmjs.org/trystero/-/trystero-0.21.7.tgz",
|
||||
"integrity": "sha512-SdpxC9Q29bDBUdIWvkELHvOlmpelHAbjgclXR6cPeUWeLkbyY8ku2ZCJjozO4L2CLOMiclOoMKdmtpYLAwZvIw==",
|
||||
"version": "git+ssh://git@github.com/vrtmrz/trystero.git#9e892a93ec14eeb57ce806d272fbb7c3935256d8",
|
||||
"integrity": "sha512-LUlmTTSxgomyYvU1K05snl18+GLAxqO4W8P9lePLbRnZVJyGZUVXMM4/aW9384GtIf0VLJquloWqz9PriJZg2w==",
|
||||
"from": "trystero@github:vrtmrz/trystero#9e892a93ec14eeb57ce806d272fbb7c3935256d8",
|
||||
"requires": {
|
||||
"@noble/secp256k1": "^1.7.1",
|
||||
"@noble/secp256k1": "^3.0.0",
|
||||
"@supabase/supabase-js": "^2.49.8",
|
||||
"@waku/discovery": "^0.0.8",
|
||||
"@waku/sdk": "^0.0.31",
|
||||
"firebase": "^12.0.0",
|
||||
"firebase": "^12.2.1",
|
||||
"libp2p": "^2.8.8",
|
||||
"mqtt": "^5.13.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@noble/secp256k1": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-3.0.0.tgz",
|
||||
"integrity": "sha512-NJBaR352KyIvj3t6sgT/+7xrNyF9Xk9QlLSIqUGVUYlsnDTAUqY8LOmwpcgEx4AMJXRITQ5XEVHD+mMaPfr3mg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ts-api-utils": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "obsidian-livesync",
|
||||
"version": "0.25.13",
|
||||
"version": "0.25.17",
|
||||
"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",
|
||||
"type": "module",
|
||||
@@ -95,7 +95,7 @@
|
||||
"octagonal-wheels": "^0.1.38",
|
||||
"qrcode-generator": "^1.4.4",
|
||||
"svelte-check": "^4.1.7",
|
||||
"trystero": "^0.21.7",
|
||||
"trystero": "github:vrtmrz/trystero#9e892a93ec14eeb57ce806d272fbb7c3935256d8",
|
||||
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ export const OpenKeyValueDatabase = async (dbKey: string): Promise<KeyValueDatab
|
||||
}
|
||||
const storeKey = dbKey;
|
||||
const dbPromise = openDB(dbKey, 1, {
|
||||
upgrade(db) {
|
||||
db.createObjectStore(storeKey);
|
||||
upgrade(db, _oldVersion, _newVersion, _transaction, _event) {
|
||||
return db.createObjectStore(storeKey);
|
||||
},
|
||||
});
|
||||
const db = await dbPromise;
|
||||
|
||||
@@ -35,7 +35,7 @@ import { promiseWithResolver, type PromiseWithResolvers } from "octagonal-wheels
|
||||
import { AuthorizationHeaderGenerator } from "../lib/src/replication/httplib.ts";
|
||||
import type { KeyValueDatabase } from "../lib/src/interfaces/KeyValueDatabase.ts";
|
||||
|
||||
export { scheduleTask, cancelTask, cancelAllTasks } from "../lib/src/concurrency/task.ts";
|
||||
export { scheduleTask, cancelTask, cancelAllTasks } from "octagonal-wheels/concurrency/task";
|
||||
|
||||
// For backward compatibility, using the path for determining id.
|
||||
// Only CouchDB unacceptable ID (that starts with an underscore) has been prefixed with "/".
|
||||
|
||||
@@ -45,7 +45,7 @@ import {
|
||||
} from "../../lib/src/common/utils.ts";
|
||||
import { digestHash } from "../../lib/src/string_and_binary/hash.ts";
|
||||
import { arrayBufferToBase64, decodeBinary, readString } from "../../lib/src/string_and_binary/convert.ts";
|
||||
import { serialized, shareRunningResult } from "../../lib/src/concurrency/lock.ts";
|
||||
import { serialized, shareRunningResult } from "octagonal-wheels/concurrency/lock";
|
||||
import { LiveSyncCommands } from "../LiveSyncCommands.ts";
|
||||
import { stripAllPrefixes } from "../../lib/src/string_and_binary/path.ts";
|
||||
import {
|
||||
@@ -62,7 +62,7 @@ import {
|
||||
scheduleTask,
|
||||
} from "../../common/utils.ts";
|
||||
import { JsonResolveModal } from "../HiddenFileCommon/JsonResolveModal.ts";
|
||||
import { QueueProcessor } from "../../lib/src/concurrency/processor.ts";
|
||||
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
|
||||
import { pluginScanningCount } from "../../lib/src/mock_and_interop/stores.ts";
|
||||
import type ObsidianLiveSyncPlugin from "../../main.ts";
|
||||
import { base64ToArrayBuffer, base64ToString } from "octagonal-wheels/binary/base64";
|
||||
|
||||
@@ -45,11 +45,11 @@ import {
|
||||
BASE_IS_NEW,
|
||||
EVEN,
|
||||
} from "../../common/utils.ts";
|
||||
import { serialized, skipIfDuplicated } from "../../lib/src/concurrency/lock.ts";
|
||||
import { serialized, skipIfDuplicated } from "octagonal-wheels/concurrency/lock";
|
||||
import { JsonResolveModal } from "../HiddenFileCommon/JsonResolveModal.ts";
|
||||
import { LiveSyncCommands } from "../LiveSyncCommands.ts";
|
||||
import { addPrefix, stripAllPrefixes } from "../../lib/src/string_and_binary/path.ts";
|
||||
import { QueueProcessor } from "../../lib/src/concurrency/processor.ts";
|
||||
import { QueueProcessor } from "octagonal-wheels/concurrency/processor";
|
||||
import { hiddenFilesEventCount, hiddenFilesProcessingCount } from "../../lib/src/mock_and_interop/stores.ts";
|
||||
import type { IObsidianModule } from "../../modules/AbstractObsidianModule.ts";
|
||||
import { EVENT_SETTING_SAVED, eventHub } from "../../common/events.ts";
|
||||
@@ -1765,10 +1765,7 @@ ${messageFetch}${messageOverwrite}${messageMerge}
|
||||
continue L1;
|
||||
}
|
||||
}
|
||||
if (
|
||||
ignoreFilter &&
|
||||
ignoreFilter.some((e) => (e.pattern.startsWith("/") || e.pattern.startsWith("\\/")) && e.test(v))
|
||||
) {
|
||||
if (ignoreFilter && ignoreFilter.some((e) => e.test(v))) {
|
||||
continue L1;
|
||||
}
|
||||
if (await this.plugin.$$isIgnoredByIgnoreFiles(v)) {
|
||||
|
||||
@@ -174,6 +174,13 @@ export class P2PReplicator
|
||||
if (this.settings.P2P_Enabled && this.settings.P2P_AutoStart) {
|
||||
setTimeout(() => void this.open(), 100);
|
||||
}
|
||||
const rep = this._replicatorInstance;
|
||||
rep?.allowReconnection();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
$everyBeforeSuspendProcess(): Promise<boolean> {
|
||||
const rep = this._replicatorInstance;
|
||||
rep?.disconnectFromServer();
|
||||
return Promise.resolve(true);
|
||||
}
|
||||
}
|
||||
|
||||
2
src/lib
2
src/lib
Submodule src/lib updated: f21001fcb2...9f69880ec2
@@ -1,5 +1,5 @@
|
||||
import { type App, TFile, type DataWriteOptions, TFolder, TAbstractFile } from "../../../deps.ts";
|
||||
import { serialized } from "../../../lib/src/concurrency/lock.ts";
|
||||
import { serialized } from "octagonal-wheels/concurrency/lock";
|
||||
import { Logger } from "../../../lib/src/common/logger.ts";
|
||||
import { isPlainText } from "../../../lib/src/string_and_binary/path.ts";
|
||||
import type { FilePath, HasSettings, UXFileInfoStub } from "../../../lib/src/common/types.ts";
|
||||
|
||||
@@ -14,14 +14,14 @@ import {
|
||||
} from "../../../lib/src/common/types.ts";
|
||||
import { delay, fireAndForget, getFileRegExp } from "../../../lib/src/common/utils.ts";
|
||||
import { type FileEventItem, type FileEventType } from "../../../common/types.ts";
|
||||
import { serialized, skipIfDuplicated } from "../../../lib/src/concurrency/lock.ts";
|
||||
import { serialized, skipIfDuplicated } from "octagonal-wheels/concurrency/lock";
|
||||
import {
|
||||
finishAllWaitingForTimeout,
|
||||
finishWaitingForTimeout,
|
||||
isWaitingForTimeout,
|
||||
waitForTimeout,
|
||||
} from "../../../lib/src/concurrency/task.ts";
|
||||
import { Semaphore } from "../../../lib/src/concurrency/semaphore.ts";
|
||||
} from "octagonal-wheels/concurrency/task";
|
||||
import { Semaphore } from "octagonal-wheels/concurrency/semaphore";
|
||||
import type { LiveSyncCore } from "../../../main.ts";
|
||||
import { InternalFileToUXFileInfoStub, TFileToUXFileInfoStub } from "./utilObsidian.ts";
|
||||
import ObsidianLiveSyncPlugin from "../../../main.ts";
|
||||
@@ -207,6 +207,9 @@ export class StorageEventManagerObsidian extends StorageEventManager {
|
||||
}
|
||||
}
|
||||
if (file instanceof TFolder) continue;
|
||||
// TODO: Confirm why only the TFolder skipping
|
||||
// Possibly following line is needed...
|
||||
// if (file?.isFolder) continue;
|
||||
if (!(await this.core.$$isTargetFile(file.path))) continue;
|
||||
|
||||
// Stop cache using to prevent the corruption;
|
||||
|
||||
@@ -17,6 +17,15 @@ import { isMetaEntry } from "../../lib/src/common/types.ts";
|
||||
import { isDeletedEntry, isDocContentSame, isLoadedEntry, readAsBlob } from "../../lib/src/common/utils.ts";
|
||||
import { countCompromisedChunks } from "../../lib/src/pouchdb/negotiation.ts";
|
||||
|
||||
type ErrorInfo = {
|
||||
path: string;
|
||||
recordedSize: number;
|
||||
actualSize: number;
|
||||
storageSize: number;
|
||||
contentMatched: boolean;
|
||||
isConflicted?: boolean;
|
||||
};
|
||||
|
||||
export class ModuleMigration extends AbstractModule implements ICoreModule {
|
||||
async migrateUsingDoctor(skipRebuild: boolean = false, activateReason = "updated", forceRescan = false) {
|
||||
const { shouldRebuild, shouldRebuildLocal, isModified, settings } = await performDoctorConsultation(
|
||||
@@ -112,7 +121,8 @@ export class ModuleMigration extends AbstractModule implements ICoreModule {
|
||||
}
|
||||
|
||||
this._log("Checking for incomplete documents...", LOG_LEVEL_NOTICE, "check-incomplete");
|
||||
const errorFiles = [];
|
||||
|
||||
const errorFiles = [] as ErrorInfo[];
|
||||
for await (const metaDoc of this.localDatabase.findAllNormalDocs({ conflicts: true })) {
|
||||
const path = getPath(metaDoc);
|
||||
|
||||
@@ -133,17 +143,38 @@ export class ModuleMigration extends AbstractModule implements ICoreModule {
|
||||
if (isDeletedEntry(doc)) {
|
||||
continue;
|
||||
}
|
||||
const storageFileContent = await this.core.storageAccess.readHiddenFileBinary(path);
|
||||
const isConflicted = metaDoc?._conflicts && metaDoc._conflicts.length > 0;
|
||||
|
||||
let storageFileContent;
|
||||
try {
|
||||
storageFileContent = await this.core.storageAccess.readHiddenFileBinary(path);
|
||||
} catch (e) {
|
||||
Logger(`Failed to read file ${path}: Possibly unprocessed or missing`);
|
||||
Logger(e, LOG_LEVEL_VERBOSE);
|
||||
continue;
|
||||
}
|
||||
// const storageFileBlob = createBlob(storageFileContent);
|
||||
const sizeOnStorage = storageFileContent.byteLength;
|
||||
const recordedSize = doc.size;
|
||||
const docBlob = readAsBlob(doc);
|
||||
const actualSize = docBlob.size;
|
||||
if (recordedSize !== actualSize || sizeOnStorage !== actualSize || sizeOnStorage !== recordedSize) {
|
||||
if (
|
||||
recordedSize !== actualSize ||
|
||||
sizeOnStorage !== actualSize ||
|
||||
sizeOnStorage !== recordedSize ||
|
||||
isConflicted
|
||||
) {
|
||||
const contentMatched = await isDocContentSame(doc.data, storageFileContent);
|
||||
errorFiles.push({ path, recordedSize, actualSize, storageSize: sizeOnStorage, contentMatched });
|
||||
errorFiles.push({
|
||||
path,
|
||||
recordedSize,
|
||||
actualSize,
|
||||
storageSize: sizeOnStorage,
|
||||
contentMatched,
|
||||
isConflicted,
|
||||
});
|
||||
Logger(
|
||||
`Size mismatch for ${path}: ${recordedSize} (DB Recorded) , ${actualSize} (DB Stored) , ${sizeOnStorage} (Storage Stored), ${contentMatched ? "Content Matched" : "Content Mismatched"}`
|
||||
`Size mismatch for ${path}: ${recordedSize} (DB Recorded) , ${actualSize} (DB Stored) , ${sizeOnStorage} (Storage Stored), ${contentMatched ? "Content Matched" : "Content Mismatched"} ${isConflicted ? "Conflicted" : "Not Conflicted"}`
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -167,24 +198,23 @@ export class ModuleMigration extends AbstractModule implements ICoreModule {
|
||||
// Probably restored by the user by resolving A or B on other device, We should overwrite the storage
|
||||
// Also do not fix it automatically. It should be overwritten by replication.
|
||||
const recoverable = errorFiles.filter((e) => {
|
||||
return e.recordedSize === e.storageSize;
|
||||
return e.recordedSize === e.storageSize && !e.isConflicted;
|
||||
});
|
||||
const unrecoverable = errorFiles.filter((e) => {
|
||||
return e.recordedSize !== e.storageSize;
|
||||
return e.recordedSize !== e.storageSize || e.isConflicted;
|
||||
});
|
||||
const fileInfo = (e: (typeof errorFiles)[0]) => {
|
||||
return `${e.path} (M: ${e.recordedSize}, A: ${e.actualSize}, S: ${e.storageSize}) ${e.isConflicted ? "(Conflicted)" : ""}`;
|
||||
};
|
||||
const messageUnrecoverable =
|
||||
unrecoverable.length > 0
|
||||
? $msg("moduleMigration.fix0256.messageUnrecoverable", {
|
||||
filesNotRecoverable: unrecoverable
|
||||
.map((e) => `- ${e.path} (M: ${e.recordedSize}, A: ${e.actualSize}, S: ${e.storageSize})`)
|
||||
.join("\n"),
|
||||
filesNotRecoverable: unrecoverable.map((e) => `- ${fileInfo(e)}`).join("\n"),
|
||||
})
|
||||
: "";
|
||||
|
||||
const message = $msg("moduleMigration.fix0256.message", {
|
||||
files: recoverable
|
||||
.map((e) => `- ${e.path} (M: ${e.recordedSize}, A: ${e.actualSize}, S: ${e.storageSize})`)
|
||||
.join("\n"),
|
||||
files: recoverable.map((e) => `- ${fileInfo(e)}`).join("\n"),
|
||||
messageUnrecoverable,
|
||||
});
|
||||
const CHECK_IT_LATER = $msg("moduleMigration.fix0256.buttons.checkItLater");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { fireAndForget } from "../../../lib/src/common/utils.ts";
|
||||
import { serialized } from "../../../lib/src/concurrency/lock.ts";
|
||||
import { serialized } from "octagonal-wheels/concurrency/lock";
|
||||
import type ObsidianLiveSyncPlugin from "../../../main.ts";
|
||||
|
||||
let plugin: ObsidianLiveSyncPlugin;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ConflictResolveModal } from "./InteractiveConflictResolving/ConflictRes
|
||||
import { AbstractObsidianModule, type IObsidianModule } from "../AbstractObsidianModule.ts";
|
||||
import { displayRev, getPath, getPathWithoutPrefix } from "../../common/utils.ts";
|
||||
import { fireAndForget } from "octagonal-wheels/promises";
|
||||
import { serialized } from "../../lib/src/concurrency/lock.ts";
|
||||
import { serialized } from "octagonal-wheels/concurrency/lock";
|
||||
|
||||
export class ModuleInteractiveConflictResolver extends AbstractObsidianModule implements IObsidianModule {
|
||||
$everyOnloadStart(): Promise<boolean> {
|
||||
|
||||
@@ -370,7 +370,7 @@ export class ModuleLog extends AbstractObsidianModule implements IObsidianModule
|
||||
if (level == LOG_LEVEL_DEBUG && !showDebugLog) {
|
||||
return;
|
||||
}
|
||||
if (level < LOG_LEVEL_INFO && this.settings && this.settings.lessInformationInLog) {
|
||||
if (level <= LOG_LEVEL_INFO && this.settings && this.settings.lessInformationInLog) {
|
||||
return;
|
||||
}
|
||||
if (this.settings && !this.settings.showVerboseLog && level == LOG_LEVEL_VERBOSE) {
|
||||
|
||||
@@ -140,6 +140,7 @@ export class ModuleObsidianSettings extends AbstractObsidianModule implements IO
|
||||
jwtSub: settings.jwtSub,
|
||||
useRequestAPI: settings.useRequestAPI,
|
||||
bucketPrefix: settings.bucketPrefix,
|
||||
forcePathStyle: settings.forcePathStyle,
|
||||
};
|
||||
settings.encryptedCouchDBConnection = await this.encryptConfigurationItem(
|
||||
JSON.stringify(connectionSetting),
|
||||
|
||||
@@ -859,26 +859,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
|
||||
}
|
||||
|
||||
getMinioJournalSyncClient() {
|
||||
const id = this.plugin.settings.accessKey;
|
||||
const key = this.plugin.settings.secretKey;
|
||||
const bucket = this.plugin.settings.bucket;
|
||||
const prefix = this.plugin.settings.bucketPrefix;
|
||||
const region = this.plugin.settings.region;
|
||||
const endpoint = this.plugin.settings.endpoint;
|
||||
const useCustomRequestHandler = this.plugin.settings.useCustomRequestHandler;
|
||||
const customHeaders = this.plugin.settings.bucketCustomHeaders;
|
||||
return new JournalSyncMinio(
|
||||
id,
|
||||
key,
|
||||
endpoint,
|
||||
bucket,
|
||||
prefix,
|
||||
this.plugin.simpleStore,
|
||||
this.plugin,
|
||||
useCustomRequestHandler,
|
||||
region,
|
||||
customHeaders
|
||||
);
|
||||
return new JournalSyncMinio(this.plugin.settings, this.plugin.simpleStore, this.plugin);
|
||||
}
|
||||
async resetRemoteBucket() {
|
||||
const minioJournal = this.getMinioJournalSyncClient();
|
||||
|
||||
@@ -320,6 +320,7 @@ The pane also can be launched by \`P2P Replicator\` command from the Command Pal
|
||||
syncWarnMinio.addClass("op-warn-info");
|
||||
|
||||
new Setting(paneEl).autoWireText("endpoint", { holdValue: true });
|
||||
new Setting(paneEl).autoWireToggle("forcePathStyle", { holdValue: true });
|
||||
new Setting(paneEl).autoWireText("accessKey", { holdValue: true });
|
||||
|
||||
new Setting(paneEl).autoWireText("secretKey", {
|
||||
|
||||
95
updates.md
95
updates.md
@@ -1,8 +1,52 @@
|
||||
## 0.25.17
|
||||
|
||||
16th September, 2025
|
||||
|
||||
### Fixed
|
||||
|
||||
- No longer information-level logs have produced during toggling `Show only notifications` in the settings (#708).
|
||||
- Ignoring filters for Hidden file sync now works correctly (#709).
|
||||
|
||||
### Refactored
|
||||
|
||||
- Removed some unnecessary intermediate files.
|
||||
|
||||
## 0.25.16
|
||||
|
||||
4th September, 2025
|
||||
|
||||
### Improved
|
||||
|
||||
- Improved connectivity for P2P connections
|
||||
- The connection to the signalling server can now be disconnected while in the background or when explicitly disconnected.
|
||||
- These features use a patch that has not been incorporated upstream.
|
||||
- This patch is available at [vrtmrz/trystero](https://github.com/vrtmrz/trystero).
|
||||
|
||||
## 0.25.15
|
||||
|
||||
3rd September, 2025
|
||||
|
||||
### Improved
|
||||
|
||||
- Now we can configure `forcePathStyle` for bucket synchronisation (#707).
|
||||
|
||||
## 0.25.14
|
||||
|
||||
2nd September, 2025
|
||||
|
||||
### Fixed
|
||||
|
||||
- Opening IndexedDB handling has been ensured.
|
||||
- Migration check of corrupted files detection has been fixed.
|
||||
- Now informs us about conflicted files as non-recoverable, but noted so.
|
||||
- No longer errors on not-found files.
|
||||
|
||||
## 0.25.13
|
||||
|
||||
1st September, 2025
|
||||
|
||||
### Fixed
|
||||
|
||||
- Conflict resolving dialogue now properly displays the changeset name instead of A or B (#691).
|
||||
|
||||
## 0.25.12
|
||||
@@ -23,57 +67,6 @@
|
||||
- No errors are shown during synchronisations in offline (if not explicitly requested) (#699).
|
||||
- Missing some checking during automatic-synchronisation now works correctly.
|
||||
|
||||
## 0.25.10
|
||||
|
||||
26th August, 2025
|
||||
|
||||
### New experimental feature
|
||||
|
||||
- We can perform Garbage Collection (Beta2) without rebuilding the entire database, and also fetch the database.
|
||||
- Note that this feature is very experimental and should be used with caution.
|
||||
- This feature requires disabling `Fetch chunks on demand`.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Resetting the bucket now properly clears all uploaded files.
|
||||
|
||||
### Refactored
|
||||
|
||||
- Some files have been moved to better reflect their purpose and improve maintainability.
|
||||
- The extensive LiveSyncLocalDB has been split into separate files for each role.
|
||||
|
||||
## 0.25.9
|
||||
|
||||
20th August, 2025
|
||||
|
||||
### Fixed
|
||||
|
||||
- CORS Checking messages now use replacements.
|
||||
- Configuring CORS setting via the UI now respects the existing rules.
|
||||
- Now startup-checking works correctly again, performs migration check serially and then it will also fix starting LiveSync or start-up sync. (#696)
|
||||
- Statusline in editor now supported 'Bases'.
|
||||
|
||||
## 0.25.8
|
||||
|
||||
18th August, 2025
|
||||
|
||||
### New feature
|
||||
|
||||
- Insecure chunk detection has been implemented.
|
||||
- A notification dialogue will be shown if any insecure chunks are detected; these may have been created by v0.25.6 due to its issue. If this dialogue appears, please ensure you rebuild the database after backing it up.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Unexpected `Failed to obtain PBKDF2 salt` or similar errors during bucket-synchronisation no longer occur.
|
||||
- Unexpected long delays for chunk-missing documents when using bucket-synchronisation have been resolved.
|
||||
- Fetched remote chunks are now properly stored in the local database if `Fetch chunks on demand` is enabled.
|
||||
- The 'fetch' dialogue's message has been refined.
|
||||
- No longer overwriting any corrupted documents to the storage on boot-sequence.
|
||||
|
||||
### Refactored
|
||||
|
||||
- Type errors have been corrected.
|
||||
|
||||
## 0.25.0
|
||||
|
||||
19th July, 2025 (beta1 in 0.25.0-beta1, 13th July, 2025)
|
||||
|
||||
@@ -11,6 +11,56 @@ As a result, this is the first time in a while that forward compatibility has be
|
||||
|
||||
---
|
||||
|
||||
## 0.25.10
|
||||
|
||||
26th August, 2025
|
||||
|
||||
### New experimental feature
|
||||
|
||||
- We can perform Garbage Collection (Beta2) without rebuilding the entire database, and also fetch the database.
|
||||
- Note that this feature is very experimental and should be used with caution.
|
||||
- This feature requires disabling `Fetch chunks on demand`.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Resetting the bucket now properly clears all uploaded files.
|
||||
|
||||
### Refactored
|
||||
|
||||
- Some files have been moved to better reflect their purpose and improve maintainability.
|
||||
- The extensive LiveSyncLocalDB has been split into separate files for each role.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Unexpected `Failed to obtain PBKDF2 salt` or similar errors during bucket-synchronisation no longer occur.
|
||||
- Unexpected long delays for chunk-missing documents when using bucket-synchronisation have been resolved.
|
||||
- Fetched remote chunks are now properly stored in the local database if `Fetch chunks on demand` is enabled.
|
||||
- The 'fetch' dialogue's message has been refined.
|
||||
- No longer overwriting any corrupted documents to the storage on boot-sequence.
|
||||
|
||||
### Refactored
|
||||
|
||||
- Type errors have been corrected.
|
||||
|
||||
## 0.25.9
|
||||
|
||||
20th August, 2025
|
||||
|
||||
### Fixed
|
||||
|
||||
- CORS Checking messages now use replacements.
|
||||
- Configuring CORS setting via the UI now respects the existing rules.
|
||||
- Now startup-checking works correctly again, performs migration check serially and then it will also fix starting LiveSync or start-up sync. (#696)
|
||||
- Statusline in editor now supported 'Bases'.
|
||||
|
||||
## 0.25.8
|
||||
|
||||
18th August, 2025
|
||||
|
||||
### New feature
|
||||
|
||||
- Insecure chunk detection has been implemented.
|
||||
- A notification dialogue will be shown if any insecure chunks are detected; these may have been created by v0.25.6 due to its issue. If this dialogue appears, please ensure you rebuild the database after backing it up.
|
||||
|
||||
## 0.25.7
|
||||
|
||||
|
||||
Reference in New Issue
Block a user