Skip to content

Commit

Permalink
Scaffold out some of the main flows in the app
Browse files Browse the repository at this point in the history
  • Loading branch information
dguenther committed Aug 19, 2024
1 parent 97eb592 commit 149b2aa
Show file tree
Hide file tree
Showing 26 changed files with 982 additions and 180 deletions.
123 changes: 77 additions & 46 deletions packages/mobile-app/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,84 @@
import { FontAwesome6, Ionicons, FontAwesome } from "@expo/vector-icons";
import { Tabs } from "expo-router";
import { useState } from "react";
import { Button, Modal, SafeAreaView, Text } from "react-native";
import { LinkButton } from "../../components/LinkButton";

export default function Layout() {
const [modalVisible, setModalVisible] = useState(false);

return (
<Tabs>
<Tabs.Screen
name="index"
options={{
title: "Balances",
tabBarIcon: ({ focused, color, size }) => (
<Ionicons
name={focused ? "wallet" : "wallet-outline"}
size={size}
color={color}
/>
),
}}
/>
<Tabs.Screen
name="transact"
options={{
title: "Transact",
tabBarIcon: ({ color, size }) => (
<FontAwesome6
name="arrow-right-arrow-left"
size={size}
color={color}
/>
),
}}
/>
<Tabs.Screen
name="contacts"
options={{
title: "Contacts",
tabBarIcon: ({ color, size }) => (
<FontAwesome name="user-circle-o" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="ui"
options={{
title: "UI Kit",
tabBarIcon: ({ color, size }) => (
<FontAwesome name="paint-brush" size={size} color={color} />
),
}}
/>
</Tabs>
<>
<Modal animationType="slide" visible={modalVisible}>
<SafeAreaView style={{ flex: 1 }}>
<Text>Transact</Text>
<LinkButton
title="Receive"
href="/address/"
onPress={() => setModalVisible(false)}
/>
<Text>Receive assets from another wallet</Text>
<LinkButton
title="Send"
href="/send/"
onPress={() => setModalVisible(false)}
/>
<Text>Send assets to another wallet</Text>
<Button title="Close" onPress={() => setModalVisible(false)} />
</SafeAreaView>
</Modal>
<Tabs>
<Tabs.Screen
name="index"
options={{
title: "Balances",
tabBarIcon: ({ focused, color, size }) => (
<Ionicons
name={focused ? "wallet" : "wallet-outline"}
size={size}
color={color}
/>
),
}}
/>
<Tabs.Screen
name="transact"
listeners={{
tabPress: (e) => {
e.preventDefault();
setModalVisible(!modalVisible);
},
}}
options={{
title: "Transact",
tabBarIcon: ({ color, size }) => (
<FontAwesome6
name="arrow-right-arrow-left"
size={size}
color={color}
/>
),
}}
/>
<Tabs.Screen
name="contacts"
options={{
title: "Contacts",
tabBarIcon: ({ color, size }) => (
<FontAwesome name="user-circle-o" size={size} color={color} />
),
}}
/>
<Tabs.Screen
name="ui"
options={{
title: "UI Kit",
tabBarIcon: ({ color, size }) => (
<FontAwesome name="paint-brush" size={size} color={color} />
),
}}
/>
</Tabs>
</>
);
}
59 changes: 29 additions & 30 deletions packages/mobile-app/app/(tabs)/contacts.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,37 @@
import { View, Text, Button } from "react-native";
import { View, Text, Button, StyleSheet, Modal, TextInput } from "react-native";

import { useFacade } from "../../data/facades";
import { StatusBar } from "expo-status-bar";
import { LinkButton } from "../../components/LinkButton";
import { useState } from "react";

export default function Contacts() {
const facade = useFacade();

const walletStatus = facade.getWalletStatus.useQuery(undefined, {
refetchInterval: 1000,
});

const pauseSyncing = facade.pauseSyncing.useMutation();
const resumeSyncing = facade.resumeSyncing.useMutation();
const [modalVisible, setModalVisible] = useState(false);

return (
<View>
{walletStatus.data && (
<>
<Text>{`Scan status: ${walletStatus.data.status}`}</Text>
<Text>{`Latest known block: ${walletStatus.data.latestKnownBlock}`}</Text>
</>
)}
<Text>{}</Text>
<Button
onPress={async () => {
await resumeSyncing.mutateAsync(undefined);
}}
title="Resume Syncing"
/>
<Button
onPress={async () => {
await pauseSyncing.mutateAsync(undefined);
}}
title="Pause Syncing"
/>
<View style={styles.container}>
<Modal visible={modalVisible} animationType="slide">
<View style={styles.container}>
<Text>Add Contact</Text>
<TextInput placeholder="Name" />
<TextInput placeholder="Address" />
<TextInput placeholder="Add note (Optional)" />
<Button title="Add Contact" onPress={() => setModalVisible(false)} />
<Button title="Close" onPress={() => setModalVisible(false)} />
</View>
</Modal>
<LinkButton title="Menu" href="/menu/" />
<Button title="Add" onPress={() => setModalVisible(true)} />

<StatusBar style="auto" />
</View>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
43 changes: 36 additions & 7 deletions packages/mobile-app/app/(tabs)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { StatusBar } from "expo-status-bar";
import { ScrollView, StyleSheet, Text, View } from "react-native";
import { useFacade } from "../../data/facades";
import { useEffect, useState } from "react";
import { LinkButton } from "../../components/LinkButton";

export default function Balances() {
const facade = useFacade();
Expand All @@ -24,6 +25,10 @@ export default function Balances() {

const getAccountsResult = facade.getAccounts.useQuery();

const getWalletStatusResult = facade.getWalletStatus.useQuery(undefined, {
refetchInterval: 1000,
});

useEffect(() => {
if (getAccountsResult.data?.[0]) {
setAccount(getAccountsResult.data[0].name);
Expand All @@ -32,6 +37,37 @@ export default function Balances() {

return (
<View style={styles.container}>
<View style={{ display: "flex", flexDirection: "row" }}>
<LinkButton href="/menu/" title="Menu" />
<LinkButton
href="/accountSelect/"
title={getAccountResult.data?.name ?? "Account 1"}
/>
<LinkButton
href={`/accountSettings/?accountName=${getAccountResult.data?.name}`}
title="Account Settings"
/>
</View>
<Text>You're currently on Testnet</Text>
{getAccountResult.data && (
<>
<Text>{`${getAccountResult.data.balances.iron.confirmed}`}</Text>
<Text>{`$IRON`}</Text>
</>
)}
{getWalletStatusResult.data &&
getWalletStatusResult.data.status === "SCANNING" && (
// TODO: Only show this if the wallet is behind a certain number of blocks to avoid flickering
<>
<Text>{`Blocks Scanned: ${getAccountResult.data?.head?.sequence ?? "--"} / ${getWalletStatusResult.data.latestKnownBlock}`}</Text>
<Text>Your balances may currently be inaccurate.</Text>
<Text>Learn More</Text>
</>
)}
<View style={{ display: "flex", flexDirection: "row" }}>
<LinkButton href="/send/" title="Send" />
<LinkButton href="/address/" title="Receive" />
</View>
<Text style={{ fontWeight: 700, fontSize: 24 }}>Transactions</Text>
<ScrollView>
{getTransactionsResult.data?.map((transaction) => (
Expand All @@ -45,13 +81,6 @@ export default function Balances() {
</View>
))}
</ScrollView>
<Text style={{ fontWeight: 700, fontSize: 24 }}>Balance</Text>
{getAccountResult.data && (
<>
<Text>{`Unconfirmed: IRON ${getAccountResult.data.balances.iron.unconfirmed}`}</Text>
<Text>{`Confirmed: IRON ${getAccountResult.data.balances.iron.confirmed}`}</Text>
</>
)}
<StatusBar style="auto" />
</View>
);
Expand Down
92 changes: 5 additions & 87 deletions packages/mobile-app/app/(tabs)/transact.tsx
Original file line number Diff line number Diff line change
@@ -1,89 +1,7 @@
import { View, Text, ScrollView, TextInput, Button } from "react-native";
import { useFacade } from "../../data/facades";
import { useQueryClient } from "@tanstack/react-query";
import React from "react";
import { AccountFormat } from "@ironfish/sdk";

/**
* This is a placeholder page to make the Expo Tabs layout work with
* the Transact button as a modal.
*/
export default function Transact() {
const facade = useFacade();
const qc = useQueryClient();

const getAccountsResult = facade.getAccounts.useQuery(undefined, {
refetchInterval: 1000,
});
const createAccount = facade.createAccount.useMutation({
onSuccess: () => {
qc.invalidateQueries({
queryKey: ["getAccounts"],
});
},
});
const importAccount = facade.importAccount.useMutation({
onSuccess: () => {
qc.invalidateQueries({
queryKey: ["getAccounts"],
});
},
});
const removeAccount = facade.removeAccount.useMutation({
onSuccess: () => {
qc.invalidateQueries({
queryKey: ["getAccounts"],
});
},
});
const exportAccount = facade.exportAccount.useMutation();

const [importAccountText, setImportAccountText] = React.useState("");

return (
<ScrollView>
<Text>Accounts</Text>
{(getAccountsResult.data ?? []).map((account, i) => (
<View key={i}>
<Text>{account.name}</Text>
<Text>{JSON.stringify(account)}</Text>
<Button
onPress={async () => {
await removeAccount.mutateAsync({ name: account.name });
console.log("Removed Account", account.name);
}}
title="Remove Account"
/>
<Button
onPress={async () => {
const otherResult = await exportAccount.mutateAsync({
name: account.name,
format: AccountFormat.Base64Json,
});
console.log("Exported Account:", otherResult);
}}
title="Export Account"
/>
</View>
))}
<Button
onPress={async () => {
const otherResult = await createAccount.mutateAsync({ name: "dave" });
console.log("Created Account:", otherResult);
}}
title="Create Account"
/>
<TextInput
value={importAccountText}
onChangeText={setImportAccountText}
placeholder="Import account"
/>
<Button
onPress={async () => {
const otherResult = await importAccount.mutateAsync({
account: importAccountText,
name: "asdf",
});
console.log("Imported Account:", otherResult);
}}
title="Import Account"
/>
</ScrollView>
);
return null;
}
Loading

0 comments on commit 149b2aa

Please sign in to comment.