@@ -11,6 +11,7 @@ import { Switch } from '@/components/ui/switch'
1111import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from '@/components/ui/select'
1212import { GripVertical , Trash2 , Plus , ChevronDown , ChevronRight , Apple , Tv , Monitor , Laptop , Smartphone , Star } from 'lucide-react'
1313import useDirDetection from '@/hooks/use-dir-detection'
14+ import { VariablesPopover } from '@/components/ui/variables-popover'
1415
1516const platformOptions = [
1617 { value : 'android' , label : 'settings.subscriptions.applications.platforms.android' } ,
@@ -89,25 +90,25 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
8990 < div ref = { setNodeRef } style = { style } className = "cursor-default" >
9091 < div className = "group relative rounded-md border bg-card transition-colors hover:bg-accent/20" >
9192 { /* Header with drag handle, expand/collapse, and delete button */ }
92- < div className = "flex items-center gap-3 p-4" >
93- < button type = "button" style = { { cursor : cursor } } className = "touch-none opacity-50 transition-opacity group-hover:opacity-100" { ...attributes } { ...listeners } >
94- < GripVertical className = "h-5 w-5" />
93+ < div className = "flex items-center gap-2 p-3 sm:gap-3 sm: p-4" >
94+ < button type = "button" style = { { cursor : cursor } } className = "touch-none shrink-0 opacity-50 transition-opacity group-hover:opacity-100" { ...attributes } { ...listeners } >
95+ < GripVertical className = "h-4 w-4 sm:h-5 sm: w-5" />
9596 < span className = "sr-only" > Drag to reorder</ span >
9697 </ button >
9798
98- < button type = "button" onClick = { ( ) => setIsExpanded ( ! isExpanded ) } className = { 'flex flex-1 flex-wrap items-center gap-2 hover:text-foreground sm:flex-nowrap' } >
99- { isExpanded ? < ChevronDown className = "h-4 w-4" /> : < ChevronRight className = "h-4 w-4" /> }
99+ < button type = "button" onClick = { ( ) => setIsExpanded ( ! isExpanded ) } className = { 'flex flex-1 min-w-0 flex-wrap items-center gap-1.5 hover:text-foreground sm:gap-2 sm:flex-nowrap' } >
100+ { isExpanded ? < ChevronDown className = "h-4 w-4 shrink-0 " /> : < ChevronRight className = "h-4 w-4 shrink-0 " /> }
100101 { /* Icon preview with graceful fallback */ }
101102 { ( ( ) => {
102103 const iconUrl = form . watch ( `applications.${ index } .icon_url` )
103104 const name = ( form . watch ( `applications.${ index } .name` ) || '' ) . trim ( )
104105 const initial = name ? name . charAt ( 0 ) . toUpperCase ( ) : ''
105106 const platform = form . watch ( `applications.${ index } .platform` )
106107 if ( iconUrl && ! iconBroken ) {
107- return < img src = { iconUrl } alt = { name || 'icon' } className = "h-5 w-5 rounded-sm object-cover" onError = { ( ) => setIconBroken ( true ) } onClick = { e => e . stopPropagation ( ) } />
108+ return < img src = { iconUrl } alt = { name || 'icon' } className = "h-4 w-4 shrink-0 rounded-sm object-cover sm:h-5 sm:w-5 " onError = { ( ) => setIconBroken ( true ) } onClick = { e => e . stopPropagation ( ) } />
108109 }
109110 return (
110- < span aria-label = "app-icon-fallback" className = "inline-flex h-5 w-5 items-center justify-center overflow-hidden rounded-sm bg-muted text-muted-foreground/90" >
111+ < span aria-label = "app-icon-fallback" className = "inline-flex h-4 w-4 shrink-0 items-center justify-center overflow-hidden rounded-sm bg-muted text-muted-foreground/90 sm:h-5 sm:w-5 " >
111112 { initial ? (
112113 < span className = "text-[10px] font-medium leading-none" > { initial } </ span >
113114 ) : (
@@ -122,13 +123,13 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
122123 < FormField
123124 control = { form . control }
124125 name = { `applications.${ index } .platform` }
125- render = { ( { field } ) => < span className = "text-xs text-muted-foreground" > { t ( platformOptions . find ( o => o . value === field . value ) ?. label || '' ) } </ span > }
126+ render = { ( { field } ) => < span className = "hidden text-xs text-muted-foreground sm:inline " > { t ( platformOptions . find ( o => o . value === field . value ) ?. label || '' ) } </ span > }
126127 />
127128 < FormField
128129 control = { form . control }
129130 name = { `applications.${ index } .platform` }
130131 render = { ( { field } ) => (
131- < span className = "text-muted-foreground/80" >
132+ < span className = "text-muted-foreground/80 shrink-0 " >
132133 < PlatformIcon platform = { field . value } />
133134 </ span >
134135 ) }
@@ -137,11 +138,11 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
137138 control = { form . control }
138139 name = { `applications.${ index } .name` }
139140 render = { ( { field } ) => (
140- < h4 className = "flex min-w-0 items-center gap-1.5 truncate text-sm font-medium" >
141+ < h4 className = "flex min-w-0 items-center gap-1.5 truncate text-xs font-medium sm:text-sm " >
141142 { field . value || t ( 'settings.subscriptions.applications.application' , { defaultValue : 'Application' } ) }
142143 { form . watch ( `applications.${ index } .recommended` ) ? (
143- < span title = { t ( 'settings.subscriptions.applications.recommended' ) } className = "inline-flex items-center text-amber-500/90" >
144- < Star className = "h-3.5 w-3.5 fill-amber-500/30" />
144+ < span title = { t ( 'settings.subscriptions.applications.recommended' ) } className = "inline-flex shrink-0 items-center text-amber-500/90" >
145+ < Star className = "h-3 w-3 fill-amber-500/30 sm:h-3.5 sm:w-3.5 " />
145146 </ span >
146147 ) : null }
147148 </ h4 >
@@ -158,16 +159,16 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
158159 e . stopPropagation ( )
159160 onRemove ( index )
160161 } }
161- className = "h-8 w-8 shrink-0 p-0 text-destructive opacity-70 transition-opacity hover:bg-destructive/10 hover:text-destructive hover:opacity-100"
162+ className = "h-7 w-7 shrink-0 p-0 text-destructive opacity-70 transition-opacity hover:bg-destructive/10 hover:text-destructive hover:opacity-100 sm:h-8 sm:w-8 "
162163 >
163- < Trash2 className = "h-4 w-4" />
164+ < Trash2 className = "h-3.5 w-3.5 sm:h-4 sm: w-4" />
164165 </ Button >
165166 </ div >
166167
167168 { /* Collapsible content */ }
168169 { isExpanded && (
169- < div className = "border-t bg-muted/20 p-4" >
170- < div className = "space-y-4" >
170+ < div className = "border-t bg-muted/20 p-3 sm:p- 4" >
171+ < div className = "space-y-3 sm:space-y- 4" >
171172 { /* Application fields */ }
172173 < div className = "grid grid-cols-1 gap-3 sm:grid-cols-2" >
173174 < FormField
@@ -241,7 +242,10 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
241242 name = { `applications.${ index } .import_url` }
242243 render = { ( { field } ) => (
243244 < FormItem className = "space-y-1 sm:col-span-2" >
244- < FormLabel className = "text-xs text-muted-foreground/80" > { t ( 'settings.subscriptions.applications.importUrl' ) } </ FormLabel >
245+ < div className = "flex items-center gap-1.5" >
246+ < FormLabel className = "text-xs text-muted-foreground/80" > { t ( 'settings.subscriptions.applications.importUrl' ) } </ FormLabel >
247+ < VariablesPopover includeProfileTitle = { true } />
248+ </ div >
245249 < FormControl >
246250 < Input placeholder = { t ( 'settings.subscriptions.applications.importUrlPlaceholder' ) } { ...field } className = "h-8 text-left font-mono text-xs" dir = "ltr" />
247251 </ FormControl >
@@ -258,9 +262,9 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
258262 < FormItem className = "space-y-1 sm:col-span-2" >
259263 < FormLabel className = "text-xs text-muted-foreground/80" > { t ( 'settings.subscriptions.applications.descriptionApp' ) } </ FormLabel >
260264 < FormControl >
261- < div className = "flex gap-2" >
265+ < div className = "flex flex-col gap-2 sm:flex-row " >
262266 < Select value = { selectedLanguage } onValueChange = { setSelectedLanguage } >
263- < SelectTrigger className = "h-8 w-32 text-xs" >
267+ < SelectTrigger className = "h-8 w-full text-xs sm:w-32 " >
264268 < SelectValue />
265269 </ SelectTrigger >
266270 < SelectContent className = "scrollbar-thin z-[50]" >
@@ -316,13 +320,14 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
316320
317321 { /* Download Links */ }
318322 < div className = "space-y-2" >
319- < div className = "flex items-center justify-between" >
323+ < div className = "flex flex-col gap-2 sm:flex-row sm: items-center sm: justify-between" >
320324 < FormLabel className = "text-xs font-medium text-muted-foreground/80" >
321325 { t ( 'settings.subscriptions.applications.downloadLinks' ) } ({ downloadLinkFields . length } )
322326 </ FormLabel >
323- < Button type = "button" variant = "outline" size = "sm" onClick = { addDownloadLink } className = "h-7 text-xs" >
327+ < Button type = "button" variant = "outline" size = "sm" onClick = { addDownloadLink } className = "h-7 w-full text-xs sm:w-auto " >
324328 < Plus className = "mr-1 h-3 w-3" />
325- { t ( 'settings.subscriptions.applications.addDownloadLink' ) }
329+ < span className = "hidden sm:inline" > { t ( 'settings.subscriptions.applications.addDownloadLink' ) } </ span >
330+ < span className = "sm:hidden" > { t ( 'settings.subscriptions.applications.addDownloadLink' , { defaultValue : 'Add Link' } ) } </ span >
326331 </ Button >
327332 </ div >
328333
@@ -342,12 +347,12 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
342347 const linkLang = form . watch ( `applications.${ index } .download_links.${ linkIndex } .language` )
343348 const ltrForThis = isRtl && linkLang !== 'fa'
344349 return (
345- < div key = { linkField . id } className = "flex gap-2 rounded-md border bg-muted/20 p-2" >
350+ < div key = { linkField . id } className = "flex flex-col gap-2 rounded-md border bg-muted/20 p-2 sm:flex-row " >
346351 < FormField
347352 control = { form . control }
348353 name = { `applications.${ index } .download_links.${ linkIndex } .name` }
349354 render = { ( { field } ) => (
350- < FormItem className = "flex-1" >
355+ < FormItem className = "flex-1 min-w-0 " >
351356 < FormControl >
352357 < Input
353358 placeholder = { t ( 'settings.subscriptions.applications.downloadLinkNamePlaceholder' ) }
@@ -368,7 +373,7 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
368373 control = { form . control }
369374 name = { `applications.${ index } .download_links.${ linkIndex } .url` }
370375 render = { ( { field } ) => (
371- < FormItem className = "flex-1" >
376+ < FormItem className = "flex-1 min-w-0 " >
372377 < FormControl >
373378 < Input placeholder = { t ( 'settings.subscriptions.applications.downloadLinkUrlPlaceholder' ) } { ...field } className = "h-7 text-left font-mono text-xs" dir = "ltr" />
374379 </ FormControl >
@@ -378,35 +383,37 @@ export function SortableApplication({ index, onRemove, form, id }: SortableAppli
378383 </ FormItem >
379384 ) }
380385 />
381- < FormField
382- control = { form . control }
383- name = { `applications.${ index } .download_links.${ linkIndex } .language` }
384- render = { ( { field } ) => (
385- < FormItem className = "w-24" >
386- < Select onValueChange = { field . onChange } value = { field . value } >
387- < FormControl >
388- < SelectTrigger className = "h-7 text-xs" >
389- < SelectValue />
390- </ SelectTrigger >
391- </ FormControl >
392- < SelectContent className = "scrollbar-thin z-[50]" >
393- { languageOptions . map ( option => (
394- < SelectItem key = { option . value } value = { option . value } >
395- < div className = "flex items-center gap-1.5" >
396- < span className = "text-xs" > { option . icon } </ span >
397- < span className = "text-xs" > { option . label } </ span >
398- </ div >
399- </ SelectItem >
400- ) ) }
401- </ SelectContent >
402- </ Select >
403- < FormMessage />
404- </ FormItem >
405- ) }
406- />
407- < Button type = "button" variant = "ghost" size = "icon" onClick = { ( ) => removeDownloadLink ( linkIndex ) } className = "h-7 w-7 p-0 text-destructive hover:bg-destructive/10" >
408- < Trash2 className = "h-3 w-3" />
409- </ Button >
386+ < div className = "flex items-start gap-2 sm:items-center" >
387+ < FormField
388+ control = { form . control }
389+ name = { `applications.${ index } .download_links.${ linkIndex } .language` }
390+ render = { ( { field } ) => (
391+ < FormItem className = "w-full sm:w-24" >
392+ < Select onValueChange = { field . onChange } value = { field . value } >
393+ < FormControl >
394+ < SelectTrigger className = "h-7 text-xs" >
395+ < SelectValue />
396+ </ SelectTrigger >
397+ </ FormControl >
398+ < SelectContent className = "scrollbar-thin z-[50]" >
399+ { languageOptions . map ( option => (
400+ < SelectItem key = { option . value } value = { option . value } >
401+ < div className = "flex items-center gap-1.5" >
402+ < span className = "text-xs" > { option . icon } </ span >
403+ < span className = "text-xs" > { option . label } </ span >
404+ </ div >
405+ </ SelectItem >
406+ ) ) }
407+ </ SelectContent >
408+ </ Select >
409+ < FormMessage />
410+ </ FormItem >
411+ ) }
412+ />
413+ < Button type = "button" variant = "ghost" size = "icon" onClick = { ( ) => removeDownloadLink ( linkIndex ) } className = "h-7 w-7 shrink-0 p-0 text-destructive hover:bg-destructive/10" >
414+ < Trash2 className = "h-3 w-3" />
415+ </ Button >
416+ </ div >
410417 </ div >
411418 )
412419 } ) }
0 commit comments