diff --git a/packages/mobile/android/app/build.gradle b/packages/mobile/android/app/build.gradle
index 8c0ffa385..86deb18c9 100644
--- a/packages/mobile/android/app/build.gradle
+++ b/packages/mobile/android/app/build.gradle
@@ -92,7 +92,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 433
- versionName "4.3.0"
+ versionName "4.4.0"
missingDimensionStrategy 'react-native-camera', 'general'
missingDimensionStrategy 'store', 'play'
}
diff --git a/packages/mobile/ios/ton_keeper.xcodeproj/project.pbxproj b/packages/mobile/ios/ton_keeper.xcodeproj/project.pbxproj
index ed578fecd..360b519f9 100644
--- a/packages/mobile/ios/ton_keeper.xcodeproj/project.pbxproj
+++ b/packages/mobile/ios/ton_keeper.xcodeproj/project.pbxproj
@@ -1056,7 +1056,7 @@
outputFileListPaths = (
);
outputPaths = (
- "$SRCROOT/$PROJECT_NAME/Resources/Generated/R.generated.swift",
+ $SRCROOT/$PROJECT_NAME/Resources/Generated/R.generated.swift,
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
@@ -1298,7 +1298,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 4.3.0;
+ MARKETING_VERSION = 4.4.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -1332,7 +1332,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = 4.3.0;
+ MARKETING_VERSION = 4.4.0;
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
diff --git a/packages/mobile/ios/ton_keeper/SupportingFiles/Info.plist b/packages/mobile/ios/ton_keeper/SupportingFiles/Info.plist
index b2717dd15..47c0122ee 100644
--- a/packages/mobile/ios/ton_keeper/SupportingFiles/Info.plist
+++ b/packages/mobile/ios/ton_keeper/SupportingFiles/Info.plist
@@ -151,8 +151,6 @@
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationPortrait
- UIUserInterfaceStyle
- Dark
UIViewControllerBasedStatusBarAppearance
diff --git a/packages/mobile/package.json b/packages/mobile/package.json
index 3c24d549c..85b3016d8 100644
--- a/packages/mobile/package.json
+++ b/packages/mobile/package.json
@@ -33,7 +33,7 @@
"@expo/react-native-action-sheet": "^4.0.1",
"@gorhom/bottom-sheet": "^4.6.0",
"@rainbow-me/animated-charts": "https://github.com/tonkeeper/react-native-animated-charts#737b1633c41e13da437c8e111c4aedd15bd10558",
- "@react-native-async-storage/async-storage": "^1.15.5",
+ "@react-native-async-storage/async-storage": "^1.23.1",
"@react-native-community/clipboard": "^1.5.1",
"@react-native-community/netinfo": "^9.3.2",
"@react-native-firebase/analytics": "18.5.0",
diff --git a/packages/mobile/src/components/CardsWidget/components/CardsList.tsx b/packages/mobile/src/components/CardsWidget/components/CardsList.tsx
index bf546230a..2a5d5240a 100644
--- a/packages/mobile/src/components/CardsWidget/components/CardsList.tsx
+++ b/packages/mobile/src/components/CardsWidget/components/CardsList.tsx
@@ -5,7 +5,7 @@ import { formatter } from '@tonkeeper/shared/formatter';
import { MainStackRouteNames } from '$navigation';
import { useNavigation } from '@tonkeeper/router';
import { Platform, Text } from 'react-native';
-import { DarkTheme } from '@tonkeeper/uikit/src/styles/themes/dark';
+import { BlueTheme } from '@tonkeeper/uikit/src/styles/themes/blue';
import { CryptoCurrencies } from '$shared/constants';
import { useGetTokenPrice } from '$hooks/useTokenPrice';
import { capitalizeFirstLetter } from '@tonkeeper/shared/utils/date';
@@ -15,11 +15,11 @@ export interface CardsListProps {
}
const colorsForCardIconBackground = [
- DarkTheme.accentGreen,
- DarkTheme.accentOrange,
- DarkTheme.accentBlue,
- DarkTheme.accentRed,
- DarkTheme.accentPurple,
+ BlueTheme.accentGreen,
+ BlueTheme.accentOrange,
+ BlueTheme.accentBlue,
+ BlueTheme.accentRed,
+ BlueTheme.accentPurple,
];
function getColorByFourDigits(fourDigits: string | null | undefined) {
diff --git a/packages/mobile/src/core/AccessConfirmation/AccessConfirmation.tsx b/packages/mobile/src/core/AccessConfirmation/AccessConfirmation.tsx
index 16e1a0da7..316db2832 100644
--- a/packages/mobile/src/core/AccessConfirmation/AccessConfirmation.tsx
+++ b/packages/mobile/src/core/AccessConfirmation/AccessConfirmation.tsx
@@ -24,6 +24,7 @@ import { t } from '@tonkeeper/shared/i18n';
import { tk, vault } from '$wallet';
import { CanceledActionError } from '$core/Send/steps/ConfirmStep/ActionErrors';
import { useBiometrySettings, useWallet } from '@tonkeeper/shared/hooks';
+import { Screen } from '@tonkeeper/uikit';
export const AccessConfirmation: FC = () => {
const route = useRoute();
@@ -215,7 +216,7 @@ export const AccessConfirmation: FC = () => {
}
return (
-
+
{
onBiometryPress={handleBiometry}
/>
-
+
);
};
diff --git a/packages/mobile/src/core/AddWatchOnly/AddWatchOnly.tsx b/packages/mobile/src/core/AddWatchOnly/AddWatchOnly.tsx
index 971956831..616e6a43e 100644
--- a/packages/mobile/src/core/AddWatchOnly/AddWatchOnly.tsx
+++ b/packages/mobile/src/core/AddWatchOnly/AddWatchOnly.tsx
@@ -152,8 +152,8 @@ export const AddWatchOnly: FC = () => {
const { spacerStyle } = useReanimatedKeyboardHeight();
return (
-
-
+
+
diff --git a/packages/mobile/src/core/AddressUpdateInfo/AddressUpdateInfo.tsx b/packages/mobile/src/core/AddressUpdateInfo/AddressUpdateInfo.tsx
index d881bf55d..7f99d9881 100644
--- a/packages/mobile/src/core/AddressUpdateInfo/AddressUpdateInfo.tsx
+++ b/packages/mobile/src/core/AddressUpdateInfo/AddressUpdateInfo.tsx
@@ -3,8 +3,7 @@ import { Spacer } from '$uikit';
import { Address } from '@tonkeeper/core';
import { t } from '@tonkeeper/shared/i18n';
import { tk } from '$wallet';
-import { Pressable, Screen, Steezy, Text, View } from '@tonkeeper/uikit';
-import { DarkTheme } from '@tonkeeper/uikit/src/styles/themes/dark';
+import { Pressable, Screen, Steezy, Text, View, useTheme } from '@tonkeeper/uikit';
import React, { FC } from 'react';
import { Platform } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
@@ -34,9 +33,11 @@ export const AddressUpdateInfo: FC = () => {
const oldStyle = splitAddress(oldAddress);
const newStyle = splitAddress(newAddress);
+ const theme = useTheme();
+
return (
-
-
+
+
@@ -51,8 +52,8 @@ export const AddressUpdateInfo: FC = () => {
{t('address_update.your_wallet')}
copyText(oldAddress)}
>
@@ -71,8 +72,8 @@ export const AddressUpdateInfo: FC = () => {
copyText(newAddress)}
>
diff --git a/packages/mobile/src/core/App.tsx b/packages/mobile/src/core/App.tsx
index 202f13b14..db72319ce 100644
--- a/packages/mobile/src/core/App.tsx
+++ b/packages/mobile/src/core/App.tsx
@@ -1,10 +1,17 @@
import React from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { Provider as StoreProvider, useSelector } from 'react-redux';
-import { ThemeProvider } from 'styled-components/native';
+import { ThemeProvider as StyledThemeProvider } from 'styled-components/native';
import { store } from '$store';
-import { AppearanceAccents, DarkTheme, TonTheme } from '$styled';
+import {
+ AccentKey,
+ AppearanceAccents,
+ BlueTheme,
+ DarkTheme,
+ LightTheme,
+ TonTheme,
+} from '$styled';
import { AppNavigator } from '$navigation/AppNavigator';
import { ScrollPositionProvider } from '$uikit';
import { useMemo } from 'react';
@@ -19,24 +26,70 @@ import { HideableAmountProvider } from '$core/HideableAmount/HideableAmountProvi
import { queryClient } from '@tonkeeper/shared/queryClient';
import { WalletProvider } from '../context';
-import { BlockingLoaderView } from '@tonkeeper/uikit';
+import { BlockingLoaderView, ThemeName, ThemeProvider } from '@tonkeeper/uikit';
+import { getThemeByName } from '@tonkeeper/uikit/src/styles/utils';
+import { useThemeName } from '$hooks/useThemeName';
+
+const getLegacyThemeByName = (name: ThemeName): TonTheme => {
+ const uikitTheme = getThemeByName(name);
+
+ if (name === ThemeName.Dark) {
+ return { ...DarkTheme, colors: { ...DarkTheme.colors, ...uikitTheme } };
+ }
+
+ if (name === ThemeName.Light) {
+ return { ...LightTheme, colors: { ...LightTheme.colors, ...uikitTheme } };
+ }
+
+ return { ...BlueTheme, colors: { ...BlueTheme.colors, ...uikitTheme } };
+};
const TonThemeProvider = ({ children }) => {
const accent = useSelector(accentSelector);
+ const themeName = useThemeName();
+
+ const accentColors =
+ accent !== AccentKey.default ? AppearanceAccents[accent].colors : undefined;
+
+ const uiThemeAccentColors = useMemo(() => {
+ if (!accentColors) {
+ return {};
+ }
+ return {
+ textAccent: accentColors.accentPrimary,
+ buttonPrimaryBackground: accentColors.accentPrimary,
+ buttonPrimaryBackgroundDisabled: accentColors.accentPrimaryLight,
+ buttonPrimaryBackgroundHighlighted: accentColors.accentPrimaryDark,
+ fieldActiveBorder: accentColors.accentPrimary,
+ accentBlue: accentColors.accentPrimary,
+ tabBarActiveIcon: accentColors.accentPrimary,
+ };
+ }, [accentColors]);
+
+ const uitheme = useMemo(
+ () => ({ ...getThemeByName(themeName), ...uiThemeAccentColors }),
+ [themeName, uiThemeAccentColors],
+ );
- const accentColors = AppearanceAccents[accent].colors;
+ const legacyTheme = useMemo(() => getLegacyThemeByName(themeName), [themeName]);
const theme = useMemo(
(): TonTheme => ({
- ...DarkTheme,
- colors: { ...DarkTheme.colors, ...accentColors },
+ ...legacyTheme,
+ colors: {
+ ...legacyTheme.colors,
+ ...accentColors,
+ ...uiThemeAccentColors,
+ },
}),
- [accentColors],
+ [accentColors, legacyTheme, uiThemeAccentColors],
);
return (
- {children}
+
+ {children}
+
);
};
diff --git a/packages/mobile/src/core/BuyFiat/BuyFiat.tsx b/packages/mobile/src/core/BuyFiat/BuyFiat.tsx
index a12a0182c..5640f5964 100644
--- a/packages/mobile/src/core/BuyFiat/BuyFiat.tsx
+++ b/packages/mobile/src/core/BuyFiat/BuyFiat.tsx
@@ -16,6 +16,7 @@ import { trackEvent } from '$utils/stats';
import { useWallet, useWalletCurrency } from '@tonkeeper/shared/hooks';
import { config } from '$config';
import { tk } from '$wallet';
+import { useTheme } from '@tonkeeper/uikit';
export const BuyFiat: FC = ({ route }) => {
const currency = route.params.currency;
@@ -141,6 +142,8 @@ export const BuyFiat: FC = ({ route }) => {
}, 500);
}, []);
+ const theme = useTheme();
+
return (
{renderHeader()}
@@ -163,7 +166,7 @@ export const BuyFiat: FC = ({ route }) => {
thirdPartyCookiesEnabled={true}
onNavigationStateChange={handleNavigationChange}
allowFileAccess
- forceDarkOn={methodId !== 'onramp'}
+ forceDarkOn={theme.isDark && methodId !== 'onramp'}
allowsInlineMediaPlayback
allowsFullscreenVideo
keyboardDisplayRequiresUserAction={false}
diff --git a/packages/mobile/src/core/Colectibles/NFTCardItem.tsx b/packages/mobile/src/core/Colectibles/NFTCardItem.tsx
index adade1249..44d1f6811 100644
--- a/packages/mobile/src/core/Colectibles/NFTCardItem.tsx
+++ b/packages/mobile/src/core/Colectibles/NFTCardItem.tsx
@@ -1,6 +1,6 @@
import { t } from '@tonkeeper/shared/i18n';
import { openNFT } from '$navigation';
-import { DarkTheme, Steezy } from '$styles';
+import { Steezy } from '$styles';
import { Icon, Pressable, View } from '$uikit';
import { checkIsTonDiamondsNFT } from '$utils';
import { useFlags } from '$utils/flags';
@@ -12,6 +12,7 @@ import { AnimationDirection, HideableAmount } from '$core/HideableAmount/Hideabl
import { HideableImage } from '$core/HideableAmount/HideableImage';
import { Address } from '@tonkeeper/shared/Address';
import { DNS, KnownTLDs } from '@tonkeeper/core';
+import { useTheme } from '@tonkeeper/uikit';
interface NFTCardItemProps {
item: any;
@@ -46,10 +47,12 @@ export const NFTCardItem = memo((props) => {
const nftRawAddress = useMemo(() => Address.parse(item.address).toRaw(), []);
+ const theme = useTheme();
+
return (
@@ -60,7 +63,7 @@ export const NFTCardItem = memo((props) => {
{isTonDiamondsNft && !flags.disable_apperance ? (
-
+
) : null}
@@ -122,6 +125,6 @@ const styles = Steezy.create(({ colors, corners }) => ({
height: '100%',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
- background: DarkTheme.backgroundTertiary,
+ background: colors.backgroundTertiary,
},
}));
diff --git a/packages/mobile/src/core/CreatePin/CreatePin.tsx b/packages/mobile/src/core/CreatePin/CreatePin.tsx
index 07c69aa1f..6b392beea 100644
--- a/packages/mobile/src/core/CreatePin/CreatePin.tsx
+++ b/packages/mobile/src/core/CreatePin/CreatePin.tsx
@@ -9,7 +9,7 @@ import { CreatePinForm } from '$shared/components';
import { tk } from '$wallet';
import { popToTop } from '$navigation/imperative';
import { useParams } from '@tonkeeper/router/src/imperative';
-import { BlockingLoader } from '@tonkeeper/uikit';
+import { BlockingLoader, Screen } from '@tonkeeper/uikit';
export const CreatePin: FC = () => {
const params = useParams<{ isImport?: boolean }>();
@@ -44,9 +44,11 @@ export const CreatePin: FC = () => {
);
return (
-
-
-
-
+
+
+
+
+
+
);
};
diff --git a/packages/mobile/src/core/CustomizeWallet/CustomizeWallet.tsx b/packages/mobile/src/core/CustomizeWallet/CustomizeWallet.tsx
index a12a629a1..fdb3f146b 100644
--- a/packages/mobile/src/core/CustomizeWallet/CustomizeWallet.tsx
+++ b/packages/mobile/src/core/CustomizeWallet/CustomizeWallet.tsx
@@ -39,6 +39,8 @@ import LinearGradient from 'react-native-linear-gradient';
import { RouteProp } from '@react-navigation/native';
import { AppStackParamList } from '$navigation/AppStack';
import { AppStackRouteNames } from '$navigation';
+import { convertHexToRGBA } from '$utils';
+import { useThemeName } from '$hooks/useThemeName';
const COLORS_LIST = Object.values(WalletColor);
@@ -57,6 +59,7 @@ export const CustomizeWallet: FC = memo((props) => {
const wallet = useWallet();
const nav = useNavigation();
const theme = useTheme();
+ const themeName = useThemeName();
const [name, setName] = useState(
identifiers.length > 1 ? wallet.config.name.slice(0, -5) : wallet.config.name,
@@ -133,7 +136,7 @@ export const CustomizeWallet: FC = memo((props) => {
}, []);
return (
-
+
@@ -161,10 +164,15 @@ export const CustomizeWallet: FC = memo((props) => {
-
+
@@ -189,7 +197,7 @@ export const CustomizeWallet: FC = memo((props) => {
{color === selectedColor ? (
@@ -207,7 +215,10 @@ export const CustomizeWallet: FC = memo((props) => {
({
width: 30,
height: 30,
borderRadius: 30 / 2,
- borderColor: colors.backgroundPage,
+ borderColor: colors.backgroundPageAlternate,
borderWidth: 5,
},
buttonContainer: {
diff --git a/packages/mobile/src/core/CustomizeWallet/EmojiPicker/EmojiPicker.tsx b/packages/mobile/src/core/CustomizeWallet/EmojiPicker/EmojiPicker.tsx
index 8a14f9842..9beb17c8d 100644
--- a/packages/mobile/src/core/CustomizeWallet/EmojiPicker/EmojiPicker.tsx
+++ b/packages/mobile/src/core/CustomizeWallet/EmojiPicker/EmojiPicker.tsx
@@ -1,6 +1,6 @@
-import { isAndroid } from '$utils';
+import { changeAlphaValue, convertHexToRGBA, isAndroid } from '$utils';
import { FlashList } from '@shopify/flash-list';
-import { Steezy, View, WalletIcon, ns } from '@tonkeeper/uikit';
+import { Steezy, View, WalletIcon, ns, useTheme } from '@tonkeeper/uikit';
import { WALLET_ICONS } from '@tonkeeper/uikit/src/utils/walletIcons';
import React, { memo, useCallback } from 'react';
import { TouchableOpacity } from 'react-native';
@@ -36,6 +36,10 @@ export const EmojiPicker: React.FC = memo(({ onChange }) => {
[onChange],
);
+ const theme = useTheme();
+
+ const rgbaColor = convertHexToRGBA(theme.backgroundPageAlternate);
+
return (
= memo(({ onChange }) => {
/>
@@ -136,6 +106,6 @@ const styles = Steezy.create(({ colors }) => ({
left: 0,
right: 0,
height: 20,
- backgroundColor: colors.backgroundPage,
+ backgroundColor: colors.backgroundPageAlternate,
},
}));
diff --git a/packages/mobile/src/core/DAppBrowser/DAppBrowser.tsx b/packages/mobile/src/core/DAppBrowser/DAppBrowser.tsx
index 53093a6c5..7fae81bef 100644
--- a/packages/mobile/src/core/DAppBrowser/DAppBrowser.tsx
+++ b/packages/mobile/src/core/DAppBrowser/DAppBrowser.tsx
@@ -2,7 +2,7 @@ import { useDeeplinking } from '$libs/deeplinking';
import { openDAppsSearch } from '$navigation';
import { getCorrectUrl, getSearchQuery, getUrlWithoutTonProxy } from '$utils';
import React, { FC, memo, useCallback, useState } from 'react';
-import { Linking, useWindowDimensions } from 'react-native';
+import { Linking, StatusBar, useWindowDimensions } from 'react-native';
import { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
import {
ShouldStartLoadRequest,
@@ -16,6 +16,7 @@ import { useDAppBridge } from './hooks/useDAppBridge';
import { useWallet } from '@tonkeeper/shared/hooks';
import { Address } from '@tonkeeper/shared/Address';
import { config } from '$config';
+import { Screen, isIOS } from '@tonkeeper/uikit';
export interface DAppBrowserProps {
url: string;
@@ -144,7 +145,8 @@ const DAppBrowserComponent: FC = (props) => {
}, [currentUrl, initialUrl, openUrl]);
return (
-
+
+ {isIOS ? : null}
= (props) => {
/>
-
+
);
};
diff --git a/packages/mobile/src/core/DAppBrowser/components/BrowserNavBar/BrowserNavBar.style.ts b/packages/mobile/src/core/DAppBrowser/components/BrowserNavBar/BrowserNavBar.style.ts
index 52f26393c..3651d22af 100644
--- a/packages/mobile/src/core/DAppBrowser/components/BrowserNavBar/BrowserNavBar.style.ts
+++ b/packages/mobile/src/core/DAppBrowser/components/BrowserNavBar/BrowserNavBar.style.ts
@@ -76,7 +76,7 @@ export const ActionsContainer = styled.View`
flex-direction: row;
flex: 1;
height: ${ns(32)}px;
- background: ${({ theme }) => theme.colors.backgroundSecondary};
+ background: ${({ theme }) => theme.colors.buttonSecondaryBackground};
border-radius: ${ns(16)}px;
overflow: hidden;
`;
@@ -101,7 +101,7 @@ export const ActionItemContent = styled.View`
export const ActionsDivider = styled.View`
width: 1px;
margin: ${ns(8)}px 0;
- background: ${({ theme }) => theme.colors.backgroundTertiary};
+ background: ${({ theme }) => theme.colors.separatorCommon};
`;
export const BackButtonTouchable = styled.TouchableOpacity.attrs({
@@ -109,7 +109,7 @@ export const BackButtonTouchable = styled.TouchableOpacity.attrs({
})``;
export const BackButton = styled.View`
- background: ${({ theme }) => theme.colors.backgroundSecondary};
+ background: ${({ theme }) => theme.colors.buttonSecondaryBackground};
width: ${ns(32)}px;
height: ${ns(32)}px;
border-radius: ${ns(32 / 2)}px;
diff --git a/packages/mobile/src/core/DAppsCategory/DAppsCategory.tsx b/packages/mobile/src/core/DAppsCategory/DAppsCategory.tsx
index cb3e7963a..9e6f4b90d 100644
--- a/packages/mobile/src/core/DAppsCategory/DAppsCategory.tsx
+++ b/packages/mobile/src/core/DAppsCategory/DAppsCategory.tsx
@@ -58,11 +58,12 @@ const DAppsCategoryComponent: FC = (props) => {
export const DAppsCategory = memo(DAppsCategoryComponent);
-const styles = Steezy.create(() => ({
+const styles = Steezy.create(({ colors }) => ({
contentContainerStyle: {
paddingBottom: 0,
},
searchBarContainer: {
+ backgroundColor: colors.backgroundPageAlternate,
padding: 16,
position: 'relative',
},
diff --git a/packages/mobile/src/core/DAppsExplore/DAppsExplore.tsx b/packages/mobile/src/core/DAppsExplore/DAppsExplore.tsx
index ccaffa18b..0f7931c0f 100644
--- a/packages/mobile/src/core/DAppsExplore/DAppsExplore.tsx
+++ b/packages/mobile/src/core/DAppsExplore/DAppsExplore.tsx
@@ -19,7 +19,7 @@ import {
AppsCategory,
} from './components';
import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import { Screen, SegmentedControl, Steezy, View } from '@tonkeeper/uikit';
+import { Screen, SegmentedControl, Spacer, Steezy, View } from '@tonkeeper/uikit';
import { shallow } from 'zustand/shallow';
import { BrowserStackParamList } from '$navigation/BrowserStack/BrowserStack.interface';
import { t } from '@tonkeeper/shared/i18n';
@@ -109,7 +109,7 @@ const DAppsExploreComponent: FC = () => {
});
return (
-
+
@@ -119,6 +119,7 @@ const DAppsExploreComponent: FC = () => {
/>
}
+ alternateBackground={segmentIndex === 1}
>
setSegmentIndex(segment)}
@@ -147,8 +148,9 @@ const DAppsExploreComponent: FC = () => {
+
-
+
@@ -182,6 +184,7 @@ const styles = Steezy.create(({ colors }) => ({
overflow: 'hidden',
},
searchBarContainer: {
+ backgroundColor: colors.backgroundPageAlternate,
padding: 16,
position: 'relative',
},
diff --git a/packages/mobile/src/core/DAppsExplore/components/FeaturedApps/FeaturedApps.tsx b/packages/mobile/src/core/DAppsExplore/components/FeaturedApps/FeaturedApps.tsx
index 8dfaa19e6..83c9fabb2 100644
--- a/packages/mobile/src/core/DAppsExplore/components/FeaturedApps/FeaturedApps.tsx
+++ b/packages/mobile/src/core/DAppsExplore/components/FeaturedApps/FeaturedApps.tsx
@@ -37,6 +37,7 @@ const CarouselItem = memo(({ metadata }) => {
{metadata.name}
@@ -44,6 +45,7 @@ const CarouselItem = memo(({ metadata }) => {
void;
@@ -10,14 +12,30 @@ interface Props {
const SearchButtonComponent: FC = (props) => {
const { onPress } = props;
+ const containerStyle = Steezy.useStyle(styles.container);
+
return (
-
-
+
+
- {t('browser.search_label')}
-
-
+
+ {t('browser.search_label')}
+
+
);
};
export const SearchButton = memo(SearchButtonComponent);
+
+const styles = Steezy.create(({ colors, corners }) => ({
+ container: {
+ backgroundColor: colors.backgroundContentAlternate,
+ borderRadius: corners.medium,
+ },
+ wrap: {
+ height: 48,
+ paddingHorizontal: 16,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+}));
diff --git a/packages/mobile/src/core/DAppsSearch/components/SearchBar/SearchBar.tsx b/packages/mobile/src/core/DAppsSearch/components/SearchBar/SearchBar.tsx
index 755e0c988..883fab055 100644
--- a/packages/mobile/src/core/DAppsSearch/components/SearchBar/SearchBar.tsx
+++ b/packages/mobile/src/core/DAppsSearch/components/SearchBar/SearchBar.tsx
@@ -51,6 +51,7 @@ const SearchBarComponent: FC = (props) => {
onSubmitEditing={handleSubmit}
selectTextOnFocus={true}
selectionColor={theme.colors.accentPrimary}
+ keyboardAppearance={theme.isDark ? 'dark' : 'light'}
/>
diff --git a/packages/mobile/src/core/HideableAmount/ShowBalance.tsx b/packages/mobile/src/core/HideableAmount/ShowBalance.tsx
index b6890c3c1..78b99613d 100644
--- a/packages/mobile/src/core/HideableAmount/ShowBalance.tsx
+++ b/packages/mobile/src/core/HideableAmount/ShowBalance.tsx
@@ -4,27 +4,51 @@ import { usePrivacyStore } from '$store/zustand/privacy/usePrivacyStore';
import { Steezy } from '$styles';
import { Pressable, View } from '$uikit';
import { Haptics, isAndroid } from '$utils';
-import { DarkTheme } from '$styled';
-import { Text } from '@tonkeeper/uikit';
+import { Icon, Text, useTheme } from '@tonkeeper/uikit';
+import { DangerLevel } from '@tonkeeper/shared/hooks';
+import { useNavigation } from '@tonkeeper/router';
+import { SettingsStackRouteNames } from '$navigation';
+import { BatteryIcon } from '@tonkeeper/shared/components/BatteryIcon/BatteryIcon';
const TouchableComponent = isAndroid ? Pressable : TouchableHighlight;
-export const ShowBalance: React.FC<{ amount: string }> = ({ amount }) => {
+const getColorByDangerLevel = (
+ dangerLevel: DangerLevel,
+): undefined | 'accentOrange' | 'accentRed' => {
+ switch (dangerLevel) {
+ case DangerLevel.Normal:
+ return undefined;
+ case DangerLevel.Medium:
+ return 'accentOrange';
+ case DangerLevel.High:
+ return 'accentRed';
+ }
+};
+
+export const ShowBalance: React.FC<{
+ amount: string;
+ dangerLevel: DangerLevel;
+ isWatchOnly: boolean;
+}> = ({ amount, dangerLevel, isWatchOnly }) => {
const hideAmounts = usePrivacyStore((state) => state.actions.toggleHiddenAmounts);
const isHidden = usePrivacyStore((state) => state.hiddenAmounts);
+ const nav = useNavigation();
const handleToggleHideAmounts = useCallback(() => {
hideAmounts();
Haptics.impactHeavy();
}, [hideAmounts]);
+ const handleNavigateToBackup = () => nav.navigate(SettingsStackRouteNames.Backup);
+ const theme = useTheme();
+
return (
{isHidden ? (
@@ -34,7 +58,23 @@ export const ShowBalance: React.FC<{ amount: string }> = ({ amount }) => {
) : (
- {amount}
+
+ {amount}
+
+
+ )}
+ {!isWatchOnly && }
+ {dangerLevel !== DangerLevel.Normal && (
+
+
)}
@@ -46,6 +86,7 @@ const styles = Steezy.create(({ colors }) => ({
flexDirection: 'row',
height: 54,
alignItems: 'center',
+ gap: 8,
},
starsContainer: {
height: 40,
@@ -59,4 +100,8 @@ const styles = Steezy.create(({ colors }) => ({
stars: {
paddingTop: 8,
},
+ dangerButton: {
+ paddingTop: 21,
+ paddingBottom: 11,
+ },
}));
diff --git a/packages/mobile/src/core/ImportWallet/ImportWallet.tsx b/packages/mobile/src/core/ImportWallet/ImportWallet.tsx
index 588dd9151..020d5523c 100644
--- a/packages/mobile/src/core/ImportWallet/ImportWallet.tsx
+++ b/packages/mobile/src/core/ImportWallet/ImportWallet.tsx
@@ -13,6 +13,7 @@ import { useImportWallet } from '$hooks/useImportWallet';
import { tk } from '$wallet';
import { ImportWalletInfo } from '$wallet/WalletTypes';
import { DEFAULT_WALLET_VERSION } from '$wallet/constants';
+import { Screen } from '@tonkeeper/uikit';
export const ImportWallet: FC<{
route: RouteProp;
@@ -60,9 +61,11 @@ export const ImportWallet: FC<{
);
return (
-
-
-
-
+
+
+
+
+
+
);
};
diff --git a/packages/mobile/src/core/Jetton/Jetton.style.ts b/packages/mobile/src/core/Jetton/Jetton.style.ts
index 06077fa30..188d4925d 100644
--- a/packages/mobile/src/core/Jetton/Jetton.style.ts
+++ b/packages/mobile/src/core/Jetton/Jetton.style.ts
@@ -122,5 +122,5 @@ export const HeaderViewDetailsButton = styled(TouchableOpacity).attrs({
border-radius: ${ns(32 / 2)}px;
align-items: center;
justify-content: center;
- background: ${({ theme }) => theme.colors.backgroundSecondary};
+ background: ${({ theme }) => theme.colors.buttonSecondaryBackground};
`;
diff --git a/packages/mobile/src/core/ModalContainer/AppearanceModal/AppearanceModal.tsx b/packages/mobile/src/core/ModalContainer/AppearanceModal/AppearanceModal.tsx
index 212519c0c..6b50ea522 100644
--- a/packages/mobile/src/core/ModalContainer/AppearanceModal/AppearanceModal.tsx
+++ b/packages/mobile/src/core/ModalContainer/AppearanceModal/AppearanceModal.tsx
@@ -1,6 +1,5 @@
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useDimensions } from '$hooks/useDimensions';
-import { accentSelector } from '$store/main';
import { NFTModel, TonDiamondMetadata } from '$store/models';
import {
AccentKey,
@@ -179,7 +178,6 @@ const AppearanceModal = memo((props) => {
/>
= (props) => {
- const { accents, selectedAccentIndex, isUnavailableAccent, ...buttonProps } = props;
-
- const theme = useTheme();
+ const { accents, selectedAccentIndex, ...buttonProps } = props;
const colors = useMemo(
() => [
@@ -55,16 +52,12 @@ const CustomButtonComponent: FC = (props) => {
default: accent.colors.accentPrimary,
pressed: accent.colors.accentPrimaryLight,
})),
- {
- default: theme.colors.backgroundSecondary,
- pressed: theme.colors.backgroundTertiary,
- },
],
- [accents, theme.colors],
+ [accents],
);
const animation = useDerivedValue(
- () => [...accents.map((_, i) => i === selectedAccentIndex), isUnavailableAccent],
+ () => [...accents.map((_, i) => i === selectedAccentIndex)],
[selectedAccentIndex],
);
const [isPressed, setPressed] = useState(false);
diff --git a/packages/mobile/src/core/NFT/ImageWithTitle/ImageWithTitle.tsx b/packages/mobile/src/core/NFT/ImageWithTitle/ImageWithTitle.tsx
index 119e43b62..3bb9002bf 100644
--- a/packages/mobile/src/core/NFT/ImageWithTitle/ImageWithTitle.tsx
+++ b/packages/mobile/src/core/NFT/ImageWithTitle/ImageWithTitle.tsx
@@ -1,7 +1,7 @@
import React, { useCallback, useMemo } from 'react';
import * as S from './ImageWithTitle.style';
import { ImageWithTitleProps } from '$core/NFT/ImageWithTitle/ImageWithTitle.interface';
-import { Badge, Icon, Separator, ShowMore, Spacer, Text, View } from '$uikit';
+import { Badge, Separator, ShowMore, Spacer, Text, View } from '$uikit';
import { t } from '@tonkeeper/shared/i18n';
import { isIOS, ns } from '$utils';
import Clipboard from '@react-native-community/clipboard';
@@ -9,6 +9,7 @@ import { Toast } from '$store';
import { HideableImage } from '$core/HideableAmount/HideableImage';
import { Steezy } from '$styles';
import { HideableAmount } from '$core/HideableAmount/HideableAmount';
+import { Icon } from '@tonkeeper/uikit';
export const ImageWithTitle: React.FC = ({
uri,
@@ -108,7 +109,7 @@ export const ImageWithTitle: React.FC = ({
: collection || t('nft_unnamed_collection')}
- {isVerified && }
+ {isVerified && }
{description ? (
diff --git a/packages/mobile/src/core/NFT/RenewDomainButton.tsx b/packages/mobile/src/core/NFT/RenewDomainButton.tsx
index 9b15e3815..666b1454e 100644
--- a/packages/mobile/src/core/NFT/RenewDomainButton.tsx
+++ b/packages/mobile/src/core/NFT/RenewDomainButton.tsx
@@ -16,6 +16,7 @@ import { Base64 } from '$utils';
import { Address } from '@tonkeeper/core';
import { useWallet } from '@tonkeeper/shared/hooks';
import { tk } from '$wallet';
+import { Spacer } from '@tonkeeper/uikit';
export type RenewDomainButtonRef = {
renewUpdated: () => void;
@@ -121,6 +122,7 @@ export const RenewDomainButton = forwardRef
{t('dns_renew_valid_caption', { count: days })}
+
);
},
diff --git a/packages/mobile/src/core/NFT/TonDiamondFeature/FeatureButton/FeatureButton.style.ts b/packages/mobile/src/core/NFT/TonDiamondFeature/FeatureButton/FeatureButton.style.ts
index 3edc3eab6..94b6c3ad0 100644
--- a/packages/mobile/src/core/NFT/TonDiamondFeature/FeatureButton/FeatureButton.style.ts
+++ b/packages/mobile/src/core/NFT/TonDiamondFeature/FeatureButton/FeatureButton.style.ts
@@ -1,5 +1,5 @@
import styled from '$styled';
-import { Highlight, Text } from '$uikit';
+import { Highlight } from '$uikit';
import { nfs, ns } from '$utils';
export const Wrap = styled.View`
@@ -23,7 +23,3 @@ export const InnerContainer = styled.View<{ withIcon?: boolean }>`
export const IconContainer = styled.View`
margin-right: ${ns(8)}px;
`;
-
-export const Title = styled(Text).attrs({ variant: 'label2' })`
- color: ${({ theme }) => theme.colors.foregroundPrimary};
-`;
diff --git a/packages/mobile/src/core/NFT/TonDiamondFeature/FeatureButton/FeatureButton.tsx b/packages/mobile/src/core/NFT/TonDiamondFeature/FeatureButton/FeatureButton.tsx
index 0d678f29f..da6ed1b9c 100644
--- a/packages/mobile/src/core/NFT/TonDiamondFeature/FeatureButton/FeatureButton.tsx
+++ b/packages/mobile/src/core/NFT/TonDiamondFeature/FeatureButton/FeatureButton.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import { FeatureButtonProps } from './FeatureButton.interface';
import * as S from './FeatureButton.style';
import { Icon } from '$uikit';
+import { Text } from '@tonkeeper/uikit';
export const FeatureButton: React.FC = (props) => {
const { title, iconName, color, highlightColor, onPress } = props;
@@ -11,14 +12,11 @@ export const FeatureButton: React.FC = (props) => {
- {iconName ? (
-
- ) : null}
+ {iconName ? : null}
- {title}
+
+ {title}
+
diff --git a/packages/mobile/src/core/ScanQR/ScanQR.tsx b/packages/mobile/src/core/ScanQR/ScanQR.tsx
index 50c59e567..4b9bc9cd4 100644
--- a/packages/mobile/src/core/ScanQR/ScanQR.tsx
+++ b/packages/mobile/src/core/ScanQR/ScanQR.tsx
@@ -8,7 +8,7 @@ import {
request,
openSettings,
} from 'react-native-permissions';
-import { Platform } from 'react-native';
+import { Platform, StatusBar } from 'react-native';
import { ScanQRProps } from './ScanQR.interface';
import * as S from './ScanQR.style';
import { Button, Icon, NavBar, Text } from '$uikit';
@@ -32,7 +32,6 @@ export const ScanQR: FC = ({ route }) => {
const scannerRef = useRef(null);
const theme = useTheme();
-
const [isFlashlightOn, setFlashlightOn] = useState(false);
const [isCameraBlocked, setCameraBlocked] = useState(false);
@@ -122,14 +121,11 @@ export const ScanQR: FC = ({ route }) => {
return (
+ {isIOS ? : null}
{isIOS && }
-
+
{isHasPermission && (
@@ -160,7 +156,7 @@ export const ScanQR: FC = ({ route }) => {
textAlign="center"
numberOfLines={1}
allowFontScaling={false}
- color="foregroundPrimary"
+ color="constantLight"
variant="h2"
>
{t('scan_qr_title')}
@@ -207,7 +203,7 @@ export const ScanQR: FC = ({ route }) => {
{isIOS && }
diff --git a/packages/mobile/src/core/Security/Security.tsx b/packages/mobile/src/core/Security/Security.tsx
index 8e704f244..40f48eba3 100644
--- a/packages/mobile/src/core/Security/Security.tsx
+++ b/packages/mobile/src/core/Security/Security.tsx
@@ -9,7 +9,7 @@ import { MainStackRouteNames, openChangePin } from '$navigation';
import { getBiometryName, ns } from '$utils';
import { Toast } from '$store';
import { t } from '@tonkeeper/shared/i18n';
-import { useBiometrySettings, useWallet } from '@tonkeeper/shared/hooks';
+import { useBiometrySettings, useLockSettings, useWallet } from '@tonkeeper/shared/hooks';
import { useNavigation } from '@tonkeeper/router';
import { vault } from '$wallet';
import { Haptics, Switch } from '@tonkeeper/uikit';
@@ -22,6 +22,8 @@ export const Security: FC = () => {
const biometry = useBiometrySettings();
+ const { lockScreenEnabled, toggleLock } = useLockSettings();
+
const handleCopyLockupConfig = useCallback(() => {
try {
Clipboard.setString(JSON.stringify(wallet.getLockupConfig()));
@@ -98,6 +100,19 @@ export const Security: FC = () => {
scrollEventThrottle={16}
>
{renderBiometryToggler()}
+
+ }
+ >
+ {t('security_lock_screen_switch')}
+
+
+
+
+ {t('security_lock_screen_tip')}
+
+
{t('security_change_passcode')}
diff --git a/packages/mobile/src/core/Send/steps/AddressStep/AddressStep.tsx b/packages/mobile/src/core/Send/steps/AddressStep/AddressStep.tsx
index cad9853d0..47786802b 100644
--- a/packages/mobile/src/core/Send/steps/AddressStep/AddressStep.tsx
+++ b/packages/mobile/src/core/Send/steps/AddressStep/AddressStep.tsx
@@ -97,10 +97,11 @@ const AddressStepComponent: FC = (props) => {
if (resolvedDomain === 'aborted') {
return 'aborted';
} else if (resolvedDomain?.wallet?.address) {
+ const isWallet = !!resolvedDomain?.wallet?.account?.is_wallet;
return new TonWeb.Address(resolvedDomain.wallet.address).toString(
true,
true,
- false,
+ !isWallet,
) as string;
}
diff --git a/packages/mobile/src/core/Send/steps/AddressStep/components/AddressInput/AddressInput.tsx b/packages/mobile/src/core/Send/steps/AddressStep/components/AddressInput/AddressInput.tsx
index df6355eaf..8f8abe28d 100644
--- a/packages/mobile/src/core/Send/steps/AddressStep/components/AddressInput/AddressInput.tsx
+++ b/packages/mobile/src/core/Send/steps/AddressStep/components/AddressInput/AddressInput.tsx
@@ -192,7 +192,9 @@ const AddressInputComponent: FC = (props) => {
const preparedAddress =
recipient && (recipient.name || recipient.domain)
- ? Address.parse(recipient.address, { bounceable: false }).toShort()
+ ? Address.parse(recipient.address, {
+ bounceable: Address.isBounceable(recipient.address),
+ }).toShort()
: '';
const isFirstRender = useRef(true);
diff --git a/packages/mobile/src/core/Settings/Settings.tsx b/packages/mobile/src/core/Settings/Settings.tsx
index ba607996e..7aea35bb9 100644
--- a/packages/mobile/src/core/Settings/Settings.tsx
+++ b/packages/mobile/src/core/Settings/Settings.tsx
@@ -25,17 +25,11 @@ import {
openRefillBatteryModal,
} from '$navigation';
import { walletActions } from '$store/wallet';
-import {
- APPLE_STORE_ID,
- GOOGLE_PACKAGE_NAME,
- LargeNavBarHeight,
- IsTablet,
-} from '$shared/constants';
-import { checkIsTonDiamondsNFT, hNs, ns, throttle } from '$utils';
-import { LargeNavBarInteractiveDistance } from '$uikit/LargeNavBar/LargeNavBar';
+import { APPLE_STORE_ID, GOOGLE_PACKAGE_NAME } from '$shared/constants';
+import { checkIsTonDiamondsNFT, throttle } from '$utils';
import { CellSectionItem } from '$shared/components';
import { useFlags } from '$utils/flags';
-import { SearchEngine, useBrowserStore } from '$store';
+import { SearchEngine, ThemeOptions, useAppThemeStore, useBrowserStore } from '$store';
import AnimatedLottieView from 'lottie-react-native';
import { Steezy } from '$styles';
import { i18n, t } from '@tonkeeper/shared/i18n';
@@ -85,6 +79,9 @@ export const Settings: FC = () => {
const searchEngine = useBrowserStore((state) => state.searchEngine);
const setSearchEngine = useBrowserStore((state) => state.actions.setSearchEngine);
+ const selectedTheme = useAppThemeStore((state) => state.selectedTheme);
+ const setSelectedTheme = useAppThemeStore((state) => state.actions.setSelectedTheme);
+
// eslint-disable-next-line react-hooks/exhaustive-deps
const handleAnimateDiamond = useCallback(
throttle(() => {
@@ -152,6 +149,8 @@ export const Settings: FC = () => {
const searchEngineVariants = Object.values(SearchEngine);
+ const themeVariants = Object.values(ThemeOptions);
+
const handleSwitchLanguage = useCallback(() => {
if (Platform.OS === 'android') {
return openSelectLanguage();
@@ -374,6 +373,25 @@ export const Settings: FC = () => {
onPress={handleSecurity}
/>
)}
+ item}
+ width={176}
+ renderItem={(item) => (
+ {t(`settings_theme_names.${item}`)}
+ )}
+ >
+
+ {t(`settings_theme_names.${selectedTheme}`)}
+
+ }
+ title={t('settings_theme')}
+ />
+
= (props) => {
}, [handleDone, identifiers]);
return (
-
+
= (props) => {
onPress={handleDone}
/>
}
+ alternateBackground
/>
diff --git a/packages/mobile/src/core/Staking/Staking.tsx b/packages/mobile/src/core/Staking/Staking.tsx
index dec0220fa..da22d693f 100644
--- a/packages/mobile/src/core/Staking/Staking.tsx
+++ b/packages/mobile/src/core/Staking/Staking.tsx
@@ -18,7 +18,7 @@ import { t } from '@tonkeeper/shared/i18n';
import { Address } from '@tonkeeper/shared/Address';
import { PoolImplementationType } from '@tonkeeper/core/src/TonAPI';
import { CryptoCurrencies, Decimals } from '$shared/constants';
-import { Flash } from '@tonkeeper/uikit';
+import { Flash, Screen } from '@tonkeeper/uikit';
import { Ton } from '$libs/Ton';
import { useBalancesState, useJettons, useStakingState } from '@tonkeeper/shared/hooks';
import { StakingManager, StakingProvider } from '$wallet/managers/StakingManager';
@@ -205,11 +205,10 @@ export const Staking: FC = () => {
);
return (
-
-
+ = () => {
/>
) : null
}
+ />
+ }
+ showsVerticalScrollIndicator={false}
>
- }
- showsVerticalScrollIndicator={false}
- >
-
- {notificationsStore?.showRestakeBanner &&
- notificationsStore?.stakingAddressToMigrateFrom && (
- <>
-
-
- >
- )}
- {!hasActivePools ? (
-
- {t('staking.title_large')}
-
-
- {t('staking.desc_large')}{' '}
-
- {t('staking.learn_more')}
-
-
-
-
- ) : null}
- {hasActivePools ? (
+
+ {notificationsStore?.showRestakeBanner &&
+ notificationsStore?.stakingAddressToMigrateFrom && (
<>
-
- {t('staking.active')}
-
-
- {activePools.map((pool, index) => (
-
- ))}
-
+
>
- ) : null}
- {hasActivePools ? (
+ )}
+ {!hasActivePools ? (
+
+ {t('staking.title_large')}
+
+
+ {t('staking.desc_large')}{' '}
+
+ {t('staking.learn_more')}
+
+
+
+
+ ) : null}
+ {hasActivePools ? (
+ <>
- {t('staking.other')}
+ {t('staking.active')}
- ) : null}
- {data.recommendedList.length > 0 ? (
- <>
-
- {data.recommendedList.map((provider, index) => (
- = 2}>
-
-
- ))}
-
-
- >
- ) : null}
- {data.otherList.length > 0 ? (
- <>
-
- {data.otherList.map((provider, index) => (
+
+ {activePools.map((pool, index) => (
+
+ ))}
+
+
+ >
+ ) : null}
+ {hasActivePools ? (
+
+ {t('staking.other')}
+
+ ) : null}
+ {data.recommendedList.length > 0 ? (
+ <>
+
+ {data.recommendedList.map((provider, index) => (
+ = 2}>
= () => {
highestApy={
highestApyPool && highestApyPool.implementation === provider.id
}
- separator={index < data.otherList.length - 1}
+ message={getEstimateProfitMessage(provider)}
+ separator={index < data.recommendedList.length - 1}
onPress={handleProviderPress}
/>
- ))}
-
-
- >
- ) : null}
-
-
-
-
+
+ ))}
+
+
+ >
+ ) : null}
+ {data.otherList.length > 0 ? (
+ <>
+
+ {data.otherList.map((provider, index) => (
+
+ ))}
+
+
+ >
+ ) : null}
+
+
+
);
};
diff --git a/packages/mobile/src/core/Swap/Swap.style.ts b/packages/mobile/src/core/Swap/Swap.style.ts
index 69c7bf324..47c7e52d8 100644
--- a/packages/mobile/src/core/Swap/Swap.style.ts
+++ b/packages/mobile/src/core/Swap/Swap.style.ts
@@ -30,7 +30,7 @@ export const BackButtonContainer = styled.TouchableOpacity.attrs({
})``;
export const BackButton = styled.View`
- background: ${({ theme }) => theme.colors.backgroundSecondary};
+ background: ${({ theme }) => theme.colors.buttonSecondaryBackground};
height: ${hNs(32)}px;
width: ${ns(32)}px;
border-radius: ${ns(32 / 2)}px;
diff --git a/packages/mobile/src/core/TonConnect/TonConnect.style.ts b/packages/mobile/src/core/TonConnect/TonConnect.style.ts
index d8ce5fb6f..09671d2a5 100644
--- a/packages/mobile/src/core/TonConnect/TonConnect.style.ts
+++ b/packages/mobile/src/core/TonConnect/TonConnect.style.ts
@@ -62,7 +62,7 @@ export const VerticalDivider = styled.View`
`;
export const Logo = styled.View`
- background-color: ${({ theme }) => theme.colors.backgroundSecondary};
+ background-color: #1d2633;
border-radius: ${({ theme }) => theme.radius.large}px;
width: ${ns(72)}px;
height: ${ns(72)}px;
diff --git a/packages/mobile/src/core/TonConnect/TonConnectModal.tsx b/packages/mobile/src/core/TonConnect/TonConnectModal.tsx
index 3bbe8e2c6..4b1b3d098 100644
--- a/packages/mobile/src/core/TonConnect/TonConnectModal.tsx
+++ b/packages/mobile/src/core/TonConnect/TonConnectModal.tsx
@@ -6,6 +6,7 @@ import { Linking, StyleSheet } from 'react-native';
import { useTheme } from '$hooks/useTheme';
import { Button, List, Loader, Spacer, Text, TransitionOpacity } from '$uikit';
import {
+ convertHexToRGBA,
delay,
getDomainFromURL,
triggerNotificationSuccess,
@@ -280,12 +281,15 @@ export const TonConnectModal = (props: TonConnectModalProps) => {
-
+
@@ -308,7 +312,10 @@ export const TonConnectModal = (props: TonConnectModalProps) => {
diff --git a/packages/mobile/src/core/Wallet/Wallet.style.ts b/packages/mobile/src/core/Wallet/Wallet.style.ts
index f7de96af4..23c0bf1ce 100644
--- a/packages/mobile/src/core/Wallet/Wallet.style.ts
+++ b/packages/mobile/src/core/Wallet/Wallet.style.ts
@@ -77,7 +77,7 @@ export const IconWrapper = styled.View`
export const Divider = styled.View`
height: ${ns(0.5)}px;
width: ${deviceWidth}px;
- background: rgba(79, 90, 112, 0.24);
+ background: ${({ theme }) => theme.colors.separatorCommon};
margin-bottom: ${ns(24)}px;
`;
@@ -133,5 +133,5 @@ export const HeaderViewDetailsButton = styled(TouchableOpacity).attrs({
border-radius: ${ns(32 / 2)}px;
align-items: center;
justify-content: center;
- background: ${({ theme }) => theme.colors.backgroundSecondary};
+ background: ${({ theme }) => theme.colors.buttonSecondaryBackground};
`;
diff --git a/packages/mobile/src/core/WebView/WebView.tsx b/packages/mobile/src/core/WebView/WebView.tsx
index 81cb25fb5..cdd249679 100644
--- a/packages/mobile/src/core/WebView/WebView.tsx
+++ b/packages/mobile/src/core/WebView/WebView.tsx
@@ -100,7 +100,7 @@ export const WebView: FC = ({ route }) => {
hideKeyboardAccessoryView
thirdPartyCookiesEnabled={true}
allowFileAccess
- forceDarkOn
+ forceDarkOn={theme.isDark}
allowsInlineMediaPlayback
allowsFullscreenVideo
keyboardDisplayRequiresUserAction={false}
diff --git a/packages/mobile/src/hooks/useThemeName.ts b/packages/mobile/src/hooks/useThemeName.ts
new file mode 100644
index 000000000..de1451253
--- /dev/null
+++ b/packages/mobile/src/hooks/useThemeName.ts
@@ -0,0 +1,38 @@
+import { ThemeOptions, useAppThemeStore } from '$store/zustand/appTheme';
+import { ThemeName } from '@tonkeeper/uikit';
+import { useEffect, useMemo, useState } from 'react';
+import { useColorScheme } from 'react-native';
+
+export const useThemeName = (): ThemeName => {
+ const { selectedTheme } = useAppThemeStore();
+ const colorScheme = useColorScheme();
+ const [systemAppearance, setSystemAppearance] = useState(colorScheme);
+
+ useEffect(() => {
+ const timeout = setTimeout(() => {
+ setSystemAppearance(colorScheme);
+ }, 300);
+
+ return () => {
+ clearTimeout(timeout);
+ };
+ }, [colorScheme]);
+
+ const themeName = useMemo(() => {
+ if (selectedTheme === ThemeOptions.System) {
+ return systemAppearance === 'light' ? ThemeName.Light : ThemeName.Dark;
+ }
+
+ if (selectedTheme === ThemeOptions.Light) {
+ return ThemeName.Light;
+ }
+
+ if (selectedTheme === ThemeOptions.Dark) {
+ return ThemeName.Dark;
+ }
+
+ return ThemeName.Blue;
+ }, [selectedTheme, systemAppearance]);
+
+ return themeName;
+};
diff --git a/packages/mobile/src/modals/ExchangeModal.tsx b/packages/mobile/src/modals/ExchangeModal.tsx
index 7f1653d21..d55622851 100644
--- a/packages/mobile/src/modals/ExchangeModal.tsx
+++ b/packages/mobile/src/modals/ExchangeModal.tsx
@@ -1,11 +1,11 @@
import React, { useCallback, useMemo, useState } from 'react';
-import { Button, Loader, Spacer, View } from '$uikit';
+import { Loader, Spacer, View } from '$uikit';
import * as S from '../core/Exchange/Exchange.style';
import { ExchangeItem } from '../core/Exchange/ExchangeItem/ExchangeItem';
import { t } from '@tonkeeper/shared/i18n';
import { LayoutAnimation } from 'react-native';
-import { Modal, SegmentedControl, Text } from '@tonkeeper/uikit';
+import { Button, Modal, SegmentedControl, Text } from '@tonkeeper/uikit';
import { Steezy } from '$styles';
import { useMethodsToBuyStore } from '$store/zustand/methodsToBuy/useMethodsToBuyStore';
import { CategoryType } from '$store/zustand/methodsToBuy/types';
@@ -124,12 +124,13 @@ export const ExchangeModal = () => {
+ />
) : null}
diff --git a/packages/mobile/src/navigation/AppNavigator.tsx b/packages/mobile/src/navigation/AppNavigator.tsx
index 33f7f47cd..e75fa7b00 100644
--- a/packages/mobile/src/navigation/AppNavigator.tsx
+++ b/packages/mobile/src/navigation/AppNavigator.tsx
@@ -6,8 +6,8 @@ import { StatusBar } from 'react-native';
import { setNavigationRef, onNavigationReady } from './imperative';
import { AppStack } from './MainStack';
import { mainSelector } from '$store/main';
-import { useTheme } from '$hooks/useTheme';
import { ProvidersWithoutNavigation } from './Providers';
+import { isAndroid, useTheme } from '@tonkeeper/uikit';
export const AppNavigator: FC = () => {
const theme = useTheme();
@@ -17,11 +17,11 @@ export const AppNavigator: FC = () => {
() => ({
dark: true,
colors: {
- primary: theme.colors.accentPrimary,
- background: theme.colors.backgroundPrimary,
- card: theme.colors.backgroundPrimary,
- text: theme.colors.constantLight,
- notification: theme.colors.backgroundPrimary,
+ primary: theme.accentBlue,
+ background: theme.backgroundPage,
+ card: theme.backgroundPage,
+ text: theme.textPrimary,
+ notification: theme.backgroundPage,
border: 'none',
},
}),
@@ -40,8 +40,8 @@ export const AppNavigator: FC = () => {
>
diff --git a/packages/mobile/src/navigation/CreateWalletStack/CreateWalletStack.tsx b/packages/mobile/src/navigation/CreateWalletStack/CreateWalletStack.tsx
index 797abf20c..eb3b8a974 100644
--- a/packages/mobile/src/navigation/CreateWalletStack/CreateWalletStack.tsx
+++ b/packages/mobile/src/navigation/CreateWalletStack/CreateWalletStack.tsx
@@ -17,7 +17,7 @@ export const CreateWalletStack = memo(() => {
headerShown: false,
gestureEnabled: true,
contentStyle: {
- backgroundColor: theme.colors.backgroundPrimary,
+ backgroundColor: theme.colors.backgroundPage,
},
fullScreenGestureEnabled: true,
}}
diff --git a/packages/mobile/src/navigation/MainStack/MainStack.tsx b/packages/mobile/src/navigation/MainStack/MainStack.tsx
index 4260e3b72..d09f04240 100644
--- a/packages/mobile/src/navigation/MainStack/MainStack.tsx
+++ b/packages/mobile/src/navigation/MainStack/MainStack.tsx
@@ -1,4 +1,4 @@
-import React, { FC, useMemo } from 'react';
+import React, { FC } from 'react';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { MainStackParamList } from './MainStack.interface';
@@ -24,7 +24,7 @@ import { withModalStack } from '@tonkeeper/router';
import { ToncoinScreen } from '$core/Wallet/ToncoinScreen';
import { InscriptionScreen } from '$core/InscriptionScreen';
import { useDiamondsChecker } from '$hooks/useDiamondsChecker';
-import { useWallet } from '@tonkeeper/shared/hooks';
+import { useLockSettings, useWallet } from '@tonkeeper/shared/hooks';
import {
StartScreen,
HoldersWebView,
@@ -61,12 +61,20 @@ export const MainStack: FC = () => {
const hasWallet = !!wallet;
+ const { lockScreenEnabled } = useLockSettings();
+
+ const shouldObtainTonProof =
+ hasWallet && !wallet.isWatchOnly && !wallet.tonProof.tonProofToken;
+
const showLockScreen =
- tk.lockEnabled && !isUnlocked && hasWallet && !attachedScreen.pathname;
+ (lockScreenEnabled || shouldObtainTonProof) &&
+ !isUnlocked &&
+ hasWallet &&
+ !attachedScreen.pathname;
const isMigrated = useExternalState(tk.migrationStore, (state) => state.isMigrated);
- const root = useMemo(() => {
+ const renderRoot = () => {
if (hasWallet) {
if (showLockScreen) {
return (
@@ -90,7 +98,7 @@ export const MainStack: FC = () => {
}
return ;
- }, [hasWallet, isMigrated, showLockScreen]);
+ };
return (
{
fullScreenGestureEnabled: true,
}}
>
- {root}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ {renderRoot()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/packages/mobile/src/navigation/MainStack/TabStack/TabStack.tsx b/packages/mobile/src/navigation/MainStack/TabStack/TabStack.tsx
index 812f77c1a..3f1bcfd49 100644
--- a/packages/mobile/src/navigation/MainStack/TabStack/TabStack.tsx
+++ b/packages/mobile/src/navigation/MainStack/TabStack/TabStack.tsx
@@ -84,7 +84,11 @@ export const TabStack: FC = () => {
]}
/>
) : (
-
+
{
const nav = useNavigation();
const isValid = useMemo(() => {
- const word1 = values['0'];
- const word2 = values['1'];
- const word3 = values['2'];
+ const word1 = values['0'] ? values['0'].trim() : '';
+ const word2 = values['1'] ? values['1'].trim() : '';
+ const word3 = values['2'] ? values['2'].trim() : '';
return word1 === words[0].word && word2 === words[1].word && word3 === words[2].word;
}, [values, words]);
@@ -72,8 +72,8 @@ export const BackupCheckPhraseScreen = memo(() => {
);
return (
-
-
+
+
& ExtractMediaVars<{ isTablet: unknown }>
+ >;
+}
+
+const defaultSizes: Sizes = {
+ title: 'h2',
+ caption: 'body1',
+ index: 'body2',
+ word: 'body1',
+ styles: Steezy.create({
+ line: {
+ width: 151,
+ flexDirection: 'row',
+ marginBottom: 8,
+ height: 24,
+ },
+ }),
+};
+
+const smallSizes: Sizes = {
+ title: 'h3',
+ caption: 'body2',
+ index: 'body3',
+ word: 'body2',
+ styles: Steezy.create({
+ line: {
+ width: 151,
+ flexDirection: 'row',
+ marginBottom: 4,
+ height: 18,
+ },
+ }),
+};
+
+const sizesConfig = deviceHeight >= 650 ? defaultSizes : smallSizes;
function getRandIndexes(length: number, indexes: number[] = []) {
if (indexes.length === length) {
@@ -23,7 +70,6 @@ function getRandIndexes(length: number, indexes: number[] = []) {
export const BackupPhraseScreen = memo(() => {
const params = useParams<{ mnemonic: string; isBackupAgain?: boolean }>();
- const safeArea = useSafeAreaInsets();
const nav = useNavigation();
const mnemonic = params.mnemonic!;
@@ -39,15 +85,15 @@ export const BackupPhraseScreen = memo(() => {
}, [phrase]);
return (
-
-
+
+
-
+
{t('recovery_phrase.title')}
-
+
{t('recovery_phrase.caption')}
@@ -56,21 +102,32 @@ export const BackupPhraseScreen = memo(() => {
{leftColumn.map((word, index) => (
-
-
+
+
{index + 1}.
- {word}
+ {word}
))}
{rightColumn.map((word, index) => (
-
-
+
+
{index + 1 + 12}.
- {word}
+ {word}
))}
diff --git a/packages/mobile/src/screens/BackupScreen/BackupScreen.tsx b/packages/mobile/src/screens/BackupScreen/BackupScreen.tsx
index d5632b91b..2bbf48667 100644
--- a/packages/mobile/src/screens/BackupScreen/BackupScreen.tsx
+++ b/packages/mobile/src/screens/BackupScreen/BackupScreen.tsx
@@ -4,16 +4,51 @@ import { memo } from 'react';
import { format } from 'date-fns';
import { getLocale } from '$utils/date';
import { i18n, t } from '@tonkeeper/shared/i18n';
-import { useWalletSetup } from '@tonkeeper/shared/hooks';
+import {
+ DangerLevel,
+ useDangerLevel,
+ useWalletCurrency,
+ useWalletSetup,
+} from '@tonkeeper/shared/hooks';
+import { tk } from '$wallet';
+import { formatter } from '@tonkeeper/shared/formatter';
export const BackupScreen = memo(() => {
const { lastBackupAt } = useWalletSetup();
const nav = useNavigation();
+ const currency = useWalletCurrency();
+ const dangerLevel = useDangerLevel(tk.wallet.totalTon);
+
return (
+ {dangerLevel !== DangerLevel.Normal && (
+ <>
+
+
+ {t('backup_screen.backup_warning', {
+ totalFiat: formatter.format(tk.wallet.totalFiat, { currency }),
+ })}
+
+
+
+ >
+ )}
{t('backup_screen.manual_title')}
@@ -27,7 +62,7 @@ export const BackupScreen = memo(() => {
) : (
@@ -48,7 +83,7 @@ export const BackupScreen = memo(() => {
})}
leftContent={
-
+
}
/>
@@ -92,4 +127,16 @@ const styles = Steezy.create(({ colors }) => ({
position: 'absolute',
right: 16,
},
+ dangerBanner: {
+ paddingHorizontal: 16,
+ paddingVertical: 12,
+ marginHorizontal: 16,
+ borderRadius: 16,
+ },
+ dangerBannerYellow: {
+ backgroundColor: colors.accentOrange,
+ },
+ dangerBannerRed: {
+ backgroundColor: colors.accentRed,
+ },
}));
diff --git a/packages/mobile/src/screens/HoldersWebView/HoldersWebView.tsx b/packages/mobile/src/screens/HoldersWebView/HoldersWebView.tsx
index 747da00ce..20cb3f1a4 100644
--- a/packages/mobile/src/screens/HoldersWebView/HoldersWebView.tsx
+++ b/packages/mobile/src/screens/HoldersWebView/HoldersWebView.tsx
@@ -6,7 +6,7 @@ import React, {
useReducer,
useState,
} from 'react';
-import { Steezy } from '@tonkeeper/uikit';
+import { Steezy, useTheme } from '@tonkeeper/uikit';
import WebView from 'react-native-webview';
import {
DappMainButton,
@@ -14,7 +14,6 @@ import {
reduceMainButton,
} from './components/DAppMainButton';
import { BackHandler, KeyboardAvoidingView, Platform, StatusBar } from 'react-native';
-import { DarkTheme } from '@tonkeeper/uikit/src/styles/themes/dark';
import {
createInjectSource,
dispatchMainButtonResponse,
@@ -49,11 +48,12 @@ export interface HoldersWebViewProps {
export const HoldersWebView = memo((props) => {
const navigation = useNavigation();
const safeAreaInsets = useSafeAreaInsets();
+ const theme = useTheme();
const [mainButton, dispatchMainButton] = useReducer(reduceMainButton(), {
text: '',
- textColor: DarkTheme.buttonPrimaryForeground,
- color: DarkTheme.buttonPrimaryBackground,
- disabledColor: DarkTheme.buttonPrimaryBackgroundDisabled,
+ textColor: theme.buttonPrimaryForeground,
+ color: theme.buttonPrimaryBackground,
+ disabledColor: theme.buttonPrimaryBackgroundDisabled,
isVisible: false,
isActive: false,
isProgressVisible: false,
diff --git a/packages/mobile/src/screens/HoldersWebView/components/DAppMainButton.tsx b/packages/mobile/src/screens/HoldersWebView/components/DAppMainButton.tsx
index 81ce56179..19ab3d463 100644
--- a/packages/mobile/src/screens/HoldersWebView/components/DAppMainButton.tsx
+++ b/packages/mobile/src/screens/HoldersWebView/components/DAppMainButton.tsx
@@ -13,7 +13,7 @@ import Animated, {
useDerivedValue,
withTiming,
} from 'react-native-reanimated';
-import { DarkTheme } from '@tonkeeper/uikit/src/styles/themes/dark';
+import { useTheme } from '@tonkeeper/uikit';
export function processMainButtonMessage(
parsed: any,
@@ -134,21 +134,22 @@ export type MainButtonProps = {
export const DappMainButton = React.memo(
(props: { style?: StyleProp } & Omit) => {
+ const theme = useTheme();
const bgColor = useDerivedValue(() => {
return withTiming(
props.isProgressVisible
- ? DarkTheme.buttonPrimaryBackground
+ ? theme.buttonPrimaryBackground
: props.isActive
? props.color
- : props.disabledColor ?? DarkTheme.buttonPrimaryBackground,
+ : props.disabledColor ?? theme.buttonPrimaryBackground,
);
- }, [props.color, props.disabledColor, props.isActive]);
+ }, [props.color, props.disabledColor, props.isActive, theme]);
const textColor = useDerivedValue(() => {
return withTiming(
- props.isProgressVisible ? DarkTheme.buttonPrimaryForeground : props.textColor,
+ props.isProgressVisible ? theme.buttonPrimaryForeground : props.textColor,
);
- }, [props.textColor]);
+ }, [props.textColor, theme]);
const animatedBgStyle = useAnimatedStyle(() => {
return { backgroundColor: bgColor.value };
diff --git a/packages/mobile/src/screens/StartScreen/StartScreen.tsx b/packages/mobile/src/screens/StartScreen/StartScreen.tsx
index 58cc6eecb..b867b02ea 100644
--- a/packages/mobile/src/screens/StartScreen/StartScreen.tsx
+++ b/packages/mobile/src/screens/StartScreen/StartScreen.tsx
@@ -6,10 +6,10 @@ import {
Spacer,
Button,
deviceHeight,
+ useTheme,
+ ThemeName,
} from '@tonkeeper/uikit';
-import Svg, { Path, Defs, LinearGradient, Stop, G, ClipPath } from 'react-native-svg';
-import { useWindowDimensions } from 'react-native';
-import Animated from 'react-native-reanimated';
+import { Image, useWindowDimensions } from 'react-native';
import { memo, useCallback } from 'react';
import { t } from '@tonkeeper/shared/i18n';
import { MainStackRouteNames } from '$navigation';
@@ -19,6 +19,22 @@ import { useNavigation } from '@tonkeeper/router';
import { network } from '@tonkeeper/core';
import { config } from '$config';
import DeviceInfo from 'react-native-device-info';
+import { useThemeName } from '$hooks/useThemeName';
+
+const COVER_BLUE_SOURCE = require('./cover-blue.png');
+const COVER_LIGHT_SOURCE = require('./cover-light.png');
+const COVER_DARK_SOURCE = require('./cover-dark.png');
+
+const getCoverSource = (theme: ThemeName) => {
+ if (theme === ThemeName.Dark) {
+ return COVER_DARK_SOURCE;
+ }
+ if (theme === ThemeName.Light) {
+ return COVER_LIGHT_SOURCE;
+ }
+
+ return COVER_BLUE_SOURCE;
+};
const HEIGHT_RATIO = deviceHeight / 844;
@@ -27,13 +43,6 @@ export const StartScreen = memo(() => {
const dispatch = useDispatch();
const nav = useNavigation();
- const origShapesWidth = 560;
- const origShapesHeight = 494;
- const origShapesScreenHeight = 844;
- const ratioHeight = dimensions.height / origShapesScreenHeight;
- const logoShapesPosX = origShapesWidth / 2 - dimensions.width / 2;
- const logoShapesPosY = origShapesHeight / 2 - (origShapesHeight * ratioHeight) / 2;
-
const unsubscribeNotifications = useCallback(async () => {
// unsubscribe from all notifications, if app was reinstalled
try {
@@ -59,29 +68,18 @@ export const StartScreen = memo(() => {
nav.navigate(MainStackRouteNames.ImportWalletStack);
}, [nav, unsubscribeNotifications]);
+ const themeName = useThemeName();
+
return (
-
+
-
-
-
-
-
+ />
Tonkeeper
@@ -152,186 +150,3 @@ const styles = Steezy.create(({ safeArea }) => ({
zIndex: 1,
},
}));
-
-const LogoShapes = () => (
-
-);
diff --git a/packages/mobile/src/screens/StartScreen/cover-blue.png b/packages/mobile/src/screens/StartScreen/cover-blue.png
new file mode 100644
index 000000000..087ac6ab5
Binary files /dev/null and b/packages/mobile/src/screens/StartScreen/cover-blue.png differ
diff --git a/packages/mobile/src/screens/StartScreen/cover-dark.png b/packages/mobile/src/screens/StartScreen/cover-dark.png
new file mode 100644
index 000000000..f19f1854d
Binary files /dev/null and b/packages/mobile/src/screens/StartScreen/cover-dark.png differ
diff --git a/packages/mobile/src/screens/StartScreen/cover-light.png b/packages/mobile/src/screens/StartScreen/cover-light.png
new file mode 100644
index 000000000..77ddcfb81
Binary files /dev/null and b/packages/mobile/src/screens/StartScreen/cover-light.png differ
diff --git a/packages/mobile/src/shared/components/AmountInput/AmountInput.tsx b/packages/mobile/src/shared/components/AmountInput/AmountInput.tsx
index 434d1fd34..d16f7b6f9 100644
--- a/packages/mobile/src/shared/components/AmountInput/AmountInput.tsx
+++ b/packages/mobile/src/shared/components/AmountInput/AmountInput.tsx
@@ -1,8 +1,6 @@
import { SendAmount } from '$core/Send/Send.interface';
-import { walletWalletSelector } from '$store/wallet';
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { TextInput } from 'react-native-gesture-handler';
-import { useSelector } from 'react-redux';
import BigNumber from 'bignumber.js';
import { formatInputAmount, parseLocaleNumber } from '$utils';
import { cryptoToFiat, fiatToCrypto, trimZeroDecimals } from '$utils/currency';
@@ -243,6 +241,7 @@ const AmountInputComponent: React.FC = (props) => {
onChangeText={handleChangeAmount}
onLayout={handleInputLayout}
returnKeyType="next"
+ keyboardAppearance={theme.isDark ? 'dark' : 'light'}
/>
{value}
diff --git a/packages/mobile/src/shared/components/BottomButtonWrap/BottomButtonWrap.tsx b/packages/mobile/src/shared/components/BottomButtonWrap/BottomButtonWrap.tsx
index 6d0efab67..d66632f72 100644
--- a/packages/mobile/src/shared/components/BottomButtonWrap/BottomButtonWrap.tsx
+++ b/packages/mobile/src/shared/components/BottomButtonWrap/BottomButtonWrap.tsx
@@ -1,7 +1,7 @@
import React, { FC, ReactNode } from 'react';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
-import { ns } from '$utils';
+import { convertHexToRGBA, ns } from '$utils';
import * as S from './BottomButtonWrap.style';
import { useTheme } from '$hooks/useTheme';
@@ -28,7 +28,10 @@ export const BottomButtonWrap: FC<{ children: ReactNode }> = ({ children }) => {
}}
>
{children}
diff --git a/packages/mobile/src/shared/components/Chart/new/PeriodSelector/PeriodSelector.tsx b/packages/mobile/src/shared/components/Chart/new/PeriodSelector/PeriodSelector.tsx
index a107ed7b0..8d9e4d517 100644
--- a/packages/mobile/src/shared/components/Chart/new/PeriodSelector/PeriodSelector.tsx
+++ b/packages/mobile/src/shared/components/Chart/new/PeriodSelector/PeriodSelector.tsx
@@ -25,7 +25,7 @@ export const Period: React.FC<{
}> = (props) => {
const theme = useTheme();
const backgroundColor = props.selected
- ? theme.colors.backgroundSecondary
+ ? theme.colors.buttonSecondaryBackground
: 'transparent';
return (
diff --git a/packages/mobile/src/shared/components/ImportWalletForm/ImportWalletForm.style.ts b/packages/mobile/src/shared/components/ImportWalletForm/ImportWalletForm.style.ts
index f0f28371b..b88bd6431 100644
--- a/packages/mobile/src/shared/components/ImportWalletForm/ImportWalletForm.style.ts
+++ b/packages/mobile/src/shared/components/ImportWalletForm/ImportWalletForm.style.ts
@@ -26,11 +26,18 @@ export const InputNumber = styled.TextInput.attrs({
top: 0;
padding-left: 0;
padding-right: 0;
- padding-top: ${ns(isAndroid ? 17 : 18.5)}px;
- padding-bottom: ${ns(isAndroid ? 15.5 : 17.5)}px;
+ padding-top: ${ns(isAndroid ? 16.5 : 18.5)}px;
+ padding-bottom: ${ns(isAndroid ? 16 : 17.5)}px;
${isAndroid ? 'text-align-vertical: top;' : ''}
z-index: 3;
position: absolute;
+ ${() => {
+ if (isAndroid) {
+ return `
+ line-height: ${ns(24)}px;
+ `;
+ }
+ }}
`;
export const ButtonWrap = styled.View`
diff --git a/packages/mobile/src/shared/components/ImportWalletForm/ImportWalletForm.tsx b/packages/mobile/src/shared/components/ImportWalletForm/ImportWalletForm.tsx
index 84ee7f8b9..91ed0c3df 100644
--- a/packages/mobile/src/shared/components/ImportWalletForm/ImportWalletForm.tsx
+++ b/packages/mobile/src/shared/components/ImportWalletForm/ImportWalletForm.tsx
@@ -1,5 +1,7 @@
import React, { FC, useCallback, useMemo, useRef, useState } from 'react';
import Animated, {
+ FadeIn,
+ FadeOut,
useAnimatedScrollHandler,
useSharedValue,
} from 'react-native-reanimated';
@@ -9,21 +11,22 @@ import { useDispatch } from 'react-redux';
import { deviceHeight, isAndroid, ns, parseLockupConfig } from '$utils';
import { InputItem } from './InputItem';
-import { Button, Input, NavBarHelper, Text } from '$uikit';
+import { Input, NavBarHelper, Text, Button } from '$uikit';
import * as S from './ImportWalletForm.style';
import { useReanimatedKeyboardHeight } from '$hooks/useKeyboardHeight';
import { ImportWalletFormProps } from './ImportWalletForm.interface';
import { useInputsRegistry } from './useInputRegistry';
import { WordHintsPopup, WordHintsPopupRef } from './WordHintsPopup';
-import { Keyboard } from 'react-native';
+import { Keyboard, KeyboardAvoidingView } from 'react-native';
import { wordlist } from '$libs/Ton/mnemonic/wordlist';
import { Toast } from '$store';
import { t } from '@tonkeeper/shared/i18n';
+import { Steezy, Button as ButtonNew, View } from '@tonkeeper/uikit';
+import Clipboard from '@react-native-community/clipboard';
export const ImportWalletForm: FC = (props) => {
const { onWordsFilled } = props;
-
const { bottom: bottomInset } = useSafeAreaInsets();
const dispatch = useDispatch();
const inputsRegistry = useInputsRegistry();
@@ -36,6 +39,7 @@ export const ImportWalletForm: FC = (props) => {
const [isConfigInputShown, setConfigInputShown] = useState(false);
const [config, setConfig] = useState('');
const [isRestoring, setRestoring] = useState(false);
+ const [hasTextInAnyOfInputs, setHasTextInAnyOfInputs] = useState(false);
const deferredScrollToInput = useRef<((offset: number) => void) | null>(null);
const { keyboardHeight } = useReanimatedKeyboardHeight({
@@ -57,25 +61,42 @@ export const ImportWalletForm: FC = (props) => {
setConfig(text);
}, []);
- const handleMultipleWords = useCallback((index: number, text: string) => {
- const words = text
- .split(' ')
- .map((word) => word.trim())
- .filter((word) => word.length > 0);
+ const handleMultipleWords = useCallback(
+ (index: number, text: string) => {
+ if (!hasTextInAnyOfInputs) {
+ setHasTextInAnyOfInputs(true);
+ }
+ const words = text
+ .replace(/\r\n|\r|\n/g, ' ')
+ .split(' ')
+ .map((word) => word.trim())
+ .filter((word) => word.length > 0);
- let cursor = index;
- for (const word of words) {
- inputsRegistry.getRef(cursor)?.setValue(word);
- cursor += 1;
- if (cursor === 24) {
- break;
+ let cursor = index;
+ for (const word of words) {
+ inputsRegistry.getRef(cursor)?.setValue(word);
+ cursor += 1;
+ if (cursor === 24) {
+ break;
+ }
}
- }
- if (cursor > 0) {
- inputsRegistry.getRef(cursor - 1)?.focus();
+ if (cursor > 0) {
+ inputsRegistry.getRef(cursor - 1)?.focus();
+ }
+ },
+ [hasTextInAnyOfInputs, inputsRegistry],
+ );
+
+ const handlePasteButton = useCallback(async () => {
+ if (!hasTextInAnyOfInputs) {
+ setHasTextInAnyOfInputs(true);
}
- }, []);
+ const maybePhrase = await Clipboard.getString();
+ if (maybePhrase.replace(/\r\n|\r|\n/g, ' ').split(' ').length === 24) {
+ handleMultipleWords(0, maybePhrase);
+ }
+ }, [hasTextInAnyOfInputs, handleMultipleWords]);
const handleSpace = useCallback((index: number) => {
if (index === 24) {
@@ -185,6 +206,15 @@ export const ImportWalletForm: FC = (props) => {
const handleChangeText = useCallback(
(index: number) => (text: string) => {
+ if (
+ !text &&
+ hasTextInAnyOfInputs &&
+ Object.values(inputsRegistry.refs).filter((val) => val.getValue()).length === 1
+ ) {
+ setHasTextInAnyOfInputs(false);
+ } else if (!hasTextInAnyOfInputs) {
+ setHasTextInAnyOfInputs(true);
+ }
const overlap = 10;
const offsetTop = inputsRegistry.getPosition(index) + S.INPUT_HEIGHT - overlap;
const contentWidth = isAndroid ? 0 : inputsRegistry.getContentWidth(index);
@@ -201,7 +231,7 @@ export const ImportWalletForm: FC = (props) => {
},
});
},
- [],
+ [hasTextInAnyOfInputs],
);
const scrollHandler = useAnimatedScrollHandler({
@@ -269,6 +299,29 @@ export const ImportWalletForm: FC = (props) => {
+
+
+ {!hasTextInAnyOfInputs && (
+
+
+
+ )}
+
+
>
);
};
+
+const styles = Steezy.create({
+ pasteButtonContainer: {
+ position: 'absolute',
+ alignItems: 'center',
+ left: 0,
+ right: 0,
+ },
+});
diff --git a/packages/mobile/src/shared/components/ImportWalletForm/InputItem.tsx b/packages/mobile/src/shared/components/ImportWalletForm/InputItem.tsx
index ca060eb61..90902c002 100644
--- a/packages/mobile/src/shared/components/ImportWalletForm/InputItem.tsx
+++ b/packages/mobile/src/shared/components/ImportWalletForm/InputItem.tsx
@@ -52,6 +52,8 @@ export const InputItem = forwardRef((props, ref) =
const handleChangeText = useCallback(
(text) => {
let newText = text.trim();
+ newText = newText.replace(/\r\n|\r|\n/g, ' ');
+
if (newText.split(' ').length > 1) {
onMultipleWords(index, newText);
} else if (text.slice(-1) === ' ') {
diff --git a/packages/mobile/src/shared/components/SwapButton/SwapButton.tsx b/packages/mobile/src/shared/components/SwapButton/SwapButton.tsx
index b6c43c0ac..f59112620 100644
--- a/packages/mobile/src/shared/components/SwapButton/SwapButton.tsx
+++ b/packages/mobile/src/shared/components/SwapButton/SwapButton.tsx
@@ -85,8 +85,8 @@ const SwapButtonComponent: FC = (props) => {
hitSlop={HIT_SLOP_INSETS}
>
-
-
+
+
);
diff --git a/packages/mobile/src/store/wallet/sagas.ts b/packages/mobile/src/store/wallet/sagas.ts
index e91f47ddb..eb0ae288b 100644
--- a/packages/mobile/src/store/wallet/sagas.ts
+++ b/packages/mobile/src/store/wallet/sagas.ts
@@ -444,8 +444,6 @@ export function* walletGetUnlockedVault(action?: WalletGetUnlockedVaultAction) {
? tk.wallets.get(action.payload.walletIdentifier)!
: tk.wallet;
- const generatedVault = yield select(walletGeneratedVaultSelector);
-
let withoutBiometryOnOpen = false;
if (tk.biometryEnabled) {
@@ -464,9 +462,7 @@ export function* walletGetUnlockedVault(action?: WalletGetUnlockedVaultAction) {
mnemonic,
);
- if (generatedVault) {
- setLastEnteredPasscode(passcode);
- }
+ setLastEnteredPasscode(passcode);
action?.payload?.onDone?.(unlockedVault);
return unlockedVault;
diff --git a/packages/mobile/src/store/zustand/appTheme/index.ts b/packages/mobile/src/store/zustand/appTheme/index.ts
new file mode 100644
index 000000000..dd55148e3
--- /dev/null
+++ b/packages/mobile/src/store/zustand/appTheme/index.ts
@@ -0,0 +1,2 @@
+export * from './useAppTheme';
+export * from './types';
diff --git a/packages/mobile/src/store/zustand/appTheme/types.ts b/packages/mobile/src/store/zustand/appTheme/types.ts
new file mode 100644
index 000000000..f28394a3f
--- /dev/null
+++ b/packages/mobile/src/store/zustand/appTheme/types.ts
@@ -0,0 +1,13 @@
+export enum ThemeOptions {
+ Blue = 'blue',
+ Dark = 'dark',
+ Light = 'light',
+ System = 'system',
+}
+
+export interface IAppThemeStore {
+ selectedTheme: ThemeOptions;
+ actions: {
+ setSelectedTheme: (selectedTheme: ThemeOptions) => void;
+ };
+}
diff --git a/packages/mobile/src/store/zustand/appTheme/useAppTheme.ts b/packages/mobile/src/store/zustand/appTheme/useAppTheme.ts
new file mode 100644
index 000000000..e68cfb590
--- /dev/null
+++ b/packages/mobile/src/store/zustand/appTheme/useAppTheme.ts
@@ -0,0 +1,26 @@
+import AsyncStorage from '@react-native-async-storage/async-storage';
+import { create } from 'zustand';
+import { createJSONStorage, persist } from 'zustand/middleware';
+import { IAppThemeStore, ThemeOptions } from './types';
+
+const initialState: Omit = {
+ selectedTheme: ThemeOptions.Blue,
+};
+
+export const useAppThemeStore = create(
+ persist(
+ (set) => ({
+ ...initialState,
+ actions: {
+ setSelectedTheme: (selectedTheme) => {
+ set({ selectedTheme });
+ },
+ },
+ }),
+ {
+ name: 'app-theme',
+ storage: createJSONStorage(() => AsyncStorage),
+ partialize: ({ selectedTheme }) => ({ selectedTheme } as IAppThemeStore),
+ },
+ ),
+);
diff --git a/packages/mobile/src/store/zustand/index.ts b/packages/mobile/src/store/zustand/index.ts
index fec3a7fc0..4eda0220c 100644
--- a/packages/mobile/src/store/zustand/index.ts
+++ b/packages/mobile/src/store/zustand/index.ts
@@ -7,3 +7,4 @@ export * from './flash';
export * from './notifications';
export * from './encryptedComments';
export * from './addressUpdate';
+export * from './appTheme';
diff --git a/packages/mobile/src/styled/colors.ts b/packages/mobile/src/styled/colors.ts
index 03fab7129..36700c2cd 100644
--- a/packages/mobile/src/styled/colors.ts
+++ b/packages/mobile/src/styled/colors.ts
@@ -1,4 +1,4 @@
-export enum DARK_COLORS {
+export enum BLUE_COLORS {
textPrimary = '#FFFFFF',
textSecondary = '#8994A3',
textTertiary = '#556170',
@@ -17,11 +17,64 @@ export enum DARK_COLORS {
backgroundTertiary = '#2E3847',
backgroundHighlighted = 'rgba(79, 90, 112, 0.24)',
backgroundQuaternary = '#3E4A5C',
- backgroundCamera = '#0c121f',
border = 'rgba(255, 255, 255, 0.08)',
separatorCommon = 'rgba(79, 90, 112, 0.24)',
}
+export enum DARK_COLORS {
+ textPrimary = '#D9D9D9',
+ textSecondary = '#8D8D93',
+ textTertiary = '#4E4E52',
+ textLink = '#45AEF5',
+
+ iconPrimary = '#EBEBEB',
+ iconSecondary = '#8D8D93',
+ iconTertiary = '#4E4E52',
+
+ foregroundPrimary = '#FFFFFF',
+ foregroundSecondary = '#8D8D93',
+ foregroundTertiary = '#4E4E52',
+ backgroundPrimary = '#000000',
+ backgroundPrimaryTrans = 'rgba(0, 0, 0, 0.92)',
+ backgroundSecondary = '#1B1B1F',
+ backgroundTertiary = '#2B2B2E',
+ backgroundHighlighted = 'rgba(255, 255, 255, 0.04)',
+ backgroundQuaternary = '#353538',
+ border = 'rgba(255, 255, 255, 0.12)',
+ separatorCommon = 'rgba(255, 255, 255, 0.12)',
+}
+
+export enum LIGHT_COLORS {
+ textPrimary = '#000000',
+ textSecondary = '#818C99',
+ textTertiary = '#95A0AD',
+ textLink = '#007AFF',
+
+ iconPrimary = '#000000',
+ iconSecondary = '#818C99',
+ iconTertiary = '#95A0AD',
+
+ foregroundPrimary = '#000000',
+ foregroundSecondary = '#818C99',
+ foregroundTertiary = '#95A0AD',
+ backgroundPrimary = '#EFEEF3',
+ backgroundPrimaryTrans = 'rgba(255, 255, 255, 0.92)',
+ backgroundSecondary = '#FFFFFF',
+ backgroundTertiary = '#F0F0F0',
+ backgroundHighlighted = 'rgba(0, 0, 0, 0.04)',
+ backgroundQuaternary = 'rgba(129, 140, 153, 0.20)',
+ border = 'rgba(60, 60, 67, 0.08)',
+ separatorCommon = 'rgba(60, 60, 67, 0.08)',
+
+ accentPrimary = '#007AFF',
+ accentPrimaryLight = '#3D9AFF',
+ accentPrimaryDark = '#1F8AFF',
+ accentPositive = '#25B86F',
+ accentNegative = '#FF3B30',
+ accentBlue = '#007AFF',
+ accentOrange = '#F5A73B',
+}
+
export enum CONSTANT_COLORS {
constantDark = '#000000',
constantLight = '#FFFFFF',
diff --git a/packages/mobile/src/styled/theme.ts b/packages/mobile/src/styled/theme.ts
index 5a5069a39..a6600f174 100644
--- a/packages/mobile/src/styled/theme.ts
+++ b/packages/mobile/src/styled/theme.ts
@@ -1,7 +1,15 @@
-import { DARK_COLORS, COMMON_COLORS, CONSTANT_COLORS } from './colors';
+import { Theme, ThemeName } from '@tonkeeper/uikit';
+import {
+ DARK_COLORS,
+ COMMON_COLORS,
+ CONSTANT_COLORS,
+ BLUE_COLORS,
+ LIGHT_COLORS,
+} from './colors';
import { FONT } from './fonts';
import { DARK_GRADIENTS } from './gradients';
import { RADIUS } from './radius';
+import { getThemeByName } from '@tonkeeper/uikit/src/styles/utils';
type ThemeSpecificColor = keyof typeof DARK_COLORS;
type ConstantColor = keyof typeof CONSTANT_COLORS;
@@ -12,7 +20,11 @@ export enum ThemeNames {
dark = 'dark',
}
-export type TonThemeColor = ThemeSpecificColor | ConstantColor | CommonColor;
+export type TonThemeColor =
+ | ThemeSpecificColor
+ | ConstantColor
+ | CommonColor
+ | keyof Theme;
const CommonTheme = {
font: FONT,
@@ -29,7 +41,17 @@ export const LightTheme = {
gradients: DARK_GRADIENTS,
colors: {
...CommonTheme.colors,
- ...DARK_COLORS,
+ ...LIGHT_COLORS,
+ },
+};
+
+export const BlueTheme = {
+ ...CommonTheme,
+ isDark: true,
+ gradients: DARK_GRADIENTS,
+ colors: {
+ ...CommonTheme.colors,
+ ...BLUE_COLORS,
},
};
diff --git a/packages/mobile/src/styles/Steezy.ts b/packages/mobile/src/styles/Steezy.ts
index 08b17ad3a..9606a25b7 100644
--- a/packages/mobile/src/styles/Steezy.ts
+++ b/packages/mobile/src/styles/Steezy.ts
@@ -1,8 +1,11 @@
-import { createSteezy, createDynamicStyleVars, createMediaStyleVars } from "@bogoslavskiy/react-native-steezy";
-import { useSafeAreaInsets } from "react-native-safe-area-context";
-import { ns } from "$utils";
-import { DarkTheme } from "./DarkTheme";
-import { RADIUS } from "$styled";
+import {
+ createSteezy,
+ createDynamicStyleVars,
+ createMediaStyleVars,
+} from '@bogoslavskiy/react-native-steezy';
+import { useSafeAreaInsets } from 'react-native-safe-area-context';
+import { ns } from '$utils';
+import { useTheme } from '@tonkeeper/uikit';
export const media = createMediaStyleVars({
isTablet: {
@@ -16,17 +19,18 @@ const corners = {
small: 12,
medium: 16,
large: 20,
- full: (size: number) => size / 2,
-}
+ full: (size: number) => size / 2,
+};
export const variables = createDynamicStyleVars(() => {
const safeArea = useSafeAreaInsets();
+ const theme = useTheme();
return {
safeArea,
- colors: DarkTheme,
+ colors: theme,
radius: corners,
- corners
+ corners,
};
});
diff --git a/packages/mobile/src/styles/index.ts b/packages/mobile/src/styles/index.ts
index aa5d79513..91bdf6b15 100644
--- a/packages/mobile/src/styles/index.ts
+++ b/packages/mobile/src/styles/index.ts
@@ -1,8 +1,7 @@
import { StyleProp as SteezyStyleProp } from '@bogoslavskiy/react-native-steezy';
-import { ViewStyle, TextStyle, ImageStyle } from "react-native";
+import { ViewStyle, TextStyle, ImageStyle } from 'react-native';
export type StaticStyles = ViewStyle | TextStyle | ImageStyle;
export type StyleProp = SteezyStyleProp;
export { Steezy } from './Steezy';
-export { DarkTheme } from './DarkTheme';
diff --git a/packages/mobile/src/tabs/Activity/ActivityScreen.tsx b/packages/mobile/src/tabs/Activity/ActivityScreen.tsx
index 4acd7c2fe..80756df35 100644
--- a/packages/mobile/src/tabs/Activity/ActivityScreen.tsx
+++ b/packages/mobile/src/tabs/Activity/ActivityScreen.tsx
@@ -72,7 +72,7 @@ export const ActivityScreen = memo(() => {
activityList.error === null)
) {
return (
-
+
{t('activity.empty_transaction_title')}
diff --git a/packages/mobile/src/tabs/Wallet/WalletScreen.tsx b/packages/mobile/src/tabs/Wallet/WalletScreen.tsx
index 8a589ccbc..38e128140 100644
--- a/packages/mobile/src/tabs/Wallet/WalletScreen.tsx
+++ b/packages/mobile/src/tabs/Wallet/WalletScreen.tsx
@@ -91,10 +91,11 @@ export const WalletScreen = memo(({ navigation }) => {
))}
{shouldUpdate && }
-
-
- {!isWatchOnly && }
-
+
{wallet && isConnected !== false ? (
({
width: TabletMaxWidth,
},
},
- balanceWithBattery: {
- flexDirection: 'row',
- alignItems: 'center',
- },
addressContainer: {
marginBottom: 8,
marginTop: 4,
diff --git a/packages/mobile/src/tabs/Wallet/components/ExpiringDomainCell.tsx b/packages/mobile/src/tabs/Wallet/components/ExpiringDomainCell.tsx
index bea49c233..ea5294543 100644
--- a/packages/mobile/src/tabs/Wallet/components/ExpiringDomainCell.tsx
+++ b/packages/mobile/src/tabs/Wallet/components/ExpiringDomainCell.tsx
@@ -53,7 +53,7 @@ export const ExpiringDomainCell = memo(({ withoutSpacer, styl
onPress={() => openRenewAllDomainModal()}
leftContent={
-
+
}
title={
diff --git a/packages/mobile/src/tabs/Wallet/components/Tabs/TabsHeader.tsx b/packages/mobile/src/tabs/Wallet/components/Tabs/TabsHeader.tsx
index 92048497e..e9de6d093 100644
--- a/packages/mobile/src/tabs/Wallet/components/Tabs/TabsHeader.tsx
+++ b/packages/mobile/src/tabs/Wallet/components/Tabs/TabsHeader.tsx
@@ -1,13 +1,14 @@
import { Steezy } from '$styles';
import { AnimatedView, Icon, TouchableOpacity, View } from '$uikit';
import { Style } from '@bogoslavskiy/react-native-steezy/dist/types';
-import { isAndroid } from '$utils';
+import { convertHexToRGBA, isAndroid } from '$utils';
import * as React from 'react';
import { useWindowDimensions } from 'react-native';
import { useAnimatedStyle } from 'react-native-reanimated';
import { useTabCtx } from './TabsContainer';
import { goBack } from '$navigation/imperative';
import LinearGradient from 'react-native-linear-gradient';
+import { useTheme } from '@tonkeeper/uikit';
interface TabsHeaderProps {
style?: Style;
@@ -19,6 +20,7 @@ interface TabsHeaderProps {
export const TabsHeader: React.FC = (props) => {
const dimensions = useWindowDimensions();
const { headerHeight, scrollY } = useTabCtx();
+ const theme = useTheme();
const shouldRenderGoBackButton = props.withBackButton ?? false;
@@ -47,7 +49,7 @@ export const TabsHeader: React.FC = (props) => {
style={styles.leftContentGradient.static}
start={{ x: 0, y: 1 }}
end={{ x: 1, y: 1 }}
- colors={['rgba(16, 22, 31, 1)', 'rgba(16, 22, 31, 0)']}
+ colors={[theme.backgroundPage, convertHexToRGBA(theme.backgroundPage, 0)]}
pointerEvents="none"
/>
>
@@ -87,7 +89,7 @@ const styles = Steezy.create(({ colors, safeArea }) => ({
position: 'absolute',
top: 0,
zIndex: isAndroid ? 1 : 4,
- backgroundColor: colors.backgroundPrimary,
+ backgroundColor: colors.backgroundPage,
},
leftContent: {
top: 16,
@@ -106,7 +108,7 @@ const styles = Steezy.create(({ colors, safeArea }) => ({
zIndex: 2,
},
backButton: {
- backgroundColor: colors.backgroundSecondary,
+ backgroundColor: colors.buttonSecondaryBackground,
height: 32,
width: 32,
borderRadius: 16,
diff --git a/packages/mobile/src/tabs/Wallet/components/WalletContentList.tsx b/packages/mobile/src/tabs/Wallet/components/WalletContentList.tsx
index 70862a1b8..bed257603 100644
--- a/packages/mobile/src/tabs/Wallet/components/WalletContentList.tsx
+++ b/packages/mobile/src/tabs/Wallet/components/WalletContentList.tsx
@@ -123,7 +123,7 @@ export const WalletContentList = memo((props) => {
}
diff --git a/packages/mobile/src/tabs/Wallet/components/WalletSelector.tsx b/packages/mobile/src/tabs/Wallet/components/WalletSelector.tsx
index fad3394fd..a184b1496 100644
--- a/packages/mobile/src/tabs/Wallet/components/WalletSelector.tsx
+++ b/packages/mobile/src/tabs/Wallet/components/WalletSelector.tsx
@@ -17,11 +17,13 @@ import React, { FC, memo, useCallback } from 'react';
import { useNavigation } from '@tonkeeper/router';
import { FlashCountKeys, useFlashCount } from '$store';
import { tk } from '$wallet';
+import { useThemeName } from '$hooks/useThemeName';
const WalletSelectorComponent: FC = () => {
const wallet = useWallet();
const nav = useNavigation();
const [flashShownCount, disableFlash] = useFlashCount(FlashCountKeys.MultiWallet);
+ const themeName = useThemeName();
const handlePress = useCallback(() => {
disableFlash();
@@ -35,7 +37,7 @@ const WalletSelectorComponent: FC = () => {
= 3}
>
@@ -43,15 +45,20 @@ const WalletSelectorComponent: FC = () => {
emojiStyle={styles.emoji.static}
size={20}
value={wallet.config.emoji}
+ color="constantWhite"
/>
-
+
{wallet.config.name}
-
+
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/inscriptions.ts b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/inscriptions.ts
index a537a0a00..51b50a9f8 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/inscriptions.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/inscriptions.ts
@@ -1,18 +1,13 @@
import { DependencyPrototype } from './utils/prototype';
-import { tk } from '$wallet';
import { TonInscriptionsState } from '$wallet/managers/TonInscriptions';
+import { Wallet } from '$wallet/Wallet';
export class InscriptionsDependency extends DependencyPrototype<
TonInscriptionsState,
TonInscriptionsState['items']
> {
- constructor() {
- super(tk.wallet.tonInscriptions.state, (state) => state.items);
- }
-
- setWallet(wallet) {
- this.dataProvider = wallet.tonInscriptions.state;
- super.setWallet(wallet);
+ constructor(wallet: Wallet) {
+ super(wallet.tonInscriptions.state, (state) => state.items);
}
}
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/jettons.ts b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/jettons.ts
index 07177ddbb..a592c90dd 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/jettons.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/jettons.ts
@@ -1,18 +1,18 @@
import { DependencyPrototype } from './utils/prototype';
-import { tk } from '$wallet';
import { JettonsState } from '$wallet/managers/JettonsManager';
import { FiatRate } from '../utils/types';
import { Address } from '@tonkeeper/core';
import { formatter } from '$utils/formatter';
import BigNumber from 'bignumber.js';
+import { Wallet } from '$wallet/Wallet';
export class JettonBalancesDependency extends DependencyPrototype<
JettonsState,
Pick
> {
- constructor() {
- super(tk.wallet.jettons.state, (state) => ({
+ constructor(wallet: Wallet) {
+ super(wallet.jettons.state, (state) => ({
jettonBalances: state.jettonBalances,
jettonRates: state.jettonRates,
}));
@@ -40,6 +40,7 @@ export class JettonBalancesDependency extends DependencyPrototype<
trend:
rate.diff_24h.startsWith('+') || rate.diff_24h === '0' ? 'positive' : 'negative',
total: {
+ in_ton: new BigNumber(jettonBalance).multipliedBy(rate.ton).toString(),
formatted: formatter.format(
new BigNumber(jettonBalance).multipliedBy(rate.fiat),
{ currency },
@@ -48,9 +49,4 @@ export class JettonBalancesDependency extends DependencyPrototype<
},
};
}
-
- setWallet(wallet) {
- this.dataProvider = wallet.jettons.state;
- super.setWallet(wallet);
- }
}
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/staking.ts b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/staking.ts
index 1a89e3605..8e111d76b 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/staking.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/staking.ts
@@ -1,21 +1,16 @@
import { DependencyPrototype } from './utils/prototype';
-import { tk } from '$wallet';
import { StakingState } from '$wallet/managers/StakingManager';
import { AccountStakingInfo, PoolInfo } from '@tonkeeper/core/src/TonAPI';
+import { Wallet } from '$wallet/Wallet';
export class StakingDependency extends DependencyPrototype<
StakingState,
{ info: AccountStakingInfo; pool: PoolInfo }[]
> {
- constructor() {
- super(tk.wallet.staking.state, (s) =>
+ constructor(wallet: Wallet) {
+ super(wallet.staking.state, (s) =>
s.pools.map((pool) => ({ info: s.stakingInfo[pool.address], pool })),
);
}
-
- setWallet(wallet) {
- this.dataProvider = wallet.staking.state;
- super.setWallet(wallet);
- }
}
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/stakingJettons.ts b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/stakingJettons.ts
index 66ada7c19..d5f736792 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/stakingJettons.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/stakingJettons.ts
@@ -1,21 +1,16 @@
import { DependencyPrototype } from './utils/prototype';
-import { tk } from '$wallet';
import { Address } from '@tonkeeper/shared/Address';
import { StakingState } from '$wallet/managers/StakingManager';
import { JettonBalanceModel } from '$wallet/models/JettonBalanceModel';
+import { Wallet } from '$wallet/Wallet';
export class StakingJettonsDependency extends DependencyPrototype<
StakingState,
Pick
> {
- constructor() {
- super(tk.wallet.staking.state, (state) => ({ stakingJettons: state.stakingJettons }));
- }
-
- setWallet(wallet) {
- this.dataProvider = wallet.staking.state;
- super.setWallet(wallet);
+ constructor(wallet: Wallet) {
+ super(wallet.staking.state, (state) => ({ stakingJettons: state.stakingJettons }));
}
get filterTokensBalancesFn(): (balance: JettonBalanceModel) => boolean {
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tokenApproval.ts b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tokenApproval.ts
index 059c9d47a..83388e478 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tokenApproval.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tokenApproval.ts
@@ -1,5 +1,4 @@
import { DependencyPrototype } from './utils/prototype';
-import { tk } from '$wallet';
import {
TokenApprovalState,
@@ -11,18 +10,14 @@ import {
JettonVerification,
} from '$wallet/models/JettonBalanceModel';
import { InscriptionBalance } from '@tonkeeper/core/src/TonAPI';
+import { Wallet } from '$wallet/Wallet';
export class TokenApprovalDependency extends DependencyPrototype<
TokenApprovalState,
Pick
> {
- constructor() {
- super(tk.wallet.tokenApproval.state, (state) => ({ tokens: state.tokens }));
- }
-
- setWallet(wallet) {
- this.dataProvider = wallet.tokenApproval.state;
- super.setWallet(wallet);
+ constructor(wallet: Wallet) {
+ super(wallet.tokenApproval.state, (state) => ({ tokens: state.tokens }));
}
get filterInscriptionsFn(): (balance: InscriptionBalance) => boolean {
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tonBalances.ts b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tonBalances.ts
index d78762f75..132f0a3cc 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tonBalances.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tonBalances.ts
@@ -1,6 +1,6 @@
import { DependencyPrototype } from './utils/prototype';
-import { tk } from '$wallet';
import { BalancesState } from '$wallet/managers/BalancesManager';
+import { Wallet } from '$wallet/Wallet';
export enum TonBalanceType {
Liquid = 'Liquid',
@@ -17,19 +17,14 @@ export class TonBalancesDependency extends DependencyPrototype<
BalancesState,
Pick
> {
- constructor() {
- super(tk.wallet.balances.state, (state) => ({
+ constructor(wallet: Wallet) {
+ super(wallet.balances.state, (state) => ({
ton: state.ton,
tonLocked: state.tonLocked,
tonRestricted: state.tonRestricted,
}));
}
- setWallet(wallet) {
- this.dataProvider = wallet.balances.state;
- super.setWallet(wallet);
- }
-
get balances() {
const balances: TonBalance[] = [
{ type: TonBalanceType.Liquid, balance: this.state.ton },
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tonPrice.ts b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tonPrice.ts
index ecf6694d0..969554e19 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tonPrice.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/tonPrice.ts
@@ -1,16 +1,16 @@
import { DependencyPrototype } from './utils/prototype';
import { PricesState } from '$wallet/managers/TonPriceManager';
-import { tk } from '$wallet';
import { FiatRate } from '../utils/types';
import { formatter } from '@tonkeeper/shared/formatter';
import BigNumber from 'bignumber.js';
+import { State } from '@tonkeeper/core';
export class TonPriceDependency extends DependencyPrototype<
PricesState,
Pick
> {
- constructor() {
- super(tk.tonPrice.state, (state) => ({ ton: state.ton, currency: state.currency }));
+ constructor(state: State) {
+ super(state, (state) => ({ ton: state.ton, currency: state.currency }));
}
protected shouldEmit(
@@ -20,11 +20,6 @@ export class TonPriceDependency extends DependencyPrototype<
return prev.ton !== cur.ton;
}
- setWallet(wallet) {
- this.dataProvider = wallet.tonPrice.state;
- super.setWallet(wallet);
- }
-
public getRawTotal(balance: string): string {
return new BigNumber(balance).multipliedBy(this.state.ton.fiat).toString();
}
@@ -45,6 +40,7 @@ export class TonPriceDependency extends DependencyPrototype<
? 'positive'
: 'negative',
total: {
+ in_ton: balance,
formatted: formatter.format(new BigNumber(balance).multipliedBy(rate.ton.fiat), {
currency: rate.currency,
}),
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/utils/prototype.ts b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/utils/prototype.ts
index 08b8e6061..3e21054ea 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/dependencies/utils/prototype.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/dependencies/utils/prototype.ts
@@ -69,10 +69,7 @@ export class DependencyPrototype<
};
}
- public setWallet(wallet: Wallet) {
+ public destroy() {
this.unsubscribe?.();
- this.wallet = wallet;
- this.subscribeToDataProvider();
- this.onStateChanged();
}
}
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/inscriptions.ts b/packages/mobile/src/tabs/Wallet/content-providers/inscriptions.ts
index 9f28412a9..1f644dd82 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/inscriptions.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/inscriptions.ts
@@ -54,6 +54,7 @@ export class InscriptionsContentProvider extends ContentProviderPrototype<{
},
trend: 'negative',
total: {
+ in_ton: '0',
formatted: formatter.format(0, {
currency: this.deps.tonPrice.state.currency,
}),
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/utils/receiver.ts b/packages/mobile/src/tabs/Wallet/content-providers/utils/receiver.ts
index 4179d0282..d4827df6b 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/utils/receiver.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/utils/receiver.ts
@@ -8,13 +8,14 @@ import { TokensContentProvider } from '../tokens';
import { StakingJettonsDependency } from '../dependencies/stakingJettons';
import { TokenApprovalDependency } from '../dependencies/tokenApproval';
import { JettonBalancesDependency } from '../dependencies/jettons';
-import { Wallet } from '$wallet/Wallet';
import { StakingContentProvider } from '../staking';
import { StakingDependency } from '../dependencies/staking';
import { InscriptionsContentProvider } from '../inscriptions';
import { InscriptionsDependency } from '../dependencies/inscriptions';
import { NamespacedLogger, logger } from '$logger';
import BigNumber from 'bignumber.js';
+import { Wallet } from '$wallet/Wallet';
+import { tk } from '$wallet';
type Subscriber = (cells: CellItemToRender[]) => void;
@@ -23,14 +24,15 @@ export class WalletContentReceiver {
private subscribers = new Set();
private logger: NamespacedLogger;
+ private wallet: Wallet = tk.wallet;
- private tonPrice = new TonPriceDependency();
- private tonBalances = new TonBalancesDependency();
- private stakingJettons = new StakingJettonsDependency();
- private tokenApproval = new TokenApprovalDependency();
- private jettonBalances = new JettonBalancesDependency();
- private staking = new StakingDependency();
- private inscriptions = new InscriptionsDependency();
+ private tonPrice = new TonPriceDependency(tk.tonPrice.state);
+ private tonBalances = new TonBalancesDependency(this.wallet);
+ private stakingJettons = new StakingJettonsDependency(this.wallet);
+ private tokenApproval = new TokenApprovalDependency(this.wallet);
+ private jettonBalances = new JettonBalancesDependency(this.wallet);
+ private staking = new StakingDependency(this.wallet);
+ private inscriptions = new InscriptionsDependency(this.wallet);
private memoizedCells = new Map();
@@ -44,6 +46,11 @@ export class WalletContentReceiver {
this.inscriptions,
];
+ constructor() {
+ this.subscribeToProvidersChanges(this.providersList);
+ this.logger = logger.extend('WalletListContent');
+ }
+
private providersList: ContentProviderPrototype[] = [
new TONContentProvider(this.tonPrice, this.tonBalances),
new TokensContentProvider(
@@ -56,15 +63,10 @@ export class WalletContentReceiver {
new InscriptionsContentProvider(this.tonPrice, this.inscriptions, this.tokenApproval),
];
- constructor() {
- this.subscribeToProvidersChanges(this.providersList);
- this.logger = logger.extend('WalletListContent');
- }
-
- public setWallet(wallet: Wallet) {
- this.logger.debug('provide wallet to deps');
+ public destroy() {
+ this.logger.warn('Destroy');
this.depsList.forEach((provider) => {
- provider.setWallet(wallet);
+ provider.destroy();
});
}
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/utils/types.ts b/packages/mobile/src/tabs/Wallet/content-providers/utils/types.ts
index 165ba9e80..b72c9d5d5 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/utils/types.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/utils/types.ts
@@ -5,6 +5,7 @@ import { TonIconProps } from '@tonkeeper/uikit';
export type FiatRate = {
total: {
formatted: string;
+ in_ton: string;
raw: string;
};
percent?: string;
diff --git a/packages/mobile/src/tabs/Wallet/content-providers/utils/usePreparedWalletContent.ts b/packages/mobile/src/tabs/Wallet/content-providers/utils/usePreparedWalletContent.ts
index 8e1bed33d..e1819d182 100644
--- a/packages/mobile/src/tabs/Wallet/content-providers/utils/usePreparedWalletContent.ts
+++ b/packages/mobile/src/tabs/Wallet/content-providers/utils/usePreparedWalletContent.ts
@@ -1,17 +1,15 @@
-import { useEffect, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
import { CellItemToRender } from './types';
-import { useInstance } from '$hooks/useInstance';
import { WalletContentReceiver } from './receiver';
-import { tk } from '$wallet';
+import { useWallet } from '@tonkeeper/shared/hooks';
export const usePreparedWalletContent = () => {
- const providersReceiver = useInstance(() => new WalletContentReceiver());
+ const wallet = useWallet();
+ const providersReceiver = useMemo(() => new WalletContentReceiver(), [wallet]);
const [preparedContent, setPreparedContent] = useState([]);
useEffect(() => {
- return tk.onChangeWallet(() => {
- providersReceiver.setWallet(tk.wallet);
- });
+ return () => providersReceiver.destroy();
}, [providersReceiver]);
useEffect(() => {
diff --git a/packages/mobile/src/tabs/Wallet/hooks/useBalance.ts b/packages/mobile/src/tabs/Wallet/hooks/useBalance.ts
index f9a30e3e1..e576e52d7 100644
--- a/packages/mobile/src/tabs/Wallet/hooks/useBalance.ts
+++ b/packages/mobile/src/tabs/Wallet/hooks/useBalance.ts
@@ -1,7 +1,7 @@
import { useMemo } from 'react';
import BigNumber from 'bignumber.js';
import { formatter } from '$utils/formatter';
-import { useWalletCurrency } from '@tonkeeper/shared/hooks';
+import { useDangerLevel, useWalletCurrency } from '@tonkeeper/shared/hooks';
import { CellItemToRender } from '../content-providers/utils/types';
export type Rate = {
@@ -12,17 +12,33 @@ export type Rate = {
export const useBalance = (cellItems: CellItemToRender[]) => {
const currency = useWalletCurrency();
+ const { inSelectedCurrency, inTonRaw } = useMemo(
+ () =>
+ cellItems.reduce(
+ (total, item) => {
+ const balance = item.fiatRate?.total.raw ?? '0';
+ const tonBalance = item.fiatRate?.total.in_ton ?? '0';
- return useMemo(() => {
- const totalNumber = cellItems.reduce((total, item) => {
- const balance = item.fiatRate?.total.raw ?? '0';
- return total.plus(balance);
- }, new BigNumber(0));
+ total.inSelectedCurrency = total.inSelectedCurrency.plus(balance);
+ total.inTonRaw = total.inTonRaw.plus(tonBalance);
+
+ return total;
+ },
+ { inSelectedCurrency: new BigNumber(0), inTonRaw: new BigNumber(0) },
+ ),
+ [cellItems],
+ );
- return formatter.format(totalNumber.toString(), {
- currency,
- forceRespectDecimalPlaces: true,
- decimals: totalNumber.gte(1000) ? 0 : 2,
- });
- }, [cellItems, currency]);
+ const dangerLevel = useDangerLevel(inTonRaw.toString());
+
+ return useMemo(() => {
+ return {
+ inSelectedCurrency: formatter.format(inSelectedCurrency.toString(), {
+ currency,
+ forceRespectDecimalPlaces: true,
+ decimals: inSelectedCurrency.gte(1000) ? 0 : 2,
+ }),
+ dangerLevel,
+ };
+ }, [currency, dangerLevel, inSelectedCurrency]);
};
diff --git a/packages/mobile/src/uikit/Button/Button.style.ts b/packages/mobile/src/uikit/Button/Button.style.ts
index 368c71bd0..edba3ed56 100644
--- a/packages/mobile/src/uikit/Button/Button.style.ts
+++ b/packages/mobile/src/uikit/Button/Button.style.ts
@@ -21,8 +21,16 @@ export const Button = styled(Animated.View)<{
return `
background: ${
inverted
- ? theme.colors[isPressed ? 'backgroundSecondary' : 'backgroundTertiary']
- : theme.colors[isPressed ? 'backgroundTertiary' : 'backgroundSecondary']
+ ? theme.colors[
+ isPressed
+ ? 'buttonSecondaryBackground'
+ : 'buttonSecondaryBackgroundHighlighted'
+ ]
+ : theme.colors[
+ isPressed
+ ? 'buttonSecondaryBackgroundHighlighted'
+ : 'buttonSecondaryBackground'
+ ]
};
`;
} else if (mode === 'tertiary') {
@@ -39,10 +47,10 @@ export const Button = styled(Animated.View)<{
return `
background: ${
disabled
- ? theme.colors.accentPrimaryDark
+ ? theme.colors.buttonPrimaryBackgroundDisabled
: isPressed
- ? theme.colors.accentPrimaryLight
- : theme.colors.accentPrimary
+ ? theme.colors.buttonPrimaryBackgroundHighlighted
+ : theme.colors.buttonPrimaryBackground
};
`;
}
@@ -110,9 +118,13 @@ export const Title = styled(Text).attrs({ allowFontScaling: false })<{
return `
color: ${theme.colors.backgroundPrimary};
`;
+ } else if (mode === 'secondary') {
+ return `
+ color: ${theme.colors.buttonSecondaryForeground};
+ `;
} else {
return `
- color: ${theme.colors.foregroundPrimary};
+ color: ${theme.colors.buttonPrimaryForeground};
`;
}
}}
diff --git a/packages/mobile/src/uikit/Button/Button.tsx b/packages/mobile/src/uikit/Button/Button.tsx
index 2ead008b1..c771cffd7 100644
--- a/packages/mobile/src/uikit/Button/Button.tsx
+++ b/packages/mobile/src/uikit/Button/Button.tsx
@@ -2,8 +2,8 @@ import React, { FC, useCallback, useState } from 'react';
import * as S from './Button.style';
import { ButtonProps } from './Button.interface';
-import { Loader } from '../Loader/Loader';
import { TouchableWithoutFeedback } from 'react-native';
+import { Loader } from '@tonkeeper/uikit';
export const Button: FC = (props) => {
const {
@@ -37,7 +37,7 @@ export const Button: FC = (props) => {
function renderContent() {
if (isLoading) {
- return ;
+ return ;
}
return (
diff --git a/packages/mobile/src/uikit/Checkbox/Checkbox.tsx b/packages/mobile/src/uikit/Checkbox/Checkbox.tsx
index 172e6ef73..a6ed5c855 100644
--- a/packages/mobile/src/uikit/Checkbox/Checkbox.tsx
+++ b/packages/mobile/src/uikit/Checkbox/Checkbox.tsx
@@ -1,5 +1,4 @@
import React from 'react';
-import { Icon } from '../Icon/Icon';
import { Steezy } from '$styles';
import Animated, {
interpolateColor,
@@ -12,6 +11,7 @@ import { useTheme } from '$hooks/useTheme';
import { useEffect } from 'react';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { Platform, TouchableOpacity as NTouchableOpacity } from 'react-native';
+import { Icon } from '@tonkeeper/uikit';
export interface CheckboxViewProps {
checked: boolean;
@@ -47,7 +47,7 @@ export const CheckboxView: React.FC = (props) => {
borderColor: interpolateColor(
colorProgress.value,
[0, 1],
- [colors.backgroundTertiary, 'transparent'],
+ [colors.iconTertiary, 'transparent'],
),
};
});
@@ -69,7 +69,7 @@ export const CheckboxView: React.FC = (props) => {
return (
-
+
);
@@ -98,7 +98,7 @@ const styles = Steezy.create(({ colors }) => ({
width: 22,
height: 22,
borderRadius: 6,
- borderColor: colors.backgroundContentTint,
+ borderColor: colors.iconTertiary,
borderWidth: 2,
alignItems: 'center',
justifyContent: 'center',
diff --git a/packages/mobile/src/uikit/CheckmarkItem.tsx b/packages/mobile/src/uikit/CheckmarkItem.tsx
index 3d9bf4465..03b3b9bbb 100644
--- a/packages/mobile/src/uikit/CheckmarkItem.tsx
+++ b/packages/mobile/src/uikit/CheckmarkItem.tsx
@@ -12,43 +12,39 @@ interface RadioItemProps {
selected: boolean;
}
-export const CheckmarkItem = React.memo(({ label, selected, onChange }) => (
- onChange?.(!selected)}
- activeOpacity={0.6}
- >
-
-
-
- {label}
-
-
-
-));
+export const CheckmarkItem = React.memo(
+ ({ label, selected, onChange }) => (
+ onChange?.(!selected)} activeOpacity={0.6}>
+
+
+
+ {label}
+
+
+
+ ),
+);
export const Checkmark = ({ checked }: { checked: boolean }) => {
const theme = useTheme();
return (
-
{checked && (
-
+
)}
@@ -65,19 +61,19 @@ const styles = StyleSheet.create({
borderWidth: ns(2),
},
checkmark: {
- width: 22,
- height: 22,
- justifyContent: 'center',
- alignItems: 'center'
+ width: 22,
+ height: 22,
+ justifyContent: 'center',
+ alignItems: 'center',
},
checkmarkItem: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
paddingVertical: 12,
- marginLeft: 3
+ marginLeft: 3,
},
checkmarkLabelText: {
- marginLeft: 11
- }
-});
\ No newline at end of file
+ marginLeft: 11,
+ },
+});
diff --git a/packages/mobile/src/uikit/Input/Input.style.ts b/packages/mobile/src/uikit/Input/Input.style.ts
index b9591e5fd..0798203b0 100644
--- a/packages/mobile/src/uikit/Input/Input.style.ts
+++ b/packages/mobile/src/uikit/Input/Input.style.ts
@@ -13,9 +13,7 @@ export const InputWrapper = styled.View<{
overflow: hidden;
border-radius: ${({ theme }) => ns(theme.radius.normal)}px;
background-color: ${({ theme, isFailed }) =>
- isFailed
- ? changeAlphaValue(convertHexToRGBA(theme.colors.accentNegative), 0.08)
- : theme.colors.backgroundSecondary};
+ isFailed ? theme.colors.fieldErrorBackground : theme.colors.fieldBackground};
padding-horizontal: ${ns(16)}px;
padding-right: ${({ withClearButton }) => ns(withClearButton ? 52 : 16)}px;
diff --git a/packages/mobile/src/uikit/Input/Input.tsx b/packages/mobile/src/uikit/Input/Input.tsx
index c917e2155..471814439 100644
--- a/packages/mobile/src/uikit/Input/Input.tsx
+++ b/packages/mobile/src/uikit/Input/Input.tsx
@@ -137,7 +137,7 @@ export const Input: FC = (props) => {
borderColor: interpolateColor(
focusAnimation.value,
[0, 1],
- [colors.backgroundSecondary, colors.accentPrimary],
+ ['transparent', colors.accentPrimary],
),
};
});
@@ -149,7 +149,7 @@ export const Input: FC = (props) => {
borderColor: interpolateColor(
failAnimation.value,
[0, 1],
- [colors.backgroundSecondary, colors.accentNegative],
+ ['transparent', colors.accentNegative],
),
backgroundColor: `rgba(255,71,102, ${bgAlpha})`,
};
@@ -165,7 +165,7 @@ export const Input: FC = (props) => {
borderColor: interpolateColor(
successAnimation.value,
[0, 1],
- [colors.backgroundSecondary, colors.accentPositive],
+ ['transparent', colors.accentPositive],
),
};
});
diff --git a/packages/mobile/src/uikit/List/ListItem.tsx b/packages/mobile/src/uikit/List/ListItem.tsx
index aefaba6ca..e90266395 100644
--- a/packages/mobile/src/uikit/List/ListItem.tsx
+++ b/packages/mobile/src/uikit/List/ListItem.tsx
@@ -1,11 +1,11 @@
import React, { memo, useCallback } from 'react';
import { TextStyle, ViewStyle } from 'react-native';
import { Steezy, StyleProp } from '$styles';
-import { View } from '@tonkeeper/uikit';
+import { View, useTheme } from '@tonkeeper/uikit';
import { SText } from '../StyledNativeComponents';
import { Icon } from '../Icon/Icon';
import { Pressable } from '../Pressable';
-import { DarkTheme, TonThemeColor } from '$styled';
+import { TonThemeColor } from '$styled';
import FastImage from 'react-native-fast-image';
import Animated, {
SharedValue,
@@ -128,9 +128,11 @@ export const ListItem = memo((props) => {
);
}, [props.title, props.label, props.subtitle, compact, titleProps]);
+ const theme = useTheme();
+
return (
theme.colors.backgroundSecondary};
border-radius: ${({ theme }) => ns(theme.radius.normal)}px;
overflow: hidden;
`;
diff --git a/packages/mobile/src/uikit/List/old/List.tsx b/packages/mobile/src/uikit/List/old/List.tsx
index 23c38df67..efdcb01dc 100644
--- a/packages/mobile/src/uikit/List/old/List.tsx
+++ b/packages/mobile/src/uikit/List/old/List.tsx
@@ -4,6 +4,7 @@ import * as S from './List.style';
import { ListCellProps, ListProps } from './List.interface';
import { Separator } from '../../Separator/Separator';
import { View } from '../../StyledNativeComponents';
+import { useTheme } from '@tonkeeper/uikit';
export const ListCell: FC = ({
label,
@@ -57,5 +58,11 @@ export const List: FC = ({
});
}, [align, children, separator]);
- return {content};
+ const theme = useTheme();
+
+ return (
+
+ {content}
+
+ );
};
diff --git a/packages/mobile/src/uikit/ListButton/ListButton.tsx b/packages/mobile/src/uikit/ListButton/ListButton.tsx
index ba278c765..8bed17395 100644
--- a/packages/mobile/src/uikit/ListButton/ListButton.tsx
+++ b/packages/mobile/src/uikit/ListButton/ListButton.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { View } from '@tonkeeper/uikit';
+import { View, useTheme } from '@tonkeeper/uikit';
import { Steezy } from '$styles';
import Svg, { Path, Rect } from 'react-native-svg';
import { TouchableOpacity } from 'react-native-gesture-handler';
@@ -11,24 +11,30 @@ export interface ListButtonProps {
onPress: () => void;
}
-const PlusIcon = () => (
-
-);
+const PlusIcon = () => {
+ const theme = useTheme();
+ return (
+
+ );
+};
const TouchableOpacityComponent = isAndroid ? NativeTouchableOpacity : TouchableOpacity;
-const MinusIcon = () => (
-
-);
+const MinusIcon = () => {
+ const theme = useTheme();
+ return (
+
+ );
+};
export const ListButton: React.FC = (props) => {
return (
theme.colors.backgroundSecondary};
+ background: ${({ theme }) => theme.colors.buttonSecondaryBackground};
height: ${hNs(32)}px;
width: ${ns(32)}px;
border-radius: ${ns(32 / 2)}px;
diff --git a/packages/mobile/src/uikit/NavBar/NavBar.tsx b/packages/mobile/src/uikit/NavBar/NavBar.tsx
index e2b62617b..45e09a64b 100644
--- a/packages/mobile/src/uikit/NavBar/NavBar.tsx
+++ b/packages/mobile/src/uikit/NavBar/NavBar.tsx
@@ -1,6 +1,6 @@
import React, { FC, useCallback, useMemo } from 'react';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
-import { LayoutChangeEvent, View } from 'react-native';
+import { LayoutChangeEvent, StatusBar, View } from 'react-native';
import Animated, {
useAnimatedStyle,
useSharedValue,
@@ -10,12 +10,11 @@ import Animated, {
import * as S from './NavBar.style';
import { NavBarProps } from './NavBar.interface';
import { goBack } from '$navigation/imperative';
-import { Icon } from '../Icon/Icon';
import { useTheme } from '$hooks/useTheme';
import { NavBarHeight } from '$shared/constants';
-import { hNs } from '$utils';
+import { convertHexToRGBA, hNs } from '$utils';
import { Text } from '../Text/Text';
-import { Steezy } from '@tonkeeper/uikit';
+import { Icon, Steezy, isIOS } from '@tonkeeper/uikit';
export const NavBarHelper: FC = () => {
const { top } = useSafeAreaInsets();
@@ -101,7 +100,7 @@ export const NavBar: FC = (props) => {
-
+
@@ -152,9 +151,13 @@ export const NavBar: FC = (props) => {
isTransparent={isTransparent}
isBackground={fillBackground}
>
+ {isModal && isIOS ? : null}
{isTransparent && (
)}
@@ -165,7 +168,7 @@ export const NavBar: FC = (props) => {
disabled={hideBackButton}
>
-
+
diff --git a/packages/mobile/src/uikit/ShowMore/ShowMore.tsx b/packages/mobile/src/uikit/ShowMore/ShowMore.tsx
index ea7e3b2c9..db85fc24e 100644
--- a/packages/mobile/src/uikit/ShowMore/ShowMore.tsx
+++ b/packages/mobile/src/uikit/ShowMore/ShowMore.tsx
@@ -4,22 +4,14 @@ import { TouchableOpacity, View } from 'react-native';
import LinearGradient from 'react-native-linear-gradient';
import { changeAlphaValue, convertHexToRGBA, ns } from '$utils';
import { t } from '@tonkeeper/shared/i18n';
+import { useTheme } from '$hooks/useTheme';
export interface ShowMoreProps {
maxLines: number;
text: string;
- /**
- * Background color for ellipsize button
- */
- backgroundColor?: string;
}
-export const ShowMore: React.FC = ({
- maxLines,
- text,
- backgroundColor = '#1D2633',
-}) => {
-
+export const ShowMore: React.FC = ({ maxLines, text }) => {
const [showEllipsize, setShowEllipsize] = useState(false);
const onTextLayout = useCallback(
(e) => {
@@ -34,6 +26,8 @@ export const ShowMore: React.FC = ({
const handleShowAll = useCallback(() => setShouldShowAll(true), [setShouldShowAll]);
+ const theme = useTheme();
+
function Ellipsize() {
return (
= ({
start={{ x: 0, y: 0 }}
end={{ x: 1, y: 1 }}
colors={[
- changeAlphaValue(convertHexToRGBA(backgroundColor), 0),
- convertHexToRGBA(backgroundColor),
+ changeAlphaValue(convertHexToRGBA(theme.colors.backgroundSecondary), 0),
+ convertHexToRGBA(theme.colors.backgroundSecondary),
]}
style={{ width: ns(24), height: ns(20) }}
/>
-
+
{t('nft_more')}
diff --git a/packages/mobile/src/uikit/Toast/new/ToastComponent.tsx b/packages/mobile/src/uikit/Toast/new/ToastComponent.tsx
index b63f60fca..543f1b3aa 100644
--- a/packages/mobile/src/uikit/Toast/new/ToastComponent.tsx
+++ b/packages/mobile/src/uikit/Toast/new/ToastComponent.tsx
@@ -104,7 +104,7 @@ export const ToastComponent = memo(() => {
{
backgroundColor: toast.warning
? theme.colors.accentOrange
- : theme.colors.backgroundTertiary,
+ : theme.colors.backgroundContentTint,
},
]}
>
diff --git a/packages/mobile/src/utils/color.ts b/packages/mobile/src/utils/color.ts
index 48c2081e2..63a6eb6a9 100644
--- a/packages/mobile/src/utils/color.ts
+++ b/packages/mobile/src/utils/color.ts
@@ -3,7 +3,7 @@ export function changeAlphaValue(rgbaColor: string, newAlphaValue: number): stri
return rgbaColor.replace(regex, `$1 ${newAlphaValue})`);
}
-export function convertHexToRGBA(hex: string): string {
+export function convertHexToRGBA(hex: string, alphaValue = 1): string {
let c: any;
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
c = hex.substring(1).split('');
@@ -11,7 +11,9 @@ export function convertHexToRGBA(hex: string): string {
c = [c[0], c[0], c[1], c[1], c[2], c[2]];
}
c = '0x' + c.join('');
- return 'rgba(' + [(c >> 16) & 255, (c >> 8) & 255, c & 255].join(',') + ',1)';
+ return (
+ 'rgba(' + [(c >> 16) & 255, (c >> 8) & 255, c & 255].join(',') + `,${alphaValue})`
+ );
}
throw new Error('Bad Hex');
}
diff --git a/packages/mobile/src/wallet/Tonkeeper.ts b/packages/mobile/src/wallet/Tonkeeper.ts
index 685bb5b1a..59d76d543 100644
--- a/packages/mobile/src/wallet/Tonkeeper.ts
+++ b/packages/mobile/src/wallet/Tonkeeper.ts
@@ -44,7 +44,7 @@ export interface WalletsStoreState {
wallets: WalletConfig[];
selectedIdentifier: string;
biometryEnabled: boolean;
- lockEnabled: boolean;
+ lockScreenEnabled: boolean;
}
export interface MigrationState {
@@ -79,7 +79,7 @@ export class Tonkeeper {
wallets: [],
selectedIdentifier: '',
biometryEnabled: false,
- lockEnabled: true,
+ lockScreenEnabled: false,
});
public migrationStore = new State({
@@ -112,11 +112,21 @@ export class Tonkeeper {
});
}
- public get wallet() {
- return this.wallets.get(this.walletsStore.data.selectedIdentifier)!;
+ public get wallet(): Wallet {
+ const wallet = this.wallets.get(this.walletsStore.data.selectedIdentifier)!;
+
+ if (!wallet && this.walletsStore.data.wallets.length) {
+ return this.wallets.get(this.walletsStore.data.wallets[0].identifier)!;
+ }
+
+ return wallet;
}
public get walletForUnlock() {
+ if (this.wallet && !this.wallet.isWatchOnly) {
+ return this.wallet;
+ }
+
return Array.from(this.wallets.values()).find((wallet) => !wallet.isWatchOnly)!;
}
@@ -124,8 +134,8 @@ export class Tonkeeper {
return this.walletsStore.data.biometryEnabled;
}
- public get lockEnabled() {
- return this.walletsStore.data.lockEnabled;
+ public get lockScreenEnabled() {
+ return this.walletsStore.data.lockScreenEnabled;
}
public async init() {
@@ -553,10 +563,10 @@ export class Tonkeeper {
}
public async enableLock() {
- await this.walletsStore.setAsync({ lockEnabled: true });
+ await this.walletsStore.setAsync({ lockScreenEnabled: true });
}
public async disableLock() {
- await this.walletsStore.setAsync({ lockEnabled: false });
+ await this.walletsStore.setAsync({ lockScreenEnabled: false });
}
}
diff --git a/packages/mobile/src/wallet/Wallet/WalletContent.ts b/packages/mobile/src/wallet/Wallet/WalletContent.ts
index 3918274a8..e8bdad4f3 100644
--- a/packages/mobile/src/wallet/Wallet/WalletContent.ts
+++ b/packages/mobile/src/wallet/Wallet/WalletContent.ts
@@ -26,6 +26,7 @@ import { TonProofManager } from '../managers/TonProofManager';
import { JettonVerification } from '../models/JettonBalanceModel';
import { CardsManager } from '$wallet/managers/CardsManager';
import { JettonQuantity } from '@tonkeeper/core/src/TonAPI';
+import { WalletContentReceiver } from '../../tabs/Wallet/content-providers/utils/receiver';
export interface WalletStatusState {
isReloading: boolean;
@@ -193,6 +194,33 @@ export class WalletContent extends WalletBase {
]);
}
+ public get totalTon() {
+ const ton = new BigNumber(this.balances.state.data.ton).multipliedBy(
+ this.tonPrice.state.data.ton.fiat,
+ );
+ const jettons = this.jettons.state.data.jettonBalances.reduce((total, jetton) => {
+ const isBlacklisted = jetton.verification === JettonVerification.BLACKLIST;
+ const approvalStatus =
+ this.tokenApproval.state.data.tokens[Address.parse(jetton.jettonAddress).toRaw()];
+ if (
+ (isBlacklisted && !approvalStatus) ||
+ approvalStatus?.current === TokenApprovalStatus.Declined
+ ) {
+ return total;
+ }
+ const rate =
+ this.jettons.state.data.jettonRates[Address.parse(jetton.jettonAddress).toRaw()];
+
+ return rate
+ ? total.plus(new BigNumber(jetton.balance).multipliedBy(rate.ton))
+ : total;
+ }, new BigNumber(0));
+ const staking = new BigNumber(this.staking.state.data.stakingBalance).multipliedBy(
+ this.tonPrice.state.data.ton.fiat,
+ );
+ return ton.plus(jettons).plus(staking).toString();
+ }
+
public get totalFiat() {
const ton = new BigNumber(this.balances.state.data.ton).multipliedBy(
this.tonPrice.state.data.ton.fiat,
diff --git a/packages/router/package.json b/packages/router/package.json
index 4d06a8ec5..b15da01c2 100644
--- a/packages/router/package.json
+++ b/packages/router/package.json
@@ -4,9 +4,9 @@
"main": "./src/index.ts",
"scripts": {},
"dependencies": {
- "@react-navigation/bottom-tabs": "^6.5.8",
- "@react-navigation/native": "^6.1.7",
- "@react-navigation/native-stack": "^6.9.13"
+ "@react-navigation/bottom-tabs": "^6.5.20",
+ "@react-navigation/native": "^6.1.17",
+ "@react-navigation/native-stack": "^6.9.26"
},
"devDependencies": {}
}
diff --git a/packages/shared/components/BatteryIcon/BatteryIcon.tsx b/packages/shared/components/BatteryIcon/BatteryIcon.tsx
index f13c0b7ea..8555140d8 100644
--- a/packages/shared/components/BatteryIcon/BatteryIcon.tsx
+++ b/packages/shared/components/BatteryIcon/BatteryIcon.tsx
@@ -29,25 +29,13 @@ export const BatteryIcon = memo(() => {
return (
<>
-
- {getBatteryState(balance) === BatteryState.Empty ? (
-
- ) : (
-
- )}
+
>
);
diff --git a/packages/shared/components/RefillBattery/RefillBattery.tsx b/packages/shared/components/RefillBattery/RefillBattery.tsx
index 3d6dfcc19..f4e998fdc 100644
--- a/packages/shared/components/RefillBattery/RefillBattery.tsx
+++ b/packages/shared/components/RefillBattery/RefillBattery.tsx
@@ -47,16 +47,14 @@ export const RefillBattery = memo((props) => {
contentContainerStyle={{ paddingBottom: bottomInsets + 16 }}
>
- {batteryState === BatteryState.Empty ? (
-
- ) : (
-
-
-
- )}
+
+
+
{config.get('battery_beta') && (
<>
diff --git a/packages/shared/components/WalletListItem/WalletListItem.tsx b/packages/shared/components/WalletListItem/WalletListItem.tsx
index a22cc1443..02c0151d5 100644
--- a/packages/shared/components/WalletListItem/WalletListItem.tsx
+++ b/packages/shared/components/WalletListItem/WalletListItem.tsx
@@ -11,6 +11,7 @@ import {
isAndroid,
} from '@tonkeeper/uikit';
import { ListItemProps } from '@tonkeeper/uikit/src/components/List/ListItem';
+import { useThemeName } from '@tonkeeper/mobile/src/hooks/useThemeName';
import { FC, memo } from 'react';
import { t } from '../../i18n';
@@ -21,6 +22,8 @@ interface Props extends ListItemProps {
const WalletListItemComponent: FC = (props) => {
const { wallet, ...listItemProps } = props;
+ const themeName = useThemeName();
+
const titleWithTag = wallet.isTestnet || wallet.isWatchOnly;
return (
@@ -38,13 +41,14 @@ const WalletListItemComponent: FC = (props) => {
}
diff --git a/packages/shared/hooks/index.ts b/packages/shared/hooks/index.ts
index faf7be6ea..6d386d70e 100644
--- a/packages/shared/hooks/index.ts
+++ b/packages/shared/hooks/index.ts
@@ -12,3 +12,4 @@ export * from './useBiometrySettings';
export * from './useLockSettings';
export * from './useWalletSetup';
export * from './useIsEnabledForBattery';
+export * from './useDangerLevel';
diff --git a/packages/shared/hooks/useDangerLevel.ts b/packages/shared/hooks/useDangerLevel.ts
new file mode 100644
index 000000000..2d5d2eeaf
--- /dev/null
+++ b/packages/shared/hooks/useDangerLevel.ts
@@ -0,0 +1,27 @@
+import BigNumber from 'bignumber.js';
+import { useWalletSetup } from './useWalletSetup';
+import { useWallet } from './useWallet';
+
+export enum DangerLevel {
+ Normal,
+ Medium,
+ High,
+}
+
+export const useDangerLevel = (inTonRaw: string): DangerLevel => {
+ const { lastBackupAt } = useWalletSetup();
+ const wallet = useWallet();
+
+ if (lastBackupAt !== null || wallet.isWatchOnly) {
+ return DangerLevel.Normal;
+ }
+
+ const inTonBn = new BigNumber(inTonRaw);
+
+ if (inTonBn.gte(20)) {
+ return DangerLevel.High;
+ } else if (inTonBn.gte(2)) {
+ return DangerLevel.Medium;
+ }
+ return DangerLevel.Normal;
+};
diff --git a/packages/shared/hooks/useLockSettings.ts b/packages/shared/hooks/useLockSettings.ts
index c7ba40979..bb5e0e9e0 100644
--- a/packages/shared/hooks/useLockSettings.ts
+++ b/packages/shared/hooks/useLockSettings.ts
@@ -2,10 +2,13 @@ import { tk } from '@tonkeeper/mobile/src/wallet';
import { useExternalState } from './useExternalState';
export const useLockSettings = () => {
- const lockEnabled = useExternalState(tk.walletsStore, (state) => state.lockEnabled);
+ const lockScreenEnabled = useExternalState(
+ tk.walletsStore,
+ (state) => state.lockScreenEnabled,
+ );
return {
- lockEnabled,
- toggleLock: () => (tk.lockEnabled ? tk.disableLock() : tk.enableLock()),
+ lockScreenEnabled,
+ toggleLock: () => (tk.lockScreenEnabled ? tk.disableLock() : tk.enableLock()),
};
};
diff --git a/packages/shared/i18n/locales/tonkeeper/en.json b/packages/shared/i18n/locales/tonkeeper/en.json
index 96196eb9d..7a95c6d44 100644
--- a/packages/shared/i18n/locales/tonkeeper/en.json
+++ b/packages/shared/i18n/locales/tonkeeper/en.json
@@ -650,7 +650,14 @@
"send_sending_wrong_time_description": "Turn on automatic time and date in your device settings. Then retry your transfer.",
"send_sending_wrong_time_title": "Error occurred",
"send_title": "Send %{currency}",
- "settings_appearance": "Theme",
+ "settings_appearance": "Appearance",
+ "settings_theme": "Theme",
+ "settings_theme_names": {
+ "blue": "Deep Blue",
+ "dark": "Dark",
+ "light": "Light",
+ "system": "System"
+ },
"settings_backup_seed": "Backup",
"settings_contact_support": "Contact us",
"settings_delete_account": "Delete account",
@@ -857,7 +864,7 @@
"swap_title": "Swap",
"tab_browser": "Browser",
"tab_nft": "NFTs",
- "tab_collectibles": "Purchases",
+ "tab_collectibles": "Collectibles",
"tab_swap": "Swap",
"tab_wallet": "Wallet",
"today": "Today",
@@ -1168,6 +1175,7 @@
},
"backup_screen": {
"title": "Backup",
+ "backup_warning": "Your balance is %{totalFiat}, and it's only protected by a recovery phrase you haven't written down yet. Backup the phrase to avoid losing funds in case of device issues.",
"manual_title": "Manual",
"manual_caption": "Back up your wallet manually by writing down the recovery phrase.",
"manual_button": "Back Up Manually",
diff --git a/packages/shared/i18n/locales/tonkeeper/ru-RU.json b/packages/shared/i18n/locales/tonkeeper/ru-RU.json
index 7046f0ece..71b7dc202 100644
--- a/packages/shared/i18n/locales/tonkeeper/ru-RU.json
+++ b/packages/shared/i18n/locales/tonkeeper/ru-RU.json
@@ -609,7 +609,14 @@
"send_sending_wrong_time_description" : "Включите автоматическое время и дату в настройках своего устройства. После этого повторите перевод.",
"send_sending_wrong_time_title" : "Произошла ошибка",
"send_title" : "Отправить %{currency}",
- "settings_appearance" : "Тема",
+ "settings_appearance" : "Оформление",
+ "settings_theme" : "Тема",
+ "settings_theme_names": {
+ "blue": "Темно-синяя",
+ "dark": "Тёмная",
+ "light": "Светлая",
+ "system": "Системная"
+ },
"settings_backup_seed" : "Резервная копия",
"settings_contact_support" : "Написать команде",
"settings_delete_account" : "Удалить аккаунт",
@@ -845,7 +852,7 @@
"swap_title" : "Обмен",
"tab_browser" : "Браузер",
"tab_nft" : "NFT",
- "tab_collectibles": "Покупки",
+ "tab_collectibles": "Коллекции",
"tab_settings" : "Настройки",
"tab_swap" : "Обмен",
"tab_wallet" : "Кошелёк",
@@ -1232,6 +1239,7 @@
},
"backup_screen": {
"title": "Резервная копия",
+ "backup_warning": "На вашем балансе %{totalFiat} и он защищён только секретным ключом, который вы ещё не записали. Сделайте резервную копию ключа, чтобы не потерять средства в случае проблем с устройством.",
"manual_title": "Вручную",
"manual_caption": "Создайте резервную копию своего кошелька вручную, записав секретный ключ.",
"manual_button": "Сделать копию вручную",
diff --git a/packages/shared/modals/ActivityActionModal/ActionModalContent.tsx b/packages/shared/modals/ActivityActionModal/ActionModalContent.tsx
index 2fc7b903c..a69a0783a 100644
--- a/packages/shared/modals/ActivityActionModal/ActionModalContent.tsx
+++ b/packages/shared/modals/ActivityActionModal/ActionModalContent.tsx
@@ -197,7 +197,7 @@ export const ActionModalContent = memo((props) => {
)}
-
+
diff --git a/packages/uikit/assets/icons/png/ic-information-circle-24@4x.png b/packages/uikit/assets/icons/png/ic-information-circle-24@4x.png
new file mode 100644
index 000000000..e70f91f21
Binary files /dev/null and b/packages/uikit/assets/icons/png/ic-information-circle-24@4x.png differ
diff --git a/packages/uikit/assets/icons/svg/24/ic-information-circle-24.svg b/packages/uikit/assets/icons/svg/24/ic-information-circle-24.svg
new file mode 100644
index 000000000..17792fa9a
--- /dev/null
+++ b/packages/uikit/assets/icons/svg/24/ic-information-circle-24.svg
@@ -0,0 +1,4 @@
+
diff --git a/packages/uikit/src/components/ActionButton/Separators.tsx b/packages/uikit/src/components/ActionButton/Separators.tsx
index 09717212f..57069bab4 100644
--- a/packages/uikit/src/components/ActionButton/Separators.tsx
+++ b/packages/uikit/src/components/ActionButton/Separators.tsx
@@ -1,8 +1,7 @@
import Svg, { Defs, LinearGradient, Rect, Stop } from 'react-native-svg';
import { Dimensions } from 'react-native';
import React from 'react';
-import { DarkTheme } from '@tonkeeper/uikit/src/styles/themes/dark';
-import { Steezy } from '../../styles';
+import { Steezy, useTheme } from '../../styles';
import { View } from '../View';
const svgWidth = Dimensions.get('window').width - 32;
@@ -54,31 +53,33 @@ let stopPoints = [
0.733333, 0.8, 0.866667, 0.933333, 1,
];
-const stopPointsJSX = stopPoints.map((offset, index) => (
-
-));
-
-const Gradients = () => (
-
- {[
- 'gradientHorizontal',
- 'gradientHorizontalReversed',
- 'gradientVertical',
- 'gradientVerticalReversed',
- ].map((id) => (
-
- {stopPointsJSX}
-
- ))}
-
-);
+const Gradients = () => {
+ const theme = useTheme();
+ return (
+
+ {[
+ 'gradientHorizontal',
+ 'gradientHorizontalReversed',
+ 'gradientVertical',
+ 'gradientVerticalReversed',
+ ].map((id) => (
+
+ {stopPoints.map((offset, index) => (
+
+ ))}
+
+ ))}
+
+ );
+};
function SeparatorsTwoRows() {
+ const theme = useTheme();
return (
);
@@ -64,7 +70,8 @@ export function MappedSvgComponent(props: MappedSvgComponentProps) {
fillRule="evenodd"
clipRule="evenodd"
d="M23.0435 10.0162C23.5411 4.40199 28.2565 0 34.0001 0C39.7437 0 44.4591 4.40199 44.9567 10.0162C53.2387 10.0931 57.9328 10.5333 61.4046 13.0557C62.7629 14.0426 63.9574 15.2371 64.9443 16.5954C68 20.8013 68 26.8009 68 38.8V85.2C68 97.1991 68 103.199 64.9443 107.405C63.9574 108.763 62.7629 109.957 61.4046 110.944C57.1987 114 51.1991 114 39.2 114H28.8C16.8009 114 10.8013 114 6.59544 110.944C5.23712 109.957 4.0426 108.763 3.05573 107.405C0 103.199 0 97.1991 0 85.2V38.8C0 26.8009 0 20.8013 3.05573 16.5954C4.0426 15.2371 5.23712 14.0426 6.59544 13.0557C10.0673 10.5333 14.7614 10.0931 23.0435 10.0162ZM4 35.6C4 26.6006 4 22.101 6.2918 18.9466C7.03195 17.9278 7.92784 17.032 8.94658 16.2918C12.101 14 16.6006 14 25.6 14H42.4C51.3994 14 55.899 14 59.0534 16.2918C60.0722 17.032 60.968 17.9278 61.7082 18.9466C64 22.101 64 26.6006 64 35.6V88.4C64 97.3994 64 101.899 61.7082 105.053C60.968 106.072 60.0722 106.968 59.0534 107.708C55.899 110 51.3994 110 42.4 110H25.6C16.6006 110 12.101 110 8.94658 107.708C7.92784 106.968 7.03195 106.072 6.2918 105.053C4 101.899 4 97.3994 4 88.4V35.6Z"
- fill="#2E3847"
+ fill={theme.iconTertiary}
+ opacity={0.64}
/>
);
@@ -119,17 +126,27 @@ export function AnimatedBatteryIcon(props: AnimatedBatteryIconProps) {
},
]}
>
-
+ {props.empty ? (
+
+
+
+ ) : (
+
+ )}
);
@@ -149,4 +166,9 @@ const styles = Steezy.create(({ colors }) => ({
emptyBatteryBody: {
backgroundColor: colors.accentOrange,
},
+ emptyIconContainer: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
}));
diff --git a/packages/uikit/src/components/Button.tsx b/packages/uikit/src/components/Button.tsx
index f06c28e0a..f07e7f7d5 100644
--- a/packages/uikit/src/components/Button.tsx
+++ b/packages/uikit/src/components/Button.tsx
@@ -99,7 +99,14 @@ export const Button = memo((props) => {
{loading ? (
-
+
) : !!children ? (
{children}
) : (
@@ -111,6 +118,11 @@ export const Button = memo((props) => {
ellipsizeMode="tail"
style={titleStyle}
type={textType}
+ color={
+ ['primary', 'green'].includes(color)
+ ? 'buttonPrimaryForeground'
+ : 'textPrimary'
+ }
>
{title}
diff --git a/packages/uikit/src/components/Icon/Icon.tsx b/packages/uikit/src/components/Icon/Icon.tsx
index 1df0c98f7..aab9aa1f2 100644
--- a/packages/uikit/src/components/Icon/Icon.tsx
+++ b/packages/uikit/src/components/Icon/Icon.tsx
@@ -13,7 +13,10 @@ export type IconColors =
| 'constantWhite'
| 'accentBlue'
| 'accentOrange'
- | 'accentGreen';
+ | 'accentRed'
+ | 'accentGreen'
+ | 'buttonSecondaryForeground'
+ | 'buttonPrimaryForeground';
export interface IconProps {
name: IconNames;
diff --git a/packages/uikit/src/components/Icon/Icon.types.ts b/packages/uikit/src/components/Icon/Icon.types.ts
index 0d0e3bcb0..25d2be6aa 100644
--- a/packages/uikit/src/components/Icon/Icon.types.ts
+++ b/packages/uikit/src/components/Icon/Icon.types.ts
@@ -54,6 +54,7 @@ export type IconNames =
| 'ic-backspace-bold-24'
| 'ic-backup-24'
| 'ic-battery-almost-empty-24'
+ | 'ic-information-circle-24'
| 'ic-key-24'
| 'ic-reset-24'
| 'ic-ton-disabled-24'
@@ -242,6 +243,7 @@ export const AllIcons = [
'ic-backspace-bold-24',
'ic-backup-24',
'ic-battery-almost-empty-24',
+ 'ic-information-circle-24',
'ic-key-24',
'ic-reset-24',
'ic-ton-disabled-24',
@@ -431,6 +433,7 @@ export const IconSizes = {
'ic-backspace-bold-24': 24,
'ic-backup-24': 24,
'ic-battery-almost-empty-24': 24,
+ 'ic-information-circle-24': 24,
'ic-key-24': 24,
'ic-reset-24': 24,
'ic-ton-disabled-24': 24,
diff --git a/packages/uikit/src/components/Icon/IconList.native.ts b/packages/uikit/src/components/Icon/IconList.native.ts
index 84e50d81d..97b6dab47 100644
--- a/packages/uikit/src/components/Icon/IconList.native.ts
+++ b/packages/uikit/src/components/Icon/IconList.native.ts
@@ -54,6 +54,7 @@ export const IconList = {
'ic-backspace-bold-24': require('../../../assets/icons/png/ic-backspace-bold-24.png'),
'ic-backup-24': require('../../../assets/icons/png/ic-backup-24.png'),
'ic-battery-almost-empty-24': require('../../../assets/icons/png/ic-battery-almost-empty-24.png'),
+ 'ic-information-circle-24': require('../../../assets/icons/png/ic-information-circle-24.png'),
'ic-key-24': require('../../../assets/icons/png/ic-key-24.png'),
'ic-reset-24': require('../../../assets/icons/png/ic-reset-24.png'),
'ic-ton-disabled-24': require('../../../assets/icons/png/ic-ton-disabled-24.png'),
diff --git a/packages/uikit/src/components/Input.tsx b/packages/uikit/src/components/Input.tsx
index 008122fdc..3c8ccaef0 100644
--- a/packages/uikit/src/components/Input.tsx
+++ b/packages/uikit/src/components/Input.tsx
@@ -197,7 +197,7 @@ export const Input = forwardRef((props, ref) => {
const containerStaticStyle = {
backgroundColor: colors.fieldBackground,
borderRadius: corners.medium,
- borderColor: colors.fieldBackground,
+ borderColor: 'transparent',
};
const inputStyle = useMemo(
@@ -224,7 +224,7 @@ export const Input = forwardRef((props, ref) => {
borderColor: interpolateColor(
state.value,
[InputState.Unfocused, InputState.Focused, InputState.Invalid],
- [colors.fieldBackground, colors.fieldActiveBorder, colors.fieldErrorBorder],
+ ['transparent', colors.fieldActiveBorder, colors.fieldErrorBorder],
),
}));
@@ -314,7 +314,7 @@ export const Input = forwardRef((props, ref) => {
placeholder={!hasLabel ? placeholder : undefined}
placeholderTextColor={colors.textSecondary}
onChangeText={handleChangeText}
- keyboardAppearance="dark"
+ keyboardAppearance={colors.isDark ? 'dark' : 'light'}
allowFontScaling={false}
scrollEnabled={false}
multiline={multiline}
diff --git a/packages/uikit/src/components/List/List.tsx b/packages/uikit/src/components/List/List.tsx
index aba44cefc..331a440d0 100644
--- a/packages/uikit/src/components/List/List.tsx
+++ b/packages/uikit/src/components/List/List.tsx
@@ -31,17 +31,14 @@ export const List = memo((props) => {
});
}, [props.children]);
-
return (
<>
- {props.headerTitle && (
-
- )}
+ {props.headerTitle && }
{items}
>
- )
+ );
});
const styles = Steezy.create(({ corners, colors }) => ({
@@ -49,9 +46,9 @@ const styles = Steezy.create(({ corners, colors }) => ({
marginBottom: 16,
overflow: 'hidden',
borderRadius: corners.medium,
- backgroundColor: colors.backgroundContent
+ backgroundColor: colors.backgroundContent,
},
indentHorizontal: {
- marginHorizontal: 16
- }
-}));
\ No newline at end of file
+ marginHorizontal: 16,
+ },
+}));
diff --git a/packages/uikit/src/components/RefreshControl.tsx b/packages/uikit/src/components/RefreshControl.tsx
index 401c61f0e..3a9d1f28c 100644
--- a/packages/uikit/src/components/RefreshControl.tsx
+++ b/packages/uikit/src/components/RefreshControl.tsx
@@ -11,7 +11,7 @@ export const RefreshControl = memo((props) => {
);
});
diff --git a/packages/uikit/src/components/SlideButton/SlideButton.tsx b/packages/uikit/src/components/SlideButton/SlideButton.tsx
index 558fed383..cabbb51a1 100644
--- a/packages/uikit/src/components/SlideButton/SlideButton.tsx
+++ b/packages/uikit/src/components/SlideButton/SlideButton.tsx
@@ -25,7 +25,7 @@ export interface SlideButtonProps {
text: string;
}
-const BUTTON_WIDTH = 76;
+const BUTTON_WIDTH = 92;
const SPRING_CONFIG = {
mass: 1.5,
@@ -83,7 +83,7 @@ export const SlideButton = memo((props) => {
-
+
diff --git a/packages/uikit/src/components/Text/Text.tsx b/packages/uikit/src/components/Text/Text.tsx
index 6accefbe6..55bc8e483 100644
--- a/packages/uikit/src/components/Text/Text.tsx
+++ b/packages/uikit/src/components/Text/Text.tsx
@@ -17,10 +17,12 @@ export type TextColors =
| 'textAccent'
| 'textPrimaryAlternate'
| 'accentOrange'
+ | 'accentRed'
| 'accentGreen'
| 'accentBlue'
| 'constantWhite'
- | 'constantBlack';
+ | 'constantBlack'
+ | 'buttonPrimaryForeground';
export interface TextProps extends AnimateProps {
type?: TTextTypes;
diff --git a/packages/uikit/src/components/TextInput.tsx b/packages/uikit/src/components/TextInput.tsx
index 00ec813d0..32e1655aa 100644
--- a/packages/uikit/src/components/TextInput.tsx
+++ b/packages/uikit/src/components/TextInput.tsx
@@ -1,5 +1,5 @@
import { TextInput as GestureTextInput } from 'react-native-gesture-handler';
-import { Steezy, StyleProp } from '../styles';
+import { Steezy, StyleProp, useTheme } from '../styles';
import { forwardRef } from 'react';
import {
TextInputProps as NativeTextInputProps,
@@ -7,14 +7,12 @@ import {
TextStyle,
} from 'react-native';
-
const { useStyle } = Steezy;
export type TextInputProps = Omit & {
component?: React.ComponentType;
style?: StyleProp;
gesture?: boolean;
-
};
export type TextInputRef = NativeTextInput;
@@ -22,9 +20,17 @@ export type TextInputRef = NativeTextInput;
export const TextInput = forwardRef((props, ref) => {
const { gesture, component, style, ...rest } = props;
const styles = useStyle(style);
+ const theme = useTheme();
const Component = gesture ? GestureTextInput : component ?? NativeTextInput;
// @ts-ignore
- return ;
+ return (
+
+ );
});
diff --git a/packages/uikit/src/components/WalletIcon.tsx b/packages/uikit/src/components/WalletIcon.tsx
index 95bc13ec2..61c88aaa2 100644
--- a/packages/uikit/src/components/WalletIcon.tsx
+++ b/packages/uikit/src/components/WalletIcon.tsx
@@ -1,17 +1,18 @@
import { memo } from 'react';
import { StyleProp, Text, TextStyle } from 'react-native';
import { WALLET_ICONS } from '../utils/walletIcons';
-import { Icon, IconNames } from './Icon';
+import { Icon, IconColors, IconNames } from './Icon';
interface WalletIconProps {
value: string;
emojiStyle?: StyleProp;
size?: number;
+ color?: IconColors;
}
export const WalletIcon = memo((props) => {
if (WALLET_ICONS.includes(props.value)) {
- return ;
+ return ;
}
return {props.value};
diff --git a/packages/uikit/src/containers/Modal/ScreenModal/ScreenModal.tsx b/packages/uikit/src/containers/Modal/ScreenModal/ScreenModal.tsx
index 0890f24d6..532016eb8 100644
--- a/packages/uikit/src/containers/Modal/ScreenModal/ScreenModal.tsx
+++ b/packages/uikit/src/containers/Modal/ScreenModal/ScreenModal.tsx
@@ -1,19 +1,27 @@
-import { View, StyleSheet, TouchableWithoutFeedback, TextInput } from 'react-native';
+import { TouchableWithoutFeedback, TextInput } from 'react-native';
import { memo } from 'react';
+import { View } from '../../../components/View';
+import { Steezy } from '../../../styles';
const onRelease = () => TextInput?.State?.currentlyFocusedInput()?.blur?.();
export interface ScreenModalProps {
children?: React.ReactNode;
blurOnBackgroundPress?: boolean;
+ alternateBackground?: boolean;
}
export const ScreenModal = memo((props) => {
if (props.blurOnBackgroundPress) {
return (
-
+
@@ -22,15 +30,24 @@ export const ScreenModal = memo((props) => {
);
}
- return {props.children};
+ return (
+
+ {props.children}
+
+ );
});
-const styles = StyleSheet.create({
+const styles = Steezy.create(({ colors }) => ({
container: {
flex: 1,
},
+ alternateBackground: {
+ backgroundColor: colors.backgroundPageAlternate,
+ },
touchableContainer: {
width: '100%',
height: '100%',
},
-});
+}));
diff --git a/packages/uikit/src/containers/Modal/ScreenModal/ScreenModalHeader.tsx b/packages/uikit/src/containers/Modal/ScreenModal/ScreenModalHeader.tsx
index 2a28a41ef..65b18a1ec 100644
--- a/packages/uikit/src/containers/Modal/ScreenModal/ScreenModalHeader.tsx
+++ b/packages/uikit/src/containers/Modal/ScreenModal/ScreenModalHeader.tsx
@@ -6,6 +6,8 @@ import { Steezy } from '../../../styles';
import { memo } from 'react';
import { isString } from '../../../utils/strings';
import { useNavigation } from '@tonkeeper/router';
+import { StatusBar } from 'react-native';
+import { isIOS } from '../../../utils';
export interface ScreenModalHeaderProps {
children?: React.ReactNode;
@@ -18,13 +20,14 @@ export const ScreenModalHeader = memo((props) => {
return (
+ {isIOS && }
nav.goBack()}
activeOpacity={0.6}
>
-
+
@@ -69,6 +72,6 @@ const styles = Steezy.create(({ colors }) => ({
borderRadius: 32 / 2,
alignItems: 'center',
justifyContent: 'center',
- backgroundColor: colors.backgroundContent,
+ backgroundColor: colors.buttonSecondaryBackground,
},
}));
diff --git a/packages/uikit/src/containers/Modal/SheetModal/SheetModal.tsx b/packages/uikit/src/containers/Modal/SheetModal/SheetModal.tsx
index 2e330b876..b8593cccd 100644
--- a/packages/uikit/src/containers/Modal/SheetModal/SheetModal.tsx
+++ b/packages/uikit/src/containers/Modal/SheetModal/SheetModal.tsx
@@ -25,6 +25,7 @@ export type SheetModalRef = BottomSheetModal;
export type SheetModalProps = Omit & {
children?: React.ReactNode;
+ alternateBackground?: boolean;
};
const ANIMATION_CONFIGS = isIOS
@@ -121,7 +122,9 @@ export const SheetModal = memo(
ref={setRef}
backgroundStyle={{
borderRadius: 18,
- backgroundColor: theme.backgroundPage,
+ backgroundColor: props.alternateBackground
+ ? theme.backgroundPageAlternate
+ : theme.backgroundPage,
}}
>
{props.children}
diff --git a/packages/uikit/src/containers/Modal/SheetModal/SheetModalFooter.tsx b/packages/uikit/src/containers/Modal/SheetModal/SheetModalFooter.tsx
index 5f504b7c6..101b93075 100644
--- a/packages/uikit/src/containers/Modal/SheetModal/SheetModalFooter.tsx
+++ b/packages/uikit/src/containers/Modal/SheetModal/SheetModalFooter.tsx
@@ -12,10 +12,11 @@ export type SheetModalFooterProps = {
relative?: boolean;
style?: ViewStyle;
height?: number;
+ alternateBackground?: boolean;
};
export const SheetModalFooter = React.memo((props: SheetModalFooterProps) => {
- const { style, children, height, relative } = props;
+ const { style, children, height, relative, alternateBackground } = props;
const safeArea = useSafeAreaInsets();
const theme = useTheme();
@@ -47,7 +48,9 @@ export const SheetModalFooter = React.memo((props: SheetModalFooterProps) => {
const contentStyle = {
paddingBottom: safeArea.bottom,
- backgroundColor: theme.backgroundPage,
+ backgroundColor: alternateBackground
+ ? theme.backgroundPageAlternate
+ : theme.backgroundPage,
height,
};
diff --git a/packages/uikit/src/containers/Modal/SheetModal/SheetModalHeader.tsx b/packages/uikit/src/containers/Modal/SheetModal/SheetModalHeader.tsx
index 62014ddae..c42bb4672 100644
--- a/packages/uikit/src/containers/Modal/SheetModal/SheetModalHeader.tsx
+++ b/packages/uikit/src/containers/Modal/SheetModal/SheetModalHeader.tsx
@@ -7,6 +7,7 @@ import { Icon } from '../../../components/Icon';
import { memo, useLayoutEffect } from 'react';
import { useTheme } from '../../../styles';
import Animated, { useAnimatedStyle } from 'react-native-reanimated';
+import { convertHexToRGBA } from '@tonkeeper/mobile/src/utils';
export interface SheetModalHeaderProps {
onIconLeftPress?: () => void;
@@ -75,7 +76,7 @@ export const SheetModalHeader = memo((props) => {
>
{gradient && (
@@ -129,8 +130,10 @@ export const SheetModalHeader = memo((props) => {
onClose?.();
}}
>
-
-
+
+
diff --git a/packages/uikit/src/containers/Screen/Screen.tsx b/packages/uikit/src/containers/Screen/Screen.tsx
index 9c0e43f3a..41dc3f9b3 100644
--- a/packages/uikit/src/containers/Screen/Screen.tsx
+++ b/packages/uikit/src/containers/Screen/Screen.tsx
@@ -4,14 +4,16 @@ import {
useScreenScrollHandler,
} from './hooks/useScreenScroll';
import React, { isValidElement, memo, useMemo } from 'react';
-import { View, StyleSheet } from 'react-native';
import { ScreenLargeHeader } from './ScreenLargeHeader';
import { ScreenHeader } from './ScreenHeader';
import { KeyboardAvoidingContainer } from './KeyboardAvoidingContainer';
+import { Steezy } from '../../styles';
+import { View } from '../../components/View';
interface Props {
children: React.ReactNode;
keyboardAvoiding?: boolean;
+ alternateBackground?: boolean;
}
export const Screen = memo((props) => {
@@ -37,16 +39,35 @@ export const Screen = memo((props) => {
return (
{props.keyboardAvoiding ? (
- {props.children}
+
+
+ {props.children}
+
+
) : (
- {props.children}
+
+ {props.children}
+
)}
);
});
-const styles = StyleSheet.create({
+const styles = Steezy.create(({ colors }) => ({
container: {
flex: 1,
},
-});
+ alternateBackground: {
+ backgroundColor: colors.backgroundPageAlternate,
+ },
+}));
diff --git a/packages/uikit/src/containers/Screen/ScreenButtonContainer.tsx b/packages/uikit/src/containers/Screen/ScreenButtonContainer.tsx
index fe8ad8563..4db599130 100644
--- a/packages/uikit/src/containers/Screen/ScreenButtonContainer.tsx
+++ b/packages/uikit/src/containers/Screen/ScreenButtonContainer.tsx
@@ -5,6 +5,7 @@ import { Steezy, useTheme } from '../../styles';
import { View } from '../../components/View';
import { LinearGradient } from 'expo-linear-gradient';
import { KeyboardAvoidingContainer } from './KeyboardAvoidingContainer';
+import { convertHexToRGBA } from '@tonkeeper/mobile/src/utils';
interface Props extends WithStyleProp {
children: ReactNode;
@@ -27,7 +28,7 @@ export const ScreenButtonContainer: FC = memo(
return (
void;
onGoBack?: () => void;
showCloseButton?: boolean;
+ alternateBackground?: boolean;
}
export const ScreenHeader = memo((props) => {
@@ -55,6 +57,7 @@ export const ScreenHeader = memo((props) => {
onBackPress,
onGoBack,
subtitle,
+ alternateBackground,
} = props;
const { scrollY, headerEjectionPoint } = useScreenScroll();
@@ -134,7 +137,7 @@ export const ScreenHeader = memo((props) => {
style={[
styles.backButton,
backButtonAnimatedStyle,
- { backgroundColor: theme.backgroundContent },
+ { backgroundColor: theme.buttonSecondaryBackground },
]}
>
@@ -154,14 +157,18 @@ export const ScreenHeader = memo((props) => {
{ height: headerHeight },
styles.container,
ejectionShiftStyle,
- !gradient && { backgroundColor: theme.backgroundPage },
+ !gradient && {
+ backgroundColor: alternateBackground
+ ? theme.backgroundPageAlternate
+ : theme.backgroundPage,
+ },
!isModal && { paddingTop: safeArea.top },
styles.absolute,
]}
>
{gradient && (
diff --git a/packages/uikit/src/containers/Screen/ScreenLargeHeader.tsx b/packages/uikit/src/containers/Screen/ScreenLargeHeader.tsx
index 104ece098..da1d1c620 100644
--- a/packages/uikit/src/containers/Screen/ScreenLargeHeader.tsx
+++ b/packages/uikit/src/containers/Screen/ScreenLargeHeader.tsx
@@ -1,5 +1,14 @@
-import { ScreenHeaderHeight, ScreenLargeHeaderDistance, ScreenLargeHeaderHeight } from './utils/constants';
-import Animated, { useAnimatedStyle, interpolate, SharedValue, Extrapolate } from 'react-native-reanimated';
+import {
+ ScreenHeaderHeight,
+ ScreenLargeHeaderDistance,
+ ScreenLargeHeaderHeight,
+} from './utils/constants';
+import Animated, {
+ useAnimatedStyle,
+ interpolate,
+ SharedValue,
+ Extrapolate,
+} from 'react-native-reanimated';
import { TouchableOpacity, Insets, StyleSheet, View } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { deviceHeight, deviceWidth, ns } from '../../utils';
@@ -17,6 +26,7 @@ interface ScreenLargeHeaderProps {
safeArea?: boolean;
border?: boolean;
opacity?: SharedValue;
+ alternateBackground?: boolean;
}
export const ScreenLargeHeader = memo((props) => {
@@ -29,12 +39,13 @@ export const ScreenLargeHeader = memo((props) => {
safeArea = true,
border = true,
opacity,
+ alternateBackground,
} = props;
const { scrollY, headerEjectionPoint } = useScreenScroll();
const { top: topInset } = useSafeAreaInsets();
const theme = useTheme();
-
+
const backgroundStyle = useAnimatedStyle(() => {
return {
opacity: scrollY.value > 0 ? 1 : 0,
@@ -162,7 +173,9 @@ export const ScreenLargeHeader = memo((props) => {
styles.background,
{
height: ScreenHeaderHeight + topInset,
- backgroundColor: theme.backgroundPage,
+ backgroundColor: alternateBackground
+ ? theme.backgroundPageAlternate
+ : theme.backgroundPage,
},
]}
/>
diff --git a/packages/uikit/src/styles/Steezy.ts b/packages/uikit/src/styles/Steezy.ts
index 802834ebb..0987e307a 100644
--- a/packages/uikit/src/styles/Steezy.ts
+++ b/packages/uikit/src/styles/Steezy.ts
@@ -1,8 +1,12 @@
-import { createSteezy, createDynamicStyleVars, createMediaStyleVars } from '@bogoslavskiy/react-native-steezy';
+import {
+ createSteezy,
+ createDynamicStyleVars,
+ createMediaStyleVars,
+} from '@bogoslavskiy/react-native-steezy';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
-import { DarkTheme } from './themes/dark';
import { corners } from './constants';
import { ns } from '../utils';
+import { useTheme } from './contexts/ThemeContext';
export const media = createMediaStyleVars({
isTablet: {
@@ -12,10 +16,11 @@ export const media = createMediaStyleVars({
export const variables = createDynamicStyleVars(() => {
const safeArea = useSafeAreaInsets();
+ const theme = useTheme();
return {
safeArea,
- colors: DarkTheme,
+ colors: theme,
corners,
};
});
diff --git a/packages/uikit/src/styles/contexts/ThemeContext.tsx b/packages/uikit/src/styles/contexts/ThemeContext.tsx
index dc0d50704..a02d69e3b 100644
--- a/packages/uikit/src/styles/contexts/ThemeContext.tsx
+++ b/packages/uikit/src/styles/contexts/ThemeContext.tsx
@@ -1,16 +1,19 @@
import { PropsWithChildren, createContext, memo, useContext } from 'react';
-import { DarkTheme } from '../themes/dark';
+import { BlueTheme } from '../themes/blue';
+import { Theme } from '../themes/theme.type';
-const ThemeContext = createContext(DarkTheme);
+const ThemeContext = createContext(BlueTheme);
-export const ThemeProvider = memo((props) => {
+interface Props extends PropsWithChildren {
+ theme: Theme;
+}
+
+export const ThemeProvider = memo((props) => {
return (
-
- {props.children}
-
- )
+ {props.children}
+ );
});
export const useTheme = () => {
return useContext(ThemeContext);
-};
\ No newline at end of file
+};
diff --git a/packages/uikit/src/styles/index.ts b/packages/uikit/src/styles/index.ts
index 828d55943..f19f33713 100644
--- a/packages/uikit/src/styles/index.ts
+++ b/packages/uikit/src/styles/index.ts
@@ -1,5 +1,5 @@
export { ThemeProvider, useTheme } from './contexts/ThemeContext';
export { StyleProp } from '@bogoslavskiy/react-native-steezy';
-export { Theme } from './themes/theme.type';
+export { Theme, ThemeName } from './themes/theme.type';
export { Steezy } from './Steezy';
export { ViewStyle } from '@bogoslavskiy/react-native-steezy/dist/types';
diff --git a/packages/mobile/src/styles/DarkTheme.ts b/packages/uikit/src/styles/themes/blue.ts
similarity index 52%
rename from packages/mobile/src/styles/DarkTheme.ts
rename to packages/uikit/src/styles/themes/blue.ts
index e40542174..f884cb281 100644
--- a/packages/mobile/src/styles/DarkTheme.ts
+++ b/packages/uikit/src/styles/themes/blue.ts
@@ -1,22 +1,29 @@
-export const DarkTheme = {
+export const BlueTheme = {
+ isDark: true,
+
textPrimary: '#FFFFFF',
textSecondary: '#8994A3',
textTertiary: '#556170',
- textLink: '#45AEF5',
+ textAccent: '#45AEF5',
+ textPrimaryAlternate: '#10161F',
backgroundPage: '#10161F',
- backgroundTransparent: 'rgba(16, 22, 31, 0.92)',
+ backgroundPageAlternate: '#10161F',
+ backgroundTransparent: 'rgba(16, 22, 31, 0.96)',
backgroundContent: '#1D2633',
+ backgroundContentAlternate: '#1D2633',
backgroundContentTint: '#2E3847',
+ backgroundContentAttention: '#424C5C',
+ backgroundHighlighted: 'rgba(79, 90, 112, 0.24)',
backgroundOverlayStrong: 'rgba(0, 0, 0, 0.72)',
backgroundOverlayLight: 'rgba(0, 0, 0, 0.48)',
- backgroundSecondary: '#1D2633',
- backgroundPrimary: '#10161F',
- backgroundTertiary: '#2E3847',
+ backgroundOverlayExtraLight: 'rgba(0, 0, 0, 0.24)',
+ backgroundContentPlaceholder: 'rgba(255, 255, 255, 0.08)',
iconPrimary: '#FFFFFF',
iconSecondary: '#8994A3',
iconTertiary: '#556170',
+ iconPrimaryAlternate: '#10161F',
buttonPrimaryBackground: '#45AEF5',
buttonPrimaryForeground: '#FFFFFF',
@@ -27,7 +34,14 @@ export const DarkTheme = {
buttonPrimaryBackgroundDisabled: '#378AC2',
buttonSecondaryBackgroundDisabled: '#171F29',
buttonTertiaryBackgroundDisabled: '#28303D',
- backgroundContentAttention: '#424C5C',
+ buttonPrimaryBackgroundHighlighted: '#5BB8F6',
+ buttonSecondaryBackgroundHighlighted: '#222C3B',
+ buttonTertiaryBackgroundHighlighted: '#364052',
+
+ buttonPrimaryBackgroundGreen: '#39CC83',
+ buttonPrimaryBackgroundGreenDisabled: '#2B9962',
+ buttonPrimaryBackgroundGreenHighlighted: '#49CC8B',
+ buttonGreenForeground: '#FFFFFF',
fieldBackground: '#1D2633',
fieldActiveBorder: '#45AEF5',
@@ -43,5 +57,12 @@ export const DarkTheme = {
tabBarActiveIcon: '#45AEF5',
tabBarInactiveIcon: '#8994A3',
- separatorCommon: 'rgba(194, 218, 255, 0.08)',
+ separatorCommon: 'rgba(79, 90, 112, 0.24)',
+ separatorAlternate: 'rgba(255, 255, 255, 0.08)',
+ separatorActionButtons: '#1F2632',
+
+ constantBlack: '#000000',
+ constantWhite: '#FFFFFF',
+ constantBlue: '#0077FF',
+ constantRed: '#FF3B30',
};
diff --git a/packages/uikit/src/styles/themes/dark.ts b/packages/uikit/src/styles/themes/dark.ts
index 030c7ea75..f15de5b89 100644
--- a/packages/uikit/src/styles/themes/dark.ts
+++ b/packages/uikit/src/styles/themes/dark.ts
@@ -1,44 +1,49 @@
export const DarkTheme = {
- textPrimary: '#FFFFFF',
- textSecondary: '#8994A3',
- textTertiary: '#556170',
+ isDark: true,
+
+ textPrimary: '#D9D9D9',
+ textSecondary: '#8D8D93',
+ textTertiary: '#4E4E52',
textAccent: '#45AEF5',
- textPrimaryAlternate: '#10161F',
+ textPrimaryAlternate: '#000000',
- backgroundPage: '#10161F',
- backgroundTransparent: 'rgba(16, 22, 31, 0.96)',
- backgroundContent: '#1D2633',
- backgroundContentTint: '#2E3847',
- backgroundContentAttention: '#424C5C',
- backgroundHighlighted: 'rgba(79, 90, 112, 0.24)',
- backgroundOverlayStrong: 'rgba(0, 0, 0, 0.72)',
- backgroundOverlayLight: 'rgba(0, 0, 0, 0.48)',
- backgroundOverlayExtraLight: 'rgba(0, 0, 0, 0.24)',
+ backgroundPage: '#000000',
+ backgroundPageAlternate: '#000000',
+ backgroundTransparent: 'rgba(0, 0, 0, 0.96)',
+ backgroundContent: '#17171A',
+ backgroundContentAlternate: '#17171A',
+ backgroundContentTint: '#272729',
+ backgroundContentAttention: '#2F2F33',
+ backgroundHighlighted: 'rgba(255, 255, 255, 0.04)',
+ backgroundOverlayStrong: 'rgba(20, 20, 20, 0.72)',
+ backgroundOverlayLight: 'rgba(20, 20, 20, 0.48)',
+ backgroundOverlayExtraLight: 'rgba(20, 20, 20, 0.24)',
+ backgroundContentPlaceholder: 'rgba(255, 255, 255, 0.08)',
- iconPrimary: '#FFFFFF',
- iconSecondary: '#8994A3',
- iconTertiary: '#556170',
- iconPrimaryAlternate: '#10161F',
+ iconPrimary: '#EBEBEB',
+ iconSecondary: '#8D8D93',
+ iconTertiary: '#4E4E52',
+ iconPrimaryAlternate: '#000000',
buttonPrimaryBackground: '#45AEF5',
buttonPrimaryForeground: '#FFFFFF',
- buttonSecondaryBackground: '#1D2633',
- buttonSecondaryForeground: '#FFFFFF',
- buttonTertiaryBackground: '#2E3847',
- buttonTertiaryForeground: '#FFFFFF',
+ buttonSecondaryBackground: '#1B1B1F',
+ buttonSecondaryForeground: '#EBEBEB',
+ buttonTertiaryBackground: '#2B2B2E',
+ buttonTertiaryForeground: '#EBEBEB',
buttonPrimaryBackgroundDisabled: '#378AC2',
- buttonSecondaryBackgroundDisabled: '#171F29',
- buttonTertiaryBackgroundDisabled: '#28303D',
+ buttonSecondaryBackgroundDisabled: '#0E0E0F',
+ buttonTertiaryBackgroundDisabled: '#18181A',
buttonPrimaryBackgroundHighlighted: '#5BB8F6',
- buttonSecondaryBackgroundHighlighted: '#222C3B',
- buttonTertiaryBackgroundHighlighted: '#364052',
+ buttonSecondaryBackgroundHighlighted: '#242429',
+ buttonTertiaryBackgroundHighlighted: '#353538',
buttonPrimaryBackgroundGreen: '#39CC83',
buttonPrimaryBackgroundGreenDisabled: '#2B9962',
buttonPrimaryBackgroundGreenHighlighted: '#49CC8B',
buttonGreenForeground: '#FFFFFF',
- fieldBackground: '#1D2633',
+ fieldBackground: '#17171A',
fieldActiveBorder: '#45AEF5',
fieldErrorBorder: '#FF4766',
fieldErrorBackground: 'rgba(255, 71, 102, 0.08)',
@@ -50,35 +55,11 @@ export const DarkTheme = {
accentPurple: '#7665E5',
tabBarActiveIcon: '#45AEF5',
- tabBarInactiveIcon: '#8994A3',
-
- separatorCommon: 'rgba(79, 90, 112, 0.24)',
- separatorAlternate: 'rgba(255, 255, 255, 0.08)',
+ tabBarInactiveIcon: '#8D8D93',
- gradientBackgroundTop: {
- from: 'rgba(16, 22, 31, 1)',
- to: 'rgba(16, 22, 31, 0)',
- },
- gradientBackgroundBottom: {
- from: 'rgba(16, 22, 31, 1)',
- to: 'rgba(16, 22, 31, 0)',
- },
- gradientBlueTop: {
- from: 'rgba(69, 174, 245, 1)',
- to: 'rgba(69, 174, 245, 0)',
- },
- gradientBlueBottom: {
- from: 'rgba(69, 174, 245, 1)',
- to: 'rgba(69, 174, 245, 0)',
- },
- gradientGreen: {
- from: 'rgba(57, 204, 131, 1)',
- to: 'rgba(57, 204, 131, 0)',
- },
- gradientRed: {
- from: 'rgba(255, 71, 102, 1)',
- to: 'rgba(255, 71, 102, 0)',
- },
+ separatorCommon: 'rgba(255, 255, 255, 0.12)',
+ separatorAlternate: 'rgba(255, 255, 255, 0.12)',
+ separatorActionButtons: '#1F1F1F',
constantBlack: '#000000',
constantWhite: '#FFFFFF',
diff --git a/packages/uikit/src/styles/themes/light.ts b/packages/uikit/src/styles/themes/light.ts
new file mode 100644
index 000000000..ca87b8a4f
--- /dev/null
+++ b/packages/uikit/src/styles/themes/light.ts
@@ -0,0 +1,68 @@
+export const LightTheme = {
+ isDark: false,
+
+ textPrimary: '#000000',
+ textSecondary: '#818C99',
+ textTertiary: '#95A0AD',
+ textAccent: '#007AFF',
+ textPrimaryAlternate: '#FFFFFF',
+
+ backgroundPage: '#EFEEF3',
+ backgroundPageAlternate: '#FFFFFF',
+ backgroundTransparent: 'rgba(255, 255, 255, 0.96)',
+ backgroundContent: '#FFFFFF',
+ backgroundContentAlternate: '#EFEEF3',
+ backgroundContentTint: '#E7E6EB',
+ backgroundContentAttention: '#F0F0F0',
+ backgroundHighlighted: 'rgba(129, 140, 153, 0.08)',
+ backgroundOverlayStrong: 'rgba(20, 20, 20, 0.72)',
+ backgroundOverlayLight: 'rgba(20, 20, 20, 0.48)',
+ backgroundOverlayExtraLight: 'rgba(20, 20, 20, 0.24)',
+ backgroundContentPlaceholder: 'rgba(0, 0, 0, 0.08)',
+
+ iconPrimary: '#000000',
+ iconSecondary: '#818C99',
+ iconTertiary: '#95A0AD',
+ iconPrimaryAlternate: '#FFFFFF',
+
+ buttonPrimaryBackground: '#007AFF',
+ buttonPrimaryForeground: '#FFFFFF',
+ buttonSecondaryBackground: 'rgba(129, 140, 153, 0.16)',
+ buttonSecondaryForeground: '#000000',
+ buttonTertiaryBackground: 'rgba(129, 140, 153, 0.12)',
+ buttonTertiaryForeground: '#000000',
+ buttonPrimaryBackgroundDisabled: '#3D9AFF',
+ buttonSecondaryBackgroundDisabled: 'rgba(129, 140, 153, 0.12)',
+ buttonTertiaryBackgroundDisabled: 'rgba(129, 140, 153, 0.08)',
+ buttonPrimaryBackgroundHighlighted: '#1F8AFF',
+ buttonSecondaryBackgroundHighlighted: 'rgba(129, 140, 153, 0.24)',
+ buttonTertiaryBackgroundHighlighted: 'rgba(129, 140, 153, 0.20)',
+
+ buttonPrimaryBackgroundGreen: '#25B86F',
+ buttonPrimaryBackgroundGreenDisabled: '#2B9962',
+ buttonPrimaryBackgroundGreenHighlighted: '#17C26D',
+ buttonGreenForeground: '#FFFFFF',
+
+ fieldBackground: 'rgba(129, 140, 153, 0.12)',
+ fieldActiveBorder: '#007AFF',
+ fieldErrorBorder: '#FF3B30',
+ fieldErrorBackground: 'rgba(255, 59, 48, 0.08)',
+
+ accentBlue: '#007AFF',
+ accentGreen: '#25B86F',
+ accentRed: '#FF3B30',
+ accentOrange: '#F5A73B',
+ accentPurple: '#7665E5',
+
+ tabBarActiveIcon: '#007AFF',
+ tabBarInactiveIcon: '#95A0AD',
+
+ separatorCommon: 'rgba(60, 60, 67, 0.08)',
+ separatorAlternate: 'rgba(60, 60, 67, 0.08)',
+ separatorActionButtons: '#E1E0E5',
+
+ constantBlack: '#000000',
+ constantWhite: '#FFFFFF',
+ constantBlue: '#0077FF',
+ constantRed: '#FF3B30',
+};
diff --git a/packages/uikit/src/styles/themes/theme.type.ts b/packages/uikit/src/styles/themes/theme.type.ts
index 11093d187..af56a01ae 100644
--- a/packages/uikit/src/styles/themes/theme.type.ts
+++ b/packages/uikit/src/styles/themes/theme.type.ts
@@ -1,13 +1,11 @@
-import { DarkTheme } from './dark';
+import { BlueTheme } from './blue';
-type ThemeGradient =
- | 'gradientBackgroundTop'
- | 'gradientBackgroundBottom'
- | 'gradientBlueTop'
- | 'gradientBlueBottom'
- | 'gradientGreen'
- | 'gradientRed';
-
-export type Theme = Omit;
+export type Theme = typeof BlueTheme;
export type ThemeKeys = keyof Theme;
+
+export enum ThemeName {
+ Dark = 'dark',
+ Light = 'light',
+ Blue = 'blue',
+}
diff --git a/packages/uikit/src/styles/utils.ts b/packages/uikit/src/styles/utils.ts
new file mode 100644
index 000000000..6d48e2f5d
--- /dev/null
+++ b/packages/uikit/src/styles/utils.ts
@@ -0,0 +1,16 @@
+import { BlueTheme } from './themes/blue';
+import { DarkTheme } from './themes/dark';
+import { LightTheme } from './themes/light';
+import { Theme, ThemeName } from './themes/theme.type';
+
+export const getThemeByName = (name: ThemeName): Theme => {
+ if (name === ThemeName.Dark) {
+ return DarkTheme;
+ }
+
+ if (name === ThemeName.Light) {
+ return LightTheme;
+ }
+
+ return BlueTheme;
+};
diff --git a/packages/uikit/src/utils/walletColor.ts b/packages/uikit/src/utils/walletColor.ts
index 9222cc7a5..083b3b0c7 100644
--- a/packages/uikit/src/utils/walletColor.ts
+++ b/packages/uikit/src/utils/walletColor.ts
@@ -1,3 +1,5 @@
+import { ThemeName } from '../styles';
+
export enum WalletColor {
SteelGray = 'SteelGray',
LightSteelGray = 'LightSteelGray',
@@ -24,7 +26,7 @@ export enum WalletColor {
FireOrange = 'FireOrange',
}
-const DARK_THEME_COLORS = {
+const BLUE_THEME_COLORS = {
[WalletColor.SteelGray]: '#293342',
[WalletColor.LightSteelGray]: '#424C5C',
[WalletColor.Gray]: '#9DA2A4',
@@ -50,6 +52,26 @@ const DARK_THEME_COLORS = {
[WalletColor.FireOrange]: '#FF525D',
};
-export const getWalletColorHex = (color: WalletColor) => {
- return DARK_THEME_COLORS[color];
+const DARK_THEME_COLORS = {
+ ...BLUE_THEME_COLORS,
+ [WalletColor.SteelGray]: '#2F2F33',
+ [WalletColor.LightSteelGray]: '#4E4E52',
+ [WalletColor.Gray]: '#8D8D93',
+};
+
+const LIGHT_THEME_COLORS = {
+ ...BLUE_THEME_COLORS,
+ [WalletColor.SteelGray]: '#818C99',
+ [WalletColor.LightSteelGray]: '#95A0AD',
+ [WalletColor.Gray]: '#B6BBC2',
+};
+
+export const getWalletColorHex = (color: WalletColor, themeName: ThemeName) => {
+ if (themeName === ThemeName.Dark) {
+ return DARK_THEME_COLORS[color];
+ }
+ if (themeName === ThemeName.Light) {
+ return LIGHT_THEME_COLORS[color];
+ }
+ return BLUE_THEME_COLORS[color];
};
diff --git a/yarn.lock b/yarn.lock
index 32800be05..a9f54b67d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2553,13 +2553,20 @@
resolved "https://registry.yarnpkg.com/@react-dnd/shallowequal/-/shallowequal-2.0.0.tgz#a3031eb54129f2c66b2753f8404266ec7bf67f0a"
integrity sha512-Pc/AFTdwZwEKJxFJvlxrSmGe/di+aAOBn60sremrpLo6VI/6cmiUYNNwlI5KNYttg7uypzA3ILPMPgxB2GYZEg==
-"@react-native-async-storage/async-storage@^1.13.4", "@react-native-async-storage/async-storage@^1.15.5":
+"@react-native-async-storage/async-storage@^1.13.4":
version "1.19.1"
resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.19.1.tgz#09d35caaa31823b40fdfeebf95decf8f992a6274"
integrity sha512-5QXuGCtB+HL3VtKL2JN3+6t4qh8VXizK+aGDAv6Dqiq3MLrzgZHb4tjVgtEWMd8CcDtD/JqaAI1b6/EaYGtFIA==
dependencies:
merge-options "^3.0.4"
+"@react-native-async-storage/async-storage@^1.23.1":
+ version "1.23.1"
+ resolved "https://registry.yarnpkg.com/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz#cad3cd4fab7dacfe9838dce6ecb352f79150c883"
+ integrity sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA==
+ dependencies:
+ merge-options "^3.0.4"
+
"@react-native-community/cli-clean@11.3.7":
version "11.3.7"
resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-11.3.7.tgz#cb4c2f225f78593412c2d191b55b8570f409a48f"
@@ -2839,46 +2846,46 @@
invariant "^2.2.4"
nullthrows "^1.1.1"
-"@react-navigation/bottom-tabs@^6.5.8":
- version "6.5.8"
- resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.8.tgz#9536c6e45154abc183c363d07c94991e10b14856"
- integrity sha512-0aa/jXea+LyBgR5NoRNWGKw0aFhjHwCkusigMRXIrCA4kINauDcAO0w0iFbZeKfaTCVAix5kK5UxDJJ2aJpevg==
+"@react-navigation/bottom-tabs@^6.5.20":
+ version "6.5.20"
+ resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.20.tgz#5335e75b02c527ef0569bd97d4f9185d65616e49"
+ integrity sha512-ow6Z06iS4VqBO8d7FP+HsGjJLWt2xTWIvuWjpoCvsM/uQXzCRDIjBv9HaKcXbF0yTW7IMir0oDAbU5PFzEDdgA==
dependencies:
- "@react-navigation/elements" "^1.3.18"
+ "@react-navigation/elements" "^1.3.30"
color "^4.2.3"
warn-once "^0.1.0"
-"@react-navigation/core@^6.4.9":
- version "6.4.9"
- resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.9.tgz#aa09ce534f5393427cb993cf242abdbd848fb2c7"
- integrity sha512-G9GH7bP9x0qqupxZnkSftnkn4JoXancElTvFc8FVGfEvxnxP+gBo3wqcknyBi7M5Vad4qecsYjCOa9wqsftv9g==
+"@react-navigation/core@^6.4.16":
+ version "6.4.16"
+ resolved "https://registry.yarnpkg.com/@react-navigation/core/-/core-6.4.16.tgz#f9369a134805174536b9aa0f0f483b930511caf9"
+ integrity sha512-UDTJBsHxnzgFETR3ZxhctP+RWr4SkyeZpbhpkQoIGOuwSCkt1SE0qjU48/u6r6w6XlX8OqVudn1Ab0QFXTHxuQ==
dependencies:
"@react-navigation/routers" "^6.1.9"
escape-string-regexp "^4.0.0"
nanoid "^3.1.23"
query-string "^7.1.3"
react-is "^16.13.0"
- use-latest-callback "^0.1.5"
+ use-latest-callback "^0.1.9"
-"@react-navigation/elements@^1.3.18":
- version "1.3.18"
- resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.18.tgz#d8364b40276f3efb9c229c39da3b8b465f18f0a2"
- integrity sha512-/0hwnJkrr415yP0Hf4PjUKgGyfshrvNUKFXN85Mrt1gY49hy9IwxZgrrxlh0THXkPeq8q4VWw44eHDfAcQf20Q==
+"@react-navigation/elements@^1.3.30":
+ version "1.3.30"
+ resolved "https://registry.yarnpkg.com/@react-navigation/elements/-/elements-1.3.30.tgz#a81371f599af1070b12014f05d6c09b1a611fd9a"
+ integrity sha512-plhc8UvCZs0UkV+sI+3bisIyn78wz9O/BiWZXpounu72k/R/Sj5PuZYFJ1fi6psvriUveMCGh4LeZckAZu2qiQ==
-"@react-navigation/native-stack@^6.9.13":
- version "6.9.13"
- resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.13.tgz#f308c398ee18fcd45de8ec7c04fe0641735feb31"
- integrity sha512-ejlepMrvFneewL+XlXHHhn+6y3lwvavM4/R7XwBV0XJxCymujexK+7Vkg7UcvJ1lx4CRhOcyBSNfGmdNIHREyQ==
+"@react-navigation/native-stack@^6.9.26":
+ version "6.9.26"
+ resolved "https://registry.yarnpkg.com/@react-navigation/native-stack/-/native-stack-6.9.26.tgz#90facf7783c9927f094bc9f01c613af75b6c241e"
+ integrity sha512-++dueQ+FDj2XkZ902DVrK79ub1vp19nSdAZWxKRgd6+Bc0Niiesua6rMCqymYOVaYh+dagwkA9r00bpt/U5WLw==
dependencies:
- "@react-navigation/elements" "^1.3.18"
+ "@react-navigation/elements" "^1.3.30"
warn-once "^0.1.0"
-"@react-navigation/native@^6.1.7":
- version "6.1.7"
- resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.7.tgz#968ef85b76d35f63111890668836fe2f125bbf90"
- integrity sha512-W6E3+AtTombMucCRo6q7vPmluq8hSjS+IxfazJ/SokOe7ChJX7eLvvralIsJkjFj3iWV1KgOSnHxa6hdiFasBw==
+"@react-navigation/native@^6.1.17":
+ version "6.1.17"
+ resolved "https://registry.yarnpkg.com/@react-navigation/native/-/native-6.1.17.tgz#439f15a99809d26ea4682d2a3766081cf2ca31cf"
+ integrity sha512-mer3OvfwWOHoUSMJyLa4vnBH3zpFmCwuzrBPlw7feXklurr/ZDiLjLxUScOot6jLRMz/67GyilEYMmP99LL0RQ==
dependencies:
- "@react-navigation/core" "^6.4.9"
+ "@react-navigation/core" "^6.4.16"
escape-string-regexp "^4.0.0"
fast-deep-equal "^3.1.3"
nanoid "^3.1.23"
@@ -15195,10 +15202,10 @@ url@^0.11.0:
punycode "^1.4.1"
qs "^6.11.0"
-use-latest-callback@^0.1.5:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.6.tgz#3fa6e7babbb5f9bfa24b5094b22939e1e92ebcf6"
- integrity sha512-VO/P91A/PmKH9bcN9a7O3duSuxe6M14ZoYXgA6a8dab8doWNdhiIHzEkX/jFeTTRBsX0Ubk6nG4q2NIjNsj+bg==
+use-latest-callback@^0.1.9:
+ version "0.1.9"
+ resolved "https://registry.yarnpkg.com/use-latest-callback/-/use-latest-callback-0.1.9.tgz#10191dc54257e65a8e52322127643a8940271e2a"
+ integrity sha512-CL/29uS74AwreI/f2oz2hLTW7ZqVeV5+gxFeGudzQrgkCytrHw33G4KbnQOrRlAEzzAFXi7dDLMC9zhWcVpzmw==
use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0:
version "1.2.0"