CI/CD Pipeline / Build and Push PocketBase Docker Image (push) Successful in 10s
CI/CD Pipeline / i18n Catalog Check (push) Successful in 43s
CI/CD Pipeline / Build and Push App Docker Image (push) Successful in 2m14s
CI/CD Pipeline / Deploy to Kubernetes (push) Successful in 8m29s
121 lines
3.6 KiB
TypeScript
121 lines
3.6 KiB
TypeScript
import { useState } from "react";
|
|
import { Box, Title, Stack, Switch, Button, Text, Group } from "@mantine/core";
|
|
import { Trans, useLingui } from "@lingui/react/macro";
|
|
import { useWebPush } from "@/hooks/use-web-push";
|
|
import { useAuth } from "@/contexts/auth-context";
|
|
import { useIsDeveloper } from "@/features/core/hooks/use-is-developer";
|
|
import { updateUserTelemetryAlerts } from "@/features/settings/server";
|
|
import toast from "@/lib/sonner";
|
|
|
|
const TelemetryAlertsSwitch = () => {
|
|
const { t } = useLingui();
|
|
const { metadata, set } = useAuth();
|
|
const [saving, setSaving] = useState(false);
|
|
|
|
const handleToggle = async (checked: boolean) => {
|
|
setSaving(true);
|
|
try {
|
|
const result = await updateUserTelemetryAlerts({ data: checked });
|
|
if (result?.metadata) {
|
|
set({ metadata: result.metadata });
|
|
}
|
|
} catch {
|
|
toast.error(t`Couldn't update telemetry alerts`);
|
|
} finally {
|
|
setSaving(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Switch
|
|
checked={metadata?.telemetryAlerts === true}
|
|
onChange={(e) => handleToggle(e.currentTarget.checked)}
|
|
disabled={saving}
|
|
label={t`Telemetry alerts`}
|
|
description={t`Error spikes and failing functions, pushed to this account`}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export function NotificationsSection() {
|
|
const { supported, configured, permission, subscribed, busy, enable, disable, sendTest } =
|
|
useWebPush();
|
|
const isDeveloper = useIsDeveloper();
|
|
const { t } = useLingui();
|
|
|
|
if (!supported || !configured) {
|
|
return (
|
|
<Box
|
|
px="md"
|
|
py="sm"
|
|
style={{ borderBottom: "1px solid var(--mantine-color-default-border)" }}
|
|
>
|
|
<Title order={3}><Trans>Notifications</Trans></Title>
|
|
<Text size="sm" c="dimmed" mt="xs">
|
|
{supported
|
|
? <Trans>Notifications aren't available right now.</Trans>
|
|
: <Trans>This device doesn't support push notifications. On iOS, install the app to your Home Screen first.</Trans>}
|
|
</Text>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
const handleToggle = async (checked: boolean) => {
|
|
if (checked) {
|
|
const ok = await enable();
|
|
if (ok) {
|
|
toast.success(t`Notifications enabled on this device`);
|
|
} else if (permission === "denied") {
|
|
toast.error(
|
|
t`Notifications are blocked. Enable them in your browser settings.`
|
|
);
|
|
} else {
|
|
toast.error(t`Couldn't enable notifications`);
|
|
}
|
|
} else {
|
|
const ok = await disable();
|
|
if (ok) toast.success(t`Notifications disabled on this device`);
|
|
else toast.error(t`Couldn't disable notifications`);
|
|
}
|
|
};
|
|
|
|
const handleTest = async () => {
|
|
const ok = await sendTest();
|
|
if (ok) toast.success(t`Test notification sent`);
|
|
else toast.error(t`Couldn't send test notification`);
|
|
};
|
|
|
|
return (
|
|
<Box
|
|
px="md"
|
|
py="sm"
|
|
style={{ borderBottom: "1px solid var(--mantine-color-default-border)" }}
|
|
>
|
|
<Title order={3}><Trans>Notifications</Trans></Title>
|
|
<Stack mt="xs" gap="sm">
|
|
<Switch
|
|
checked={subscribed}
|
|
onChange={(e) => handleToggle(e.currentTarget.checked)}
|
|
disabled={busy}
|
|
label={t`Enable notifications on this device`}
|
|
/>
|
|
{subscribed && isDeveloper && <TelemetryAlertsSwitch />}
|
|
{subscribed && (
|
|
<Group>
|
|
<Button
|
|
variant="light"
|
|
size="xs"
|
|
onClick={handleTest}
|
|
loading={busy}
|
|
>
|
|
<Trans>Send test notification</Trans>
|
|
</Button>
|
|
</Group>
|
|
)}
|
|
</Stack>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
export default NotificationsSection;
|