From c8a79ef0a27ef3dfadec63134f7b81a8e4a0023c Mon Sep 17 00:00:00 2001 From: andhikayuana Date: Sun, 2 Mar 2025 05:44:12 +0700 Subject: [PATCH 1/2] chore: refactor dependency injection using koin --- app/build.gradle.kts | 2 + .../java/com/brainwallet/BrainwalletApp.kt | 24 +++--- .../main/java/com/brainwallet/di/Module.kt | 37 +++++---- .../activities/settings/SettingsActivity.java | 5 +- .../presenter/activities/util/BRActivity.java | 13 ++-- .../presenter/fragments/FragmentBuy.java | 6 +- .../presenter/fragments/FragmentMenu.java | 3 +- .../language/ChangeLanguageBottomSheet.kt | 6 +- .../tools/manager/BRSharedPrefs.java | 16 ++-- .../tools/security/BRKeyStore.java | 76 +++++++++---------- .../com/brainwallet/ui/BrainwalletActivity.kt | 6 +- .../ui/screens/welcome/WelcomeScreen.kt | 4 +- .../ui/screens/welcome/WelcomeViewModel.kt | 9 +-- gradle/libs.versions.toml | 8 ++ 14 files changed, 109 insertions(+), 106 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8e57bbcc..b604e822 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -211,6 +211,8 @@ dependencies { implementation(libs.bundles.google.play.review) implementation(libs.kotlinx.serialization.json) implementation (libs.airbnb.lottie.compose) + implementation(platform(libs.koin.bom)) + implementation(libs.bundles.koin) implementation(libs.squareup.okhttp) implementation(libs.jakewarthon.timber) diff --git a/app/src/main/java/com/brainwallet/BrainwalletApp.kt b/app/src/main/java/com/brainwallet/BrainwalletApp.kt index 650c5591..5ada1bf1 100644 --- a/app/src/main/java/com/brainwallet/BrainwalletApp.kt +++ b/app/src/main/java/com/brainwallet/BrainwalletApp.kt @@ -6,7 +6,8 @@ import android.app.Application import android.content.Context import android.content.res.Resources import com.appsflyer.AppsFlyerLib -import com.brainwallet.di.Module +import com.brainwallet.di.dataModule +import com.brainwallet.di.viewModelModule import com.brainwallet.notification.setupNotificationChannels import com.brainwallet.presenter.activities.util.BRActivity import com.brainwallet.presenter.entities.ServiceItems @@ -17,6 +18,10 @@ import com.brainwallet.tools.util.Utils import com.brainwallet.util.cryptography.KeyStoreKeyGenerator import com.brainwallet.util.cryptography.KeyStoreManager import com.google.firebase.crashlytics.FirebaseCrashlytics +import org.koin.android.ext.koin.androidContext +import org.koin.android.ext.koin.androidLogger +import org.koin.core.context.GlobalContext.startKoin +import org.koin.core.logger.Level import timber.log.Timber import timber.log.Timber.DebugTree import java.util.Timer @@ -28,12 +33,12 @@ class BrainwalletApp : Application() { override fun onCreate() { super.onCreate() + initializeModule() + /** DEV: Top placement requirement. */ val enableCrashlytics = !Utils.isEmulatorOrDebug(this) FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(enableCrashlytics) - initializeModule() - setupNotificationChannels(this) AnalyticsManager.init(this) @@ -68,9 +73,13 @@ class BrainwalletApp : Application() { } protected fun initializeModule() { - module = Module(this) - module!!.remoteConfigSource.initialize() keyStoreManager = KeyStoreManager(this, KeyStoreKeyGenerator.Impl()) + + startKoin { + androidLogger(if (BuildConfig.DEBUG) Level.DEBUG else Level.ERROR) + androidContext(this@BrainwalletApp) + modules(dataModule, viewModelModule) + } } // override fun attachBaseContext(base: Context) { @@ -100,11 +109,6 @@ class BrainwalletApp : Application() { @SuppressLint("StaticFieldLeak") private var currentActivity: Activity? = null - //TODO: revisit this, please migrate using koin for DI Framework - @SuppressLint("StaticFieldLeak") - @JvmField - var module: Module? = null - @SuppressLint("StaticFieldLeak") @JvmField var keyStoreManager: KeyStoreManager? = null diff --git a/app/src/main/java/com/brainwallet/di/Module.kt b/app/src/main/java/com/brainwallet/di/Module.kt index 58f60025..b32f178f 100644 --- a/app/src/main/java/com/brainwallet/di/Module.kt +++ b/app/src/main/java/com/brainwallet/di/Module.kt @@ -7,34 +7,31 @@ import com.brainwallet.data.repository.SettingRepository import com.brainwallet.data.source.RemoteConfigSource import com.brainwallet.tools.manager.BRApiManager import com.brainwallet.tools.sqlite.CurrencyDataSource +import com.brainwallet.ui.screens.welcome.WelcomeViewModel import com.google.firebase.ktx.Firebase import com.google.firebase.remoteconfig.ktx.remoteConfig +import org.koin.android.ext.koin.androidApplication +import org.koin.core.module.dsl.viewModelOf +import org.koin.dsl.module //TODO: revisit later -class Module( - val context: Context, - val remoteConfigSource: RemoteConfigSource = provideRemoteConfigSource(), - val apiManager: BRApiManager = provideBRApiManager(remoteConfigSource), - val sharedPreferences: SharedPreferences = provideSharedPreferences(context), - val settingRepository: SettingRepository = provideSettingRepository( - sharedPreferences = sharedPreferences, - currencyDataSource = CurrencyDataSource.getInstance(context) - ) -) -private fun provideBRApiManager(remoteConfigSource: RemoteConfigSource): BRApiManager { - return BRApiManager(remoteConfigSource) -} +//todo module using koin as di framework here -private fun provideRemoteConfigSource(): RemoteConfigSource { - return RemoteConfigSource.FirebaseImpl(Firebase.remoteConfig) +val dataModule = module { + single { + RemoteConfigSource.FirebaseImpl(Firebase.remoteConfig).also { + it.initialize() + } + } + single { BRApiManager(get()) } + single { CurrencyDataSource.getInstance(get()) } + single { provideSharedPreferences(context = androidApplication()) } + single { SettingRepository.Impl(get(), get()) } } -private fun provideSettingRepository( - sharedPreferences: SharedPreferences, - currencyDataSource: CurrencyDataSource -): SettingRepository { - return SettingRepository.Impl(sharedPreferences, currencyDataSource) +val viewModelModule = module { + viewModelOf(::WelcomeViewModel) } private fun provideSharedPreferences( diff --git a/app/src/main/java/com/brainwallet/presenter/activities/settings/SettingsActivity.java b/app/src/main/java/com/brainwallet/presenter/activities/settings/SettingsActivity.java index 290ba14a..0f2e5cd2 100644 --- a/app/src/main/java/com/brainwallet/presenter/activities/settings/SettingsActivity.java +++ b/app/src/main/java/com/brainwallet/presenter/activities/settings/SettingsActivity.java @@ -30,6 +30,8 @@ import com.brainwallet.tools.animation.BRAnimator; import com.brainwallet.tools.manager.BRSharedPrefs; +import org.koin.java.KoinJavaComponent; + import java.util.ArrayList; import java.util.List; @@ -44,6 +46,8 @@ public static SettingsActivity getApp() { return app; } + private SettingRepository settingRepository = (SettingRepository) KoinJavaComponent.inject(SettingRepository.class).getValue(); + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -135,7 +139,6 @@ private void populateItems() { items.add(new BRSettingsItem(getString(R.string.Settings_manage), "", null, true)); //toggle dark mode - SettingRepository settingRepository = BrainwalletApp.module.getSettingRepository(); boolean isDarkMode = settingRepository.isDarkMode(); items.add(new BRSettingsItem(getString(R.string.toggle_dark_mode), getString(isDarkMode ? androidx.appcompat.R.string.abc_capital_on : androidx.appcompat.R.string.abc_capital_off), v -> { settingRepository.toggleDarkMode(!isDarkMode); diff --git a/app/src/main/java/com/brainwallet/presenter/activities/util/BRActivity.java b/app/src/main/java/com/brainwallet/presenter/activities/util/BRActivity.java index f7fb864d..6f62d97c 100644 --- a/app/src/main/java/com/brainwallet/presenter/activities/util/BRActivity.java +++ b/app/src/main/java/com/brainwallet/presenter/activities/util/BRActivity.java @@ -1,7 +1,6 @@ package com.brainwallet.presenter.activities.util; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; @@ -13,11 +12,11 @@ import com.brainwallet.BrainwalletApp; import com.brainwallet.data.repository.SettingRepository; -import com.brainwallet.di.Module; import com.brainwallet.presenter.activities.DisabledActivity; import com.brainwallet.presenter.activities.intro.RecoverActivity; import com.brainwallet.presenter.activities.intro.WriteDownActivity; import com.brainwallet.tools.animation.BRAnimator; +import com.brainwallet.tools.manager.BRApiManager; import com.brainwallet.tools.manager.InternetManager; import com.brainwallet.tools.security.AuthManager; import com.brainwallet.tools.security.BRKeyStore; @@ -25,10 +24,10 @@ import com.brainwallet.tools.security.PostAuth; import com.brainwallet.tools.threads.BRExecutor; import com.brainwallet.tools.util.BRConstants; -import com.brainwallet.tools.util.ExtensionKt; -import com.brainwallet.ui.BrainwalletActivity; import com.brainwallet.wallet.BRWalletManager; +import org.koin.java.KoinJavaComponent; + import java.util.Locale; import timber.log.Timber; @@ -39,12 +38,11 @@ public class BRActivity extends AppCompatActivity { System.loadLibrary(BRConstants.NATIVE_LIB_NAME); } - SettingRepository settingRepository; + private SettingRepository settingRepository = (SettingRepository) KoinJavaComponent.inject(SettingRepository.class).getValue(); @Override protected void onCreate(@Nullable Bundle savedInstanceState) { - settingRepository = BrainwalletApp.module.getSettingRepository(); //just inject here String languageCode = settingRepository.getCurrentLanguage().getCode(); Locale.setDefault(settingRepository.getCurrentLanguage().toLocale()); AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(languageCode)); @@ -150,7 +148,8 @@ public static void init(Activity app) { if (!(app instanceof RecoverActivity || app instanceof WriteDownActivity)) { - BrainwalletApp.module.getApiManager().startTimer(app); + BRApiManager apiManager = KoinJavaComponent.get(BRApiManager.class); + apiManager.startTimer(app); } //show wallet locked if it is diff --git a/app/src/main/java/com/brainwallet/presenter/fragments/FragmentBuy.java b/app/src/main/java/com/brainwallet/presenter/fragments/FragmentBuy.java index 4755a8d8..739a4073 100644 --- a/app/src/main/java/com/brainwallet/presenter/fragments/FragmentBuy.java +++ b/app/src/main/java/com/brainwallet/presenter/fragments/FragmentBuy.java @@ -32,10 +32,14 @@ import com.brainwallet.BuildConfig; import com.brainwallet.R; import com.brainwallet.tools.animation.BRAnimator; +import com.brainwallet.tools.manager.BRApiManager; import com.brainwallet.tools.manager.BRSharedPrefs; import com.brainwallet.tools.util.BRConstants; import com.brainwallet.tools.util.Utils; +import org.koin.core.component.KoinComponentKt; +import org.koin.java.KoinJavaComponent; + import java.util.Date; import timber.log.Timber; @@ -139,7 +143,7 @@ public static String url(Context context, Partner partner, String currency) { Long timestamp = new Date().getTime(); String uuid = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); String prefix = partner == Partner.MOONPAY ? "/moonpay/buy" : ""; - String baseUrl = BrainwalletApp.module.getApiManager().getBaseUrlProd(); + String baseUrl = ((BRApiManager) KoinJavaComponent.get(BRApiManager.class)).getBaseUrlProd(); return String.format(baseUrl + prefix + "?address=%s&code=%s&idate=%s&uid=%s", walletAddress, currency, timestamp, uuid); } diff --git a/app/src/main/java/com/brainwallet/presenter/fragments/FragmentMenu.java b/app/src/main/java/com/brainwallet/presenter/fragments/FragmentMenu.java index 655a45e4..44935669 100644 --- a/app/src/main/java/com/brainwallet/presenter/fragments/FragmentMenu.java +++ b/app/src/main/java/com/brainwallet/presenter/fragments/FragmentMenu.java @@ -36,6 +36,7 @@ import com.brainwallet.data.source.RemoteConfigSource; import org.json.JSONObject; +import org.koin.java.KoinJavaComponent; import java.util.ArrayList; import java.util.List; @@ -95,7 +96,7 @@ public View onCreateView(LayoutInflater inflater, * remote config example here */ try { - RemoteConfigSource remoteConfigSource = BrainwalletApp.module.getRemoteConfigSource(); + RemoteConfigSource remoteConfigSource = KoinJavaComponent.get(RemoteConfigSource.class); String string = remoteConfigSource.getString(KEY_FEATURE_MENU_HIDDEN_EXAMPLE); Timber.d("timber: [RemoteConfig] -> " + string); JSONObject configValue = new JSONObject(string); diff --git a/app/src/main/java/com/brainwallet/presenter/language/ChangeLanguageBottomSheet.kt b/app/src/main/java/com/brainwallet/presenter/language/ChangeLanguageBottomSheet.kt index 6dd6d1ea..77bb688b 100644 --- a/app/src/main/java/com/brainwallet/presenter/language/ChangeLanguageBottomSheet.kt +++ b/app/src/main/java/com/brainwallet/presenter/language/ChangeLanguageBottomSheet.kt @@ -6,7 +6,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.FrameLayout -import com.brainwallet.BrainwalletApp import com.brainwallet.R import com.brainwallet.data.model.Language import com.brainwallet.data.repository.SettingRepository @@ -17,17 +16,16 @@ import com.brainwallet.tools.util.getString import com.brainwallet.ui.RoundedBottomSheetDialogFragment import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog +import org.koin.android.ext.android.inject import java.util.Locale class ChangeLanguageBottomSheet : RoundedBottomSheetDialogFragment() { lateinit var binding: ChangeLanguageBottomSheetBinding - lateinit var settingRepository: SettingRepository + private val settingRepository by inject() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - - settingRepository = BrainwalletApp.module!!.settingRepository } override fun onCreateView( diff --git a/app/src/main/java/com/brainwallet/tools/manager/BRSharedPrefs.java b/app/src/main/java/com/brainwallet/tools/manager/BRSharedPrefs.java index 849e21ef..a3edc499 100644 --- a/app/src/main/java/com/brainwallet/tools/manager/BRSharedPrefs.java +++ b/app/src/main/java/com/brainwallet/tools/manager/BRSharedPrefs.java @@ -7,6 +7,9 @@ import com.brainwallet.data.repository.SettingRepository; import com.brainwallet.tools.util.BRConstants; +import org.koin.java.KoinJavaComponent; +import org.koin.mp.KoinPlatformTools_jvmKt; + import java.util.ArrayList; import java.util.Currency; import java.util.List; @@ -35,11 +38,7 @@ public static void removeListener(OnIsoChangedListener listener) { } public static String getIsoSymbol(Context context) { - if (BrainwalletApp.module == null) { - return "USD"; - } - - SharedPreferences settingsToGet = BrainwalletApp.module.getSharedPreferences(); + SharedPreferences settingsToGet = KoinJavaComponent.get(SharedPreferences.class); String defIso; String defaultLanguage = Locale.getDefault().getLanguage(); @@ -61,12 +60,7 @@ else if (defaultLanguage == "en") { } public static void putIso(Context context, String code) { - //migrate using new shared preferences used by setting repository - if (BrainwalletApp.module == null) { - return; - } - - SharedPreferences settings = BrainwalletApp.module.getSharedPreferences(); + SharedPreferences settings = KoinJavaComponent.get(SharedPreferences.class); SharedPreferences.Editor editor = settings.edit(); editor.putString(SettingRepository.KEY_FIAT_CURRENCY_CODE, code); //using new shared prefs used by setting repository editor.apply(); diff --git a/app/src/main/java/com/brainwallet/tools/security/BRKeyStore.java b/app/src/main/java/com/brainwallet/tools/security/BRKeyStore.java index ab17f77d..363bad5a 100644 --- a/app/src/main/java/com/brainwallet/tools/security/BRKeyStore.java +++ b/app/src/main/java/com/brainwallet/tools/security/BRKeyStore.java @@ -17,19 +17,18 @@ import android.util.Base64; import android.view.View; +import com.brainwallet.BrainwalletApp; +import com.brainwallet.R; +import com.brainwallet.exceptions.BRKeystoreErrorException; +import com.brainwallet.presenter.customviews.BRDialogView; import com.brainwallet.tools.animation.BRDialog; import com.brainwallet.tools.manager.BRSharedPrefs; import com.brainwallet.tools.threads.BRExecutor; import com.brainwallet.tools.util.BytesUtil; import com.brainwallet.tools.util.TypesConverter; import com.brainwallet.tools.util.Utils; -import com.brainwallet.BrainwalletApp; -import com.brainwallet.R; -import com.brainwallet.exceptions.BRKeystoreErrorException; -import com.brainwallet.presenter.customviews.BRDialogView; import com.brainwallet.wallet.BRWalletManager; import com.google.firebase.crashlytics.FirebaseCrashlytics; -import com.brainwallet.data.source.RemoteConfigSource; import com.platform.entities.WalletInfo; import com.platform.tools.KVStoreManager; @@ -147,28 +146,24 @@ private synchronized static boolean _setData(Context context, byte[] data, Strin int request_code, boolean auth_required) throws UserNotAuthenticatedException { validateSet(data, alias, alias_file, alias_iv, auth_required); - boolean newKeyStoreManagerEnabled = BrainwalletApp.module.getRemoteConfigSource().getBoolean(RemoteConfigSource.KEY_KEYSTORE_MANAGER_ENABLED); - Timber.d("timber: _set"); - if (newKeyStoreManagerEnabled) { - try { - lock.lock(); - return BrainwalletApp.keyStoreManager.setDataBlocking(new AliasObject(alias, alias_file, alias_iv), data); - } catch (UserNotAuthenticatedException e) { - Timber.e(e, "timber:_setData: showAuthenticationScreen: %s", alias); - showAuthenticationScreen(context, request_code, alias); - throw e; - } catch (Exception e) { - Timber.e(e, "timber:setData: error retrieving"); - FirebaseCrashlytics.getInstance().recordException(e); - return false; - } finally { - lock.unlock(); - } - } else { - return _setDataLegacy(context, data, alias, alias_iv, request_code, auth_required); + try { + lock.lock(); + return BrainwalletApp.keyStoreManager.setDataBlocking(new AliasObject(alias, alias_file, alias_iv), data); + } catch (UserNotAuthenticatedException e) { + Timber.e(e, "timber:_setData: showAuthenticationScreen: %s", alias); + showAuthenticationScreen(context, request_code, alias); + throw e; + } catch (Exception e) { + Timber.e(e, "timber:setData: error retrieving"); + FirebaseCrashlytics.getInstance().recordException(e); + return false; + } finally { + lock.unlock(); } + } + @Deprecated private static boolean _setDataLegacy(Context context, byte[] data, String alias, String alias_iv, int request_code, boolean auth_required) throws UserNotAuthenticatedException { KeyStore keyStore; try { @@ -256,27 +251,24 @@ private synchronized static byte[] _getData(final Context context, String alias, throws UserNotAuthenticatedException { validateGet(alias, alias_file, alias_iv);//validate entries - boolean newKeyStoreManagerEnabled = BrainwalletApp.module.getRemoteConfigSource().getBoolean(RemoteConfigSource.KEY_KEYSTORE_MANAGER_ENABLED); - if (newKeyStoreManagerEnabled) { - try { - lock.lock(); - return BrainwalletApp.keyStoreManager.getDataBlocking(new AliasObject(alias, alias_file, alias_iv)); - } catch (UserNotAuthenticatedException e) { - Timber.e(e, "timber:_getData: showAuthenticationScreen: %s", alias); - showAuthenticationScreen(context, request_code, alias); - throw e; - } catch (Exception e) { - Timber.e(e, "timber:getData: error retrieving"); - FirebaseCrashlytics.getInstance().recordException(e); - return null; - } finally { - lock.unlock(); - } - } else { - return _getDataLegacy(context, alias, alias_file, alias_iv, request_code); + try { + lock.lock(); + return BrainwalletApp.keyStoreManager.getDataBlocking(new AliasObject(alias, alias_file, alias_iv)); + } catch (UserNotAuthenticatedException e) { + Timber.e(e, "timber:_getData: showAuthenticationScreen: %s", alias); + showAuthenticationScreen(context, request_code, alias); + throw e; + } catch (Exception e) { + Timber.e(e, "timber:getData: error retrieving"); + FirebaseCrashlytics.getInstance().recordException(e); + return null; + } finally { + lock.unlock(); } + } + @Deprecated private static byte[] _getDataLegacy(Context context, String alias, String alias_file, String alias_iv, int request_code) throws UserNotAuthenticatedException { KeyStore keyStore; diff --git a/app/src/main/java/com/brainwallet/ui/BrainwalletActivity.kt b/app/src/main/java/com/brainwallet/ui/BrainwalletActivity.kt index 24bfe3a3..fcd88f8c 100644 --- a/app/src/main/java/com/brainwallet/ui/BrainwalletActivity.kt +++ b/app/src/main/java/com/brainwallet/ui/BrainwalletActivity.kt @@ -12,6 +12,7 @@ import androidx.lifecycle.lifecycleScope import com.brainwallet.BrainwalletApp import com.brainwallet.R import com.brainwallet.data.model.AppSetting +import com.brainwallet.data.repository.SettingRepository import com.brainwallet.navigation.LegacyNavigation import com.brainwallet.navigation.MainNavHost import com.brainwallet.navigation.Route @@ -40,6 +41,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch +import org.koin.android.ext.android.inject import timber.log.Timber @@ -48,6 +50,8 @@ import timber.log.Timber */ class BrainwalletActivity : BRActivity() { + private val settingRepository by inject() + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -63,7 +67,7 @@ class BrainwalletActivity : BRActivity() { } setContent { - val appSetting by BrainwalletApp.module!!.settingRepository.settings.collectAsState( + val appSetting by settingRepository.settings.collectAsState( AppSetting() ) diff --git a/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeScreen.kt index ddc83f5b..86fa5907 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeScreen.kt @@ -38,7 +38,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel import com.airbnb.lottie.compose.LottieAnimation import com.airbnb.lottie.compose.LottieCompositionSpec import com.airbnb.lottie.compose.LottieConstants @@ -53,11 +52,12 @@ import com.brainwallet.ui.composable.BrainwalletButton import com.brainwallet.ui.composable.bottomsheet.FiatSelectorBottomSheet import com.brainwallet.ui.composable.bottomsheet.LanguageSelectorBottomSheet import com.brainwallet.ui.theme.BrainwalletTheme +import org.koin.compose.koinInject @Composable fun WelcomeScreen( onNavigate: OnNavigate = {}, - viewModel: WelcomeViewModel = viewModel() + viewModel: WelcomeViewModel = koinInject() ) { val state by viewModel.state.collectAsState() diff --git a/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeViewModel.kt b/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeViewModel.kt index 774712d2..94079de4 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeViewModel.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeViewModel.kt @@ -3,11 +3,9 @@ package com.brainwallet.ui.screens.welcome import androidx.appcompat.app.AppCompatDelegate import androidx.core.os.LocaleListCompat import androidx.lifecycle.viewModelScope -import com.brainwallet.BrainwalletApp import com.brainwallet.data.model.AppSetting import com.brainwallet.data.model.Language import com.brainwallet.data.repository.SettingRepository -import com.brainwallet.tools.util.LocaleHelper import com.brainwallet.ui.BrainwalletViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -21,14 +19,13 @@ import kotlinx.coroutines.flow.updateAndGet import kotlinx.coroutines.launch //TODO: revisit this later -class WelcomeViewModel : BrainwalletViewModel() { +class WelcomeViewModel( + private val settingRepository: SettingRepository +) : BrainwalletViewModel() { private val _state = MutableStateFlow(WelcomeState()) val state: StateFlow = _state.asStateFlow() - private var settingRepository: SettingRepository = - BrainwalletApp.module!!.settingRepository //for now just inject here - private val appSetting = settingRepository.settings .distinctUntilChanged() .onEach { setting -> diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bac3a46d..1dd204b5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,6 +28,7 @@ jakewarthon-timber = "4.7.1" eclipse-jetty = "9.2.19.v20160908" junit = "4.13.2" mockk = "1.13.13" +koin-bom = "4.0.2" [libraries] androidx-core = { module = "androidx.core:core-ktx", version.ref = "androidx-core-ktx" } @@ -101,6 +102,12 @@ mockk = { module = "io.mockk:mockk", version.ref = "mockk" } pinterest-ktlint = "com.pinterest.ktlint:ktlint-cli:1.5.0" fastlane-screengrab = "tools.fastlane:screengrab:2.1.1" airbnb-lottie-compose = "com.airbnb.android:lottie-compose:6.5.2" +koin-bom = { module = "io.insert-koin:koin-bom", version.ref = "koin-bom" } +koin-android = { module = "io.insert-koin:koin-android" } +koin-android-compat = { module = "io.insert-koin:koin-android-compat" } +koin-compose = { module = "io.insert-koin:koin-compose" } +koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel" } + [bundles] androidx-lifecycle = ["androidx-lifecycle-runtime", "androidx-lifecycle-viewmodel", "androidx-lifecycle-viewmodel-compose"] @@ -113,6 +120,7 @@ google-play-review = ["google-play-review", "google-play-review-ktx"] eclipse-jetty = ["eclipse-jetty-webapp", "eclipse-jetty-websocket", "eclipse-jetty-continuation"] android-test = ["androidx-test-core", "androidx-test-core-ktx", "androidx-test-rules","androidx-test-espresso-core", "androidx-test-junit-ext","androidx-test-juniext-ext-ktx", "androidx-test-runner", "androidx-test-uiautomator"] androidx-compose-ui-test = ["androidx-compose-ui-test-junit4", "androidx-compose-ui-test-manifest"] +koin = ["koin-android", "koin-android-compat", "koin-compose", "koin-compose-viewmodel"] [plugins] android-application = { id = "com.android.application", version.ref = "agp" } From 1af9d75d6aa7d51d19fa6aae286aa6c0a1080423 Mon Sep 17 00:00:00 2001 From: andhikayuana Date: Tue, 4 Mar 2025 05:49:19 +0700 Subject: [PATCH 2/2] chore: viewmodel using koinInject --- app/src/main/java/com/brainwallet/di/Module.kt | 13 +++++++++++-- .../ui/screens/inputwords/InputWordsScreen.kt | 17 +++++++---------- .../ui/screens/setpasscode/SetPasscodeScreen.kt | 15 ++++++++------- .../ui/screens/unlock/UnLockScreen.kt | 4 ++-- .../yourseedproveit/YourSeedProveItScreen.kt | 4 ++-- .../yourseedwords/YourSeedWordsScreen.kt | 9 +++++---- 6 files changed, 35 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/brainwallet/di/Module.kt b/app/src/main/java/com/brainwallet/di/Module.kt index b32f178f..152ec64a 100644 --- a/app/src/main/java/com/brainwallet/di/Module.kt +++ b/app/src/main/java/com/brainwallet/di/Module.kt @@ -7,15 +7,19 @@ import com.brainwallet.data.repository.SettingRepository import com.brainwallet.data.source.RemoteConfigSource import com.brainwallet.tools.manager.BRApiManager import com.brainwallet.tools.sqlite.CurrencyDataSource +import com.brainwallet.ui.screens.inputwords.InputWordsViewModel +import com.brainwallet.ui.screens.setpasscode.SetPasscodeViewModel +import com.brainwallet.ui.screens.unlock.UnLockViewModel import com.brainwallet.ui.screens.welcome.WelcomeViewModel +import com.brainwallet.ui.screens.yourseedproveit.YourSeedProveItViewModel +import com.brainwallet.ui.screens.yourseedwords.YourSeedWordsViewModel import com.google.firebase.ktx.Firebase import com.google.firebase.remoteconfig.ktx.remoteConfig import org.koin.android.ext.koin.androidApplication +import org.koin.core.module.dsl.viewModel import org.koin.core.module.dsl.viewModelOf import org.koin.dsl.module -//TODO: revisit later - //todo module using koin as di framework here val dataModule = module { @@ -32,6 +36,11 @@ val dataModule = module { val viewModelModule = module { viewModelOf(::WelcomeViewModel) + viewModel { InputWordsViewModel() } + viewModel { SetPasscodeViewModel() } + viewModel { UnLockViewModel() } + viewModel { YourSeedProveItViewModel() } + viewModel { YourSeedWordsViewModel() } } private fun provideSharedPreferences( diff --git a/app/src/main/java/com/brainwallet/ui/screens/inputwords/InputWordsScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/inputwords/InputWordsScreen.kt index ff7685e2..c17c2c58 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/inputwords/InputWordsScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/inputwords/InputWordsScreen.kt @@ -15,7 +15,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons @@ -44,15 +43,12 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.em import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel import com.brainwallet.R import com.brainwallet.data.model.AppSetting import com.brainwallet.navigation.OnNavigate @@ -62,14 +58,14 @@ import com.brainwallet.ui.composable.BorderedLargeButton import com.brainwallet.ui.composable.BrainwalletScaffold import com.brainwallet.ui.composable.BrainwalletTopAppBar import com.brainwallet.ui.composable.SeedWordItemTextField -import com.brainwallet.ui.theme.BrainwalletAppTheme import com.brainwallet.ui.theme.BrainwalletTheme +import org.koin.compose.koinInject @Composable fun InputWordsScreen( onNavigate: OnNavigate, source: Route.InputWords.Source? = null, - viewModel: InputWordsViewModel = viewModel() + viewModel: InputWordsViewModel = koinInject() ) { val state by viewModel.state.collectAsState() val focusRequesters = List(12) { FocusRequester() } //12 seed words @@ -212,7 +208,8 @@ fun InputWordsScreen( Spacer(modifier = Modifier.height(8.dp)) Text( - modifier = Modifier.fillMaxWidth() + modifier = Modifier + .fillMaxWidth() .padding(horizontal = horizontalVerticalSpacing.dp), text = stringResource(R.string.dont_guess_desc), style = MaterialTheme.typography.bodyLarge.copy( @@ -231,11 +228,11 @@ fun InputWordsScreen( Spacer(modifier = Modifier.weight(0.5f)) BorderedLargeButton( - modifier = Modifier.testTag("buttonRestore") + modifier = Modifier + .testTag("buttonRestore") .padding(horizontal = halfLeadTrailPadding.dp) .padding(vertical = rowPadding.dp) - .height(activeRowHeight.dp) - , + .height(activeRowHeight.dp), onClick = { viewModel.onEvent(InputWordsEvent.OnRestoreClick(context = context)) focusManager.clearFocus() diff --git a/app/src/main/java/com/brainwallet/ui/screens/setpasscode/SetPasscodeScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/setpasscode/SetPasscodeScreen.kt index 2647c065..482ae79b 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/setpasscode/SetPasscodeScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/setpasscode/SetPasscodeScreen.kt @@ -29,10 +29,8 @@ import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.withStyle -import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel import com.brainwallet.R import com.brainwallet.navigation.OnNavigate import com.brainwallet.navigation.UiEffect @@ -41,12 +39,13 @@ import com.brainwallet.ui.composable.BrainwalletTopAppBar import com.brainwallet.ui.composable.PasscodeIndicator import com.brainwallet.ui.composable.PasscodeKeypad import com.brainwallet.ui.composable.PasscodeKeypadEvent +import org.koin.compose.koinInject @Composable fun SetPasscodeScreen( onNavigate: OnNavigate, passcode: List = emptyList(), - viewModel: SetPasscodeViewModel = viewModel() + viewModel: SetPasscodeViewModel = koinInject() ) { val state by viewModel.state.collectAsState() val context = LocalContext.current @@ -100,8 +99,9 @@ fun SetPasscodeScreen( ) if (state.isConfirm) { - Text(modifier = Modifier - .padding(top = leadingCopyPadding.dp), + Text( + modifier = Modifier + .padding(top = leadingCopyPadding.dp), text = stringResource(R.string.confirm_desc), style = MaterialTheme.typography.bodyLarge.copy( textAlign = TextAlign.Center, @@ -110,8 +110,9 @@ fun SetPasscodeScreen( ), ) } else { - Text(modifier = Modifier - .padding(top = leadingCopyPadding.dp), + Text( + modifier = Modifier + .padding(top = leadingCopyPadding.dp), text = buildAnnotatedString { append(stringResource(R.string.setup_app_details_1)) append("\n") diff --git a/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockScreen.kt index fd2f826d..0db28fbe 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockScreen.kt @@ -28,7 +28,6 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel import com.brainwallet.R import com.brainwallet.navigation.OnNavigate import com.brainwallet.tools.util.BRConstants @@ -38,12 +37,13 @@ import com.brainwallet.ui.composable.PasscodeIndicator import com.brainwallet.ui.composable.PasscodeKeypad import com.brainwallet.ui.composable.PasscodeKeypadEvent import com.brainwallet.ui.theme.BrainwalletTheme +import org.koin.compose.koinInject //TODO: WIP here @Composable fun UnLockScreen( onNavigate: OnNavigate, - viewModel: UnLockViewModel = viewModel() + viewModel: UnLockViewModel = koinInject() ) { val state by viewModel.state.collectAsState() val context = LocalContext.current diff --git a/app/src/main/java/com/brainwallet/ui/screens/yourseedproveit/YourSeedProveItScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/yourseedproveit/YourSeedProveItScreen.kt index 95c3b72c..3e793c6a 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/yourseedproveit/YourSeedProveItScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/yourseedproveit/YourSeedProveItScreen.kt @@ -52,7 +52,6 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel import com.brainwallet.R import com.brainwallet.navigation.OnNavigate import com.brainwallet.navigation.Route @@ -61,12 +60,13 @@ import com.brainwallet.ui.composable.BrainwalletScaffold import com.brainwallet.ui.composable.BrainwalletTopAppBar import com.brainwallet.ui.composable.LargeButton import com.brainwallet.ui.composable.SeedWordItem +import org.koin.compose.koinInject @Composable fun YourSeedProveItScreen( onNavigate: OnNavigate, seedWords: List, - viewModel: YourSeedProveItViewModel = viewModel() + viewModel: YourSeedProveItViewModel = koinInject() ) { val state by viewModel.state.collectAsState() val context = LocalContext.current diff --git a/app/src/main/java/com/brainwallet/ui/screens/yourseedwords/YourSeedWordsScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/yourseedwords/YourSeedWordsScreen.kt index 9c73bcfb..bd2e5119 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/yourseedwords/YourSeedWordsScreen.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/yourseedwords/YourSeedWordsScreen.kt @@ -28,7 +28,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel import com.brainwallet.R import com.brainwallet.navigation.OnNavigate import com.brainwallet.navigation.UiEffect @@ -36,12 +35,13 @@ import com.brainwallet.ui.composable.BrainwalletScaffold import com.brainwallet.ui.composable.BrainwalletTopAppBar import com.brainwallet.ui.composable.LargeButton import com.brainwallet.ui.composable.SeedWordItem +import org.koin.compose.koinInject @Composable fun YourSeedWordsScreen( onNavigate: OnNavigate, seedWords: List, - viewModel: YourSeedWordsViewModel = viewModel() + viewModel: YourSeedWordsViewModel = koinInject() ) { /// Layout values val columnPadding = 16 @@ -81,8 +81,9 @@ fun YourSeedWordsScreen( ) //todo: yuana private key text need to open dialog? - Text(modifier = Modifier - .padding(top = leadingCopyPadding.dp), + Text( + modifier = Modifier + .padding(top = leadingCopyPadding.dp), text = stringResource(R.string.your_seed_words_desc), style = MaterialTheme.typography.bodyLarge.copy( textAlign = TextAlign.Center,