Skip to content

Commit

Permalink
0.24.0.dev-rc4
Browse files Browse the repository at this point in the history
  • Loading branch information
vrtmrz committed Oct 18, 2024
1 parent 7ca5ac5 commit e0e0ab0
Show file tree
Hide file tree
Showing 19 changed files with 556 additions and 368 deletions.
2 changes: 1 addition & 1 deletion manifest-beta.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "obsidian-livesync",
"name": "Self-hosted LiveSync",
"version": "0.24.0.dev-rc3",
"version": "0.24.0.dev-rc4",
"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",
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "obsidian-livesync",
"version": "0.24.0.dev-rc3",
"version": "0.24.0.dev-rc4",
"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",
Expand Down
1 change: 1 addition & 0 deletions src/common/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const EVENT_LEAF_ACTIVE_CHANGED = "leaf-active-changed";
export const EVENT_LOG_ADDED = "log-added";

export const EVENT_REQUEST_OPEN_SETTINGS = "request-open-settings";
export const EVENT_REQUEST_OPEN_SETTING_WIZARD = "request-open-setting-wizard";
export const EVENT_REQUEST_OPEN_SETUP_URI = "request-open-setup-uri";
export const EVENT_REQUEST_COPY_SETUP_URI = "request-copy-setup-uri";

