One Calendar is a privacy-first calendar web app built with Next.js. It has modern security features, including e2ee, password-protected sharing, and self-destructing share links 📅 calendar.xyehr.cn
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

Delete utils directory

authored by

Evan Huang and committed by
GitHub
f9da62e2 125612b6

-109
-43
utils/notification-permission.ts
··· 1 - // 请求通知权限 2 - export function requestNotificationPermission() { 3 - if (typeof window !== "undefined" && "Notification" in window) { 4 - // 如果已经有权限,直接返回 5 - if (Notification.permission === "granted") { 6 - return Promise.resolve(true) 7 - } 8 - 9 - // 如果已经被拒绝,也直接返回 10 - if (Notification.permission === "denied") { 11 - return Promise.resolve(false) 12 - } 13 - 14 - // 否则请求权限 15 - return Notification.requestPermission().then((permission) => { 16 - return permission === "granted" 17 - }) 18 - } 19 - 20 - return Promise.resolve(false) 21 - } 22 - 23 - // 替换为不自动请求权限的版本 24 - export function checkNotificationPermission() { 25 - if (typeof window !== "undefined" && "Notification" in window) { 26 - // 如果已经有权限,直接返回 27 - if (Notification.permission === "granted") { 28 - return Promise.resolve(true) 29 - } 30 - 31 - // 如果已经被拒绝,也直接返回 32 - if (Notification.permission === "denied") { 33 - return Promise.resolve(false) 34 - } 35 - 36 - // 返回当前状态,但不自动请求权限 37 - // 只有在用户明确触发操作时才应该请求权限 38 - return Promise.resolve(false) 39 - } 40 - 41 - return Promise.resolve(false) 42 - } 43 -
-66
utils/notifications.tsx
··· 1 - import { toast } from "@/components/ui/use-toast"; 2 - import { ToastAction } from "@/components/ui/toast"; 3 - 4 - let notificationInterval: NodeJS.Timeout | null = null; 5 - 6 - export type NOTIFICATION_SOUNDS = "telegram"; 7 - 8 - const notificationSounds: Record<NOTIFICATION_SOUNDS, string> = { 9 - telegram: "https://cdn.xyehr.cn/source/Voicy_Telegram_notification.mp3", 10 - }; 11 - 12 - // 清除所有的通知计时器 13 - export const clearAllNotificationTimers = () => { 14 - if (notificationInterval) { 15 - clearInterval(notificationInterval); 16 - notificationInterval = null; 17 - } 18 - }; 19 - 20 - // 检查待处理的通知 21 - export const checkPendingNotifications = () => { 22 - const now = Date.now(); 23 - const pendingEvents = getPendingEvents(now); 24 - 25 - pendingEvents.forEach((event) => { 26 - triggerNotification(event); 27 - showToast(event); 28 - }); 29 - }; 30 - 31 - // 获取待处理的事件 32 - const getPendingEvents = (currentTime: number) => { 33 - const events = JSON.parse(localStorage.getItem("events") || "[]"); 34 - return events.filter((event: any) => event.notificationTime <= currentTime); 35 - }; 36 - 37 - // 播放通知声音 38 - const triggerNotification = (event: any) => { 39 - const sound = notificationSounds["telegram"]; 40 - new Audio(sound).play(); 41 - }; 42 - 43 - // 显示 Toast 通知 44 - const showToast = (event: any) => { 45 - toast({ 46 - title: `事件提醒:${event.title}`, 47 - description: event.description || "没有描述内容", 48 - duration: 4000, 49 - }); 50 - }; 51 - 52 - // 每隔一分钟检查一次通知 53 - export const startNotificationChecking = () => { 54 - if (!notificationInterval) { 55 - notificationInterval = setInterval(() => { 56 - checkPendingNotifications(); 57 - }, 60000); 58 - } 59 - }; 60 - 61 - export const stopNotificationChecking = () => { 62 - if (notificationInterval) { 63 - clearInterval(notificationInterval); 64 - notificationInterval = null; 65 - } 66 - };