Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
30d2341
feat: new translations
OtavioStasiak Oct 15, 2025
4640d5c
feat: add delete swipe on serveritem
OtavioStasiak Oct 15, 2025
7a498d2
feat: save server icon
OtavioStasiak Oct 15, 2025
9d8a153
feat: add delete swipe and update action sheet content layout on serv…
OtavioStasiak Oct 15, 2025
ffe2aec
chore: update ServerItem storybook
OtavioStasiak Oct 15, 2025
85a9275
chore: serversHistoryItem stories
OtavioStasiak Oct 15, 2025
14cfd01
fix: e2e tests
OtavioStasiak Oct 15, 2025
d688e3f
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Oct 15, 2025
c19d7ff
chore: format code with Prettier [skip ci]
OtavioStasiak Oct 15, 2025
ee14016
fix: remove comment
OtavioStasiak Oct 15, 2025
a0f841e
fix: unit tests
OtavioStasiak Oct 15, 2025
4a4a760
fix: lint
OtavioStasiak Oct 15, 2025
5967cb3
fix: lint
OtavioStasiak Oct 16, 2025
d536b3b
fix: e2e tests
OtavioStasiak Oct 17, 2025
7dc56cf
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Oct 20, 2025
756632e
fix: actionsheet background
OtavioStasiak Oct 20, 2025
aa70160
fix: e2e tests
OtavioStasiak Oct 20, 2025
7093ac9
fix: unit test
OtavioStasiak Oct 20, 2025
b2fcd13
fix: changeserver e2e test
OtavioStasiak Oct 21, 2025
00378ea
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Oct 21, 2025
2420de1
fix: animation behavior on android
OtavioStasiak Oct 21, 2025
ad99286
chore: code improvements
OtavioStasiak Oct 21, 2025
8f49e2a
fix: deleteserver test
OtavioStasiak Oct 21, 2025
b27782a
fix: e2e tests
OtavioStasiak Oct 21, 2025
01fb37d
fix: unit tests
OtavioStasiak Oct 21, 2025
eb799ff
fix: black color token
OtavioStasiak Oct 22, 2025
12781ef
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Nov 5, 2025
1e66e34
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Nov 5, 2025
f0532cd
feat: hint translation
OtavioStasiak Nov 5, 2025
b62a073
cleanup
OtavioStasiak Nov 5, 2025
84e6fbc
action: organized translations
OtavioStasiak Nov 5, 2025
0fc1975
fix: snapshot test
OtavioStasiak Nov 5, 2025
94594ef
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Nov 6, 2025
9192d48
fix: Update app/i18n/locales/te-IN.json
OtavioStasiak Nov 6, 2025
6e6baa3
fix: pt br workspaces translation
OtavioStasiak Nov 6, 2025
4b402fd
fix: translation
OtavioStasiak Nov 6, 2025
27f67cc
chore: code improvements
OtavioStasiak Nov 6, 2025
cc095b6
feat: support rtl
OtavioStasiak Nov 6, 2025
454b1a9
fix: unit tests
OtavioStasiak Nov 6, 2025
ab8a065
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Nov 6, 2025
274a93f
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Nov 25, 2025
b9c3425
fix: useResponsiveLayout instead of Dimensions
OtavioStasiak Nov 25, 2025
42c3f0e
code organization
OtavioStasiak Nov 25, 2025
d5ad71c
chore: conditional swipe
OtavioStasiak Nov 25, 2025
1f53cc9
chore: format code and fix lint issues [skip ci]
OtavioStasiak Nov 25, 2025
7ccc40a
fix: snapshot test
OtavioStasiak Nov 25, 2025
45a78e9
fix: snapshot
OtavioStasiak Nov 25, 2025
266ad94
Merge branch 'develop' into feat.servers-history-actionsheet-layout
OtavioStasiak Nov 25, 2025
e8b5930
fix: snapshot
OtavioStasiak Nov 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 58 additions & 4 deletions .maestro/tests/assorted/changeserver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ tags:
visible:
id: 'rooms-list-header-server-add'
timeout: 60000
- extendedWaitUntil:
visible:
id: 'rooms-list-header-create-workspace-button'
timeout: 60000

# should login to server, add new server, close the app, open the app and show previous logged server
- tapOn:
Expand All @@ -53,6 +49,8 @@ tags:
id: 'workspace-view'
timeout: 60000
- launchApp
- waitForAnimationToEnd:
timeout: 500
- extendedWaitUntil:
visible:
id: 'rooms-list-view'
Expand All @@ -73,6 +71,8 @@ tags:
visible:
id: 'server-item-${output.data.alternateServer}'
timeout: 60000
- waitForAnimationToEnd:
timeout: 5000
- tapOn:
id: 'server-item-${output.data.alternateServer}'
- extendedWaitUntil:
Expand Down Expand Up @@ -111,6 +111,8 @@ tags:
visible:
id: 'rooms-list-header-servers-list-button'
timeout: 60000
- waitForAnimationToEnd:
timeout: 5000
- tapOn:
id: 'rooms-list-header-servers-list-button'
- extendedWaitUntil:
Expand All @@ -123,6 +125,8 @@ tags:
timeout: 60000
- tapOn:
id: 'server-item-${output.data.server}'
- waitForAnimationToEnd:
timeout: 500
- extendedWaitUntil:
visible:
id: 'rooms-list-view'
Expand All @@ -138,6 +142,8 @@ tags:

