mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
136 lines
4.4 KiB
TypeScript
136 lines
4.4 KiB
TypeScript
// Copyright 2024, Command Line Inc.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
import { atoms, getApi } from "@/store/global";
|
|
import { useAtom, useAtomValue } from "jotai";
|
|
import { useCallback, useEffect, useState } from "react";
|
|
|
|
const notificationActions: { [key: string]: () => void } = {
|
|
installUpdate: () => {
|
|
getApi().installAppUpdate();
|
|
},
|
|
// Add other action functions here
|
|
};
|
|
|
|
export function useNotification() {
|
|
const notificationPopoverMode = useAtomValue(atoms.notificationPopoverMode);
|
|
const [notifications, setNotifications] = useAtom(atoms.notifications);
|
|
const [hoveredId, setHoveredId] = useState<string | null>(null);
|
|
|
|
const removeNotification = useCallback(
|
|
(id: string) => {
|
|
setNotifications((prevNotifications) => prevNotifications.filter((n) => n.id !== id));
|
|
},
|
|
[setNotifications]
|
|
);
|
|
|
|
const hideNotification = useCallback(
|
|
(id: string) => {
|
|
setNotifications((prevNotifications) =>
|
|
prevNotifications.map((n) => (n.id === id ? { ...n, hidden: true } : n))
|
|
);
|
|
},
|
|
[setNotifications]
|
|
);
|
|
|
|
const hideAllNotifications = useCallback(() => {
|
|
setNotifications((prevNotifications) => prevNotifications.map((n) => ({ ...n, hidden: true })));
|
|
}, [setNotifications]);
|
|
|
|
const removeAllNotifications = useCallback(() => {
|
|
setNotifications((prevNotifications) => prevNotifications.filter((n) => n.persistent));
|
|
}, [setNotifications]);
|
|
|
|
const copyNotification = useCallback(
|
|
(id: string) => {
|
|
const notif = notifications.find((n) => n.id === id);
|
|
if (!notif) return;
|
|
|
|
let text = notif.title ?? "";
|
|
if (notif.message) {
|
|
text += text.length > 0 ? `\n${notif.message}` : notif.message;
|
|
}
|
|
navigator.clipboard
|
|
.writeText(text)
|
|
.then(() => {
|
|
console.info("Text copied to clipboard");
|
|
})
|
|
.catch((err) => {
|
|
console.error("Failed to copy text: ", err);
|
|
});
|
|
},
|
|
[notifications]
|
|
);
|
|
|
|
const handleActionClick = useCallback(
|
|
(e: React.MouseEvent, action: NotificationActionType, id: string) => {
|
|
e.stopPropagation();
|
|
const actionFn = notificationActions[action.actionKey];
|
|
if (actionFn) {
|
|
actionFn();
|
|
removeNotification(id);
|
|
} else {
|
|
console.warn(`No action found for key: ${action.actionKey}`);
|
|
}
|
|
},
|
|
[removeNotification]
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (notificationPopoverMode) {
|
|
return;
|
|
}
|
|
|
|
const hasExpiringNotifications = notifications.some((notif) => notif.expiration);
|
|
if (!hasExpiringNotifications) {
|
|
return;
|
|
}
|
|
|
|
const intervalId = setInterval(() => {
|
|
const now = Date.now();
|
|
|
|
setNotifications((prevNotifications) =>
|
|
prevNotifications.filter(
|
|
(notif) => !notif.expiration || notif.expiration > now || notif.id === hoveredId
|
|
)
|
|
);
|
|
}, 1000);
|
|
|
|
return () => clearInterval(intervalId);
|
|
}, [notificationPopoverMode, notifications, hoveredId, setNotifications]);
|
|
|
|
const formatTimestamp = (timestamp: string): string => {
|
|
const notificationTime = new Date(timestamp).getTime();
|
|
const now = Date.now();
|
|
const diffInSeconds = Math.floor((now - notificationTime) / 1000);
|
|
const diffInMinutes = Math.floor(diffInSeconds / 60);
|
|
const diffInHours = Math.floor(diffInMinutes / 60);
|
|
const diffInDays = Math.floor(diffInHours / 24);
|
|
|
|
if (diffInMinutes === 0) {
|
|
return `Just now`;
|
|
} else if (diffInMinutes < 60) {
|
|
return `${diffInMinutes} mins ago`;
|
|
} else if (diffInHours < 24) {
|
|
return `${diffInHours} hrs ago`;
|
|
} else if (diffInDays < 7) {
|
|
return `${diffInDays} days ago`;
|
|
} else {
|
|
return new Date(timestamp).toLocaleString();
|
|
}
|
|
};
|
|
|
|
return {
|
|
notifications,
|
|
hoveredId,
|
|
setHoveredId,
|
|
removeNotification,
|
|
removeAllNotifications,
|
|
hideNotification,
|
|
hideAllNotifications,
|
|
copyNotification,
|
|
handleActionClick,
|
|
formatTimestamp,
|
|
};
|
|
}
|