diff --git a/commitlint.config.js b/commitlint.config.js index 4748253d4..ccdb539d1 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -5,7 +5,6 @@ module.exports = { 2, 'always', [ - 'accounts', 'activity', 'backup', 'boost', @@ -21,9 +20,8 @@ module.exports = { 'security', 'send', 'settings', - 'slashpay', + 'shop', 'suggestions', - 'tokens', 'transfer', 'ui', 'wallet', diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 3b07ff10e..23860bec5 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1452,6 +1452,27 @@ PODS: - react-native-tcp-socket (6.0.6): - CocoaAsyncSocket - React-Core + - react-native-webview (13.13.5): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.11.18.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - React-NativeModulesApple (0.78.0): - glog - hermes-engine @@ -2065,6 +2086,7 @@ DEPENDENCIES: - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) - "react-native-skia (from `../node_modules/@shopify/react-native-skia`)" - react-native-tcp-socket (from `../node_modules/react-native-tcp-socket`) + - react-native-webview (from `../node_modules/react-native-webview`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) @@ -2230,6 +2252,8 @@ EXTERNAL SOURCES: :path: "../node_modules/@shopify/react-native-skia" react-native-tcp-socket: :path: "../node_modules/react-native-tcp-socket" + react-native-webview: + :path: "../node_modules/react-native-webview" React-NativeModulesApple: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" React-perflogger: @@ -2335,101 +2359,102 @@ SPEC CHECKSUMS: glog: eb93e2f488219332457c3c4eafd2738ddc7e80b8 hermes-engine: b417d2b2aee3b89b58e63e23a51e02be91dc876d lottie-ios: a881093fab623c467d3bce374367755c272bdd59 - lottie-react-native: 3fd634de5c0cc095d36687d1b92b7c242d6103e8 + lottie-react-native: 35b7c1125a01f847fa5905d380e54951132d2450 MMKV: ce484c1ac40bf76d5f09a0195d2ec5b3d3840d55 MMKVCore: 1eb661c6c498ab88e3df9ce5d8ff94d05fcc0567 OpenSSL-Universal: b60a3702c9fea8b3145549d421fdb018e53ab7b4 - RCT-Folly: 36fe2295e44b10d831836cc0d1daec5f8abcf809 + RCT-Folly: e78785aa9ba2ed998ea4151e314036f6c49e6d82 RCTDeprecation: b2eecf2d60216df56bc5e6be5f063826d3c1ee35 RCTRequired: 78522de7dc73b81f3ed7890d145fa341f5bb32ea RCTTypeSafety: c135dd2bf50402d87fd12884cbad5d5e64850edd React: b229c49ed5898dab46d60f61ed5a0bfa2ee2fadb React-callinvoker: 2ac508e92c8bd9cf834cc7d7787d94352e4af58f - React-Core: 13cdd1558d0b3f6d9d5a22e14d89150280e79f02 - React-CoreModules: b07a6744f48305405e67c845ebf481b6551b712a - React-cxxreact: 1055a86c66ac35b4e80bd5fb766aed5f494dfff4 + React-Core: 325b4f6d9162ae8b9a6ff42fe78e260eb124180d + React-CoreModules: 558041e5258f70cd1092f82778d07b8b2ff01897 + React-cxxreact: 8fff17cbe76e6a8f9991b59552e1235429f9c74b React-debug: 0a5fcdbacc6becba0521e910c1bcfdb20f32a3f6 - React-defaultsnativemodule: 4bb28fc97fee5be63a9ebf8f7a435cfe8ba69459 - React-domnativemodule: b36a11c2597243d7563985028c51ece988d8ae33 - React-Fabric: afc561718f25b2cd800b709d934101afe376a12c - React-FabricComponents: f4e0a4e18a27bf6d39cbf2a0b42f37a92fa4e37f - React-FabricImage: 37d8e8b672eda68a19d71143eb65148084efb325 + React-defaultsnativemodule: 618dc50a0fad41b489997c3eb7aba3a74479fd14 + React-domnativemodule: 7ba599afb6c2a7ec3eb6450153e2efe0b8747e9a + React-Fabric: 252112089d2c63308f4cbfade4010b6606db67d1 + React-FabricComponents: 3c0f75321680d14d124438ab279c64ec2a3d13c4 + React-FabricImage: 728b8061cdec2857ca885fd605ee03ad43ffca98 React-featureflags: 19682e02ef5861d96b992af16a19109c3dfc1200 - React-featureflagsnativemodule: d7cddf6d907b4e5ab84f9e744b7e88461656e48c - React-graphics: b0f78580cdaf5800d25437e3d41cc6c3d83b7aea - React-hermes: 71186f872c932e4574d5feb3ed754dda63a0b3bd - React-idlecallbacksnativemodule: dd2af19cdd3bc55149d17a2409ed72b694dfbe9c - React-ImageManager: a77dde8d5aa6a2b6962c702bf3a47695ef0aa32b - React-jserrorhandler: 9c14e89f12d5904257a79aaf84a70cd2e5ac07ba - React-jsi: 0775a66820496769ad83e629f0f5cce621a57fc7 - React-jsiexecutor: 2cf5ba481386803f3c88b85c63fa102cba5d769e - React-jsinspector: 8052d532bb7a98b6e021755674659802fb140cc5 - React-jsinspectortracing: bdd8fd0adcb4813663562e7874c5842449df6d8a - React-jsitracing: 2bab3bf55de3d04baf205def375fa6643c47c794 - React-logger: 795cd5055782db394f187f9db0477d4b25b44291 - React-Mapbuffer: 0502faf46cab8fb89cfc7bf3e6c6109b6ef9b5de - React-microtasksnativemodule: 663bc64e3a96c5fc91081923ae7481adc1359a78 - react-native-address-generator: d246f305d2b93bd82cdf9d2901344f240a8792db - react-native-biometrics: 352e5a794bfffc46a0c86725ea7dc62deb085bdc - react-native-blur: 5b2d13981ad6ce3d15339e135377336cb9be2d68 - react-native-image-picker: b779fcdd787275d7315555888e8f69b609a5c6ed - react-native-ldk: d2d6d06d3da0d15324a809f2248eef11f116665e - react-native-mmkv: 637830702ab3cb525fface3eab763ad9cee00617 - react-native-netinfo: f0a9899081c185db1de5bb2fdc1c88c202a059ac - react-native-pubky: e8080719ae924287d3d75aa22ef0c9db253a2ccc - react-native-quick-base64: 27bade09b88268e7ed63121def711e55fb4aef82 - react-native-quick-crypto: 8ed2e6b19357620772d1886a7c21b53c1947b4e0 - react-native-restart: 7595693413fe3ca15893702f2c8306c62a708162 - react-native-safe-area-context: 849d7df29ecb2a7155c769c0b76849ba952c2aa3 - react-native-skia: d646e9b3a4991b264426c8cd8ca1dbcb5cbebd4c - react-native-tcp-socket: e724380c910c2e704816ec817ed28f1342246ff7 - React-NativeModulesApple: 16fbd5b040ff6c492dacc361d49e63cba7a6a7a1 - React-perflogger: ab51b7592532a0ea45bf6eed7e6cae14a368b678 - React-performancetimeline: bc2e48198ec814d578ac8401f65d78a574358203 + React-featureflagsnativemodule: 23528c7e7d50782b7ef0804168ba40bbaf1e86ab + React-graphics: fefe48f71bfe6f48fd037f59e8277b12e91b6be1 + React-hermes: a9a0c8377627b5506ef9a7b6f60a805c306e3f51 + React-idlecallbacksnativemodule: 7e2b6a3b70e042f89cd91dbd73c479bb39a72a7e + React-ImageManager: e3300996ac2e2914bf821f71e2f2c92ae6e62ae2 + React-jserrorhandler: fa75876c662e5d7e79d6efc763fc9f4c88e26986 + React-jsi: f3f51595cc4c089037b536368f016d4742bf9cf7 + React-jsiexecutor: cca6c232db461e2fd213a11e9364cfa6fdaa20eb + React-jsinspector: 2bd4c9fddf189d6ec2abf4948461060502582bef + React-jsinspectortracing: a417d8a0ad481edaa415734b4dac81e3e5ee7dc6 + React-jsitracing: 1ff7172c5b0522cbf6c98d82bdbb160e49b5804e + React-logger: 018826bfd51b9f18e87f67db1590bc510ad20664 + React-Mapbuffer: 3c11cee7737609275c7b66bd0b1de475f094cedf + React-microtasksnativemodule: 843f352b32aacbe13a9c750190d34df44c3e6c2c + react-native-address-generator: e2148d02756126b3c6123894aa0af2a36528173f + react-native-biometrics: 43ed5b828646a7862dbc7945556446be00798e7d + react-native-blur: b06c3fe88680beac622d8d13b8c36ec15c50383b + react-native-image-picker: 037a6ccde76aa165446e1eaeb8866cb00f461916 + react-native-ldk: c676f1f7113c2c64cf8470bb76d4954e4b72ff3a + react-native-mmkv: a6e08ad1b51b84af075f91798f8a92c878472265 + react-native-netinfo: cec9c4e86083cb5b6aba0e0711f563e2fbbff187 + react-native-pubky: 54d37810f35d9da11f8c199a6036e5729081951b + react-native-quick-base64: 99ddcde16a1bdab6aed68f375ab1ed5431946f13 + react-native-quick-crypto: 43bac82b1ce916efb64a6dccb8e020678d8d9c14 + react-native-restart: 0bc732f4461709022a742bb29bcccf6bbc5b4863 + react-native-safe-area-context: 3e33e7c43c8b74dba436a5a32651cb8d7064c740 + react-native-skia: 78dfcd1f530419f762a56988969f6430b4eabdc2 + react-native-tcp-socket: ae8abcfebc071216302a09d9ed1e375d4e877484 + react-native-webview: 079eca50edf657503318b66687dadfb903731aa8 + React-NativeModulesApple: 88433b6946778bea9c153e27b671de15411bf225 + React-perflogger: 9e8d3c0dc0194eb932162812a168aa5dc662f418 + React-performancetimeline: 5a2d6efef52bdcefac079c7baa30934978acd023 React-RCTActionSheet: 592674cf61142497e0e820688f5a696e41bf16dd - React-RCTAnimation: 8fbb8dba757b49c78f4db403133ab6399a4ce952 - React-RCTAppDelegate: 346f71ef725906ba8fac77c2fe9c6c9b89d09c96 - React-RCTBlob: f89b162d0fe6b570a18e755eb16cbe356d3c6d17 - React-RCTFabric: ae3cfd54caf162df6224c841466e4c1220f82b2b - React-RCTFBReactNativeSpec: ce1d60e8eae94c0adaa9acae24d26149c7fe181e - React-RCTImage: ccac9969940f170503857733f9a5f63578e106e1 - React-RCTLinking: d82427bbf18415a3732105383dff119131cadd90 - React-RCTNetwork: 12ad4d0fbde939e00251ca5ca890da2e6825cc3c - React-RCTSettings: e7865bf9f455abf427da349c855f8644b5c39afa - React-RCTText: 2cdfd88745059ec3202a0842ea75a956c7d6f27d - React-RCTVibration: a3a1458e6230dfd64b3768ebc0a4aac430d9d508 + React-RCTAnimation: e6d669872f9b3b4ab9527aab283b7c49283236b7 + React-RCTAppDelegate: 1768f69e774410cbd0716465db9494acc823a63a + React-RCTBlob: 3e2dce94c56218becc4b32b627fc2293149f798d + React-RCTFabric: 4dd8a0d13c5e15acc48fac2996a7ef76fc7c5e6a + React-RCTFBReactNativeSpec: b2aeef7ea8755ddfdf0c6ca1363ff6766a91080f + React-RCTImage: dc04b176c022d12a8f55ae7a7279b1e091066ae0 + React-RCTLinking: 88f5e37fe4f26fbc80791aa2a5f01baf9b9a3fd5 + React-RCTNetwork: f213693565efbd698b8e9c18d700a514b49c0c8e + React-RCTSettings: a2d32a90c45a3575568cad850abc45924999b8a5 + React-RCTText: 54cdcd1cbf6f6a91dc6317f5d2c2b7fc3f6bf7a0 + React-RCTVibration: 11dae0e7f577b5807bb7d31e2e881eb46f854fd4 React-rendererconsistency: 64e897e00d2568fd8dfe31e2496f80e85c0aaad1 - React-rendererdebug: a3f6d3ae7d2fa0035885026756281c07ee32479e + React-rendererdebug: 41ce452460c44bba715d9e41d5493a96de277764 React-rncore: 58748c2aa445f56b99e5118dad0aedb51c40ce9f - React-RuntimeApple: f0fda7bacabd32daa099cfda8f07466c30acd149 - React-RuntimeCore: 683ee0b6a76d4b4bf6fbf83a541895b4887cc636 + React-RuntimeApple: 7785ed0d8ae54da65a88736bb63ca97608a6d933 + React-RuntimeCore: 6029ea70bc77f98cfd43ebe69217f14e93ba1f12 React-runtimeexecutor: a188df372373baf5066e6e229177836488799f80 - React-RuntimeHermes: 907c8e9bec13ea6466b94828c088c24590d4d0b6 - React-runtimescheduler: a2e2a39125dd6426b5d8b773f689d660cd7c5f60 + React-RuntimeHermes: a264609c28b796edfffc8ae4cb8fad1773ab948b + React-runtimescheduler: 23ec3a1e0fb1ec752d1a9c1fb15258c30bfc7222 React-timing: bb220a53a795ed57976a4855c521f3de2f298fe5 - React-utils: 300d8bbb6555dcffaca71e7a0663201b5c7edbbc - ReactAppDependencyProvider: f2e81d80afd71a8058589e19d8a134243fa53f17 - ReactCodegen: a63a0ab6ae824aef2e8c744981edd718b16eb9f2 - ReactCommon: 3d39389f8e2a2157d5c999f8fba57bd1c8f226f0 - ReactNativeCameraKit: 9d774586c0333b11f19c6730d5b23f898d168fe0 - RNCClipboard: d7a8903d32692b0a1e71738c3825465a9acae10e - RNDeviceInfo: feea80a690d2bde1fe51461cf548039258bd03f2 - RNFS: 4ac0f0ea233904cb798630b3c077808c06931688 - RNGestureHandler: ebb08ce5dfc9caff34ae9cda3ef0d18daae3a7ef - RNKeychain: 74fb927843227b7bce9b8e305a1680c9734c6910 - RNLocalize: 06991b9c31e7a898a9fa6ddb204ce0f53a967248 - RNNotifee: 4a6ee5c7deaf00e005050052d73ee6315dff7ec9 - RNPermissions: b142799c9a127a1e6bb66fdb44f5c72131721dc0 - RNQrGenerator: ac6a6c766e80dd3625038929ed2b13e2f3edcafb - RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93 - RNReactNativeHapticFeedback: 288ef2881046914e9108441e783f64899807282a - RNReanimated: e1ee63008dcd075b8fdf60f315f43026ba11b8ef - RNScreens: 92045ed4a8d561352cebaa00a8c9f1a8fb80419b - RNShare: 388aa509809c6879949406504edb279eb3104a16 - RNSVG: 5b15de1a22aea9cadf43ae537c42196647fa681e - RNZipArchive: 7bb4c70d6aa2dd235212c0a4a3de0a4e237e2569 + React-utils: 3b054aaebe658fc710a8d239d0e4b9fd3e0b78f9 + ReactAppDependencyProvider: a1fb08dfdc7ebc387b2e54cfc9decd283ed821d8 + ReactCodegen: 008c319179d681a6a00966edfc67fda68f9fbb2e + ReactCommon: 0c097b53f03d6bf166edbcd0915da32f3015dd90 + ReactNativeCameraKit: b8f892326f100d3fce71e99df80e6aad670177ed + RNCClipboard: ee059e6006b137e369caed5eb852b4aad9f5d886 + RNDeviceInfo: d863506092aef7e7af3a1c350c913d867d795047 + RNFS: 89de7d7f4c0f6bafa05343c578f61118c8282ed8 + RNGestureHandler: 9f3109e11ed88fe5bed280bf7762b25e4c52f396 + RNKeychain: 824e7372c7e921d76c4ea4169bdc6c7a32025784 + RNLocalize: 15463c4d79c7da45230064b4adcf5e9bb984667e + RNNotifee: 5e3b271e8ea7456a36eec994085543c9adca9168 + RNPermissions: a03f8bd0e6c9d87597e39be694f90d208dd6f835 + RNQrGenerator: afacf12b55dfba0e3aaca963eec23691e8426431 + RNQuickAction: c2c8f379e614428be0babe4d53a575739667744d + RNReactNativeHapticFeedback: f9cfb40676f21a52e9e172648d033f539156a5ec + RNReanimated: f999fb5f61876de2729bc4863f036dd5841200fc + RNScreens: 96fe858d87d26c3f46f0696f9e8824ce33a05aa7 + RNShare: b1660f26d8bc57cbf9acf11872a8eb2f3ecf4825 + RNSVG: e1b90420e46f8923da4b5023963afd4964d0d12a + RNZipArchive: f4a5af907d1581e995c879e34799be35c6bc3e21 SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 - sodium-react-native-direct: b1a221d1fd27faafcb70a373ba6928a354e04cf6 + sodium-react-native-direct: daae90d1cfeea4837002395183ade1cac0d49795 SSZipArchive: c69881e8ac5521f0e622291387add5f60f30f3c4 Yoga: afd04ff05ebe0121a00c468a8a3c8080221cb14c ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5 diff --git a/ios/bitkit.xcodeproj/project.pbxproj b/ios/bitkit.xcodeproj/project.pbxproj index a79397a55..c221b6188 100644 --- a/ios/bitkit.xcodeproj/project.pbxproj +++ b/ios/bitkit.xcodeproj/project.pbxproj @@ -145,12 +145,12 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "bitkit" */; buildPhases = ( - 1B056C2CD201F7F3E7155066 /* [CP] Check Pods Manifest.lock */, + 4A704124906508F4238F0403 /* [CP] Check Pods Manifest.lock */, + 1B056C2CD201F7F3E7155066 /* [CP] Embed Pods Frameworks */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 4A704124906508F4238F0403 /* [CP] Embed Pods Frameworks */, 93C89E86D39997036A57DDDB /* [CP] Copy Pods Resources */, ); buildRules = ( @@ -230,43 +230,43 @@ shellPath = /bin/sh; shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; }; - 1B056C2CD201F7F3E7155066 /* [CP] Check Pods Manifest.lock */ = { + 1B056C2CD201F7F3E7155066 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-bitkit/Pods-bitkit-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-bitkit-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-bitkit/Pods-bitkit-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-bitkit/Pods-bitkit-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - 4A704124906508F4238F0403 /* [CP] Embed Pods Frameworks */ = { + 4A704124906508F4238F0403 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-bitkit/Pods-bitkit-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Embed Pods Frameworks"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-bitkit/Pods-bitkit-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-bitkit-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-bitkit/Pods-bitkit-frameworks.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; 93C89E86D39997036A57DDDB /* [CP] Copy Pods Resources */ = { diff --git a/package.json b/package.json index 655de1144..91bf4a2a5 100644 --- a/package.json +++ b/package.json @@ -106,6 +106,7 @@ "react-native-svg": "15.11.1", "react-native-tcp-socket": "6.0.6", "react-native-toast-message": "2.2.1", + "react-native-webview": "13.13.5", "react-native-zip-archive": "7.0.1", "react-redux": "9.1.2", "readable-stream": "4.7.0", diff --git a/src/assets/icons/index.ts b/src/assets/icons/index.ts index 2bb18bd84..1e494deb8 100644 --- a/src/assets/icons/index.ts +++ b/src/assets/icons/index.ts @@ -4,304 +4,361 @@ */ export const aboutIcon = (color = 'white'): string => ` -`; +`; + +export const activityIcon = (color = 'white'): string => ` +`; export const advancedIcon = (color = 'white'): string => ` -`; +`; + +export const airplaneIcon = (color = 'white'): string => ` +`; export const arrowClockwiseIcon = (color = 'white'): string => ` -`; +`; export const arrowCounterClockIcon = (color = 'white'): string => ` -`; +`; export const arrowLNfundsIcon = (color = 'white'): string => ` -`; +`; export const arrowsClockwiseIcon = (color = 'white'): string => ` -`; +`; export const backIcon = (color = 'white'): string => ` -`; +`; export const backspaceIcon = (color = 'white'): string => ` -`; +`; export const backupIcon = (color = 'white'): string => ` -`; +`; + +export const bicycleIcon = (color = 'white'): string => ` +`; export const bitcoinCircleIcon = (color = 'white'): string => ` -`; +`; export const bitcoinSlantedIcon = (color = 'white'): string => ` -`; +`; export const blocksIcon = (color = 'white'): string => ` -`; +`; export const broadcastIcon = (color = 'white'): string => ` -`; +`; export const burgerIcon = (color = 'white'): string => ` -`; +`; export const calculatorIcon = (color = 'white'): string => ` -`; +`; export const calendarIcon = (color = 'white'): string => ` -`; +`; export const cameraIcon = (color = 'white'): string => ` -`; +`; + +export const carIcon = (color = 'white'): string => ` +`; export const checkCircleIcon = (color = 'white'): string => ` -`; +`; export const checkmarkIcon = (color = 'white'): string => ` -`; +`; export const chevronRightIcon = (color = 'white'): string => ` -`; +`; export const clipboardTextIcon = (color = 'white'): string => ` -`; +`; export const clockIcon = (color = 'white'): string => ` -`; +`; export const cloudCheckIcon = (color = 'white'): string => ` -`; +`; export const coinsIcon = (color = 'white'): string => ` -`; +`; export const copyIcon = (color = 'white'): string => ` `; export const cornersOutIcon = (color = 'white'): string => ` -`; +`; export const devSettingsIcon = (color = 'white'): string => ` -`; +`; export const discordIcon = (color = 'white'): string => ` -`; +`; export const downArrowIcon = (color = 'white'): string => ` -`; +`; export const exclamationIcon = (color = 'white'): string => ` -`; +`; export const eyeIcon = (color = 'white'): string => ` -`; +`; export const faceIdIcon = (color = 'white'): string => ` -`; +`; export const factsIcon = (color = 'white'): string => ` -`; +`; export const fingerPrintIcon = (color = 'white'): string => ` -`; +`; export const flashlightIcon = (color = 'white'): string => ` -`; +`; + +export const forkKnifeIcon = (color = 'white'): string => ` +`; + +export const gameControllerIcon = (color = 'white'): string => ` +`; export const generalSettingsIcon = (color = 'white'): string => ` -`; +`; + +export const giftIcon = (color = 'white'): string => ` +`; export const gitBranchIcon = (color = 'white'): string => ` -`; +`; export const githubIcon = (color = 'white'): string => ` -`; +`; export const globeIcon = (color = 'white'): string => ` -`; +`; export const globeSimpleIcon = (color = 'white'): string => ` -`; +`; + +export const headphonesIcon = (color = 'white'): string => ` +`; export const heartbeatIcon = (color = 'white'): string => ` -`; +`; + +export const horseIcon = (color = 'white'): string => ` +`; export const hourglassIcon = (color = 'white'): string => ` -`; +`; export const hourglassSimpleIcon = (color = 'white'): string => ` -`; +`; + +export const houseIcon = (color = 'white'): string => ` +`; export const leftSignIcon = (color = 'white'): string => ` -`; +`; export const lightningIcon = (color = 'white'): string => ` -`; +`; export const lightningCircleIcon = (color = 'white'): string => ` -`; +`; export const lightningHollowIcon = (color = 'white'): string => ` -`; +`; export const listIcon = (color = 'white'): string => ` -`; +`; export const magnifyingGlassIcon = (color = 'white'): string => ` -`; +`; export const mediumIcon = (color = 'white'): string => ` -`; +`; export const minusCircledIcon = (color = 'white'): string => ` -`; +`; export const newsIcon = (color = 'white'): string => ` -`; +`; export const noteIcon = (color = 'white'): string => ` -`; +`; export const pasteIcon = (color = 'white'): string => ` -`; +`; + +export const pedestrianIcon = (color = 'white'): string => ` +`; export const pencilIcon = (color = 'white'): string => ` -`; +`; + +export const phoneCallIcon = (color = 'white'): string => ` +`; export const pictureIcon = (color = 'white'): string => ` -`; +`; export const plusIcon = (color = 'white'): string => ` -`; +`; export const plusCircledIcon = (color = 'white'): string => ` -`; +`; export const powerIcon = (color = 'white'): string => ` -`; +`; export const priceIcon = (color = 'white'): string => ` -`; +`; + +export const printerIcon = (color = 'white'): string => ` +`; export const qrIcon = (color = 'white'): string => ` -`; +`; export const receiveIcon = (color = 'white'): string => ` -`; +`; export const receivedIcon = (color = 'white'): string => ` -`; +`; export const rectanglesTwoIcon = (color = 'white'): string => ` -`; +`; export const rightArrowIcon = (color = 'white'): string => ` -`; +`; export const rightSignIcon = (color = 'white'): string => ` -`; +`; export const scanIcon = (color = 'white'): string => ` -`; +`; export const securityIcon = (color = 'white'): string => ` -`; +`; export const sendIcon = (color = 'white'): string => ` -`; +`; export const sentIcon = (color = 'white'): string => ` -`; +`; export const settingsIcon = (color = 'white'): string => ` -`; +`; export const shareAndroidIcon = (color = 'white'): string => ` -`; +`; export const shareIosIcon = (color = 'white'): string => ` -`; +`; + +export const shoppingBagIcon = (color = 'white'): string => ` +`; + +export const shoppingCartIcon = (color = 'white'): string => ` +`; export const sortAscendingIcon = (color = 'white'): string => ` -`; +`; export const speedFastIcon = (color = 'white'): string => ` -`; +`; export const speedNormalIcon = (color = 'white'): string => ` -`; +`; export const speedSlowIcon = (color = 'white'): string => ` -`; +`; export const stackIcon = (color = 'white'): string => ` -`; +`; + +export const starIcon = (color = 'white'): string => ` +`; + +export const storefrontIcon = (color = 'white'): string => ` +`; export const supportIcon = (color = 'white'): string => ` -`; +`; export const tagIcon = (color = 'white'): string => ` -`; +`; export const telegramIcon = (color = 'white'): string => ` `; export const timerIcon = (color = 'white'): string => ` -`; +`; export const timerIconAltIcon = (color = 'white'): string => ` -`; +`; export const timerSpeedIcon = (color = 'white'): string => ` -`; +`; export const toggleIcon = (color = 'white'): string => ` -`; +`; export const touchIdIcon = (color = 'white'): string => ` -`; +`; + +export const trainIcon = (color = 'white'): string => ` +`; export const transferIcon = (color = 'white'): string => ` -`; +`; export const trashIcon = (color = 'white'): string => ` -`; +`; export const twitterIcon = (color = 'white'): string => ` `; export const unifiedCircleIcon = (color = 'white'): string => ` -`; +`; export const unitBitcoinIcon = (color = 'white'): string => ` -`; +`; export const unitFiatIcon = (color = 'white'): string => ` -`; +`; export const upArrowIcon = (color = 'white'): string => ` -`; +`; export const userIcon = (color = 'white'): string => ` -`; +`; export const userMinusIcon = (color = 'white'): string => ` -`; +`; export const userPlusIcon = (color = 'white'): string => ` -`; +`; export const userSquareIcon = (color = 'white'): string => ` -`; +`; export const usersIcon = (color = 'white'): string => ` -`; +`; + +export const videoCameraIcon = (color = 'white'): string => ` +`; export const warningIcon = (color = 'white'): string => ` -`; +`; export const weatherIcon = (color = 'white'): string => ` -`; +`; export const xIcon = (color = 'white'): string => ` -`; +`; diff --git a/src/assets/illustrations/rocket2.png b/src/assets/illustrations/rocket2.png new file mode 100644 index 000000000..ed89904e4 Binary files /dev/null and b/src/assets/illustrations/rocket2.png differ diff --git a/src/assets/illustrations/shopping-bag.png b/src/assets/illustrations/shopping-bag.png new file mode 100644 index 000000000..5ae370d06 Binary files /dev/null and b/src/assets/illustrations/shopping-bag.png differ diff --git a/src/assets/svgs/raw/activity.svg b/src/assets/svgs/raw/activity.svg new file mode 100644 index 000000000..7fd404570 --- /dev/null +++ b/src/assets/svgs/raw/activity.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/assets/svgs/raw/airplane.svg b/src/assets/svgs/raw/airplane.svg new file mode 100644 index 000000000..03f8be74f --- /dev/null +++ b/src/assets/svgs/raw/airplane.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/svgs/raw/bicycle.svg b/src/assets/svgs/raw/bicycle.svg new file mode 100644 index 000000000..5f3c15928 --- /dev/null +++ b/src/assets/svgs/raw/bicycle.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/svgs/raw/car.svg b/src/assets/svgs/raw/car.svg new file mode 100644 index 000000000..bc851d439 --- /dev/null +++ b/src/assets/svgs/raw/car.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/svgs/raw/forkKnife.svg b/src/assets/svgs/raw/forkKnife.svg new file mode 100644 index 000000000..4b46cb0a6 --- /dev/null +++ b/src/assets/svgs/raw/forkKnife.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/raw/gameController.svg b/src/assets/svgs/raw/gameController.svg new file mode 100644 index 000000000..bc1b13d21 --- /dev/null +++ b/src/assets/svgs/raw/gameController.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/svgs/raw/gift.svg b/src/assets/svgs/raw/gift.svg new file mode 100644 index 000000000..7940204f0 --- /dev/null +++ b/src/assets/svgs/raw/gift.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/svgs/raw/headphones.svg b/src/assets/svgs/raw/headphones.svg new file mode 100644 index 000000000..3b146f7eb --- /dev/null +++ b/src/assets/svgs/raw/headphones.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/svgs/raw/heartbeat.svg b/src/assets/svgs/raw/heartbeat.svg index 7fd404570..b5a48a334 100644 --- a/src/assets/svgs/raw/heartbeat.svg +++ b/src/assets/svgs/raw/heartbeat.svg @@ -1,4 +1,12 @@ - - - - \ No newline at end of file + + + + + + + + + + + + diff --git a/src/assets/svgs/raw/horse.svg b/src/assets/svgs/raw/horse.svg new file mode 100644 index 000000000..6d2a9b051 --- /dev/null +++ b/src/assets/svgs/raw/horse.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgs/raw/house.svg b/src/assets/svgs/raw/house.svg new file mode 100644 index 000000000..44f7998af --- /dev/null +++ b/src/assets/svgs/raw/house.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/raw/pedestrian.svg b/src/assets/svgs/raw/pedestrian.svg new file mode 100644 index 000000000..48b31d92d --- /dev/null +++ b/src/assets/svgs/raw/pedestrian.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/assets/svgs/raw/phoneCall.svg b/src/assets/svgs/raw/phoneCall.svg new file mode 100644 index 000000000..afe371657 --- /dev/null +++ b/src/assets/svgs/raw/phoneCall.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgs/raw/printer.svg b/src/assets/svgs/raw/printer.svg new file mode 100644 index 000000000..3b88e13c9 --- /dev/null +++ b/src/assets/svgs/raw/printer.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/raw/shoppingBag.svg b/src/assets/svgs/raw/shoppingBag.svg new file mode 100644 index 000000000..a502a4cdb --- /dev/null +++ b/src/assets/svgs/raw/shoppingBag.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/svgs/raw/shoppingCart.svg b/src/assets/svgs/raw/shoppingCart.svg new file mode 100644 index 000000000..7355a75b2 --- /dev/null +++ b/src/assets/svgs/raw/shoppingCart.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/raw/star.svg b/src/assets/svgs/raw/star.svg new file mode 100644 index 000000000..6a8796669 --- /dev/null +++ b/src/assets/svgs/raw/star.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/raw/storefront.svg b/src/assets/svgs/raw/storefront.svg new file mode 100644 index 000000000..5d5787a45 --- /dev/null +++ b/src/assets/svgs/raw/storefront.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/svgs/raw/train.svg b/src/assets/svgs/raw/train.svg new file mode 100644 index 000000000..b357d82d1 --- /dev/null +++ b/src/assets/svgs/raw/train.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/svgs/raw/videoCamera.svg b/src/assets/svgs/raw/videoCamera.svg new file mode 100644 index 000000000..f23f27aa7 --- /dev/null +++ b/src/assets/svgs/raw/videoCamera.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/svgs/shop/airplane.svg b/src/assets/svgs/shop/airplane.svg new file mode 100644 index 000000000..03f8be74f --- /dev/null +++ b/src/assets/svgs/shop/airplane.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/svgs/shop/bicycle.svg b/src/assets/svgs/shop/bicycle.svg new file mode 100644 index 000000000..5f3c15928 --- /dev/null +++ b/src/assets/svgs/shop/bicycle.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/svgs/shop/car.svg b/src/assets/svgs/shop/car.svg new file mode 100644 index 000000000..bc851d439 --- /dev/null +++ b/src/assets/svgs/shop/car.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/assets/svgs/shop/forkKnife.svg b/src/assets/svgs/shop/forkKnife.svg new file mode 100644 index 000000000..4b46cb0a6 --- /dev/null +++ b/src/assets/svgs/shop/forkKnife.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/shop/gameController.svg b/src/assets/svgs/shop/gameController.svg new file mode 100644 index 000000000..bc1b13d21 --- /dev/null +++ b/src/assets/svgs/shop/gameController.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/svgs/shop/gift.svg b/src/assets/svgs/shop/gift.svg new file mode 100644 index 000000000..7940204f0 --- /dev/null +++ b/src/assets/svgs/shop/gift.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/svgs/shop/globe.svg b/src/assets/svgs/shop/globe.svg new file mode 100644 index 000000000..ddfc5d288 --- /dev/null +++ b/src/assets/svgs/shop/globe.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/shop/headphones.svg b/src/assets/svgs/shop/headphones.svg new file mode 100644 index 000000000..3b146f7eb --- /dev/null +++ b/src/assets/svgs/shop/headphones.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/svgs/shop/heartbeat.svg b/src/assets/svgs/shop/heartbeat.svg new file mode 100644 index 000000000..b5a48a334 --- /dev/null +++ b/src/assets/svgs/shop/heartbeat.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/assets/svgs/shop/horse.svg b/src/assets/svgs/shop/horse.svg new file mode 100644 index 000000000..6d2a9b051 --- /dev/null +++ b/src/assets/svgs/shop/horse.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgs/shop/house.svg b/src/assets/svgs/shop/house.svg new file mode 100644 index 000000000..44f7998af --- /dev/null +++ b/src/assets/svgs/shop/house.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/shop/pedestrian.svg b/src/assets/svgs/shop/pedestrian.svg new file mode 100644 index 000000000..48b31d92d --- /dev/null +++ b/src/assets/svgs/shop/pedestrian.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/assets/svgs/shop/phoneCall.svg b/src/assets/svgs/shop/phoneCall.svg new file mode 100644 index 000000000..afe371657 --- /dev/null +++ b/src/assets/svgs/shop/phoneCall.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgs/shop/printer.svg b/src/assets/svgs/shop/printer.svg new file mode 100644 index 000000000..3b88e13c9 --- /dev/null +++ b/src/assets/svgs/shop/printer.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/shop/shoppingBag.svg b/src/assets/svgs/shop/shoppingBag.svg new file mode 100644 index 000000000..a502a4cdb --- /dev/null +++ b/src/assets/svgs/shop/shoppingBag.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/svgs/shop/shoppingCart.svg b/src/assets/svgs/shop/shoppingCart.svg new file mode 100644 index 000000000..7355a75b2 --- /dev/null +++ b/src/assets/svgs/shop/shoppingCart.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/assets/svgs/shop/stack.svg b/src/assets/svgs/shop/stack.svg new file mode 100644 index 000000000..e2cc8da21 --- /dev/null +++ b/src/assets/svgs/shop/stack.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/svgs/shop/star.svg b/src/assets/svgs/shop/star.svg new file mode 100644 index 000000000..6a8796669 --- /dev/null +++ b/src/assets/svgs/shop/star.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/svgs/shop/train.svg b/src/assets/svgs/shop/train.svg new file mode 100644 index 000000000..b357d82d1 --- /dev/null +++ b/src/assets/svgs/shop/train.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/svgs/shop/videoCamera.svg b/src/assets/svgs/shop/videoCamera.svg new file mode 100644 index 000000000..f23f27aa7 --- /dev/null +++ b/src/assets/svgs/shop/videoCamera.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/Card.tsx b/src/components/Card.tsx new file mode 100644 index 000000000..1a63c3ffb --- /dev/null +++ b/src/components/Card.tsx @@ -0,0 +1,132 @@ +import { + Canvas, + LinearGradient, + RoundedRect, + vec, +} from '@shopify/react-native-skia'; +import React, { memo, ReactElement, useMemo } from 'react'; +import { + Image, + ImageSourcePropType, + StyleProp, + StyleSheet, + View, + ViewStyle, +} from 'react-native'; + +import { IColors } from '../styles/colors'; +import { Pressable, View as ThemedView } from '../styles/components'; +import { BodyMSB, CaptionB } from '../styles/text'; + +const CARD_SIZE = 164; +const CARD_BORDER_RADIUS = 16; +const GLOW_OFFSET = 25; + +const Shade = memo(({ size = CARD_SIZE }: { size?: number }): ReactElement => { + return ( + + + + + + + + ); +}); + +type CardProps = { + title: string; + description: string; + color: keyof IColors; + image: ImageSourcePropType; + size?: number; + style?: StyleProp; + testID?: string; + onPress: () => void; +}; + +const Card = ({ + color, + image, + title, + description, + size = CARD_SIZE, + style, + testID, + onPress, +}: CardProps): ReactElement => { + const containerStyle = useMemo( + () => [styles.container, { width: size, height: size }, style], + [style, size], + ); + + return ( + + + + + + + + + {title} + + {description} + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + alignSelf: 'center', + borderRadius: CARD_BORDER_RADIUS, + paddingHorizontal: 15, + paddingVertical: 10, + }, + pressable: { + flex: 1, + }, + imageContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + }, + image: { + height: 100, + width: 100, + }, + canvasWrapper: { + position: 'absolute', + top: -GLOW_OFFSET, + left: -GLOW_OFFSET, + }, + canvas: { + flex: 1, + }, + title: { + fontFamily: 'InterTight-Black', + fontSize: 20, + lineHeight: 20, + letterSpacing: -0.5, + textTransform: 'uppercase', + }, +}); + +export default memo(Card); diff --git a/src/components/ContactsList.tsx b/src/components/ContactsList.tsx index 1ba4ea4b4..219897d7e 100644 --- a/src/components/ContactsList.tsx +++ b/src/components/ContactsList.tsx @@ -2,8 +2,8 @@ import { BottomSheetSectionList } from '@gorhom/bottom-sheet'; import React, { ReactElement, useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { SectionList, StyleSheet, TouchableOpacity, View } from 'react-native'; -import { useAppSelector } from '../hooks/redux'; +import { useAppSelector } from '../hooks/redux'; import { useProfile, useSlashtags } from '../hooks/slashtags'; import { contactsSelector } from '../store/reselect/slashtags'; import { IContactRecord } from '../store/types/slashtags'; diff --git a/src/components/List.tsx b/src/components/List.tsx index 1480df4d2..e10d97b41 100644 --- a/src/components/List.tsx +++ b/src/components/List.tsx @@ -318,6 +318,8 @@ const Item = memo(_Item, (prevProps, nextProps) => { return isEqual(prevProps, nextProps); }); +export { Item }; + export interface IListData { data: ItemData[]; title?: string; diff --git a/src/components/Suggestions.tsx b/src/components/Suggestions.tsx index eceb2c200..83783c38a 100644 --- a/src/components/Suggestions.tsx +++ b/src/components/Suggestions.tsx @@ -11,6 +11,7 @@ import { useSheetRef } from '../sheets/SheetRefsProvider'; import { pinSelector, quickpayIntroSeenSelector, + shopIntroSeenSelector, transferIntroSeenSelector, } from '../store/reselect/settings'; import { @@ -35,6 +36,7 @@ const Suggestions = (): ReactElement => { const quickpayIntroSeen = useAppSelector(quickpayIntroSeenSelector); const suggestions = useAppSelector(todosFullSelector); const newChannels = useAppSelector(newChannelsNotificationsSelector); + const shopIntroSeen = useAppSelector(shopIntroSeenSelector); const transferIntroSeen = useAppSelector(transferIntroSeenSelector); const [index, setIndex] = useState(0); @@ -110,6 +112,14 @@ const Suggestions = (): ReactElement => { } } + if (id === 'shop') { + if (shopIntroSeen) { + navigation.navigate('ShopDiscover'); + } else { + navigation.navigate('ShopIntro'); + } + } + if (id === 'support') { navigation.navigate('Settings', { screen: 'SupportSettings' }); } diff --git a/src/constants/app.ts b/src/constants/app.ts index 0be4e86e3..9cb0c71c5 100644 --- a/src/constants/app.ts +++ b/src/constants/app.ts @@ -6,3 +6,5 @@ export const appStoreUrl = export const playStoreUrl = `https://play.google.com/store/apps/details?id=${getBundleId()}`; export const PIN_ATTEMPTS = '8'; + +export const BITREFILL_REF = 'AL6dyZYt'; diff --git a/src/navigation/root/DrawerContent.tsx b/src/navigation/root/DrawerContent.tsx index 45b86e357..fb2a9168f 100644 --- a/src/navigation/root/DrawerContent.tsx +++ b/src/navigation/root/DrawerContent.tsx @@ -9,13 +9,16 @@ import { StyleSheet, View } from 'react-native'; import AppStatus from '../../components/AppStatus'; import GradientView from '../../components/GradientView'; +import { useAppSelector } from '../../hooks/redux'; +import { shopIntroSeenSelector } from '../../store/reselect/settings'; import colors from '../../styles/colors'; import { Pressable } from '../../styles/components'; import { + ActivityIcon, CoinsIcon, - HeartbeatIcon, SettingsIcon, StackIcon, + StorefrontIcon, UserSquareIcon, UsersIcon, } from '../../styles/icons'; @@ -49,6 +52,7 @@ const DrawerItem = ({ const DrawerContent = (props: DrawerContentComponentProps): ReactElement => { const { t } = useTranslation('wallet'); const navigation = useNavigation(); + const shopIntroSeen = useAppSelector(shopIntroSeenSelector); return ( @@ -63,7 +67,7 @@ const DrawerContent = (props: DrawerContentComponentProps): ReactElement => { onPress={() => navigation.navigate('Wallet')} /> } + icon={} label={t('drawer.activity')} testID="DrawerActivity" onPress={() => { @@ -88,6 +92,18 @@ const DrawerContent = (props: DrawerContentComponentProps): ReactElement => { testID="DrawerWidgets" onPress={() => navigation.navigate('WidgetsSuggestions')} /> + } + label={t('drawer.shop')} + testID="DrawerShop" + onPress={() => { + if (shopIntroSeen) { + navigation.navigate('ShopDiscover'); + } else { + navigation.navigate('ShopIntro'); + } + }} + /> } label={t('drawer.settings')} diff --git a/src/navigation/root/RootNavigator.tsx b/src/navigation/root/RootNavigator.tsx index aee6858c3..9c35dab89 100644 --- a/src/navigation/root/RootNavigator.tsx +++ b/src/navigation/root/RootNavigator.tsx @@ -29,6 +29,9 @@ import Contacts from '../../screens/Contacts/Contacts'; import Profile from '../../screens/Profile/Profile'; import ProfileEdit from '../../screens/Profile/ProfileEdit'; import ScannerScreen from '../../screens/Scanner/MainScanner'; +import ShopDiscover from '../../screens/Shop/ShopDiscover'; +import ShopIntro from '../../screens/Shop/ShopIntro'; +import ShopMain from '../../screens/Shop/ShopMain'; import Widget from '../../screens/Widgets/Widget'; import WidgetEdit from '../../screens/Widgets/WidgetEdit'; import WidgetsOnboarding from '../../screens/Widgets/WidgetsOnboarding'; @@ -153,6 +156,9 @@ const RootNavigator = (): ReactElement => { + + + - + ); diff --git a/src/screens/Shop/ShopDiscover.tsx b/src/screens/Shop/ShopDiscover.tsx new file mode 100644 index 000000000..e9340b5bf --- /dev/null +++ b/src/screens/Shop/ShopDiscover.tsx @@ -0,0 +1,207 @@ +import React, { ReactElement, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { FlatList, StyleSheet, View, useWindowDimensions } from 'react-native'; +import { SvgProps } from 'react-native-svg'; + +import Card from '../../components/Card'; +import { EItemType, Item, ItemData } from '../../components/List'; +import NavigationHeader from '../../components/NavigationHeader'; +import SafeAreaInset from '../../components/SafeAreaInset'; +import type { RootStackScreenProps } from '../../navigation/types'; +import { View as ThemedView } from '../../styles/components'; +import { + AirplaneIcon, + BicycleIcon, + CarIcon, + ForkKnifeIcon, + GameControllerIcon, + GiftIcon, + GlobeIcon, + HeadphonesIcon, + HeartbeatIcon, + HorseIcon, + HouseIcon, + PedestrianIcon, + PhoneCallIcon, + PrinterIcon, + ShoppingBagIcon, + ShoppingCartIcon, + StackIcon, + StorefrontIcon, + TrainIcon, + VideoCameraIcon, +} from '../../styles/icons'; +import { Caption13Up } from '../../styles/text'; + +const imageGift = require('../../assets/illustrations/gift.png'); +const imageGlobe = require('../../assets/illustrations/globe.png'); +const imagePhone = require('../../assets/illustrations/phone.png'); +const imageRocket = require('../../assets/illustrations/rocket2.png'); + +const categories = [ + { title: 'Apparel', route: 'buy/apparel', icon: PedestrianIcon }, + { title: 'Automobiles', route: 'buy/automobiles', icon: CarIcon }, + { title: 'Cruises', route: 'buy/cruises', icon: TrainIcon }, + { title: 'Ecommerce', route: 'buy/ecommerce', icon: ShoppingCartIcon }, + { title: 'Electronics', route: 'buy/electronics', icon: PrinterIcon }, + { + title: 'Entertainment', + route: 'buy/entertainment', + icon: HeadphonesIcon, + }, + { title: 'Experiences', route: 'buy/experiences', icon: GlobeIcon }, + { title: 'Flights', route: 'buy/flights', icon: AirplaneIcon }, + { title: 'Food', route: 'buy/food', icon: StorefrontIcon }, + { + title: 'Food Delivery', + route: 'buy/food-delivery', + icon: BicycleIcon, + }, + { title: 'Games', route: 'buy/games', icon: GameControllerIcon }, + { title: 'Gifts', route: 'buy/gifts', icon: GiftIcon }, + { title: 'Groceries', route: 'buy/groceries', icon: ShoppingBagIcon }, + { + title: 'Health & Beauty', + route: 'buy/health-beauty', + icon: HeartbeatIcon, + }, + { title: 'Home', route: 'buy/home', icon: HouseIcon }, + { title: 'Multi-Brand', route: 'buy/multi-brand', icon: StackIcon }, + { title: 'Pets', route: 'buy/pets', icon: HorseIcon }, + { + title: 'Restaurants', + route: 'buy/restaurants', + icon: ForkKnifeIcon, + }, + { title: 'Retail', route: 'buy/retail', icon: StorefrontIcon }, + { title: 'Streaming', route: 'buy/streaming', icon: VideoCameraIcon }, + { title: 'Travel', route: 'buy/travel', icon: AirplaneIcon }, + { title: 'VoIP', route: 'buy/voip', icon: PhoneCallIcon }, +]; + +const ShopDiscover = ({ + navigation, +}: RootStackScreenProps<'ShopDiscover'>): ReactElement => { + const { t } = useTranslation('other'); + const { width } = useWindowDimensions(); + + const cardSize = (width - 32 - 16) / 2; + + const listData: ItemData[] = useMemo(() => { + const wrappedIcon = (Icon: React.FC): React.FC => { + return (props: SvgProps) => ( + + + + ); + }; + + return categories.map((category) => ({ + title: category.title, + type: EItemType.button, + Icon: wrappedIcon(category.icon), + onPress: (): void => { + navigation.navigate('ShopMain', { page: category.route }); + }, + })); + }, [navigation]); + + const ListHeader = () => ( + <> + + { + navigation.navigate('ShopMain', { page: 'gift-cards' }); + }} + /> + + { + navigation.navigate('ShopMain', { page: 'esims' }); + }} + /> + + { + navigation.navigate('ShopMain', { page: 'refill' }); + }} + /> + + { + navigation.navigate('ShopMain', { page: 'buy/travel' }); + }} + /> + + + + {t('shop.discover.label')} + + + ); + + return ( + + + + + } + ListHeaderComponent={ListHeader} + contentContainerStyle={styles.content} + showsVerticalScrollIndicator={false} + /> + + + ); +}; + +const styles = StyleSheet.create({ + root: { + flex: 1, + }, + content: { + flexGrow: 1, + paddingHorizontal: 16, + }, + cards: { + flexDirection: 'row', + flexWrap: 'wrap', + gap: 16, + marginBottom: 16, + }, + sectionHeader: { + height: 50, + justifyContent: 'center', + }, + icon: { + borderRadius: 40, + width: 32, + height: 32, + justifyContent: 'center', + alignItems: 'center', + }, +}); + +export default ShopDiscover; diff --git a/src/screens/Shop/ShopIntro.tsx b/src/screens/Shop/ShopIntro.tsx new file mode 100644 index 000000000..a639a90a9 --- /dev/null +++ b/src/screens/Shop/ShopIntro.tsx @@ -0,0 +1,34 @@ +import { NativeStackScreenProps } from '@react-navigation/native-stack'; +import React, { ReactElement } from 'react'; +import { useTranslation } from 'react-i18next'; + +import OnboardingScreen from '../../components/OnboardingScreen'; +import { useAppDispatch } from '../../hooks/redux'; +import { RootStackParamList } from '../../navigation/types'; +import { updateSettings } from '../../store/slices/settings'; +import { Display } from '../../styles/text'; + +const imageSrc = require('../../assets/illustrations/shopping-bag.png'); + +type ShopIntroProps = NativeStackScreenProps; + +const ShopIntro = ({ navigation }: ShopIntroProps): ReactElement => { + const { t } = useTranslation('other'); + const dispatch = useAppDispatch(); + + return ( + {t('shop.intro.title')}} + description={t('shop.intro.description')} + image={imageSrc} + buttonText={t('shop.intro.button')} + testID="ShopIntro" + onButtonPress={(): void => { + dispatch(updateSettings({ shopIntroSeen: true })); + navigation.navigate('ShopDiscover'); + }} + /> + ); +}; + +export default ShopIntro; diff --git a/src/screens/Shop/ShopMain.tsx b/src/screens/Shop/ShopMain.tsx new file mode 100644 index 000000000..e74aad0f9 --- /dev/null +++ b/src/screens/Shop/ShopMain.tsx @@ -0,0 +1,66 @@ +import React, { memo, ReactElement } from 'react'; +import { useTranslation } from 'react-i18next'; +import { StyleSheet, View } from 'react-native'; +import { WebView, WebViewMessageEvent } from 'react-native-webview'; + +import NavigationHeader from '../../components/NavigationHeader'; +import SafeAreaInset from '../../components/SafeAreaInset'; +import { BITREFILL_REF, appName } from '../../constants/app'; +import type { RootStackScreenProps } from '../../navigation/types'; +import { View as ThemedView } from '../../styles/components'; +import { processUri } from '../../utils/scanner/scanner'; + +const ShopMain = ({ + route, +}: RootStackScreenProps<'ShopMain'>): ReactElement => { + const { page } = route.params; + const { t } = useTranslation('other'); + + const baseUrl = 'https://embed.bitrefill.com'; + // Payment method "bitcoin" gives a unified invoice + const paymentMethod = 'bitcoin'; + const params = `?ref=${BITREFILL_REF}&paymentMethod=${paymentMethod}&theme=dark&utm_source=${appName}`; + const uri = `${baseUrl}/${page}/${params}`; + + const handleMessage = (event: WebViewMessageEvent) => { + const json = event.nativeEvent.data; + const data = JSON.parse(json); + + if (data.event === 'payment_intent') { + processUri({ uri: data.paymentUri }); + } + }; + + return ( + + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + root: { + flex: 1, + }, + content: { + flex: 1, + paddingHorizontal: 16, + }, + webview: { + backgroundColor: '#141716', + borderRadius: 8, + flex: 1, + marginBottom: 16, + }, +}); + +export default memo(ShopMain); diff --git a/src/screens/Wallets/Send/Success.tsx b/src/screens/Wallets/Send/Success.tsx index d5959151b..d8d2ccf89 100644 --- a/src/screens/Wallets/Send/Success.tsx +++ b/src/screens/Wallets/Send/Success.tsx @@ -87,7 +87,7 @@ const Success = ({ route }: SendScreenProps<'Success'>): ReactElement => {