import type { AdminChannelRecord } from "../../../lib/types"; import { Notice } from "../../components"; import { Surface, Tag } from "../../../components/primitives"; import { PLATFORM_LABEL } from "../channelFields"; import { adminOpsOf, capabilityMeta, hasCapability } from "./channelCapabilities"; /** Generic per-adapter shell for platforms without a specialised panel (design/17 * §2). KOOK gets KookPanel; every other platform renders this honest shell. It * shows the platform label + account, the capabilities the adapter declares * (from `record.accounts[].capabilities`), a placeholder for platform-specific * feature areas (still to be wired), and a proactive-push note. It never * fabricates data, buttons, or friend/channel lists — non-KOOK platforms have no * backend /view endpoint yet, so the page only displays capability + placeholders * + the generic connect/disconnect/log/identity actions rendered above it. */ export function GenericAdapterPanel({ platform, accountId, record, recordUnknown = false, }: { platform: string; accountId?: string; record?: AdminChannelRecord; /** The channel list could not be read (backend unreachable): capability/account * emptiness is then unverified, so never present it as "declares nothing". */ recordUnknown?: boolean; }): React.ReactNode { const label = PLATFORM_LABEL[platform] ?? platform; const account = record?.accounts?.find((a) => accountId === undefined ? (!a.id || a.id === "default") : a.id === accountId, ); const caps = account?.capabilities ?? []; const accountName = account?.botNickname || (account?.botUsername ? `@${account.botUsername}` : accountId ?? "default"); return (
{label} 平台能力 {accountName} {account?.botId ? bot_id:{account.botId} : null} 通用壳 · 平台专属端点未接入
); } /** Capability badges: what this adapter declares it supports. Empty → honest note. */ function CapabilityBadges({ caps, recordUnknown }: { caps: readonly string[]; recordUnknown: boolean }): React.ReactNode { return (

平台能力

{caps.length === 0 ? ( {recordUnknown ? "读取失败(与后端失联),无法确认该适配器声明的能力;请先确认后端在线后重试。" : "该适配器尚未声明能力列表;平台专属端点未接入,当前仅提供通用操作(连接 / 断开 / 消息日志 / 身份测试)。"} ) : (
{caps.map((c) => { const m = capabilityMeta(c); return ( {m.label} ); })}
)}
); } /** Placeholder for future platform-specific feature areas (friends/channels/members/ * test-send). Only the admin-operations the adapter actually declares surface here, * each marked as not yet wired. */ function FeaturePlaceholder({ caps, recordUnknown }: { caps: readonly string[]; recordUnknown: boolean }): React.ReactNode { const adminOps = adminOpsOf(caps); return (

平台专属功能区(占位)

{adminOps.length === 0 ? ( {recordUnknown ? "读取失败(与后端失联),无法确认该平台的专属功能模块;请先确认后端在线后重试。" : "该平台暂无已声明的专属功能模块。频道 / 成员 / 发送测试等平台能力将随后续接入后在此显示。"} ) : ( <>
{adminOps.map((op) => ( {capabilityMeta(op).label} · 后续接入 ))}
以上模块为占位展示,对应后端专属端点尚未接入,当前不提供真实数据 / 操作。 )}
); } /** Proactive-push note: declared → placeholder; otherwise an honest "not supported". */ function ProactiveNote({ caps, recordUnknown }: { caps: readonly string[]; recordUnknown: boolean }): React.ReactNode { const supported = hasCapability(caps, "Proactive"); return (

主动推送

{supported ? ( 主动推送(占位,后端待接):该适配器声明了主动推送能力,定时 / 主动消息功能待后端接入。 ) : recordUnknown ? ( 读取失败(与后端失联),无法确认该适配器是否支持主动推送;请先确认后端在线后重试。 ) : ( 当前适配器未声明主动推送能力(Proactive),不支持主动 / 定时消息;仅在被对话触发时响应。 )}
); }