Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ argon2 = "0.5"
rand = "0.10"
dirs = "5"
sha2 = "0.10"
# Legacy SHA-1 only used for Tencent COS HMAC-SHA1 signing (yuanbao
# channel media upload). Not used for any new security-sensitive work.
sha1 = "0.10"
hmac = "0.12"
# Archive extraction for the Node.js runtime bootstrap. Unix Node
# distributions ship as .tar.xz, Windows as .zip. `xz2` with `static`
Expand Down
1 change: 1 addition & 0 deletions app/src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 14 additions & 2 deletions app/src/components/channels/ChannelSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,36 @@ import { useT } from '../../lib/i18n/I18nContext';
import { useAppSelector } from '../../store/hooks';
import type { ChannelConnectionStatus, ChannelDefinition, ChannelType } from '../../types/channels';
import ChannelStatusBadge from './ChannelStatusBadge';
import YuanbaoIcon from './YuanbaoIcon';

interface ChannelSelectorProps {
definitions: ChannelDefinition[];
selectedChannel: ChannelType;
onSelectChannel: (channel: ChannelType) => void;
}

// Emoji icons for channels rendered as plain text. `yuanbao` is handled
// separately with a branded SVG (see `YuanbaoIcon`).
const CHANNEL_ICONS: Record<string, string> = {
telegram: '✈️',
discord: '🎮',
web: '🌐',
yuanbao: '🟡',
mcp: '🔌',
};

const renderChannelIcon = (icon: string) =>
icon === 'yuanbao' ? (
<YuanbaoIcon />
) : (
<span className="text-base">{CHANNEL_ICONS[icon] ?? ''}</span>
);

/** Virtual (static) tabs that are not backed by a ChannelDefinition from the core. */
const VIRTUAL_TABS: { id: ChannelType; display_name: string }[] = [
{ id: 'mcp', display_name: 'MCP Servers' },
];

const CHANNEL_STATUS_PRIORITY: ChannelConnectionStatus[] = [
'connected',
'connecting',
Expand Down Expand Up @@ -84,7 +96,7 @@ const ChannelSelector = ({
: 'border-stone-200 dark:border-neutral-800 bg-stone-50 dark:bg-neutral-800/60 text-stone-600 dark:text-neutral-300 hover:border-stone-300 dark:hover:border-neutral-700'
}`}>
<span className="flex items-center gap-2">
<span className="text-base">{CHANNEL_ICONS[def.icon] ?? ''}</span>
{renderChannelIcon(def.icon)}
<span className="font-medium">{def.display_name}</span>
</span>
<ChannelStatusBadge status={bestStatus} />
Expand All @@ -105,7 +117,7 @@ const ChannelSelector = ({
? 'border-primary-500/60 bg-primary-50 dark:bg-primary-500/15 text-primary-600 dark:text-primary-300'
: 'border-stone-200 dark:border-neutral-800 bg-stone-50 dark:bg-neutral-800/60 text-stone-600 dark:text-neutral-300 hover:border-stone-300 dark:hover:border-neutral-700'
}`}>
<span className="text-base">{CHANNEL_ICONS[tab.id] ?? ''}</span>
{renderChannelIcon(tab.id)}
<span className="font-medium">{tab.display_name}</span>
</button>
);
Expand Down
16 changes: 14 additions & 2 deletions app/src/components/channels/ChannelSetupModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import { useT } from '../../lib/i18n/I18nContext';
import type { ChannelDefinition, ChannelType } from '../../types/channels';
import DiscordConfig from './DiscordConfig';
import TelegramConfig from './TelegramConfig';
import YuanbaoConfig from './YuanbaoConfig';
import YuanbaoIcon from './YuanbaoIcon';

// Emoji icons for channels rendered as plain text. `yuanbao` is handled
// separately with a branded SVG (see `YuanbaoIcon`) — matches the
// rendering used in `ChannelSelector`.
const CHANNEL_ICONS: Record<string, string> = {
telegram: '\u2708\uFE0F',
discord: '\uD83C\uDFAE',
Expand All @@ -29,6 +34,8 @@ function ChannelConfigContent({ definition }: { definition: ChannelDefinition })
return <TelegramConfig definition={definition} />;
case 'discord':
return <DiscordConfig definition={definition} />;
case 'yuanbao':
return <YuanbaoConfig definition={definition} />;
default:
return (
<p className="text-sm text-stone-400 dark:text-neutral-500 py-4">
Expand Down Expand Up @@ -62,7 +69,8 @@ export default function ChannelSetupModal({ definition, onClose }: ChannelSetupM
if (e.target === e.currentTarget) onClose();
};

const icon = CHANNEL_ICONS[definition.icon] ?? '';
const emojiIcon = CHANNEL_ICONS[definition.icon] ?? '';
const isYuanbao = definition.icon === 'yuanbao';

Comment thread
coderabbitai[bot] marked this conversation as resolved.
const modalContent = (
<div
Expand All @@ -86,7 +94,11 @@ export default function ChannelSetupModal({ definition, onClose }: ChannelSetupM
<div className="flex items-start justify-between">
<div className="flex-1 min-w-0 pr-2">
<div className="flex items-center gap-2">
{icon && <span className="text-base">{icon}</span>}
{isYuanbao ? (
<YuanbaoIcon className="w-5 h-5" />
) : (
emojiIcon && <span className="text-base">{emojiIcon}</span>
)}
<h2
id="channel-setup-title"
className="text-base font-semibold text-stone-900 dark:text-neutral-100">
Expand Down
Loading