# should reopen the app and show main server
- launchApp
- waitForAnimationToEnd:
timeout: 500
- extendedWaitUntil:
visible:
id: 'rooms-list-view'
Expand All @@ -146,3 +152,51 @@ tags:
file: './utils/check-server.yaml'
env:
server: ${output.data.server}

# should test swipe to delete on alternate server
- extendedWaitUntil:
visible:
id: 'rooms-list-header-servers-list-button'
timeout: 60000
- tapOn:
id: 'rooms-list-header-servers-list-button'
- extendedWaitUntil:
visible:
id: 'server-item-${output.data.alternateServer}'
timeout: 60000

# swipe left to reveal delete button
- swipe:
direction: LEFT
from:
id: 'server-item-${output.data.alternateServer}'

# tap delete button
- tapOn:
id: 'server-item-${output.data.alternateServer}-delete'

# confirm deletion
- extendedWaitUntil:
visible:
text: '.*Delete.*'
timeout: 60000
- tapOn:
text: 'Delete'

# verify alternate server is deleted
- waitForAnimationToEnd:
timeout: 500
- extendedWaitUntil:
visible:
id: 'rooms-list-header-servers-list-button'
timeout: 60000
- tapOn:
id: 'rooms-list-header-servers-list-button'
- extendedWaitUntil:
notVisible:
id: 'server-item-${output.data.alternateServer}'
timeout: 60000

# verify main server still exists
- assertVisible:
id: 'server-item-${output.data.server}'
16 changes: 14 additions & 2 deletions .maestro/tests/assorted/delete-server.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,26 @@ tags:
visible:
id: 'server-item-${output.data.server}'
timeout: 60000
- longPressOn:
id: 'server-item-${output.data.server}'

# swipe left to reveal delete button
- swipe:
direction: LEFT
from:
id: 'server-item-${output.data.server}'

# tap delete button
- tapOn:
id: 'server-item-${output.data.server}-delete'

# confirm deletion
- extendedWaitUntil:
visible:
text: '.*Delete.*'
timeout: 60000
- tapOn:
text: 'Delete'
- waitForAnimationToEnd:
timeout: 300
- extendedWaitUntil:
visible:
id: 'rooms-list-header-servers-list-button'
Expand Down
16 changes: 12 additions & 4 deletions .maestro/tests/onboarding/server-history.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ tags:
id: 'servers-history-https://mobile.rocket.chat'

# should tap on a server history and navigate to login
- tapOn: 'Connect to https://mobile.rocket.chat as ${output.user.username}'
- tapOn:
id: 'servers-history-https://mobile.rocket.chat'
- assertVisible:
id: 'login-view-submit'
- assertVisible: ${output.user.username}
Expand All @@ -42,10 +43,17 @@ tags:
- tapOn:
id: 'servers-history-button'
- assertVisible:
id: 'servers-history-delete-https://mobile.rocket.chat'
- tapOn:
id: 'servers-history-delete-https://mobile.rocket.chat'
id: 'servers-history-https://mobile.rocket.chat'

# swipe left to reveal delete button and delete the server history
- swipe:
direction: LEFT
from:
id: 'servers-history-https://mobile.rocket.chat'
- waitForAnimationToEnd:
timeout: 500
- tapOn:
id: 'servers-history-https://mobile.rocket.chat-delete'
- extendedWaitUntil:
notVisible:
id: 'servers-history-button'
Expand Down
11 changes: 6 additions & 5 deletions app/containers/ServerItem/ServerItem.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@ const ServerItem = ({
item,
theme = 'light',
onPress = () => alert('Press'),
onLongPress,
onDeletePress,
hasCheck
}: {
item?: Partial<IServerItem['item']>;
theme?: TSupportedThemes;
onPress?: IServerItem['onPress'];
onLongPress?: IServerItem['onLongPress'];
onDeletePress?: IServerItem['onDeletePress'];
hasCheck?: IServerItem['hasCheck'];
}) => (
<ThemeContext.Provider
value={{
theme,
colors: themes[theme]
}}>
<ServerItemComponent item={{ ...defaultItem, ...item }} onPress={onPress} onLongPress={onLongPress} hasCheck={hasCheck} />
<ServerItemComponent item={{ ...defaultItem, ...item }} onPress={onPress} onDeletePress={onDeletePress} hasCheck={hasCheck} />
</ThemeContext.Provider>
);

