Spaces:
Running
Running
File size: 1,947 Bytes
6c3af4e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | import { addLogEntry } from "./logEntries";
const MAX_NOTIFICATION_QUERY_LENGTH = 100;
export const REQUEST_PERMISSION_TIMEOUT_MS = 8000;
/**
* Requests permission to show browser notifications. Some browsers can
* silently never resolve this request (e.g. Brave has been observed doing
* this on localhost), so it falls back to "default" after a timeout instead
* of leaving the caller waiting forever.
*/
export async function requestNotificationPermission(): Promise<NotificationPermission> {
if (!("Notification" in window)) {
return "denied";
}
if (Notification.permission === "granted") {
return "granted";
}
if (Notification.permission === "denied") {
return "denied";
}
return new Promise((resolve) => {
const timeoutId = setTimeout(
() => resolve("default"),
REQUEST_PERMISSION_TIMEOUT_MS,
);
Notification.requestPermission().then((permission) => {
clearTimeout(timeoutId);
resolve(permission);
});
});
}
/**
* Shows a browser notification that the AI answer is ready, unless this page
* already has the focus.
*/
export function showAiCompleteNotification(query: string) {
if (!("Notification" in window)) {
return;
}
if (Notification.permission !== "granted") {
return;
}
if (document.hasFocus()) {
return;
}
const truncatedQuery =
query.length > MAX_NOTIFICATION_QUERY_LENGTH
? `${query.slice(0, MAX_NOTIFICATION_QUERY_LENGTH)}โฆ`
: query;
try {
const notification = new Notification(truncatedQuery, {
body: "AI response is ready on MiniSearch.",
icon: "/favicon.png",
tag: "ai-complete",
requireInteraction: false,
});
notification.onclick = () => {
window.focus();
notification.close();
};
} catch (error) {
addLogEntry(
`Failed to show AI-complete notification: ${error instanceof Error ? error.message : String(error)}`,
);
}
}
|