Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prepare mobile app for release candidate #3260

Merged
merged 15 commits into from
Mar 13, 2023
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ You can also optionally rename `.env.example` to `.env` and set your own variabl
yarn install
```

Note: yarn `^1.22.17` is required but this is sometimes ignored by more recent versions of yarn while installing, so if you have any issues make sure to manually check you are using v1 with `yarn -v`
Note: yarn `^1.22.17` is required but this is sometimes ignored by more recent versions of yarn while installing, so if you have any issues make sure to manually check you are using v1 with `yarn -v`

### Build all packages for production

Expand Down
2 changes: 1 addition & 1 deletion packages/app-mobile/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
process.env.TAMAGUI_TARGET = "native"; // Don't forget to specify your TAMAGUI_TARGET here

module.exports = function(api) {
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
Expand Down
5 changes: 5 additions & 0 deletions packages/app-mobile/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import * as SQLite from "expo-sqlite";

import { registerRootComponent } from "expo";
import setGlobalVars from "indexeddbshim/dist/indexeddbshim-noninvasive";
import "./src/crypto-shim";

if (typeof Buffer === "undefined") {
Expand All @@ -9,6 +12,8 @@ if (typeof BigInt === "undefined") {
global.BigInt = require("big-integer");
}

setGlobalVars(window, { checkOrigin: false, win: SQLite });

// eslint-disable-next-line
import "react-native-url-polyfill/auto";
// Import the the ethers shims (**BEFORE** ethers)
Expand Down
6 changes: 5 additions & 1 deletion packages/app-mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@cardinal/payment-manager": "^1.7.9",
"@cardinal/token-manager": "^1.7.9",
"@coral-xyz/common": "*",
"@coral-xyz/db": "*",
"@coral-xyz/tamagui": "*",
"@coral-xyz/recoil": "*",
"@ethersproject/shims": "^5.7.0",
Expand All @@ -26,6 +27,7 @@
"@gorhom/bottom-sheet": "^4.4.5",
"@metaplex-foundation/mpl-token-metadata": "^2.7.0",
"@project-serum/anchor": "^0.24.2",
"@react-native-async-storage/async-storage": "1.17.11",
"@react-navigation/bottom-tabs": "^6.4.0",
"@react-navigation/native": "^6.0.11",
"@react-navigation/native-stack": "^6.7.0",
Expand All @@ -45,8 +47,10 @@
"expo-random": "~13.1.1",
"expo-secure-store": "~12.1.1",
"expo-splash-screen": "~0.18.1",
"expo-sqlite": "~11.1.1",
"expo-status-bar": "~1.4.4",
"expo-updates": "~0.16.1",
"indexeddbshim": "^11.0.0-beta.0",
"expo-updates": "~0.16.3",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-hook-form": "^7.40.0",
Expand Down
54 changes: 54 additions & 0 deletions packages/app-mobile/src/components/ImageSvg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useState, useEffect } from "react";
import { Image } from "react-native";

import { SvgUri } from "react-native-svg";

export function ImageSvg({
uri,
width = 32,
height = 32,
style,
}: {
uri: string;
width: number;
height: number;
style?: any;
}): JSX.Element {
const [type, setType] = useState<string | undefined>(undefined);

useEffect(() => {
fetch(uri, { method: "HEAD" })
.then((r) => {
const h = new Headers(r.headers);
const ct = h.get("content-type");
if (ct) {
if (ct.includes("svg")) {
setType("svg");
}
}
})
.catch((error) => {
console.error(error);
});
}, [uri]);

if (type === "svg") {
const url = `${uri}.svg`;
return <SvgUri width={width} height={height} uri={url} />;
}

return (
<Image
source={{ uri }}
style={[
{
aspectRatio: 1,
width,
height,
borderRadius: 100,
},
style,
]}
/>
);
}
55 changes: 50 additions & 5 deletions packages/app-mobile/src/components/TokenInputField.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import type { BigNumber } from "ethers";

import { useState } from "react";
import type { TextInputProps } from "react-native";
import type {
TextInputProps,
StyleProp,
ViewStyle,
TextStyle,
} from "react-native";
import { TextInput } from "react-native";

import { toDisplayBalance } from "@coral-xyz/common";
import { ethers } from "ethers";

import { StyledTextInput } from "~components/index";
Expand All @@ -18,9 +25,8 @@ export function StyledTokenTextInput({
onChangeText: (value: BigNumber | null) => void;
props: TextInputProps;
}) {
const [focused] = useState(false);
const [focused, setFocused] = useState(false);
const [inputValue, setInputValue] = useState<string | null>(null);
console.log("StyledTokenTextInput:inputValue", inputValue);

// // Clear input value (fall back to value prop) if focus changes
// useEffect(() => {
Expand Down Expand Up @@ -65,8 +71,47 @@ export function StyledTokenTextInput({
returnKeyType="done"
defaultValue={value}
onChangeText={handleChangeText}
// onFocus={() => setFocused(true)}
// onBlur={() => setFocused(false)}
{...props}
/>
);
}

export function UnstyledTokenTextInput({
decimals,
amount,
onChangeAmount,
style,
...props
}: {
decimals: number;
amount: BigNumber | null;
onChangeAmount: (value: BigNumber | null) => void;
style: StyleProp<ViewStyle & TextStyle>;
}) {
const handleChangeText = (value: string) => {
try {
const parsedVal = value.length === 1 && value[0] === "." ? "0." : value;

const num =
parsedVal === "" || parsedVal === "0." ? 0.0 : parseFloat(parsedVal);

if (num >= 0) {
onChangeAmount(ethers.utils.parseUnits(num.toString(), decimals));
}
} catch (error) {
console.error("UnstyledTokenTextInput:error", error);
// Do nothing.
}
};

return (
<TextInput
placeholder="0.0"
keyboardType="decimal-pad"
returnKeyType="done"
defaultValue={amount ? toDisplayBalance(amount, decimals) : ""}
onChangeText={handleChangeText}
style={style}
{...props}
/>
);
Expand Down
9 changes: 1 addition & 8 deletions packages/app-mobile/src/components/TransactionData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { useEffect, useRef, useState } from "react";
import { Text, View, TextInput } from "react-native";

import { useEthereumFeeData } from "@coral-xyz/recoil";
import { SettingsList } from "~screens/Unlocked/Settings/components/SettingsMenuList";
import { ethers } from "ethers";

import { IconCloseModal } from "~components/Icon";
import { PrimaryButton, SecondaryButton } from "~components/index";
import { useTheme } from "~hooks/useTheme";
import { SettingsList } from "~screens/Unlocked/Settings/components/SettingsMenuList";

type TransactionMode = "normal" | "fast" | "degen" | "custom";

Expand Down Expand Up @@ -159,13 +159,6 @@ export function EthereumSettingsDrawer({
setEditingGas(mode === "custom");
}, [mode]);

useEffect(() => {
document.addEventListener("keydown", handleEsc);
return () => {
document.removeEventListener("keydown", handleEsc);
};
}, [editingGas, editingNonce]);

// Escape handler that closes edit modes if they are active, otherwise closes
// the entire drawer.
const handleEsc = (event: KeyboardEvent) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ import { Pressable, Text, View } from "react-native";

import { Token, NavTokenAction, NavTokenOptions } from "@@types/types";
import { Blockchain } from "@coral-xyz/common";
import {
SwapProvider, // TODO(peter): broken
enabledBlockchains as enabledBlockchainsAtom,
} from "@coral-xyz/recoil";
// import // SwapProvider, // TODO(peter): turn back on when app store approved
// enabledBlockchains as enabledBlockchainsAtom,
// "@coral-xyz/recoil";
import { XStack } from "@coral-xyz/tamagui";
import { MaterialIcons } from "@expo/vector-icons";
import { useRecoilValueLoadable } from "recoil";
// import { useRecoilValueLoadable } from "recoil";

import { Margin } from "~components/index";
import { useTheme } from "~hooks/useTheme";

const HorizontalSpacer = () => <View style={{ width: 16 }} />;
const ENABLE_ONRAMP = false;

const getRouteFromAction = (
action: NavTokenAction
): "DepositList" | "SendSelectTokenModal" | "SwapModal" => {
Expand All @@ -31,57 +28,46 @@ const getRouteFromAction = (
};

export function TransferWidget({
blockchain,
address,
blockchain,
onPressOption,
rampEnabled,
swapEnabled,
token,
}: {
blockchain?: Blockchain;
address?: string;
rampEnabled: boolean;
blockchain?: Blockchain;
onPressOption: (action: NavTokenAction, options: NavTokenOptions) => void;
rampEnabled: boolean;
swapEnabled: boolean;
token?: Token;
}): JSX.Element {
const eb = useRecoilValueLoadable(enabledBlockchainsAtom);
const enabledBlockchains = eb.state === "hasValue" ? eb.contents : [];
const enableOnramp = ENABLE_ONRAMP;
const renderSwap =
blockchain !== Blockchain.ETHEREUM &&
enabledBlockchains.includes(Blockchain.SOLANA);
// const eb = useRecoilValueLoadable(enabledBlockchainsAtom);
// const enabledBlockchains = eb.state === "hasValue" ? eb.contents : [];
// const renderSwap =
// blockchain !== Blockchain.ETHEREUM &&
// enabledBlockchains.includes(Blockchain.SOLANA);

const onPress = (action: NavTokenAction, options: NavTokenOptions) => {
const route = getRouteFromAction(action);
onPressOption(route, options);
};

return (
<View
style={{
flexDirection: "row",
justifyContent: "center",
alignItems: "center",
}}
>
{enableOnramp ? (
<>
<RampButton blockchain={blockchain} address={address} />
<HorizontalSpacer />
</>
<XStack space jc="center">
{rampEnabled ? (
<RampButton blockchain={blockchain} address={address} />
) : null}
<ReceiveButton onPress={onPress} blockchain={blockchain} />
<HorizontalSpacer />
<SendButton onPress={onPress} blockchain={blockchain} token={token} />
{renderSwap ? (
<>
<HorizontalSpacer />
<SwapButton
onPress={onPress}
blockchain={blockchain}
address={address}
/>
</>
{swapEnabled ? (
<SwapButton
// onPress={onPress}
// blockchain={blockchain}
// address={address}
/>
) : null}
</View>
</XStack>
);
}

Expand Down Expand Up @@ -132,24 +118,27 @@ function TransferButton({
);
}

function SwapButton({
blockchain,
address,
onPress,
}: {
blockchain?: Blockchain;
address?: string;
onPress: (route: NavTokenAction, options: NavTokenOptions) => void;
}) {
return (
<SwapProvider tokenAddress={address}>
<TransferButton
label="Swap"
icon="compare-arrows"
onPress={() => onPress(NavTokenAction.Swap, { blockchain })}
/>
</SwapProvider>
);
// NOTE(peter) turned off for app store launch
function SwapButton() {
// function SwapButton({
// blockchain,
// address,
// onPress,
// }: {
// blockchain?: Blockchain;
// address?: string;
// onPress: (route: NavTokenAction, options: NavTokenOptions) => void;
// }) {
return null;
// return (
// <SwapProvider tokenAddress={address}>
// <TransferButton
// label="Swap"
// icon="compare-arrows"
// onPress={() => onPress(NavTokenAction.Swap, { blockchain })}
// />
// </SwapProvider>
// );
}

function SendButton({
Expand Down
2 changes: 1 addition & 1 deletion packages/app-mobile/src/navigation/LockedNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { deleteItemAsync } from "expo-secure-store";
import { UI_RPC_METHOD_KEYRING_STORE_UNLOCK } from "@coral-xyz/common";
import { useBackgroundClient, useUser } from "@coral-xyz/recoil";
import { MaterialIcons } from "@expo/vector-icons";
import { IconPushDetail } from "~screens/Unlocked/Settings/components/SettingsRow";
import { useForm } from "react-hook-form";
import { useSafeAreaInsets } from "react-native-safe-area-context";

Expand All @@ -31,6 +30,7 @@ import {
WelcomeLogoHeader,
} from "~components/index";
import { useTheme } from "~hooks/useTheme";
import { IconPushDetail } from "~screens/Unlocked/Settings/components/SettingsRow";

const maybeResetApp = () => {
Alert.alert(
Expand Down
Loading