improved grammar & fixed typos in docs and plugin texts

This commit is contained in:
Miigon
2022-08-04 14:34:45 +08:00
committed by GitHub
parent f0ffb0620e
commit 63abeb7f6b
6 changed files with 86 additions and 87 deletions

111
README.md
View File

@@ -3,32 +3,32 @@
[Japanese docs](./README_ja.md).
Self-hosted LiveSync is a community implemented synchronization plugin.
It uses Self-hosted or you procured CouchDB as the server. Available on every obsidian installed devices.
A purchased or self-hosted CouchDB acts as the intermediate server. Available on every obsidian-compatible platform.
Note: It has no compatibilities with official "Sync".
Note: It has no compatibility with the official "Obsidian Sync".
![obsidian_live_sync_demo](https://user-images.githubusercontent.com/45774780/137355323-f57a8b09-abf2-4501-836c-8cb7d2ff24a3.gif)
If you install or upgrade LiveSync, please back your vault up.
Before installing or upgrading LiveSync, please back your vault up.
## Features
- Visual conflict resolver included.
- Synchronize with other devices bidirectionally near-real-time
- Bidirectional synchronization between devices nearly in real-time
- You can use CouchDB or its compatibles like IBM Cloudant.
- End-to-End encryption.
- End-to-End encryption supported.
- Plugin synchronization(Beta)
- Receive WebClip from [obsidian-livesync-webclip](https://chrome.google.com/webstore/detail/obsidian-livesync-webclip/jfpaflmpckblieefkegjncjoceapakdf) (End-to-End encryption will not be applicable.)
It must be useful for the Researcher, Engineer, Developer who has to keep NDA or something like agreement. Especially, in some companies, people have to store all data to their fully controlled host, even End-to-End encryption applied.
Useful for researchers, engineers and developers with a need to keep their notes fully self-hosted for security reasons. Or just anyone who would like the peace of mind knowing that their notes are fully private.
## IMPORTANT NOTICE
- Do not use with other synchronize solutions. Before enabling this plugin, make sure to disable other synchronize solutions, to avoid content corruption or duplication. If you want to synchronize to both backend, sync one by one, please.
This includes making your vault on the cloud-controlled folder(e.g., Inside the iCloud folder).
- This is the synchronization plugin. Not backup solutions. Do not rely on this for backup.
- When the device's storage has been run out, Database corruption may happen.
- When editing hidden files or any other invisible files from obsidian, the file wouldn't be kept in the database. (**Or be deleted.**)
- Do not use in conjunction with another synchronization solution (including iCloud, Obsidian Sync). Before enabling this plugin, make sure to disable all the other synchronization methods to avoid content corruption or duplication. If you want to synchronize to two or more services, do them one by one and never enable two synchronization methods at the same time.
This includes not putting your vault inside a cloud-synchronized folder (eg. an iCloud folder or Dropbox folder)
- This is a synchronization plugin. Not a backup solutions. Do not rely on this for backup.
- If the device's storage runs out, database corruption may happen.
- Hidden files or any other invisible files wouldn't be kept in the database, thus won't be synchronized. (**and may also get deleted**)
## How to use
@@ -38,58 +38,57 @@ First, get your database ready. IBM Cloudant is preferred for testing. Or you ca
1. [Setup IBM Cloudant](docs/setup_cloudant.md)
2. [Setup your CouchDB](docs/setup_own_server.md)
Note: Information about hosting service wanted! Currently, [Using fly.io](https://github.com/vrtmrz/obsidian-livesync/discussions/85) is on the table.
Note: More information about alternative hosting methods needed! Currently, [using fly.io](https://github.com/vrtmrz/obsidian-livesync/discussions/85) is being discussed.
### First device
1. Install the plugin on your device.
2. Configure with the remote database.
2. Configure remote database infomation.
1. Fill your server's information into the `Remote Database configuration` pane.
2. Enabling `End to End Encryption` is recommended. After inputting the passphrase, you have to press `Just apply`.
3. Hit `Test Database Connection` and make sure that the plugin says `Connected`.
4. Hit `Check database configuration` and make sure all tests have been passed.
3. Configure how to synchronize on `Sync setting`. (You can leave these configures later)
2. Enabling `End to End Encryption` is recommended. After entering a passphrase, click `Apply`.
3. Click `Test Database Connection` and make sure that the plugin says `Connected to (your-database-name)`.
4. Click `Check database configuration` and make sure all tests have passed.
3. Configure when should the synchronization happen in `Sync Settings` tab. (You can also leave them for later)
1. If you want to synchronize in real-time, enable `LiveSync`.
2. Or, set up the synchronization as you like.
3. Additional configuration is also here. I recommend enabling `Use Trash for deleted files, but you can leave all configurations disabled.
2. Or, set up the synchronization as you like. By default, none of the settings are enabled, meaning you would need to manually trigger the synchronization process.
3. Additional configurations are also here. I recommend enabling `Use Trash for deleted files`, but you can also leave all configurations as-is.
4. Configure miscellaneous features.
1. Enabling `Show staus inside editor` bring you information. While edit mode, you can see the status on the top-right of the editor. (Recommended)
5. Back to the editor. I hope that initial scan is in the progress or done.
6. When status became stabilized (All ⏳ and 🧩 have been disappeared), you are ready to synchronize with the server.
7. Press the replicate icon on the Ribbon or run `Replicate now` from the Command pallet. You'll send all your data to the server.
8. Open the command palette, `Copy setup URI`, and set the passphrase to encrypt the information. Then your configuration will be copied to the clipboard. Please share copied URI with your other devices.
**IMPORTANT NOTICE: BE CAREFUL TO TREAT THIS URI. THE URI CONTAINS YOUR CREDENTIALS EVEN THOUGH NOBODY COULD READ WITHOUT THE PASSPHRASE.**
1. Enabling `Show staus inside editor` shows status at the top-right corner of the editor while in editing mode. (Recommended)
5. Go back to the editor. Wait for the initial scan to complete.
6. When the status no longer changes and shows a ⏹️ for COMPLETED (No ⏳ and 🧩 icons), you are ready to synchronize with the server.
7. Press the replicate icon on the Ribbon or run `Replicate now` from the command palette. This will send all your data to the server.
8. Open command palette, run `Copy setup URI`, and set a passphrase. This will export your configuration to clipboard as a link for you to import into your other devices.
**IMPORTANT: BE CAREFUL NOT TO SHARE THIS LINK. THE URI CONTAINS ALL YOUR CREDENTIALS.** (even though nobody could read them without the passphrase)
### Subsequent Devices
<!-- what does this line mean? what is a timestamp? could this be too much unnecessary technical details? -->
Strongly recommend using the vault in which all files are completely synchronized including timestamps. Otherwise, some files will be corrupted if failed to resolve conflicts. To simplify, I recommend using a new empty vault.
1. Install the plug-in.
2. Open the link that you had been copied to the other device.
3. The plug-in asks you that are you sure to apply the configurations. Please answer `Yes` and the following instruction below:
2. Open the link that you have exported from the first device.
3. The plug-in will ask you whether you are sure to apply the configurations. Answer `Yes`, then follow these instructions:
1. Answer `Yes` to `Keep local DB?`.
*Note: If you started with existed vault, you have to answer `No`. And `No` to `Rebuild the database?`.*
*Note: If you start with an existing vault, you have to answer `No` to this question and also answer `No` to `Rebuild the database?`.*
2. Answer `Yes` to `Keep remote DB?`.
3. Answer `Yes` to `Replicate once?`.
Yes, you have to answer `Yes` to everything.
Then, all your settings are copied from the first device.
4. Your notes will arrive soon.
Then, all your settings should be successfully imported from the first device.
4. Your notes should get synchronized soon.
## Something looks corrupted...
Please open the link again and Answer as below:
- If your local database looks corrupted
(in other words, when your Obsidian getting weird even standalone.)
Please open the configuration link again and Answer as below:
- If your local database looks corrupted (in other words, when your Obsidian getting weird even standalone.)
- Answer `No` to `Keep local DB?`
- If your remote database looks corrupted
(in other words, when something happens while replicating)
- If your remote database looks corrupted (in other words, when something happens while replicating)
- Answer `No` to `Keep remote DB?`
If you answered `No` to both, your databases will be rebuilt by the content on your device. And the remote database will lock out other devices. You have to synchronize all your devices again. (When this time, almost all your files should be synchronized including a timestamp. So you can use the existed vault).
If you answered `No` to both, your databases will be rebuilt by the content on your device. And the remote database will lock out other devices. You have to synchronize all your devices again. (When this time, almost all your files should be synchronized with a timestamp. So you can use a existed vault).
## Test Server
Setting up an instance of Cloudant or local CouchDB is a little complicated, so I made the [Tasting server of self-hosted-livesync](https://olstaste.vrtmrz.net/) up. Try free!
Setting up an instance of Cloudant or local CouchDB is a little complicated, so I set up a [Tasting server for self-hosted-livesync](https://olstaste.vrtmrz.net/). Try it out for free!
Note: Please read "Limitations" carefully. Do not send your private vault.
## Information in StatusBar
@@ -98,33 +97,33 @@ Synchronization status is shown in statusbar.
- Status
- ⏹️ Stopped
- 💤 LiveSync is enabled. Waiting for changes.
- ⚡️ Synchronize is now in progress.
-Error occurred.
- ↑ Uploaded pieces
- 💤 LiveSync enabled. Waiting for changes.
- ⚡️ Synchronization in progress.
-An error occurred.
- ↑ Uploaded pieces <!-- is a "piece" the same thing as a "chunk"? -->
- ↓ Downloaded pieces
- ⏳ Number of the pending processes
- 🧩 Number of the files that waiting for their chunks.
If you have deleted or renamed files, please wait until ⏳ disappeared.
- ⏳ Number of pending processes
- 🧩 Number of files waiting for their chunks.
If you have deleted or renamed files, please wait until ⏳ icon disappeared.
## Hints
- When the folder became empty by replication, The folder will be deleted in the default setting. But you can change this behaivour. Check the [Settings](docs/settings.md).
- LiveSync mode drains many batteries in mobile devices. Periodic sync and some automatic sync is recommended.
- Mobile Obsidian can not connect to the non-secure(HTTP) or local CA-signed servers, even though the certificate is stored in the device store.
- If a folder becomes empty after a replication, it will be deleted by default. But you can toggle this behaviour. Check the [Settings](docs/settings.md).
- LiveSync mode drains more batteries in mobile devices. Periodic sync with some automatic sync is recommended.
- Mobile Obsidian can not connect to a non-secure (HTTP) or a locally-signed servers, even if the root certificate is installed on the device.
- There are no 'exclude_folders' like configurations.
- When synchronized, files are compared by their modified times and overwritten by the newer ones once. Then plugin checks the conflicts and if a merge is needed, the dialog will open.
- Rarely, the file in the database would be broken. The plugin will not write storage when it looks broken, so some old files must be on your device. If you edit the file, it will be cured. But if the file does not exist on any device, can not rescue it. So you can delete these items from the setting dialog.
- While synchronizing, files are compared by their modification time and the older ones will be overwritten by the newer ones. Then plugin checks for conflicts and if a merge is needed, a dialog will open.
- Rarely, a file in the database could be corrupted. The plugin will not write to local storage when a file looks corrupted. If a local version of the file is on your device, the corruption could be fixed by editing the local file and synchronizing it. But if the file does not exist on any of your devices, then it can not be rescued. In this case you can delete these items from the settings dialog.
- If your database looks corrupted, try "Drop History". Usually, It is the easiest way.
- To stop the bootup sequence for fixing problems on databases, you can put `redflag.md` on top of your vault.
- Q: Database is growing, how can I shrink it up?
A: each of the docs is saved with their old 100 revisions to detect and resolve confliction. Picture yourself that one device has been off the line for a while, and joined again. The device has to check his note and remote saved note. If exists in revision histories of remote notes even though the device's note is a little different from the latest one, it could be merged safely. Even if that is not in revision histories, we only have to check differences after the revision that both devices commonly have. This is like The git's conflict resolving method. So, We have to make the database again like an enlarged git repo if you want to solve the root of the problem.
- To stop the bootup sequence (eg. for fixing problems on databases), you can put a `redflag.md` file at the root of your vault.
- Q: Database is growing, how can I shrink it down?
A: each of the docs is saved with their past 100 revisions for detecting and resolving conflicts. Picturing that one device has been offline for a while, and comes online again. The device has to compare its notes with the remotely saved ones. If there exists a historic revision in which the note used to be identical, it could be updated safely (like git fast-forward). Even if that is not in revision histories, we only have to check the differences after the revision that both devices commonly have. This is like git's conflict resolving method. So, We have to make the database again like an enlarged git repo if you want to solve the root of the problem.
- And more technical Information are in the [Technical Information](docs/tech_info.md)
- If you want to synchronize files without obsidian, you can use [filesystem-livesync](https://github.com/vrtmrz/filesystem-livesync).
- WebClipper is also available.
Available from on Chrome Web Store:[obsidian-livesync-webclip](https://chrome.google.com/webstore/detail/obsidian-livesync-webclip/jfpaflmpckblieefkegjncjoceapakdf)
- WebClipper is also available on Chrome Web Store:[obsidian-livesync-webclip](https://chrome.google.com/webstore/detail/obsidian-livesync-webclip/jfpaflmpckblieefkegjncjoceapakdf)
Repo is here: [obsidian-livesync-webclip](https://github.com/vrtmrz/obsidian-livesync-webclip). (Docs are work in progress.)
## License
The source code is licensed MIT.
The source code is licensed under the MIT License.

View File

@@ -10,7 +10,7 @@ If you feel something, please feel free to inform me.
| 🛰️ | [Remote Database Configurations](#remote-database-configurations) |
| 📦 | [Local Database Configurations](#local-database-configurations) |
| ⚙️ | [General Settings](#general-settings) |
| 🔁 | [Sync setting](#sync-setting) |
| 🔁 | [Sync Settings](#sync-settings) |
| 🔧 | [Miscellaneous](#miscellaneous) |
| 🧰 | [Hatch](#miscellaneous) |
| 🔌 | [Plugin and its settings](#plugin-and-its-settings) |
@@ -47,10 +47,10 @@ The passphrase to used as the key of encryption. Please use the long text.
### Apply
Set the End to End encryption enabled and its passphrase for use in replication.
If you change the passphrase with existen database, overwriting remote database is strongly recommended.
If you change the passphrase of a existing database, overwriting the remote database is strongly recommended.
### Overwrite by local DB
### Overwrite remote database
Overwrite the remote database by the local database using the passphrase you applied.
@@ -114,7 +114,7 @@ If you enable this option, log only the entries with the popup.
### Verbose log
## Sync setting
## Sync Settings
### LiveSync
Do LiveSync.

View File

@@ -71,7 +71,7 @@ In these instructions, create IBM Cloudant Instance for trial.
follow the figure, it's
"apikey-v2-2unu15184f7o8emr90xlqgkm2ncwhbltml6tgnjl9sd5"<sup>(\*3)</sup> and "c2c11651d75497fa3d3c486e4c8bdf27"<sup>(\*4)</sup>
## Self-hosted LiveSync setting
## Self-hosted LiveSync settings
![Setting](../images/remote_db_setting.png)

View File

@@ -9,8 +9,8 @@
3. Another device is watching remote CouchDB's changes, so retrieve new changes.
4. Self-hosted LiveSync reflects replicated changeset into Obsidian's vault.
Note: The figure is drawn as single-directional, between two devices. But everything occurs bi-directionally between many devices at once in real.
Note: The figure is drawn as single-directional, between two devices for demonstration purposes. Everything actually occurs bi-directionally between many devices at the same time.
## Techniques to keep bandwidth low.
## Techniques to keep bandwidth consumption low.
![dedupe](../images/2.png)

View File

@@ -99,7 +99,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
addScreenElement("100", containerInformationEl);
const containerRemoteDatabaseEl = containerEl.createDiv();
containerRemoteDatabaseEl.createEl("h3", { text: "Remote Database configuration" });
const syncWarn = containerRemoteDatabaseEl.createEl("div", { text: `These settings are kept locked while automatic synchronization options are enabled. Disable these options in the "Sync Settings" tab to unlock.` });
const syncWarn = containerRemoteDatabaseEl.createEl("div", { text: `These settings are kept locked while any synchronization options are enabled. Disable these options in the "Sync Settings" tab to unlock.` });
syncWarn.addClass("op-warn-info");
syncWarn.addClass("sls-hidden");
@@ -116,7 +116,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
const applyDisplayEnabled = () => {
if (isAnySyncEnabled()) {
dbsettings.forEach((e) => {
e.setDisabled(true).setTooltip("When any sync is enabled, It cound't be changed.");
e.setDisabled(true).setTooltip("Could not change this while any synchronization options are enabled.");
});
syncWarn.removeClass("sls-hidden");
} else {
@@ -197,7 +197,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
);
new Setting(containerRemoteDatabaseEl)
.setName("End to End Encryption")
.setDesc("Encrypt contents on the remote database. If you use the plugins synchronizing feature, enabling this is recommend.")
.setDesc("Encrypt contents on the remote database. If you use the plugin's synchronization feature, enabling this is recommend.")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.workingEncrypt).onChange(async (value) => {
this.plugin.settings.workingEncrypt = value;
@@ -207,7 +207,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
);
const phasspharase = new Setting(containerRemoteDatabaseEl)
.setName("Passphrase")
.setDesc("Encrypting passphrase. If you change the passphrase with existen database, overwriting remote database is strongly recommended.")
.setDesc("Encrypting passphrase. If you change the passphrase of a existing database, overwriting the remote database is strongly recommended.")
.addText((text) => {
text.setPlaceholder("")
.setValue(this.plugin.settings.workingPassphrase)
@@ -277,7 +277,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
};
new Setting(containerRemoteDatabaseEl)
.setName("Apply")
.setDesc("Apply encryption settinngs")
.setDesc("Apply encryption settings")
.addButton((button) =>
button
.setButtonText("Apply")
@@ -322,7 +322,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
}
new Setting(containerRemoteDatabaseEl)
.setName("Overwrite by local DB")
.setName("Overwrite remote database")
.setDesc("Overwrite remote database with local DB and passphrase.")
.addButton((button) =>
button
@@ -336,7 +336,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
)
new Setting(containerRemoteDatabaseEl)
.setName("Rebuild")
.setName("Rebuild everything")
.setDesc("Rebuild local and remote database with local files.")
.addButton((button) =>
button
@@ -680,7 +680,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
addScreenElement("20", containerGeneralSettingsEl);
const containerSyncSettingEl = containerEl.createDiv();
containerSyncSettingEl.createEl("h3", { text: "Sync setting" });
containerSyncSettingEl.createEl("h3", { text: "Sync Settings" });
if (this.plugin.settings.versionUpFlash != "") {
const c = containerSyncSettingEl.createEl("div", { text: this.plugin.settings.versionUpFlash });
@@ -731,7 +731,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
})
),
new Setting(containerSyncSettingEl)
.setName("Periodic sync intreval")
.setName("Periodic Sync interval")
.setDesc("Interval (sec)")
.addText((text) => {
text.setPlaceholder("")
@@ -770,7 +770,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
),
new Setting(containerSyncSettingEl)
.setName("Sync on Start")
.setDesc("Start synchronization on Obsidian started.")
.setDesc("Start synchronization after launching Obsidian.")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.syncOnStart).onChange(async (value) => {
this.plugin.settings.syncOnStart = value;
@@ -782,7 +782,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
new Setting(containerSyncSettingEl)
.setName("Use Trash for deleted files")
.setDesc("Do not delete files that deleted in remote, just move to trash.")
.setDesc("Do not delete files that are deleted in remote, just move to trash.")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.trashInsteadDelete).onChange(async (value) => {
this.plugin.settings.trashInsteadDelete = value;
@@ -792,7 +792,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
new Setting(containerSyncSettingEl)
.setName("Do not delete empty folder")
.setDesc("Normally, folder is deleted When the folder became empty by replication. enable this, leave it as is")
.setDesc("Normally, a folder is deleted when it becomes empty after a replication. Enabling this will prevent it from getting deleted")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.doNotDeleteFolder).onChange(async (value) => {
this.plugin.settings.doNotDeleteFolder = value;
@@ -820,8 +820,8 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
// })
// );
new Setting(containerSyncSettingEl)
.setName("Check conflict only on opening file.")
.setDesc("Do not check conflict while replication")
.setName("Check conflict only on opened files")
.setDesc("Do not check conflict for replication")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.checkConflictOnlyOnOpen).onChange(async (value) => {
this.plugin.settings.checkConflictOnlyOnOpen = value;
@@ -833,7 +833,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
text: sanitizeHTMLToDom(`Experimental`),
});
new Setting(containerSyncSettingEl)
.setName("Sync hidden files.")
.setName("Sync hidden files")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.syncInternalFiles).onChange(async (value) => {
this.plugin.settings.syncInternalFiles = value;
@@ -841,7 +841,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
})
);
new Setting(containerSyncSettingEl)
.setName("Scan hidden files before replication.")
.setName("Scan for hidden files before replication")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.syncInternalFilesBeforeReplication).onChange(async (value) => {
this.plugin.settings.syncInternalFilesBeforeReplication = value;
@@ -849,8 +849,8 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
})
);
new Setting(containerSyncSettingEl)
.setName("Scan hidden files periodicaly.")
.setDesc("Seconds, zero to disable.")
.setName("Scan hidden files periodically")
.setDesc("Seconds, 0 to disable.")
.addText((text) => {
text.setPlaceholder("")
.setValue(this.plugin.settings.syncInternalFilesInterval + "")
@@ -930,7 +930,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
text: sanitizeHTMLToDom(`Advanced settings`),
});
containerSyncSettingEl.createEl("div", {
text: `If you reached the payload size limit when using IBM Cloudant, please set batch size and batch limit to a lower value.`,
text: `If you reached the payload size limit when using IBM Cloudant, please decrease batch size and batch limit to a lower value.`,
});
new Setting(containerSyncSettingEl)
.setName("Batch size")
@@ -1127,7 +1127,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
new Setting(containerHatchEl)
.setName("Suspend file watching")
.setDesc("If enables it, all file operations are ignored.")
.setDesc("Stop watching for file change.")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.suspendFileWatching).onChange(async (value) => {
this.plugin.settings.suspendFileWatching = value;
@@ -1221,7 +1221,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
new Setting(containerPluginSettings)
.setName("Scan plugins periodically")
.setDesc("Scan plugins each 1 minutes.")
.setDesc("Scan plugins every 1 minute.")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.autoSweepPluginsPeriodic).onChange(async (value) => {
this.plugin.settings.autoSweepPluginsPeriodic = value;
@@ -1272,7 +1272,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
containerCorruptedDataEl.createEl("h3", { text: "Corrupted or missing data" });
containerCorruptedDataEl.createEl("h4", { text: "Corrupted" });
if (Object.keys(this.plugin.localDatabase.corruptedEntries).length > 0) {
const cx = containerCorruptedDataEl.createEl("div", { text: "If you have copy of these items on any device, simply edit once or twice. Or not, delete this. sorry.." });
const cx = containerCorruptedDataEl.createEl("div", { text: "If you have a copy of these files on any device, simply edit them once and sync. If not, there's nothing we can do except deleting them. sorry.." });
for (const k in this.plugin.localDatabase.corruptedEntries) {
const xx = cx.createEl("div", { text: `${k}` });
@@ -1302,7 +1302,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
containerCorruptedDataEl.createEl("h4", { text: "Missing or waiting" });
if (Object.keys(this.plugin.queuedFiles).length > 0) {
const cx = containerCorruptedDataEl.createEl("div", {
text: "These files have missing or waiting chunks. Perhaps almost chunks will be found in a while after replication. But if there're no chunk, you have to restore database entry from existed file by hitting the button below.",
text: "These files have missing or waiting chunks. Perhaps these chunks will arrive in a while after replication. But if they don't, you have to restore it's database entry from a existing local file by hitting the button below.",
});
const files = [...new Set([...this.plugin.queuedFiles.map((e) => e.entry._id)])];
for (const k of files) {

View File

@@ -1370,7 +1370,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
}
const procs = getProcessingCounts();
const procsDisp = procs == 0 ? "" : `${procs}`;
const message = `Sync:${w}${sent}${arrived}${waiting}${procsDisp}${queued}`;
const message = `Sync: ${w}${sent}${arrived}${waiting}${procsDisp}${queued}`;
const locks = getLocks();
const pendingTask = locks.pending.length
? "\nPending: " +