refactor(integrations): retire unavailable options
Remove retired Command Code, Discord, and Telegram integration entries, search targets, and documentation. Keep Command Code provider usage and logo support available through normalized provider ID aliases.
This commit is contained in:
@@ -1,74 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '@/components/icon/Icon';
|
||||
import { SettingsSection } from '@/components/sections/shared/SettingsSection';
|
||||
import type { IconName } from '@/components/icon/icons';
|
||||
import { useI18n, type I18nKey } from '@/lib/i18n';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
type ComingSoonMessenger = {
|
||||
id: 'discord' | 'telegram';
|
||||
icon: IconName;
|
||||
brandClassName: string;
|
||||
nameKey: I18nKey;
|
||||
descriptionKey: I18nKey;
|
||||
};
|
||||
|
||||
const COMING_SOON_MESSENGERS: readonly ComingSoonMessenger[] = [
|
||||
{
|
||||
id: 'discord',
|
||||
icon: 'discord-fill',
|
||||
brandClassName: 'text-[#5865F2]',
|
||||
nameKey: 'settings.integrations.messengers.discord.name',
|
||||
descriptionKey: 'settings.integrations.messengers.discord.description',
|
||||
},
|
||||
{
|
||||
id: 'telegram',
|
||||
icon: 'telegram-fill',
|
||||
brandClassName: 'text-[#2AABEE]',
|
||||
nameKey: 'settings.integrations.messengers.telegram.name',
|
||||
descriptionKey: 'settings.integrations.messengers.telegram.description',
|
||||
},
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Non-interactive Discord/Telegram placeholders — same card chrome as live
|
||||
* integrations, greyed out, with a Coming soon badge and no expandable body.
|
||||
*/
|
||||
export const ComingSoonMessengersSection: React.FC = () => {
|
||||
const { t } = useI18n();
|
||||
|
||||
return (
|
||||
<SettingsSection
|
||||
title={t('settings.integrations.messengers.title')}
|
||||
info={t('settings.integrations.messengers.info')}
|
||||
divider={false}
|
||||
settingsItem="integrations.messengers"
|
||||
contentClassName="space-y-3"
|
||||
>
|
||||
{COMING_SOON_MESSENGERS.map((messenger) => (
|
||||
<div
|
||||
key={messenger.id}
|
||||
data-settings-item={`integrations.messengers.${messenger.id}`}
|
||||
aria-disabled="true"
|
||||
className={cn(
|
||||
'flex min-w-0 items-center gap-3 rounded-xl border border-[var(--interactive-border)] bg-[var(--surface-elevated)] px-4 py-3',
|
||||
'pointer-events-none opacity-60',
|
||||
)}
|
||||
>
|
||||
<div className="flex size-10 shrink-0 items-center justify-center rounded-[10px] bg-[var(--surface-muted)]">
|
||||
<Icon name={messenger.icon} className={cn('size-5', messenger.brandClassName)} />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="truncate text-sm font-semibold text-foreground">{t(messenger.nameKey)}</div>
|
||||
<p className="mt-0.5 line-clamp-1 text-xs leading-snug text-muted-foreground">
|
||||
{t(messenger.descriptionKey)}
|
||||
</p>
|
||||
</div>
|
||||
<span className="max-w-36 shrink-0 truncate rounded-full bg-[var(--surface-muted)] px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
|
||||
{t('settings.common.state.comingSoon')}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</SettingsSection>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '@/components/icon/Icon';
|
||||
import { SettingsPageLayout } from '@/components/sections/shared/SettingsPageLayout';
|
||||
import { SETTINGS_DESCRIPTION_CLASS } from '@/components/sections/shared/SettingsSection';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { ThirdPartyIntegrationsSection } from './ThirdPartyIntegrationsSection';
|
||||
|
||||
@@ -18,15 +19,19 @@ export const IntegrationsPage: React.FC<IntegrationsPageProps> = ({
|
||||
return (
|
||||
<SettingsPageLayout
|
||||
title={t('settings.page.integrations.title')}
|
||||
description={t('settings.page.integrations.description')}
|
||||
description={(
|
||||
<div className="space-y-3">
|
||||
<p className={SETTINGS_DESCRIPTION_CLASS}>{t('settings.page.integrations.description')}</p>
|
||||
<div role="alert" className="flex items-start gap-2 rounded-lg border border-[var(--status-warning-border)] bg-[var(--status-warning-background)] p-3">
|
||||
<Icon name="error-warning" className="mt-0.5 size-4 shrink-0 text-[var(--status-warning)]" />
|
||||
<p className="typography-meta text-[var(--status-warning)]">
|
||||
{t('settings.integrations.experimentalWarning')}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
showSaveStatus={false}
|
||||
>
|
||||
<div className="flex items-start gap-2 rounded-lg border border-[var(--status-warning-border)] bg-[var(--status-warning-background)] p-3">
|
||||
<Icon name="error-warning" className="mt-0.5 size-4 shrink-0 text-[var(--status-warning)]" />
|
||||
<p className="typography-meta text-[var(--status-warning)]">
|
||||
{t('settings.integrations.experimentalWarning')}
|
||||
</p>
|
||||
</div>
|
||||
<ThirdPartyIntegrationsSection
|
||||
divider={false}
|
||||
onOpenProviderSetup={onOpenProviderSetup}
|
||||
|
||||
@@ -13,7 +13,6 @@ import { toast } from '@/components/ui';
|
||||
import { Icon } from '@/components/icon/Icon';
|
||||
import { SettingsSection } from '@/components/sections/shared/SettingsSection';
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
|
||||
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
import { openExternalUrl } from '@/lib/url';
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -330,11 +329,7 @@ export const ThirdPartyIntegrationsSection: React.FC<ThirdPartyIntegrationsSecti
|
||||
className="flex w-full min-w-0 items-center gap-3 px-4 py-3 text-left hover:bg-[var(--interactive-hover)]/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--interactive-focus-ring)]"
|
||||
>
|
||||
<div className="flex size-10 shrink-0 items-center justify-center rounded-[10px] bg-[var(--surface-muted)]">
|
||||
{plugin.providerId === 'command-code' ? (
|
||||
<ProviderLogo providerId={plugin.providerId} className="size-5" />
|
||||
) : (
|
||||
<Icon name={plugin.icon} className={cn('size-5', plugin.brandClassName)} />
|
||||
)}
|
||||
<Icon name={plugin.icon} className={cn('size-5', plugin.brandClassName)} />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="truncate text-sm font-semibold text-foreground">{t(plugin.nameKey)}</div>
|
||||
|
||||
@@ -131,11 +131,6 @@ describe('third-party plugin catalog helpers', () => {
|
||||
packageName: '@openchamber/opencode-claude',
|
||||
homepage: 'https://github.com/openchamber/opencode-claude',
|
||||
},
|
||||
{
|
||||
id: 'opencode-commandcode',
|
||||
packageName: '@openchamber/opencode-commandcode',
|
||||
homepage: 'https://github.com/openchamber/opencode-commandcode',
|
||||
},
|
||||
{
|
||||
id: 'opencode-cursor-oauth',
|
||||
packageName: '@openchamber/opencode-cursor',
|
||||
|
||||
@@ -25,16 +25,6 @@ export const THIRD_PARTY_PLUGINS: readonly ThirdPartyPluginDefinition[] = [
|
||||
descriptionKey: 'settings.integrations.thirdParty.opencodeClaude.description',
|
||||
homepage: 'https://github.com/openchamber/opencode-claude',
|
||||
},
|
||||
{
|
||||
id: 'opencode-commandcode',
|
||||
packageName: '@openchamber/opencode-commandcode',
|
||||
providerId: 'command-code',
|
||||
icon: 'command-code',
|
||||
brandClassName: 'text-foreground',
|
||||
nameKey: 'settings.integrations.thirdParty.opencodeCommandcode.name',
|
||||
descriptionKey: 'settings.integrations.thirdParty.opencodeCommandcode.description',
|
||||
homepage: 'https://github.com/openchamber/opencode-commandcode',
|
||||
},
|
||||
{
|
||||
id: 'opencode-cursor-oauth',
|
||||
packageName: '@openchamber/opencode-cursor',
|
||||
|
||||
Reference in New Issue
Block a user