mirror of
https://github.com/devonthesofa/obsidian-note-status.git
synced 2026-07-22 12:30:24 +00:00
feat: add manual non-Markdown data export/import to vault
- Implement exportToVault and importFromVault in NonMarkdownStatusStore - Add getNonMarkdownStore method to StatusStoreManager - Add manual synchronization buttons to the Synchronization settings UI - Support data migration between internal storage and vault sync file
This commit is contained in:
parent
f97bca5fa9
commit
32af8e1c78
3 changed files with 88 additions and 4 deletions
|
|
@ -2,6 +2,7 @@ import { PluginSettings, SyncGroup } from "@/types/pluginSettings";
|
|||
import React from "react";
|
||||
import { SettingItem } from "./SettingItem";
|
||||
import settingsService from "@/core/settingsService";
|
||||
import statusStoreManager from "@/core/statusStoreManager";
|
||||
|
||||
export type Props = {
|
||||
settings: PluginSettings;
|
||||
|
|
@ -22,6 +23,24 @@ export const SynchronizationSettings: React.FC<Props> = ({
|
|||
alert("Plugin settings imported successfully.");
|
||||
};
|
||||
|
||||
const handleDataExport = async () => {
|
||||
try {
|
||||
await statusStoreManager.getNonMarkdownStore().exportToVault();
|
||||
alert("Non-Markdown status data exported to vault.");
|
||||
} catch (e) {
|
||||
alert(`Export failed: ${e.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDataImport = async () => {
|
||||
try {
|
||||
await statusStoreManager.getNonMarkdownStore().importFromVault();
|
||||
alert("Non-Markdown status data imported from vault.");
|
||||
} catch (e) {
|
||||
alert(`Import failed: ${e.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleGroup = (group: SyncGroup) => {
|
||||
const currentGroups = [...(settings.syncGroups || [])];
|
||||
const index = currentGroups.indexOf(group);
|
||||
|
|
@ -234,6 +253,18 @@ export const SynchronizationSettings: React.FC<Props> = ({
|
|||
placeholder="_note-status-data.json"
|
||||
/>
|
||||
</SettingItem>
|
||||
|
||||
<div
|
||||
className="note-status-settings__actions"
|
||||
style={{ marginTop: "1em", display: "flex", gap: "10px" }}
|
||||
>
|
||||
<button onClick={handleDataExport}>
|
||||
📤 Export internal data to vault
|
||||
</button>
|
||||
<button onClick={handleDataImport}>
|
||||
📥 Import data from vault
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,14 +5,22 @@ import { StatusStore } from "./statusStores/types";
|
|||
|
||||
class StatusStoreManager {
|
||||
private stores: StatusStore[] = [];
|
||||
private nonMarkdownStore: NonMarkdownStatusStore | null = null;
|
||||
|
||||
async initialize(plugin: Plugin) {
|
||||
const frontmatterStore = new FrontmatterStatusStore(plugin.app);
|
||||
this.stores = [frontmatterStore];
|
||||
|
||||
const nonMarkdownStore = new NonMarkdownStatusStore(plugin);
|
||||
await nonMarkdownStore.initialize();
|
||||
this.registerStore(nonMarkdownStore);
|
||||
this.nonMarkdownStore = new NonMarkdownStatusStore(plugin);
|
||||
await this.nonMarkdownStore.initialize();
|
||||
this.registerStore(this.nonMarkdownStore);
|
||||
}
|
||||
|
||||
getNonMarkdownStore(): NonMarkdownStatusStore {
|
||||
if (!this.nonMarkdownStore) {
|
||||
throw new Error("NonMarkdownStatusStore is not initialized");
|
||||
}
|
||||
return this.nonMarkdownStore;
|
||||
}
|
||||
|
||||
registerStore(store: StatusStore) {
|
||||
|
|
|
|||
|
|
@ -58,14 +58,59 @@ export class NonMarkdownStatusStore implements StatusStore {
|
|||
settings.enableNonMarkdownSync &&
|
||||
settings.nonMarkdownSyncPath
|
||||
) {
|
||||
return normalizePath(settings.nonMarkdownSyncPath);
|
||||
return this.getVaultPath();
|
||||
}
|
||||
|
||||
return this.getInternalPath();
|
||||
}
|
||||
|
||||
private getInternalPath(): string {
|
||||
const configDir = this.plugin.app.vault.configDir;
|
||||
const pluginDir = `${configDir}/plugins/${this.plugin.manifest.id}`;
|
||||
return normalizePath(`${pluginDir}/non-markdown-statuses.json`);
|
||||
}
|
||||
|
||||
private getVaultPath(): string {
|
||||
const settings = settingsService.settings;
|
||||
return normalizePath(settings.nonMarkdownSyncPath);
|
||||
}
|
||||
|
||||
async exportToVault(): Promise<void> {
|
||||
const internalPath = this.getInternalPath();
|
||||
const vaultPath = this.getVaultPath();
|
||||
|
||||
if (!(await this.plugin.app.vault.adapter.exists(internalPath))) {
|
||||
throw new Error("No internal data found to export.");
|
||||
}
|
||||
|
||||
const raw = await this.plugin.app.vault.adapter.read(internalPath);
|
||||
await this.ensureDirectoryExists(vaultPath);
|
||||
await this.plugin.app.vault.adapter.write(vaultPath, raw);
|
||||
|
||||
// Reload if vault sync is active
|
||||
if (settingsService.settings.enableNonMarkdownSync) {
|
||||
this.data = await this.loadFromDisk();
|
||||
}
|
||||
}
|
||||
|
||||
async importFromVault(): Promise<void> {
|
||||
const internalPath = this.getInternalPath();
|
||||
const vaultPath = this.getVaultPath();
|
||||
|
||||
if (!(await this.plugin.app.vault.adapter.exists(vaultPath))) {
|
||||
throw new Error("No vault sync file found to import.");
|
||||
}
|
||||
|
||||
const raw = await this.plugin.app.vault.adapter.read(vaultPath);
|
||||
await this.ensureDirectoryExists(internalPath);
|
||||
await this.plugin.app.vault.adapter.write(internalPath, raw);
|
||||
|
||||
// Reload if vault sync is inactive
|
||||
if (!settingsService.settings.enableNonMarkdownSync) {
|
||||
this.data = await this.loadFromDisk();
|
||||
}
|
||||
}
|
||||
|
||||
canHandle(file: TFile): boolean {
|
||||
return file.extension !== "md";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue