Skip to content

Commit

Permalink
fix account swsitching (#4205)
Browse files Browse the repository at this point in the history
* prevent switching to an account that already selected

* fix wrong icon showing up

* removes memo

* some adujstments

* reset back to localhost

* cleanup and logign

* drawer content view

* push activeUser to the front

* small updates

* delete keys
  • Loading branch information
peterpme authored Jun 22, 2023
1 parent d5c41f1 commit 586af83
Show file tree
Hide file tree
Showing 12 changed files with 382 additions and 193 deletions.
4 changes: 2 additions & 2 deletions packages/app-mobile/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ const getEnvironment = () => {
packageName: "app.backpack.dev",
// graphqlApiUrl: localGraphQLApi,
graphqlApiUrl: remoteGraphQLApi,
// serviceWorkerUrl: 'http://localhost:9333',
serviceWorkerUrl: latestServiceWorkerUrl,
serviceWorkerUrl: "http://localhost:9333",
// serviceWorkerUrl: latestServiceWorkerUrl,
};
};

Expand Down
2 changes: 1 addition & 1 deletion packages/app-mobile/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function App(): JSX.Element {
return (
<ErrorBoundary fallbackRender={renderError}>
<BackgroundHiddenWebView />
<Suspense fallback={<FullScreenLoading label="loading recoil..." />}>
<Suspense fallback={<FullScreenLoading />}>
<RecoilRoot>
<Main />
</RecoilRoot>
Expand Down
39 changes: 39 additions & 0 deletions packages/app-mobile/src/components/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ import {
} from "@coral-xyz/tamagui";

import {
IconCheckmark,
ArrowRightIcon,
IconCheckmarkBold,
WarningIcon,
} from "~components/Icon";
import { PriceChangePill } from "~components/Pill";
import { Avatar } from "~components/UserAvatar";
import { BlockchainLogo } from "~components/index";
import { SettingsRow } from "~screens/Unlocked/Settings/components/SettingsRow";

export {
_ListItemOneLine,
Expand Down Expand Up @@ -235,3 +238,39 @@ export function ListItemTokenPrice({
</ListItem>
);
}

const getDetailIcon = (isLoading: boolean, isActive: boolean) => {
if (isLoading) {
return <ActivityIndicator size="small" />;
}

if (isActive) {
return <IconCheckmark size={24} />;
}

return null;
};

export function UserAccountListItem({
uuid,
username,
isActive,
isLoading,
onPress,
}: {
uuid: string;
username: string;
isActive: boolean;
isLoading: boolean;
onPress: (uuid: string) => void;
}): JSX.Element {
const detailIcon = getDetailIcon(isLoading, isActive);
return (
<SettingsRow
icon={<Avatar username={username} size={24} />}
label={`@${username}`}
detailIcon={detailIcon}
onPress={() => onPress(uuid)}
/>
);
}
52 changes: 6 additions & 46 deletions packages/app-mobile/src/components/UserAccountsMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
import type { BottomSheetBackdropProps } from "@gorhom/bottom-sheet";

import { useCallback, useMemo, useRef, useState } from "react";
import {
ScrollView,
Pressable,
Text,
View,
ActivityIndicator,
} from "react-native";
import { ScrollView, Pressable, Text, View } from "react-native";

import { UI_RPC_METHOD_ACTIVE_USER_UPDATE } from "@coral-xyz/common";
import { useAllUsers, useBackgroundClient, useUser } from "@coral-xyz/recoil";
import { BottomSheetBackdrop, BottomSheetModal } from "@gorhom/bottom-sheet";
import { useNavigation } from "@react-navigation/native";
import { useSafeAreaInsets } from "react-native-safe-area-context";

import { ExpandCollapseIcon, IconCheckmark } from "~components/Icon";
import { Screen, Avatar, RoundedContainerGroup } from "~components/index";
import { ExpandCollapseIcon } from "~components/Icon";
import { UserAccountListItem } from "~components/ListItem";
import { Screen, RoundedContainerGroup } from "~components/index";
import { useTheme } from "~hooks/useTheme";
import { SettingsRow } from "~screens/Unlocked/Settings/components/SettingsRow";

// NOTE(peter) not used anymore in lieu of using react navigation modal
export function AccountDropdownHeader(): JSX.Element {
Expand Down Expand Up @@ -95,6 +89,7 @@ export function AccountDropdownHeader(): JSX.Element {
);
}

// used to be used for the user accounts
export function UserAccountMenu({ navigation }): JSX.Element {
const insets = useSafeAreaInsets();

Expand All @@ -111,6 +106,7 @@ export function UserAccountMenu({ navigation }): JSX.Element {
);
}

// deprecated not used anywhere
function UsersList({ onDismiss }: { onDismiss: () => void }): JSX.Element {
const background = useBackgroundClient();
const users = useAllUsers();
Expand Down Expand Up @@ -170,39 +166,3 @@ function UsersList({ onDismiss }: { onDismiss: () => void }): JSX.Element {
</ScrollView>
);
}

const getDetailIcon = (isLoading: boolean, isActive: boolean) => {
if (isLoading) {
return <ActivityIndicator size="small" />;
}

if (isActive) {
return <IconCheckmark size={24} />;
}

return null;
};

export function UserAccountListItem({
uuid,
username,
isActive,
isLoading,
onPress,
}: {
uuid: string;
username: string;
isActive: boolean;
isLoading: boolean;
onPress: (uuid: string) => void;
}): JSX.Element {
const detailIcon = getDetailIcon(isLoading, isActive);
return (
<SettingsRow
icon={<Avatar size={24} />}
label={`@${username}`}
detailIcon={detailIcon}
onPress={() => onPress(uuid)}
/>
);
}
14 changes: 8 additions & 6 deletions packages/app-mobile/src/components/UserAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect, memo } from "react";
import { useState, useEffect } from "react";
import { View, StyleSheet } from "react-native";

import { Image } from "expo-image";
Expand All @@ -14,7 +14,7 @@ const cache = new Map();

// This component exists because our avatars return either SVG or PNG or GIF from 1 endpoint with no extension
// used for any user
export const UserAvatar = memo(function UserAvatar({
export function UserAvatar({
uri,
size = 32,
style,
Expand Down Expand Up @@ -70,7 +70,7 @@ export const UserAvatar = memo(function UserAvatar({
]}
/>
);
});
}

const styles = StyleSheet.create({
container: {
Expand All @@ -81,12 +81,14 @@ const styles = StyleSheet.create({
},
});

export const Avatar = memo(function Avatar({
export function Avatar({
size = 64,
username,
}: {
size?: number;
username?: string;
}): JSX.Element {
const avatarUrl = useAvatarUrl(size);
const avatarUrl = useAvatarUrl(size, username);
const theme = useTheme();
const outerSize = size + 6;

Expand All @@ -103,7 +105,7 @@ export const Avatar = memo(function Avatar({
<UserAvatar size={size} uri={avatarUrl} />
</View>
);
});
}

export const CurrentUserAvatar = ({ size = 64 }: { size?: number }) => (
<Avatar size={size} />
Expand Down
22 changes: 2 additions & 20 deletions packages/app-mobile/src/lib/SessionProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,26 +133,8 @@ export const SessionProvider = ({
params: [],
});

// // TODO: don't manually specify this list of keys
// // ^^ this was done before peter's time so no idea
// const stores = [
// "keyring-store",
// "keyname-store",
// "wallet-data",
// "nav-store7",
// ];
//
// for (const store of stores) {
// try {
// await SecureStore.deleteItemAsync(store);
// } catch (err) {
// console.error(err);
// // ignore
// }
// }

// lockKeystore();
}, [background]);
lockKeystore();
}, [background, lockKeystore]);

const contextValue = useMemo(
() => ({
Expand Down
66 changes: 41 additions & 25 deletions packages/app-mobile/src/navigation/GlobalDrawerContent.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useState } from "react";
import { Alert, Pressable } from "react-native";

import Constants from "expo-constants";

import {
UI_RPC_METHOD_ACTIVE_USER_UPDATE,
UI_RPC_METHOD_KEYRING_STORE_LOCK,
Expand All @@ -12,17 +14,17 @@ import {
StyledText,
XStack,
useTheme as useTamaguiTheme,
YStack,
} from "@coral-xyz/tamagui";
import { MaterialIcons } from "@expo/vector-icons";
import {
DrawerContentScrollView,
DrawerItemList,
} from "@react-navigation/drawer";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { DrawerItemList } from "@react-navigation/drawer";
import { FlatList } from "react-native-gesture-handler";

import { UserAccountListItem } from "~components/UserAccountsMenu";
import { UserAccountListItem } from "~components/ListItem";
import { CurrentUserAvatar } from "~components/UserAvatar";

import RNDrawerContentView from "./RNDrawerContentView";

import { useSession } from "~src/lib/SessionProvider";

function Header() {
Expand All @@ -46,6 +48,10 @@ function UserList() {
const { setAppState } = useSession();

const handleUpdateActiveUser = async (uuid: string) => {
if (uuid === user.uuid) {
return;
}

try {
setLoadingId(uuid);
await background.request({
Expand All @@ -64,24 +70,32 @@ function UserList() {
};

const theme = useTamaguiTheme();
const activeUser = users.find((u) => u.uuid === user.uuid);

return (
<Stack jc="flex-start">
<StyledText ml={12} mb={8} size="$xs" color="$baseTextMedEmphasis">
ACCOUNTS ({users.length})
</StyledText>
{users.map(({ username, uuid }: any) => {
return (
<UserAccountListItem
key={uuid}
uuid={uuid}
username={username}
isActive={user.username === username}
isLoading={loadingId === uuid}
onPress={handleUpdateActiveUser}
/>
);
})}
<FlatList
data={[activeUser, ...users.filter((u) => u.uuid !== user.uuid)]}
style={{ marginBottom: 8, maxHeight: 260 }}
keyExtractor={(item) => item.uuid}
showsVerticalScrollIndicator={false}
scrollEnabled={users.length >= 4}
renderItem={({ item: { username, uuid } }) => {
return (
<UserAccountListItem
key={uuid}
uuid={uuid}
username={username}
isActive={user.username === username}
isLoading={loadingId === uuid}
onPress={handleUpdateActiveUser}
/>
);
}}
/>
<Pressable onPress={handlePressAddAccount}>
<XStack ai="center" ml={16}>
<MaterialIcons
Expand Down Expand Up @@ -123,21 +137,23 @@ function UserList() {
}

export function GlobalDrawerContent(props) {
const insets = useSafeAreaInsets();
// SafeAreaView doesn't load immediately which causes screen thrashing
// it will go from 0 to 34 on an iphone x, but only in this global drawer context -_-
const marginBottom = Constants.statusBarHeight >= 53 ? 50 : 16;
return (
<DrawerContentScrollView
<RNDrawerContentView
{...props}
contentContainerStyle={{
style={{
flexGrow: 1,
justifyContent: "space-between",
marginBottom: insets.bottom,
marginBottom,
}}
>
<Stack>
<YStack>
<Header />
<DrawerItemList {...props} />
</Stack>
</YStack>
<UserList />
</DrawerContentScrollView>
</RNDrawerContentView>
);
}
Loading

1 comment on commit 586af83

@vercel
Copy link

@vercel vercel bot commented on 586af83 Jun 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.