Skip to content

Commit 177def8

Browse files
committed
fix: Android Menu selector
Added design system menu Fixed splash screen for dark mode
1 parent e2274aa commit 177def8

File tree

6 files changed

+146
-103
lines changed

6 files changed

+146
-103
lines changed

App.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ LogBox.ignoreLogs([
5353
'event="noNetwork', // ethers
5454
"[Reanimated] Reading from `value` during component render. Please ensure that you do not access the `value` property or use `get` method of a shared value while React is rendering a component.",
5555
"Attempted to import the module",
56+
"Couldn't find real values for `KeyboardContext`. Please make sure you're inside of `KeyboardProvider` - otherwise functionality of `react-native-keyboard-controller` will not work. [Component Stack]",
5657
]);
5758

5859
// This is the default configuration

app.config.ts

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ const isProduction = !isDev && !isPreview;
1818
const scheme = isDev
1919
? "converse-dev"
2020
: isPreview
21-
? "converse-preview"
22-
: "converse";
21+
? "converse-preview"
22+
: "converse";
2323
const androidPackage = isDev
2424
? "com.converse.dev"
2525
: isPreview
26-
? "com.converse.preview"
27-
: "com.converse.prod";
26+
? "com.converse.preview"
27+
: "com.converse.prod";
2828
const appDomainConverse = isDev
2929
? "dev.converse.xyz"
3030
: isPreview
31-
? "preview.converse.xyz"
32-
: "converse.xyz";
31+
? "preview.converse.xyz"
32+
: "converse.xyz";
3333
const appDomainGetConverse = isDev
3434
? "dev.getconverse.app"
3535
: isPreview
36-
? "preview.getconverse.app"
37-
: "getconverse.app";
36+
? "preview.getconverse.app"
37+
: "getconverse.app";
3838

