Skip to content

Commit f78b776

Browse files
authored
fix: various UI fixes (#2521)
* fix(widgets): fact changing on rerender * fix(widgets): fix widgets sort order * refactor(ui): replace showSheet with sheetRef usage in various components * fix(contacts): fix add contact by paste * fix(contacts): fix sheet not opening on send to contact * fix(receive): elements not pressable on Android
1 parent 14c9664 commit f78b776

File tree

12 files changed

+63
-61
lines changed

12 files changed

+63
-61
lines changed

e2e/slashtags.e2e.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ d('Profile and Contacts', () => {
8383
await element(by.id('ProfileAddLink')).tap();
8484

8585
await element(by.id('LinkLabelInput')).typeText('LINK-LABEL');
86+
await sleep(300); // wait for keyboard
8687
await element(by.id('LinkValueInput')).typeText('link-value');
88+
await sleep(300); // wait for keyboard
8789
await element(by.id('SaveLink')).tap();
8890
await waitFor(element(by.id('SaveLink'))).not.toBeVisible();
8991
await expect(element(by.text('LINK-LABEL'))).toExist();
@@ -137,6 +139,13 @@ d('Profile and Contacts', () => {
137139
.withTimeout(30000);
138140
await expect(element(by.text(satoshi.name))).toExist();
139141
await expect(element(by.text(satoshi.bio))).toExist();
142+
143+
// Android: keyboard is not dismissed after adding contact in e2e
144+
if (device.getPlatform() === 'android') {
145+
await element(by.id('NameInput')).tapReturnKey();
146+
await sleep(300); // wait for keyboard to hide
147+
}
148+
140149
await element(by.id('SaveContactButton')).tap();
141150
await expect(element(by.text('WEBSITE'))).toExist();
142151
await expect(element(by.text(satoshi.website))).toExist();
@@ -152,6 +161,14 @@ d('Profile and Contacts', () => {
152161
.withTimeout(30000);
153162
await expect(element(by.text(hal.name1))).toExist();
154163
await element(by.id('NameInput')).replaceText(hal.name2);
164+
await sleep(300); // wait for keyboard to hide
165+
166+
// Android: keyboard is not dismissed after adding contact in e2e
167+
if (device.getPlatform() === 'android') {
168+
await element(by.id('NameInput')).tapReturnKey();
169+
await sleep(300); // wait for keyboard to hide
170+
}
171+
155172
await element(by.id('SaveContactButton')).tap();
156173
await expect(element(by.text(hal.name2.toUpperCase()))).toExist();
157174
await element(by.id('NavigationClose')).tap();

src/components/TabBar.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import type { RootNavigationProp } from '../navigation/types';
1919
import { useSheetRef } from '../sheets/SheetRefsProvider';
2020
import { resetSendTransaction } from '../store/actions/wallet';
2121
import { spendingOnboardingSelector } from '../store/reselect/aggregations';
22-
import { showSheet } from '../store/utils/ui';
2322
import { ScanIcon } from '../styles/icons';
2423
import ButtonBlur from './buttons/ButtonBlur';
2524

@@ -34,13 +33,13 @@ const TabBar = (): ReactElement => {
3433

3534
const onReceivePress = (): void => {
3635
const currentRoute = rootNavigation.getCurrentRoute();
36+
const screen =
37+
// if we are on the spending screen and the user has not yet received funds
38+
currentRoute === 'ActivitySpending' && isSpendingOnboarding
39+
? 'ReceiveAmount'
40+
: 'ReceiveQR';
3741

38-
// if we are on the spending screen and the user has not yet received funds
39-
if (currentRoute === 'ActivitySpending' && isSpendingOnboarding) {
40-
showSheet('receive', { screen: 'ReceiveAmount' });
41-
} else {
42-
receiveSheetRef.current?.present();
43-
}
42+
receiveSheetRef.current?.present({ screen });
4443
};
4544

4645
const onSendPress = (): void => {

src/components/Widgets.tsx

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
import { useFocusEffect } from '@react-navigation/native';
22
import { useNavigation } from '@react-navigation/native';
3-
import React, {
4-
ReactElement,
5-
memo,
6-
useCallback,
7-
useMemo,
8-
useState,
9-
} from 'react';
3+
import React, { ReactElement, memo, useCallback, useState } from 'react';
104
import { useTranslation } from 'react-i18next';
115
import { StyleSheet } from 'react-native';
126
import DraggableFlatList, {
@@ -52,18 +46,6 @@ const Widgets = (): ReactElement => {
5246

5347
useFocusEffect(useCallback(() => setEditing(false), []));
5448

55-
const sortedWidgets = useMemo(() => {
56-
const savedWidgets = Object.keys(widgets);
57-
58-
const sorted = savedWidgets.sort((a, b) => {
59-
const indexA = sortOrder.indexOf(a);
60-
const indexB = sortOrder.indexOf(b);
61-
return indexA - indexB;
62-
});
63-
64-
return sorted;
65-
}, [widgets, sortOrder]);
66-
6749
const onDragEnd = useCallback(
6850
({ data }) => {
6951
const order = data.map((id): string => id);
@@ -83,7 +65,7 @@ const Widgets = (): ReactElement => {
8365
({ item: id, drag }: RenderItemParams<string>): ReactElement => {
8466
const initiateDrag = (): void => {
8567
// only allow dragging if there are more than 1 widget
86-
if (sortedWidgets.length > 1 && editing) {
68+
if (sortOrder.length > 1 && editing) {
8769
drag();
8870
}
8971
};
@@ -168,14 +150,14 @@ const Widgets = (): ReactElement => {
168150
/>
169151
);
170152
},
171-
[editing, widgets, sortedWidgets.length],
153+
[editing, widgets, sortOrder.length],
172154
);
173155

174156
return (
175157
<View style={styles.root}>
176158
<View style={styles.title} testID="WidgetsTitle">
177159
<Caption13Up color="secondary">{t('widgets')}</Caption13Up>
178-
{sortedWidgets.length > 0 && (
160+
{sortOrder.length > 0 && (
179161
<TouchableOpacity
180162
hitSlop={{ top: 15, right: 15, bottom: 15, left: 15 }}
181163
testID="WidgetsEdit"
@@ -190,7 +172,7 @@ const Widgets = (): ReactElement => {
190172
</View>
191173

192174
<DraggableFlatList
193-
data={sortedWidgets}
175+
data={sortOrder}
194176
keyExtractor={(id): string => id}
195177
renderItem={(params): ReactElement => (
196178
<ScaleDecorator>{renderItem(params)}</ScaleDecorator>

src/components/widgets/edit/FactsItems.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { useMemo } from 'react';
12
import { useTranslation } from 'react-i18next';
23
import { TFactsWidgetOptions } from '../../../store/types/widgets';
34
import { BodySSB, Title } from '../../../styles/text';
@@ -6,7 +7,7 @@ import { EWidgetItemType, TWidgetItem } from './types';
67

78
export const getFactsItems = (options: TFactsWidgetOptions): TWidgetItem[] => {
89
const { t } = useTranslation('widgets');
9-
const fact = getRandomFact();
10+
const fact = useMemo(() => getRandomFact(), []);
1011

1112
return [
1213
{

src/screens/Activity/ActivityDetail.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ import type {
6666
RootNavigationProp,
6767
RootStackScreenProps,
6868
} from '../../navigation/types';
69+
import { useSheetRef } from '../../sheets/SheetRefsProvider';
6970
import {
7071
activityItemSelector,
7172
activityItemsSelector,
@@ -85,7 +86,6 @@ import {
8586
deleteMetaTxTag,
8687
} from '../../store/slices/metadata';
8788
import { ETransferStatus } from '../../store/types/wallet';
88-
import { showSheet } from '../../store/utils/ui';
8989
import { getBoostedTransactionParents } from '../../utils/boost';
9090
import {
9191
ellipsis,
@@ -159,6 +159,8 @@ const OnchainActivityDetail = ({
159159
const { wallet } = useOnchainWallet();
160160
const { t } = useTranslation('wallet');
161161
const { t: tTime } = useTranslation('intl', { i18n: i18nTime });
162+
const boostSheetRef = useSheetRef('boost');
163+
const activityTagsSheetRef = useSheetRef('activityTags');
162164
const switchUnit = useSwitchUnit();
163165
const dispatch = useAppDispatch();
164166
const contacts = useAppSelector(contactsSelector);
@@ -235,11 +237,11 @@ const OnchainActivityDetail = ({
235237
};
236238

237239
const handleBoost = (): void => {
238-
showSheet('boost', { activityItem: item });
240+
boostSheetRef.current?.present({ activityItem: item });
239241
};
240242

241243
const handleAddTag = (): void => {
242-
showSheet('activityTags', { id });
244+
activityTagsSheetRef.current?.present({ id });
243245
};
244246

245247
const handleRemoveTag = (tag: string): void => {
@@ -678,8 +680,10 @@ const LightningActivityDetail = ({
678680
}): ReactElement => {
679681
const { t } = useTranslation('wallet');
680682
const { t: tTime } = useTranslation('intl', { i18n: i18nTime });
683+
const activityTagsSheetRef = useSheetRef('activityTags');
681684
const switchUnit = useSwitchUnit();
682685
const colors = useColors();
686+
683687
const {
684688
id,
685689
txType,
@@ -700,7 +704,7 @@ const LightningActivityDetail = ({
700704
});
701705

702706
const handleAddTag = (): void => {
703-
showSheet('activityTags', { id });
707+
activityTagsSheetRef.current?.present({ id });
704708
};
705709

706710
const handleRemoveTag = (tag: string): void => {

src/screens/Contacts/Contact.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import { useBalance } from '../../hooks/wallet';
1919
import { RootStackScreenProps } from '../../navigation/types';
2020
import { contactsSelector } from '../../store/reselect/slashtags';
2121
import { isLDKReadySelector } from '../../store/reselect/ui';
22-
import { selectedNetworkSelector } from '../../store/reselect/wallet';
2322
import { deleteContact } from '../../store/slices/slashtags';
2423
import { AnimatedView, View } from '../../styles/components';
2524
import {
@@ -45,7 +44,6 @@ const Contact = ({
4544
const [loading, setLoading] = useState(false);
4645

4746
const dispatch = useAppDispatch();
48-
const selectedNetwork = useAppSelector(selectedNetworkSelector);
4947
const contacts = useAppSelector(contactsSelector);
5048
const isLDKReady = useAppSelector(isLDKReadySelector);
5149

@@ -91,11 +89,7 @@ const Contact = ({
9189
});
9290
}
9391

94-
const res = await processUri({
95-
uri: url,
96-
source: 'send',
97-
selectedNetwork,
98-
});
92+
const res = await processUri({ uri: url });
9993
setLoading(false);
10094
if (res.isOk()) {
10195
navigation.popToTop();

src/screens/Settings/AddressViewer/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ import { updateWallet } from '../../../store/slices/wallet';
4343
import { TWalletName } from '../../../store/types/wallet';
4444
import { updateActivityList } from '../../../store/utils/activity';
4545
import { updateOnchainFeeEstimates } from '../../../store/utils/fees';
46-
import { showSheet } from '../../../store/utils/ui';
4746
import {
4847
View as ThemedView,
4948
TouchableOpacity,
@@ -620,6 +619,7 @@ const AddressViewer = (): ReactElement => {
620619
* The on-chain transaction will retrieve and include the app's receiving address by default.
621620
* Finally, this method will prompt the sendNavigation modal to appear for the user to finalize and confirm the transaction.
622621
*/
622+
// biome-ignore lint/correctness/useExhaustiveDependencies: sheetRef doesn't change
623623
const onSpendFundsPress = useCallback(
624624
async (utxosLength, selectedUtxosLength): Promise<void> => {
625625
if (utxosLength <= 0) {
@@ -649,7 +649,7 @@ const AddressViewer = (): ReactElement => {
649649
}),
650650
);
651651
sendMax();
652-
showSheet('send', { screen: 'ReviewAndSend' });
652+
sendSheetRef.current?.present({ screen: 'ReviewAndSend' });
653653
},
654654
[selectedUtxos, utxos, selectedNetwork, dispatch],
655655
);

src/screens/Settings/Security/index.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@ import React, { memo, ReactElement, useMemo, useState, useEffect } from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { StyleSheet } from 'react-native';
44

5-
import { View as ThemedView } from '../../../styles/components';
6-
75
import { IsSensorAvailableResult } from '../../../components/Biometrics';
86
import { EItemType, IListData } from '../../../components/List';
97
import { useAppDispatch, useAppSelector } from '../../../hooks/redux';
108
import type { SettingsScreenProps } from '../../../navigation/types';
9+
import { useSheetRef } from '../../../sheets/SheetRefsProvider';
1110
import { updateSettings } from '../../../store/slices/settings';
12-
import { showSheet } from '../../../store/utils/ui';
11+
import { View as ThemedView } from '../../../styles/components';
1312
import rnBiometrics from '../../../utils/biometrics';
1413
import SettingsView from '../SettingsView';
1514

@@ -18,6 +17,7 @@ const SecuritySettings = ({
1817
}: SettingsScreenProps<'SecuritySettings'>): ReactElement => {
1918
const { t } = useTranslation('settings');
2019
const dispatch = useAppDispatch();
20+
const pinSheetRef = useSheetRef('pinNavigation');
2121
const [biometryData, setBiometricData] = useState<IsSensorAvailableResult>();
2222
const {
2323
enableAutoReadClipboard,
@@ -53,6 +53,7 @@ const SecuritySettings = ({
5353
? t('security.footer', { biometryTypeName })
5454
: undefined;
5555

56+
// biome-ignore lint/correctness/useExhaustiveDependencies: sheetRef doesn't change
5657
const settingsListData: IListData[] = useMemo(
5758
() => [
5859
{
@@ -119,7 +120,7 @@ const SecuritySettings = ({
119120
if (pin) {
120121
navigation.navigate('DisablePin');
121122
} else {
122-
showSheet('pinNavigation', { showLaterButton: false });
123+
pinSheetRef.current?.present({ showLaterButton: false });
123124
}
124125
},
125126
},

src/screens/Transfer/Funding.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import React, { ReactElement } from 'react';
22
import { Trans, useTranslation } from 'react-i18next';
33
import { StyleSheet, View } from 'react-native';
4-
import { useAppSelector } from '../../hooks/redux';
54

65
import NavigationHeader from '../../components/NavigationHeader';
76
import SafeAreaInset from '../../components/SafeAreaInset';
87
import RectangleButton from '../../components/buttons/RectangleButton';
8+
import { useAppSelector } from '../../hooks/redux';
99
import { useBalance } from '../../hooks/wallet';
1010
import type { TransferScreenProps } from '../../navigation/types';
11+
import { useSheetRef } from '../../sheets/SheetRefsProvider';
1112
import { spendingIntroSeenSelector } from '../../store/reselect/settings';
1213
import { isGeoBlockedSelector } from '../../store/reselect/user';
13-
import { showSheet } from '../../store/utils/ui';
1414
import { View as ThemedView } from '../../styles/components';
1515
import { QrIcon, ShareAndroidIcon, TransferIcon } from '../../styles/icons';
1616
import { BodyM, Display } from '../../styles/text';
@@ -21,6 +21,7 @@ const Funding = ({
2121
}: TransferScreenProps<'Funding'>): ReactElement => {
2222
const { t } = useTranslation('lightning');
2323
const { onchainBalance } = useBalance();
24+
const receiveSheetRef = useSheetRef('receive');
2425
const isGeoBlocked = useAppSelector(isGeoBlockedSelector);
2526
const spendingIntroSeen = useAppSelector(spendingIntroSeenSelector);
2627

@@ -34,7 +35,7 @@ const Funding = ({
3435

3536
const onFund = (): void => {
3637
navigation.popTo('Wallet', { screen: 'Home' });
37-
showSheet('receive', { screen: 'ReceiveAmount' });
38+
receiveSheetRef.current?.present({ screen: 'ReceiveAmount' });
3839
};
3940

4041
const onAdvanced = (): void => {

src/screens/Wallets/Receive/ReceiveDetails.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { ReactElement, memo, useState, useEffect } from 'react';
22
import { useTranslation } from 'react-i18next';
3-
import { Image, StyleSheet, View } from 'react-native';
4-
import { FadeIn, FadeOut } from 'react-native-reanimated';
3+
import { Image, Platform, StyleSheet, View } from 'react-native';
4+
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
55

66
import BottomSheetNavigationHeader from '../../../components/BottomSheetNavigationHeader';
77
import GradientView from '../../../components/GradientView';
@@ -27,7 +27,7 @@ import {
2727
updatePendingInvoice,
2828
} from '../../../store/slices/metadata';
2929
import { removeInvoiceTag, updateInvoice } from '../../../store/slices/receive';
30-
import { AnimatedView, BottomSheetTextInput } from '../../../styles/components';
30+
import { BottomSheetTextInput } from '../../../styles/components';
3131
import { TagIcon } from '../../../styles/icons';
3232
import { Caption13Up } from '../../../styles/text';
3333
import { estimateOrderFee } from '../../../utils/blocktank';
@@ -174,11 +174,12 @@ const ReceiveDetails = ({
174174
</View>
175175

176176
{!keyboardShown && (
177-
<AnimatedView
177+
<Animated.View
178178
style={styles.bottom}
179-
color="transparent"
180179
entering={FadeIn}
181-
exiting={FadeOut}>
180+
// FadeOut causing a bug on Android
181+
exiting={Platform.OS === 'ios' ? FadeOut : undefined}
182+
>
182183
<Caption13Up style={styles.label} color="secondary">
183184
{t('tags')}
184185
</Caption13Up>
@@ -209,7 +210,7 @@ const ReceiveDetails = ({
209210
<Image style={styles.image} source={imageSrc} />
210211
</View>
211212
)}
212-
</AnimatedView>
213+
</Animated.View>
213214
)}
214215

215216
<View style={styles.buttonContainer}>

0 commit comments

Comments
 (0)