Files
obsidian-livesync/src/serviceFeatures/basicCommands.ts
T

150 lines
5.4 KiB
TypeScript

import { LOG_LEVEL_NOTICE } from "octagonal-wheels/common/logger";
import { fireAndForget } from "octagonal-wheels/promises";
import type { NecessaryServices } from "@vrtmrz/livesync-commonlib/compat/interfaces/ServiceModule";
import { createInstanceLogFunction } from "@vrtmrz/livesync-commonlib/compat/services/lib/logUtils";
import {
REPLICATION_PROGRESS_PRESENTATIONS,
USER_INITIATED_REPLICATION_AUTHORITY,
} from "@vrtmrz/livesync-commonlib/replication";
import { $msg } from "@/common/translation";
import { copyFileDatabaseInfo, type FileDatabaseInfoCore } from "@/serviceFeatures/fileDatabaseInfo";
/**
* Services required by the platform-independent command palette actions.
*
* The database report deliberately receives a structural adapter rather than
* the whole host. This keeps the report helper independent from the core while
* retaining the same local database, storage, settings, path, and UI sources.
*/
export type BasicCommandsHost = NecessaryServices<
| "API"
| "appLifecycle"
| "control"
| "database"
| "fileProcessing"
| "path"
| "replication"
| "setting"
| "UI"
| "vault",
"storageAccess"
>;
function createFileDatabaseInfoCore(host: BasicCommandsHost): FileDatabaseInfoCore {
const { services, serviceModules } = host;
return {
localDatabase: services.database.localDatabase,
services: {
path: services.path,
UI: services.UI,
},
settings: services.setting.currentSettings(),
storageAccess: serviceModules.storageAccess,
};
}
/**
* Register the platform-independent command palette actions.
*
* Registration remains tied to `onInitialise`, matching the legacy module's
* timing and allowing hosts to compose the feature before the lifecycle runs.
*/
export function useBasicCommandsFeature(host: BasicCommandsHost): void {
const { services } = host;
const log = createInstanceLogFunction("SF:BasicCommands", services.API);
services.appLifecycle.onInitialise.addHandler(() => {
services.API.addCommand({
id: "livesync-replicate",
name: $msg("Sync now"),
callback: async () => {
await services.replication.replicateUserInitiated({
trigger: "manual",
progressPresentation: REPLICATION_PROGRESS_PRESENTATIONS.QUIET,
interaction: USER_INITIATED_REPLICATION_AUTHORITY,
});
},
});
services.API.addCommand({
id: "livesync-dump",
name: $msg("Copy database information for the active file"),
checkCallback: (checking) => {
const file = services.vault.getActiveFilePath();
if (!file) return false;
if (!checking) {
fireAndForget(() => copyFileDatabaseInfo(createFileDatabaseInfoCore(host), file));
}
return true;
},
});
services.API.addCommand({
id: "livesync-toggle",
name: "Toggle LiveSync",
callback: async () => {
const settings = services.setting.currentSettings();
if (settings.liveSync) {
settings.liveSync = false;
log("LiveSync Disabled.", LOG_LEVEL_NOTICE);
} else {
settings.liveSync = true;
log("LiveSync Enabled.", LOG_LEVEL_NOTICE);
}
await services.control.applySettings();
await services.setting.saveSettingData();
},
});
services.API.addCommand({
id: "livesync-suspendall",
name: "Toggle All Sync.",
callback: async () => {
if (services.appLifecycle.isSuspended()) {
services.appLifecycle.setSuspended(false);
log("Self-hosted LiveSync resumed", LOG_LEVEL_NOTICE);
} else {
services.appLifecycle.setSuspended(true);
log("Self-hosted LiveSync suspended", LOG_LEVEL_NOTICE);
}
await services.control.applySettings();
await services.setting.saveSettingData();
},
});
services.API.addCommand({
id: "livesync-scan-files",
name: "Scan storage and database again",
checkCallback: (checking) => {
if (!services.setting.currentSettings().useAdvancedMode) return false;
if (!checking) {
fireAndForget(() => services.vault.scanVault(true));
}
return true;
},
});
services.API.addCommand({
id: "livesync-runbatch",
name: $msg("Apply pending changes now"),
callback: async () => {
await services.fileProcessing.commitPendingFileEvents();
},
});
services.API.addCommand({
id: "livesync-abortsync",
name: "Abort synchronization immediately",
checkCallback: (checking) => {
if (!services.setting.currentSettings().useAdvancedMode) return false;
if (!checking) {
fireAndForget(() => services.replication.stopActiveTransfer());
}
return true;
},
});
return Promise.resolve(true);
});
}