Replace codepush with Hot updater

This commit is contained in:
minibits-cash
2025-04-21 01:23:09 +02:00
parent 0ecd9d7813
commit 9f5ac0b3a5
21 changed files with 4526 additions and 167 deletions
+1
View File
@@ -3,6 +3,7 @@
google-services.json
minibits-upload-key.keystore
GoogleService-Info.plist
minibits-prod-firebase-adminsdk.json
# OSX
#
+1 -1
View File
@@ -95,7 +95,7 @@ android {
applicationId "com.minibits_wallet"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 58034
versionCode 58036
versionName "0.2.2"
}
@@ -13,6 +13,7 @@ import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader
import com.facebook.react.modules.network.OkHttpClientProvider
// import com.microsoft.codepush.react.CodePush
import com.hotupdater.HotUpdater
class MainApplication : Application(), ReactApplication {
@@ -38,6 +39,9 @@ class MainApplication : Application(), ReactApplication {
// override fun getJSBundleFile(): String {
// return CodePush.getJSBundleFile()
// }
override fun getJSBundleFile(): String? {
return HotUpdater.getJSBundleFile(applicationContext)
}
}
override val reactHost: ReactHost
+1
View File
@@ -37,3 +37,4 @@ newArchEnabled=true
# Use this property to enable or disable the Hermes JS engine.
# If set to false, you will be using JSC instead.
hermesEnabled=true
+2 -1
View File
@@ -13,6 +13,7 @@ module.exports = {
],
'module:react-native-dotenv',
'react-native-reanimated/plugin',
'@babel/plugin-proposal-export-namespace-from'
'@babel/plugin-proposal-export-namespace-from',
'hot-updater/babel-plugin',
],
};
+26
View File
@@ -0,0 +1,26 @@
import { metro } from '@hot-updater/metro';
import {firebaseStorage, firebaseDatabase} from '@hot-updater/firebase';
import * as admin from 'firebase-admin';
import { defineConfig } from 'hot-updater';
import 'dotenv/config';
// https://firebase.google.com/docs/admin/setup?hl=en#initialize_the_sdk_in_non-google_environments
// Check your .env file and add the credentials
// Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to your credentials file path
// Example: GOOGLE_APPLICATION_CREDENTIALS=./firebase-adminsdk-credentials.json
const credential = admin.credential.applicationDefault();
export default defineConfig({
build: metro({
enableHermes: true,
}),
storage: firebaseStorage({
projectId: process.env.HOT_UPDATER_FIREBASE_PROJECT_ID!,
storageBucket: process.env.HOT_UPDATER_FIREBASE_STORAGE_BUCKET!,
credential,
}),
database: firebaseDatabase({
projectId: process.env.HOT_UPDATER_FIREBASE_PROJECT_ID!,
credential,
}),
});
+32
View File
@@ -62,6 +62,31 @@ PODS:
- hermes-engine (0.79.0-rc.3):
- hermes-engine/Pre-built (= 0.79.0-rc.3)
- hermes-engine/Pre-built (0.79.0-rc.3)
- HotUpdater (0.16.0):
- DoubleConversion
- glog
- hermes-engine
- RCT-Folly (= 2024.11.18.00)
- RCTRequired
- RCTTypeSafety
- React-Core
- React-debug
- React-Fabric
- React-featureflags
- React-graphics
- React-hermes
- React-ImageManager
- React-jsi
- React-NativeModulesApple
- React-RCTFabric
- React-renderercss
- React-rendererdebug
- React-utils
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- SSZipArchive (~> 2.2.2)
- Yoga
- libwebp (1.5.0):
- libwebp/demux (= 1.5.0)
- libwebp/mux (= 1.5.0)
@@ -2330,6 +2355,7 @@ PODS:
- SDWebImage/Core (~> 5.10)
- Sentry/HybridSDK (8.48.0)
- SocketRocket (0.7.1)
- SSZipArchive (2.2.3)
- Yoga (0.0.0)
DEPENDENCIES:
@@ -2340,6 +2366,7 @@ DEPENDENCIES:
- fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
- "HotUpdater (from `../node_modules/@hot-updater/react-native`)"
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCT-Folly/Fabric (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
- RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`)
@@ -2446,6 +2473,7 @@ SPEC REPOS:
- SDWebImageWebPCoder
- Sentry
- SocketRocket
- SSZipArchive
EXTERNAL SOURCES:
boost:
@@ -2463,6 +2491,8 @@ EXTERNAL SOURCES:
hermes-engine:
:podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec"
:tag: hermes-2025-03-03-RNv0.79.0-bc17d964d03743424823d7dd1a9f37633459c5c5
HotUpdater:
:path: "../node_modules/@hot-updater/react-native"
RCT-Folly:
:podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
RCTDeprecation:
@@ -2648,6 +2678,7 @@ SPEC CHECKSUMS:
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
hermes-engine: 222573b97e0c0023ee02f5a8480d6aa3080ceb3f
HotUpdater: 3f457ec8e209a7060a1403d6d523ef159eb016f8
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
OpenSSL-Universal: d776ce24dab24323e6995dfb17c64d598885d05c
@@ -2740,6 +2771,7 @@ SPEC CHECKSUMS:
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
Sentry: 1ca8405451040482877dcd344dfa3ef80b646631
SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748
SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9
Yoga: df4e6df930f6d93d6647c10c61d4d6fe5a694805
PODFILE CHECKSUM: b2ad66c55434d53dace9ea1b56b7aa7734ed7189
@@ -443,7 +443,10 @@
"-DFOLLY_CFG_NO_COROUTINES=1",
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
);
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
@@ -524,7 +527,10 @@
"-DFOLLY_CFG_NO_COROUTINES=1",
"-DFOLLY_HAVE_CLOCK_GETTIME=1",
);
OTHER_LDFLAGS = "$(inherited) ";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
@@ -31,7 +31,7 @@
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
buildConfiguration = "Release"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
+2
View File
@@ -3,6 +3,7 @@ import React
import React_RCTAppDelegate
import ReactAppDependencyProvider
import Firebase
import HotUpdater
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -47,6 +48,7 @@ class ReactNativeDelegate: RCTDefaultReactNativeFactoryDelegate {
RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
#else
Bundle.main.url(forResource: "main", withExtension: "jsbundle")
HotUpdater.bundleURL()
#endif
}
}
+9 -2
View File
@@ -1,11 +1,11 @@
{
"name": "minibits_wallet",
"version": "0.2.2-beta.5",
"version": "0.2.2-beta.6",
"private": true,
"scripts": {
"android:clean": "cd android && ./gradlew clean",
"android:dev": "react-native run-android --active-arch-only",
"android:test": "react-native run-android --mode=release",
"android:test": "react-native run-android --mode=release --active-arch-only",
"android:bundle": "react-native build-android --mode=release",
"android:apk": "cd android && ./gradlew assembleRelease",
"ios:dev": "npx react-native run-ios --scheme \"minibits_wallet\"",
@@ -29,6 +29,7 @@
"@gandlaf21/bc-ur": "^1.1.12",
"@gandlaf21/bolt11-decode": "^3.1.1",
"@gocodingnow/rn-size-matters": "^0.0.4",
"@hot-updater/react-native": "0.16.3",
"@notifee/react-native": "^9.1.8",
"@react-native-clipboard/clipboard": "^1.16.2",
"@react-native-community/netinfo": "^11.4.1",
@@ -87,6 +88,8 @@
"@babel/plugin-proposal-export-namespace-from": "^7.18.9",
"@babel/preset-env": "^7.25.3",
"@babel/runtime": "^7.25.0",
"@hot-updater/firebase": "0.16.3",
"@hot-updater/metro": "0.16.3",
"@react-native-community/cli": "18.0.0",
"@react-native-community/cli-platform-android": "18.0.0",
"@react-native-community/cli-platform-ios": "18.0.0",
@@ -100,8 +103,12 @@
"@types/react": "^19.0.0",
"@types/react-test-renderer": "^19.0.0",
"babel-plugin-module-resolver": "^5.0.0",
"dotenv": "^16.5.0",
"eslint": "^8.56.0",
"eslint-plugin-unused-imports": "^2.0.0",
"firebase-admin": "^13.2.0",
"firebase-tools": "^14.2.0",
"hot-updater": "^0.16.3",
"jest": "^29.6.3",
"metro-react-native-babel-preset": "0.76.7",
"prettier": "2.8.8",
-4
View File
@@ -6,7 +6,6 @@ import {
JS_BUNDLE_VERSION,
ANDROID_VERSION_NAME,
} from '@env'
// import codePush from 'react-native-code-push'
import FlashMessage from "react-native-flash-message"
import {
SafeAreaProvider,
@@ -129,7 +128,4 @@ const $title: TextStyle = {
color: 'white'
}
/*const deploymentKey = APP_ENV === Env.PROD ? CODEPUSH_PRODUCTION_DEPLOYMENT_KEY : CODEPUSH_STAGING_DEPLOYMENT_KEY
const codePushOptions = { deploymentKey, checkFrequency: codePush.CheckFrequency.MANUAL }
export default codePush(codePushOptions)(App)*/
export default App
+5 -2
View File
@@ -14,6 +14,7 @@ import { colors, useThemeColor, spacing } from "../theme"
import { Text, TextProps } from "./Text"
import { useSafeAreaInsets } from "react-native-safe-area-context"
import { Header } from "@react-navigation/stack"
import { moderateVerticalScale } from "@gocodingnow/rn-size-matters"
interface ModalProps extends ViewProps {
@@ -136,7 +137,7 @@ export function BottomModal(props: ModalProps) {
const insets = useSafeAreaInsets()
const $innerContainerStyle = [
$innerContainerBase, { backgroundColor: useThemeColor('card'), paddingBottom: insets.bottom + 60 }, $containerStyleOverride
$innerContainerBase, { backgroundColor: useThemeColor('card'), paddingBottom: insets.bottom + moderateVerticalScale(40) }, $containerStyleOverride
]
const isHeadingPresent = !!(HeadingComponent || heading || headingTx)
@@ -163,6 +164,7 @@ export function BottomModal(props: ModalProps) {
const statusBarOnModalOpen = useThemeColor('statusBarOnModalOpen')
return (
<View>
<Modal
isVisible={isVisible}
statusBarTranslucent={false}
@@ -214,7 +216,8 @@ export function BottomModal(props: ModalProps) {
/>
))}
</View>
</Modal>
</Modal>
</View>
)
}
+3 -1
View File
@@ -39,6 +39,7 @@ import {
} from "../screens"
import { colors, spacing, typography } from "../theme"
import { moderateVerticalScale } from "@gocodingnow/rn-size-matters"
import { initialWindowMetrics } from "react-native-safe-area-context"
const $tabBar: ViewStyle = {
borderTopColor: 'transparent',
@@ -152,13 +153,14 @@ declare global {
}
}
export const TabsNavigator = createBottomTabNavigator({
initialRouteName: "WalletNavigator",
backBehavior: 'firstRoute',
screenOptions: {
headerShown: false,
tabBarHideOnKeyboard: true,
tabBarStyle: [$tabBar, { height: moderateVerticalScale(70) }],
tabBarStyle: [$tabBar, { height: 70 + initialWindowMetrics?.insets.bottom }],
tabBarItemStyle: $tabBarItem,
tabBarLabelStyle: $tabBarLabel,
animation: 'shift',
+2 -1
View File
@@ -48,7 +48,8 @@ export const ContactsScreen = observer(function ({ route }: Props) {
])
const gotoProfile = function () {
navigation.navigate('Profile')
// @ts-ignore
navigation.navigate('Profile', {prevScreen: 'Contacts'})
}
const headerBg = useThemeColor('header')
+21 -3
View File
@@ -11,13 +11,18 @@ import { log } from '../services/logService'
import { KeyChain, MinibitsClient, NostrClient, NostrProfile } from '../services'
import { translate, TxKeyPath } from '../i18n'
import { CollapsibleText } from '../components/CollapsibleText'
import { StaticScreenProps, useNavigation } from '@react-navigation/native'
import { CommonActions, StaticScreenProps, useNavigation } from '@react-navigation/native'
import { QRShareModal } from '../components/QRShareModal'
type Props = StaticScreenProps<undefined>
type Props = StaticScreenProps<{
prevScreen: 'Contacts' | 'Wallet'
}>
export const ProfileScreen = observer(function ProfileScreen({ route }: Props) {
const navigation = useNavigation()
const {
prevScreen
} = route.params
const {walletProfileStore, userSettingsStore, relaysStore, walletStore} = useStores()
const {npub, nip05, pubkey} = walletProfileStore
@@ -168,7 +173,20 @@ export const ProfileScreen = observer(function ProfileScreen({ route }: Props) {
<Screen contentContainerStyle={$screen} preset='fixed'>
<Header
leftIcon='faArrowLeft'
onLeftPress={() => {navigation.goBack()}}
onLeftPress={() => {
if(prevScreen === 'Wallet') {
navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [{
name: 'WalletNavigator'
}]
})
)
} else {
navigation.goBack()
}
}}
rightIcon='faCopy'
onRightPress={onCopyNip05}
/>
+43 -14
View File
@@ -5,6 +5,8 @@ import notifee, { AuthorizationStatus } from '@notifee/react-native'
import messaging from '@react-native-firebase/messaging'
import {
APP_ENV,
HOT_UPDATER_API_KEY,
HOT_UPDATER_URL,
} from '@env'
import {ThemeCode, Themes, colors, spacing, useThemeColor} from '../theme'
import {ListItem, Screen, Text, Card, NwcIcon, Button, BottomModal, InfoModal, Icon} from '../components'
@@ -19,6 +21,7 @@ import { NotificationService } from '../services/notificationService'
import { SvgXml } from 'react-native-svg'
import { CurrencySign } from './Wallet/CurrencySign'
import { CommonActions, StaticScreenProps, useNavigation } from '@react-navigation/native'
import { HotUpdater } from '@hot-updater/react-native'
type Props = StaticScreenProps<undefined>
@@ -50,18 +53,36 @@ export const SettingsScreen = observer(function SettingsScreen({ route }: Props)
useEffect(() => {
const checkForUpdate = async () => {
try {
/*const update = await codePush.checkForUpdate(deploymentKey, handleBinaryVersionMismatchCallback)
if (update && update.failedInstall !== true) { // do not announce update that failed to install before
setUpdateDescription(update.description)
setUpdateSize(`${round(update.packageSize * 0.000001, 2)}MB`)
const updateInfo = await HotUpdater.checkForUpdate({
source: HOT_UPDATER_URL,
requestHeaders: {
Authorization: `Bearer ${HOT_UPDATER_API_KEY}`,
},
})
log.debug('[checkForUpdate]', {updateInfo})
if (!updateInfo) {
return
}
if(!__DEV__) {
setIsUpdateAvailable(true)
}*/
setUpdateDescription(updateInfo.message)
if (updateInfo.shouldForceUpdate) {
// apply emergency update immediately
await HotUpdater.updateBundle(updateInfo.id, updateInfo.fileUrl)
HotUpdater.reload()
}
}
} catch (e: any) {
log.info(e.name, e.message)
return false // silent
log.error(e)
return false
}
}
}
checkForUpdate()
}, [])
@@ -139,26 +160,32 @@ export const SettingsScreen = observer(function SettingsScreen({ route }: Props)
} */
const gotoMints = function() {
// @ts-ignore
navigation.navigate('Mints', {})
}
const gotoSecurity = function() {
// @ts-ignore
navigation.navigate('Security')
}
const gotoPrivacy = function() {
// @ts-ignore
navigation.navigate('Privacy')
}
const gotoDevOptions = function() {
// @ts-ignore
navigation.navigate('Developer')
}
const gotoRelays = function() {
// @ts-ignore
navigation.navigate('Relays')
}
}
const gotoBackupOptions = function() {
// @ts-ignore
navigation.navigate('BackupOptions')
}
@@ -171,7 +198,8 @@ export const SettingsScreen = observer(function SettingsScreen({ route }: Props)
))
}
/* const gotoUpdate = function() {
const gotoUpdate = function() {
// @ts-ignore
navigation.navigate('Update', {
isNativeUpdateAvailable,
isUpdateAvailable,
@@ -179,9 +207,10 @@ export const SettingsScreen = observer(function SettingsScreen({ route }: Props)
updateSize,
prevScreen: 'Settings'
})
}*/
}
const gotoNwc = function() {
// @ts-ignore
navigation.navigate('Nwc')
}
@@ -465,7 +494,7 @@ export const SettingsScreen = observer(function SettingsScreen({ route }: Props)
bottomSeparator={true}
onPress={gotoPrivacy}
/>
{/*<ListItem
<ListItem
tx='settingsScreen.update'
leftIcon='faWandMagicSparkles'
leftIconColor={(isUpdateAvailable || isNativeUpdateAvailable) ? colors.palette.iconMagenta200 : colors.palette.neutral400}
@@ -481,7 +510,7 @@ export const SettingsScreen = observer(function SettingsScreen({ route }: Props)
style={$item}
bottomSeparator={true}
onPress={gotoUpdate}
/>*/}
/>
<ListItem
tx='settingsScreen.devOptions'
leftIcon='faCode'
+53 -35
View File
@@ -2,9 +2,9 @@ import {observer} from 'mobx-react-lite'
import React, {FC, useEffect, useState} from 'react'
import {Linking, Platform, ScrollView, Switch, TextStyle, View, ViewStyle} from 'react-native'
import {
APP_ENV,
CODEPUSH_STAGING_DEPLOYMENT_KEY,
CODEPUSH_PRODUCTION_DEPLOYMENT_KEY,
APP_ENV,
HOT_UPDATER_API_KEY,
HOT_UPDATER_URL,
} from '@env'
// import codePush from "react-native-code-push"
import {colors, spacing, useThemeColor} from '../theme'
@@ -18,17 +18,18 @@ import {
ErrorModal,
InfoModal,
Button,
BottomModal,
} from '../components'
import {useHeader} from '../utils/useHeader'
import AppError from '../utils/AppError'
import AppError, { Err } from '../utils/AppError'
import { log } from '../services'
import {Env} from '../utils/envtypes'
import { CommonActions, StaticScreenProps, useNavigation } from '@react-navigation/native'
import { translate } from '../i18n'
import { HotUpdater, useHotUpdaterStore } from '@hot-updater/react-native'
import { ResultModalInfo } from './Wallet/ResultModalInfo'
const deploymentKey = APP_ENV === Env.PROD ? CODEPUSH_PRODUCTION_DEPLOYMENT_KEY : CODEPUSH_STAGING_DEPLOYMENT_KEY
type Props = StaticScreenProps<{
isNativeUpdateAvailable: boolean,
isUpdateAvailable: boolean,
@@ -45,14 +46,20 @@ export const UpdateScreen = observer(function UpdateScreen({ route }: Props) {
updateDescription,
updateSize,
prevScreen
} = route.params
} = route.params
const { progress, isBundleUpdated } = useHotUpdaterStore()
useHeader({
leftIcon: 'faArrowLeft',
onLeftPress: () => {
//@ts-ignore
navigation.setParams({isUpdateAvailable: undefined})
//@ts-ignore
navigation.setParams({isNativeUpdateAvailable: undefined})
//@ts-ignore
navigation.setParams({updateDescription: undefined})
//@ts-ignore
navigation.setParams({updateSize: undefined})
if(prevScreen === 'Settings') {
@@ -70,39 +77,35 @@ export const UpdateScreen = observer(function UpdateScreen({ route }: Props) {
},
})
// const {userSettingsStore} = useStores()
const [info, setInfo] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [isUpdateModalVisible, setIsUpdateModalVisible] = useState(false)
const [error, setError] = useState<AppError | undefined>()
const toggleUpdateModal = () => {
setIsUpdateModalVisible(previousState => !previousState)
}
const handleUpdate = function (): void {
/*try {
codePush.sync({
deploymentKey,
rollbackRetryOptions: {
delayInHours: 1,
maxRetryAttempts: 3
const handleUpdate = async function () {
try {
setIsUpdateModalVisible(true)
const updateInfo = await HotUpdater.checkForUpdate({
source: HOT_UPDATER_URL,
requestHeaders: {
Authorization: `Bearer ${HOT_UPDATER_API_KEY}`,
},
installMode: codePush.InstallMode.IMMEDIATE,
},
(status) => {
switch (status) {
case codePush.SyncStatus.DOWNLOADING_PACKAGE:
log.trace('Downloading update...')
setInfo(translate("updateScreen.downloading"))
break
case codePush.SyncStatus.INSTALLING_UPDATE:
log.trace('Installing update...')
setInfo(translate("updateScreen.installing"))
break
}
})
} catch (e: any) {
if (!updateInfo) {
throw new AppError(Err.NETWORK_ERROR, 'Could not retrieve update information')
}
await HotUpdater.updateBundle(updateInfo.id, updateInfo.fileUrl)
HotUpdater.reload()
} catch(e: any) {
handleError(e)
}*/
}
}
@@ -128,6 +131,7 @@ export const UpdateScreen = observer(function UpdateScreen({ route }: Props) {
const handleError = function (e: AppError): void {
setIsLoading(false)
setIsUpdateModalVisible(false)
setError(e)
}
@@ -162,14 +166,14 @@ export const UpdateScreen = observer(function UpdateScreen({ route }: Props) {
topSeparator={true}
style={$item}
/>
<ListItem
{/*<ListItem
tx='updateScreen.updateSize'
subText={updateSize || '1.0MB'}
leftIcon='faDownload'
leftIconColor={colors.palette.neutral500}
topSeparator={true}
style={$item}
/>
/>*/}
</>
)}
{isNativeUpdateAvailable && (
@@ -220,7 +224,21 @@ export const UpdateScreen = observer(function UpdateScreen({ route }: Props) {
}
/>
{isLoading && <Loading />}
</ScrollView>
</ScrollView>
<BottomModal
isVisible={isUpdateModalVisible ? true : false}
style={{alignItems: 'stretch', padding: spacing.small}}
ContentComponent={
<ResultModalInfo
icon='faDownload'
iconColor={colors.palette.accent400}
title={`${Math.round(progress * 100)}%`}
message='Update is in progress...'
/>
}
onBackButtonPress={toggleUpdateModal}
onBackdropPress={toggleUpdateModal}
/>
{error && <ErrorModal error={error} />}
{info && <InfoModal message={info} />}
</Screen>
+42 -21
View File
@@ -14,7 +14,8 @@ import {
Linking,
LayoutAnimation,
AppStateStatus,
Platform,
Platform,
Alert,
} from 'react-native'
// import codePush, { RemotePackage } from 'react-native-code-push'
import {moderateScale, verticalScale} from '@gocodingnow/rn-size-matters'
@@ -48,6 +49,8 @@ import {WalletTask} from '../services'
import {translate} from '../i18n'
import AppError, { Err } from '../utils/AppError'
import {
HOT_UPDATER_API_KEY,
HOT_UPDATER_URL,
MINIBITS_MINT_URL,
} from '@env'
import { IncomingParser } from '../services/incomingParser'
@@ -58,6 +61,7 @@ import { CurrencyAmount } from './Wallet/CurrencyAmount'
import { LeftProfileHeader } from './ContactsScreen'
import { getUnixTime } from 'date-fns/getUnixTime'
import FastImage from 'react-native-fast-image'
import { HotUpdater } from '@hot-updater/react-native'
const MINT_CHECK_INTERVAL = 60
@@ -109,24 +113,38 @@ export const WalletScreen = observer(function WalletScreen({ route }: Props) {
const [isNativeUpdateAvailable, setIsNativeUpdateAvailable] = useState<boolean>(false)
// On app start
/* useEffect(() => {
const checkForUpdate = async () => {
useEffect(() => {
const checkForUpdate = async () => {
try {
const update = await codePush.checkForUpdate(deploymentKey, handleBinaryVersionMismatchCallback)
if (update && update.failedInstall !== true) { // do not announce update that failed to install before
// log.trace('[checkForUpdate]', update)
if(ANDROID_VERSION_NAME === update.appVersion) {
setUpdateDescription(update.description)
setUpdateSize(`${round(update.packageSize * 0.000001, 2)}MB`)
setIsUpdateAvailable(true)
toggleUpdateModal()
}
}
} catch (e: any) {
return false // silent
}
const updateInfo = await HotUpdater.checkForUpdate({
source: HOT_UPDATER_URL,
requestHeaders: {
Authorization: `Bearer ${HOT_UPDATER_API_KEY}`,
},
})
log.debug('[checkForUpdate]', {updateInfo})
if (!updateInfo) {
return
}
if(!__DEV__) {
setIsUpdateAvailable(true)
setUpdateDescription(updateInfo.message)
toggleUpdateModal()
if (updateInfo.shouldForceUpdate) {
// apply emergency update immediately
await HotUpdater.updateBundle(updateInfo.id, updateInfo.fileUrl)
HotUpdater.reload()
}
}
} catch (e: any) {
log.error(e)
return false
}
}
setTimeout(() => {
@@ -139,11 +157,11 @@ export const WalletScreen = observer(function WalletScreen({ route }: Props) {
}, [])
const handleBinaryVersionMismatchCallback = function(update: RemotePackage) {
/* const handleBinaryVersionMismatchCallback = function(update: RemotePackage) {
log.info('[handleBinaryVersionMismatchCallback] triggered', ANDROID_VERSION_NAME, update)
setIsNativeUpdateAvailable(true)
toggleUpdateModal()
} */
}*/
// On app start
useEffect(() => {
@@ -394,7 +412,10 @@ export const WalletScreen = observer(function WalletScreen({ route }: Props) {
const gotoProfile = function () {
// @ts-ignore
navigation.navigate('ContactsNavigator', {
screen: 'Profile'
screen: 'Profile',
params: {
prevScreen: 'Wallet'
}
})
}
@@ -718,7 +739,7 @@ export const WalletScreen = observer(function WalletScreen({ route }: Props) {
textStyle={{marginLeft: spacing.tiny}}
preset='secondary'
/>
</View>
</View>
</View>
{info && <InfoModal message={info} />}
{error && <ErrorModal error={error} />}
+2
View File
@@ -7,6 +7,8 @@ declare module '@env' {
export const MINIBITS_NIP05_DOMAIN: string
export const MINIBITS_RELAY_URL: string
export const MINIBITS_MINT_URL: string
export const HOT_UPDATER_URL: string
export const HOT_UPDATER_API_KEY: string
export const ANDROID_VERSION_NAME: string
export const ANDROID_VERSION_CODE: string
export const JS_BUNDLE_VERSION: string
+4268 -79
View File
File diff suppressed because it is too large Load Diff