feat(notifications): link the subscribe activity to the channel
The "Subscribed on YouTube" inbox entry now names the channel and offers two convenience links that survive a reload (driven by the typed payload, not the live callback): "Channel manager" (jumps to the manager focused on that channel) and "Open on YouTube". Wires the panel to the app's focus-channel navigation; trilingual strings.
This commit is contained in:
parent
fb6f0c5dcb
commit
75ecf19147
5 changed files with 35 additions and 2 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { useEffect, useSyncExternalStore } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { Bell, Check, CheckCheck, Eye, RotateCcw, Search, Trash2, X } from "lucide-react";
|
||||
import { Bell, Check, CheckCheck, ExternalLink, Eye, RotateCcw, Search, Trash2, Tv, X } from "lucide-react";
|
||||
import { api, type AppNotification, type FeedFilters } from "../lib/api";
|
||||
import { useLiveQuery } from "../lib/useLiveQuery";
|
||||
import {
|
||||
|
|
@ -14,6 +14,7 @@ import {
|
|||
resolveVideo,
|
||||
subscribe,
|
||||
type Notification as ClientNotif,
|
||||
type ChannelSubscribedMeta,
|
||||
type VideoHiddenMeta,
|
||||
type VideoWatchedMeta,
|
||||
} from "../lib/notifications";
|
||||
|
|
@ -46,10 +47,12 @@ export default function NotificationsPanel({
|
|||
filters,
|
||||
setFilters,
|
||||
setPage,
|
||||
onFocusChannel,
|
||||
}: {
|
||||
filters: FeedFilters;
|
||||
setFilters: (f: FeedFilters) => void;
|
||||
setPage: (p: Page) => void;
|
||||
onFocusChannel: (name: string) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const qc = useQueryClient();
|
||||
|
|
@ -183,6 +186,7 @@ export default function NotificationsPanel({
|
|||
t={t}
|
||||
onFind={locateHidden}
|
||||
onRevert={revertState}
|
||||
onFocusChannel={onFocusChannel}
|
||||
onRemove={() => removeClient(n.id)}
|
||||
/>
|
||||
))}
|
||||
|
|
@ -287,18 +291,22 @@ function ClientActivityRow({
|
|||
t,
|
||||
onFind,
|
||||
onRevert,
|
||||
onFocusChannel,
|
||||
onRemove,
|
||||
}: {
|
||||
n: ClientNotif;
|
||||
t: (k: string, o?: any) => string;
|
||||
onFind: (meta: VideoHiddenMeta) => void;
|
||||
onRevert: (meta: VideoHiddenMeta | VideoWatchedMeta) => void;
|
||||
onFocusChannel: (name: string) => void;
|
||||
onRemove: () => void;
|
||||
}) {
|
||||
const { icon: Icon, color } = LEVEL_STYLE[n.level];
|
||||
const needsAction = n.requiresInteraction && !n.dismissed;
|
||||
const hidden = n.meta?.kind === "video-hidden" ? n.meta : null;
|
||||
const watched = n.meta?.kind === "video-watched" ? n.meta : null;
|
||||
const subscribed: ChannelSubscribedMeta | null =
|
||||
n.meta?.kind === "channel-subscribed" ? n.meta : null;
|
||||
return (
|
||||
<div
|
||||
className={`glass rounded-xl p-3.5 flex items-start gap-3 ${needsAction ? "ring-1 ring-accent/30" : ""}`}
|
||||
|
|
@ -342,6 +350,25 @@ function ClientActivityRow({
|
|||
{t("notifications.unwatch")}
|
||||
</button>
|
||||
</div>
|
||||
) : subscribed ? (
|
||||
<div className="flex items-center gap-3 mt-1">
|
||||
<button
|
||||
onClick={() => onFocusChannel(subscribed.channelName)}
|
||||
className="flex items-center gap-1 text-accent text-sm font-semibold hover:underline"
|
||||
>
|
||||
<Tv className="w-3.5 h-3.5" />
|
||||
{t("notifications.openInManager")}
|
||||
</button>
|
||||
<a
|
||||
href={`https://www.youtube.com/channel/${subscribed.channelId}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-1 text-accent text-sm font-semibold hover:underline"
|
||||
>
|
||||
<ExternalLink className="w-3.5 h-3.5" />
|
||||
{t("notifications.openOnYouTube")}
|
||||
</a>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
n.action &&
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue