mirror of
https://github.com/al0cam/AutoMover.git
synced 2026-07-22 05:41:25 +00:00
feat: added export/import for obsidian settings
This commit is contained in:
parent
1e616ac1a3
commit
2bc63e3872
3 changed files with 229 additions and 5 deletions
194
IO/SettingsIO.ts
Normal file
194
IO/SettingsIO.ts
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
import type { AutoMoverSettings } from "Settings/Settings";
|
||||
import { Notice, TFile } from "obsidian";
|
||||
import type { App } from "obsidian";
|
||||
|
||||
class SettingsIO {
|
||||
private static instance: SettingsIO;
|
||||
private app: App;
|
||||
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance(): SettingsIO {
|
||||
if (!SettingsIO.instance) {
|
||||
SettingsIO.instance = new SettingsIO();
|
||||
}
|
||||
return SettingsIO.instance;
|
||||
}
|
||||
|
||||
public init(app: App): void {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the plugin settings to a JSON file.
|
||||
*
|
||||
* @param settings - The settings object to export.
|
||||
* @returns A promise that resolves to true if the export was successful, false otherwise.
|
||||
*/
|
||||
public async exportSettings(settings: AutoMoverSettings) {
|
||||
try {
|
||||
if (!this.app) {
|
||||
throw new Error("App reference not set");
|
||||
}
|
||||
|
||||
const settingsData = JSON.stringify(settings, null, 2);
|
||||
|
||||
const electron = (window as any).require
|
||||
? (window as any).require("electron")
|
||||
: null;
|
||||
const remote = electron ? electron.remote : null;
|
||||
|
||||
if (!remote || !remote.dialog) {
|
||||
// Fall back to saving in vault if Electron APIs are not available
|
||||
return this.exportToVault(settingsData);
|
||||
}
|
||||
|
||||
const { canceled, filePath } = await remote.dialog.showSaveDialog({
|
||||
title: "Export AutoMover Settings",
|
||||
defaultPath: "AutoMover_settings.json",
|
||||
filters: [{ name: "JSON Files", extensions: ["json"] }],
|
||||
properties: ["createDirectory"],
|
||||
});
|
||||
|
||||
if (canceled || !filePath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fs = require("node:fs");
|
||||
fs.writeFileSync(filePath, settingsData);
|
||||
|
||||
new Notice("Settings exported successfully");
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Failed to export settings:", error);
|
||||
new Notice("Failed to export settings");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the settings to the vault.
|
||||
* Exports the settings to a file named AutoMover_settings.json
|
||||
*
|
||||
* @param settingsData - The settings data to export.
|
||||
* @returns A promise that resolves to true if the export was successful, false otherwise.
|
||||
*/
|
||||
private async exportToVault(settingsData: string): Promise<boolean> {
|
||||
try {
|
||||
const filename = "AutoMover_settings.json";
|
||||
await this.app.vault.create(filename, settingsData);
|
||||
new Notice(`Settings exported to vault: ${filename}`);
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Failed to export to vault:", error);
|
||||
new Notice("Failed to export settings to vault");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Imports settings from a JSON file.
|
||||
*
|
||||
* @returns The imported settings or null if the import failed.
|
||||
*/
|
||||
public async importSettings(): Promise<AutoMoverSettings | null> {
|
||||
try {
|
||||
if (!this.app) {
|
||||
throw new Error("App reference not set");
|
||||
}
|
||||
|
||||
const electron = (window as any).require
|
||||
? (window as any).require("electron")
|
||||
: null;
|
||||
const remote = electron ? electron.remote : null;
|
||||
|
||||
if (!remote || !remote.dialog) {
|
||||
// Fall back to importing from vault if Electron APIs are not available
|
||||
return this.importFromVault();
|
||||
}
|
||||
|
||||
const { canceled, filePaths } = await remote.dialog.showOpenDialog({
|
||||
title: "Import AutoMover Settings",
|
||||
filters: [{ name: "JSON Files", extensions: ["json"] }],
|
||||
properties: ["openFile"],
|
||||
});
|
||||
|
||||
if (canceled || !filePaths || filePaths.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fs = require("node:fs");
|
||||
const fileContent = fs.readFileSync(filePaths[0], "utf8");
|
||||
|
||||
const importedSettings = JSON.parse(fileContent);
|
||||
|
||||
if (!this.validateSettings(importedSettings)) {
|
||||
new Notice("Invalid settings file format");
|
||||
return null;
|
||||
}
|
||||
|
||||
new Notice("Settings imported successfully");
|
||||
return importedSettings;
|
||||
} catch (error) {
|
||||
console.error("Failed to import settings:", error);
|
||||
new Notice("Failed to import settings");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback method to import settings from the vault.
|
||||
* from the file AutoMover_settings.json
|
||||
*
|
||||
* @returns The imported settings or null if the import failed.
|
||||
*/
|
||||
private async importFromVault(): Promise<AutoMoverSettings | null> {
|
||||
try {
|
||||
const filename = "AutoMover_settings.json";
|
||||
const file = this.app.vault.getAbstractFileByPath(filename);
|
||||
|
||||
if (!file || !(file instanceof TFile)) {
|
||||
new Notice(`Could not find ${filename} in vault`);
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileContent = await this.app.vault.read(file);
|
||||
const importedSettings = JSON.parse(fileContent);
|
||||
|
||||
if (!this.validateSettings(importedSettings)) {
|
||||
new Notice("Invalid settings file format");
|
||||
return null;
|
||||
}
|
||||
|
||||
new Notice("Settings imported from vault successfully");
|
||||
return importedSettings;
|
||||
} catch (error) {
|
||||
console.error("Failed to import from vault:", error);
|
||||
new Notice("Failed to import settings from vault");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the settings object to ensure it has the correct structure.
|
||||
*
|
||||
* @param settings - The settings object to validate.
|
||||
* @return True if the settings object is valid, false otherwise.
|
||||
*/
|
||||
private validateSettings(settings: any): settings is AutoMoverSettings {
|
||||
if (!settings) return false;
|
||||
|
||||
if (typeof settings.moveOnOpen !== "boolean") return false;
|
||||
if (!Array.isArray(settings.movingRules)) return false;
|
||||
if (!Array.isArray(settings.exclusionRules)) return false;
|
||||
if (typeof settings.automaticMoving !== "boolean") return false;
|
||||
|
||||
if (settings.timer !== null && typeof settings.timer !== "number")
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const settingsIO = SettingsIO.getInstance();
|
||||
export default settingsIO;
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
import type AutoMoverPlugin from "main";
|
||||
import settingsIO from "IO/SettingsIO";
|
||||
import { ExclusionRule } from "Models/ExclusionRule";
|
||||
import { MovingRule } from "Models/MovingRule";
|
||||
import * as obsidian from "obsidian";
|
||||
import timerUtil from "Utils/TimerUtil";
|
||||
import type AutoMoverPlugin from "main";
|
||||
import * as obsidian from "obsidian";
|
||||
|
||||
export class SettingsTab extends obsidian.PluginSettingTab {
|
||||
plugin: AutoMoverPlugin;
|
||||
|
|
@ -17,6 +18,34 @@ export class SettingsTab extends obsidian.PluginSettingTab {
|
|||
containerEl.empty();
|
||||
|
||||
new obsidian.Setting(containerEl).setName("Automatic moving").setHeading();
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Export/Import of settings")
|
||||
.setDesc(
|
||||
`Import will replace the current settings.
|
||||
If you aren't prompted to choose a location, then the file will be exported to/imported from the vault root as AutoMover_settings.json.`,
|
||||
)
|
||||
.addButton((button) => {
|
||||
button.setButtonText("Export settings");
|
||||
button.onClick(async () => {
|
||||
settingsIO.exportSettings(this.plugin.settings);
|
||||
});
|
||||
})
|
||||
.addButton((button) => {
|
||||
button.setButtonText("Import settings");
|
||||
button.onClick(async () => {
|
||||
const importedSettings = await settingsIO.importSettings();
|
||||
if (importedSettings) {
|
||||
this.plugin.settings = importedSettings;
|
||||
await this.plugin.saveData(this.plugin.settings);
|
||||
this.plugin.app.workspace.trigger(
|
||||
"AutoMover:automatic-moving-update",
|
||||
this.plugin.settings,
|
||||
);
|
||||
this.display();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
new obsidian.Setting(containerEl)
|
||||
.setName("Move on open")
|
||||
.setDesc("Should the file be moved when it is opened?")
|
||||
|
|
|
|||
7
main.ts
7
main.ts
|
|
@ -1,11 +1,11 @@
|
|||
import settingsIO from "IO/SettingsIO";
|
||||
import * as Settings from "Settings/Settings";
|
||||
import { SettingsTab } from "Settings/SettingsTab";
|
||||
import exclusionMatcherUtil from "Utils/ExclusionMatcherUtil";
|
||||
import movingUtil from "Utils/MovingUtil";
|
||||
import ruleMatcherUtil from "Utils/RuleMatcherUtil";
|
||||
import * as obsidian from "obsidian";
|
||||
import exclusionMatcherUtil from "Utils/ExclusionMatcherUtil";
|
||||
import timerUtil from "Utils/TimerUtil";
|
||||
import { addIcon } from "obsidian";
|
||||
import * as obsidian from "obsidian";
|
||||
|
||||
export default class AutoMoverPlugin extends obsidian.Plugin {
|
||||
settings: Settings.AutoMoverSettings;
|
||||
|
|
@ -13,6 +13,7 @@ export default class AutoMoverPlugin extends obsidian.Plugin {
|
|||
async onload() {
|
||||
// console.log("loading plugin");
|
||||
movingUtil.init(this.app);
|
||||
settingsIO.init(this.app);
|
||||
/**
|
||||
* Loading settings and creating the settings tab
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue