Skip to content

Commit 1db42d1

Browse files
authored
Balance hiding (#144)
* adds balance hiding functionality * revert file * remove unnecessary prop drilling * hide transaction balances * pr feedback * adds balanceMask variable
1 parent eaee4c1 commit 1db42d1

File tree

8 files changed

+174
-71
lines changed

8 files changed

+174
-71
lines changed

packages/mobile-app/app/(drawer)/account/account-settings/account-select/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import { Stack, useRouter } from "expo-router";
33
import { useFacade } from "@/data/facades";
44
import { CurrencyUtils } from "@ironfish/sdk";
55
import { Layout, Text, Button, Card, Spinner } from "@ui-kitten/components";
6-
import React from "react";
6+
import { useHideBalances } from "@/hooks/useHideBalances";
77

88
export default function AccountSelect() {
99
const router = useRouter();
1010
const facade = useFacade();
11+
const { hideBalances, balanceMask } = useHideBalances();
1112

1213
const getAccountsResult = facade.getAccounts.useQuery(undefined, {
1314
refetchInterval: 1000,
@@ -49,7 +50,9 @@ export default function AccountSelect() {
4950
<Layout>
5051
<Text category="s1">{account.name}</Text>
5152
<Text category="p2" appearance="hint">
52-
{`${CurrencyUtils.render(account.balances.iron.confirmed)} $IRON`}
53+
{hideBalances
54+
? `${balanceMask} $IRON`
55+
: `${CurrencyUtils.render(account.balances.iron.confirmed)} $IRON`}
5356
</Text>
5457
</Layout>
5558
{account.active && (

packages/mobile-app/app/(drawer)/account/account-settings/index.tsx

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import {
55
Menu,
66
MenuItem,
77
Toggle,
8+
Text,
89
} from "@ui-kitten/components";
9-
import { StyleSheet } from "react-native";
10+
import { StyleSheet, View } from "react-native";
1011
import { Stack, useRouter } from "expo-router";
1112
import { useFacade } from "@/data/facades";
1213
import { CurrencyUtils } from "@ironfish/sdk";
@@ -15,6 +16,7 @@ import { useEffect, useState, useCallback } from "react";
1516
import { useAccount } from "@/providers/AccountProvider";
1617
import { SafeAreaView } from "react-native";
1718
import { Spinner } from "@ui-kitten/components";
19+
import { useHideBalances } from "@/hooks/useHideBalances";
1820

1921
const ForwardIcon = (props: any): IconElement => (
2022
<Icon {...props} name="arrow-ios-forward" />
@@ -46,14 +48,18 @@ const ACCOUNT_SETTINGS_ROUTES = {
4648
function getMenuItems({
4749
currentAccountName,
4850
currentAccountBalance,
51+
hideBalances,
52+
balanceMask,
4953
}: {
5054
currentAccountName: string;
5155
currentAccountBalance: string;
56+
hideBalances: boolean;
57+
balanceMask: string;
5258
}) {
5359
return Object.entries(ACCOUNT_SETTINGS_ROUTES).map(([key, route]) => {
5460
if (key === "accountSelect") {
5561
return {
56-
title: `${currentAccountName} (${currentAccountBalance} $IRON)`,
62+
title: `${currentAccountName} (${hideBalances ? balanceMask : currentAccountBalance} $IRON)`,
5763
href: route.href,
5864
};
5965
}
@@ -70,8 +76,9 @@ function getMenuItems({
7076
function AccountSettingsContent({ accountName }: { accountName: string }) {
7177
const router = useRouter();
7278
const facade = useFacade();
79+
const { balanceMask } = useHideBalances();
7380

74-
// I tried using isPending and variables on the mutation, but it was causing toggle
81+
// I tried using the useHideBalances hook but it was causing toggle
7582
// re-renders that made the toggle animation jittery.
7683
const appSettings = facade.getAppSettings.useQuery();
7784
const [hideBalances, setHideBalances] = useState(false);
@@ -105,6 +112,8 @@ function AccountSettingsContent({ accountName }: { accountName: string }) {
105112
currentAccountBalance: CurrencyUtils.render(
106113
getAccountResult.data?.balances.iron.confirmed ?? "0",
107114
),
115+
hideBalances,
116+
balanceMask,
108117
});
109118

110119
const handleSelect = (index: number) => {
@@ -128,12 +137,26 @@ function AccountSettingsContent({ accountName }: { accountName: string }) {
128137
.concat(
129138
<MenuItem
130139
key="hide-balances"
131-
title="Hide Balances"
132-
accessoryRight={() => (
133-
<Toggle
134-
checked={hideBalances}
135-
onChange={onToggleHideBalances}
136-
/>
140+
title={(props) => (
141+
<Layout style={styles.tipContainer}>
142+
<View style={styles.textColumn}>
143+
<Text>Hide Balances</Text>
144+
<Text
145+
category="c1"
146+
appearance="hint"
147+
style={styles.tipText}
148+
>
149+
Tip: Long press on your balance to quickly toggle
150+
visibility
151+
</Text>
152+
</View>
153+
<View style={styles.toggleContainer}>
154+
<Toggle
155+
checked={hideBalances}
156+
onChange={onToggleHideBalances}
157+
/>
158+
</View>
159+
</Layout>
137160
)}
138161
/>,
139162
)}
@@ -170,7 +193,23 @@ const styles = StyleSheet.create({
170193
menu: {
171194
flex: 1,
172195
},
173-
toggle: {
174-
marginRight: 8,
196+
tipContainer: {
197+
flexDirection: "row",
198+
width: "100%",
199+
},
200+
textColumn: {
201+
flex: 1,
202+
paddingLeft: 12,
203+
paddingRight: 8,
204+
},
205+
toggleContainer: {
206+
justifyContent: "center",
207+
alignItems: "flex-end",
208+
paddingRight: 12,
209+
},
210+
tipText: {
211+
marginTop: 4,
212+
width: "80%",
213+
fontStyle: "italic",
175214
},
176215
});

packages/mobile-app/app/(drawer)/account/index.tsx

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
Spinner,
1313
Modal,
1414
} from "@ui-kitten/components";
15-
import { StyleSheet, View } from "react-native";
15+
import { StyleSheet, View, Pressable } from "react-native";
1616
import { setStringAsync } from "expo-clipboard";
1717
import Animated, {
1818
useAnimatedScrollHandler,
@@ -28,6 +28,8 @@ import { CurrencyUtils } from "@ironfish/sdk";
2828
import { CONFIRMATIONS } from "@/data/constants";
2929
import { AssetRow } from "@/components/account/AssetRow";
3030
import { TransactionRow } from "@/components/account/TransactionRow";
31+
import { useHideBalances } from "@/hooks/useHideBalances";
32+
import { SettingsKey } from "@/data/settings/db";
3133

3234
const ReceiveIcon = (props: IconProps) => (
3335
<Icon {...props} name="download-outline" />
@@ -46,11 +48,13 @@ interface Balance {
4648
}
4749

4850
export default function Balances() {
51+
const { hideBalances, balanceMask } = useHideBalances();
4952
const facade = useFacade();
5053
const { account, accountName, isLoading } = useAccount();
5154
const scrollYOffset = useSharedValue(0);
5255
const [selectedIndex, setSelectedIndex] = useState(0);
5356
const [addressModalVisible, setAddressModalVisible] = useState(false);
57+
const { mutate: setAppSetting } = facade.setAppSetting.useMutation();
5458

5559
const scrollHandler = useAnimatedScrollHandler((event) => {
5660
scrollYOffset.value = event.contentOffset.y;
@@ -105,6 +109,13 @@ export default function Balances() {
105109
},
106110
);
107111

112+
const handleLongPress = () => {
113+
setAppSetting({
114+
key: SettingsKey.HideBalances,
115+
value: hideBalances ? "false" : "true",
116+
});
117+
};
118+
108119
if (isLoading || !account) {
109120
return (
110121
<SafeAreaView>
@@ -178,44 +189,48 @@ export default function Balances() {
178189
paddingTop: 40,
179190
}}
180191
>
181-
<Layout style={styles.headerBalance}>
182-
<Text category="h1" style={styles.balanceAmount}>
183-
{CurrencyUtils.render(
184-
account?.balances.iron.confirmed ?? "0",
185-
)}
186-
</Text>
187-
<Text category="s1" appearance="hint">
188-
{getIronAsset.data?.verification.status === "verified"
189-
? getIronAsset.data.verification.symbol
190-
: (getIronAsset.data?.name ?? "IRON")}
191-
</Text>
192-
193-
<Layout style={styles.actionButtons}>
194-
<Button
195-
appearance="ghost"
196-
accessoryLeft={ReceiveIcon}
197-
style={styles.actionButton}
198-
onPress={() => setAddressModalVisible(true)}
199-
>
200-
Receive
201-
</Button>
202-
<Button
203-
appearance="ghost"
204-
accessoryLeft={SendIcon}
205-
style={styles.actionButton}
206-
onPress={() => router.push("/(drawer)/account/send")}
207-
>
208-
Send
209-
</Button>
210-
<Button
211-
appearance="ghost"
212-
accessoryLeft={BridgeIcon}
213-
style={styles.actionButton}
214-
onPress={() => router.push("/(drawer)/account/bridge")}
215-
>
216-
Bridge
217-
</Button>
192+
<Pressable onLongPress={handleLongPress} delayLongPress={2000}>
193+
<Layout style={styles.headerBalance}>
194+
<Text category="h1" style={styles.balanceAmount}>
195+
{hideBalances
196+
? balanceMask
197+
: CurrencyUtils.render(
198+
account?.balances.iron.confirmed ?? "0",
199+
)}
200+
</Text>
201+
<Text category="s1" appearance="hint">
202+
{getIronAsset.data?.verification.status === "verified"
203+
? getIronAsset.data.verification.symbol
204+
: (getIronAsset.data?.name ?? "IRON")}
205+
</Text>
218206
</Layout>
207+
</Pressable>
208+
209+
<Layout style={styles.actionButtons}>
210+
<Button
211+
appearance="ghost"
212+
accessoryLeft={ReceiveIcon}
213+
style={styles.actionButton}
214+
onPress={() => setAddressModalVisible(true)}
215+
>
216+
Receive
217+
</Button>
218+
<Button
219+
appearance="ghost"
220+
accessoryLeft={SendIcon}
221+
style={styles.actionButton}
222+
onPress={() => router.push("/(drawer)/account/send")}
223+
>
224+
Send
225+
</Button>
226+
<Button
227+
appearance="ghost"
228+
accessoryLeft={BridgeIcon}
229+
style={styles.actionButton}
230+
onPress={() => router.push("/(drawer)/account/bridge")}
231+
>
232+
Bridge
233+
</Button>
219234
</Layout>
220235
</Animated.View>
221236

@@ -265,6 +280,11 @@ export default function Balances() {
265280
}
266281
amount={CurrencyUtils.render(
267282
account.balances.iron.confirmed,
283+
hideBalances,
284+
account.balances.iron.assetId,
285+
getIronAsset.data?.verification.status === "verified"
286+
? getIronAsset.data.verification
287+
: undefined,
268288
)}
269289
verified={
270290
getIronAsset.data?.verification.status === "verified"
@@ -289,7 +309,7 @@ export default function Balances() {
289309
}
290310
amount={CurrencyUtils.render(
291311
balance.confirmed,
292-
false,
312+
hideBalances,
293313
balance.assetId,
294314
asset?.verification.status === "verified"
295315
? asset.verification

packages/mobile-app/app/(drawer)/account/send/index.tsx

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CurrencyUtils } from "@ironfish/sdk";
66
import { useQueries } from "@tanstack/react-query";
77
import { Asset } from "@/data/facades/chain/types";
88
import { AccountBalance } from "@/data/facades/wallet/types";
9+
import { useHideBalances } from "@/hooks/useHideBalances";
910
import {
1011
Layout,
1112
Text,
@@ -41,6 +42,7 @@ type TransactionState = "sending" | "sent" | "idle";
4142
export default function Send() {
4243
const facade = useFacade();
4344
const router = useRouter();
45+
const { hideBalances, balanceMask } = useHideBalances();
4446

4547
const [selectedAssetId, setSelectedAssetId] =
4648
useState<string>(IRON_ASSET_ID_HEX);
@@ -95,12 +97,12 @@ export default function Send() {
9597
return map;
9698
}, [getCustomAssets]);
9799

98-
// Create asset options for the select component
100+
// Update asset options to respect hide balances
99101
const assetOptions = useMemo(() => {
100102
const options = [
101103
{
102104
id: IRON_ASSET_ID_HEX,
103-
title: `IRON (${CurrencyUtils.render(getAccountResult.data?.balances.iron.available ?? "0")})`,
105+
title: `IRON (${hideBalances ? balanceMask : CurrencyUtils.render(getAccountResult.data?.balances.iron.available ?? "0")})`,
104106
},
105107
];
106108

@@ -109,20 +111,24 @@ export default function Send() {
109111
if (asset) {
110112
options.push({
111113
id: b.assetId,
112-
title: `${asset.name} (${CurrencyUtils.render(
113-
b.available,
114-
false,
115-
b.assetId,
116-
asset.verification.status === "verified"
117-
? asset.verification
118-
: undefined,
119-
)})`,
114+
title: `${asset.name} (${
115+
hideBalances
116+
? balanceMask
117+
: CurrencyUtils.render(
118+
b.available,
119+
false,
120+
b.assetId,
121+
asset.verification.status === "verified"
122+
? asset.verification
123+
: undefined,
124+
)
125+
})`,
120126
});
121127
}
122128
});
123129

124130
return options;
125-
}, [getAccountResult.data, assetMap]);
131+
}, [getAccountResult.data, assetMap, hideBalances, balanceMask]);
126132

127133
// Find the selected asset index
128134
const selectedIndex = useMemo(() => {
@@ -303,7 +309,7 @@ export default function Send() {
303309
{transactionState === "sending" ? "Sending..." : "Sent!"}
304310
</Text>
305311
<Text category="s1" style={styles.amountText}>
306-
{amount}{" "}
312+
{hideBalances ? balanceMask : amount}{" "}
307313
{selectedAssetId === IRON_ASSET_ID_HEX
308314
? "$IRON"
309315
: (assetMap.get(selectedAssetId)?.name ?? "Unknown")}{" "}

0 commit comments

Comments
 (0)