1
1
import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
2
- import Animated , { useAnimatedStyle , useSharedValue , withSpring , withTiming } from 'react-native-reanimated' ;
3
- import { LayoutChangeEvent , Text , TouchableOpacity , View , Platform , StyleSheet } from 'react-native' ;
4
- import { Close , Notification , Check , Delete , useTheme } from 'stream-chat-react-native' ;
2
+ import Animated , {
3
+ useAnimatedStyle ,
4
+ useSharedValue ,
5
+ withSpring ,
6
+ withTiming ,
7
+ } from 'react-native-reanimated' ;
8
+ import {
9
+ LayoutChangeEvent ,
10
+ Text ,
11
+ TouchableOpacity ,
12
+ View ,
13
+ Platform ,
14
+ StyleSheet ,
15
+ } from 'react-native' ;
16
+ import { Close , Notification , Delete , useTheme } from 'stream-chat-react-native' ;
5
17
import { styles as menuDrawerStyles } from './MenuDrawer.tsx' ;
6
18
import AsyncStore from '../utils/AsyncStore.ts' ;
7
19
import { StreamChat } from 'stream-chat' ;
20
+ import { LabeledTextInput } from '../screens/AdvancedUserSelectorScreen.tsx' ;
8
21
9
- export const SlideInView = ( { visible, children } : { visible : boolean ; children : React . ReactNode } ) => {
22
+ export const SlideInView = ( {
23
+ visible,
24
+ children,
25
+ } : {
26
+ visible : boolean ;
27
+ children : React . ReactNode ;
28
+ } ) => {
10
29
const animatedHeight = useSharedValue ( 0 ) ;
11
30
12
31
const onLayout = ( event : LayoutChangeEvent ) => {
13
32
const { height } = event . nativeEvent . layout ;
14
33
animatedHeight . value = height ;
15
34
} ;
16
35
17
- const animatedStyle = useAnimatedStyle ( ( ) => ( {
18
- height : withSpring ( visible ? animatedHeight . value : 0 , { damping : 10 } ) ,
19
- opacity : withTiming ( visible ? 1 : 0 , { duration : 500 } ) ,
20
- } ) , [ visible ] ) ;
36
+ const animatedStyle = useAnimatedStyle (
37
+ ( ) => ( {
38
+ height : withSpring ( visible ? animatedHeight . value : 0 , { damping : 10 } ) ,
39
+ opacity : withTiming ( visible ? 1 : 0 , { duration : 500 } ) ,
40
+ } ) ,
41
+ [ visible ] ,
42
+ ) ;
21
43
22
44
return (
23
45
< Animated . View style = { animatedStyle } >
24
- { visible ? < View onLayout = { onLayout } style = { { position : 'absolute' , width : '100%' } } >
25
- { children }
26
- </ View > : null }
46
+ { visible ? (
47
+ < View onLayout = { onLayout } style = { { position : 'absolute' , width : '100%' } } >
48
+ { children }
49
+ </ View >
50
+ ) : null }
27
51
</ Animated . View >
28
52
) ;
29
53
} ;
30
54
31
55
const isAndroid = Platform . OS === 'android' ;
32
56
33
- export const SecretMenu = ( { close, visible, chatClient } : { close : ( ) => void , visible : boolean , chatClient : StreamChat } ) => {
57
+ type NotificationConfigItem = { label : string ; name : string ; id : string } ;
58
+
59
+ const SecretMenuNotificationConfigItem = ( {
60
+ notificationConfigItem,
61
+ storeProvider,
62
+ isSelected,
63
+ } : {
64
+ notificationConfigItem : NotificationConfigItem ;
65
+ storeProvider : ( item : NotificationConfigItem ) => void ;
66
+ isSelected : boolean ;
67
+ } ) => {
68
+ const [ providerNameOverride , setProviderNameOverride ] = useState < string > ( '' ) ;
69
+ const [ lastSubmittedOverride , setLastSubmittedOverride ] = useState < string | null > ( null ) ;
70
+
71
+ const asyncStorageKey = useMemo (
72
+ ( ) => `@stream-rn-sampleapp-push-provider-${ notificationConfigItem . id } -override` ,
73
+ [ notificationConfigItem ] ,
74
+ ) ;
75
+
76
+ useEffect ( ( ) => {
77
+ const getProviderNameOverride = async ( ) => {
78
+ const nameOverride = await AsyncStore . getItem ( asyncStorageKey , '' ) ;
79
+ setLastSubmittedOverride ( nameOverride ?? '' ) ;
80
+ } ;
81
+ getProviderNameOverride ( ) ;
82
+ } , [ asyncStorageKey ] ) ;
83
+
84
+ const storeProviderNameOverride = useCallback ( async ( ) => {
85
+ await AsyncStore . setItem ( asyncStorageKey , providerNameOverride ) ;
86
+ setLastSubmittedOverride ( providerNameOverride ) ;
87
+ } , [ asyncStorageKey , providerNameOverride ] ) ;
88
+
89
+ return (
90
+ < View
91
+ style = { [ styles . notificationItemContainer , { borderColor : isSelected ? 'green' : 'gray' } ] }
92
+ >
93
+ < TouchableOpacity
94
+ style = { { flexDirection : 'row' } }
95
+ onPress = { ( ) => storeProvider ( notificationConfigItem ) }
96
+ >
97
+ < Text style = { styles . notificationItem } > { notificationConfigItem . label } </ Text >
98
+ < Text
99
+ numberOfLines = { 1 }
100
+ style = { { opacity : 0.7 , fontSize : 14 , marginLeft : 4 , maxWidth : 145 } }
101
+ >
102
+ { lastSubmittedOverride && lastSubmittedOverride . length > 0
103
+ ? lastSubmittedOverride
104
+ : notificationConfigItem . name }
105
+ </ Text >
106
+ </ TouchableOpacity >
107
+ { isSelected ? (
108
+ < >
109
+ < LabeledTextInput
110
+ onChangeText = { setProviderNameOverride }
111
+ label = { 'PN Provider name override' }
112
+ value = { providerNameOverride }
113
+ />
114
+ < TouchableOpacity style = { styles . submitButton } onPress = { storeProviderNameOverride } >
115
+ < Text style = { { color : 'white' , fontSize : 12 } } > Submit</ Text >
116
+ </ TouchableOpacity >
117
+ </ >
118
+ ) : null }
119
+ </ View >
120
+ ) ;
121
+ } ;
122
+
123
+ export const SecretMenu = ( {
124
+ close,
125
+ visible,
126
+ chatClient,
127
+ } : {
128
+ close : ( ) => void ;
129
+ visible : boolean ;
130
+ chatClient : StreamChat ;
131
+ } ) => {
34
132
const [ selectedProvider , setSelectedProvider ] = useState < string | null > ( null ) ;
35
133
const {
36
134
theme : {
37
135
colors : { black, grey } ,
38
136
} ,
39
137
} = useTheme ( ) ;
40
138
41
- const notificationConfigItems = useMemo ( ( ) => [ { label : 'Firebase' , name : 'rn-fcm' , id : 'firebase' } , { label : 'APNs' , name : 'APN' , id : 'apn' } ] , [ ] ) ;
139
+ const notificationConfigItems = useMemo (
140
+ ( ) => [
141
+ { label : 'Firebase' , name : 'rn-fcm' , id : 'firebase' } ,
142
+ ...( isAndroid ? [ ] : [ { label : 'APNs' , name : 'APN' , id : 'apn' } ] ) ,
143
+ ] ,
144
+ [ ] ,
145
+ ) ;
42
146
43
147
useEffect ( ( ) => {
44
148
const getSelectedProvider = async ( ) => {
45
- const provider = await AsyncStore . getItem ( '@stream-rn-sampleapp-push-provider' , notificationConfigItems [ 0 ] ) ;
149
+ const provider = await AsyncStore . getItem (
150
+ '@stream-rn-sampleapp-push-provider' ,
151
+ notificationConfigItems [ 0 ] ,
152
+ ) ;
46
153
setSelectedProvider ( provider ?. id ?? 'firebase' ) ;
47
154
} ;
48
155
getSelectedProvider ( ) ;
49
156
} , [ notificationConfigItems ] ) ;
50
157
51
- const storeProvider = useCallback ( async ( item : { label : string , name : string , id : string } ) => {
52
- await AsyncStore . setItem ( '@stream-rn-sampleapp-push-provider' , item ) ;
53
- setSelectedProvider ( item . id ) ;
158
+ const storeProvider = useCallback ( async ( item : NotificationConfigItem ) => {
159
+ await AsyncStore . setItem ( '@stream-rn-sampleapp-push-provider' , item ) ;
160
+ setSelectedProvider ( item . id ) ;
54
161
} , [ ] ) ;
55
162
56
163
const removeAllDevices = useCallback ( async ( ) => {
@@ -65,7 +172,7 @@ export const SecretMenu = ({ close, visible, chatClient }: { close: () => void,
65
172
< View
66
173
style = { [
67
174
menuDrawerStyles . menuItem ,
68
- { opacity : isAndroid ? 0.3 : 1 , alignItems : 'flex-start' } ,
175
+ { alignItems : 'flex-start' } ,
69
176
] }
70
177
>
71
178
< Notification height = { 24 } pathFill = { grey } width = { 24 } />
@@ -81,14 +188,16 @@ export const SecretMenu = ({ close, visible, chatClient }: { close: () => void,
81
188
>
82
189
Notification Provider
83
190
</ Text >
84
- { isAndroid ? null : < View style = { { marginLeft : 16 } } >
191
+ < View style = { { marginLeft : 16 } } >
85
192
{ notificationConfigItems . map ( ( item ) => (
86
- < TouchableOpacity key = { item . id } style = { { paddingTop : 8 , flexDirection : 'row' } } onPress = { ( ) => storeProvider ( item ) } >
87
- < Text style = { styles . notificationItem } > { item . label } </ Text >
88
- { item . id === selectedProvider ? < Check height = { 16 } pathFill = { 'green' } width = { 16 } style = { { marginLeft : 12 } } /> : null }
89
- </ TouchableOpacity >
193
+ < SecretMenuNotificationConfigItem
194
+ key = { item . id }
195
+ notificationConfigItem = { item }
196
+ storeProvider = { storeProvider }
197
+ isSelected = { item . id === selectedProvider }
198
+ />
90
199
) ) }
91
- </ View > }
200
+ </ View >
92
201
</ View >
93
202
</ View >
94
203
< TouchableOpacity onPress = { removeAllDevices } style = { menuDrawerStyles . menuItem } >
@@ -126,9 +235,24 @@ export const SecretMenu = ({ close, visible, chatClient }: { close: () => void,
126
235
127
236
export const styles = StyleSheet . create ( {
128
237
separator : { height : 1 , width : '100%' , opacity : 0.2 } ,
129
- notificationContainer : { } ,
238
+ notificationItemContainer : {
239
+ paddingTop : 8 ,
240
+ marginTop : 12 ,
241
+ borderRadius : 15 ,
242
+ borderWidth : 2 ,
243
+ padding : 8 ,
244
+ width : 225 ,
245
+ } ,
130
246
notificationItem : {
131
- fontSize : 13 ,
247
+ fontSize : 15 ,
132
248
fontWeight : '500' ,
133
249
} ,
250
+ submitButton : {
251
+ flex : 1 ,
252
+ marginTop : 8 ,
253
+ borderRadius : 5 ,
254
+ backgroundColor : 'lightskyblue' ,
255
+ padding : 8 ,
256
+ alignItems : 'center' ,
257
+ } ,
134
258
} ) ;
0 commit comments