mirror of
https://github.com/BlueWallet/BlueWallet.git
synced 2025-02-23 23:27:26 +01:00
Merge pull request #7465 from BlueWallet/mana
REF: Manage Wallet to a different better package
This commit is contained in:
commit
5e1b8b1c4e
6 changed files with 98 additions and 110 deletions
|
@ -6,6 +6,7 @@ import { WalletCarouselItem } from './WalletsCarousel';
|
|||
import { TransactionListItem } from './TransactionListItem';
|
||||
import { useTheme } from './themes';
|
||||
import { BitcoinUnit } from '../models/bitcoinUnits';
|
||||
import { TouchableOpacityWrapper } from './ListItem';
|
||||
|
||||
enum ItemType {
|
||||
WalletSection = 'wallet',
|
||||
|
@ -29,11 +30,14 @@ interface ManageWalletsListItemProps {
|
|||
isDraggingDisabled: boolean;
|
||||
drag?: () => void;
|
||||
isPlaceHolder?: boolean;
|
||||
onPressIn?: () => void;
|
||||
onPressOut?: () => void;
|
||||
state: { wallets: TWallet[]; searchQuery: string };
|
||||
navigateToWallet: (wallet: TWallet) => void;
|
||||
renderHighlightedText: (text: string, query: string) => JSX.Element;
|
||||
handleDeleteWallet: (wallet: TWallet) => void;
|
||||
handleToggleHideBalance: (wallet: TWallet) => void;
|
||||
isActive?: boolean;
|
||||
}
|
||||
|
||||
interface SwipeContentProps {
|
||||
|
@ -67,6 +71,9 @@ const ManageWalletsListItem: React.FC<ManageWalletsListItemProps> = ({
|
|||
renderHighlightedText,
|
||||
handleDeleteWallet,
|
||||
handleToggleHideBalance,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
isActive,
|
||||
}) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
|
@ -110,6 +117,10 @@ const ManageWalletsListItem: React.FC<ManageWalletsListItemProps> = ({
|
|||
containerStyle={{ backgroundColor: colors.background }}
|
||||
leftContent={leftContent}
|
||||
rightContent={rightContent}
|
||||
Component={TouchableOpacityWrapper}
|
||||
onPressOut={onPressOut}
|
||||
onPressIn={onPressIn}
|
||||
style={isActive ? styles.activeItem : undefined}
|
||||
>
|
||||
<ListItem.Content
|
||||
style={{
|
||||
|
@ -121,6 +132,8 @@ const ManageWalletsListItem: React.FC<ManageWalletsListItemProps> = ({
|
|||
item={item.data}
|
||||
handleLongPress={isDraggingDisabled ? undefined : drag}
|
||||
onPress={onPress}
|
||||
onPressIn={onPressIn}
|
||||
onPressOut={onPressOut}
|
||||
animationsEnabled={false}
|
||||
searchQuery={state.searchQuery}
|
||||
isPlaceHolder={isPlaceHolder}
|
||||
|
@ -164,6 +177,9 @@ const styles = StyleSheet.create({
|
|||
alignItems: 'center',
|
||||
backgroundColor: 'red',
|
||||
},
|
||||
activeItem: {
|
||||
backgroundColor: 'rgba(0, 0, 0, 0.1)',
|
||||
},
|
||||
});
|
||||
|
||||
export { ManageWalletsListItem, LeftSwipeContent, RightSwipeContent };
|
||||
|
|
|
@ -172,6 +172,8 @@ interface WalletCarouselItemProps {
|
|||
searchQuery?: string;
|
||||
renderHighlightedText?: (text: string, query: string) => JSX.Element;
|
||||
animationsEnabled?: boolean;
|
||||
onPressIn?: () => void;
|
||||
onPressOut?: () => void;
|
||||
}
|
||||
|
||||
export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
||||
|
@ -186,6 +188,8 @@ export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
|||
renderHighlightedText,
|
||||
animationsEnabled = true,
|
||||
isPlaceHolder = false,
|
||||
onPressIn,
|
||||
onPressOut,
|
||||
}) => {
|
||||
const scaleValue = useRef(new Animated.Value(1.0)).current;
|
||||
const { colors } = useTheme();
|
||||
|
@ -203,7 +207,8 @@ export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
|||
tension: 100,
|
||||
}).start();
|
||||
}
|
||||
}, [scaleValue, animationsEnabled]);
|
||||
if (onPressIn) onPressIn();
|
||||
}, [scaleValue, animationsEnabled, onPressIn]);
|
||||
|
||||
const onPressedOut = useCallback(() => {
|
||||
if (animationsEnabled) {
|
||||
|
@ -214,7 +219,8 @@ export const WalletCarouselItem: React.FC<WalletCarouselItemProps> = React.memo(
|
|||
tension: 100,
|
||||
}).start();
|
||||
}
|
||||
}, [scaleValue, animationsEnabled]);
|
||||
if (onPressOut) onPressOut();
|
||||
}, [scaleValue, animationsEnabled, onPressOut]);
|
||||
|
||||
const handlePress = useCallback(() => {
|
||||
onPressedOut();
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
B4D0B2682C1DED67006B6B1B /* ReceiveMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4D0B2672C1DED67006B6B1B /* ReceiveMethod.swift */; };
|
||||
B4EE583C226703320003363C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B40D4E35225841ED00428FCC /* Assets.xcassets */; };
|
||||
B4EFF73B2C3F6C5E0095D655 /* MockData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4EFF73A2C3F6C5E0095D655 /* MockData.swift */; };
|
||||
C978A716948AB7DEC5B6F677 /* (null) in Frameworks */ = {isa = PBXBuildFile; };
|
||||
C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */ = {isa = PBXBuildFile; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -427,7 +427,7 @@
|
|||
files = (
|
||||
782F075B5DD048449E2DECE9 /* libz.tbd in Frameworks */,
|
||||
764B49B1420D4AEB8109BF62 /* libsqlite3.0.tbd in Frameworks */,
|
||||
C978A716948AB7DEC5B6F677 /* (null) in Frameworks */,
|
||||
C978A716948AB7DEC5B6F677 /* BuildFile in Frameworks */,
|
||||
17CDA0718F42DB2CE856C872 /* libPods-BlueWallet.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
16
package-lock.json
generated
16
package-lock.json
generated
|
@ -68,7 +68,7 @@
|
|||
"react-native-default-preference": "https://github.com/BlueWallet/react-native-default-preference.git#6338a1f1235e4130b8cfc2dd3b53015eeff2870c",
|
||||
"react-native-device-info": "13.2.0",
|
||||
"react-native-document-picker": "9.3.1",
|
||||
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#3a61627",
|
||||
"react-native-draglist": "github:BlueWallet/react-native-draglist#a4af02f",
|
||||
"react-native-fs": "2.20.0",
|
||||
"react-native-gesture-handler": "2.21.2",
|
||||
"react-native-handoff": "github:BlueWallet/react-native-handoff#v0.0.4",
|
||||
|
@ -20615,17 +20615,13 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-draggable-flatlist": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "git+ssh://git@github.com/BlueWallet/react-native-draggable-flatlist.git#3a61627474a4e35198ae961310c77fb305507509",
|
||||
"node_modules/react-native-draglist": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "git+ssh://git@github.com/BlueWallet/react-native-draglist.git#a4af02fec803b75508a8136e35eca564bbb1d644",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/preset-typescript": "^7.17.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react-native": ">=0.64.0",
|
||||
"react-native-gesture-handler": ">=2.0.0",
|
||||
"react-native-reanimated": ">=2.8.0"
|
||||
"react": ">=17.0.1",
|
||||
"react-native": ">=0.64.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-fs": {
|
||||
|
|
|
@ -132,7 +132,7 @@
|
|||
"react-native-default-preference": "https://github.com/BlueWallet/react-native-default-preference.git#6338a1f1235e4130b8cfc2dd3b53015eeff2870c",
|
||||
"react-native-device-info": "13.2.0",
|
||||
"react-native-document-picker": "9.3.1",
|
||||
"react-native-draggable-flatlist": "github:BlueWallet/react-native-draggable-flatlist#3a61627",
|
||||
"react-native-draglist": "github:BlueWallet/react-native-draglist#a4af02f",
|
||||
"react-native-fs": "2.20.0",
|
||||
"react-native-gesture-handler": "2.21.2",
|
||||
"react-native-handoff": "github:BlueWallet/react-native-handoff#v0.0.4",
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
import React, { useEffect, useLayoutEffect, useReducer, useCallback, useMemo, useRef } from 'react';
|
||||
import { StyleSheet, TouchableOpacity, Image, Text, Alert, I18nManager, Animated, LayoutAnimation } from 'react-native';
|
||||
import {
|
||||
NestableScrollContainer,
|
||||
ScaleDecorator,
|
||||
OpacityDecorator,
|
||||
NestableDraggableFlatList,
|
||||
RenderItem,
|
||||
// @ts-expect-error: react-native-draggable-flatlist is not typed
|
||||
} from 'react-native-draggable-flatlist';
|
||||
import React, { useEffect, useLayoutEffect, useReducer, useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { StyleSheet, TouchableOpacity, Image, Text, Alert, I18nManager, Animated, LayoutAnimation, FlatList } from 'react-native';
|
||||
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
||||
import { useFocusEffect, useNavigation } from '@react-navigation/native';
|
||||
import triggerHapticFeedback, { HapticFeedbackTypes } from '../../blue_modules/hapticFeedback';
|
||||
|
@ -25,6 +17,7 @@ import prompt from '../../helpers/prompt';
|
|||
import HeaderRightButton from '../../components/HeaderRightButton';
|
||||
import { ManageWalletsListItem } from '../../components/ManageWalletsListItem';
|
||||
import { useSettings } from '../../hooks/context/useSettings';
|
||||
import DragList, { DragListRenderItemInfo } from 'react-native-draglist';
|
||||
|
||||
enum ItemType {
|
||||
WalletSection = 'wallet',
|
||||
|
@ -206,21 +199,24 @@ const ManageWallets: React.FC = () => {
|
|||
color: colors.foregroundColor,
|
||||
},
|
||||
};
|
||||
const [data, setData] = useState(state.tempOrder);
|
||||
const listRef = useRef<FlatList<Item> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({
|
||||
type: SET_INITIAL_ORDER,
|
||||
payload: { wallets: walletsRef.current, txMetadata },
|
||||
});
|
||||
setData(state.tempOrder);
|
||||
}, [state.tempOrder]);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch({ type: SET_INITIAL_ORDER, payload: { wallets: walletsRef.current, txMetadata } });
|
||||
}, [txMetadata]);
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearchQuery) {
|
||||
dispatch({ type: SET_FILTERED_ORDER, payload: debouncedSearchQuery });
|
||||
} else {
|
||||
dispatch({ type: SET_INITIAL_ORDER, payload: { wallets: walletsRef.current, txMetadata } });
|
||||
dispatch({ type: SET_TEMP_ORDER, payload: state.order });
|
||||
}
|
||||
}, [debouncedSearchQuery, txMetadata]);
|
||||
}, [debouncedSearchQuery, state.order]);
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
if (state.searchQuery.length === 0 && !state.isSearchFocused) {
|
||||
|
@ -244,6 +240,7 @@ const ManageWallets: React.FC = () => {
|
|||
dispatch({ type: SET_IS_SEARCH_FOCUSED, payload: false });
|
||||
}
|
||||
}, [goBack, setWalletsWithNewOrder, state.searchQuery, state.isSearchFocused, state.tempOrder, navigation]);
|
||||
|
||||
const hasUnsavedChanges = useMemo(() => {
|
||||
return JSON.stringify(walletsRef.current) !== JSON.stringify(state.tempOrder.map(item => item.data));
|
||||
}, [state.tempOrder]);
|
||||
|
@ -319,6 +316,14 @@ const ManageWallets: React.FC = () => {
|
|||
}, [hasUnsavedChanges, navigation, setIsDrawerShouldHide]),
|
||||
);
|
||||
|
||||
// Ensure the listener is re-added every time there are unsaved changes
|
||||
useEffect(() => {
|
||||
if (beforeRemoveListenerRef.current) {
|
||||
navigation.removeListener('beforeRemove', beforeRemoveListenerRef.current);
|
||||
navigation.addListener('beforeRemove', beforeRemoveListenerRef.current);
|
||||
}
|
||||
}, [hasUnsavedChanges, navigation]);
|
||||
|
||||
const renderHighlightedText = useCallback(
|
||||
(text: string, query: string) => {
|
||||
const parts = text.split(new RegExp(`(${query})`, 'gi'));
|
||||
|
@ -425,60 +430,43 @@ const ManageWallets: React.FC = () => {
|
|||
},
|
||||
[goBack, navigate],
|
||||
);
|
||||
const renderWalletItem = useCallback(
|
||||
({ item, drag, isActive }: RenderItem<Item>) => (
|
||||
<ScaleDecorator drag={drag} activeScale={1.1}>
|
||||
<OpacityDecorator activeOpacity={0.5}>
|
||||
<ManageWalletsListItem
|
||||
item={item}
|
||||
isDraggingDisabled={state.searchQuery.length > 0 || state.isSearchFocused}
|
||||
drag={drag}
|
||||
state={state}
|
||||
navigateToWallet={navigateToWallet}
|
||||
renderHighlightedText={renderHighlightedText}
|
||||
handleDeleteWallet={handleDeleteWallet}
|
||||
handleToggleHideBalance={handleToggleHideBalance}
|
||||
/>
|
||||
</OpacityDecorator>
|
||||
</ScaleDecorator>
|
||||
),
|
||||
const renderItem = useCallback(
|
||||
(info: DragListRenderItemInfo<Item>) => {
|
||||
const { item, onDragStart, onDragEnd, isActive } = info;
|
||||
return (
|
||||
<ManageWalletsListItem
|
||||
item={item}
|
||||
onPressIn={state.isSearchFocused || state.searchQuery.length > 0 ? undefined : onDragStart}
|
||||
onPressOut={state.isSearchFocused || state.searchQuery.length > 0 ? undefined : onDragEnd}
|
||||
isDraggingDisabled={state.searchQuery.length > 0 || state.isSearchFocused}
|
||||
state={state}
|
||||
navigateToWallet={navigateToWallet}
|
||||
renderHighlightedText={renderHighlightedText}
|
||||
handleDeleteWallet={handleDeleteWallet}
|
||||
handleToggleHideBalance={handleToggleHideBalance}
|
||||
isActive={isActive}
|
||||
drag={state.isSearchFocused || state.searchQuery.length > 0 ? undefined : onDragStart}
|
||||
/>
|
||||
);
|
||||
},
|
||||
[state, navigateToWallet, renderHighlightedText, handleDeleteWallet, handleToggleHideBalance],
|
||||
);
|
||||
|
||||
const renderPlaceholder = useCallback(
|
||||
({ item, drag, isActive }: RenderItem<Item>) => (
|
||||
<ManageWalletsListItem
|
||||
item={item}
|
||||
isDraggingDisabled={state.searchQuery.length > 0 || state.isSearchFocused}
|
||||
state={state}
|
||||
navigateToWallet={navigateToWallet}
|
||||
renderHighlightedText={renderHighlightedText}
|
||||
isPlaceHolder
|
||||
handleDeleteWallet={handleDeleteWallet}
|
||||
handleToggleHideBalance={handleToggleHideBalance}
|
||||
/>
|
||||
),
|
||||
[handleDeleteWallet, handleToggleHideBalance, navigateToWallet, renderHighlightedText, state],
|
||||
);
|
||||
|
||||
const onChangeOrder = useCallback(() => {
|
||||
triggerHapticFeedback(HapticFeedbackTypes.ImpactMedium);
|
||||
}, []);
|
||||
|
||||
const onDragBegin = useCallback(() => {
|
||||
triggerHapticFeedback(HapticFeedbackTypes.Selection);
|
||||
}, []);
|
||||
|
||||
const onRelease = useCallback(() => {
|
||||
triggerHapticFeedback(HapticFeedbackTypes.ImpactLight);
|
||||
}, []);
|
||||
const onDragEnd = useCallback(
|
||||
({ data }: { data: Item[] }) => {
|
||||
const updatedWallets = data.filter((item): item is WalletItem => item.type === ItemType.WalletSection).map(item => item.data);
|
||||
|
||||
dispatch({ type: SET_INITIAL_ORDER, payload: { wallets: updatedWallets, txMetadata: state.txMetadata } });
|
||||
const onReordered = useCallback(
|
||||
(fromIndex: number, toIndex: number) => {
|
||||
const copy = [...state.order];
|
||||
const removed = copy.splice(fromIndex, 1);
|
||||
copy.splice(toIndex, 0, removed[0]);
|
||||
dispatch({ type: SET_TEMP_ORDER, payload: copy });
|
||||
dispatch({
|
||||
type: SET_INITIAL_ORDER,
|
||||
payload: {
|
||||
wallets: copy.filter(item => item.type === ItemType.WalletSection).map(item => item.data as TWallet),
|
||||
txMetadata: state.txMetadata,
|
||||
},
|
||||
});
|
||||
},
|
||||
[state.txMetadata],
|
||||
[state.order, state.txMetadata],
|
||||
);
|
||||
|
||||
const keyExtractor = useCallback((item: Item, index: number) => index.toString(), []);
|
||||
|
@ -499,39 +487,21 @@ const ManageWallets: React.FC = () => {
|
|||
|
||||
return (
|
||||
<GestureHandlerRootView style={[{ backgroundColor: colors.background }, styles.root]}>
|
||||
<NestableScrollContainer contentInsetAdjustmentBehavior="automatic" automaticallyAdjustContentInsets scrollEnabled>
|
||||
<>
|
||||
{renderHeader}
|
||||
<NestableDraggableFlatList
|
||||
data={state.tempOrder.filter((item): item is WalletItem => item.type === ItemType.WalletSection)}
|
||||
extraData={state.tempOrder}
|
||||
keyExtractor={keyExtractor}
|
||||
renderItem={renderWalletItem}
|
||||
onChangeOrder={onChangeOrder}
|
||||
onDragBegin={onDragBegin}
|
||||
onPlaceholderIndexChange={onChangeOrder}
|
||||
onRelease={onRelease}
|
||||
delayLongPress={150}
|
||||
useNativeDriver={true}
|
||||
dragItemOverflow
|
||||
autoscrollThreshold={1}
|
||||
renderPlaceholder={renderPlaceholder}
|
||||
autoscrollSpeed={0.5}
|
||||
contentInsetAdjustmentBehavior="automatic"
|
||||
<DragList
|
||||
automaticallyAdjustContentInsets
|
||||
onDragEnd={onDragEnd}
|
||||
containerStyle={styles.root}
|
||||
/>
|
||||
<NestableDraggableFlatList
|
||||
data={state.tempOrder.filter((item): item is TransactionItem => item.type === ItemType.TransactionSection)}
|
||||
keyExtractor={keyExtractor}
|
||||
renderItem={renderWalletItem}
|
||||
dragItemOverflow
|
||||
containerStyle={styles.root}
|
||||
automaticallyAdjustKeyboardInsets
|
||||
automaticallyAdjustsScrollIndicatorInsets
|
||||
contentInsetAdjustmentBehavior="automatic"
|
||||
automaticallyAdjustContentInsets
|
||||
useNativeDriver={true}
|
||||
data={data}
|
||||
containerStyle={[{ backgroundColor: colors.background }, styles.root]}
|
||||
keyExtractor={keyExtractor}
|
||||
onReordered={onReordered}
|
||||
renderItem={renderItem}
|
||||
ref={listRef}
|
||||
/>
|
||||
</NestableScrollContainer>
|
||||
</>
|
||||
</GestureHandlerRootView>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue