Files
buzz/desktop/src/app/useAppShellLifecycleEffects.ts
2026-07-19 22:09:56 +02:00

80 lines
2.3 KiB
TypeScript

import * as React from "react";
import { setDesktopAppBadge } from "@/features/notifications/lib/desktop";
import { relayClient } from "@/shared/api/relayClient";
type AppShellLifecycleEffectsOptions = {
homeBadgeCountExcludingHighPriority: number;
unreadChannelIds: ReadonlySet<string>;
unreadChannelNotificationCount: number;
};
export function useAppShellLifecycleEffects({
homeBadgeCountExcludingHighPriority,
unreadChannelIds,
unreadChannelNotificationCount,
}: AppShellLifecycleEffectsOptions) {
// Prevent webview file:/// navigation on file drop outside the composer.
// Scoped to file drags only (text drag-and-drop into inputs still works).
// Composer's onDrop fires first (React synthetic before window bubble).
React.useEffect(() => {
function preventNavigation(e: DragEvent) {
if (e.dataTransfer?.types.includes("Files")) {
e.preventDefault();
}
}
window.addEventListener("dragover", preventNavigation);
window.addEventListener("drop", preventNavigation);
return () => {
window.removeEventListener("dragover", preventNavigation);
window.removeEventListener("drop", preventNavigation);
};
}, []);
React.useEffect(() => {
let isCancelled = false;
const startPreconnect = () => {
if (isCancelled) {
return;
}
void relayClient.preconnect().catch((error) => {
if (!isCancelled) {
console.error("Failed to preconnect to relay", error);
}
});
};
if ("requestIdleCallback" in window) {
const idleId = window.requestIdleCallback(startPreconnect, {
timeout: 1_500,
});
return () => {
isCancelled = true;
window.cancelIdleCallback(idleId);
};
}
const timeoutId = globalThis.setTimeout(startPreconnect, 250);
return () => {
isCancelled = true;
globalThis.clearTimeout(timeoutId);
};
}, []);
React.useEffect(() => {
const count =
unreadChannelNotificationCount + homeBadgeCountExcludingHighPriority;
void setDesktopAppBadge(
count
? { kind: "count", count }
: { kind: unreadChannelIds.size ? "dot" : "none" },
);
}, [
homeBadgeCountExcludingHighPriority,
unreadChannelIds,
unreadChannelNotificationCount,
]);
}