refactor: notification system
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { Notice } from "@/components/base";
|
||||
import { showNotice } from "@/services/noticeService";
|
||||
|
||||
export async function copyClashEnv() {
|
||||
return invoke<void>("copy_clash_env");
|
||||
@@ -145,25 +145,29 @@ export async function getAppDir() {
|
||||
|
||||
export async function openAppDir() {
|
||||
return invoke<void>("open_app_dir").catch((err) =>
|
||||
Notice.error(err?.message || err.toString(), 1500),
|
||||
showNotice('error', err?.message || err.toString()),
|
||||
);
|
||||
}
|
||||
|
||||
export async function openCoreDir() {
|
||||
return invoke<void>("open_core_dir").catch((err) =>
|
||||
Notice.error(err?.message || err.toString(), 1500),
|
||||
showNotice('error', err?.message || err.toString()),
|
||||
);
|
||||
}
|
||||
|
||||
export async function openLogsDir() {
|
||||
return invoke<void>("open_logs_dir").catch((err) =>
|
||||
Notice.error(err?.message || err.toString(), 1500),
|
||||
showNotice('error', err?.message || err.toString()),
|
||||
);
|
||||
}
|
||||
|
||||
export async function openWebUrl(url: string) {
|
||||
return invoke<void>("open_web_url", { url });
|
||||
}
|
||||
export const openWebUrl = async (url: string) => {
|
||||
try {
|
||||
await invoke("open_web_url", { url });
|
||||
} catch (err: any) {
|
||||
showNotice('error', err.toString());
|
||||
}
|
||||
};
|
||||
|
||||
export async function cmdGetProxyDelay(
|
||||
name: string,
|
||||
@@ -214,7 +218,7 @@ export async function cmdTestDelay(url: string) {
|
||||
|
||||
export async function invoke_uwp_tool() {
|
||||
return invoke<void>("invoke_uwp_tool").catch((err) =>
|
||||
Notice.error(err?.message || err.toString(), 1500),
|
||||
showNotice('error', err?.message || err.toString(), 1500),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
80
src/services/noticeService.ts
Normal file
80
src/services/noticeService.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
export interface NoticeItem {
|
||||
id: number;
|
||||
type: 'success' | 'error' | 'info';
|
||||
message: ReactNode;
|
||||
duration: number;
|
||||
timerId?: ReturnType<typeof setTimeout>;
|
||||
}
|
||||
|
||||
type Listener = (notices: NoticeItem[]) => void;
|
||||
|
||||
let nextId = 0;
|
||||
let notices: NoticeItem[] = [];
|
||||
const listeners: Set<Listener> = new Set();
|
||||
|
||||
function notifyListeners() {
|
||||
listeners.forEach((listener) => listener([...notices])); // Pass a copy
|
||||
}
|
||||
|
||||
// Shows a notification.
|
||||
|
||||
export function showNotice(
|
||||
type: 'success' | 'error' | 'info',
|
||||
message: ReactNode,
|
||||
duration?: number,
|
||||
): number {
|
||||
const id = nextId++;
|
||||
const effectiveDuration =
|
||||
duration ?? (type === 'error' ? 8000 : type === 'info' ? 5000 : 3000); // Longer defaults
|
||||
|
||||
const newNotice: NoticeItem = {
|
||||
id,
|
||||
type,
|
||||
message,
|
||||
duration: effectiveDuration,
|
||||
};
|
||||
|
||||
// Auto-hide timer (only if duration is not null/0)
|
||||
if (effectiveDuration > 0) {
|
||||
newNotice.timerId = setTimeout(() => {
|
||||
hideNotice(id);
|
||||
}, effectiveDuration);
|
||||
}
|
||||
|
||||
|
||||
notices = [...notices, newNotice];
|
||||
notifyListeners();
|
||||
return id;
|
||||
}
|
||||
|
||||
// Hides a specific notification by its ID.
|
||||
|
||||
export function hideNotice(id: number) {
|
||||
const notice = notices.find((n) => n.id === id);
|
||||
if (notice?.timerId) {
|
||||
clearTimeout(notice.timerId); // Clear timeout if manually closed
|
||||
}
|
||||
notices = notices.filter((n) => n.id !== id);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
// Subscribes a listener function to notice state changes.
|
||||
|
||||
export function subscribeNotices(listener: Listener): () => void {
|
||||
listeners.add(listener);
|
||||
listener([...notices]);
|
||||
return () => {
|
||||
listeners.delete(listener);
|
||||
};
|
||||
}
|
||||
|
||||
// Function to clear all notices at once
|
||||
export function clearAllNotices() {
|
||||
notices.forEach(n => {
|
||||
if (n.timerId) clearTimeout(n.timerId);
|
||||
});
|
||||
notices = [];
|
||||
notifyListeners();
|
||||
}
|
||||
Reference in New Issue
Block a user