🐛 fix(api): Update subscription_protocol to subscribe_type for consistency across services
This commit is contained in:
parent
9d8b814212
commit
b6da51b618
@ -42,7 +42,7 @@ import { z } from 'zod';
|
||||
const platforms = ['windows', 'macos', 'linux', 'android', 'ios', 'harmony'];
|
||||
|
||||
const defaultValues = {
|
||||
subscription_protocol: 'Clash',
|
||||
subscribe_type: 'Clash',
|
||||
name: '',
|
||||
icon: '',
|
||||
url: '',
|
||||
@ -58,7 +58,7 @@ const versionSchema = z.object({
|
||||
const formSchema = z.object({
|
||||
icon: z.string(),
|
||||
name: z.string(),
|
||||
subscription_protocol: z.string(),
|
||||
subscribe_type: z.string(),
|
||||
platform: z.object({
|
||||
windows: z.array(versionSchema).optional(),
|
||||
macos: z.array(versionSchema).optional(),
|
||||
@ -172,7 +172,7 @@ export default function SubscribeAppForm<
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name='subscription_protocol'
|
||||
name='subscribe_type'
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('subscriptionProtocol')}</FormLabel>
|
||||
|
||||
@ -76,9 +76,9 @@ export default function SubscribeApp() {
|
||||
header: t('appName'),
|
||||
},
|
||||
{
|
||||
accessorKey: 'subscription_protocol',
|
||||
accessorKey: 'subscribe_type',
|
||||
header: t('subscriptionProtocol'),
|
||||
cell: ({ row }) => row.getValue('subscription_protocol'),
|
||||
cell: ({ row }) => row.getValue('subscribe_type'),
|
||||
},
|
||||
]}
|
||||
actions={{
|
||||
|
||||
2
apps/admin/services/admin/typings.d.ts
vendored
2
apps/admin/services/admin/typings.d.ts
vendored
@ -50,7 +50,7 @@ declare namespace API {
|
||||
name: string;
|
||||
icon: string;
|
||||
description: string;
|
||||
subscription_protocol: string;
|
||||
subscribe_type: string;
|
||||
platform: ApplicationPlatform;
|
||||
};
|
||||
|
||||
|
||||
2
apps/admin/services/common/typings.d.ts
vendored
2
apps/admin/services/common/typings.d.ts
vendored
@ -42,7 +42,7 @@ declare namespace API {
|
||||
name: string;
|
||||
icon: string;
|
||||
description: string;
|
||||
subscription_protocol: string;
|
||||
subscribe_type: string;
|
||||
platform: ApplicationPlatform;
|
||||
};
|
||||
|
||||
|
||||
@ -43,6 +43,15 @@ import CopyToClipboard from 'react-copy-to-clipboard';
|
||||
import { toast } from 'sonner';
|
||||
import Subscribe from '../subscribe/page';
|
||||
|
||||
const platforms: (keyof API.ApplicationPlatform)[] = [
|
||||
'windows',
|
||||
'mac',
|
||||
'linux',
|
||||
'ios',
|
||||
'android',
|
||||
'harmony',
|
||||
];
|
||||
|
||||
export default function Content() {
|
||||
const t = useTranslations('dashboard');
|
||||
const { getUserSubscribe, getAppSubLink } = useGlobalStore();
|
||||
@ -56,14 +65,14 @@ export default function Content() {
|
||||
return data.data?.list || [];
|
||||
},
|
||||
});
|
||||
const { data: application } = useQuery({
|
||||
const { data: applications } = useQuery({
|
||||
queryKey: ['queryApplicationConfig'],
|
||||
queryFn: async () => {
|
||||
const { data } = await queryApplicationConfig();
|
||||
return data.data as API.ApplicationResponse;
|
||||
return data.data?.applications || [];
|
||||
},
|
||||
});
|
||||
const [platform, setPlatform] = useState<keyof API.ApplicationResponse>(getPlatform());
|
||||
const [platform, setPlatform] = useState<keyof API.ApplicationPlatform>(getPlatform());
|
||||
|
||||
const { data } = useQuery({
|
||||
queryKey: ['getStat'],
|
||||
@ -87,16 +96,27 @@ export default function Content() {
|
||||
<div className='flex flex-wrap justify-between gap-4'>
|
||||
<Tabs
|
||||
value={platform}
|
||||
onValueChange={(value) => setPlatform(value as keyof API.ApplicationResponse)}
|
||||
onValueChange={(value) => setPlatform(value as keyof API.ApplicationPlatform)}
|
||||
className='w-full max-w-full md:w-auto'
|
||||
>
|
||||
<TabsList className='flex *:flex-auto'>
|
||||
{application &&
|
||||
Object.keys(application)?.map((item) => (
|
||||
<TabsTrigger value={item} key={item} className='px-1 uppercase lg:px-3'>
|
||||
{item}
|
||||
</TabsTrigger>
|
||||
))}
|
||||
{platforms.map((item) => (
|
||||
<TabsTrigger value={item} key={item} className='px-1 lg:px-3'>
|
||||
<Icon
|
||||
icon={`${
|
||||
{
|
||||
windows: 'simple-icons:windows',
|
||||
mac: 'simple-icons:apple',
|
||||
linux: 'simple-icons:linux',
|
||||
ios: 'simple-icons:ios',
|
||||
android: 'simple-icons:android',
|
||||
harmony: 'simple-icons:harmonyos',
|
||||
}[item]
|
||||
}`}
|
||||
className='size-6'
|
||||
/>
|
||||
</TabsTrigger>
|
||||
))}
|
||||
</TabsList>
|
||||
</Tabs>
|
||||
{data?.protocol && data?.protocol.length > 1 && (
|
||||
@ -215,54 +235,69 @@ export default function Content() {
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className='grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6'>
|
||||
{application?.[platform]?.map((app) => (
|
||||
<div
|
||||
key={app.name}
|
||||
className='text-muted-foreground flex size-full flex-col items-center justify-between gap-2 text-xs'
|
||||
>
|
||||
<span>{app.name}</span>
|
||||
{app.icon && (
|
||||
<Image
|
||||
src={app.icon}
|
||||
alt={app.name}
|
||||
width={64}
|
||||
height={64}
|
||||
className='p-1'
|
||||
/>
|
||||
)}
|
||||
<div className='flex'>
|
||||
<Button
|
||||
size='sm'
|
||||
variant='secondary'
|
||||
className='rounded-r-none px-1.5'
|
||||
asChild
|
||||
>
|
||||
<Link href={app.url}>{t('download')}</Link>
|
||||
</Button>
|
||||
{applications
|
||||
?.filter((application) => {
|
||||
const platformApps = application.platform?.[platform];
|
||||
return platformApps && platformApps.length > 0;
|
||||
})
|
||||
.map((application) => {
|
||||
const platformApps = application.platform?.[platform];
|
||||
const app =
|
||||
platformApps?.find((item) => item.is_default) || platformApps?.[0];
|
||||
if (!app) return null;
|
||||
const handleCopy = (text: string, result: boolean) => {
|
||||
const href = getAppSubLink(application.subscribe_type, url);
|
||||
|
||||
<CopyToClipboard
|
||||
text={url}
|
||||
onCopy={(text, result) => {
|
||||
const href = getAppSubLink(app.subscribe_type, url);
|
||||
if (isBrowser() && href) {
|
||||
window.location.href = href;
|
||||
} else if (result) {
|
||||
toast.success(
|
||||
<>
|
||||
<p>{t('copySuccess')}</p>
|
||||
<p>{t('manualImportMessage')}</p>
|
||||
</>,
|
||||
);
|
||||
}
|
||||
}}
|
||||
if (isBrowser() && href) {
|
||||
window.location.href = href;
|
||||
return;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
toast.success(
|
||||
<>
|
||||
<p>{t('copySuccess')}</p>
|
||||
<p>{t('manualImportMessage')}</p>
|
||||
</>,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
key={application.name}
|
||||
className='text-muted-foreground flex size-full flex-col items-center justify-between gap-2 text-xs'
|
||||
>
|
||||
<Button size='sm' className='rounded-l-none p-2'>
|
||||
{t('import')}
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
<span>{application.name}</span>
|
||||
|
||||
{application.icon && (
|
||||
<Image
|
||||
src={application.icon}
|
||||
alt={application.name}
|
||||
width={64}
|
||||
height={64}
|
||||
className='p-1'
|
||||
/>
|
||||
)}
|
||||
<div className='flex'>
|
||||
<Button
|
||||
size='sm'
|
||||
variant='secondary'
|
||||
className='rounded-r-none px-1.5'
|
||||
asChild
|
||||
>
|
||||
<Link href={app.url}>{t('download')}</Link>
|
||||
</Button>
|
||||
|
||||
<CopyToClipboard text={url} onCopy={handleCopy}>
|
||||
<Button size='sm' className='rounded-l-none p-2'>
|
||||
{t('import')}
|
||||
</Button>
|
||||
</CopyToClipboard>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<div className='text-muted-foreground hidden size-full flex-col items-center justify-between gap-2 text-sm lg:flex'>
|
||||
<span>{t('qrCode')}</span>
|
||||
<QRCodeCanvas
|
||||
|
||||
2
apps/user/services/common/typings.d.ts
vendored
2
apps/user/services/common/typings.d.ts
vendored
@ -42,7 +42,7 @@ declare namespace API {
|
||||
name: string;
|
||||
icon: string;
|
||||
description: string;
|
||||
subscription_protocol: string;
|
||||
subscribe_type: string;
|
||||
platform: ApplicationPlatform;
|
||||
};
|
||||
|
||||
|
||||
2
apps/user/services/user/typings.d.ts
vendored
2
apps/user/services/user/typings.d.ts
vendored
@ -42,7 +42,7 @@ declare namespace API {
|
||||
name: string;
|
||||
icon: string;
|
||||
description: string;
|
||||
subscription_protocol: string;
|
||||
subscribe_type: string;
|
||||
platform: ApplicationPlatform;
|
||||
};
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ export function Logout() {
|
||||
}
|
||||
}
|
||||
|
||||
export function getPlatform(): 'windows' | 'mac' | 'linux' | 'android' | 'ios' {
|
||||
export function getPlatform(): 'windows' | 'mac' | 'linux' | 'android' | 'ios' | 'harmony' {
|
||||
const parser = new UAParser();
|
||||
const os = parser.getOS();
|
||||
const osName = os.name?.toLowerCase() || '';
|
||||
@ -70,6 +70,7 @@ export function getPlatform(): 'windows' | 'mac' | 'linux' | 'android' | 'ios' {
|
||||
return 'linux';
|
||||
if (osName.includes('android')) return 'android';
|
||||
if (osName.includes('ios')) return 'ios';
|
||||
if (osName.includes('harmony')) return 'harmony';
|
||||
|
||||
return 'windows';
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
"@hookform/resolvers": "^3.10.0",
|
||||
"@iconify-json/flagpack": "^1.2.2",
|
||||
"@iconify-json/mdi": "^1.2.2",
|
||||
"@iconify-json/simple-icons": "^1.2.20",
|
||||
"@iconify-json/uil": "^1.2.3",
|
||||
"@iconify/react": "^5.2.0",
|
||||
"@monaco-editor/react": "^4.6.0",
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Button } from '@workspace/ui/components/button';
|
||||
import { Label } from '@workspace/ui/components/label.js';
|
||||
import { Label } from '@workspace/ui/components/label';
|
||||
import { Switch } from '@workspace/ui/components/switch';
|
||||
import { Combobox } from '@workspace/ui/custom-components/combobox';
|
||||
import { EnhancedInput, EnhancedInputProps } from '@workspace/ui/custom-components/enhanced-input';
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
import { icons as FlagPack } from '@iconify-json/flagpack';
|
||||
import { icons as Mdi } from '@iconify-json/mdi';
|
||||
import { icons as Simple } from '@iconify-json/simple-icons';
|
||||
import { icons as Uil } from '@iconify-json/uil';
|
||||
|
||||
import { addCollection, Icon as Iconify, IconProps } from '@iconify/react';
|
||||
@ -9,6 +10,7 @@ import { addCollection, Icon as Iconify, IconProps } from '@iconify/react';
|
||||
addCollection(FlagPack);
|
||||
addCollection(Mdi);
|
||||
addCollection(Uil);
|
||||
addCollection(Simple);
|
||||
|
||||
export function Icon(props: IconProps) {
|
||||
return <Iconify {...props} />;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user