obsidian-plugin-config 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +4 -0
- package/README.md +45 -0
- package/bin/obsidian-inject.js +98 -0
- package/obsidian-plugin-config-1.0.2.tgz +0 -0
- package/package.json +88 -0
- package/scripts/acp.ts +71 -0
- package/scripts/build-npm.ts +137 -0
- package/scripts/esbuild.config.ts +311 -0
- package/scripts/help.ts +46 -0
- package/scripts/inject-path.ts +487 -0
- package/scripts/inject-prompt.ts +399 -0
- package/scripts/open-editor.mjs +18 -0
- package/scripts/release.ts +97 -0
- package/scripts/update-exports.js +91 -0
- package/scripts/update-version-config.ts +98 -0
- package/scripts/update-version.ts +102 -0
- package/scripts/utils.ts +117 -0
- package/src/index.ts +6 -0
- package/src/main_test.ts +106 -0
- package/src/modals/GenericConfirmModal.ts +67 -0
- package/src/modals/index.ts +3 -0
- package/src/test-centralized-utils.ts +23 -0
- package/src/tools/index.ts +9 -0
- package/src/utils/NoticeHelper.ts +102 -0
- package/src/utils/SettingsHelper.ts +180 -0
- package/src/utils/index.ts +3 -0
- package/templates/.vscode/settings.json +4 -0
- package/templates/eslint.config.ts +48 -0
- package/templates/help-plugin.ts +39 -0
- package/templates/package-versions.json +28 -0
- package/templates/tsconfig.json +37 -0
- package/test-plugin/manifest.json +10 -0
- package/test-plugin/package.json +38 -0
- package/test-plugin/scripts/acp.ts +71 -0
- package/test-plugin/scripts/esbuild.config.ts +165 -0
- package/test-plugin/scripts/help.ts +29 -0
- package/test-plugin/scripts/release.ts +97 -0
- package/test-plugin/scripts/update-version.ts +102 -0
- package/test-plugin/scripts/utils.ts +117 -0
- package/test-plugin/src/main.ts +11 -0
- package/test-plugin/yarn.lock +386 -0
- package/test-plugin-v2/main.js +5 -0
- package/test-plugin-v2/manifest.json +10 -0
- package/test-plugin-v2/package.json +40 -0
- package/test-plugin-v2/scripts/acp.ts +71 -0
- package/test-plugin-v2/scripts/esbuild.config.ts +165 -0
- package/test-plugin-v2/scripts/help.ts +29 -0
- package/test-plugin-v2/scripts/release.ts +97 -0
- package/test-plugin-v2/scripts/update-version.ts +102 -0
- package/test-plugin-v2/scripts/utils.ts +117 -0
- package/test-plugin-v2/src/main.ts +11 -0
- package/test-plugin-v2/tsconfig.json +31 -0
- package/test-plugin-v2/yarn.lock +1986 -0
- package/tsconfig.json +38 -0
- package/versions.json +5 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { readFile, writeFile } from "fs/promises";
|
|
2
|
+
import dedent from "dedent";
|
|
3
|
+
import { inc, valid } from "semver";
|
|
4
|
+
import { askQuestion, createReadlineInterface, gitExec } from "./utils.js";
|
|
5
|
+
|
|
6
|
+
const rl = createReadlineInterface();
|
|
7
|
+
|
|
8
|
+
async function getTargetVersion(currentVersion: string): Promise<string> {
|
|
9
|
+
const updateType = await askQuestion(dedent`
|
|
10
|
+
Current version: ${currentVersion}
|
|
11
|
+
Kind of update:
|
|
12
|
+
patch(1.0.1) -> type 1 or p
|
|
13
|
+
minor(1.1.0) -> type 2 or min
|
|
14
|
+
major(2.0.0) -> type 3 or maj
|
|
15
|
+
or version number (e.g. 2.0.0)
|
|
16
|
+
Enter choice: `, rl);
|
|
17
|
+
|
|
18
|
+
switch (updateType.trim()) {
|
|
19
|
+
case "p":
|
|
20
|
+
case "1":
|
|
21
|
+
return inc(currentVersion, "patch") || "";
|
|
22
|
+
case "min":
|
|
23
|
+
case "2":
|
|
24
|
+
return inc(currentVersion, "minor") || "";
|
|
25
|
+
case "maj":
|
|
26
|
+
case "3":
|
|
27
|
+
return inc(currentVersion, "major") || "";
|
|
28
|
+
default:
|
|
29
|
+
return valid(updateType.trim()) || "";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function updateJsonFile(filename: string, updateFn: (json: any) => void): Promise<void> {
|
|
34
|
+
try {
|
|
35
|
+
const content = JSON.parse(await readFile(filename, "utf8"));
|
|
36
|
+
updateFn(content);
|
|
37
|
+
await writeFile(filename, JSON.stringify(content, null, "\t"));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error(`Error updating ${filename}:`, error instanceof Error ? error.message : String(error));
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function updateManifestVersions(targetVersion: string): Promise<void> {
|
|
45
|
+
try {
|
|
46
|
+
const manifest = JSON.parse(await readFile("manifest.json", "utf8"));
|
|
47
|
+
const { minAppVersion } = manifest;
|
|
48
|
+
|
|
49
|
+
await Promise.all([
|
|
50
|
+
updateJsonFile("manifest.json", json => json.version = targetVersion),
|
|
51
|
+
updateJsonFile("versions.json", json => json[targetVersion] = minAppVersion),
|
|
52
|
+
updateJsonFile("package.json", json => json.version = targetVersion),
|
|
53
|
+
// updateJsonFile("package-lock.json", json => json.version = targetVersion)
|
|
54
|
+
]);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error("Error updating manifest versions:", error instanceof Error ? error.message : String(error));
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function updateVersion(): Promise<void> {
|
|
62
|
+
try {
|
|
63
|
+
const currentVersion = process.env.npm_package_version || "1.0.0";
|
|
64
|
+
const targetVersion = await getTargetVersion(currentVersion);
|
|
65
|
+
|
|
66
|
+
if (!targetVersion) {
|
|
67
|
+
console.log("Invalid version");
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
// Update all files first
|
|
73
|
+
await updateManifestVersions(targetVersion);
|
|
74
|
+
console.log(`Files updated to version ${targetVersion}`);
|
|
75
|
+
|
|
76
|
+
// Add files to git
|
|
77
|
+
gitExec("git add manifest.json package.json versions.json");
|
|
78
|
+
gitExec(`git commit -m "Updated to version ${targetVersion}"`);
|
|
79
|
+
console.log("Changes committed");
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error("Error during update or commit:", error instanceof Error ? error.message : String(error));
|
|
82
|
+
console.log("Operation failed.");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
gitExec("git push");
|
|
88
|
+
console.log(`Version successfully updated to ${targetVersion} and pushed.`);
|
|
89
|
+
} catch (pushError) {
|
|
90
|
+
console.error("Failed to push version update:", pushError instanceof Error ? pushError.message : String(pushError));
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error("Error:", error instanceof Error ? error.message : String(error));
|
|
94
|
+
} finally {
|
|
95
|
+
rl.close();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
updateVersion().catch(console.error).finally(() => {
|
|
100
|
+
console.log("Exiting...");
|
|
101
|
+
process.exit();
|
|
102
|
+
});
|
package/scripts/utils.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {
|
|
2
|
+
access,
|
|
3
|
+
mkdir,
|
|
4
|
+
copyFile,
|
|
5
|
+
rm
|
|
6
|
+
} from "fs/promises";
|
|
7
|
+
import path from "path";
|
|
8
|
+
import * as readline from "readline";
|
|
9
|
+
import { execSync } from "child_process";
|
|
10
|
+
|
|
11
|
+
export function createReadlineInterface(): readline.Interface {
|
|
12
|
+
return readline.createInterface({
|
|
13
|
+
input: process.stdin as NodeJS.ReadableStream,
|
|
14
|
+
output: process.stdout as NodeJS.WritableStream,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const askQuestion = async (question: string, rl: readline.Interface): Promise<string> => {
|
|
19
|
+
try {
|
|
20
|
+
return await new Promise(resolve => rl.question(question, input => resolve(input.trim())));
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error("Error asking question:", error);
|
|
23
|
+
throw error;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Ask a yes/no confirmation question with standardized logic
|
|
29
|
+
* Accepts: y, yes, Y, YES, or empty (default to yes)
|
|
30
|
+
* Rejects: n, no, N, NO
|
|
31
|
+
* Invalid input defaults to no for safety
|
|
32
|
+
*/
|
|
33
|
+
export const askConfirmation = async (question: string, rl: readline.Interface): Promise<boolean> => {
|
|
34
|
+
const answer = await askQuestion(`${question} [Y/n]: `, rl);
|
|
35
|
+
const response = answer.toLowerCase();
|
|
36
|
+
|
|
37
|
+
// Accept: y, yes, Y, YES, or empty (default to yes)
|
|
38
|
+
// Reject: n, no, N, NO
|
|
39
|
+
const isYes = response === '' || response === 'y' || response === 'yes';
|
|
40
|
+
const isNo = response === 'n' || response === 'no';
|
|
41
|
+
|
|
42
|
+
if (isNo) {
|
|
43
|
+
return false;
|
|
44
|
+
} else if (isYes) {
|
|
45
|
+
return true;
|
|
46
|
+
} else {
|
|
47
|
+
console.log("Please answer Y (yes) or n (no). Defaulting to no for safety.");
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const cleanInput = (inputStr: string): string => {
|
|
53
|
+
if (!inputStr) return "";
|
|
54
|
+
return inputStr.trim().replace(/["`]/g, "'").replace(/\r\n/g, "\n");
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const isValidPath = async (pathToCheck: string): Promise<boolean> => {
|
|
58
|
+
if (!pathToCheck) return false;
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
// Using async fs.access is preferred over synchronous existsSync
|
|
62
|
+
// as it doesn't block the main thread/event loop
|
|
63
|
+
await access(pathToCheck.trim());
|
|
64
|
+
return true;
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export async function copyFilesToTargetDir(buildPath: string): Promise<void> {
|
|
71
|
+
const manifestDest = path.join(buildPath, "manifest.json");
|
|
72
|
+
const cssDest = path.join(buildPath, "styles.css");
|
|
73
|
+
const folderToRemove = path.join(buildPath, "_.._");
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
await mkdir(buildPath);
|
|
77
|
+
} catch (error: any) {
|
|
78
|
+
if (error.code !== "EEXIST") {
|
|
79
|
+
console.error(`Error creating directory: ${error.message}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Copy manifest
|
|
84
|
+
try {
|
|
85
|
+
await copyFile("./manifest.json", manifestDest);
|
|
86
|
+
} catch (error: any) {
|
|
87
|
+
console.error(`Error copying manifest: ${error.message}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Copy CSS
|
|
91
|
+
try {
|
|
92
|
+
// First check if CSS exists in src/styles.css
|
|
93
|
+
if (await isValidPath("./src/styles.css")) {
|
|
94
|
+
await copyFile("./src/styles.css", cssDest);
|
|
95
|
+
}
|
|
96
|
+
// Otherwise, check if it exists in the root
|
|
97
|
+
else if (await isValidPath("./styles.css")) {
|
|
98
|
+
await copyFile("./styles.css", cssDest);
|
|
99
|
+
if (await isValidPath(folderToRemove)) {
|
|
100
|
+
await rm(folderToRemove, { recursive: true });
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
} catch (error: any) {
|
|
106
|
+
console.error(`Error copying CSS: ${error.message}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function gitExec(command: string): void {
|
|
111
|
+
try {
|
|
112
|
+
execSync(command, { stdio: "inherit" });
|
|
113
|
+
} catch (error: any) {
|
|
114
|
+
console.error(`Error executing '${command}':`, error.message);
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
package/src/index.ts
ADDED
package/src/main_test.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
App,
|
|
3
|
+
Plugin,
|
|
4
|
+
PluginSettingTab,
|
|
5
|
+
Setting,
|
|
6
|
+
Notice
|
|
7
|
+
} from "obsidian";
|
|
8
|
+
import { showConfirmModal } from "./modals/GenericConfirmModal.ts";
|
|
9
|
+
import { showTestMessage, getRandomEmoji } from "obsidian-plugin-config/tools";
|
|
10
|
+
|
|
11
|
+
interface MyPluginSettings {
|
|
12
|
+
mySetting: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const DEFAULT_SETTINGS: MyPluginSettings = {
|
|
16
|
+
mySetting: "default"
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default class MyPlugin extends Plugin {
|
|
20
|
+
settings: MyPluginSettings;
|
|
21
|
+
|
|
22
|
+
async onload(): Promise<void> {
|
|
23
|
+
console.log("loading plugin");
|
|
24
|
+
await this.loadSettings();
|
|
25
|
+
|
|
26
|
+
this.addCommand({
|
|
27
|
+
id: 'show-confirmation-modal',
|
|
28
|
+
name: 'Show Confirmation Modal (Local)',
|
|
29
|
+
callback: () => this.showConfirmationModal()
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
this.addCommand({
|
|
33
|
+
id: 'show-centralized-modal',
|
|
34
|
+
name: 'Show Confirmation Modal (Centralized)',
|
|
35
|
+
callback: () => this.showCentralizedModal()
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
this.addCommand({
|
|
39
|
+
id: 'test-tools',
|
|
40
|
+
name: 'Test Centralized Tools',
|
|
41
|
+
callback: () => {
|
|
42
|
+
const message = showTestMessage();
|
|
43
|
+
const emoji = getRandomEmoji();
|
|
44
|
+
new Notice(`${emoji} ${message}`);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
this.addSettingTab(new SampleSettingTab(this.app, this));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private showConfirmationModal(): void {
|
|
52
|
+
showConfirmModal(this.app, {
|
|
53
|
+
title: "Confirmation requise",
|
|
54
|
+
message: "รtes-vous sรปr de vouloir effectuer cette action ? Cette action ne peut pas รชtre annulรฉe.",
|
|
55
|
+
confirmText: "Confirmer",
|
|
56
|
+
cancelText: "Annuler",
|
|
57
|
+
onConfirm: () => {
|
|
58
|
+
new Notice("Action confirmรฉe !");
|
|
59
|
+
console.log("Action confirmรฉe par l'utilisateur");
|
|
60
|
+
},
|
|
61
|
+
onCancel: () => {
|
|
62
|
+
new Notice("Action annulรฉe.");
|
|
63
|
+
console.log("Action annulรฉe par l'utilisateur");
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private showCentralizedModal(): void {
|
|
69
|
+
showConfirmModal(this.app, {
|
|
70
|
+
title: "Centralized Modal Test",
|
|
71
|
+
message: "This modal comes from the centralized configuration! Pretty cool, right?",
|
|
72
|
+
confirmText: "Awesome!",
|
|
73
|
+
cancelText: "Not bad",
|
|
74
|
+
onConfirm: () => {
|
|
75
|
+
new Notice("Centralized modal confirmed! ๐");
|
|
76
|
+
},
|
|
77
|
+
onCancel: () => {
|
|
78
|
+
new Notice("Centralized modal cancelled ๐ข");
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async loadSettings(): Promise<void> {
|
|
84
|
+
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async saveSettings(): Promise<void> {
|
|
88
|
+
await this.saveData(this.settings);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
class SampleSettingTab extends PluginSettingTab {
|
|
93
|
+
plugin: MyPlugin;
|
|
94
|
+
|
|
95
|
+
constructor(app: App, plugin: MyPlugin) {
|
|
96
|
+
super(app, plugin);
|
|
97
|
+
this.plugin = plugin;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
display(): void {
|
|
101
|
+
const { containerEl } = this;
|
|
102
|
+
containerEl.empty();
|
|
103
|
+
new Setting(containerEl);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { App, Modal } from "obsidian";
|
|
2
|
+
import { capitalize } from "lodash";
|
|
3
|
+
|
|
4
|
+
export interface ConfirmModalOptions {
|
|
5
|
+
title: string;
|
|
6
|
+
message: string;
|
|
7
|
+
confirmText?: string;
|
|
8
|
+
cancelText?: string;
|
|
9
|
+
onConfirm: () => void;
|
|
10
|
+
onCancel?: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class GenericConfirmModal extends Modal {
|
|
14
|
+
private options: ConfirmModalOptions;
|
|
15
|
+
|
|
16
|
+
constructor(app: App, options: ConfirmModalOptions) {
|
|
17
|
+
super(app);
|
|
18
|
+
this.options = options;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
onOpen(): void {
|
|
22
|
+
const { contentEl } = this;
|
|
23
|
+
contentEl.empty();
|
|
24
|
+
|
|
25
|
+
// Title (using lodash capitalize for demo)
|
|
26
|
+
contentEl.createEl("h2", { text: capitalize(this.options.title) });
|
|
27
|
+
|
|
28
|
+
// Message
|
|
29
|
+
contentEl.createEl("p", { text: this.options.message });
|
|
30
|
+
|
|
31
|
+
// Buttons container
|
|
32
|
+
const buttonContainer = contentEl.createDiv("modal-button-container");
|
|
33
|
+
|
|
34
|
+
// Cancel button
|
|
35
|
+
const cancelBtn = buttonContainer.createEl("button", {
|
|
36
|
+
text: this.options.cancelText || "Cancel",
|
|
37
|
+
cls: "mod-cta"
|
|
38
|
+
});
|
|
39
|
+
cancelBtn.addEventListener("click", () => {
|
|
40
|
+
this.options.onCancel?.();
|
|
41
|
+
this.close();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// Confirm button
|
|
45
|
+
const confirmBtn = buttonContainer.createEl("button", {
|
|
46
|
+
text: this.options.confirmText || "Confirm",
|
|
47
|
+
cls: "mod-cta mod-warning"
|
|
48
|
+
});
|
|
49
|
+
confirmBtn.addEventListener("click", () => {
|
|
50
|
+
this.options.onConfirm();
|
|
51
|
+
this.close();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Focus on confirm button
|
|
55
|
+
confirmBtn.focus();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
onClose(): void {
|
|
59
|
+
const { contentEl } = this;
|
|
60
|
+
contentEl.empty();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Utility function for quick usage
|
|
65
|
+
export function showConfirmModal(app: App, options: ConfirmModalOptions): void {
|
|
66
|
+
new GenericConfirmModal(app, options).open();
|
|
67
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Simple test file to verify centralized utils work
|
|
2
|
+
import { NoticeHelper } from "obsidian-plugin-config/utils";
|
|
3
|
+
|
|
4
|
+
export function testCentralizedUtils(): void {
|
|
5
|
+
console.log("๐งช Testing centralized utils...");
|
|
6
|
+
|
|
7
|
+
// Test different notice types
|
|
8
|
+
NoticeHelper.success("โ
Centralized utils are working!");
|
|
9
|
+
|
|
10
|
+
setTimeout(() => {
|
|
11
|
+
NoticeHelper.info("โน๏ธ This notice comes from the centralized config");
|
|
12
|
+
}, 1000);
|
|
13
|
+
|
|
14
|
+
setTimeout(() => {
|
|
15
|
+
NoticeHelper.warning("โ ๏ธ This is a warning from centralized utils");
|
|
16
|
+
}, 2000);
|
|
17
|
+
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
NoticeHelper.custom("๐", "Custom notice with rocket emoji!");
|
|
20
|
+
}, 3000);
|
|
21
|
+
|
|
22
|
+
console.log("โ
All centralized utils tests completed!");
|
|
23
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Simple tools for testing
|
|
2
|
+
export function showTestMessage(): string {
|
|
3
|
+
return "โ
CENTRALIZED TOOLS WORK! This comes from obsidian-plugin-config!";
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export function getRandomEmoji(): string {
|
|
7
|
+
const emojis = ["๐", "๐", "โจ", "๐ฅ", "๐ฏ", "โก", "๐ฏ", "๐"];
|
|
8
|
+
return emojis[Math.floor(Math.random() * emojis.length)];
|
|
9
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Notice } from "obsidian";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Enhanced Notice helper with different types and durations
|
|
5
|
+
*/
|
|
6
|
+
export class NoticeHelper {
|
|
7
|
+
private static readonly DEFAULT_DURATION = 5000;
|
|
8
|
+
private static readonly SUCCESS_DURATION = 3000;
|
|
9
|
+
private static readonly ERROR_DURATION = 8000;
|
|
10
|
+
private static readonly WARNING_DURATION = 6000;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Show a success notice with green styling
|
|
14
|
+
*/
|
|
15
|
+
static success(message: string, duration?: number): Notice {
|
|
16
|
+
const notice = new Notice(
|
|
17
|
+
`โ
${message}`,
|
|
18
|
+
duration ?? this.SUCCESS_DURATION
|
|
19
|
+
);
|
|
20
|
+
return notice;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Show an error notice with red styling
|
|
25
|
+
*/
|
|
26
|
+
static error(message: string, duration?: number): Notice {
|
|
27
|
+
const notice = new Notice(
|
|
28
|
+
`โ ${message}`,
|
|
29
|
+
duration ?? this.ERROR_DURATION
|
|
30
|
+
);
|
|
31
|
+
return notice;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Show a warning notice with yellow styling
|
|
36
|
+
*/
|
|
37
|
+
static warning(message: string, duration?: number): Notice {
|
|
38
|
+
const notice = new Notice(
|
|
39
|
+
`โ ๏ธ ${message}`,
|
|
40
|
+
duration ?? this.WARNING_DURATION
|
|
41
|
+
);
|
|
42
|
+
return notice;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Show an info notice with blue styling
|
|
47
|
+
*/
|
|
48
|
+
static info(message: string, duration?: number): Notice {
|
|
49
|
+
const notice = new Notice(
|
|
50
|
+
`โน๏ธ ${message}`,
|
|
51
|
+
duration ?? this.DEFAULT_DURATION
|
|
52
|
+
);
|
|
53
|
+
return notice;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Show a loading notice that can be updated
|
|
58
|
+
*/
|
|
59
|
+
static loading(message: string): Notice {
|
|
60
|
+
return new Notice(`โณ ${message}`, 0); // 0 = permanent until manually hidden
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Update a loading notice to success and auto-hide
|
|
65
|
+
*/
|
|
66
|
+
static updateToSuccess(notice: Notice, message: string): void {
|
|
67
|
+
notice.setMessage(`โ
${message}`);
|
|
68
|
+
setTimeout(() => notice.hide(), this.SUCCESS_DURATION);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Update a loading notice to error and auto-hide
|
|
73
|
+
*/
|
|
74
|
+
static updateToError(notice: Notice, message: string): void {
|
|
75
|
+
notice.setMessage(`โ ${message}`);
|
|
76
|
+
setTimeout(() => notice.hide(), this.ERROR_DURATION);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Show a notice with custom emoji and duration
|
|
81
|
+
*/
|
|
82
|
+
static custom(emoji: string, message: string, duration?: number): Notice {
|
|
83
|
+
return new Notice(
|
|
84
|
+
`${emoji} ${message}`,
|
|
85
|
+
duration ?? this.DEFAULT_DURATION
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Show a progress notice for long operations
|
|
91
|
+
*/
|
|
92
|
+
static progress(message: string, current: number, total: number): Notice {
|
|
93
|
+
const percentage = Math.round((current / total) * 100);
|
|
94
|
+
const progressBar = "โ".repeat(Math.floor(percentage / 5)) +
|
|
95
|
+
"โ".repeat(20 - Math.floor(percentage / 5));
|
|
96
|
+
|
|
97
|
+
return new Notice(
|
|
98
|
+
`๐ ${message}\n[${progressBar}] ${percentage}%`,
|
|
99
|
+
0
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|