3939
export default ({ config }: ConfigContext): ExpoConfig => ({
4040
...config,
@@ -44,11 +44,6 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
4444
orientation: "portrait",
4545
icon: isProduction ? "./assets/icon.png" : "./assets/icon-preview.png",
4646
userInterfaceStyle: "automatic",
47-
splash: {
48-
image: "./assets/splash.png",
49-
resizeMode: "contain",
50-
backgroundColor: "#ffffff",
51-
},
5247
updates: {
5348
fallbackToCacheTimeout: 0,
5449
url: "https://u.expo.dev/49a65fae-3895-4487-8e8a-5bd8bee3a401",
@@ -77,8 +72,8 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
7772
googleServicesFile: isDev
7873
? "./scripts/build/android/google-services/dev.json"
7974
: isPreview
80-
? "./scripts/build/android/google-services/preview.json"
81-
: "./scripts/build/android/google-services/production.json",
75+
? "./scripts/build/android/google-services/preview.json"
76+
: "./scripts/build/android/google-services/production.json",
8277
permissions: [
8378
"INTERNET",
8479
"READ_EXTERNAL_STORAGE",
@@ -225,6 +220,19 @@ export default ({ config }: ConfigContext): ExpoConfig => ({
225220
},
226221
},
227222
],
223+
[
224+
"expo-splash-screen",
225+
{
226+
image: "./assets/splash.png",
227+
backgroundColor: "#ffffff",
228+
dark: {
229+
image: "./assets/splash-dark.png",
230+
backgroundColor: "#000000",
231+
},
232+
imageWidth: 300,
233+
},
234+
],
235+
"expo-secure-store",
228236
[
229237
"@sentry/react-native/expo",
230238
{

design-system/Menu/Menu.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { useCallback, useMemo } from "react";
2+
import {
3+
MenuView,
4+
NativeActionEvent,
5+
MenuAction as RNMenuAction,
6+
} from "@react-native-menu/menu";
7+
import { Platform, StyleProp, ViewStyle } from "react-native";
8+
import { Pressable } from "../Pressable";
9+
import { useAppTheme } from "@/theme/useAppTheme";
10+
import { Haptics } from "@/utils/haptics";
11+
import { getInlinedItem } from "./Menu.utils";
12+
13+
export type IMenuAction = Omit<RNMenuAction, "titleColor" | "imageColor"> & {
14+
color?: string;
15+
};
16+
17+
type MenuProps = {
18+
actions: IMenuAction[];
19+
children: React.ReactNode;
20+
style?: StyleProp<ViewStyle>;
21+
onPress?: (actionId: string) => void;
22+
};
23+
24+
export const Menu = ({ children, actions, style, onPress }: MenuProps) => {
25+
const { theme } = useAppTheme();
26+
27+
const themedActions: RNMenuAction[] = useMemo(() => {
28+
return actions.map((action) => {
29+
const themedAction = {
30+
...action,
31+
// AR: Right now Android will only show a background color of white, so don't set a titleColor which is android specific anyways
32+
// This may be only an android 13 issue though, will either need to fix the library or wait for a fix
33+
titleColor: action.color ?? theme.colors.global.primary,
34+
imageColor:
35+
action.color ??
36+
(Platform.OS === "android" ? theme.colors.global.primary : undefined),
37+
displayInline: action.displayInline,
38+
};
39+
return action.displayInline ? getInlinedItem(themedAction) : themedAction;
40+
});
41+
}, [actions, theme.colors.global.primary]);
42+
43+
const handlePress = useCallback(
44+
({ nativeEvent }: NativeActionEvent) => {
45+
Haptics.selectionAsync();
46+
onPress?.(nativeEvent.event);
47+
},
48+
[onPress]
49+
);
50+
51+
return (
52+
<MenuView
53+
onPressAction={handlePress}
54+
actions={themedActions}
55+
style={style}
56+
shouldOpenOnLongPress={false}
57+
>
58+
<Pressable style={$pressable}>{children}</Pressable>
59+
</MenuView>
60+
);
61+
};
62+
63+
const $pressable: ViewStyle = {
64+
alignItems: "center",
65+
justifyContent: "center",
66+
};

design-system/Menu/Menu.utils.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Platform } from "react-native";
2+
import { MenuAction as RNMenuAction } from "@react-native-menu/menu";
3+
4+
/**
5+
* Android will always make a sub menu item, so instead this will just return the item
6+
* iOS seems to work fine with the item, so this will just return the item
7+
* @param item RN Menu Action
8+
* @returns RN Menu Action
9+
*/
10+
export const getInlinedItem = (item: RNMenuAction): RNMenuAction => {
11+
if (Platform.OS === "ios") {
12+
return {
13+
title: "",
14+
displayInline: true,
15+
subactions: [item],
16+
};
17+
}
18+
return item;
19+
};

features/conversation-list/conversation-list.screen-header.tsx

Lines changed: 29 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,12 @@ import { usePreferredName } from "@/hooks/usePreferredName";
1414
import { translate } from "@/i18n";
1515
import { useHeader } from "@/navigation/use-header";
1616
import { useAppTheme } from "@/theme/useAppTheme";
17-
import { Haptics } from "@/utils/haptics";
1817
import { shortDisplayName } from "@/utils/str";
1918
import { useAccountsProfiles } from "@/utils/useAccountsProfiles";
2019
import { useNavigation } from "@react-navigation/native";
2120
import React from "react";
2221
import { Alert, Platform } from "react-native";
23-
import {
24-
ContextMenuButton,
25-
MenuActionConfig,
26-
} from "react-native-ios-context-menu";
22+
import { Menu } from "@/design-system/Menu/Menu";
2723

2824
export function useHeaderWrapper() {
2925
const { theme } = useAppTheme();
@@ -84,80 +80,46 @@ export function useHeaderWrapper() {
8480
<Avatar size={theme.avatarSize.sm} />
8581
</Center>
8682
</Pressable>
87-
<ContextMenuButton
88-
// hitSlop={theme.spacing.sm} // Not working...
83+
<Menu
8984
style={{
9085
paddingVertical: theme.spacing.sm, // TMP solution for the hitSlop not working
9186
paddingRight: theme.spacing.sm, // TMP solution for the hitSlop not working
9287
}}
93-
isMenuPrimaryAction
94-
onPressMenuItem={({ nativeEvent }) => {
95-
Haptics.selectionAsync();
96-
if (nativeEvent.actionKey === "all-chats") {
88+
onPress={(actionId: string) => {
89+
if (actionId === "all-chats") {
9790
Alert.alert("Coming soon");
98-
} else if (nativeEvent.actionKey === "new-account") {
91+
} else if (actionId === "new-account") {
9992
navigation.navigate("NewAccountNavigator");
100-
} else if (nativeEvent.actionKey === "app-settings") {
93+
} else if (actionId === "app-settings") {
10194
Alert.alert("Coming soon");
10295
}
10396

10497
// Pressed on an account
10598
else {
106-
setCurrentAccount(nativeEvent.actionKey, false);
99+
setCurrentAccount(actionId, false);
107100
}
108101
}}
109-
menuConfig={{
110-
menuTitle: "",
111-
menuItems: [
112-
...accountsProfiles.map((profilePreferedName, index) => {
113-
return {
114-
actionKey: accounts[index],
115-
actionTitle: shortDisplayName(profilePreferedName),
116-
icon: {
117-
iconType: "SYSTEM",
118-
iconValue:
119-
currentAccount === accounts[index]
120-
? Platform.select({
121-
default: "checkmark",
122-
ios: "checkmark",
123-
android: "checkmark",
124-
})
125-
: "",
126-
},
127-
} as MenuActionConfig;
128-
}),
129-
{
130-
type: "menu",
131-
menuTitle: "",
132-
menuOptions: ["displayInline"],
133-
menuItems: [
134-
{
135-
actionKey: "new-account",
136-
actionTitle: translate("new_account"),
137-
icon: {
138-
iconType: "SYSTEM",
139-
iconValue: iconRegistry["new-account-card"],
140-
},
141-
},
142-
],
143-
},
144-
{
145-
type: "menu",
146-
menuTitle: "",
147-
menuOptions: ["displayInline"],
148-
menuItems: [
149-
{
150-
actionKey: "app-settings",
151-
actionTitle: translate("App settings"),
152-
icon: {
153-
iconType: "SYSTEM",
154-
iconValue: iconRegistry["settings"],
155-
},
156-
},
157-
],
158-
},
159-
],
160-
}}
102+
actions={[
103+
...accountsProfiles.map((profilePreferedName, index) => {
104+
return {
105+
id: accounts[index],
106+
title: shortDisplayName(profilePreferedName),
107+
image: currentAccount === accounts[index] ? "checkmark" : "",
108+
};
109+
}),
110+
{
111+
displayInline: true,
112+
id: "new-account",
113+
title: translate("new_account"),
114+
image: iconRegistry["new-account-card"],
115+
},
116+
{
117+
displayInline: true,
118+
id: "app-settings",
119+
title: translate("App settings"),
120+
image: iconRegistry["settings"],
121+
},
122+
]}
161123
>
162124
<HStack
163125
// {...debugBorder()}
@@ -181,7 +143,7 @@ export function useHeaderWrapper() {
181143
/>
182144
</Center>
183145
</HStack>
184-
</ContextMenuButton>
146+
</Menu>
185147
</HStack>
186148
),
187149
},

features/conversation/conversation-composer/conversation-composer-add-attachment-button.tsx

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import { Center } from "@/design-system/Center";
2+
import { Menu } from "@/design-system/Menu/Menu";
13
import { useConversationComposerStore } from "@/features/conversation/conversation-composer/conversation-composer.store-context";
24
import { getCurrentAccount } from "@data/store/accountsStore";
35
import { Icon } from "@design-system/Icon/Icon";
4-
import { Pressable } from "@design-system/Pressable";
56
import { translate } from "@i18n";
6-
import { MenuView } from "@react-native-menu/menu";
77
import { useAppTheme } from "@theme/useAppTheme";
88
import { uploadRemoteAttachment } from "@utils/attachment/uploadRemoteAttachment";
99
import {
@@ -97,13 +97,13 @@ export function AddAttachmentButton() {
9797
}, [handleAttachmentSelected]);
9898

9999
return (
100-
<MenuView
100+
<Menu
101101
style={{
102102
margin: theme.spacing.xxxs,
103103
alignSelf: "flex-end",
104104
}}
105-
onPressAction={async ({ nativeEvent }) => {
106-
switch (nativeEvent.event) {
105+
onPress={(actionId) => {
106+
switch (actionId) {
107107
case "camera":
108108
openCamera();
109109
break;
@@ -118,11 +118,6 @@ export function AddAttachmentButton() {
118118
{
119119
id: "mediaLibrary",
120120
title: translate("photo_library"),
121-
titleColor: theme.colors.text.primary,
122-
imageColor: Platform.select({
123-
ios: undefined,
124-
android: theme.colors.text.primary,
125-
}),
126121
image: Platform.select({
127122
ios: "square.and.arrow.up",
128123
android: "ic_menu_share",
@@ -131,23 +126,15 @@ export function AddAttachmentButton() {
131126
{
132127
id: "camera",
133128
title: translate("camera"),
134-
titleColor: theme.colors.text.primary,
135-
imageColor: Platform.select({
136-
ios: undefined,
137-
android: theme.colors.text.primary,
138-
}),
139129
image: Platform.select({
140130
ios: "camera",
141131
android: "ic_menu_camera",
142132
}),
143133
},
144134
]}
145-
shouldOpenOnLongPress={false}
146135
>
147-
<Pressable
136+
<Center
148137
style={{
149-
alignItems: "center",
150-
justifyContent: "center",
151138
height: 36, // Value from Figma
152139
width: 36, // Value from Figma
153140
backgroundColor: theme.colors.fill.minimal,
@@ -159,7 +146,7 @@ export function AddAttachmentButton() {
159146
icon="plus"
160147
size={20} // Value from figma
161148
/>
162-
</Pressable>
163-
</MenuView>
149+
</Center>
150+
</Menu>
164151
);
165152
}

0 commit comments

Comments
 (0)