Expand All @@ -53,9 +53,10 @@ export const Content = () => (
</>
);

export const Touchable = () => (
export const SwipeActions = () => (
<>
<ServerItem onLongPress={() => alert('Long Press')} />
<ServerItem onDeletePress={() => alert('Delete Server')} />
<ServerItem item={{ name: 'Another Server', id: 'https://example.com/' }} onDeletePress={() => alert('Delete Server')} />
</>
);

Expand Down
147 changes: 147 additions & 0 deletions app/containers/ServerItem/SwipeableDeleteItem/Actions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import Animated, {
useAnimatedStyle,
interpolate,
withSpring,
runOnJS,
useAnimatedReaction,
useSharedValue,
type SharedValue
} from 'react-native-reanimated';
import { RectButton } from 'react-native-gesture-handler';
import * as Haptics from 'expo-haptics';

import { CustomIcon } from '../../CustomIcon';
import { useTheme } from '../../../theme';
import I18n from '../../../i18n';

export interface IDeleteActionProps {
transX: SharedValue<number>;
width: number;
rowHeight: number;
actionWidth: number;
longSwipe: number;
onDeletePress(): void;
testID?: string;
}

const SERVER_ITEM_PADDING_VERTICAL = 12;

export const DeleteAction = React.memo(
({ transX, width, rowHeight, actionWidth, longSwipe, onDeletePress, testID }: IDeleteActionProps) => {
const { colors } = useTheme();

const translateXDelete = useSharedValue(0);

const triggerDeleteAnimation = (toValue: number) => {
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
translateXDelete.value = withSpring(toValue, { overshootClamping: true, mass: 0.7 });
};

useAnimatedReaction(
() => transX.value,
(currentTransX, previousTransX) => {
if (I18n.isRTL) {
if (previousTransX && currentTransX > longSwipe && previousTransX <= longSwipe) {
runOnJS(triggerDeleteAnimation)(actionWidth);
} else if (previousTransX && currentTransX <= longSwipe && previousTransX > longSwipe) {
runOnJS(triggerDeleteAnimation)(0);
}
} else if (previousTransX && currentTransX < -longSwipe && previousTransX >= -longSwipe) {
runOnJS(triggerDeleteAnimation)(-actionWidth);
} else if (previousTransX && currentTransX >= -longSwipe && previousTransX < -longSwipe) {
runOnJS(triggerDeleteAnimation)(0);
}
}
);

const animatedDeleteButtonStyles = useAnimatedStyle(() => {
if (I18n.isRTL) {
// RTL: delete button appears from the left when swiping right
if (transX.value > longSwipe && transX.value >= 2 * actionWidth) {
const parallaxSwipe = interpolate(
transX.value,
[2 * actionWidth, longSwipe],
[-actionWidth, -actionWidth - 0.1 * transX.value]
);
return {
transform: [{ translateX: parallaxSwipe - translateXDelete.value }],
left: 0,
right: undefined
};
}
return {
transform: [{ translateX: transX.value - actionWidth - translateXDelete.value }],
left: 0,
right: undefined
};
}
// LTR: delete button appears from the right when swiping left
if (transX.value < -longSwipe && transX.value <= -2 * actionWidth) {
const parallaxSwipe = interpolate(
transX.value,
[-2 * actionWidth, -longSwipe],
[actionWidth, actionWidth + 0.1 * transX.value]
);
return {
transform: [{ translateX: parallaxSwipe + translateXDelete.value }],
right: 0,
left: undefined
};
}
return {
transform: [{ translateX: transX.value + actionWidth + translateXDelete.value }],
right: 0,
left: undefined
};
});
const viewHeight = { height: rowHeight + SERVER_ITEM_PADDING_VERTICAL };

return (
<View
style={[styles.actionsLeftContainer, viewHeight, { backgroundColor: colors.buttonBackgroundDangerDefault }]}
pointerEvents='box-none'>
<Animated.View
style={[
styles.actionRightButtonContainer,
{
width
},
viewHeight,
animatedDeleteButtonStyles
]}>
<RectButton
accessible
accessibilityLabel={I18n.t('Delete')}
testID={testID}
style={[styles.actionButton, { backgroundColor: colors.buttonBackgroundDangerDefault }]}
onPress={onDeletePress}>
<CustomIcon size={24} name='delete' color={colors.fontWhite} />
</RectButton>
</Animated.View>
</View>
);
}
);

const styles = StyleSheet.create({
actionsLeftContainer: {
flexDirection: 'row',
position: 'absolute',
left: 0,
right: 0
},
actionRightButtonContainer: {
position: 'absolute',
justifyContent: 'center',
top: 0,
alignItems: 'flex-end'
},
actionButton: {
width: 80,
height: '100%',
alignItems: 'center',
justifyContent: 'center'
}
});
Loading
Loading