feat(telegram): add Topics action to forum channels in Channels tab

Forum source channels get a Topics menu item that opens the TopicsDrawer.
Non-forum channels are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-22 04:15:46 +02:00
parent 7e58cc29fa
commit 25ff067ea0
2 changed files with 25 additions and 0 deletions

View File

@@ -9,6 +9,7 @@ import {
ArrowUpFromLine, ArrowUpFromLine,
RefreshCcw, RefreshCcw,
Tag, Tag,
MessagesSquare,
} from "lucide-react"; } from "lucide-react";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -27,6 +28,7 @@ interface ChannelColumnsProps {
onSetType: (id: string, type: "SOURCE" | "DESTINATION") => void; onSetType: (id: string, type: "SOURCE" | "DESTINATION") => void;
onRescan: (id: string) => void; onRescan: (id: string) => void;
onSetCategory: (id: string, category: string | null) => void; onSetCategory: (id: string, category: string | null) => void;
onManageTopics: (id: string) => void;
} }
export function getChannelColumns({ export function getChannelColumns({
@@ -35,6 +37,7 @@ export function getChannelColumns({
onSetType, onSetType,
onRescan, onRescan,
onSetCategory, onSetCategory,
onManageTopics,
}: ChannelColumnsProps): ColumnDef<ChannelRow, unknown>[] { }: ChannelColumnsProps): ColumnDef<ChannelRow, unknown>[] {
return [ return [
{ {
@@ -147,6 +150,14 @@ export function getChannelColumns({
Rescan Channel Rescan Channel
</DropdownMenuItem> </DropdownMenuItem>
)} )}
{row.original.type === "SOURCE" && row.original.isForum && (
<DropdownMenuItem
onClick={() => onManageTopics(row.original.id)}
>
<MessagesSquare className="mr-2 h-3.5 w-3.5" />
Topics
</DropdownMenuItem>
)}
<DropdownMenuItem <DropdownMenuItem
onClick={() => { onClick={() => {
const cat = prompt("Enter category (e.g. STL, PDF, D&D, Cosplay):", row.original.category ?? ""); const cat = prompt("Enter category (e.g. STL, PDF, D&D, Cosplay):", row.original.category ?? "");

View File

@@ -7,6 +7,7 @@ import { getChannelColumns } from "./channel-columns";
import { DestinationCard } from "./destination-card"; import { DestinationCard } from "./destination-card";
import { ChannelPickerDialog } from "./channel-picker-dialog"; import { ChannelPickerDialog } from "./channel-picker-dialog";
import { JoinChannelDialog } from "./join-channel-dialog"; import { JoinChannelDialog } from "./join-channel-dialog";
import { TopicsDrawer } from "./topics-drawer";
import { import {
deleteChannel, deleteChannel,
toggleChannelActive, toggleChannelActive,
@@ -32,6 +33,7 @@ export function ChannelsTab({ channels, globalDestination, accounts }: ChannelsT
const [rescanId, setRescanId] = useState<string | null>(null); const [rescanId, setRescanId] = useState<string | null>(null);
const [fetchChannelsAccountId, setFetchChannelsAccountId] = useState<string | null>(null); const [fetchChannelsAccountId, setFetchChannelsAccountId] = useState<string | null>(null);
const [joinDialogOpen, setJoinDialogOpen] = useState(false); const [joinDialogOpen, setJoinDialogOpen] = useState(false);
const [topicsChannelId, setTopicsChannelId] = useState<string | null>(null);
// Find the first authenticated account for "Fetch Channels" // Find the first authenticated account for "Fetch Channels"
const authenticatedAccounts = accounts.filter((a) => a.authState === "AUTHENTICATED" && a.isActive); const authenticatedAccounts = accounts.filter((a) => a.authState === "AUTHENTICATED" && a.isActive);
@@ -60,6 +62,7 @@ export function ChannelsTab({ channels, globalDestination, accounts }: ChannelsT
else toast.error(result.error); else toast.error(result.error);
}); });
}, },
onManageTopics: (id) => setTopicsChannelId(id),
}); });
const { table } = useDataTable({ const { table } = useDataTable({
@@ -167,6 +170,17 @@ export function ChannelsTab({ channels, globalDestination, accounts }: ChannelsT
open={joinDialogOpen} open={joinDialogOpen}
onOpenChange={setJoinDialogOpen} onOpenChange={setJoinDialogOpen}
/> />
<TopicsDrawer
channelId={topicsChannelId}
channelTitle={
channels.find((c) => c.id === topicsChannelId)?.title
}
open={!!topicsChannelId}
onOpenChange={(open) => {
if (!open) setTopicsChannelId(null);
}}
/>
</div> </div>
); );
} }