diff --git a/android/app/build.gradle b/android/app/build.gradle index 1d5f8e41a..c63a02d18 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -109,6 +109,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation fileTree(dir: "libs", include: ["*.jar"]) implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.google.android.material:material:1.4.0' } apply plugin: 'com.google.gms.google-services' // Google Services plugin diff --git a/android/app/src/main/java/io/bluewallet/bluewallet/CustomSegmentControlPackage.java b/android/app/src/main/java/io/bluewallet/bluewallet/CustomSegmentControlPackage.java new file mode 100644 index 000000000..7e2d4a3c6 --- /dev/null +++ b/android/app/src/main/java/io/bluewallet/bluewallet/CustomSegmentControlPackage.java @@ -0,0 +1,26 @@ +package io.bluewallet.bluewallet; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.uimanager.ViewManager; +import com.facebook.react.bridge.ReactApplicationContext; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class CustomSegmentControlPackage implements ReactPackage { + + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + CustomSegmentedControlManager.registerIfNecessary(); + List viewManagers = new ArrayList<>(); + viewManagers.add(new CustomSegmentedControlManager()); + return viewManagers; + } +} diff --git a/android/app/src/main/java/io/bluewallet/bluewallet/CustomSegmentedControlManager.java b/android/app/src/main/java/io/bluewallet/bluewallet/CustomSegmentedControlManager.java new file mode 100644 index 000000000..ad70cd656 --- /dev/null +++ b/android/app/src/main/java/io/bluewallet/bluewallet/CustomSegmentedControlManager.java @@ -0,0 +1,100 @@ +package io.bluewallet.bluewallet; + +import android.content.Context; +import android.widget.LinearLayout; +import androidx.annotation.NonNull; +import com.facebook.react.uimanager.SimpleViewManager; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.annotations.ReactProp; +import com.google.android.material.tabs.TabLayout; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.WritableMap; +import com.facebook.react.uimanager.events.RCTEventEmitter; + +public class CustomSegmentedControlManager extends SimpleViewManager { + public static final String REACT_CLASS = "CustomSegmentedControl"; + private static boolean isRegistered = false; + + public static class CustomSegmentedControlView extends LinearLayout { + private TabLayout tabLayout; + private RCTEventEmitter eventEmitter; + private int viewId; + + public CustomSegmentedControlView(Context context) { + super(context); + setOrientation(LinearLayout.HORIZONTAL); + tabLayout = new TabLayout(context); + addView(tabLayout, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); + + tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { + @Override + public void onTabSelected(TabLayout.Tab tab) { + WritableMap event = Arguments.createMap(); + event.putInt("selectedIndex", tab.getPosition()); + if (eventEmitter != null) { + eventEmitter.receiveEvent(viewId, "topChange", event); + } + } + + @Override + public void onTabUnselected(TabLayout.Tab tab) {} + + @Override + public void onTabReselected(TabLayout.Tab tab) {} + }); + } + + public void setValues(ReadableArray values) { + tabLayout.removeAllTabs(); + for (int i = 0; i < values.size(); i++) { + tabLayout.addTab(tabLayout.newTab().setText(values.getString(i))); + } + } + + public void setSelectedIndex(int selectedIndex) { + if (selectedIndex >= 0 && selectedIndex < tabLayout.getTabCount()) { + TabLayout.Tab tab = tabLayout.getTabAt(selectedIndex); + if (tab != null) { + tab.select(); + } + } + } + + public void setEventEmitter(RCTEventEmitter eventEmitter, int viewId) { + this.eventEmitter = eventEmitter; + this.viewId = viewId; + } + } + + @NonNull + @Override + public String getName() { + return REACT_CLASS; + } + + @NonNull + @Override + protected CustomSegmentedControlView createViewInstance(@NonNull ThemedReactContext reactContext) { + CustomSegmentedControlView view = new CustomSegmentedControlView(reactContext); + view.setEventEmitter(reactContext.getJSModule(RCTEventEmitter.class), view.getId()); + return view; + } + + @ReactProp(name = "values") + public void setValues(CustomSegmentedControlView view, ReadableArray values) { + view.setValues(values); + } + + @ReactProp(name = "selectedIndex") + public void setSelectedIndex(CustomSegmentedControlView view, int selectedIndex) { + view.setSelectedIndex(selectedIndex); + } + + public static void registerIfNecessary() { + if (!isRegistered) { + isRegistered = true; + // Registration logic if necessary + } + } +} diff --git a/android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java b/android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java index 2b769de87..368359c01 100644 --- a/android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java +++ b/android/app/src/main/java/io/bluewallet/bluewallet/MainApplication.java @@ -31,7 +31,8 @@ public class MainApplication extends Application implements ReactApplication { @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); // Packages that cannot be autolinked yet can be added manually here, for example: - // packages.add(new MyReactNativePackage()); + packages.add(new CustomSegmentControlPackage()); + CustomSegmentedControlManager.registerIfNecessary(); return packages; } @@ -40,15 +41,15 @@ public class MainApplication extends Application implements ReactApplication { return "index"; } - @Override - protected boolean isNewArchEnabled() { - return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; - } - - @Override - protected Boolean isHermesEnabled() { - return BuildConfig.IS_HERMES_ENABLED; - } + @Override + protected boolean isNewArchEnabled() { + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + } + + @Override + protected Boolean isHermesEnabled() { + return BuildConfig.IS_HERMES_ENABLED; + } }; @Override @@ -62,19 +63,19 @@ public class MainApplication extends Application implements ReactApplication { I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance(); sharedI18nUtilInstance.allowRTL(getApplicationContext(), true); SoLoader.init(this, /* native exopackage */ false); - if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { - // If you opted-in for the New Architecture, we load the native entry point for this app. - DefaultNewArchitectureEntryPoint.load(); - } - SharedPreferences sharedPref = getApplicationContext().getSharedPreferences("group.io.bluewallet.bluewallet", Context.MODE_PRIVATE); + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + DefaultNewArchitectureEntryPoint.load(); + } + SharedPreferences sharedPref = getApplicationContext().getSharedPreferences("group.io.bluewallet.bluewallet", Context.MODE_PRIVATE); - // Retrieve the "donottrack" value. Default to "0" if not found. - String isDoNotTrackEnabled = sharedPref.getString("donottrack", "0"); + // Retrieve the "donottrack" value. Default to "0" if not found. + String isDoNotTrackEnabled = sharedPref.getString("donottrack", "0"); - // Check if do not track is not enabled and initialize Bugsnag if so - if (!isDoNotTrackEnabled.equals("1")) { - // Initialize Bugsnag or your error tracking here - Bugsnag.start(this); - } + // Check if do not track is not enabled and initialize Bugsnag if so + if (!isDoNotTrackEnabled.equals("1")) { + // Initialize Bugsnag or your error tracking here + Bugsnag.start(this); + } } } diff --git a/android/app/src/main/java/io/bluewallet/MarketAPI.java b/android/app/src/main/java/io/bluewallet/bluewallet/MarketAPI.java similarity index 100% rename from android/app/src/main/java/io/bluewallet/MarketAPI.java rename to android/app/src/main/java/io/bluewallet/bluewallet/MarketAPI.java diff --git a/components/SegmentControl.tsx b/components/SegmentControl.tsx new file mode 100644 index 000000000..317b5d195 --- /dev/null +++ b/components/SegmentControl.tsx @@ -0,0 +1,44 @@ +import React from 'react'; +import { requireNativeComponent, View, StyleSheet, NativeSyntheticEvent } from 'react-native'; + +interface SegmentedControlProps { + values: string[]; + selectedIndex: number; + onChange: (index: number) => void; +} + +interface SegmentedControlEvent { + selectedIndex: number; +} + +interface NativeSegmentedControlProps { + values: string[]; + selectedIndex: number; + onChangeEvent: (event: NativeSyntheticEvent) => void; + style?: object; +} + +const NativeSegmentedControl = requireNativeComponent('CustomSegmentedControl'); + +const SegmentedControl: React.FC = ({ values, selectedIndex, onChange }) => { + const handleChange = (event: NativeSyntheticEvent) => { + onChange(event.nativeEvent.selectedIndex); + }; + + return ( + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + width: '100%', + }, + segmentedControl: { + height: 40, + }, +}); + +export default SegmentedControl; diff --git a/components/addresses/AddressTypeTabs.tsx b/components/addresses/AddressTypeTabs.tsx deleted file mode 100644 index 6ce64e708..000000000 --- a/components/addresses/AddressTypeTabs.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import React from 'react'; -import { StyleSheet, Text, View, Pressable, LayoutAnimation, Platform, UIManager, ViewStyle, TextStyle } from 'react-native'; -import loc from '../../loc'; -import { useTheme } from '../themes'; - -export const TABS = { - EXTERNAL: 'receive', - INTERNAL: 'change', -} as const; - -type TabKey = keyof typeof TABS; -type TABS_VALUES = (typeof TABS)[keyof typeof TABS]; - -if (Platform.OS === 'android' && UIManager.setLayoutAnimationEnabledExperimental) { - UIManager.setLayoutAnimationEnabledExperimental(true); -} - -interface AddressTypeTabsProps { - currentTab: TABS_VALUES; - setCurrentTab: (tab: TABS_VALUES) => void; - customTabText?: { [key in TabKey]?: string }; -} - -const AddressTypeTabs: React.FC = ({ currentTab, setCurrentTab, customTabText }) => { - const { colors } = useTheme(); - - const stylesHook = StyleSheet.create({ - activeTab: { - backgroundColor: colors.modal, - } as ViewStyle, - activeText: { - fontWeight: 'bold', - color: colors.foregroundColor, - } as TextStyle, - inactiveTab: { - fontWeight: 'normal', - color: colors.foregroundColor, - } as TextStyle, - backTabs: { - backgroundColor: colors.buttonDisabledBackgroundColor, - } as ViewStyle, - }); - - const tabs = Object.entries(TABS).map(([key, value]) => { - return { - key: key as TabKey, - value, - name: customTabText?.[key as TabKey] || loc.addresses[`type_${value}`], - }; - }); - - const changeToTab = (tabKey: TabKey) => { - if (tabKey in TABS) { - LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); - setCurrentTab(TABS[tabKey]); - } - }; - - const render = () => { - const tabsButtons = tabs.map(tab => { - const isActive = tab.value === currentTab; - - const tabStyle = isActive ? stylesHook.activeTab : undefined; - const textStyle = isActive ? stylesHook.activeText : stylesHook.inactiveTab; - - return ( - changeToTab(tab.key)} style={[styles.tab, tabStyle]}> - {tab.name} - - ); - }); - - return ( - - - {tabsButtons} - - - ); - }; - - return render(); -}; - -const styles = StyleSheet.create({ - container: { - flex: 1, - flexDirection: 'row', - justifyContent: 'center', - } as ViewStyle, - backTabs: { - padding: 4, - marginVertical: 8, - borderRadius: 8, - } as ViewStyle, - tabs: { - flex: 1, - flexDirection: 'row', - justifyContent: 'center', - } as ViewStyle, - tab: { - borderRadius: 6, - paddingVertical: 8, - paddingHorizontal: 16, - justifyContent: 'center', - } as ViewStyle, -}); - -export { AddressTypeTabs }; diff --git a/ios/BlueWallet-Bridging-Header.h b/ios/BlueWallet-Bridging-Header.h index 73636bdb6..fb6c659be 100644 --- a/ios/BlueWallet-Bridging-Header.h +++ b/ios/BlueWallet-Bridging-Header.h @@ -4,3 +4,4 @@ #import "AppDelegate.h" #import +#import "React/RCTViewManager.h" diff --git a/ios/BlueWallet.xcodeproj/project.pbxproj b/ios/BlueWallet.xcodeproj/project.pbxproj index 4e4718603..17b1afc54 100644 --- a/ios/BlueWallet.xcodeproj/project.pbxproj +++ b/ios/BlueWallet.xcodeproj/project.pbxproj @@ -141,8 +141,10 @@ B450109D2C0FCD9F00619044 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B450109B2C0FCD8A00619044 /* Utilities.swift */; }; B450109E2C0FCDA000619044 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B450109B2C0FCD8A00619044 /* Utilities.swift */; }; B450109F2C0FCDA500619044 /* Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B450109B2C0FCD8A00619044 /* Utilities.swift */; }; + B45010A62C1507DE00619044 /* CustomSegmentedControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B45010A52C1507DE00619044 /* CustomSegmentedControlManager.m */; }; B4549F362B82B10D002E3153 /* ci_post_clone.sh in Resources */ = {isa = PBXBuildFile; fileRef = B4549F352B82B10D002E3153 /* ci_post_clone.sh */; }; B461B852299599F800E431AA /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = B461B851299599F800E431AA /* AppDelegate.mm */; }; + B47462D02C1538D800100825 /* CustomSegmentedControlManager.m in Sources */ = {isa = PBXBuildFile; fileRef = B45010A52C1507DE00619044 /* CustomSegmentedControlManager.m */; }; B47B21EC2B2128B8001F6690 /* BlueWalletUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B47B21EB2B2128B8001F6690 /* BlueWalletUITests.swift */; }; B49038D92B8FBAD300A8164A /* BlueWalletUITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = B49038D82B8FBAD300A8164A /* BlueWalletUITest.swift */; }; B4A29A2C2B55C990002A67DF /* EventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D32C5C52596CE3A008C077C /* EventEmitter.m */; }; @@ -444,6 +446,8 @@ B44033FF2BCC37F800162242 /* Bundle+decode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Bundle+decode.swift"; sourceTree = ""; }; B440340E2BCC40A400162242 /* fiatUnits.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = fiatUnits.json; path = ../../../models/fiatUnits.json; sourceTree = ""; }; B450109B2C0FCD8A00619044 /* Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utilities.swift; sourceTree = ""; }; + B45010A52C1507DE00619044 /* CustomSegmentedControlManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomSegmentedControlManager.m; sourceTree = ""; }; + B45010A92C15080500619044 /* CustomSegmentedControlManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomSegmentedControlManager.h; sourceTree = ""; }; B4549F352B82B10D002E3153 /* ci_post_clone.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ci_post_clone.sh; sourceTree = ""; }; B461B850299599F800E431AA /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = BlueWallet/AppDelegate.h; sourceTree = ""; }; B461B851299599F800E431AA /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = BlueWallet/AppDelegate.mm; sourceTree = ""; }; @@ -715,7 +719,7 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( - B4B1A4612BFA73110072E3BB /* WidgetHelper.swift */, + B45010A12C1504E900619044 /* Components */, B44033C82BCC34AC00162242 /* Shared */, B41C2E552BB3DCB8000FE097 /* PrivacyInfo.xcprivacy */, B4549F2E2B80FEA1002E3153 /* ci_scripts */, @@ -862,6 +866,24 @@ path = Utilities; sourceTree = ""; }; + B45010A12C1504E900619044 /* Components */ = { + isa = PBXGroup; + children = ( + B4B1A4612BFA73110072E3BB /* WidgetHelper.swift */, + B45010A82C1507F000619044 /* SegmentedControl */, + ); + path = Components; + sourceTree = ""; + }; + B45010A82C1507F000619044 /* SegmentedControl */ = { + isa = PBXGroup; + children = ( + B45010A52C1507DE00619044 /* CustomSegmentedControlManager.m */, + B45010A92C15080500619044 /* CustomSegmentedControlManager.h */, + ); + path = SegmentedControl; + sourceTree = ""; + }; B4549F2E2B80FEA1002E3153 /* ci_scripts */ = { isa = PBXGroup; children = ( @@ -1521,6 +1543,7 @@ 6D32C5C62596CE3A008C077C /* EventEmitter.m in Sources */, B44033FE2BCC37D700162242 /* MarketAPI.swift in Sources */, B450109C2C0FCD8A00619044 /* Utilities.swift in Sources */, + B45010A62C1507DE00619044 /* CustomSegmentedControlManager.m in Sources */, B44033CE2BCC352900162242 /* UserDefaultsGroup.swift in Sources */, 13B07FC11A68108700A75B9A /* main.m in Sources */, B461B852299599F800E431AA /* AppDelegate.mm in Sources */, @@ -1638,6 +1661,7 @@ B44033D72BCC369400162242 /* UserDefaultsExtension.swift in Sources */, B44033F72BCC377F00162242 /* WidgetData.swift in Sources */, B44033E12BCC36CA00162242 /* Placeholders.swift in Sources */, + B47462D02C1538D800100825 /* CustomSegmentedControlManager.m in Sources */, B44033E72BCC36FF00162242 /* WalletData.swift in Sources */, B44033E02BCC36C300162242 /* LatestTransaction.swift in Sources */, B44033D92BCC369900162242 /* Colors.swift in Sources */, diff --git a/ios/BlueWallet/AppDelegate.mm b/ios/BlueWallet/AppDelegate.mm index 0a2cad0c7..d100c3db3 100644 --- a/ios/BlueWallet/AppDelegate.mm +++ b/ios/BlueWallet/AppDelegate.mm @@ -10,6 +10,7 @@ #import #import #import "BlueWallet-Swift.h" +#import "CustomSegmentedControlManager.h" @interface AppDelegate() @@ -21,6 +22,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [CustomSegmentedControlManager registerIfNecessary]; [self clearFilesIfNeeded]; self.userDefaultsGroup = [[NSUserDefaults alloc] initWithSuiteName:@"group.io.bluewallet.bluewallet"]; diff --git a/ios/Components/SegmentedControl/CustomSegmentedControlManager.h b/ios/Components/SegmentedControl/CustomSegmentedControlManager.h new file mode 100644 index 000000000..9e1933175 --- /dev/null +++ b/ios/Components/SegmentedControl/CustomSegmentedControlManager.h @@ -0,0 +1,15 @@ +// +// SegmentedControlManager.h +// BlueWallet +// +// Created by Marcos Rodriguez on 6/8/24. +// Copyright © 2024 BlueWallet. All rights reserved. +// + +#import + +@interface CustomSegmentedControlManager : RCTViewManager + ++ (void)registerIfNecessary; + +@end diff --git a/ios/Components/SegmentedControl/CustomSegmentedControlManager.m b/ios/Components/SegmentedControl/CustomSegmentedControlManager.m new file mode 100644 index 000000000..31c6ce256 --- /dev/null +++ b/ios/Components/SegmentedControl/CustomSegmentedControlManager.m @@ -0,0 +1,62 @@ +#import "CustomSegmentedControlManager.h" +#import +#import +#import + +@interface CustomSegmentedControl : UISegmentedControl +@property (nonatomic, copy) RCTDirectEventBlock onChangeEvent; +- (void)setValues:(NSArray *)values; +- (void)setSelectedIndex:(NSNumber *)selectedIndex; +@end + +@implementation CustomSegmentedControl + +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self addTarget:self action:@selector(onChange:) forControlEvents:UIControlEventValueChanged]; + } + return self; +} + +- (void)setValues:(NSArray *)values { + [self removeAllSegments]; + for (NSUInteger i = 0; i < values.count; i++) { + [self insertSegmentWithTitle:values[i] atIndex:i animated:NO]; + } +} + +- (void)setSelectedIndex:(NSNumber *)selectedIndex { + self.selectedSegmentIndex = selectedIndex.integerValue; +} + +- (void)onChange:(UISegmentedControl *)sender { + if (self.onChangeEvent) { + self.onChangeEvent(@{@"selectedIndex": @(self.selectedSegmentIndex)}); + } +} + +@end + +@implementation CustomSegmentedControlManager + +static BOOL isRegistered = NO; + +RCT_EXPORT_MODULE(CustomSegmentedControl) + +- (UIView *)view { + return [CustomSegmentedControl new]; +} + +RCT_EXPORT_VIEW_PROPERTY(values, NSArray) +RCT_EXPORT_VIEW_PROPERTY(selectedIndex, NSNumber) +RCT_EXPORT_VIEW_PROPERTY(onChangeEvent, RCTDirectEventBlock) + ++ (void)registerIfNecessary { + if (!isRegistered) { + isRegistered = YES; + // Registration logic if necessary + } +} + +@end diff --git a/ios/WidgetHelper.swift b/ios/Components/WidgetHelper.swift similarity index 100% rename from ios/WidgetHelper.swift rename to ios/Components/WidgetHelper.swift diff --git a/screen/wallets/WalletAddresses.tsx b/screen/wallets/WalletAddresses.tsx index f0912b1b9..e31c20b4e 100644 --- a/screen/wallets/WalletAddresses.tsx +++ b/screen/wallets/WalletAddresses.tsx @@ -3,13 +3,21 @@ import { useFocusEffect, useRoute, RouteProp } from '@react-navigation/native'; import { ActivityIndicator, FlatList, StyleSheet, View } from 'react-native'; import { WatchOnlyWallet } from '../../class'; import { AddressItem } from '../../components/addresses/AddressItem'; -import { AddressTypeTabs, TABS } from '../../components/addresses/AddressTypeTabs'; import { useTheme } from '../../components/themes'; import usePrivacy from '../../hooks/usePrivacy'; import { useStorage } from '../../hooks/context/useStorage'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { DetailViewStackParamList } from '../../navigation/DetailViewStackParamList'; import { useExtendedNavigation } from '../../hooks/useExtendedNavigation'; +import SegmentedControl from '../../components/SegmentControl'; +import loc from '../../loc'; + +export const TABS = { + EXTERNAL: 'receive', + INTERNAL: 'change', +} as const; + +type TabKey = keyof typeof TABS; interface Address { key: string; @@ -205,10 +213,16 @@ const WalletAddresses: React.FC = () => { centerContent={!showAddresses} contentInsetAdjustmentBehavior="automatic" ListHeaderComponent={ - dispatch({ type: SET_CURRENT_TAB, payload: tab })} - /> + + loc.addresses[`type_${tab}`])} + selectedIndex={Object.values(TABS).findIndex(tab => tab === currentTab)} + onChange={(index: number) => { + const tabKey = Object.keys(TABS)[index] as TabKey; + dispatch({ type: SET_CURRENT_TAB, payload: TABS[tabKey] }); + }} + /> + } /> @@ -221,4 +235,10 @@ const styles = StyleSheet.create({ root: { flex: 1, }, + segmentController: { + margin: 40, + height: 40, + alignItems: 'center', + justifyContent: 'center', + }, }); diff --git a/tests/unit/addresses.test.ts b/tests/unit/addresses.test.ts index be8dde22d..a4583b9b1 100644 --- a/tests/unit/addresses.test.ts +++ b/tests/unit/addresses.test.ts @@ -1,6 +1,5 @@ import assert from 'assert'; -import { filterByAddressType, getAddress, sortByAddressIndex, totalBalance } from '../../screen/wallets/WalletAddresses'; -import { TABS } from '../../components/addresses/AddressTypeTabs'; +import { TABS, filterByAddressType, getAddress, sortByAddressIndex, totalBalance } from '../../screen/wallets/WalletAddresses'; jest.mock('../../blue_modules/currency', () => { return {