Skip to content

Commit 6ba8bc9

Browse files
feat: update Servers history and Servers List layout (#6733)
1 parent c0a5975 commit 6ba8bc9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+4221
-278
lines changed

.maestro/tests/assorted/changeserver.yaml

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ tags:
3232
visible:
3333
id: 'rooms-list-header-server-add'
3434
timeout: 60000
35-
- extendedWaitUntil:
36-
visible:
37-
id: 'rooms-list-header-create-workspace-button'
38-
timeout: 60000
3935

4036
# should login to server, add new server, close the app, open the app and show previous logged server
4137
- tapOn:
@@ -53,6 +49,8 @@ tags:
5349
id: 'workspace-view'
5450
timeout: 60000
5551
- launchApp
52+
- waitForAnimationToEnd:
53+
timeout: 500
5654
- extendedWaitUntil:
5755
visible:
5856
id: 'rooms-list-view'
@@ -73,6 +71,8 @@ tags:
7371
visible:
7472
id: 'server-item-${output.data.alternateServer}'
7573
timeout: 60000
74+
- waitForAnimationToEnd:
75+
timeout: 5000
7676
- tapOn:
7777
id: 'server-item-${output.data.alternateServer}'
7878
- extendedWaitUntil:
@@ -111,6 +111,8 @@ tags:
111111
visible:
112112
id: 'rooms-list-header-servers-list-button'
113113
timeout: 60000
114+
- waitForAnimationToEnd:
115+
timeout: 5000
114116
- tapOn:
115117
id: 'rooms-list-header-servers-list-button'
116118
- extendedWaitUntil:
@@ -123,6 +125,8 @@ tags:
123125
timeout: 60000
124126
- tapOn:
125127
id: 'server-item-${output.data.server}'
128+
- waitForAnimationToEnd:
129+
timeout: 500
126130
- extendedWaitUntil:
127131
visible:
128132
id: 'rooms-list-view'
@@ -138,6 +142,8 @@ tags:
138142

139143
# should reopen the app and show main server
140144
- launchApp
145+
- waitForAnimationToEnd:
146+
timeout: 500
141147
- extendedWaitUntil:
142148
visible:
143149
id: 'rooms-list-view'
@@ -146,3 +152,51 @@ tags:
146152
file: './utils/check-server.yaml'
147153
env:
148154
server: ${output.data.server}
155+
156+
# should test swipe to delete on alternate server
157+
- extendedWaitUntil:
158+
visible:
159+
id: 'rooms-list-header-servers-list-button'
160+
timeout: 60000
161+
- tapOn:
162+
id: 'rooms-list-header-servers-list-button'
163+
- extendedWaitUntil:
164+
visible:
165+
id: 'server-item-${output.data.alternateServer}'
166+
timeout: 60000
167+
168+
# swipe left to reveal delete button
169+
- swipe:
170+
direction: LEFT
171+
from:
172+
id: 'server-item-${output.data.alternateServer}'
173+
174+
# tap delete button
175+
- tapOn:
176+
id: 'server-item-${output.data.alternateServer}-delete'
177+
178+
# confirm deletion
179+
- extendedWaitUntil:
180+
visible:
181+
text: '.*Delete.*'
182+
timeout: 60000
183+
- tapOn:
184+
text: 'Delete'
185+
186+
# verify alternate server is deleted
187+
- waitForAnimationToEnd:
188+
timeout: 500
189+
- extendedWaitUntil:
190+
visible:
191+
id: 'rooms-list-header-servers-list-button'
192+
timeout: 60000
193+
- tapOn:
194+
id: 'rooms-list-header-servers-list-button'
195+
- extendedWaitUntil:
196+
notVisible:
197+
id: 'server-item-${output.data.alternateServer}'
198+
timeout: 60000
199+
200+
# verify main server still exists
201+
- assertVisible:
202+
id: 'server-item-${output.data.server}'

.maestro/tests/assorted/delete-server.yaml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,26 @@ tags:
7777
visible:
7878
id: 'server-item-${output.data.server}'
7979
timeout: 60000
80-
- longPressOn:
81-
id: 'server-item-${output.data.server}'
80+
81+
# swipe left to reveal delete button
82+
- swipe:
83+
direction: LEFT
84+
from:
85+
id: 'server-item-${output.data.server}'
86+
87+
# tap delete button
88+
- tapOn:
89+
id: 'server-item-${output.data.server}-delete'
90+
91+
# confirm deletion
8292
- extendedWaitUntil:
8393
visible:
8494
text: '.*Delete.*'
8595
timeout: 60000
8696
- tapOn:
8797
text: 'Delete'
98+
- waitForAnimationToEnd:
99+
timeout: 300
88100
- extendedWaitUntil:
89101
visible:
90102
id: 'rooms-list-header-servers-list-button'

.maestro/tests/onboarding/server-history.yaml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ tags:
2626
id: 'servers-history-https://mobile.rocket.chat'
2727

2828
# should tap on a server history and navigate to login
29-
- tapOn: 'Connect to https://mobile.rocket.chat as ${output.user.username}'
29+
- tapOn:
30+
id: 'servers-history-https://mobile.rocket.chat'
3031
- assertVisible:
3132
id: 'login-view-submit'
3233
- assertVisible: ${output.user.username}
@@ -42,10 +43,17 @@ tags:
4243
- tapOn:
4344
id: 'servers-history-button'
4445
- assertVisible:
45-
id: 'servers-history-delete-https://mobile.rocket.chat'
46-
- tapOn:
47-
id: 'servers-history-delete-https://mobile.rocket.chat'
46+
id: 'servers-history-https://mobile.rocket.chat'
4847

48+
# swipe left to reveal delete button and delete the server history
49+
- swipe:
50+
direction: LEFT
51+
from:
52+
id: 'servers-history-https://mobile.rocket.chat'
53+
- waitForAnimationToEnd:
54+
timeout: 500
55+
- tapOn:
56+
id: 'servers-history-https://mobile.rocket.chat-delete'
4957
- extendedWaitUntil:
5058
notVisible:
5159
id: 'servers-history-button'

app/containers/ServerItem/ServerItem.stories.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,21 @@ const ServerItem = ({
1818
item,
1919
theme = 'light',
2020
onPress = () => alert('Press'),
21-
onLongPress,
21+
onDeletePress,
2222
hasCheck
2323
}: {
2424
item?: Partial<IServerItem['item']>;
2525
theme?: TSupportedThemes;
2626
onPress?: IServerItem['onPress'];
27-
onLongPress?: IServerItem['onLongPress'];
27+
onDeletePress?: IServerItem['onDeletePress'];
2828
hasCheck?: IServerItem['hasCheck'];
2929
}) => (
3030
<ThemeContext.Provider
3131
value={{
3232
theme,
3333
colors: themes[theme]
3434
}}>
35-
<ServerItemComponent item={{ ...defaultItem, ...item }} onPress={onPress} onLongPress={onLongPress} hasCheck={hasCheck} />
35+
<ServerItemComponent item={{ ...defaultItem, ...item }} onPress={onPress} onDeletePress={onDeletePress} hasCheck={hasCheck} />
3636
</ThemeContext.Provider>
3737
);
3838

@@ -53,9 +53,10 @@ export const Content = () => (
5353
</>
5454
);
5555

56-
export const Touchable = () => (
56+
export const SwipeActions = () => (
5757
<>
58-
<ServerItem onLongPress={() => alert('Long Press')} />
58+
<ServerItem onDeletePress={() => alert('Delete Server')} />
59+
<ServerItem item={{ name: 'Another Server', id: 'https://example.com/' }} onDeletePress={() => alert('Delete Server')} />
5960
</>
6061
);
6162

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import React from 'react';
2+
import { View, StyleSheet } from 'react-native';
3+
import Animated, {
4+
useAnimatedStyle,
5+
interpolate,
6+
withSpring,
7+
runOnJS,
8+
useAnimatedReaction,
9+
useSharedValue,
10+
type SharedValue
11+
} from 'react-native-reanimated';
12+
import { RectButton } from 'react-native-gesture-handler';
13+
import * as Haptics from 'expo-haptics';
14+
15+
import { CustomIcon } from '../../CustomIcon';
16+
import { useTheme } from '../../../theme';
17+
import I18n from '../../../i18n';
18+
19+
export interface IDeleteActionProps {
20+
transX: SharedValue<number>;
21+
width: number;
22+
rowHeight: number;
23+
actionWidth: number;
24+
longSwipe: number;
25+
onDeletePress(): void;
26+
testID?: string;
27+
}
28+
29+
const SERVER_ITEM_PADDING_VERTICAL = 12;
30+
31+
export const DeleteAction = React.memo(
32+
({ transX, width, rowHeight, actionWidth, longSwipe, onDeletePress, testID }: IDeleteActionProps) => {
33+
const { colors } = useTheme();
34+
35+
const translateXDelete = useSharedValue(0);
36+
37+
const triggerDeleteAnimation = (toValue: number) => {
38+
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
39+
translateXDelete.value = withSpring(toValue, { overshootClamping: true, mass: 0.7 });
40+
};
41+
42+
useAnimatedReaction(
43+
() => transX.value,
44+
(currentTransX, previousTransX) => {
45+
if (I18n.isRTL) {
46+
if (previousTransX && currentTransX > longSwipe && previousTransX <= longSwipe) {
47+
runOnJS(triggerDeleteAnimation)(actionWidth);
48+
} else if (previousTransX && currentTransX <= longSwipe && previousTransX > longSwipe) {
49+
runOnJS(triggerDeleteAnimation)(0);
50+
}
51+
} else if (previousTransX && currentTransX < -longSwipe && previousTransX >= -longSwipe) {
52+
runOnJS(triggerDeleteAnimation)(-actionWidth);
53+
} else if (previousTransX && currentTransX >= -longSwipe && previousTransX < -longSwipe) {
54+
runOnJS(triggerDeleteAnimation)(0);
55+
}
56+
}
57+
);
58+
59+
const animatedDeleteButtonStyles = useAnimatedStyle(() => {
60+
if (I18n.isRTL) {
61+
// RTL: delete button appears from the left when swiping right
62+
if (transX.value > longSwipe && transX.value >= 2 * actionWidth) {
63+
const parallaxSwipe = interpolate(
64+
transX.value,
65+
[2 * actionWidth, longSwipe],
66+
[-actionWidth, -actionWidth - 0.1 * transX.value]
67+
);
68+
return {
69+
transform: [{ translateX: parallaxSwipe - translateXDelete.value }],
70+
left: 0,
71+
right: undefined
72+
};
73+
}
74+
return {
75+
transform: [{ translateX: transX.value - actionWidth - translateXDelete.value }],
76+
left: 0,
77+
right: undefined
78+
};
79+
}
80+
// LTR: delete button appears from the right when swiping left
81+
if (transX.value < -longSwipe && transX.value <= -2 * actionWidth) {
82+
const parallaxSwipe = interpolate(
83+
transX.value,
84+
[-2 * actionWidth, -longSwipe],
85+
[actionWidth, actionWidth + 0.1 * transX.value]
86+
);
87+
return {
88+
transform: [{ translateX: parallaxSwipe + translateXDelete.value }],
89+
right: 0,
90+
left: undefined
91+
};
92+
}
93+
return {
94+
transform: [{ translateX: transX.value + actionWidth + translateXDelete.value }],
95+
right: 0,
96+
left: undefined
97+
};
98+
});
99+
const viewHeight = { height: rowHeight + SERVER_ITEM_PADDING_VERTICAL };
100+
101+
return (
102+
<View
103+
style={[styles.actionsLeftContainer, viewHeight, { backgroundColor: colors.buttonBackgroundDangerDefault }]}
104+
pointerEvents='box-none'>
105+
<Animated.View
106+
style={[
107+
styles.actionRightButtonContainer,
108+
{
109+
width
110+
},
111+
viewHeight,
112+
animatedDeleteButtonStyles
113+
]}>
114+
<RectButton
115+
accessible
116+
accessibilityLabel={I18n.t('Delete')}
117+
testID={testID}
118+
style={[styles.actionButton, { backgroundColor: colors.buttonBackgroundDangerDefault }]}
119+
onPress={onDeletePress}>
120+
<CustomIcon size={24} name='delete' color={colors.fontWhite} />
121+
</RectButton>
122+
</Animated.View>
123+
</View>
124+
);
125+
}
126+
);
127+
128+
const styles = StyleSheet.create({
129+
actionsLeftContainer: {
130+
flexDirection: 'row',
131+
position: 'absolute',
132+
left: 0,
133+
right: 0
134+
},
135+
actionRightButtonContainer: {
136+
position: 'absolute',
137+
justifyContent: 'center',
138+
top: 0,
139+
alignItems: 'flex-end'
140+
},
141+
actionButton: {
142+
width: 80,
143+
height: '100%',
144+
alignItems: 'center',
145+
justifyContent: 'center'
146+
}
147+
});

0 commit comments

Comments
 (0)