From cb3dce1482c219e0782b3e1b7ae77ffeed69eb3a Mon Sep 17 00:00:00 2001 From: Chris Nguyen Date: Tue, 12 Jul 2022 11:44:17 -0700 Subject: [PATCH 1/6] Add @react-native-community/slider dependency --- ios/BitPayApp.xcodeproj/project.pbxproj | 4 ++-- ios/Podfile.lock | 8 +++++++- package.json | 1 + yarn.lock | 5 +++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ios/BitPayApp.xcodeproj/project.pbxproj b/ios/BitPayApp.xcodeproj/project.pbxproj index 88c7b328e..ba4f5a204 100644 --- a/ios/BitPayApp.xcodeproj/project.pbxproj +++ b/ios/BitPayApp.xcodeproj/project.pbxproj @@ -664,7 +664,7 @@ COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -725,7 +725,7 @@ COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "arm64 i386"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index dc5d3c2fc..d6b48ea2b 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -394,6 +394,8 @@ PODS: - React-Core - react-native-safe-area-context (3.3.2): - React-Core + - react-native-slider (4.2.4): + - React-Core - react-native-text-input-mask (3.1.4): - InputMask (~> 6.1.0) - React-Core @@ -600,6 +602,7 @@ DEPENDENCIES: - react-native-pager-view (from `../node_modules/react-native-pager-view`) - react-native-randombytes (from `../node_modules/react-native-randombytes`) - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - "react-native-slider (from `../node_modules/@react-native-community/slider`)" - react-native-text-input-mask (from `../node_modules/react-native-text-input-mask`) - react-native-tracking-transparency (from `../node_modules/react-native-tracking-transparency`) - react-native-user-agent (from `../node_modules/react-native-user-agent`) @@ -730,6 +733,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-randombytes" react-native-safe-area-context: :path: "../node_modules/react-native-safe-area-context" + react-native-slider: + :path: "../node_modules/@react-native-community/slider" react-native-text-input-mask: :path: "../node_modules/react-native-text-input-mask" react-native-tracking-transparency: @@ -814,7 +819,7 @@ SPEC CHECKSUMS: CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: cf9b38bf0b2d048436d9a82ad2abe1404f11e7de FBLazyVector: 7b423f9e248eae65987838148c36eec1dbfe0b53 - FBReactNativeSpec: 659a18b561e601d39a0e273cc7f5ca8b62b3f222 + FBReactNativeSpec: 30113914ceb067204672bf4fad2026fac0d1441c Flipper: d3da1aa199aad94455ae725e9f3aa43f3ec17021 Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41 Flipper-Folly: 755929a4f851b2fb2c347d533a23f191b008554c @@ -864,6 +869,7 @@ SPEC CHECKSUMS: react-native-pager-view: 3ee7d4c7697fb3ef788346e834a60cca97ed8540 react-native-randombytes: 421f1c7d48c0af8dbcd471b0324393ebf8fe7846 react-native-safe-area-context: 584dc04881deb49474363f3be89e4ca0e854c057 + react-native-slider: cecabb58ecffad671d2ad3ccc58c7f4d2d029e95 react-native-text-input-mask: 36a546b378fadd2efe1b7484a859d34bc2c80395 react-native-tracking-transparency: b2029ff756f1128b1f2c7c7c7f3003bc3c950f9f react-native-user-agent: a90a1e839b99801baad67a73dd6f361a52aa3cf1 diff --git a/package.json b/package.json index 8b128f9f6..e5c80fce6 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@react-native-async-storage/async-storage": "1.15.14", "@react-native-community/blur": "3.6.0", "@react-native-community/clipboard": "1.5.1", + "@react-native-community/slider": "4.2.4", "@react-native-masked-view/masked-view": "0.2.6", "@react-navigation/bottom-tabs": "6.0.9", "@react-navigation/material-top-tabs": "6.0.6", diff --git a/yarn.lock b/yarn.lock index 2a08d9b93..660b8e338 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2033,6 +2033,11 @@ resolved "https://registry.yarnpkg.com/@react-native-community/eslint-plugin/-/eslint-plugin-1.1.0.tgz#e42b1bef12d2415411519fd528e64b593b1363dc" integrity sha512-W/J0fNYVO01tioHjvYWQ9m6RgndVtbElzYozBq1ZPrHO/iCzlqoySHl4gO/fpCl9QEFjvJfjPgtPMTMlsoq5DQ== +"@react-native-community/slider@4.2.4": + version "4.2.4" + resolved "https://registry.yarnpkg.com/@react-native-community/slider/-/slider-4.2.4.tgz#8d88adceeb32f7997a122feba48d7186fca80346" + integrity sha512-uY51UoipQW4ELnFWMU6rTHRc4EUYaW+Z1O9Teijej6NYVYdUcUKq+t7WeBGjMAEc1ipyooMeBqRXToWO5zAU2Q== + "@react-native-masked-view/masked-view@0.2.6": version "0.2.6" resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.2.6.tgz#b26c52d5db3ad0926b13deea79c69620966a9221" From 044707d8c12e03bdb93c55c416534b8676f0b882 Mon Sep 17 00:00:00 2001 From: Chris Nguyen Date: Tue, 12 Jul 2022 11:45:58 -0700 Subject: [PATCH 2/6] Add log filter control --- .../settings/about/screens/SessionLog.tsx | 103 +++++++++++++----- 1 file changed, 76 insertions(+), 27 deletions(-) diff --git a/src/navigation/tabs/settings/about/screens/SessionLog.tsx b/src/navigation/tabs/settings/about/screens/SessionLog.tsx index 08687b052..b288e6c71 100644 --- a/src/navigation/tabs/settings/about/screens/SessionLog.tsx +++ b/src/navigation/tabs/settings/about/screens/SessionLog.tsx @@ -1,15 +1,20 @@ +import Slider from '@react-native-community/slider'; import {StackNavigationProp} from '@react-navigation/stack'; import {useTranslation} from 'react-i18next'; -import React, {useState, useCallback} from 'react'; +import React, {useState, memo} from 'react'; import Mailer from 'react-native-mail'; import {Alert, FlatList} from 'react-native'; import {useSelector} from 'react-redux'; import styled from 'styled-components/native'; +// @ts-ignore +import {version} from '../../../../../../package.json'; // TODO: better way to get version +import Button from '../../../../../components/button/Button'; +import {WIDTH} from '../../../../../components/styled/Containers'; +import {BaseText} from '../../../../../components/styled/Text'; +import {IS_ANDROID, IS_IOS} from '../../../../../constants'; import {RootState} from '../../../../../store'; -import {LogLevel} from '../../../../../store/log/log.models'; +import {LogEntry, LogLevel} from '../../../../../store/log/log.models'; import {LogActions} from '../../../../../store/log'; -import {AboutStackParamList} from '../AboutStack'; -import Button from '../../../../../components/button/Button'; import { SlateDark, Caution, @@ -17,10 +22,8 @@ import { LinkBlue, White, } from '../../../../../styles/colors'; -import {BaseText} from '../../../../../components/styled/Text'; -// @ts-ignore -import {version} from '../../../../../../package.json'; // TODO: better way to get version import {useAppDispatch} from '../../../../../utils/hooks'; +import {AboutStackParamList} from '../AboutStack'; export interface SessionLogsParamList {} @@ -44,11 +47,57 @@ const Logs = styled(BaseText)<{color?: string | null}>` color ? color : dark ? White : SlateDark}; `; -const SessionLogs: React.FC = () => { +const FilterLabelsContainer = styled.View` + flex-direction: row; + margin-top: 16px; +`; + +const FilterLabel = styled(BaseText)` + flex: 1 1 100%; + text-align: center; +`; + +const MIN_LOG_LEVEL = LogLevel.Error; +const MAX_LOG_LEVEL = LogLevel.Debug; +const TOTAL_LOG_LEVELS = MAX_LOG_LEVEL - MIN_LOG_LEVEL + 1; + +const THUMB_WIDTH = IS_IOS || IS_ANDROID ? 30 : 0; +const SLIDER_WIDTH = + ((TOTAL_LOG_LEVELS - 1) / TOTAL_LOG_LEVELS) * WIDTH + THUMB_WIDTH; + +const LogColorMap: Partial<{[key in LogLevel]: string | null}> = { + [LogLevel.Error]: Caution, + [LogLevel.Warn]: Warning, + [LogLevel.Debug]: LinkBlue, +}; + +const FilterLabels = memo(() => { + const labels = []; + + for (let i = MIN_LOG_LEVEL; i <= MAX_LOG_LEVEL; ++i) { + labels.push(LogLevel[i]); + } + + return ( + + {labels.map(label => ( + {label} + ))} + + ); +}); + +const renderItem = ({item}: {item: LogEntry}) => ( + + [{LogLevel[item.level]}] {item.message} + +); + +const SessionLogs: React.VFC = () => { const {t} = useTranslation(); const dispatch = useAppDispatch(); const logs = useSelector(({LOG}: RootState) => LOG.logs); - const [filterLevel] = useState(LogLevel.None); + const [filterLevel, setFilterLevel] = useState(LogLevel.Info); const filteredLogs = logs.filter(log => log.level <= filterLevel); @@ -56,6 +105,7 @@ const SessionLogs: React.FC = () => { 'Session Logs.\nBe careful, this could contain sensitive private data\n\n'; logStr += filteredLogs.map(log => { const formattedLevel = LogLevel[log.level].toLowerCase(); + return `[${log.timestamp}] [${formattedLevel}] ${log.message}\n`; }); @@ -86,24 +136,6 @@ const SessionLogs: React.FC = () => { ); }; - const renderItem = useCallback( - ({item}) => ( - - [{LogLevel[item.level]}] {item.message} - - ), - [], - ); - return ( = () => { renderItem={renderItem} keyExtractor={(item, index) => item.message + index} /> + + + + + From eb0ac404cebcb2e1282e493fc4254440b513590e Mon Sep 17 00:00:00 2001 From: Chris Nguyen Date: Tue, 12 Jul 2022 12:17:14 -0700 Subject: [PATCH 4/6] Add APP_VERSION to config --- src/constants/config.ts | 3 +++ .../services/buy-crypto/utils/simplex-utils.ts | 12 +++++------- .../tabs/settings/about/screens/SessionLog.tsx | 15 +++++++-------- src/navigation/tabs/settings/components/About.tsx | 5 ++--- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/constants/config.ts b/src/constants/config.ts index 4612e1b1a..da4ef092a 100644 --- a/src/constants/config.ts +++ b/src/constants/config.ts @@ -1,3 +1,5 @@ +// @ts-ignore +import {version} from '../../package.json'; // TODO: better way to get version import {Network} from '.'; export const DEVTOOLS_ENABLED = false; @@ -8,6 +10,7 @@ export const APP_ANALYTICS_ENABLED = !__DEV__; export const APP_NAME = 'bitpay'; export const APP_NAME_UPPERCASE = 'BitPay'; export const APP_NETWORK = Network.mainnet; +export const APP_VERSION = version; export const BASE_BITPAY_URLS = { [Network.mainnet]: 'https://bitpay.com', [Network.testnet]: 'https://test.bitpay.com', diff --git a/src/navigation/services/buy-crypto/utils/simplex-utils.ts b/src/navigation/services/buy-crypto/utils/simplex-utils.ts index 92250d0b2..9dc273347 100644 --- a/src/navigation/services/buy-crypto/utils/simplex-utils.ts +++ b/src/navigation/services/buy-crypto/utils/simplex-utils.ts @@ -1,8 +1,6 @@ -import {Currencies} from '../../../../constants/currencies'; -import {APP_NAME} from '../../../../constants/config'; -// @ts-ignore -import {version} from '../../../../../package.json'; // TODO: better way to get version import UserAgent from 'react-native-user-agent'; +import {APP_NAME, APP_VERSION} from '../../../../constants/config'; +import {Currencies} from '../../../../constants/currencies'; const PASSTHROUGH_URI_DEV = 'https://cmgustavo.github.io/website/simplex/'; const PASSTHROUGH_URI_PROD = 'https://bws.bitpay.com/static/simplex/'; @@ -102,11 +100,11 @@ const getUserAgent = (): string => { }; const getAppVersion = (): string => { - return version; + return APP_VERSION; }; const checkSimplexCoin = (coin: string): string => { - if (coin == 'PAX') { + if (coin === 'PAX') { return 'USDP'; } return coin; @@ -201,7 +199,7 @@ export const getPaymentUrl = ( let str = ''; for (let key in dataSrc) { - if (str != '') { + if (str !== '') { str += '&'; } str += key + '=' + encodeURIComponent(dataSrc[key]); diff --git a/src/navigation/tabs/settings/about/screens/SessionLog.tsx b/src/navigation/tabs/settings/about/screens/SessionLog.tsx index 957dc37a9..77a56e562 100644 --- a/src/navigation/tabs/settings/about/screens/SessionLog.tsx +++ b/src/navigation/tabs/settings/about/screens/SessionLog.tsx @@ -1,23 +1,22 @@ import Slider from '@react-native-community/slider'; import {StackNavigationProp} from '@react-navigation/stack'; +import React, {memo, useState} from 'react'; import {useTranslation} from 'react-i18next'; -import React, {useState, memo} from 'react'; -import Mailer from 'react-native-mail'; import {Alert, FlatList} from 'react-native'; +import Mailer from 'react-native-mail'; import styled from 'styled-components/native'; -// @ts-ignore -import {version} from '../../../../../../package.json'; // TODO: better way to get version import Button from '../../../../../components/button/Button'; import {WIDTH} from '../../../../../components/styled/Containers'; import {BaseText} from '../../../../../components/styled/Text'; import {IS_ANDROID, IS_IOS} from '../../../../../constants'; -import {LogEntry, LogLevel} from '../../../../../store/log/log.models'; +import {APP_VERSION} from '../../../../../constants/config'; import {LogActions} from '../../../../../store/log'; +import {LogEntry, LogLevel} from '../../../../../store/log/log.models'; import { - SlateDark, Caution, - Warning, LinkBlue, + SlateDark, + Warning, White, } from '../../../../../styles/colors'; import {useAppDispatch, useAppSelector} from '../../../../../utils/hooks'; @@ -102,7 +101,7 @@ const SessionLogs: React.VFC = () => { const handleEmail = (data: string) => { Mailer.mail( { - subject: `BitPay v${version} Logs`, + subject: `BitPay v${APP_VERSION} Logs`, body: data, isHTML: false, }, diff --git a/src/navigation/tabs/settings/components/About.tsx b/src/navigation/tabs/settings/components/About.tsx index d0fc39a60..fdb34d1c6 100644 --- a/src/navigation/tabs/settings/components/About.tsx +++ b/src/navigation/tabs/settings/components/About.tsx @@ -7,10 +7,9 @@ import { SettingTitle, } from '../../../../components/styled/Containers'; import Button from '../../../../components/button/Button'; -// @ts-ignore -import {version} from '../../../../../package.json'; // TODO: better way to get version import {useNavigation} from '@react-navigation/native'; import {URL} from '../../../../constants'; +import {APP_VERSION} from '../../../../constants/config'; import {useTranslation} from 'react-i18next'; import {View} from 'react-native'; import {useDispatch} from 'react-redux'; @@ -59,7 +58,7 @@ const About = () => { {t('Version')} - +
From 24c53511d5df55632144198ac0897bef9faeb30c Mon Sep 17 00:00:00 2001 From: Chris Nguyen Date: Tue, 12 Jul 2022 12:34:26 -0700 Subject: [PATCH 5/6] Extend log actions to accept multiple args similar to console.log --- src/store/app/app.effects.ts | 13 ++++++------- src/store/log/log.actions.ts | 27 +++++++++++++++++---------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/store/app/app.effects.ts b/src/store/app/app.effects.ts index 0a9811d70..2392fa041 100644 --- a/src/store/app/app.effects.ts +++ b/src/store/app/app.effects.ts @@ -72,6 +72,12 @@ export const startAppInit = (): Effect => async (dispatch, getState) => { dispatch(LogActions.clear()); dispatch(LogActions.info(`Initializing app (${__DEV__ ? 'D' : 'P'})...`)); + const {APP, BITPAY_ID} = getState(); + const {network, pinLockActive, biometricLockActive, colorScheme} = APP; + + dispatch(LogActions.debug(`Network: ${network}`)); + dispatch(LogActions.debug(`Theme: ${colorScheme || 'system'}`)); + await dispatch(startWalletStoreInit()); const {appFirstOpenData, onboardingCompleted, migrationComplete} = @@ -93,13 +99,6 @@ export const startAppInit = (): Effect => async (dispatch, getState) => { dispatch(LogActions.info('success [setMigrationComplete]')); } - const {BITPAY_ID} = getState(); - const {network, pinLockActive, biometricLockActive, colorScheme} = - getState().APP; - - dispatch(LogActions.debug(`Network: ${network}`)); - dispatch(LogActions.debug(`Theme: ${colorScheme || 'system'}`)); - const token = BITPAY_ID.apiToken[network]; const isPaired = !!token; const identity = dispatch(initializeAppIdentity()); diff --git a/src/store/log/log.actions.ts b/src/store/log/log.actions.ts index 5a60ae015..e15b43665 100644 --- a/src/store/log/log.actions.ts +++ b/src/store/log/log.actions.ts @@ -7,24 +7,31 @@ export const clear = (): LogActionType => { }; }; -export const debug = (message?: string): LogActionType => - _log(message, LogLevel.Debug); +export const debug = ( + ...messages: (string | null | undefined)[] +): LogActionType => _log(LogLevel.Debug, ...messages); -export const info = (message?: string): LogActionType => - _log(message, LogLevel.Info); +export const info = ( + ...messages: (string | null | undefined)[] +): LogActionType => _log(LogLevel.Info, ...messages); -export const warn = (message?: string): LogActionType => - _log(message, LogLevel.Warn); +export const warn = ( + ...messages: (string | null | undefined)[] +): LogActionType => _log(LogLevel.Warn, ...messages); -export const error = (message?: string): LogActionType => - _log(message, LogLevel.Error); +export const error = ( + ...messages: (string | null | undefined)[] +): LogActionType => _log(LogLevel.Error, ...messages); -function _log(message: string = '', level: LogLevel): LogActionType { +function _log( + level: LogLevel, + ...messages: (string | null | undefined)[] +): LogActionType { return { type: LogActionTypes.ADD_LOG, payload: { level, - message, + message: messages.join(' '), timestamp: new Date().toISOString(), } as LogEntry, }; From 40240ebfb35590eab954d3a4c2e1cd4949960099 Mon Sep 17 00:00:00 2001 From: Chris Nguyen Date: Tue, 12 Jul 2022 13:17:16 -0700 Subject: [PATCH 6/6] Allow user to tap label to change filter level --- .../settings/about/screens/SessionLog.tsx | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/src/navigation/tabs/settings/about/screens/SessionLog.tsx b/src/navigation/tabs/settings/about/screens/SessionLog.tsx index 77a56e562..faffa0c0d 100644 --- a/src/navigation/tabs/settings/about/screens/SessionLog.tsx +++ b/src/navigation/tabs/settings/about/screens/SessionLog.tsx @@ -68,21 +68,25 @@ const LogColorMap: Partial<{[key in LogLevel]: string | null}> = { [LogLevel.Debug]: LinkBlue, }; -const FilterLabels = memo(() => { - const labels = []; - - for (let i = MIN_LOG_LEVEL; i <= MAX_LOG_LEVEL; ++i) { - labels.push(LogLevel[i]); - } - - return ( - - {labels.map(label => ( - {label} - ))} - - ); -}); +const FilterLabels: React.VFC<{onPress?: (level: LogLevel) => any}> = memo( + props => { + const levels = []; + + for (let i = MIN_LOG_LEVEL; i <= MAX_LOG_LEVEL; ++i) { + levels.push(i); + } + + return ( + + {levels.map(level => ( + props.onPress?.(level)} key={level}> + {LogLevel[level]} + + ))} + + ); + }, +); const renderItem = ({item}: {item: LogEntry}) => ( @@ -90,6 +94,8 @@ const renderItem = ({item}: {item: LogEntry}) => ( ); +const keyExtractor = (item: LogEntry, index: number) => item.message + index; + const SessionLogs: React.VFC = () => { const {t} = useTranslation(); const dispatch = useAppDispatch(); @@ -98,6 +104,12 @@ const SessionLogs: React.VFC = () => { const filteredLogs = logs.filter(log => log.level <= filterLevel); + const onFilterLevelChange = (level: LogLevel) => { + if (level !== filterLevel) { + setFilterLevel(level); + } + }; + const handleEmail = (data: string) => { Mailer.mail( { @@ -145,17 +157,17 @@ const SessionLogs: React.VFC = () => { }} data={filteredLogs} renderItem={renderItem} - keyExtractor={(item, index) => item.message + index} + keyExtractor={keyExtractor} /> - +