ci(release): publish latest release

parent 48a0bb2c
- Onboarding improvements
- Adds fallback support method for opening the side panel on chrome failure
Here are the latest updates:
Native Asset Top Up: Easily access our fiat on ramp feature if you don’t have enough native asset on a network to complete a transaction.
Other changes:
- Various bug fixes and performance improvements
- Improved gas estimation for Send transactions
extension/1.2.1
\ No newline at end of file
mobile/1.32
\ No newline at end of file
import '@tamagui/core/reset.css'
import 'src/app/Global.css'
import { useEffect } from 'react'
import { I18nextProvider, useTranslation } from 'react-i18next'
import { useDispatch } from 'react-redux'
import { RouterProvider } from 'react-router-dom'
import { PersistGate } from 'redux-persist/integration/react'
import { ExtensionStatsigProvider } from 'src/app/StatsigProvider'
import { GraphqlProvider } from 'src/app/apollo'
import { ErrorElement } from 'src/app/components/ErrorElement'
import { TraceUserProperties } from 'src/app/components/Trace/TraceUserProperties'
import { DappContextProvider } from 'src/app/features/dapp/DappContext'
import { SentryAppNameTag, initializeSentry, sentryCreateHashRouter } from 'src/app/sentry'
import { initExtensionAnalytics } from 'src/app/utils/analytics'
import { getLocalUserId } from 'src/app/utils/storage'
import { getReduxPersistor, getReduxStore } from 'src/store/store'
import { Button, Flex, Image, Text } from 'ui/src'
import { CHROME_LOGO, UNISWAP_LOGO } from 'ui/src/assets'
import { iconSizes, spacing } from 'ui/src/theme'
import Trace from 'uniswap/src/features/telemetry/Trace'
import { ElementName } from 'uniswap/src/features/telemetry/constants'
import { UnitagUpdaterContextProvider } from 'uniswap/src/features/unitags/context'
import i18n from 'uniswap/src/i18n/i18n'
import { ExtensionScreens } from 'uniswap/src/types/screens/extension'
import { logger } from 'utilities/src/logger/logger'
import { ErrorBoundary } from 'wallet/src/components/ErrorBoundary/ErrorBoundary'
import { LocalizationContextProvider } from 'wallet/src/features/language/LocalizationContext'
import { syncAppWithDeviceLanguage } from 'wallet/src/features/language/slice'
import { SharedProvider } from 'wallet/src/provider'
getLocalUserId()
.then((userId) => {
initializeSentry(SentryAppNameTag.Popup, userId)
})
.catch((error) => {
logger.error(error, {
tags: { file: 'PopupApp.tsx', function: 'getLocalUserId' },
})
})
const router = sentryCreateHashRouter([
{
path: '',
element: <PopupContent />,
errorElement: <ErrorElement />,
},
])
function PopupContent(): JSX.Element {
const { t } = useTranslation()
const dispatch = useDispatch()
useEffect(() => {
dispatch(syncAppWithDeviceLanguage())
}, [dispatch])
const searchParams = new URLSearchParams(window.location.search)
const tabId = searchParams.get('tabId')
const windowId = searchParams.get('windowId')
const tabIdNumber = tabId ? Number(tabId) : undefined
const windowIdNumber = windowId ? Number(windowId) : undefined
return (
<Trace logImpression screen={ExtensionScreens.PopupOpenExtension}>
<Flex fill gap="$spacing16" height="100%" px="$spacing24" py="$spacing24">
<Flex row>
<Flex position="relative">
<Image height={iconSizes.icon40} source={UNISWAP_LOGO} width={iconSizes.icon40} />
<Flex
backgroundColor="$surface1"
borderColor="$surface3"
borderRadius={6}
borderWidth={1}
bottom={-spacing.spacing4}
p="$spacing2"
position="absolute"
right={-spacing.spacing4}
>
<Image height={iconSizes.icon12} source={CHROME_LOGO} width={iconSizes.icon12} />
</Flex>
</Flex>
</Flex>
<Flex gap="$spacing4">
<Text color="$neutral1" variant="subheading1">
{t('extension.popup.chrome.title')}
</Text>
<Text color="$neutral2" variant="body2">
{t('extension.popup.chrome.description')}
</Text>
</Flex>
<Flex fill />
<Trace logPress element={ElementName.ExtensionPopupOpenButton}>
<Button
theme="primary"
width="100%"
onPress={async () => {
if (windowIdNumber) {
// eslint-disable-next-line security/detect-non-literal-fs-filename
await chrome.sidePanel.open({ tabId: tabIdNumber, windowId: windowIdNumber })
window.close()
}
}}
>
{t('extension.popup.chrome.button')}
</Button>
</Trace>
</Flex>
</Trace>
)
}
// TODO WALL-4313 - Backup for some broken chrome.sidePanel.open functionality
// Consider removing this once the issue is resolved or leaving as fallback
export default function PopupApp(): JSX.Element {
// initialize analytics on load
useEffect(() => {
initExtensionAnalytics().catch(() => undefined)
}, [])
return (
<Trace>
<PersistGate persistor={getReduxPersistor()}>
<ExtensionStatsigProvider>
<I18nextProvider i18n={i18n}>
<SharedProvider reduxStore={getReduxStore()}>
<ErrorBoundary>
<GraphqlProvider>
<LocalizationContextProvider>
<UnitagUpdaterContextProvider>
<TraceUserProperties />
<DappContextProvider>
<RouterProvider router={router} />
</DappContextProvider>
</UnitagUpdaterContextProvider>
</LocalizationContextProvider>
</GraphqlProvider>
</ErrorBoundary>
</SharedProvider>
</I18nextProvider>
</ExtensionStatsigProvider>
</PersistGate>
</Trace>
)
}
......@@ -36,7 +36,7 @@ export const useExtensionNavigation = (): {
export async function focusOrCreateOnboardingTab(page?: string): Promise<void> {
const extension = await chrome.management.getSelf()
const tabs = await chrome.tabs.query({ url: `chrome-extension://${extension.id}/onboarding.html*` })
const tabs = await chrome.tabs.query({ url: `chrome-extension://${extension.id}/*` })
const tab = tabs[0]
const url = 'onboarding.html#/' + (page ? page : TopLevelRoutes.Onboarding)
......@@ -68,44 +68,6 @@ export async function focusOrCreateOnboardingTab(page?: string): Promise<void> {
})
}
export async function focusOrCreateDappRequestWindow(tabId: number | undefined, windowId: number): Promise<void> {
const extension = await chrome.management.getSelf()
const window = await chrome.windows.getCurrent()
const tabs = await chrome.tabs.query({ url: `chrome-extension://${extension.id}/popup.html*` })
const tab = tabs[0]
// Centering within current window
const height = 410
const width = 330
const top = Math.round((window.top ?? 0) + ((window.height ?? height) - height) / 2)
const left = Math.round((window.left ?? 0) + ((window.width ?? width) - width) / 2)
let url = `popup.html?windowId=${windowId}`
if (tabId) {
url += `&tabId=${tabId}`
}
if (!tab?.id) {
await chrome.windows.create({
url,
type: 'popup',
top,
left,
width,
height,
})
return
}
await chrome.tabs.update(tab.id, {
url,
active: true,
highlighted: true,
})
await chrome.windows.update(tab.windowId, { focused: true, top, left, width, height })
}
/**
* To avoid opening too many tabs while also ensuring that we don't take over the user's active tab,
* we only update the URL of the active tab if it's already in a specific route of the Uniswap interface.
......
......@@ -19,7 +19,6 @@ export const enum SentryAppNameTag {
Onboarding = 'onboarding',
ContentScript = 'content-script',
Background = 'background',
Popup = 'popup',
}
export function initializeSentry(appNameTag: SentryAppNameTag, sentryUserId: string): void {
......
import { focusOrCreateDappRequestWindow } from 'src/app/navigation/utils'
import { logger } from 'utilities/src/logger/logger'
export async function openSidePanel(tabId: number | undefined, windowId: number): Promise<void> {
......@@ -9,10 +8,6 @@ export async function openSidePanel(tabId: number | undefined, windowId: number)
windowId,
})
} catch (error) {
// TODO WALL-4313 - Backup for some broken chrome.sidePanel.open functionality
// Consider removing this once the issue is resolved or leaving as fallback
await focusOrCreateDappRequestWindow(tabId, windowId)
logger.error(error, {
tags: {
file: 'background/background.ts',
......
......@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "Uniswap Extension",
"description": "The Uniswap Extension is a self-custody crypto wallet that's built for swapping.",
"version": "1.2.1",
"version": "1.2.0",
"minimum_chrome_version": "116",
"icons": {
"16": "assets/icon16.png",
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preload" href="assets/fonts/Basel-Book.woff" as="font" type="font/woff" crossorigin />
<link rel="preload" href="assets/fonts/Basel-Medium.woff" as="font" type="font/woff" crossorigin />
<style>
html,
body,
#popup-root {
min-height: 100%;
}
* {
font-family: 'Basel', sans-serif;
box-sizing: border-box;
}
/**
Explicitly load Basel var from public/ so it does not block LCP's critical path.
*/
@font-face {
font-family: 'Basel';
font-weight: 500;
font-style: normal;
font-display: block;
font-named-instance: 'Medium';
src:
url(assets/fonts/Basel-Medium.woff) format('woff');
}
@font-face {
font-family: 'Basel';
font-weight: 400;
font-style: normal;
font-display: block;
font-named-instance: 'Book';
src:
url(assets/fonts/Basel-Book.woff) format('woff');
}
@supports (font-variation-settings: normal) {
* {
font-family: 'Basel', sans-serif;
}
}
html {
font-variant: none;
font-smooth: always;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
}
</style>
<title>Uniswap Extension</title>
</head>
<body>
<div id="popup-root"></div>
<script type="module" src="popup.js"></script>
</body>
</html>
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path="../../../../index.d.ts" />
import { createRoot } from 'react-dom/client'
import { OptionalStrictMode } from 'src/app/components/OptionalStrictMode'
import PopupApp from 'src/app/PopupApp'
import { initializeSentry, SentryAppNameTag } from 'src/app/sentry'
import { getLocalUserId } from 'src/app/utils/storage'
import { initializeReduxStore } from 'src/store/store'
import { logger } from 'utilities/src/logger/logger'
;(globalThis as any).regeneratorRuntime = undefined // eslint-disable-line @typescript-eslint/no-explicit-any
// The globalThis.regeneratorRuntime = undefined addresses a potentially unsafe-eval problem
// see https://github.com/facebook/regenerator/issues/378#issuecomment-802628326
getLocalUserId()
.then((userId) => {
initializeSentry(SentryAppNameTag.Popup, userId)
})
.catch((error) => {
logger.error(error, {
tags: { file: 'popup.tsx', function: 'getLocalUserId' },
})
})
async function initPopup(): Promise<void> {
await initializeReduxStore({ readOnly: true })
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const container = document.getElementById('popup-root')!
const root = createRoot(container)
root.render(
<OptionalStrictMode>
<PopupApp />
</OptionalStrictMode>,
)
}
initPopup().catch((error) => {
logger.error(error, {
tags: {
file: 'popup.tsx',
function: 'initPopup',
},
})
})
......@@ -58,7 +58,7 @@ const setupStore = (preloadedState?: PreloadedState<ExtensionState>): ReturnType
let store: ReturnType<typeof setupStore> | undefined
let persistor: ReturnType<typeof persistStore> | undefined
export async function initializeReduxStore(args?: { readOnly?: boolean }): Promise<{
export async function initializeReduxStore(): Promise<{
store: ReturnType<typeof setupStore>
persistor: ReturnType<typeof persistStore>
}> {
......@@ -69,12 +69,6 @@ export async function initializeReduxStore(args?: { readOnly?: boolean }): Promi
store = setupStore(oldStore)
persistor = persistStore(store)
if (args?.readOnly) {
// This means the store will be initialized with the persisted state from disk, but it won't persist any changes.
// Only useful for use cases where we don't want to modify the state (for example, a popup window instead of the sidebar).
persistor.pause()
}
// We wait a few seconds to make sure the store is fully initialized and persisted before deleting the old storage.
// This is needed because otherwise the background script might think the user is not onboarded if it reads the storage while it's being migrated.
if (oldStore) {
......
......@@ -172,7 +172,6 @@ module.exports = (env) => {
sidebar: './src/sidebar/sidebar.tsx',
injected: './src/contentScript/injected.ts',
ethereum: './src/contentScript/ethereum.ts',
popup: './src/popup/popup.tsx',
},
output: {
filename: '[name].js',
......
......@@ -93,8 +93,7 @@ if (!__DEV__ && !isDetoxBuild) {
environment: getSentryEnvironment(),
dsn: config.sentryDsn,
attachViewHierarchy: true,
// DataDog would do this for us now
enableCaptureFailedRequests: false,
enableCaptureFailedRequests: true,
tracesSampleRate: getSentryTracesSamplingRate(),
integrations: [
new Sentry.ReactNativeTracing({
......@@ -175,26 +174,24 @@ function App(): JSX.Element | null {
return (
<StatsigProvider {...statSigOptions}>
<DatadogProviderWrapper>
<Trace>
<StrictMode>
<I18nextProvider i18n={i18n}>
<SentryTags>
<SafeAreaProvider>
<SharedProvider reduxStore={store}>
<AnalyticsNavigationContextProvider
shouldLogScreen={shouldLogScreen}
useIsPartOfNavigationTree={useIsPartOfNavigationTree}
>
<AppOuter />
</AnalyticsNavigationContextProvider>
</SharedProvider>
</SafeAreaProvider>
</SentryTags>
</I18nextProvider>
</StrictMode>
</Trace>
</DatadogProviderWrapper>
<Trace>
<StrictMode>
<I18nextProvider i18n={i18n}>
<SentryTags>
<SafeAreaProvider>
<SharedProvider reduxStore={store}>
<AnalyticsNavigationContextProvider
shouldLogScreen={shouldLogScreen}
useIsPartOfNavigationTree={useIsPartOfNavigationTree}
>
<AppOuter />
</AnalyticsNavigationContextProvider>
</SharedProvider>
</SafeAreaProvider>
</SentryTags>
</I18nextProvider>
</StrictMode>
</Trace>
</StatsigProvider>
)
}
......@@ -248,38 +245,40 @@ function AppOuter(): JSX.Element | null {
<ApolloProvider client={client}>
<PersistGate loading={null} persistor={persistor}>
<ErrorBoundary>
<LocalizationContextProvider>
<GestureHandlerRootView style={flexStyles.fill}>
<WalletContextProvider>
<UnitagUpdaterContextProvider>
<BiometricContextProvider>
<LockScreenContextProvider>
<Sentry.TouchEventBoundary>
<DataUpdaters />
<NavigationContainer
onReady={(navigationRef): void => {
routingInstrumentation.registerNavigationContainer(navigationRef)
}}
>
<MobileWalletNavigationProvider>
<OpenAIContextProvider>
<BottomSheetModalProvider>
<AppModals />
<PerformanceProfiler onReportPrepared={onReportPrepared}>
<AppInner />
</PerformanceProfiler>
</BottomSheetModalProvider>
<NotificationToastWrapper />
</OpenAIContextProvider>
</MobileWalletNavigationProvider>
</NavigationContainer>
</Sentry.TouchEventBoundary>
</LockScreenContextProvider>
</BiometricContextProvider>
</UnitagUpdaterContextProvider>
</WalletContextProvider>
</GestureHandlerRootView>
</LocalizationContextProvider>
<DatadogProviderWrapper>
<LocalizationContextProvider>
<GestureHandlerRootView style={flexStyles.fill}>
<WalletContextProvider>
<UnitagUpdaterContextProvider>
<BiometricContextProvider>
<LockScreenContextProvider>
<Sentry.TouchEventBoundary>
<DataUpdaters />
<NavigationContainer
onReady={(navigationRef): void => {
routingInstrumentation.registerNavigationContainer(navigationRef)
}}
>
<MobileWalletNavigationProvider>
<OpenAIContextProvider>
<BottomSheetModalProvider>
<AppModals />
<PerformanceProfiler onReportPrepared={onReportPrepared}>
<AppInner />
</PerformanceProfiler>
</BottomSheetModalProvider>
<NotificationToastWrapper />
</OpenAIContextProvider>
</MobileWalletNavigationProvider>
</NavigationContainer>
</Sentry.TouchEventBoundary>
</LockScreenContextProvider>
</BiometricContextProvider>
</UnitagUpdaterContextProvider>
</WalletContextProvider>
</GestureHandlerRootView>
</LocalizationContextProvider>
</DatadogProviderWrapper>
</ErrorBoundary>
</PersistGate>
</ApolloProvider>
......
......@@ -269,7 +269,9 @@ export function AccountSwitcher({ onClose }: { onClose: () => void }): JSX.Eleme
</Button>
</Flex>
</Flex>
<AccountList accounts={accountsWithoutActive} isVisible={modalState.isOpen} onPress={onPressAccount} />
<Flex maxHeight={fullScreenContentHeight / 2}>
<AccountList accounts={accountsWithoutActive} isVisible={modalState.isOpen} onPress={onPressAccount} />
</Flex>
<TouchableArea hapticFeedback mt="$spacing16" onPress={onPressAddWallet}>
<Flex row alignItems="center" gap="$spacing8" ml="$spacing24">
<PlusCircle />
......
......@@ -363,51 +363,57 @@ exports[`AccountSwitcher renders correctly 1`] = `
style={
{
"flexDirection": "column",
"flexShrink": 1,
"maxHeight": NaN,
}
}
>
ExpoLinearGradient
<RCTScrollView
CellRendererComponent={[Function]}
ListHeaderComponent={<React.Fragment />}
bounces={false}
collapsable={false}
data={[]}
getItem={[Function]}
getItemCount={[Function]}
jestAnimatedStyle={
<View
style={
{
"value": {},
"flexDirection": "column",
"flexShrink": 1,
}
}
keyExtractor={[Function]}
keyboardShouldPersistTaps="always"
onContentSizeChange={[Function]}
onLayout={[Function]}
onMomentumScrollBegin={[Function]}
onMomentumScrollEnd={[Function]}
onScroll={[Function]}
onScrollBeginDrag={[Function]}
onScrollEndDrag={[Function]}
removeClippedSubviews={false}
renderItem={[Function]}
scrollEnabled={false}
scrollEventThrottle={16}
sentry-label="VirtualizedList"
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
stickyHeaderIndices={[]}
viewabilityConfigCallbackPairs={[]}
>
<View>
<View
collapsable={false}
onLayout={[Function]}
/>
</View>
</RCTScrollView>
ExpoLinearGradient
ExpoLinearGradient
<RCTScrollView
collapsable={false}
data={[]}
getItem={[Function]}
getItemCount={[Function]}
handlerTag={1}
handlerType="NativeViewGestureHandler"
keyExtractor={[Function]}
onContentSizeChange={[Function]}
onGestureHandlerEvent={[Function]}
onGestureHandlerStateChange={[Function]}
onLayout={[Function]}
onMomentumScrollBegin={[Function]}
onMomentumScrollEnd={[Function]}
onScroll={[Function]}
onScrollBeginDrag={[Function]}
onScrollEndDrag={[Function]}
removeClippedSubviews={false}
renderItem={[Function]}
renderScrollComponent={[Function]}
scrollEventThrottle={0.0001}
stickyHeaderIndices={[]}
viewabilityConfigCallbackPairs={[]}
waitFor={
[
{
"current": null,
},
{
"current": null,
},
]
}
>
<View />
</RCTScrollView>
ExpoLinearGradient
</View>
</View>
<View
cancelable={true}
......
......@@ -2,8 +2,8 @@ import { LinearGradient } from 'expo-linear-gradient'
import { ComponentProps, default as React, useCallback, useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet } from 'react-native'
import { FlatList } from 'react-native-gesture-handler'
import { AccountCardItem } from 'src/components/accounts/AccountCardItem'
import { VirtualizedList } from 'src/components/layout/VirtualizedList'
import { Flex, Text, useSporeColors } from 'ui/src'
import { opacify, spacing } from 'ui/src/theme'
import { PollingInterval } from 'uniswap/src/constants/misc'
......@@ -12,9 +12,6 @@ import { isNonPollingRequestInFlight } from 'wallet/src/data/utils'
import { useAccountList } from 'wallet/src/features/accounts/hooks'
import { Account, AccountType } from 'wallet/src/features/wallet/accounts/types'
// Most screens can fit more but this is set conservatively
const MIN_ACCOUNTS_TO_ENABLE_SCROLL = 5
type AccountListProps = Pick<ComponentProps<typeof AccountCardItem>, 'onPress'> & {
accounts: Account[]
isVisible?: boolean
......@@ -26,7 +23,7 @@ type AccountWithPortfolioValue = {
portfolioValue: number | undefined
}
const ViewOnlyHeader = (): JSX.Element => {
const ViewOnlyHeaderContent = (): JSX.Element => {
const { t } = useTranslation()
return (
<Flex fill px="$spacing24" py="$spacing8">
......@@ -37,6 +34,19 @@ const ViewOnlyHeader = (): JSX.Element => {
)
}
enum AccountListItemType {
SignerHeader,
SignerAccount,
ViewOnlyHeader,
ViewOnlyAccount,
}
type AccountListItem =
| { type: AccountListItemType.SignerHeader }
| { type: AccountListItemType.SignerAccount; account: AccountWithPortfolioValue }
| { type: AccountListItemType.ViewOnlyHeader }
| { type: AccountListItemType.ViewOnlyAccount; account: AccountWithPortfolioValue }
const SignerHeader = (): JSX.Element => {
const { t } = useTranslation()
return (
......@@ -107,6 +117,45 @@ export function AccountList({ accounts, onPress, isVisible }: AccountListProps):
[onPress],
)
const accountsToRender = useMemo(() => {
const items: AccountListItem[] = []
if (hasSignerAccounts) {
items.push({ type: AccountListItemType.SignerHeader })
items.push(...signerAccounts.map((account) => ({ type: AccountListItemType.SignerAccount, account })))
}
if (hasViewOnlyAccounts) {
items.push({ type: AccountListItemType.ViewOnlyHeader })
items.push(...viewOnlyAccounts.map((account) => ({ type: AccountListItemType.ViewOnlyAccount, account })))
}
return items
}, [hasSignerAccounts, hasViewOnlyAccounts, signerAccounts, viewOnlyAccounts])
const renderItem = useCallback(
({ item }: { item: AccountListItem }) => {
switch (item.type) {
case AccountListItemType.SignerHeader:
return <SignerHeader />
case AccountListItemType.ViewOnlyHeader:
return <ViewOnlyHeaderContent />
case AccountListItemType.SignerAccount:
case AccountListItemType.ViewOnlyAccount:
return renderAccountCardItem(item.account)
}
},
[renderAccountCardItem],
)
const keyExtractor = useCallback(
(item: AccountListItem, index: number) =>
item.type === AccountListItemType.SignerAccount || item.type === AccountListItemType.ViewOnlyAccount
? item.account.account.address
: item.type.toString() + index,
[],
)
return (
<Flex shrink>
{/* TODO(MOB-646): attempt to switch gradients to react-native-svg#LinearGradient and avoid new clear color */}
......@@ -116,24 +165,7 @@ export function AccountList({ accounts, onPress, isVisible }: AccountListProps):
start={{ x: 0, y: 1 }}
style={ListSheet.topGradient}
/>
<VirtualizedList
bounces={false}
scrollEnabled={accountsWithPortfolioValue.length >= MIN_ACCOUNTS_TO_ENABLE_SCROLL}
showsVerticalScrollIndicator={false}
>
{hasSignerAccounts && (
<>
<SignerHeader />
{signerAccounts.map(renderAccountCardItem)}
</>
)}
{hasViewOnlyAccounts && (
<>
<ViewOnlyHeader />
{viewOnlyAccounts.map(renderAccountCardItem)}
</>
)}
</VirtualizedList>
<FlatList data={accountsToRender} keyExtractor={keyExtractor} renderItem={renderItem} />
<LinearGradient
colors={[opacify(0, colors.surface1.val), colors.surface1.val]}
end={{ x: 0, y: 1 }}
......
......@@ -11,34 +11,40 @@ exports[`AccountList renders without error 1`] = `
>
ExpoLinearGradient
<RCTScrollView
CellRendererComponent={[Function]}
ListHeaderComponent={
<React.Fragment>
<React.Fragment>
<SignerHeader />
<AccountCardItem
address="0x82D56A352367453f74FC0dC7B071b311da373Fa6"
isPortfolioValueLoading={false}
isViewOnly={false}
onPress={[MockFunction]}
portfolioValue={55}
/>
</React.Fragment>
</React.Fragment>
}
bounces={false}
collapsable={false}
data={[]}
data={
[
{
"type": 0,
},
{
"account": {
"account": {
"address": "0x82D56A352367453f74FC0dC7B071b311da373Fa6",
"backups": [
"cloud",
],
"derivationIndex": 0,
"mnemonicId": "0x82D56A352367453f74FC0dC7B071b311da373Fa6",
"name": "Test Account",
"timeImportedMs": 10,
"type": "signerMnemonic",
},
"isPortfolioValueLoading": false,
"portfolioValue": 55,
},
"type": 1,
},
]
}
getItem={[Function]}
getItemCount={[Function]}
jestAnimatedStyle={
{
"value": {},
}
}
handlerTag={1}
handlerType="NativeViewGestureHandler"
keyExtractor={[Function]}
keyboardShouldPersistTaps="always"
onContentSizeChange={[Function]}
onGestureHandlerEvent={[Function]}
onGestureHandlerStateChange={[Function]}
onLayout={[Function]}
onMomentumScrollBegin={[Function]}
onMomentumScrollEnd={[Function]}
......@@ -47,18 +53,26 @@ exports[`AccountList renders without error 1`] = `
onScrollEndDrag={[Function]}
removeClippedSubviews={false}
renderItem={[Function]}
scrollEnabled={false}
scrollEventThrottle={16}
sentry-label="VirtualizedList"
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
renderScrollComponent={[Function]}
scrollEventThrottle={0.0001}
stickyHeaderIndices={[]}
viewabilityConfigCallbackPairs={[]}
waitFor={
[
{
"current": null,
},
{
"current": null,
},
]
}
>
<View>
<View
collapsable={false}
onFocusCapture={[Function]}
onLayout={[Function]}
style={null}
>
<View
style={
......@@ -88,6 +102,12 @@ exports[`AccountList renders without error 1`] = `
Your other wallets
</Text>
</View>
</View>
<View
onFocusCapture={[Function]}
onLayout={[Function]}
style={null}
>
<View
actions={
[
......
......@@ -377,7 +377,7 @@ function TokenDetails({
chainId={currencyChainId}
currencyId={_currencyId}
onClose={(): void => {
setShowWarningModal(false)
setShowBuyNativeTokenModal(false)
}}
/>
)}
......
......@@ -21,7 +21,6 @@ export const AVATARS_LIGHT = require('./misc/avatars-light.png')
export const AVATARS_DARK = require('./misc/avatars-dark.png')
export const APP_SCREENSHOT_LIGHT = require('./misc/app-screenshot-light.png')
export const APP_SCREENSHOT_DARK = require('./misc/app-screenshot-dark.png')
export const CHROME_LOGO = require('./logos/png/chrome-logo.png')
export const DOT_GRID = require('./misc/dot-grid.png')
export const UNITAGS_BANNER_VERTICAL_LIGHT = require('./graphics/unitags-banner-v-light.png')
export const UNITAGS_BANNER_VERTICAL_DARK = require('./graphics/unitags-banner-v-dark.png')
......
......@@ -2,7 +2,6 @@
// eslint-disable-next-line no-restricted-imports
import { createFont, isWeb } from '@tamagui/core'
import { needsSmallFont } from 'ui/src/utils/needs-small-font'
import { isInterface } from 'utilities/src/platform'
// TODO(EXT-148): remove this type and use Tamagui's FontTokens
export type TextVariantTokens = keyof typeof fonts
......@@ -48,9 +47,9 @@ const MEDIUM_WEIGHT = '500'
const MEDIUM_WEIGHT_WEB = '535'
const defaultWeights = {
book: isInterface ? BOOK_WEIGHT_WEB : BOOK_WEIGHT,
true: isInterface ? BOOK_WEIGHT_WEB : BOOK_WEIGHT,
medium: isInterface ? MEDIUM_WEIGHT_WEB : MEDIUM_WEIGHT,
book: isWeb ? BOOK_WEIGHT_WEB : BOOK_WEIGHT,
true: isWeb ? BOOK_WEIGHT_WEB : BOOK_WEIGHT,
medium: isWeb ? MEDIUM_WEIGHT_WEB : MEDIUM_WEIGHT,
}
export const fonts = {
......
......@@ -19,7 +19,7 @@ import { BottomSheetModalProps } from 'uniswap/src/components/modals/BottomSheet
import { HandleBar } from 'uniswap/src/components/modals/HandleBar'
import Trace from 'uniswap/src/features/telemetry/Trace'
import { useKeyboardLayout } from 'uniswap/src/utils/useKeyboardLayout'
import { isAndroid, isIOS } from 'utilities/src/platform'
import { isIOS } from 'utilities/src/platform'
/**
* (android only)
......@@ -250,8 +250,6 @@ function BottomSheetModalContents({
{...background}
{...backdrop}
ref={modalRef}
// Adds vertical pan gesture activate offset to avoid nested scroll gesture handler conflicts on android
activeOffsetY={isAndroid ? 12 : undefined}
animatedPosition={animatedPosition}
backgroundStyle={backgroundStyle}
containerComponent={containerComponent}
......
......@@ -127,7 +127,6 @@ export const ElementName = {
EmptyStateReceive: 'empty-state-receive',
Enable: 'enable',
EtherscanView: 'etherscan-view',
ExtensionPopupOpenButton: 'extension-popup-open-button',
FiatOnRampTokenSelector: 'fiat-on-ramp-token-selector',
FiatOnRampWidgetButton: 'fiat-on-ramp-widget-button',
FiatOnRampCountryPicker: 'fiat-on-ramp-country-picker',
......
......@@ -258,9 +258,6 @@
"extension.lock.subtitle": "Enter your password to unlock",
"extension.lock.title": "Welcome back",
"extension.network.notSupported": "Unsupported network",
"extension.popup.chrome.button": "Open extension",
"extension.popup.chrome.description": "Complete this action by opening the Uniswap extension.",
"extension.popup.chrome.title": "Continue in Uniswap",
"extension.settings.password.enter.title": "Enter your current password",
"extension.settings.password.error.wrong": "Wrong password",
"extension.settings.password.placeholder": "Current password",
......
......@@ -258,9 +258,6 @@
"extension.lock.subtitle": "Ingresa tu contraseña para desbloquear",
"extension.lock.title": "Bienvenido de nuevo",
"extension.network.notSupported": "Red no compatible",
"extension.popup.chrome.button": "Abrir extensión",
"extension.popup.chrome.description": "Completa esta acción abriendo la extensión de Uniswap.",
"extension.popup.chrome.title": "Continua en Uniswap",
"extension.settings.password.enter.title": "Ingresa tu contraseña actual",
"extension.settings.password.error.wrong": "Contraseña incorrecta",
"extension.settings.password.placeholder": "Contraseña actual",
......
......@@ -258,9 +258,6 @@
"extension.lock.subtitle": "Saisissez votre mot de passe pour déverrouiller",
"extension.lock.title": "Content de vous revoir",
"extension.network.notSupported": "Réseau non pris en charge",
"extension.popup.chrome.button": "Ouvre l'extension",
"extension.popup.chrome.description": "Complète cette action en ouvrant l'extension Uniswap.",
"extension.popup.chrome.title": "Continue sur Uniswap",
"extension.settings.password.enter.title": "Saisissez votre mot de passe actuel",
"extension.settings.password.error.wrong": "Mot de passe incorrect",
"extension.settings.password.placeholder": "Mot de passe actuel",
......
......@@ -6,7 +6,6 @@ export enum HomeTabs {
export enum ExtensionScreens {
Home = 'home',
PopupOpenExtension = 'PopupOpenExtension',
UnsupportedBrowserScreen = 'UnsupportedBrowserScreen'
}
......
......@@ -19,7 +19,7 @@ import { ONBOARDING_LANDING_DARK, ONBOARDING_LANDING_LIGHT, UNISWAP_LOGO } from
import { AnimatedFlex } from 'ui/src/components/layout/AnimatedFlex'
import { useDeviceDimensions } from 'ui/src/hooks/useDeviceDimensions'
import { imageSizes } from 'ui/src/theme'
import { isAndroid, isMobile } from 'utilities/src/platform'
import { isAndroid } from 'utilities/src/platform'
import { ONE_SECOND_MS } from 'utilities/src/time/time'
import { useTimeout } from 'utilities/src/time/timing'
import {
......@@ -355,7 +355,7 @@ export const LandingBackground = ({
if (
// Android Platform.Version is always a number
(isAndroid && typeof Platform.Version === 'number' && Platform.Version < 30) ||
(language !== Language.English && isMobile)
language !== Language.English
) {
return <OnboardingStaticImage />
}
......
......@@ -4,7 +4,6 @@ import { call, put, select, takeLatest } from 'typed-redux-saga'
import i18n from 'uniswap/src/i18n/i18n'
import { getDeviceLocales } from 'utilities/src/device/locales'
import { logger } from 'utilities/src/logger/logger'
import { isMobile } from 'utilities/src/platform'
import {
Language,
Locale,
......@@ -39,9 +38,7 @@ function* appLanguageSaga(action: ReturnType<typeof updateLanguage>) {
logger.warn('language/saga', 'appLanguageSaga', 'Sync of language setting state and i18n instance failed')
}
if (isMobile) {
yield* call(restartAppIfRTL, localeToSet)
}
yield* call(restartAppIfRTL, localeToSet)
}
function getDeviceLanguage(): Language {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment