1- import React from 'react' ;
2- import { View , Text , Modal , ScrollView , Animated , Pressable , Platform } from 'react-native' ;
3- import { useSafeAreaInsets } from 'react-native-safe-area-context' ;
4- import { useNavigation } from '@react-navigation/native' ;
5- import { useTranslation } from 'react-i18next' ;
6- import Icon from 'react-native-vector-icons/FontAwesome' ;
1+ import React from 'react'
2+ import { View , Text , Modal , ScrollView , Animated , Pressable , Platform } from 'react-native'
3+ import { useSafeAreaInsets } from 'react-native-safe-area-context'
4+ import { useNavigation } from '@react-navigation/native'
5+ import { useTranslation } from 'react-i18next'
6+ import Icon from 'react-native-vector-icons/FontAwesome'
77
8- import { ConfigContext } from '~/contexts/config' ;
9- import { ThemeContext } from '~/contexts/theme' ;
10- import { urlCover } from '~/utils/url' ;
11- import ImageError from '~/components/ImageError' ;
12- import mainStyles from '~/styles/main' ;
13- import size from '~/styles/size' ;
8+ import { ConfigContext } from '~/contexts/config'
9+ import { SettingsContext } from '~/contexts/settings'
10+ import { ThemeContext } from '~/contexts/theme'
11+ import { urlCover } from '~/utils/url'
12+ import ImageError from '~/components/ImageError'
13+ import mainStyles from '~/styles/main'
14+ import size from '~/styles/size'
15+
16+ const OptionItem = ( { option } ) => {
17+ const theme = React . useContext ( ThemeContext )
18+ const [ isHover , setIsHover ] = React . useState ( false )
19+ const settings = React . useContext ( SettingsContext )
20+
21+ if ( ! option ) return null
22+ if ( option . hidden ) return null
23+ return (
24+ < Pressable
25+ onHoverIn = { ( ) => settings . isDesktop && setIsHover ( true ) }
26+ onHoverOut = { ( ) => setIsHover ( false ) }
27+ style = { ( { pressed } ) => ( [ mainStyles . opacity ( { pressed } ) , {
28+ flexDirection : 'row' ,
29+ alignItems : 'center' ,
30+ paddingHorizontal : 20 ,
31+ paddingStart : 20 + 15 * ( option . indent || 0 ) ,
32+ height : 45 ,
33+ justifyContent : 'flex-start' ,
34+ alignContent : 'center' ,
35+ gap : 10 ,
36+ backgroundColor : isHover ? 'rgba(0,0,0,0.1)' : theme . secondaryBack ,
37+ } ] ) }
38+ onPress = { option . onPress }
39+ >
40+ {
41+ option . icon && (
42+ < Icon name = { option . icon } size = { size . icon . tiny } color = { theme . secondaryText } style = { {
43+ width : 25 ,
44+ textAlign : 'center'
45+ } } />
46+ )
47+ }
48+ {
49+ option . image && (
50+ < ImageError
51+ style = { {
52+ width : 35 ,
53+ height : 35 ,
54+ borderRadius : option . borderRadius || 5 ,
55+ } }
56+ source = { { uri : option . image } }
57+ />
58+ )
59+ }
60+ < Text
61+ style = { { color : theme . primaryText , fontSize : size . text . large } }
62+ numberOfLines = { 1 }
63+ > { option . name } </ Text >
64+ </ Pressable >
65+ )
66+ }
1467
1568const OptionsPopup = ( { ref, visible, close, options, item = null } ) => {
16- const { t } = useTranslation ( ) ;
17- const insets = useSafeAreaInsets ( ) ;
69+ const { t } = useTranslation ( )
70+ const insets = useSafeAreaInsets ( )
1871 const theme = React . useContext ( ThemeContext )
1972 const slide = React . useRef ( new Animated . Value ( - 1000 ) ) . current
2073 const isAnim = React . useRef ( false )
2174 const config = React . useContext ( ConfigContext )
22- const navigation = useNavigation ( ) ;
23- const [ virtualOptions , setVirtualOptions ] = React . useState ( ) ;
75+ const navigation = useNavigation ( )
76+ const [ virtualOptions , setVirtualOptions ] = React . useState ( )
2477
2578 React . useImperativeHandle ( ref , ( ) => ( {
2679 close : close ,
2780 showInfo : ( info ) => {
28- navigation . navigate ( 'Info' , { info } ) ;
29- close ( ) ;
81+ navigation . navigate ( 'Info' , { info } )
82+ close ( )
3083 } ,
3184 setVirtualOptions : ( opt ) => {
32- setVirtualOptions ( opt ) ;
85+ setVirtualOptions ( opt )
3386 } ,
3487 clearVirtualOptions : ( ) => {
35- setVirtualOptions ( null ) ;
88+ setVirtualOptions ( null )
3689 }
3790 } ) , [ close ] )
3891
@@ -52,7 +105,7 @@ const OptionsPopup = ({ ref, visible, close, options, item = null }) => {
52105 } ) . start ( )
53106 }
54107
55- if ( ! visible ) return null ;
108+ if ( ! visible ) return null
56109 return (
57110 < Modal
58111 transparent = { true }
@@ -132,55 +185,13 @@ const OptionsPopup = ({ ref, visible, close, options, item = null }) => {
132185 name : t ( 'Cancel' ) ,
133186 icon : 'close' ,
134187 onPress : close
135- } ] . map ( ( option , index ) => {
136- if ( ! option ) return null
137- if ( option . hidden ) return null ;
138- return (
139- < Pressable
140- style = { ( { pressed } ) => ( [ mainStyles . opacity ( { pressed } ) , {
141- flexDirection : 'row' ,
142- alignItems : 'center' ,
143- paddingHorizontal : 20 ,
144- paddingStart : 20 + 15 * ( option . indent || 0 ) ,
145- height : 45 ,
146- justifyContent : 'flex-start' ,
147- alignContent : 'center' ,
148- gap : 10 ,
149- } ] ) }
150- key = { index }
151- onPress = { option . onPress }
152- >
153- {
154- option . icon && (
155- < Icon name = { option . icon } size = { size . icon . tiny } color = { theme . secondaryText } style = { {
156- width : 25 ,
157- textAlign : 'center'
158- } } />
159- )
160- }
161- {
162- option . image && (
163- < ImageError
164- style = { {
165- width : 35 ,
166- height : 35 ,
167- borderRadius : option . borderRadius || 5 ,
168- } }
169- source = { { uri : option . image } }
170- />
171- )
172- }
173- < Text
174- style = { { color : theme . primaryText , fontSize : size . text . large } }
175- numberOfLines = { 1 }
176- > { option . name } </ Text >
177- </ Pressable >
178- )
179- } ) }
188+ } ] . map ( ( option , index ) => (
189+ < OptionItem key = { index } option = { option } />
190+ ) ) }
180191 </ Animated . View >
181192 </ ScrollView >
182193 </ Modal >
183194 )
184195}
185196
186- export default OptionsPopup ;
197+ export default OptionsPopup
0 commit comments