Merge branch 'master' into sortbyw

This commit is contained in:
Marcos Rodriguez Velez 2024-11-15 22:31:35 -04:00
commit 055cde127e
6 changed files with 38 additions and 191 deletions

View File

@ -54,13 +54,7 @@ const ToolTipMenu = React.memo((props: ToolTipMenuProps, ref?: Ref<any>) => {
subtitle: subaction.subtitle,
image: subaction.icon?.iconValue ? subaction.icon.iconValue : undefined,
state: subaction.menuState === undefined ? undefined : ((subaction.menuState ? 'on' : 'off') as MenuState),
attributes: {
disabled: subaction.disabled,
destructive: subaction.destructive,
hidden: subaction.hidden,
},
subactions: subaction.subactions ? subaction.subactions.map(mapMenuItemForMenuView).filter(Boolean) : undefined,
displayInline: subaction.displayInline || false,
attributes: { disabled: subaction.disabled, destructive: subaction.destructive, hidden: subaction.hidden },
})) || [];
return {
@ -69,12 +63,8 @@ const ToolTipMenu = React.memo((props: ToolTipMenuProps, ref?: Ref<any>) => {
subtitle: action.subtitle,
image: action.icon?.iconValue ? action.icon.iconValue : undefined,
state: action.menuState === undefined ? undefined : ((action.menuState ? 'on' : 'off') as MenuState),
attributes: {
disabled: action.disabled,
destructive: action.destructive,
hidden: action.hidden,
},
subactions: subactions.length > 0 ? (subactions.filter(Boolean) as MenuAction[]) : undefined,
attributes: { disabled: action.disabled, destructive: action.destructive, hidden: action.hidden },
subactions: subactions.length > 0 ? subactions : undefined,
displayInline: action.displayInline || false,
};
}, []);
@ -96,7 +86,6 @@ const ToolTipMenu = React.memo((props: ToolTipMenuProps, ref?: Ref<any>) => {
.map(mapMenuItemForMenuView)
.filter(item => item !== null) as MenuAction[],
displayInline: true,
keepsMenuPresented: true,
};
} else if (!Array.isArray(actionGroup) && actionGroup.id) {
return mapMenuItemForMenuView(actionGroup);

View File

@ -1,10 +1,14 @@
import React, { useCallback, useMemo } from 'react';
import { StyleSheet, TouchableOpacity } from 'react-native';
import { Icon } from '@rneui/themed';
import { useTheme } from '../themes';
import { useExtendedNavigation } from '../../hooks/useExtendedNavigation';
import loc from '../../loc';
import ToolTipMenu from '../TooltipMenu';
import { CommonToolTipActions } from '../../typings/CommonToolTipActions';
import MoreOptionsButton from './MoreOptionsButton';
const SettingsButton = () => {
const { colors } = useTheme();
const { navigate } = useExtendedNavigation();
const onPress = () => {
navigate('Settings');
@ -25,14 +29,28 @@ const SettingsButton = () => {
const actions = useMemo(() => [CommonToolTipActions.ManageWallet], []);
return (
<MoreOptionsButton
isMenuPrimaryAction={false}
onPress={onPress}
onPressMenuItem={onPressMenuItem}
actions={actions}
testID="SettingsButton"
/>
<ToolTipMenu onPressMenuItem={onPressMenuItem} actions={actions}>
<TouchableOpacity
accessibilityRole="button"
accessibilityLabel={loc.settings.default_title}
testID="SettingsButton"
style={[style.buttonStyle, { backgroundColor: colors.lightButton }]}
onPress={onPress}
>
<Icon size={22} name="more-horiz" type="material" color={colors.foregroundColor} />
</TouchableOpacity>
</ToolTipMenu>
);
};
export default SettingsButton;
const style = StyleSheet.create({
buttonStyle: {
width: 30,
height: 30,
borderRadius: 15,
justifyContent: 'center',
alignContent: 'center',
},
});

View File

@ -11,12 +11,11 @@ export interface Action {
menuState?: 'mixed' | boolean | undefined;
displayInline?: boolean; // Indicates if subactions should be displayed inline or nested (iOS only)
image?: string;
keepsMenuPresented?: boolean;
imageColor?: ColorValue;
destructive?: boolean;
hidden?: boolean;
disabled?: boolean;
subactions?: Action[];
subactions?: Action[]; // Nested/Inline actions (subactions) within an action
}
export interface ToolTipMenuProps {

View File

@ -383,7 +383,6 @@
"add_bitcoin_explain": "Simple and powerful Bitcoin wallet",
"add_create": "Create",
"total_balance": "Total Balance",
"balance": "Balance",
"add_entropy_reset_title": "Reset Entropy",
"add_entropy_reset_message": "Changing the wallet type will reset the current entropy. Do you want to proceed?",
"add_entropy": "Entropy",
@ -474,8 +473,6 @@
"no_ln_wallet_error": "Before paying a Lightning invoice, you must first add a Lightning wallet.",
"looks_like_bip38": "This looks like a password-protected private key (BIP38).",
"manage_title": "Manage Wallets",
"sort_by_order": "Order",
"sort_by_property": "Property",
"no_results_found": "No results found.",
"please_continue_scanning": "Please continue scanning.",
"select_no_bitcoin": "There are currently no Bitcoin wallets available.",

View File

@ -1,5 +1,5 @@
import React, { useEffect, useLayoutEffect, useReducer, useCallback, useMemo, useRef } from 'react';
import { StyleSheet, View, TouchableOpacity, Image, Text, Alert, I18nManager, Animated, LayoutAnimation } from 'react-native';
import { StyleSheet, TouchableOpacity, Image, Text, Alert, I18nManager, Animated, LayoutAnimation } from 'react-native';
import {
NestableScrollContainer,
ScaleDecorator,
@ -25,23 +25,12 @@ import prompt from '../../helpers/prompt';
import HeaderRightButton from '../../components/HeaderRightButton';
import { ManageWalletsListItem } from '../../components/ManageWalletsListItem';
import { useSettings } from '../../hooks/context/useSettings';
import { CommonToolTipActions } from '../../typings/CommonToolTipActions';
import MoreOptionsButton from '../../components/icons/MoreOptionsButton';
import { Action } from '../../components/types';
enum ItemType {
WalletSection = 'wallet',
TransactionSection = 'transaction',
}
enum SortOption {
Balance = 'balance',
Label = 'label',
MostRecent = 'mostRecent',
ASC = 'asc',
DESC = 'desc',
}
interface WalletItem {
type: ItemType.WalletSection;
data: TWallet;
@ -61,7 +50,6 @@ const SET_FILTERED_ORDER = 'SET_FILTERED_ORDER';
const SET_TEMP_ORDER = 'SET_TEMP_ORDER';
const REMOVE_WALLET = 'REMOVE_WALLET';
const SAVE_CHANGES = 'SAVE_CHANGES';
const SET_CURRENT_SORT = 'SET_CURRENT_SORT';
interface SaveChangesAction {
type: typeof SAVE_CHANGES;
@ -98,20 +86,14 @@ interface RemoveWalletAction {
payload: string; // Wallet ID
}
interface SetCurrentSortAction {
type: typeof SET_CURRENT_SORT;
payload: SortOption;
}
type ReducerAction =
type Action =
| SetSearchQueryAction
| SetIsSearchFocusedAction
| SetInitialOrderAction
| SetFilteredOrderAction
| SetTempOrderAction
| SaveChangesAction
| RemoveWalletAction
| SetCurrentSortAction;
| RemoveWalletAction;
interface State {
searchQuery: string;
@ -120,7 +102,6 @@ interface State {
tempOrder: Item[];
wallets: TWallet[];
txMetadata: TTXMetadata;
currentSort: SortOption;
}
const initialState: State = {
@ -130,14 +111,13 @@ const initialState: State = {
tempOrder: [],
wallets: [],
txMetadata: {},
currentSort: SortOption.Balance,
};
const deepCopyWallets = (wallets: TWallet[]): TWallet[] => {
return wallets.map(wallet => Object.assign(Object.create(Object.getPrototypeOf(wallet)), wallet));
};
const reducer = (state: State, action: ReducerAction): State => {
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case SET_SEARCH_QUERY:
return { ...state, searchQuery: action.payload };
@ -201,10 +181,8 @@ const reducer = (state: State, action: ReducerAction): State => {
tempOrder: updatedOrder,
};
}
case SET_CURRENT_SORT:
return { ...state, currentSort: action.payload };
default:
throw new Error(`Unhandled action type: ${(action as ReducerAction).type}`);
throw new Error(`Unhandled action type: ${(action as Action).type}`);
}
};
@ -285,127 +263,11 @@ const ManageWallets: React.FC = () => {
[goBack, closeImage],
);
const moreOptionsActions = useMemo((): Action[] | Action[][] => {
return [
{
id: 'sort_by_menu',
text: loc.cc.sort_by,
subactions: [
{
id: 'sort_by_order',
displayInline: true,
text: loc.wallets.sort_by_order,
keepsMenuPresented: true,
subactions: [
{ ...CommonToolTipActions.SortASC, menuState: state.currentSort === SortOption.ASC },
{ ...CommonToolTipActions.SortDESC, menuState: state.currentSort === SortOption.DESC },
],
},
{
id: 'sort_by_wallet',
displayInline: true,
text: loc.wallets.sort_by_property,
subactions: [
{
...CommonToolTipActions.SortBalance,
menuState: state.currentSort === SortOption.Balance,
disabled: state.currentSort === SortOption.Balance,
},
{
...CommonToolTipActions.SortLabel,
menuState: state.currentSort === SortOption.Label,
disabled: state.currentSort === SortOption.Label,
},
{
...CommonToolTipActions.MostRecentTransaction,
menuState: state.currentSort === SortOption.MostRecent,
disabled: state.currentSort === SortOption.MostRecent,
},
],
},
{ ...CommonToolTipActions.Reset },
],
},
];
}, [state.currentSort]);
const moreOptionsOnPressMenuItem = useCallback(
(id: string) => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
switch (id) {
case CommonToolTipActions.SortASC.id: {
dispatch({ type: SET_CURRENT_SORT, payload: SortOption.ASC });
const sortedWallets = state.tempOrder
.filter((item): item is WalletItem => item.type === ItemType.WalletSection)
.sort((a, b) => a.data.getLabel()!.localeCompare(b.data.getLabel()!));
dispatch({ type: SET_TEMP_ORDER, payload: sortedWallets });
break;
}
case CommonToolTipActions.SortDESC.id: {
dispatch({ type: SET_CURRENT_SORT, payload: SortOption.DESC });
const sortedWallets = state.tempOrder
.filter((item): item is WalletItem => item.type === ItemType.WalletSection)
.sort((a, b) => b.data.getLabel()!.localeCompare(a.data.getLabel()!));
dispatch({ type: SET_TEMP_ORDER, payload: sortedWallets });
break;
}
case CommonToolTipActions.SortBalance.id: {
dispatch({ type: SET_CURRENT_SORT, payload: SortOption.Balance });
const sortedWallets = state.tempOrder
.filter((item): item is WalletItem => item.type === ItemType.WalletSection)
.sort((a, b) => a.data.getBalance() - b.data.getBalance());
dispatch({ type: SET_TEMP_ORDER, payload: sortedWallets });
break;
}
case CommonToolTipActions.SortLabel.id: {
dispatch({ type: SET_CURRENT_SORT, payload: SortOption.Label });
const sortedWalletsByLabel = state.tempOrder
.filter((item): item is WalletItem => item.type === ItemType.WalletSection)
.sort((a, b) => a.data.getLabel()!.localeCompare(b.data.getLabel()!));
dispatch({ type: SET_TEMP_ORDER, payload: sortedWalletsByLabel });
break;
}
case CommonToolTipActions.MostRecentTransaction.id: {
dispatch({ type: SET_CURRENT_SORT, payload: SortOption.MostRecent });
const sortedWalletsByMostRecent = state.tempOrder
.filter((item): item is WalletItem => item.type === ItemType.WalletSection)
.sort((a, b) => {
const getMostRecentTime = (wallet: TWallet) => wallet.getTransactions()[0]?.time ?? 0;
return getMostRecentTime(b.data) - getMostRecentTime(a.data);
});
dispatch({ type: SET_TEMP_ORDER, payload: sortedWalletsByMostRecent });
break;
}
case CommonToolTipActions.Reset.id: {
dispatch({ type: SET_TEMP_ORDER, payload: state.order });
break;
}
}
},
[state.order, state.tempOrder],
);
const SaveButton = useMemo(
() => <HeaderRightButton disabled={!hasUnsavedChanges} title={loc.send.input_done} onPress={handleClose} />,
[handleClose, hasUnsavedChanges],
);
const MoreButton = useMemo(
() => <MoreOptionsButton isMenuPrimaryAction actions={moreOptionsActions} onPressMenuItem={moreOptionsOnPressMenuItem} />,
[moreOptionsActions, moreOptionsOnPressMenuItem],
);
const HeaderRight = useCallback(
() => (
<>
{MoreButton}
<View style={styles.separation} />
{SaveButton}
</>
),
[MoreButton, SaveButton],
);
useLayoutEffect(() => {
const searchBarOptions = {
hideWhenScrolling: false,
@ -418,10 +280,10 @@ const ManageWallets: React.FC = () => {
setOptions({
headerLeft: () => HeaderLeftButton,
headerRight: HeaderRight,
headerRight: () => SaveButton,
headerSearchBarOptions: searchBarOptions,
});
}, [setOptions, HeaderLeftButton, SaveButton, MoreButton, HeaderRight]);
}, [setOptions, HeaderLeftButton, SaveButton]);
useFocusEffect(
useCallback(() => {
@ -715,7 +577,4 @@ const styles = StyleSheet.create({
dimmedText: {
opacity: 0.8,
},
separation: {
width: 16,
},
});

View File

@ -50,8 +50,6 @@ const keys = {
SortValue: 'sortValue',
SortLabel: 'sortLabel',
SortStatus: 'sortStatus',
SortBalance: 'sortBalance',
MostRecentTransaction: 'mostRecentTransaction',
Reset: 'reset',
} as const;
@ -97,7 +95,6 @@ const icons = {
ClearClipboard: { iconValue: 'clipboard' },
SortASC: { iconValue: 'arrow.down.to.line' },
SortDESC: { iconValue: 'arrow.up.to.line' },
MostRecentTransaction: { iconValue: 'clock' },
Reset: { iconValue: 'arrow.counterclockwise' },
} as const;
@ -339,13 +336,11 @@ export const CommonToolTipActions = {
id: keys.SortASC,
text: loc.cc.sort_asc,
icon: icons.SortASC,
keepsMenuPresented: true,
},
SortDESC: {
id: keys.SortDESC,
text: loc.cc.sort_desc,
icon: icons.SortDESC,
keepsMenuPresented: true,
},
SortHeight: {
id: keys.SortHeight,
@ -363,14 +358,4 @@ export const CommonToolTipActions = {
id: keys.SortStatus,
text: loc.cc.sort_status,
},
SortBalance: {
id: keys.SortBalance,
text: loc.wallets.balance,
icon: icons.ViewInBitcoin,
},
MostRecentTransaction: {
id: keys.MostRecentTransaction,
text: loc.transactions.details_title,
icon: icons.MostRecentTransaction,
},
} as const;