diff --git a/dashboard/src/pages/_dashboard.settings.subscriptions.tsx b/dashboard/src/pages/_dashboard.settings.subscriptions.tsx
index c3ba230fe..c5c055776 100644
--- a/dashboard/src/pages/_dashboard.settings.subscriptions.tsx
+++ b/dashboard/src/pages/_dashboard.settings.subscriptions.tsx
@@ -9,17 +9,18 @@ import { Separator } from '@/components/ui/separator'
import { Switch } from '@/components/ui/switch'
import { Textarea } from '@/components/ui/textarea'
import { VariablesPopover } from '@/components/ui/variables-popover'
-import { ConfigFormat, type SubRule as ApiSubRule } from '@/service/api'
+import { type SubRule as ApiSubRule } from '@/service/api'
import { closestCenter, DndContext, DragEndEvent, KeyboardSensor, PointerSensor, useSensor, useSensors } from '@dnd-kit/core'
import { rectSortingStrategy, SortableContext, sortableKeyboardCoordinates, useSortable } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { zodResolver } from '@hookform/resolvers/zod'
-import { Clock, Code, ExternalLink, FileCode2, FileText, Globe, GripVertical, HelpCircle, Link, Lock, Megaphone, Plus, RotateCcw, Settings, Shield, Shuffle, Sword, Trash2, User } from 'lucide-react'
+import { ArrowUpWideNarrow, Cable, Clock, Code, ExternalLink, FileCode2, FileText, Globe, GripVertical, HelpCircle, Link, Lock, Megaphone, Plus, RotateCcw, Settings, Shield, Shuffle, Sword, Trash2, User } from 'lucide-react'
import { useEffect, useState } from 'react'
import { FieldErrors, useFieldArray, useForm, UseFormReturn } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
import { toast } from 'sonner'
import { z } from 'zod'
+import useDirDetection from '@/hooks/use-dir-detection'
import { useSettingsContext } from './_dashboard.settings'
// Enhanced validation schema for subscription settings
@@ -36,7 +37,7 @@ const subscriptionSchema = z.object({
rules: z.array(
z.object({
pattern: z.string().min(1, 'Pattern is required'),
- target: z.enum(['links', 'links_base64', 'xray', 'sing_box', 'clash', 'clash_meta', 'outline', 'block']),
+ target: z.enum(['links', 'links_base64', 'xray', 'wireguard', 'sing_box', 'clash', 'clash_meta', 'outline', 'block']),
response_headers: z.record(z.string()).optional(),
}),
),
@@ -78,6 +79,7 @@ const subscriptionSchema = z.object({
links: z.boolean().optional(),
links_base64: z.boolean().optional(),
xray: z.boolean().optional(),
+ wireguard: z.boolean().optional(),
sing_box: z.boolean().optional(),
clash: z.boolean().optional(),
clash_meta: z.boolean().optional(),
@@ -112,6 +114,7 @@ const configFormatOptions = [
{ value: 'links', label: 'settings.subscriptions.configFormats.links', icon: '🔗' },
{ value: 'links_base64', label: 'settings.subscriptions.configFormats.links_base64', icon: '📝' },
{ value: 'xray', label: 'settings.subscriptions.configFormats.xray', icon: '⚡' },
+ { value: 'wireguard', label: 'settings.subscriptions.configFormats.wireguard', icon: '🛜' },
{ value: 'sing_box', label: 'settings.subscriptions.configFormats.sing_box', icon: '📦' },
{ value: 'clash', label: 'settings.subscriptions.configFormats.clash', icon: '⚔️' },
{ value: 'clash_meta', label: 'settings.subscriptions.configFormats.clash_meta', icon: '🛡️' },
@@ -298,7 +301,7 @@ const buildDefaultApplications = () => {
}
// Default subscription rules
-const defaultSubscriptionRules: { pattern: string; target: ConfigFormat }[] = [
+const defaultSubscriptionRules: SubscriptionRuleFormData[] = [
{
pattern: '^([Cc]lash[\\-\\.]?[Vv]erge|[Cc]lash[\\-\\.]?[Mm]eta|[Ff][Ll][Cc]lash|[Mm]ihomo)',
target: 'clash_meta',
@@ -336,6 +339,8 @@ interface SortableRuleProps {
function SortableRule({ index, onRemove, form, id }: SortableRuleProps) {
const { t } = useTranslation()
+ const dir = useDirDetection()
+ const isRtl = dir === 'rtl'
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id })
const [isHeadersOpen, setIsHeadersOpen] = useState(false)
const responseHeaders = (form.watch(`rules.${index}.response_headers`) || {}) as Record
@@ -397,7 +402,7 @@ function SortableRule({ index, onRemove, form, id }: SortableRuleProps) {
return (
<>
-
+
-