Expand Down
14 changes: 7 additions & 7 deletions src/features/ConfigSync/CmdConfigSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1492,14 +1492,13 @@ export class ConfigSync extends LiveSyncCommands implements IObsidianModule {
return true;
}
async _askHiddenFileConfiguration(opt: { enableFetch?: boolean, enableOverwrite?: boolean }) {
const message = `Would you like to enable \`Customization sync\`?
This feature allows you to sync your customisations -- such as configurations, themes, snippets, and plugins -- across your devices in a fully controlled manner, unlike the fully automatic behaviour of hidden file synchronisation.
const message = `Would you like to enable **Customization sync**?
You may use this feature alongside hidden file synchronisation. When both features are enabled, items configured as \`Automatic\` in this feature will be managed by hidden file synchronisation.
Do not worry, you will be prompted to enable or keep disabled hidden file synchronisation after this dialogue.
Of course, you can enable or disable this feature at any time.
> [!DETAILS]-
> This feature allows you to sync your customisations -- such as configurations, themes, snippets, and plugins -- across your devices in a fully controlled manner, unlike the fully automatic behaviour of hidden file synchronisation.
>
> You may use this feature alongside hidden file synchronisation. When both features are enabled, items configured as \`Automatic\` in this feature will be managed by **hidden file synchronisation**.
> Do not worry, you will be prompted to enable or keep disabled **hidden file synchronisation** after this dialogue.
`
const CHOICE_CUSTOMIZE = "Yes, Enable it";
const CHOICE_DISABLE = "No, Disable it";
Expand Down Expand Up @@ -1576,6 +1575,7 @@ Of course, you can enable or disable this feature at any time.
this.plugin.deviceAndVaultName = name;
}
this.plugin.settings.usePluginSync = true;
this.plugin.settings.useAdvancedMode = true;
await this.plugin.saveSettings();
await this.scanAllConfigFiles(true);
}
Expand Down
22 changes: 12 additions & 10 deletions src/features/HiddenFileSync/CmdHiddenFileSync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -748,18 +748,19 @@ export class HiddenFileSync extends LiveSyncCommands implements IObsidianModule
return true;
}
async _askHiddenFileConfiguration(opt: { enableFetch?: boolean, enableOverwrite?: boolean }) {
const messageFetch = `${opt.enableFetch ? `- Fetch: Use the files stored from other devices. Choose this option if you have already configured hidden file synchronization on those devices and wish to accept their files.\n` : ""}`;
const messageOverwrite = `${opt.enableOverwrite ? ` - Overwrite: Use the files from this device. Select this option if you want to overwrite the files stored on other devices.\n` : ""}`;
const messageMerge = `- Merge: Merge the files from this device with those on other devices. Choose this option if you wish to combine files from multiple sources.
However, please be reminded that merging may cause conflicts if the files are not identical. Additionally, this process may occur within the same folder, potentially breaking your plug-in or theme settings that comprise multiple files.\n`;
const message = `Would you like to enable \`Hidden File Synchronization\`?
This feature allows you to synchronize all hidden files without any user interaction.
To enable this feature, you should choose one of the following options:
const messageFetch = `${opt.enableFetch ? `> - Fetch: Use the files stored from other devices. Choose this option if you have already configured hidden file synchronization on those devices and wish to accept their files.\n` : ""}`;
const messageOverwrite = `${opt.enableOverwrite ? `> - Overwrite: Use the files from this device. Select this option if you want to overwrite the files stored on other devices.\n` : ""}`;
const messageMerge = `> - Merge: Merge the files from this device with those on other devices. Choose this option if you wish to combine files from multiple sources.
> However, please be reminded that merging may cause conflicts if the files are not identical. Additionally, this process may occur within the same folder, potentially breaking your plug-in or theme settings that comprise multiple files.\n`;
const message = `Would you like to enable **Hidden File Synchronization**?
> [!DETAILS]-
> This feature allows you to synchronize all hidden files without any user interaction.
> To enable this feature, you should choose one of the following options:
${messageFetch}${messageOverwrite}${messageMerge}
Note: Please keep in mind that enabling this feature alongside customisation sync may override certain behaviors.`
> [!IMPORTANT]
> Please keep in mind that enabling this feature alongside customisation sync may override certain behaviors.`
const CHOICE_FETCH = "Fetch";
const CHOICE_OVERWRITE = "Overwrite";
const CHOICE_MERGE = "Merge";
Expand Down Expand Up @@ -817,6 +818,7 @@ Note: Please keep in mind that enabling this feature alongside customisation syn
} else if (mode == "MERGE") {
await this.syncInternalFilesAndDatabase("safe", true);
}
this.plugin.settings.useAdvancedMode = true;
this.plugin.settings.syncInternalFiles = true;
await this.plugin.saveSettings();
Logger(`Done! Restarting the app is strongly recommended!`, LOG_LEVEL_NOTICE);
Expand Down
2 changes: 1 addition & 1 deletion src/lib
32 changes: 25 additions & 7 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,11 +347,29 @@ export default class ObsidianLiveSyncPlugin extends Plugin implements LiveSyncLo
async onLiveSyncReady() {
if (!await this.$everyOnLayoutReady()) return;
eventHub.emitEvent(EVENT_LAYOUT_READY);
if (this.settings.suspendFileWatching) {
Logger("'Suspend file watching' turned on. Are you sure this is what you intended? Every modification on the vault will be ignored.", LOG_LEVEL_NOTICE);
}
if (this.settings.suspendParseReplicationResult) {
Logger("'Suspend database reflecting' turned on. Are you sure this is what you intended? Every replicated change will be postponed until disabling this option.", LOG_LEVEL_NOTICE);
if (this.settings.suspendFileWatching || this.settings.suspendParseReplicationResult) {
const ANSWER_KEEP = "Keep this plug-in suspended";
const ANSWER_RESUME = "Resume and restart Obsidian";
const message = `Self-hosted LiveSync has been configured to ignore some events. Is this intentional for you?
| Type | Status | Note |
|:---:|:---:|---|
| Storage Events | ${this.settings.suspendFileWatching ? "suspended" : "active"} | Every modification will be ignored |
| Database Events | ${this.settings.suspendParseReplicationResult ? "suspended" : "active"} | Every synchronised change will be postponed |
Do you want to resume them and restart Obsidian?
> [!DETAILS]-
> These flags are set by the plug-in while rebuilding, or fetching. If the process ends abnormally, it may be kept unintended.
> If you are not sure, you can try to rerun these processes. Make sure to back your vault up.
`;
if (await this.confirm.askSelectStringDialogue(message, [ANSWER_KEEP, ANSWER_RESUME], { defaultAction: ANSWER_KEEP, title: "Scram Enabled" }) == ANSWER_RESUME) {
this.settings.suspendFileWatching = false;
this.settings.suspendParseReplicationResult = false;
await this.saveSettings();
await this.$$scheduleAppReload();
return;
}
}
const isInitialized = await this.$$initializeDatabase(false, false);
if (!isInitialized) {
Expand Down Expand Up @@ -411,7 +429,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin implements LiveSyncLo

const lastVersion = ~~(versionNumberString2Number(manifestVersion) / 1000);
if (lastVersion > this.settings.lastReadUpdates && this.settings.isConfigured) {
Logger($f`Self-hosted LiveSync has undergone a major upgrade. Please open the setting dialog, and check the information pane.`, LOG_LEVEL_NOTICE);
Logger($f`You have some unread release notes! Please read them once!`, LOG_LEVEL_NOTICE);
}

//@ts-ignore
Expand Down Expand Up @@ -559,7 +577,7 @@ export default class ObsidianLiveSyncPlugin extends Plugin implements LiveSyncLo

$anyAfterConnectCheckFailed(): Promise<boolean | "CHECKAGAIN" | undefined> { return InterceptiveAny; }

$$replicateAllToServer(showingNotice: boolean = false): Promise<boolean> { throwShouldBeOverridden() }
$$replicateAllToServer(showingNotice: boolean = false, sendChunksInBulkDisabled: boolean = false): Promise<boolean> { throwShouldBeOverridden() }
$$replicateAllFromServer(showingNotice: boolean = false): Promise<boolean> { throwShouldBeOverridden() }

// Remote Governing
Expand Down
14 changes: 1 addition & 13 deletions src/modules/core/ModuleFileHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,9 @@ export class ModuleFileHandler extends AbstractModule implements ICoreModule {
if (!onlyChunks) {
return await this.db.store(readFile);
} else {
return true;
return await this.db.createChunks(readFile, false, true);
}
}
// I remember that it should be processed naturally. -->

// // If the file is exist on the database, then it should be updated.
// // Check the file is already conflicted or not.
// const conflictedRevs = await this.db.getConflictedRevs(file);
// if (conflictedRevs.length > 0) {
// // If conflicted, then it should be stored as new conflicted file.
// const readFile = await this.readFileFromStub(file);
// this.db.store(readFile, true);
// return false;
// }
//< --

// entry is exist on the database, check the difference between the file and the entry.

Expand Down
19 changes: 14 additions & 5 deletions src/modules/core/ModuleRebuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ export class ModuleRebuilder extends AbstractModule implements ICoreModule, Rebu
}
}

async askUsingOptionalFeature(opt: {
enableFetch?: boolean;
enableOverwrite?: boolean;
}) {
if (await this.core.confirm.askYesNoDialog("Do you want to enable extra features? If you are new to Self-hosted LiveSync, try the core feature first!", { title: "Enable extra features", defaultOption: "No", timeout: 15 }) == "yes") {
await this.core.$allAskUsingOptionalSyncFeature(opt);
}
}

async rebuildRemote() {
await this.core.$allSuspendExtraSync();
this.core.settings.isConfigured = true;
Expand All @@ -36,11 +45,11 @@ export class ModuleRebuilder extends AbstractModule implements ICoreModule, Rebu
await this.core.$$tryResetRemoteDatabase();
await this.core.$$markRemoteLocked();
await delay(500);
await this.core.$allAskUsingOptionalSyncFeature({ enableOverwrite: true });
await this.askUsingOptionalFeature({ enableOverwrite: true });
await delay(1000);
await this.core.$$replicateAllToServer(true);
await delay(1000);
await this.core.$$replicateAllToServer(true);
await this.core.$$replicateAllToServer(true, true);
}
$rebuildRemote(): Promise<void> {
return this.rebuildRemote();
Expand All @@ -59,11 +68,11 @@ export class ModuleRebuilder extends AbstractModule implements ICoreModule, Rebu
await this.core.$$tryResetRemoteDatabase();
await this.core.$$markRemoteLocked();
await delay(500);
await this.core.$allAskUsingOptionalSyncFeature({ enableOverwrite: true });
await this.askUsingOptionalFeature({ enableOverwrite: true });
await delay(1000);
await this.core.$$replicateAllToServer(true);
await delay(1000);
await this.core.$$replicateAllToServer(true);
await this.core.$$replicateAllToServer(true, true);

}

Expand Down Expand Up @@ -169,7 +178,7 @@ export class ModuleRebuilder extends AbstractModule implements ICoreModule, Rebu
await delay(1000);
await this.core.$$replicateAllFromServer(true);
await this.resumeReflectingDatabase();
await this.core.$allAskUsingOptionalSyncFeature({ enableFetch: true });
await this.askUsingOptionalFeature({ enableFetch: true });
}
async fetchLocalWithRebuild() {
return await this.fetchLocal(true);
Expand Down
20 changes: 14 additions & 6 deletions src/modules/core/ModuleReplicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,17 @@ Or if you are sure know what had been happened, we can unlock the database from
return;
}
if (isAnyNote(change)) {
const docPath = getPath(change);
if (!await this.core.$$isTargetFile(docPath)) {
Logger(`Skipped: ${docPath}`, LOG_LEVEL_VERBOSE);
return;
}
if (this.databaseQueuedProcessor._isSuspended) {
Logger(`Processing scheduled: ${change.path}`, LOG_LEVEL_INFO);
Logger(`Processing scheduled: ${docPath}`, LOG_LEVEL_INFO);
}
const size = change.size;
if (this.core.$$isFileSizeExceeded(size)) {
Logger(`Processing ${change.path} has been skipped due to file size exceeding the limit`, LOG_LEVEL_NOTICE);
Logger(`Processing ${docPath} has been skipped due to file size exceeding the limit`, LOG_LEVEL_NOTICE);
return;
}
this.databaseQueuedProcessor.enqueue(change);
Expand All @@ -258,6 +263,7 @@ Or if you are sure know what had been happened, we can unlock the database from
databaseQueuedProcessor = new QueueProcessor(async (docs: EntryBody[]) => {
const dbDoc = docs[0] as LoadedEntry; // It has no `data`
const path = getPath(dbDoc);

// If `Read chunks online` is disabled, chunks should be transferred before here.
// However, in some cases, chunks are after that. So, if missing chunks exist, we have to wait for them.
const doc = await this.localDatabase.getDBEntryFromMeta({ ...dbDoc }, {}, false, true, true);
Expand Down Expand Up @@ -308,15 +314,17 @@ Or if you are sure know what had been happened, we can unlock the database from
return Promise.resolve(true);
}

async $$replicateAllToServer(showingNotice: boolean = false): Promise<boolean> {
async $$replicateAllToServer(showingNotice: boolean = false, sendChunksInBulkDisabled: boolean = false): Promise<boolean> {
if (!this.core.isReady) return false;
if (!await this.core.$everyBeforeReplicate(showingNotice)) {
Logger(`Replication has been cancelled by some module failure`, LOG_LEVEL_NOTICE);
return false;
}
if (this.core.replicator instanceof LiveSyncCouchDBReplicator) {
if (await this.core.confirm.askYesNoDialog("Do you want to send all chunks before replication?", { defaultOption: "No", timeout: 20 }) == "yes") {
await this.core.replicator.sendChunks(this.core.settings, undefined, true, 0);
if (!sendChunksInBulkDisabled) {
if (this.core.replicator instanceof LiveSyncCouchDBReplicator) {
if (await this.core.confirm.askYesNoDialog("Do you want to send all chunks before replication?", { defaultOption: "No", timeout: 20 }) == "yes") {
await this.core.replicator.sendChunks(this.core.settings, undefined, true, 0);
}
}
}
const ret = await this.core.replicator.replicateAllToServer(this.settings, showingNotice);
Expand Down
Loading

0 comments on commit e0e0ab0

Please sign in to comment.