@planningcenter/chat-react-native 3.42.3-qa-856.0 → 3.42.3-qa-858.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/components/display/platform_modal_header_buttons.d.ts +28 -8
- package/build/components/display/platform_modal_header_buttons.d.ts.map +1 -1
- package/build/components/display/platform_modal_header_buttons.js +86 -45
- package/build/components/display/platform_modal_header_buttons.js.map +1 -1
- package/build/components/primitive/form_sheet.js +2 -2
- package/build/components/primitive/form_sheet.js.map +1 -1
- package/build/navigation/index.d.ts +48 -51
- package/build/navigation/index.d.ts.map +1 -1
- package/build/navigation/index.js +38 -48
- package/build/navigation/index.js.map +1 -1
- package/build/screens/bug_report_screen.d.ts.map +1 -1
- package/build/screens/bug_report_screen.js +9 -3
- package/build/screens/bug_report_screen.js.map +1 -1
- package/build/screens/conversation_details_screen.d.ts.map +1 -1
- package/build/screens/conversation_details_screen.js +2 -1
- package/build/screens/conversation_details_screen.js.map +1 -1
- package/build/screens/conversation_screen.d.ts.map +1 -1
- package/build/screens/conversation_screen.js +6 -2
- package/build/screens/conversation_screen.js.map +1 -1
- package/build/screens/message_report_screen.js +5 -3
- package/build/screens/message_report_screen.js.map +1 -1
- package/build/screens/notification_settings_screen.d.ts.map +1 -1
- package/build/screens/notification_settings_screen.js +0 -2
- package/build/screens/notification_settings_screen.js.map +1 -1
- package/package.json +4 -3
- package/src/components/display/platform_modal_header_buttons.tsx +145 -77
- package/src/components/primitive/form_sheet.tsx +2 -2
- package/src/navigation/index.tsx +46 -53
- package/src/screens/bug_report_screen.tsx +9 -3
- package/src/screens/conversation_details_screen.tsx +2 -1
- package/src/screens/conversation_screen.tsx +7 -2
- package/src/screens/message_report_screen.tsx +5 -3
- package/src/screens/notification_settings_screen.tsx +1 -4
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { HeaderBackButton, HeaderButton } from '@react-navigation/elements'
|
|
1
|
+
import { HeaderBackButton, HeaderButton, PlatformPressable } from '@react-navigation/elements'
|
|
2
2
|
import { useNavigation } from '@react-navigation/native'
|
|
3
3
|
import type {
|
|
4
|
-
|
|
5
|
-
NativeStackHeaderRightProps,
|
|
4
|
+
NativeStackHeaderItemProps,
|
|
6
5
|
NativeStackNavigationOptions,
|
|
7
6
|
} from '@react-navigation/native-stack'
|
|
8
7
|
import { useLayoutEffect } from 'react'
|
|
9
8
|
import { ColorValue, Platform, StyleSheet } from 'react-native'
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
9
|
+
import type { SFSymbol } from 'sf-symbols-typescript'
|
|
10
|
+
import { useFontScale, useTheme } from '../../hooks'
|
|
11
|
+
import { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils'
|
|
12
|
+
import { Icon, type IconString } from './icon'
|
|
13
13
|
import { TextButton } from './text_button'
|
|
14
14
|
|
|
15
15
|
interface HeaderTextButtonProps {
|
|
@@ -72,14 +72,10 @@ export const HeaderDismissButton = ({
|
|
|
72
72
|
|
|
73
73
|
const createTextHeaderRight =
|
|
74
74
|
({ onPress, title, disabled }: HeaderTextButtonProps) =>
|
|
75
|
-
(props:
|
|
75
|
+
(props: NativeStackHeaderItemProps) => (
|
|
76
76
|
<HeaderTextButton {...props} onPress={onPress} title={title} disabled={disabled} />
|
|
77
77
|
)
|
|
78
78
|
|
|
79
|
-
const createDismissHeaderLeft =
|
|
80
|
-
({ onPress, title }: { onPress: () => void; title: string }) =>
|
|
81
|
-
() => <HeaderDismissButton title={title} onPress={onPress} />
|
|
82
|
-
|
|
83
79
|
export type OptionsDecorator = (
|
|
84
80
|
options: NativeStackNavigationOptions
|
|
85
81
|
) => NativeStackNavigationOptions
|
|
@@ -95,9 +91,6 @@ interface TextButtonDecoratorProps {
|
|
|
95
91
|
disabled?: boolean
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
// Native bar items pick up liquid glass on iOS 26; hosts on an older
|
|
99
|
-
// react-navigation ignore the unstable option and keep using the
|
|
100
|
-
// headerRight/headerLeft fallbacks, as does Android.
|
|
101
94
|
export const withRightText =
|
|
102
95
|
({ text, onPress, disabled }: TextButtonDecoratorProps): OptionsDecorator =>
|
|
103
96
|
options => ({
|
|
@@ -106,95 +99,159 @@ export const withRightText =
|
|
|
106
99
|
unstable_headerRightItems: () => [{ type: 'button' as const, label: text, onPress, disabled }],
|
|
107
100
|
})
|
|
108
101
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
headerLeft: createDismissHeaderLeft({ title: text, onPress }),
|
|
114
|
-
unstable_headerLeftItems: () => [{ type: 'button' as const, label: text, onPress }],
|
|
115
|
-
})
|
|
102
|
+
const HEADER_ICON_SIZE = 17
|
|
103
|
+
const HEADER_GLASS_BUTTON_SIZE = 44
|
|
104
|
+
const HEADER_BAR_INSET = 16
|
|
105
|
+
const HEADER_SLOT_GAP = 12
|
|
116
106
|
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
)
|
|
107
|
+
export const useHeaderSlotReserve = (): number => {
|
|
108
|
+
const fontScale = useFontScale({ maxFontSizeMultiplier: MAX_FONT_SIZE_MULTIPLIER_LANDMARK })
|
|
120
109
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
110
|
+
return HEADER_BAR_INSET + HEADER_GLASS_BUTTON_SIZE * fontScale + HEADER_SLOT_GAP
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const HEADER_FALLBACK_HIT_SLOP = 14
|
|
114
|
+
|
|
115
|
+
const iconStyles = StyleSheet.create({
|
|
116
|
+
disabled: {
|
|
117
|
+
opacity: 0.4,
|
|
118
|
+
},
|
|
119
|
+
fallbackButton: {
|
|
120
|
+
alignItems: 'center',
|
|
121
|
+
justifyContent: 'center',
|
|
122
|
+
paddingHorizontal: 8,
|
|
123
|
+
},
|
|
124
|
+
fallbackButtonLeft: {
|
|
125
|
+
marginRight: Platform.select({ android: 16, default: 0 }),
|
|
126
|
+
},
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
const SF_SYMBOL_NAMES: Partial<Record<IconString, SFSymbol>> = {
|
|
130
|
+
'general.x': 'xmark',
|
|
131
|
+
'general.check': 'checkmark',
|
|
132
|
+
'general.upArrow': 'arrow.up',
|
|
133
|
+
'general.leftChevron': 'chevron.left',
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const sfSymbolFor = (icon: IconString): SFSymbol => {
|
|
137
|
+
const name = SF_SYMBOL_NAMES[icon]
|
|
138
|
+
|
|
139
|
+
if (!name) throw new Error(`No SF Symbol mapped for icon "${icon}" — add one to SF_SYMBOL_NAMES.`)
|
|
140
|
+
|
|
141
|
+
return name
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface HeaderIconProps {
|
|
145
|
+
icon: IconString
|
|
146
|
+
accessibilityLabel: string
|
|
147
|
+
onPress: () => void
|
|
148
|
+
disabled?: boolean
|
|
149
|
+
prominent?: boolean
|
|
150
|
+
tintColor?: ColorValue
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const createHeaderIconItem = ({
|
|
154
|
+
icon,
|
|
155
|
+
accessibilityLabel,
|
|
156
|
+
onPress,
|
|
157
|
+
disabled,
|
|
158
|
+
prominent,
|
|
159
|
+
tintColor,
|
|
160
|
+
}: HeaderIconProps) => ({
|
|
161
|
+
type: 'button' as const,
|
|
162
|
+
label: '',
|
|
163
|
+
accessibilityLabel,
|
|
164
|
+
onPress,
|
|
165
|
+
disabled,
|
|
166
|
+
icon: { type: 'sfSymbol' as const, name: sfSymbolFor(icon) },
|
|
167
|
+
...(prominent ? { variant: 'prominent' as const, tintColor } : {}),
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
const createHeaderIconElement =
|
|
171
|
+
(position: 'left' | 'right') =>
|
|
172
|
+
({ icon, accessibilityLabel, onPress, disabled, tintColor }: HeaderIconProps) =>
|
|
173
|
+
() => (
|
|
174
|
+
<PlatformPressable
|
|
175
|
+
onPress={onPress}
|
|
176
|
+
disabled={disabled}
|
|
177
|
+
hitSlop={HEADER_FALLBACK_HIT_SLOP}
|
|
178
|
+
accessibilityRole="button"
|
|
179
|
+
accessibilityLabel={accessibilityLabel}
|
|
180
|
+
style={[
|
|
181
|
+
iconStyles.fallbackButton,
|
|
182
|
+
position === 'left' && iconStyles.fallbackButtonLeft,
|
|
183
|
+
disabled && iconStyles.disabled,
|
|
184
|
+
]}
|
|
185
|
+
>
|
|
186
|
+
<Icon name={icon} size={HEADER_ICON_SIZE} color={tintColor} />
|
|
187
|
+
</PlatformPressable>
|
|
125
188
|
)
|
|
126
189
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
// general.x closely. The fallback keeps our icon.
|
|
130
|
-
export const withRightClose =
|
|
131
|
-
({ onPress }: { onPress: () => void }): OptionsDecorator =>
|
|
190
|
+
export const withRightIcon =
|
|
191
|
+
(props: HeaderIconProps): OptionsDecorator =>
|
|
132
192
|
options => ({
|
|
133
193
|
...options,
|
|
134
|
-
headerRight:
|
|
135
|
-
unstable_headerRightItems: () => [
|
|
136
|
-
{
|
|
137
|
-
type: 'button' as const,
|
|
138
|
-
label: 'Close',
|
|
139
|
-
icon: { type: 'sfSymbol' as const, name: 'xmark' as const },
|
|
140
|
-
onPress,
|
|
141
|
-
},
|
|
142
|
-
],
|
|
194
|
+
headerRight: createHeaderIconElement('right')(props),
|
|
195
|
+
unstable_headerRightItems: () => [createHeaderIconItem(props)],
|
|
143
196
|
})
|
|
144
197
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
)
|
|
198
|
+
export const withLeftIcon =
|
|
199
|
+
(props: HeaderIconProps): OptionsDecorator =>
|
|
200
|
+
options => ({
|
|
201
|
+
...options,
|
|
202
|
+
headerLeft: createHeaderIconElement('left')(props),
|
|
203
|
+
unstable_headerLeftItems: () => [createHeaderIconItem(props)],
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
export const withRightClose = ({ onPress }: { onPress: () => void }) =>
|
|
207
|
+
withRightIcon({ icon: 'general.x', accessibilityLabel: 'Close', onPress })
|
|
208
|
+
|
|
209
|
+
export const withLeftClose = ({ onPress }: { onPress: () => void }) =>
|
|
210
|
+
withLeftIcon({ icon: 'general.x', accessibilityLabel: 'Close', onPress })
|
|
151
211
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
212
|
+
export const withRightDone = ({ onPress }: { onPress: () => void }) =>
|
|
213
|
+
withRightIcon({ icon: 'general.check', accessibilityLabel: 'Done', onPress })
|
|
214
|
+
|
|
215
|
+
const createMinimalHeaderBackElement =
|
|
155
216
|
({ onPress }: { onPress: () => void }) =>
|
|
156
|
-
(props:
|
|
217
|
+
(props: NativeStackHeaderItemProps) => (
|
|
157
218
|
<HeaderBackButton
|
|
158
|
-
style={
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
marginLeft: Platform.select({ ios: -8, default: -3 }),
|
|
163
|
-
marginRight: Platform.select({ ios: 0, default: 30 }),
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
backImage={isLiquidGlassEnabled() ? renderGlassBackImage : undefined}
|
|
219
|
+
style={Platform.select({
|
|
220
|
+
ios: { marginLeft: -8 },
|
|
221
|
+
default: { marginLeft: -3, marginRight: 30 },
|
|
222
|
+
})}
|
|
167
223
|
displayMode="minimal"
|
|
168
224
|
onPress={onPress}
|
|
169
225
|
{...props}
|
|
170
226
|
/>
|
|
171
227
|
)
|
|
172
228
|
|
|
173
|
-
// Under glass the native minimal back button suffices; pre-26 needs the
|
|
174
|
-
// custom button and its layout nudges.
|
|
175
229
|
export const withMinimalBack =
|
|
176
230
|
({ onPress }: { onPress: () => void }): OptionsDecorator =>
|
|
177
231
|
options => ({
|
|
178
232
|
...options,
|
|
179
|
-
|
|
233
|
+
headerLeft: createMinimalHeaderBackElement({ onPress }),
|
|
234
|
+
unstable_headerLeftItems: () => [
|
|
235
|
+
createHeaderIconItem({ icon: 'general.leftChevron', accessibilityLabel: 'Back', onPress }),
|
|
236
|
+
],
|
|
180
237
|
})
|
|
181
238
|
|
|
182
|
-
|
|
183
|
-
title: string
|
|
239
|
+
type UseHeaderRightOptions = {
|
|
184
240
|
onPress: () => void
|
|
185
241
|
disabled?: boolean
|
|
186
242
|
enabled?: boolean
|
|
187
|
-
}
|
|
243
|
+
} & (
|
|
244
|
+
| (Omit<HeaderIconProps, 'tintColor'> & { title?: never })
|
|
245
|
+
| { title: string; icon?: never; accessibilityLabel?: never; prominent?: never }
|
|
246
|
+
)
|
|
188
247
|
|
|
189
|
-
|
|
190
|
-
// mutation callbacks). Static buttons belong in the navigator options.
|
|
191
|
-
export const useHeaderRight = ({
|
|
192
|
-
title,
|
|
193
|
-
onPress,
|
|
194
|
-
disabled,
|
|
195
|
-
enabled = true,
|
|
196
|
-
}: UseHeaderRightOptions) => {
|
|
248
|
+
export const useHeaderRight = (options: UseHeaderRightOptions) => {
|
|
197
249
|
const navigation = useNavigation()
|
|
250
|
+
const { colors } = useTheme()
|
|
251
|
+
const { onPress, disabled, enabled = true } = options
|
|
252
|
+
const icon = options.icon
|
|
253
|
+
const label = options.icon !== undefined ? options.accessibilityLabel : options.title
|
|
254
|
+
const prominent = options.icon !== undefined ? options.prominent : undefined
|
|
198
255
|
|
|
199
256
|
useLayoutEffect(() => {
|
|
200
257
|
if (!enabled) {
|
|
@@ -202,8 +259,19 @@ export const useHeaderRight = ({
|
|
|
202
259
|
return
|
|
203
260
|
}
|
|
204
261
|
|
|
205
|
-
|
|
206
|
-
|
|
262
|
+
const decorate = icon
|
|
263
|
+
? withRightIcon({
|
|
264
|
+
icon,
|
|
265
|
+
accessibilityLabel: label,
|
|
266
|
+
onPress,
|
|
267
|
+
disabled,
|
|
268
|
+
prominent,
|
|
269
|
+
tintColor: prominent ? colors.interaction : undefined,
|
|
270
|
+
})
|
|
271
|
+
: withRightText({ text: label, onPress, disabled })
|
|
272
|
+
|
|
273
|
+
navigation.setOptions(decorate({}))
|
|
274
|
+
}, [colors.interaction, disabled, enabled, icon, label, navigation, onPress, prominent])
|
|
207
275
|
}
|
|
208
276
|
|
|
209
277
|
const useStyles = () => {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from 'react-native'
|
|
13
13
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
14
14
|
import { useTheme } from '../../hooks'
|
|
15
|
-
import { MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils'
|
|
15
|
+
import { isLiquidGlassEnabled, MAX_FONT_SIZE_MULTIPLIER_LANDMARK } from '../../utils'
|
|
16
16
|
import type { ButtonProps, TextButtonProps } from '../display'
|
|
17
17
|
import { Button, Heading, Icon, IconString, Text, TextButton } from '../display'
|
|
18
18
|
|
|
@@ -35,7 +35,7 @@ export const getFormSheetScreenOptions = ({
|
|
|
35
35
|
presentation: 'formSheet',
|
|
36
36
|
headerShown: false,
|
|
37
37
|
sheetAllowedDetents,
|
|
38
|
-
sheetCornerRadius: 16,
|
|
38
|
+
sheetCornerRadius: isLiquidGlassEnabled() ? undefined : 16,
|
|
39
39
|
sheetGrabberVisible: true,
|
|
40
40
|
headerTitle,
|
|
41
41
|
...rest,
|
package/src/navigation/index.tsx
CHANGED
|
@@ -2,15 +2,15 @@ import { StaticParamList } from '@react-navigation/native'
|
|
|
2
2
|
import {
|
|
3
3
|
createNativeStackNavigator,
|
|
4
4
|
NativeStackHeaderRightProps,
|
|
5
|
+
NativeStackNavigationOptions,
|
|
5
6
|
} from '@react-navigation/native-stack'
|
|
6
7
|
import { CardStyleInterpolators } from '@react-navigation/stack'
|
|
7
8
|
import React from 'react'
|
|
8
9
|
import {
|
|
9
10
|
composeOptions,
|
|
10
|
-
createMinimalHeaderBackButton,
|
|
11
11
|
withMinimalBack,
|
|
12
12
|
withRightClose,
|
|
13
|
-
|
|
13
|
+
withRightDone,
|
|
14
14
|
} from '../components/display/platform_modal_header_buttons'
|
|
15
15
|
import { useDirectMessagesEnabled, useQualifiedByAge } from '../hooks'
|
|
16
16
|
import {
|
|
@@ -79,13 +79,17 @@ import {
|
|
|
79
79
|
SystemMessagePeopleScreenOptions,
|
|
80
80
|
} from '../screens/system_message_people_screen'
|
|
81
81
|
import { TeamConversationScreen } from '../screens/team_conversation_screen'
|
|
82
|
+
import { isLiquidGlassEnabled } from '../utils/liquid_glass'
|
|
82
83
|
import { ScreenLayoutWithChatAccessGate } from './screenLayout'
|
|
83
84
|
|
|
85
|
+
const globalScreenOptions: () => NativeStackNavigationOptions = () => ({
|
|
86
|
+
headerBackButtonDisplayMode: 'minimal',
|
|
87
|
+
...(isLiquidGlassEnabled() ? { headerShadowVisible: false } : {}),
|
|
88
|
+
})
|
|
89
|
+
|
|
84
90
|
export const NewConversationStack = createNativeStackNavigator({
|
|
85
91
|
initialRouteName: 'ConversationNewEntry',
|
|
86
|
-
screenOptions:
|
|
87
|
-
headerBackButtonDisplayMode: 'minimal',
|
|
88
|
-
},
|
|
92
|
+
screenOptions: globalScreenOptions,
|
|
89
93
|
screenLayout: ScreenLayoutWithChatAccessGate,
|
|
90
94
|
screens: {
|
|
91
95
|
ConversationNewEntry: {
|
|
@@ -96,7 +100,7 @@ export const NewConversationStack = createNativeStackNavigator({
|
|
|
96
100
|
title: 'New conversation',
|
|
97
101
|
headerBackVisible: false,
|
|
98
102
|
},
|
|
99
|
-
|
|
103
|
+
withRightClose({ onPress: navigation.goBack })
|
|
100
104
|
),
|
|
101
105
|
},
|
|
102
106
|
ConversationSelectGroupRecipients: {
|
|
@@ -106,8 +110,7 @@ export const NewConversationStack = createNativeStackNavigator({
|
|
|
106
110
|
{
|
|
107
111
|
title: 'New conversation',
|
|
108
112
|
},
|
|
109
|
-
|
|
110
|
-
text: 'Cancel',
|
|
113
|
+
withRightClose({
|
|
111
114
|
onPress: () => navigation.popTo('Conversations', route.params),
|
|
112
115
|
})
|
|
113
116
|
),
|
|
@@ -119,8 +122,7 @@ export const NewConversationStack = createNativeStackNavigator({
|
|
|
119
122
|
{
|
|
120
123
|
title: 'New conversation',
|
|
121
124
|
},
|
|
122
|
-
|
|
123
|
-
text: 'Cancel',
|
|
125
|
+
withRightClose({
|
|
124
126
|
onPress: () => navigation.popTo('Conversations', route.params),
|
|
125
127
|
})
|
|
126
128
|
),
|
|
@@ -133,8 +135,7 @@ export const NewConversationStack = createNativeStackNavigator({
|
|
|
133
135
|
{
|
|
134
136
|
title: 'New conversation',
|
|
135
137
|
},
|
|
136
|
-
|
|
137
|
-
text: 'Cancel',
|
|
138
|
+
withRightClose({
|
|
138
139
|
onPress: () => navigation.popTo('Conversations', route.params),
|
|
139
140
|
})
|
|
140
141
|
),
|
|
@@ -151,8 +152,7 @@ export const NewConversationStack = createNativeStackNavigator({
|
|
|
151
152
|
title: 'New conversation',
|
|
152
153
|
headerLeft: () => null,
|
|
153
154
|
},
|
|
154
|
-
|
|
155
|
-
text: 'Cancel',
|
|
155
|
+
withRightClose({
|
|
156
156
|
onPress: () => {
|
|
157
157
|
const { chat_group_graph_id, group_source_app_name } =
|
|
158
158
|
route.params as ConversationSelectRecipientsParams
|
|
@@ -169,9 +169,7 @@ export const NewConversationStack = createNativeStackNavigator({
|
|
|
169
169
|
})
|
|
170
170
|
|
|
171
171
|
export const ChatStack = createNativeStackNavigator({
|
|
172
|
-
screenOptions:
|
|
173
|
-
headerBackButtonDisplayMode: 'minimal',
|
|
174
|
-
},
|
|
172
|
+
screenOptions: globalScreenOptions,
|
|
175
173
|
screenLayout: ScreenLayoutWithChatAccessGate,
|
|
176
174
|
screens: {
|
|
177
175
|
Conversations: {
|
|
@@ -210,19 +208,19 @@ export const ChatStack = createNativeStackNavigator({
|
|
|
210
208
|
</ConversationScreenTitle>
|
|
211
209
|
)
|
|
212
210
|
},
|
|
213
|
-
headerLeft: createMinimalHeaderBackButton({
|
|
214
|
-
onPress: () => {
|
|
215
|
-
const params = route.params as ConversationRouteProps
|
|
216
|
-
if ((params as ConversationFiltersParams)?.chat_group_graph_id) {
|
|
217
|
-
// Ensure that conversations with a graph id pass them back to the conversation list
|
|
218
|
-
const { chat_group_graph_id } = params
|
|
219
|
-
navigation.popTo('Conversations', { chat_group_graph_id })
|
|
220
|
-
} else {
|
|
221
|
-
navigation.goBack()
|
|
222
|
-
}
|
|
223
|
-
},
|
|
224
|
-
}),
|
|
225
211
|
},
|
|
212
|
+
withMinimalBack({
|
|
213
|
+
onPress: () => {
|
|
214
|
+
const params = route.params as ConversationRouteProps
|
|
215
|
+
if ((params as ConversationFiltersParams)?.chat_group_graph_id) {
|
|
216
|
+
// Ensure that conversations with a graph id pass them back to the conversation list
|
|
217
|
+
const { chat_group_graph_id } = params
|
|
218
|
+
navigation.popTo('Conversations', { chat_group_graph_id })
|
|
219
|
+
} else {
|
|
220
|
+
navigation.goBack()
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
}),
|
|
226
224
|
withRightClose({ onPress: () => navigation.getParent()?.goBack() })
|
|
227
225
|
),
|
|
228
226
|
},
|
|
@@ -251,7 +249,7 @@ export const ChatStack = createNativeStackNavigator({
|
|
|
251
249
|
presentation: 'modal',
|
|
252
250
|
title: 'Conversation details',
|
|
253
251
|
},
|
|
254
|
-
|
|
252
|
+
withRightDone({ onPress: navigation.goBack })
|
|
255
253
|
),
|
|
256
254
|
},
|
|
257
255
|
AvatarPicker: {
|
|
@@ -261,46 +259,41 @@ export const ChatStack = createNativeStackNavigator({
|
|
|
261
259
|
ChatSettings: {
|
|
262
260
|
screen: SettingsScreen,
|
|
263
261
|
options: ({ navigation }) =>
|
|
264
|
-
composeOptions(
|
|
265
|
-
{
|
|
266
|
-
title: 'Chat settings',
|
|
267
|
-
headerBackVisible: false,
|
|
268
|
-
},
|
|
269
|
-
withRightText({ text: 'Done', onPress: navigation.goBack })
|
|
270
|
-
),
|
|
262
|
+
composeOptions({ title: 'Chat settings' }, withMinimalBack({ onPress: navigation.goBack })),
|
|
271
263
|
},
|
|
272
264
|
NotificationSettings: {
|
|
273
265
|
screen: NotificationSettingsScreen,
|
|
274
266
|
options: ({ navigation }) =>
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
267
|
+
navigation.getState().index === 0
|
|
268
|
+
? composeOptions(
|
|
269
|
+
{ title: 'Chat notifications' },
|
|
270
|
+
withRightClose({ onPress: navigation.goBack })
|
|
271
|
+
)
|
|
272
|
+
: composeOptions(
|
|
273
|
+
{ title: 'Chat notifications' },
|
|
274
|
+
withMinimalBack({ onPress: navigation.goBack })
|
|
275
|
+
),
|
|
282
276
|
},
|
|
283
277
|
PreferredAppSelection: {
|
|
284
278
|
screen: PreferredAppSelectionScreen,
|
|
285
|
-
options: {
|
|
286
|
-
title: 'Preferred app',
|
|
287
|
-
},
|
|
279
|
+
options: ({ navigation }) =>
|
|
280
|
+
composeOptions({ title: 'Preferred app' }, withMinimalBack({ onPress: navigation.goBack })),
|
|
288
281
|
},
|
|
289
282
|
GroupNotificationSettings: {
|
|
290
283
|
screen: GroupNotificationSettingsScreen,
|
|
291
284
|
options: ({ route, navigation }) => {
|
|
292
285
|
const title = (route.params as { title?: string })?.title || 'Group Settings'
|
|
293
286
|
|
|
294
|
-
//
|
|
295
|
-
// deeper in the stack the back button covers dismissal.
|
|
287
|
+
// The dismiss button only shows when this is the entry screen (e.g.
|
|
288
|
+
// deep links); deeper in the stack the back button covers dismissal.
|
|
296
289
|
return navigation.getState().index === 0
|
|
297
290
|
? composeOptions(
|
|
298
291
|
{
|
|
299
292
|
title,
|
|
300
293
|
},
|
|
301
|
-
|
|
294
|
+
withRightClose({ onPress: navigation.goBack })
|
|
302
295
|
)
|
|
303
|
-
: { title }
|
|
296
|
+
: composeOptions({ title }, withMinimalBack({ onPress: navigation.goBack }))
|
|
304
297
|
},
|
|
305
298
|
},
|
|
306
299
|
GroupNotificationLevelSelect: {
|
|
@@ -328,7 +321,7 @@ export const ChatStack = createNativeStackNavigator({
|
|
|
328
321
|
title: 'New conversation',
|
|
329
322
|
headerLeft: () => null,
|
|
330
323
|
},
|
|
331
|
-
|
|
324
|
+
withRightClose({ onPress: () => navigation.getParent()?.goBack() })
|
|
332
325
|
),
|
|
333
326
|
},
|
|
334
327
|
SendGiphy: {
|
|
@@ -377,7 +370,7 @@ export const ChatStack = createNativeStackNavigator({
|
|
|
377
370
|
headerBackVisible: false,
|
|
378
371
|
presentation: 'modal',
|
|
379
372
|
},
|
|
380
|
-
|
|
373
|
+
withRightClose({ onPress: navigation.goBack })
|
|
381
374
|
),
|
|
382
375
|
},
|
|
383
376
|
NotFound: {
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
composeOptions,
|
|
29
29
|
HeaderDismissButton,
|
|
30
30
|
useHeaderRight,
|
|
31
|
-
|
|
31
|
+
withLeftClose,
|
|
32
32
|
} from '../components/display/platform_modal_header_buttons'
|
|
33
33
|
import { VideoAttachmentPreview } from '../components/display/video_attachment_preview'
|
|
34
34
|
import { DefaultLoading } from '../components/page/loading'
|
|
@@ -60,7 +60,7 @@ export const BugReportScreenOptions = ({
|
|
|
60
60
|
}: NativeStackScreenProps<any>): NativeStackNavigationOptions =>
|
|
61
61
|
composeOptions(
|
|
62
62
|
{ presentation: 'modal', title: 'Report a bug' },
|
|
63
|
-
|
|
63
|
+
withLeftClose({ onPress: () => navigation.goBack() })
|
|
64
64
|
)
|
|
65
65
|
|
|
66
66
|
interface Attachment {
|
|
@@ -158,7 +158,13 @@ export function BugReportScreen() {
|
|
|
158
158
|
return ImagePicker.openImageLibraryAsync().then(result => uploadImagePickerResult(result))
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
useHeaderRight({
|
|
161
|
+
useHeaderRight({
|
|
162
|
+
icon: 'general.upArrow',
|
|
163
|
+
accessibilityLabel: 'Submit',
|
|
164
|
+
prominent: true,
|
|
165
|
+
onPress: handleSubmit,
|
|
166
|
+
disabled: !formValid,
|
|
167
|
+
})
|
|
162
168
|
|
|
163
169
|
if (status === 'pending') {
|
|
164
170
|
return (
|
|
@@ -223,7 +223,8 @@ export function ConversationDetailsScreen({ route }: ConversationDetailsScreenPr
|
|
|
223
223
|
)
|
|
224
224
|
|
|
225
225
|
useHeaderRight({
|
|
226
|
-
|
|
226
|
+
icon: 'general.check',
|
|
227
|
+
accessibilityLabel: 'Done',
|
|
227
228
|
onPress: () => {
|
|
228
229
|
saveTitle({ title: trimmedTitle || conversation.title })
|
|
229
230
|
navigation.goBack()
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
useRoute,
|
|
10
10
|
} from '@react-navigation/native'
|
|
11
11
|
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
|
12
|
-
import { FlatList, Platform, StyleSheet, View } from 'react-native'
|
|
12
|
+
import { FlatList, Platform, StyleSheet, useWindowDimensions, View } from 'react-native'
|
|
13
13
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
14
14
|
import { Badge, Icon, Text } from '../components'
|
|
15
15
|
import { ConversationStartBanner } from '../components/conversation/conversation_start_banner'
|
|
@@ -25,6 +25,7 @@ import { ReplyShadowMessage } from '../components/conversation/reply_shadow_mess
|
|
|
25
25
|
import { SystemMessage } from '../components/conversation/system_message'
|
|
26
26
|
import { TypingIndicator } from '../components/conversation/typing_indicator'
|
|
27
27
|
import { KeyboardView } from '../components/display/keyboard_view'
|
|
28
|
+
import { useHeaderSlotReserve } from '../components/display/platform_modal_header_buttons'
|
|
28
29
|
import BlankState from '../components/primitive/blank_state_primitive'
|
|
29
30
|
import { ConversationContextProvider } from '../contexts/conversation_context'
|
|
30
31
|
import { useTheme } from '../hooks'
|
|
@@ -374,11 +375,15 @@ export const ConversationScreenTitle = ({
|
|
|
374
375
|
}
|
|
375
376
|
|
|
376
377
|
const usePressableHeaderStyle = () => {
|
|
378
|
+
const { width } = useWindowDimensions()
|
|
379
|
+
const slotReserve = useHeaderSlotReserve()
|
|
380
|
+
const headerContainerStyle = { maxWidth: width - slotReserve * 2 }
|
|
381
|
+
|
|
377
382
|
return StyleSheet.create({
|
|
378
383
|
container: {
|
|
379
384
|
alignItems: Platform.select({ android: 'flex-start', default: 'center' }),
|
|
380
|
-
marginRight: Platform.select({ ios: 20, default: 16 }),
|
|
381
385
|
flex: 1,
|
|
386
|
+
...headerContainerStyle,
|
|
382
387
|
},
|
|
383
388
|
titleWrapper: {
|
|
384
389
|
alignItems: 'center',
|
|
@@ -10,7 +10,7 @@ import { Spinner, Text, KeyboardView } from '../components'
|
|
|
10
10
|
import {
|
|
11
11
|
composeOptions,
|
|
12
12
|
useHeaderRight,
|
|
13
|
-
|
|
13
|
+
withLeftClose,
|
|
14
14
|
} from '../components/display/platform_modal_header_buttons'
|
|
15
15
|
import BlankState from '../components/primitive/blank_state_primitive'
|
|
16
16
|
import { useTheme } from '../hooks'
|
|
@@ -37,7 +37,7 @@ export const MessageReportScreenOptions = ({
|
|
|
37
37
|
|
|
38
38
|
return composeOptions(
|
|
39
39
|
{ presentation: 'modal', title: 'Report message' },
|
|
40
|
-
|
|
40
|
+
withLeftClose({ onPress: handleClose })
|
|
41
41
|
)
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -106,7 +106,9 @@ function MessageReportScreenContent({
|
|
|
106
106
|
const formVisible = status !== 'pending' && status !== 'success'
|
|
107
107
|
|
|
108
108
|
useHeaderRight({
|
|
109
|
-
|
|
109
|
+
icon: 'general.upArrow',
|
|
110
|
+
accessibilityLabel: 'Submit',
|
|
111
|
+
prominent: true,
|
|
110
112
|
onPress: handleSubmit,
|
|
111
113
|
disabled: !isFormValid,
|
|
112
114
|
enabled: formVisible,
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { PlatformPressable } from '@react-navigation/elements'
|
|
2
2
|
import { StaticScreenProps, useNavigation } from '@react-navigation/native'
|
|
3
|
-
import
|
|
3
|
+
import { type ReactNode } from 'react'
|
|
4
4
|
import { FlatList, Platform, StyleSheet, View, type ViewProps, type ViewStyle } from 'react-native'
|
|
5
5
|
import { useSafeAreaInsets } from 'react-native-safe-area-context'
|
|
6
6
|
import { Badge, Heading, Icon, Text } from '../components'
|
|
7
|
-
import { useHeaderRight } from '../components/display/platform_modal_header_buttons'
|
|
8
7
|
import { useTheme } from '../hooks'
|
|
9
8
|
import { isDefined } from '../types'
|
|
10
9
|
import { chatTypeLabel } from '../utils'
|
|
@@ -51,8 +50,6 @@ export function NotificationSettingsScreen({}: NotificationSettingsScreenProps)
|
|
|
51
50
|
const { data: chatTypes } = useChatTypes()
|
|
52
51
|
const { data: groups } = useGroups()
|
|
53
52
|
|
|
54
|
-
useHeaderRight({ title: 'Done', onPress: navigation.goBack })
|
|
55
|
-
|
|
56
53
|
// Build section data
|
|
57
54
|
const listData = [
|
|
58
55
|
{
|