diff --git a/app/src/main/java/com/brainwallet/data/model/AppSetting.kt b/app/src/main/java/com/brainwallet/data/model/AppSetting.kt index 0c471167..6510f7c2 100644 --- a/app/src/main/java/com/brainwallet/data/model/AppSetting.kt +++ b/app/src/main/java/com/brainwallet/data/model/AppSetting.kt @@ -5,7 +5,8 @@ data class AppSetting( val languageCode: String = Language.ENGLISH.code, val currency: CurrencyEntity = CurrencyEntity( "USD", - "USD", - -1f + "US Dollar", + -1f, + "$" ) ) \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/data/model/CurrencyEntity.java b/app/src/main/java/com/brainwallet/data/model/CurrencyEntity.java index 769df269..f0c31051 100644 --- a/app/src/main/java/com/brainwallet/data/model/CurrencyEntity.java +++ b/app/src/main/java/com/brainwallet/data/model/CurrencyEntity.java @@ -11,11 +11,13 @@ public class CurrencyEntity implements Serializable { public String code; public String name; public float rate; + public String symbol; - public CurrencyEntity(String code, String name, float rate) { + public CurrencyEntity(String code, String name, float rate, String symbol) { this.code = code; this.name = name; this.rate = rate; + this.symbol = symbol; } public CurrencyEntity() { diff --git a/app/src/main/java/com/brainwallet/data/repository/SettingRepository.kt b/app/src/main/java/com/brainwallet/data/repository/SettingRepository.kt index 024aa52b..2e4b3388 100644 --- a/app/src/main/java/com/brainwallet/data/repository/SettingRepository.kt +++ b/app/src/main/java/com/brainwallet/data/repository/SettingRepository.kt @@ -86,8 +86,9 @@ interface SettingRepository { currencyDataSource.getCurrencyByIso(it) ?: return@let CurrencyEntity( "USD", - "USD", - -1f + "US Dollar", + -1f, + "$" ) } diff --git a/app/src/main/java/com/brainwallet/di/Module.kt b/app/src/main/java/com/brainwallet/di/Module.kt index 152ec64a..69371158 100644 --- a/app/src/main/java/com/brainwallet/di/Module.kt +++ b/app/src/main/java/com/brainwallet/di/Module.kt @@ -7,6 +7,7 @@ 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.home.SettingsViewModel import com.brainwallet.ui.screens.inputwords.InputWordsViewModel import com.brainwallet.ui.screens.setpasscode.SetPasscodeViewModel import com.brainwallet.ui.screens.unlock.UnLockViewModel @@ -36,6 +37,7 @@ val dataModule = module { val viewModelModule = module { viewModelOf(::WelcomeViewModel) + viewModelOf(::SettingsViewModel) viewModel { InputWordsViewModel() } viewModel { SetPasscodeViewModel() } viewModel { UnLockViewModel() } diff --git a/app/src/main/java/com/brainwallet/navigation/LegacyNavigation.kt b/app/src/main/java/com/brainwallet/navigation/LegacyNavigation.kt index 854ceec3..b50bef17 100644 --- a/app/src/main/java/com/brainwallet/navigation/LegacyNavigation.kt +++ b/app/src/main/java/com/brainwallet/navigation/LegacyNavigation.kt @@ -5,7 +5,6 @@ import android.content.Context import android.content.Intent import com.brainwallet.R import com.brainwallet.presenter.activities.BreadActivity -import com.brainwallet.presenter.activities.LoginActivity import com.brainwallet.ui.BrainwalletActivity import timber.log.Timber @@ -25,7 +24,7 @@ object LegacyNavigation { auth: Boolean ) { Timber.i("timber: startBreadActivity: %s", from.javaClass.name) - val intent = if (auth) BrainwalletActivity.createIntent(from, Route.UnLock) + val intent = if (auth) BrainwalletActivity.createIntent(from, Route.UnLock()) else Intent(from, BreadActivity::class.java) intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) from.startActivity(intent) @@ -35,6 +34,17 @@ object LegacyNavigation { } } + @JvmStatic + fun restartBreadActivity( + context: Context + ) { + Intent(context, BreadActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK) + }.also { + context.startActivity(it) + } + } + //open compose from old activity @JvmStatic @JvmOverloads diff --git a/app/src/main/java/com/brainwallet/navigation/MainNav.kt b/app/src/main/java/com/brainwallet/navigation/MainNav.kt index 1d1fa5e1..f6e2e091 100644 --- a/app/src/main/java/com/brainwallet/navigation/MainNav.kt +++ b/app/src/main/java/com/brainwallet/navigation/MainNav.kt @@ -74,7 +74,10 @@ fun NavGraphBuilder.mainNavGraph( composable { navBackStackEntry -> val route: Route.SetPasscode = navBackStackEntry.toRoute() - SetPasscodeScreen(onNavigate = onNavigate, passcode = route.passcode) + SetPasscodeScreen( + onNavigate = onNavigate, + passcode = route.passcode, + ) } composable { navBackStackEntry -> val route: Route.InputWords = navBackStackEntry.toRoute() @@ -98,7 +101,6 @@ fun NavGraphBuilder.mainNavGraph( ) } - /** * for now, still using old activity & fragment [com.brainwallet.presenter.activities.BreadActivity] */ @@ -106,8 +108,9 @@ fun NavGraphBuilder.mainNavGraph( // HomeScreen(onNavigate = onNavigate) // } - composable { - UnLockScreen(onNavigate = onNavigate) + composable { navBackStackEntry -> + val route: Route.UnLock = navBackStackEntry.toRoute() + UnLockScreen(onNavigate = onNavigate, isUpdatePin = route.isUpdatePin) } //todo add more composable screens diff --git a/app/src/main/java/com/brainwallet/navigation/Route.kt b/app/src/main/java/com/brainwallet/navigation/Route.kt index 905d1bb8..2e0e71a8 100644 --- a/app/src/main/java/com/brainwallet/navigation/Route.kt +++ b/app/src/main/java/com/brainwallet/navigation/Route.kt @@ -15,9 +15,13 @@ sealed class Route : JavaSerializable { @Serializable object TopUp : Route() + @Serializable + object Settings : Route() + @Serializable data class SetPasscode( - val passcode: List = emptyList() + val passcode: List = emptyList(), + val isUpdatePin: Boolean = false, ) : Route() @Serializable @@ -39,6 +43,6 @@ sealed class Route : JavaSerializable { // object Home : Route() @Serializable - object UnLock : Route() + data class UnLock(val isUpdatePin: Boolean = false) : Route() } \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/presenter/activities/BreadActivity.java b/app/src/main/java/com/brainwallet/presenter/activities/BreadActivity.java index b72234b7..ed2a01c2 100644 --- a/app/src/main/java/com/brainwallet/presenter/activities/BreadActivity.java +++ b/app/src/main/java/com/brainwallet/presenter/activities/BreadActivity.java @@ -28,13 +28,17 @@ import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; import androidx.core.app.ActivityCompat; +import androidx.drawerlayout.widget.DrawerLayout; import androidx.transition.ChangeBounds; import androidx.transition.Fade; import androidx.transition.TransitionManager; import androidx.transition.TransitionSet; -import com.brainwallet.BrainwalletApp; import com.brainwallet.R; +import com.brainwallet.navigation.LegacyNavigation; +import com.brainwallet.navigation.Route; +import com.brainwallet.presenter.activities.settings.SettingsActivity; +import com.brainwallet.presenter.activities.settings.SyncBlockchainActivity; import com.brainwallet.presenter.activities.util.BRActivity; import com.brainwallet.presenter.customviews.BRNotificationBar; import com.brainwallet.presenter.fragments.BuyTabFragment; @@ -46,6 +50,7 @@ import com.brainwallet.tools.manager.InternetManager; import com.brainwallet.tools.manager.SyncManager; import com.brainwallet.tools.security.BitcoinUrlHandler; +import com.brainwallet.tools.security.PostAuth; import com.brainwallet.tools.sqlite.TransactionDataSource; import com.brainwallet.tools.threads.BRExecutor; import com.brainwallet.tools.util.BRConstants; @@ -53,11 +58,15 @@ import com.brainwallet.tools.util.BRExchange; import com.brainwallet.tools.util.ExtensionKt; import com.brainwallet.tools.util.Utils; +import com.brainwallet.ui.BrainwalletActivity; +import com.brainwallet.ui.screens.home.SettingsViewModel; +import com.brainwallet.ui.screens.home.composable.HomeSettingDrawerComposeView; import com.brainwallet.util.PermissionUtil; import com.brainwallet.wallet.BRPeerManager; import com.brainwallet.wallet.BRWalletManager; import com.google.android.gms.tasks.Task; import com.google.android.material.bottomnavigation.BottomNavigationView; +import com.google.android.material.navigation.NavigationView; import com.google.android.play.core.review.ReviewInfo; import com.google.android.play.core.review.ReviewManager; import com.google.android.play.core.review.ReviewManagerFactory; @@ -90,6 +99,9 @@ public class BreadActivity extends BRActivity implements BRWalletManager.OnBalan private BottomNavigationView bottomNav; private Handler mHandler = new Handler(); + private NavigationView navigationDrawer; + private DrawerLayout drawerLayout; + private HomeSettingDrawerComposeView homeSettingDrawerComposeView; public static BreadActivity getApp() { return app; @@ -220,7 +232,7 @@ private void setListeners() { secondaryPrice.setOnClickListener(v -> swap()); menuBut.setOnClickListener(v -> { if (BRAnimator.isClickAllowed()) { - BRAnimator.showMenuFragment(BreadActivity.this); + drawerLayout.open(); } }); } @@ -366,6 +378,33 @@ protected void onDestroy() { private void initializeViews() { menuBut = findViewById(R.id.menuBut); + + navigationDrawer = findViewById(R.id.navigationDrawer); + drawerLayout = findViewById(R.id.drawerLayout); + homeSettingDrawerComposeView = findViewById(R.id.homeDrawerComposeView); + homeSettingDrawerComposeView.observeBus(message -> { + drawerLayout.close(); + if (SettingsViewModel.LEGACY_EFFECT_ON_LOCK.equals(message.getMessage())) { + LegacyNavigation.startBreadActivity(this, true); + } else if (SettingsViewModel.LEGACY_EFFECT_ON_TOGGLE_DARK_MODE.equals(message.getMessage())) { + LegacyNavigation.restartBreadActivity(this); + } else if (SettingsViewModel.LEGACY_EFFECT_ON_SEC_UPDATE_PIN.equals(message.getMessage())) { + Intent intent = BrainwalletActivity.createIntent(this, new Route.UnLock(true)); + intent.putExtra("noPin", true); + startActivity(intent); + } else if (SettingsViewModel.LEGACY_EFFECT_ON_SEED_PHRASE.equals(message.getMessage())) { + PostAuth.getInstance().onPhraseCheckAuth(this, true); + } else if (SettingsViewModel.LEGACY_EFFECT_ON_SHARE_ANALYTICS_DATA_TOGGLE.equals(message.getMessage())) { + boolean currentShareAnalyticsDataEnabled = BRSharedPrefs.getShareData(this); + BRSharedPrefs.putShareData(this, !currentShareAnalyticsDataEnabled); + } else if (SettingsViewModel.LEGACY_EFFECT_ON_SYNC.equals(message.getMessage())) { + Intent intent = new Intent(this, SyncBlockchainActivity.class); + startActivity(intent); + overridePendingTransition(R.anim.enter_from_right, R.anim.exit_to_left); + } + return null; + }); //since we are still using this BreadActivity, need to observe EventBus e.g. lock from [HomeSettingDrawerSheet] + bottomNav = findViewById(R.id.bottomNav); bottomNav.getMenu().clear(); bottomNav.inflateMenu(isInUsa() ? R.menu.bottom_nav_menu_us : R.menu.bottom_nav_menu); 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 0f2e5cd2..7f33f632 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 @@ -140,6 +140,7 @@ private void populateItems() { //toggle dark mode 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); LegacyNavigation.openComposeScreen(SettingsActivity.this); diff --git a/app/src/main/java/com/brainwallet/presenter/activities/settings/SyncBlockchainActivity.java b/app/src/main/java/com/brainwallet/presenter/activities/settings/SyncBlockchainActivity.java index 7d52f3cf..8ec82627 100644 --- a/app/src/main/java/com/brainwallet/presenter/activities/settings/SyncBlockchainActivity.java +++ b/app/src/main/java/com/brainwallet/presenter/activities/settings/SyncBlockchainActivity.java @@ -118,6 +118,7 @@ public void onClick(BRDialogView brDialogView) { BRExecutor.getInstance().forLightWeightBackgroundTasks().execute(new Runnable() { @Override public void run() { + ///Dev: This is the structure to do full sync BRSharedPrefs.putStartHeight(SyncBlockchainActivity.this, 0); BRSharedPrefs.putAllowSpend(SyncBlockchainActivity.this, false); BRPeerManager.getInstance().rescan(); 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 739a4073..730af0a7 100644 --- a/app/src/main/java/com/brainwallet/presenter/fragments/FragmentBuy.java +++ b/app/src/main/java/com/brainwallet/presenter/fragments/FragmentBuy.java @@ -144,7 +144,8 @@ public static String url(Context context, Partner partner, String currency) { String uuid = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); String prefix = partner == Partner.MOONPAY ? "/moonpay/buy" : ""; 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); + String query = String.format(baseUrl + prefix + "?address=%s&code=%s&idate=%s&uid=%s", walletAddress, currency, timestamp, uuid); + return query; } private void closePayment() { diff --git a/app/src/main/java/com/brainwallet/tools/animation/BRAnimator.java b/app/src/main/java/com/brainwallet/tools/animation/BRAnimator.java index 41c6d64d..8c822c0b 100644 --- a/app/src/main/java/com/brainwallet/tools/animation/BRAnimator.java +++ b/app/src/main/java/com/brainwallet/tools/animation/BRAnimator.java @@ -1,5 +1,7 @@ package com.brainwallet.tools.animation; +import static androidx.databinding.DataBindingUtil.setContentView; + import android.Manifest; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -20,6 +22,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.compose.ui.platform.ComposeView; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentActivity; @@ -52,6 +55,8 @@ public class BRAnimator { public static int SLIDE_ANIMATION_DURATION = 300; public static boolean supportIsShowing; + private static boolean shouldShowSettingsComposable = false; + public static void showBreadSignal(FragmentActivity activity, String title, String iconDescription, int drawableId, BROnSignalCompletion completion) { fragmentSignal = new FragmentSignal(); Bundle bundle = new Bundle(); @@ -242,6 +247,40 @@ public static void showMenuFragment(Activity app) { transaction.commit(); } + public static void showSettingsScreen(Activity app) { + + // Create a ComposeView + ComposeView composeView = new ComposeView(app); + +// // Set the Composable function +// composeView.setContent(() -> { +// SettingsScreenKt.SettingsScreen(shouldShowSettingsComposable); +// return null; +// }); +// +// // Set the ComposeView as the content view +// setContentView(composeView); + } + +// @Override +// protected void onCreate(Bundle savedInstanceState) { +// super.onCreate(savedInstanceState); +// setContentView(R.layout.activity_main); +// ComposeView composeView = findViewById(R.id.compose_view); +// composeView.setViewCompositionStrategy(ViewCompositionStrategy.[Your choice here]); +// composeView.setContent{ +// HomeKt.Home( +// // other function arguments +// ); +// }); +// } + + + + + + + public static boolean isClickAllowed() { if (clickAllowed) { clickAllowed = false; diff --git a/app/src/main/java/com/brainwallet/tools/manager/BRApiManager.java b/app/src/main/java/com/brainwallet/tools/manager/BRApiManager.java index aa02b78b..d57f9f71 100644 --- a/app/src/main/java/com/brainwallet/tools/manager/BRApiManager.java +++ b/app/src/main/java/com/brainwallet/tools/manager/BRApiManager.java @@ -64,17 +64,18 @@ private Set getCurrencies(Activity context) { CurrencyEntity tmp = new CurrencyEntity(); try { JSONObject tmpObj = (JSONObject) arr.get(i); - tmp.name = tmpObj.getString("code"); + tmp.name = tmpObj.getString("name"); tmp.code = tmpObj.getString("code"); tmp.rate = (float) tmpObj.getDouble("n"); if (tmp.code.equalsIgnoreCase(selectedISO)) { BRSharedPrefs.putIso(context, tmp.code); BRSharedPrefs.putCurrencyListPosition(context, i - 1); } + set.add(tmp); } catch (JSONException e) { Timber.e(e); } - set.add(tmp); + } } else { Timber.d("timber: getCurrencies: failed to get currencies"); diff --git a/app/src/main/java/com/brainwallet/tools/sqlite/CurrencyDataSource.java b/app/src/main/java/com/brainwallet/tools/sqlite/CurrencyDataSource.java index 3b17ec91..40ad36b1 100644 --- a/app/src/main/java/com/brainwallet/tools/sqlite/CurrencyDataSource.java +++ b/app/src/main/java/com/brainwallet/tools/sqlite/CurrencyDataSource.java @@ -14,6 +14,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; @@ -70,40 +71,68 @@ public List getAllCurrencies(Boolean shouldBeFiltered) { List currencies = new ArrayList<>(); + /// Set the most popular fiats + /// Hack: Database needs a symbol column. This is injected here. + HashMap codeSymbolsMap = new HashMap(); + codeSymbolsMap.put("USD","$"); + codeSymbolsMap.put("EUR","€"); + codeSymbolsMap.put("GBP","£"); + codeSymbolsMap.put("SGD","$"); + codeSymbolsMap.put("CAD","$"); + codeSymbolsMap.put("AUD","$"); + codeSymbolsMap.put("RUB","₽"); + codeSymbolsMap.put("KRW","₩"); + codeSymbolsMap.put("MXN","$"); + codeSymbolsMap.put("SAR","﷼"); + codeSymbolsMap.put("UAH","₴"); + codeSymbolsMap.put("NGN","₦"); + codeSymbolsMap.put("JPY","¥"); + codeSymbolsMap.put("CNY","¥"); + codeSymbolsMap.put("IDR","Rp"); + codeSymbolsMap.put("TRY","₺"); + /// Set the most popular fiats List filteredFiatCodes = Arrays.asList("USD","EUR","GBP", "SGD","CAD","AUD","RUB","KRW","MXN","SAR","UAH","NGN","JPY","CNY","IDR","TRY"); - Cursor cursor = null; - try { - database = openDatabase(); - - cursor = database.query(BRSQLiteHelper.CURRENCY_TABLE_NAME, - allColumns, null, null, null, null, "\'" + BRSQLiteHelper.CURRENCY_CODE + "\'"); - - cursor.moveToFirst(); - while (!cursor.isAfterLast()) { - CurrencyEntity curEntity = cursorToCurrency(cursor); - currencies.add(curEntity); - cursor.moveToNext(); + Cursor cursor = null; + try { + database = openDatabase(); + + cursor = database.query(BRSQLiteHelper.CURRENCY_TABLE_NAME, + allColumns, null, null, null, null, "\'" + BRSQLiteHelper.CURRENCY_CODE + "\'"); + + cursor.moveToFirst(); + while (!cursor.isAfterLast()) { + CurrencyEntity curEntity = cursorToCurrency(cursor); + currencies.add(curEntity); + cursor.moveToNext(); + } + } finally { + if (cursor != null) + cursor.close(); + closeDatabase(); } - } finally { - if (cursor != null) - cursor.close(); - closeDatabase(); - } - if (shouldBeFiltered) { - // Filtering Brainwallet fiats - List filteredFiats = currencies.stream() - .filter(currency -> filteredFiatCodes.contains(currency.code)) - .collect(Collectors.toList()); - currencies = filteredFiats; + if (shouldBeFiltered) { + // Filtering Brainwallet fiats + List filteredFiats = currencies.stream() + .filter(currency -> filteredFiatCodes.contains(currency.code)) + .collect(Collectors.toList()); + currencies = filteredFiats; + + // Load the symbols to Brainwallet fiats + List completeCurrencyEntities = new ArrayList<>(); + for(int i=0;i Unit + } } diff --git a/app/src/main/java/com/brainwallet/ui/composable/DarkModeToggleButton.kt b/app/src/main/java/com/brainwallet/ui/composable/DarkModeToggleButton.kt new file mode 100644 index 00000000..05b89e53 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/composable/DarkModeToggleButton.kt @@ -0,0 +1,58 @@ +package com.brainwallet.ui.composable +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon +import androidx.compose.material3.IconToggleButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.brainwallet.R +import com.brainwallet.ui.theme.BrainwalletTheme + +@Composable +fun DarkModeToggleButton( + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + modifier: Modifier = Modifier, +) { + val iconButtonSize = 32 + + IconToggleButton( + checked = checked, + onCheckedChange = onCheckedChange, + modifier = modifier, + ) { + Box( + modifier = Modifier + .fillMaxSize() + .width(iconButtonSize.dp) + .aspectRatio(1f) + .clip(CircleShape) + .border( + 1.dp, + if (checked) BrainwalletTheme.colors.warn else BrainwalletTheme.colors.surface, + CircleShape + ) + .background(if (checked) BrainwalletTheme.colors.surface else BrainwalletTheme.colors.content) + ) { + Icon( + modifier = Modifier + .align(Alignment.Center) + .width(iconButtonSize.dp) + .aspectRatio(1f), + tint = if (checked) BrainwalletTheme.colors.warn else BrainwalletTheme.colors.surface, + painter = painterResource(if (checked) R.drawable.ic_light_mode else R.drawable.ic_dark_mode), + contentDescription = stringResource(R.string.toggle_dark_mode), + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/SettingsEvent.kt b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsEvent.kt new file mode 100644 index 00000000..531305b6 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsEvent.kt @@ -0,0 +1,20 @@ +package com.brainwallet.ui.screens.home + +import com.brainwallet.data.model.CurrencyEntity +import com.brainwallet.data.model.Language + +sealed class SettingsEvent { + data class OnLoad(val shareAnalyticsDataEnabled: Boolean = false) : SettingsEvent() + object OnSecurityUpdatePinClick : SettingsEvent() + object OnSecuritySeedPhraseClick : SettingsEvent() + object OnSecurityShareAnalyticsDataClick : SettingsEvent() + object OnToggleDarkMode : SettingsEvent() + object OnToggleLock : SettingsEvent() + object OnLanguageSelectorButtonClick : SettingsEvent() + object OnLanguageSelectorDismiss : SettingsEvent() + data class OnLanguageChange(val language: Language) : SettingsEvent() + object OnFiatButtonClick : SettingsEvent() + object OnFiatSelectorDismiss : SettingsEvent() + data class OnFiatChange(val currency: CurrencyEntity) : SettingsEvent() + object OnBlockchainSyncClick : SettingsEvent() +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/SettingsState.kt b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsState.kt new file mode 100644 index 00000000..3efe10a7 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsState.kt @@ -0,0 +1,17 @@ +package com.brainwallet.ui.screens.home +import com.brainwallet.data.model.CurrencyEntity +import com.brainwallet.data.model.Language + +data class SettingsState( + val darkMode: Boolean = true, + val selectedLanguage: Language = Language.ENGLISH, + val selectedCurrency: CurrencyEntity = CurrencyEntity( + "USD", + "US Dollar", + -1f, + "$" + ), //-1 = need to fetch + val languageSelectorBottomSheetVisible: Boolean = false, + val fiatSelectorBottomSheetVisible: Boolean = false, + val shareAnalyticsDataEnabled: Boolean = false, +) \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/SettingsViewModel.kt b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsViewModel.kt new file mode 100644 index 00000000..7ec71f98 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/SettingsViewModel.kt @@ -0,0 +1,148 @@ +package com.brainwallet.ui.screens.home + +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.os.LocaleListCompat +import androidx.lifecycle.viewModelScope +import com.brainwallet.data.model.AppSetting +import com.brainwallet.data.model.Language +import com.brainwallet.data.repository.SettingRepository +import com.brainwallet.ui.BrainwalletViewModel +import com.brainwallet.util.EventBus +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.flow.updateAndGet +import kotlinx.coroutines.launch + + +class SettingsViewModel( + private val settingRepository: SettingRepository +) : BrainwalletViewModel() { + + private val _state = MutableStateFlow(SettingsState()) + val state: StateFlow = _state.asStateFlow() + + val appSetting = settingRepository.settings + .distinctUntilChanged() + .onEach { setting -> + _state.update { + it.copy( + darkMode = setting.isDarkMode, + selectedLanguage = Language.find(setting.languageCode), + selectedCurrency = setting.currency, + ) + } + } + .stateIn( + viewModelScope, + SharingStarted.Eagerly, + AppSetting() + ) + + override fun onEvent(event: SettingsEvent) { + when (event) { + is SettingsEvent.OnLoad -> viewModelScope.launch { + _state.update { it.copy(shareAnalyticsDataEnabled = event.shareAnalyticsDataEnabled) } + } + + SettingsEvent.OnToggleDarkMode -> viewModelScope.launch { + _state.update { + val toggled = it.darkMode.not() + + settingRepository.save( + appSetting.value.copy( + isDarkMode = toggled + ) + ) + + it.copy(darkMode = toggled) + } + EventBus.emit(EventBus.Event.Message(LEGACY_EFFECT_ON_TOGGLE_DARK_MODE)) + } + + SettingsEvent.OnToggleLock -> viewModelScope.launch { + EventBus.emit(EventBus.Event.Message(LEGACY_EFFECT_ON_LOCK)) + } + + SettingsEvent.OnFiatButtonClick -> _state.update { + it.copy(fiatSelectorBottomSheetVisible = true) + } + + SettingsEvent.OnLanguageSelectorButtonClick -> _state.update { + it.copy(languageSelectorBottomSheetVisible = true) + } + + SettingsEvent.OnFiatSelectorDismiss -> _state.update { + it.copy( + fiatSelectorBottomSheetVisible = false + ) + } + + SettingsEvent.OnLanguageSelectorDismiss -> _state.update { + it.copy( + languageSelectorBottomSheetVisible = false + ) + } + + is SettingsEvent.OnLanguageChange -> _state.updateAndGet { + it.copy( + selectedLanguage = event.language, + languageSelectorBottomSheetVisible = false + ) + }.let { + viewModelScope.launch { + settingRepository.save(appSetting.value.copy(languageCode = event.language.code)) + AppCompatDelegate.setApplicationLocales( + LocaleListCompat.forLanguageTags( + event.language.code + ) + ) + } + } + + is SettingsEvent.OnFiatChange -> _state.updateAndGet { + it.copy(selectedCurrency = event.currency) + }.let { + viewModelScope.launch { + settingRepository.save( + appSetting.value.copy( + currency = event.currency + ) + ) + } + } + + is SettingsEvent.OnBlockchainSyncClick -> viewModelScope.launch { + EventBus.emit(EventBus.Event.Message(LEGACY_EFFECT_ON_SYNC)) + } + + SettingsEvent.OnSecuritySeedPhraseClick -> viewModelScope.launch { + EventBus.emit(EventBus.Event.Message(LEGACY_EFFECT_ON_SEED_PHRASE)) + } + + SettingsEvent.OnSecurityUpdatePinClick -> viewModelScope.launch { + EventBus.emit(EventBus.Event.Message(LEGACY_EFFECT_ON_SEC_UPDATE_PIN)) + } + + SettingsEvent.OnSecurityShareAnalyticsDataClick -> viewModelScope.launch { + _state.update { it.copy(shareAnalyticsDataEnabled = it.shareAnalyticsDataEnabled.not()) } + + EventBus.emit(EventBus.Event.Message(LEGACY_EFFECT_ON_SHARE_ANALYTICS_DATA_TOGGLE)) + } + } + } + + companion object { + const val LEGACY_EFFECT_ON_LOCK = "onLockInvoked" + const val LEGACY_EFFECT_ON_TOGGLE_DARK_MODE = "onToggleDarkMode" + const val LEGACY_EFFECT_ON_SYNC = "onSyncInvoked" + const val LEGACY_EFFECT_ON_SEC_UPDATE_PIN = "onSecUpdatePin" + const val LEGACY_EFFECT_ON_SEED_PHRASE = "onSeedPhrase" + const val LEGACY_EFFECT_ON_SHARE_ANALYTICS_DATA_TOGGLE = "onShareAnalyticsDataToggle" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/HomeSettingDrawerSheet.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/HomeSettingDrawerSheet.kt new file mode 100644 index 00000000..497770f8 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/HomeSettingDrawerSheet.kt @@ -0,0 +1,216 @@ +package com.brainwallet.ui.screens.home.composable + +import android.content.Context +import android.net.Uri +import android.util.AttributeSet +import androidx.browser.customtabs.CustomTabsIntent +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.ModalDrawerSheet +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.AbstractComposeView +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.coroutineScope +import androidx.lifecycle.findViewTreeLifecycleOwner +import com.brainwallet.R +import com.brainwallet.data.model.AppSetting +import com.brainwallet.tools.manager.BRSharedPrefs +import com.brainwallet.tools.util.BRConstants +import com.brainwallet.ui.screens.home.SettingsEvent +import com.brainwallet.ui.screens.home.SettingsViewModel +import com.brainwallet.ui.screens.home.composable.settingsrows.CurrencyDetail +import com.brainwallet.ui.screens.home.composable.settingsrows.GamesDetail +import com.brainwallet.ui.screens.home.composable.settingsrows.LanguageDetail +import com.brainwallet.ui.screens.home.composable.settingsrows.LitecoinBlockchainDetail +import com.brainwallet.ui.screens.home.composable.settingsrows.LockSettingRowItem +import com.brainwallet.ui.screens.home.composable.settingsrows.SecurityDetail +import com.brainwallet.ui.screens.home.composable.settingsrows.SettingRowItem +import com.brainwallet.ui.screens.home.composable.settingsrows.ThemeSettingRowItem +import com.brainwallet.ui.theme.BrainwalletAppTheme +import com.brainwallet.ui.theme.BrainwalletTheme +import com.brainwallet.util.EventBus +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import org.koin.compose.koinInject +import org.koin.java.KoinJavaComponent.inject + +@Composable +fun HomeSettingDrawerSheet( + modifier: Modifier = Modifier, + viewModel: SettingsViewModel = koinInject() +) { + val state by viewModel.state.collectAsState() + val context = LocalContext.current + + LaunchedEffect(Unit) { + viewModel.onEvent(SettingsEvent.OnLoad(BRSharedPrefs.getShareData(context))) //currently just load analytics share data here + } + + /// Layout values + val headerPadding = 56 + + ModalDrawerSheet( + modifier = modifier + .fillMaxWidth() + .verticalScroll(rememberScrollState()), + drawerContainerColor = BrainwalletTheme.colors.surface, + drawerContentColor = BrainwalletTheme.colors.content + ) { + LazyColumn( + modifier = Modifier + .weight(1f) + .padding(top = headerPadding.dp) + .wrapContentHeight(align = Alignment.Top) + ) { + item { + SecurityDetail( + modifier = Modifier + .fillMaxSize() + .wrapContentHeight(), + shareAnalyticsDataEnabled = state.shareAnalyticsDataEnabled, + onEvent = { + viewModel.onEvent(it) + } + ) + } + item { + LanguageDetail( + modifier = Modifier + .fillMaxSize() + .wrapContentHeight(), + selectedLanguage = state.selectedLanguage, + onLanguageSelect = { language -> + viewModel.onEvent( + SettingsEvent.OnLanguageChange( + language + ) + ) + } + ) + + } + item { + CurrencyDetail( + modifier = Modifier + .fillMaxSize() + .wrapContentHeight(), + selectedCurrency = state.selectedCurrency, + onFiatSelect = { currency -> + viewModel.onEvent( + SettingsEvent.OnFiatChange( + currency + ) + ) + } + ) + } + item { + GamesDetail( + modifier = Modifier + .fillMaxSize() + .wrapContentHeight() + ) + } + item { + LitecoinBlockchainDetail( + modifier = Modifier + .fillMaxSize() + .wrapContentHeight(), + onEvent = { + viewModel.onEvent(it) + } + ) + } + item { + SettingRowItem( + title = stringResource(R.string.settings_title_support), + description = "brainwallet.co", + onClick = { + val builder = CustomTabsIntent.Builder() + val customTabsIntent = builder.build() + customTabsIntent.launchUrl(context, Uri.parse(BRConstants.WEB_LINK)) + } + ) + } + item { + SettingRowItem( + title = stringResource(R.string.settings_title_social_media), + description = "linktr.ee/brainwallet", + onClick = { + val builder = CustomTabsIntent.Builder() + val customTabsIntent = builder.build() + customTabsIntent.launchUrl(context, Uri.parse(BRConstants.LINKTREE_URL)) + } + ) + } + item { + // Lock / Unlock + LockSettingRowItem { + viewModel.onEvent(SettingsEvent.OnToggleLock) + } + } + item { + // Theme + ThemeSettingRowItem( + darkMode = state.darkMode, + onToggledDarkMode = { + viewModel.onEvent(SettingsEvent.OnToggleDarkMode) + } + ) + } + + item { + SettingRowItem( + title = stringResource(R.string.settings_title_app_version), + description = BRConstants.APP_VERSION_NAME_CODE + ) + } + } + } +} + +/** + * for backward compat with XML, for now we are using XML + * will used by [activity_bread.xml] + */ + +class HomeSettingDrawerComposeView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : AbstractComposeView(context, attrs) { + + private val settingsViewModel: SettingsViewModel by inject(SettingsViewModel::class.java) + + @Composable + override fun Content() { + val appSetting by settingsViewModel.appSetting.collectAsState( + AppSetting() + ) + BrainwalletAppTheme(appSetting = appSetting) { + HomeSettingDrawerSheet(viewModel = settingsViewModel) + } + } + + fun observeBus( + onEach: (EventBus.Event.Message) -> Unit + ) { + EventBus.events + .filter { it is EventBus.Event.Message } + .map { it as EventBus.Event.Message } + .onEach { onEach.invoke(it) } + .launchIn(findViewTreeLifecycleOwner()!!.lifecycle.coroutineScope) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/CurrencyDetail.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/CurrencyDetail.kt new file mode 100644 index 00000000..83821a2f --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/CurrencyDetail.kt @@ -0,0 +1,101 @@ +package com.brainwallet.ui.screens.home.composable.settingsrows + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.CheckCircle +import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem +import androidx.compose.material3.ListItemDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.brainwallet.R +import com.brainwallet.data.model.CurrencyEntity +import com.brainwallet.tools.sqlite.CurrencyDataSource +import com.brainwallet.ui.theme.BrainwalletTheme + +@Composable +fun CurrencyDetail( + modifier: Modifier = Modifier, + selectedCurrency: CurrencyEntity, + onFiatSelect: (CurrencyEntity) -> Unit +) { + val context = LocalContext.current + + /// Layout values + val closedHeight = 60 + val expandedHeight = 100 + val dividerThickness = 1 + val unselectedCircleSize = 20 + val tinyPad = 2 + + SettingRowItemExpandable( + modifier = modifier, + title = stringResource(R.string.settings_title_currency) + ) { + LazyColumn( + modifier = Modifier.height(expandedHeight.dp) + ) { + items( + items = CurrencyDataSource.getInstance(context).getAllCurrencies(true) + ) { currency -> + ListItem(colors = ListItemDefaults.colors( + containerColor = BrainwalletTheme.colors.background, + headlineColor = BrainwalletTheme.colors.content, + ), modifier = Modifier.clickable { + onFiatSelect.invoke(currency) + }, headlineContent = { + Row { + Text( + modifier = Modifier.padding(tinyPad.dp), + text = currency.name, + style = MaterialTheme.typography.labelMedium + .copy(textAlign = TextAlign.Left) + ) + Spacer(modifier = Modifier.weight(1f)) + Text( + modifier = Modifier.padding(tinyPad.dp), + text = "${currency.code} (${currency.symbol})", + style = MaterialTheme.typography.labelMedium + .copy(textAlign = TextAlign.Left) + ) + } + + }, trailingContent = { + if (selectedCurrency.code == currency.code) { + Icon( + Icons.Default.CheckCircle, + contentDescription = null, + tint = BrainwalletTheme.colors.affirm + ) + } else { + Box( + modifier = Modifier + .size(unselectedCircleSize.dp) + .alpha(0.1f) + .clip(CircleShape) + .background(BrainwalletTheme.colors.content) + ) + } + }) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/GamesDetail.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/GamesDetail.kt new file mode 100644 index 00000000..02bb1132 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/GamesDetail.kt @@ -0,0 +1,88 @@ +package com.brainwallet.ui.screens.home.composable.settingsrows + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.brainwallet.R + +@Composable +fun GamesDetail( + modifier: Modifier = Modifier +) { + /// Layout values + val contentHeight = 60 + val horizontalPadding = 14 + + SettingRowItemExpandable( + modifier = modifier, + title = stringResource(R.string.settings_title_games) + ) { + Column( + modifier = Modifier.padding(horizontal = horizontalPadding.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + + Row( + modifier = Modifier + .height(contentHeight.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(R.string.game_title, 1)) + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + }) { + Text(stringResource(R.string.game_buy_price_1, "TBD")) + } + } + + Row( + modifier = Modifier + .height(contentHeight.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(R.string.game_title, 2)) + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + }) { + Text(stringResource(R.string.game_buy_price_2, "TBD")) + } + } + + Row( + modifier = Modifier + .height(contentHeight.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(R.string.game_title, 3)) + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + }) { + Text(stringResource(R.string.game_buy_price_3, "TBD")) + } + } + Row( + modifier = Modifier + .height(contentHeight.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(R.string.game_title, 4)) + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + }) { + Text(stringResource(R.string.game_buy_price_4, "TBD")) + } + } + + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LanguageDetail.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LanguageDetail.kt new file mode 100644 index 00000000..24046969 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LanguageDetail.kt @@ -0,0 +1,90 @@ +package com.brainwallet.ui.screens.home.composable.settingsrows + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.CheckCircle +import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem +import androidx.compose.material3.ListItemDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.brainwallet.R +import com.brainwallet.data.model.Language +import com.brainwallet.ui.theme.BrainwalletTheme + +//TODO +@Composable +fun LanguageDetail( + modifier: Modifier = Modifier, + selectedLanguage: Language, + onLanguageSelect: (Language) -> Unit +) { + val languages = Language.entries.toTypedArray() + + /// Layout values + val expandedHeight = 150 + val unselectedCircleSize = 20 + + + SettingRowItemExpandable( + modifier = modifier, + title = stringResource(R.string.settings_title_language) + ) { + LazyColumn(modifier = Modifier.height(expandedHeight.dp)) { + items( + items = languages + ) { language -> + ListItem( + colors = ListItemDefaults.colors( + containerColor = BrainwalletTheme.colors.background, + headlineColor = BrainwalletTheme.colors.content, + ), + modifier = Modifier.clickable { + if (language.code.isNotBlank()) { + onLanguageSelect.invoke(language) + } + }, + headlineContent = { + Text( + modifier = Modifier, + text = language.title, + style = MaterialTheme.typography.bodyMedium + .copy(textAlign = TextAlign.Left) + ) + }, + trailingContent = { + if (selectedLanguage.code == language.code) { + Icon( + Icons.Default.CheckCircle, + contentDescription = null, + tint = BrainwalletTheme.colors.affirm + ) + } else { + Box( + modifier = Modifier + .size(unselectedCircleSize.dp) + .alpha(0.1f) + .clip(CircleShape) + .background(BrainwalletTheme.colors.content) + ) + } + } + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LitecoinBlockchainDetail.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LitecoinBlockchainDetail.kt new file mode 100644 index 00000000..339584cd --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LitecoinBlockchainDetail.kt @@ -0,0 +1,53 @@ +package com.brainwallet.ui.screens.home.composable.settingsrows + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.brainwallet.R +import com.brainwallet.ui.screens.home.SettingsEvent + +//TODO +@Composable +fun LitecoinBlockchainDetail( + modifier: Modifier = Modifier, + onEvent: (SettingsEvent) -> Unit, +) { + /// Layout values + val contentHeight = 60 + val horizontalPadding = 14 + + SettingRowItemExpandable( + modifier = modifier, + title = stringResource(R.string.blockchain_litecoin) + ) { + Column( + modifier = Modifier.padding(horizontal = horizontalPadding.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + + Row( + modifier = Modifier + .height(contentHeight.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(R.string.settings_blockchain_litecoin_description)) + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + onEvent.invoke(SettingsEvent.OnBlockchainSyncClick) + }) { + Text(stringResource(R.string.settings_blockchain_litecoin_button)) + } + } + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LockSettingRowItem.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LockSettingRowItem.kt new file mode 100644 index 00000000..8f0ab2eb --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/LockSettingRowItem.kt @@ -0,0 +1,20 @@ +package com.brainwallet.ui.screens.home.composable.settingsrows + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Lock +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.brainwallet.R + +@Composable +fun LockSettingRowItem( + onClick: () -> Unit, +) { + SettingRowItem( + title = stringResource(R.string.settings_title_lock), + onClick = onClick + ) { + Icon(Icons.Default.Lock, contentDescription = stringResource(R.string.settings_title_lock)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/SecurityDetail.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/SecurityDetail.kt new file mode 100644 index 00000000..84e86234 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/SecurityDetail.kt @@ -0,0 +1,94 @@ +package com.brainwallet.ui.screens.home.composable.settingsrows + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.brainwallet.R +import com.brainwallet.ui.screens.home.SettingsEvent + +//TODO +@Composable +fun SecurityDetail( + modifier: Modifier = Modifier, + shareAnalyticsDataEnabled: Boolean = false, + onEvent: (SettingsEvent) -> Unit +) { + + /// Layout values + val contentHeight = 60 + val horizontalPadding = 14 + + SettingRowItemExpandable( + modifier = modifier, + title = stringResource(R.string.settings_title_security), + ) { + Column( + modifier = Modifier.padding(horizontal = horizontalPadding.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Row( + modifier = Modifier + .height(contentHeight.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(R.string.security_PIN_title)) + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + onEvent.invoke(SettingsEvent.OnSecurityUpdatePinClick) + }) { + Text(stringResource(R.string.security_PIN_button)) + } + } + + Row( + modifier = Modifier + .height(contentHeight.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(R.string.security_seed_phrase_title)) + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + onEvent.invoke(SettingsEvent.OnSecuritySeedPhraseClick) + }) { + Text(stringResource(R.string.security_phrase_button)) + } + } + +// Row( +// modifier = Modifier +// .height(contentHeight.dp), +// verticalAlignment = Alignment.CenterVertically +// ) { +// Text(stringResource(R.string.security_brainwallet_phrase_title)) +// Spacer(modifier = Modifier.weight(1f)) +// Button(onClick = { +// }) { +// Text(stringResource(R.string.security_phrase_button)) +// } +// } + Row( + modifier = Modifier + .height(contentHeight.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text(stringResource(R.string.security_share_data_title)) + Spacer(modifier = Modifier.weight(1f)) + Button(onClick = { + onEvent.invoke(SettingsEvent.OnSecurityShareAnalyticsDataClick) + }) { + Text(stringResource(if (shareAnalyticsDataEnabled) R.string.Button_yes else R.string.Button_no)) + } + } + + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/SettingRowItem.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/SettingRowItem.kt new file mode 100644 index 00000000..845e31c2 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/SettingRowItem.kt @@ -0,0 +1,121 @@ +package com.brainwallet.ui.screens.home.composable.settingsrows + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.KeyboardArrowDown +import androidx.compose.material.icons.filled.KeyboardArrowUp +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem +import androidx.compose.material3.ListItemColors +import androidx.compose.material3.ListItemDefaults +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.brainwallet.ui.theme.BrainwalletColors +import com.brainwallet.ui.theme.BrainwalletTheme + +/** + * main composable for [SettingRowItem] and [SettingRowItemExpandable] + */ + +@Composable +fun SettingRowItem( + modifier: Modifier = Modifier, + title: String, + description: String? = null, + onClick: (() -> Unit)? = null, + trailingIcon: @Composable (() -> Unit)? = null, +) { + SettingRowItemExpandable( + modifier = modifier, + title = title, + description = description, + trailingIcon = trailingIcon, + hasExpandedContent = false, + onClick = onClick + ) { } +} + +@Composable +fun SettingRowItemExpandable( + modifier: Modifier = Modifier, + title: String, + description: String? = null, + hasExpandedContent: Boolean = true, + trailingIcon: @Composable (() -> Unit)? = null, + onClick: (() -> Unit)? = null, + colors: ListItemColors = ListItemDefaults.colors( + containerColor = BrainwalletTheme.colors.surface, + headlineColor = BrainwalletTheme.colors.content, + supportingColor = BrainwalletTheme.colors.content.copy(0.6f), + trailingIconColor = BrainwalletTheme.colors.content, + ), + content: @Composable () -> Unit, +) { + var expanded by remember { mutableStateOf(false) } + + /// Layout values + val closedHeight = 60 + val expandedHeight = 100 + val dividerThickness = 1 + val horizontalPadding = 14 + + + Column( + modifier = modifier.background(BrainwalletTheme.colors.settingRowItemBackground(expanded)) + ) { + HorizontalDivider(thickness = dividerThickness.dp, color = BrainwalletTheme.colors.content) + ListItem( + colors = colors, + modifier = Modifier.clickable { + if (hasExpandedContent) { + expanded = expanded.not() + } else { + onClick?.invoke() + } + }, + headlineContent = { + Text( + text = title, + style = BrainwalletTheme.typography.labelLarge + .copy(textAlign = TextAlign.Left) + ) + }, + supportingContent = { + description?.let { Text(text = it) } + }, + trailingContent = { + if (hasExpandedContent) { + Icon( + if (expanded) Icons.Default.KeyboardArrowUp else Icons.Default.KeyboardArrowDown, + contentDescription = null + ) + } else { + trailingIcon?.invoke() + } + } + ) + + AnimatedVisibility( + visible = expanded, + modifier = Modifier.padding(vertical = 8.dp) + ) { + content.invoke() + } + } +} + +fun BrainwalletColors.settingRowItemBackground( + expanded: Boolean = false +) = if (expanded) background else surface \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/ThemeSettingRowItem.kt b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/ThemeSettingRowItem.kt new file mode 100644 index 00000000..98a8b1e5 --- /dev/null +++ b/app/src/main/java/com/brainwallet/ui/screens/home/composable/settingsrows/ThemeSettingRowItem.kt @@ -0,0 +1,32 @@ +package com.brainwallet.ui.screens.home.composable.settingsrows + +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.brainwallet.R +import com.brainwallet.ui.composable.DarkModeToggleButton + +@Composable +fun ThemeSettingRowItem( + darkMode: Boolean = true, + onToggledDarkMode: () -> Unit +) { + val toggleButtonSize = 24 + SettingRowItem( + title = stringResource(R.string.settings_title_theme), + onClick = onToggledDarkMode + ) { + DarkModeToggleButton( + modifier = Modifier + .width(toggleButtonSize.dp) + .aspectRatio(1f), + checked = darkMode, + onCheckedChange = { + onToggledDarkMode.invoke() + } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/setpasscode/SetPasscodeState.kt b/app/src/main/java/com/brainwallet/ui/screens/setpasscode/SetPasscodeState.kt index 6ee3206c..c8286b67 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/setpasscode/SetPasscodeState.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/setpasscode/SetPasscodeState.kt @@ -4,6 +4,7 @@ data class SetPasscodeState( val isConfirm: Boolean = false, val passcode: List = List(4) { -1 }, //create 4 digit val passcodeConfirm: List = List(4) { -1 }, //create 4 digit + val isUpdatePin: Boolean = false, ) fun SetPasscodeState.isMatchPasscode(): Boolean = diff --git a/app/src/main/java/com/brainwallet/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/com/brainwallet/ui/screens/settings/SettingsScreen.kt deleted file mode 100644 index b3d1f4c0..00000000 --- a/app/src/main/java/com/brainwallet/ui/screens/settings/SettingsScreen.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.brainwallet.ui.screens.settings - -import androidx.compose.runtime.Composable - -@Composable -fun SettingsScreen() { - //todo -} \ No newline at end of file diff --git a/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockEvent.kt b/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockEvent.kt index 1fd49dbc..c83406f9 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockEvent.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockEvent.kt @@ -3,8 +3,14 @@ package com.brainwallet.ui.screens.unlock import android.content.Context sealed class UnLockEvent { - data class OnLoad(val context: Context) : UnLockEvent() - data class OnPinDigitChange(val digit: Int) : UnLockEvent() + data class OnLoad( + val context: Context, + val isUpdatePin: Boolean = false, + ) : UnLockEvent() + data class OnPinDigitChange( + val digit: Int, + val isValidPin: (String) -> Boolean + ) : UnLockEvent() object OnDeletePinDigit : UnLockEvent() } 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 acd4819d..0ea4da7e 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 @@ -3,6 +3,7 @@ package com.brainwallet.ui.screens.unlock +import android.widget.Toast import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -30,6 +31,9 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.brainwallet.R import com.brainwallet.navigation.OnNavigate +import com.brainwallet.navigation.UiEffect +import com.brainwallet.tools.manager.AnalyticsManager +import com.brainwallet.tools.security.AuthManager import com.brainwallet.tools.util.BRConstants import com.brainwallet.ui.composable.BrainwalletScaffold import com.brainwallet.ui.composable.BrainwalletTopAppBar @@ -39,17 +43,23 @@ 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, + isUpdatePin: Boolean = false, viewModel: UnLockViewModel = koinInject() ) { val state by viewModel.state.collectAsState() val context = LocalContext.current LaunchedEffect(Unit) { - viewModel.onEvent(UnLockEvent.OnLoad(context)) + viewModel.onEvent(UnLockEvent.OnLoad(context, isUpdatePin)) + viewModel.uiEffect.collect { effect -> + when (effect) { + is UiEffect.Navigate -> onNavigate.invoke(effect) + else -> Unit + } + } } LaunchedEffect(state.passcode.all { it > -1 }) { @@ -90,8 +100,12 @@ fun UnLockScreen( ) Spacer(modifier = Modifier.weight(1f)) - Text(stringResource(R.string.Login_ltcPrice, state.formattedCurrency)) - Text(stringResource(R.string.Login_currentLtcPrice, state.iso)) + if (state.isUpdatePin) { + Text(stringResource(R.string.UpdatePin_enterCurrent)) + } else { + Text(stringResource(R.string.Login_ltcPrice, state.formattedCurrency)) + Text(stringResource(R.string.Login_currentLtcPrice, state.iso)) + } // TODO // https://developer.android.com/develop/ui/compose/animation/customize @@ -116,7 +130,28 @@ fun UnLockScreen( PasscodeKeypadEvent.OnDelete -> viewModel.onEvent(UnLockEvent.OnDeletePinDigit) is PasscodeKeypadEvent.OnPressed -> viewModel.onEvent( UnLockEvent.OnPinDigitChange( - digit = passcodeKeypadEvent.digit + digit = passcodeKeypadEvent.digit, + isValidPin = { pin -> + + //provide old logic here, its like on the BrainwalletActivity.onUnlock + return@OnPinDigitChange AuthManager.getInstance() + .checkAuth(pin, context).also { isValid -> + if (isValid) { + AuthManager.getInstance().authSuccess(context) + AnalyticsManager.logCustomEvent(BRConstants._20200217_DUWB) + AnalyticsManager.logCustomEvent(BRConstants._20200217_DUWB) + + } else { + AuthManager.getInstance().authFail(context) + //for now just toast + Toast.makeText( + context, + R.string.incorrect_passcode, + Toast.LENGTH_SHORT + ).show() + } + } + } ) ) } diff --git a/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockState.kt b/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockState.kt index 713b1c95..ff12dab1 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockState.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockState.kt @@ -4,7 +4,8 @@ data class UnLockState( val passcode: List = List(4) { -1 }, //4 digit passcode/pin val biometricEnabled: Boolean = false, val iso: String = "USD", - val formattedCurrency: String = "" + val formattedCurrency: String = "", + val isUpdatePin: Boolean = false, ) fun UnLockState.isPasscodeFilled(): Boolean = passcode.all { it > -1 } diff --git a/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockViewModel.kt b/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockViewModel.kt index 05277d25..686b562c 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockViewModel.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/unlock/UnLockViewModel.kt @@ -1,10 +1,9 @@ package com.brainwallet.ui.screens.unlock import androidx.lifecycle.viewModelScope -import com.brainwallet.navigation.LegacyNavigation -import com.brainwallet.tools.manager.AnalyticsManager +import com.brainwallet.navigation.Route +import com.brainwallet.navigation.UiEffect import com.brainwallet.tools.manager.BRSharedPrefs -import com.brainwallet.tools.security.AuthManager import com.brainwallet.tools.sqlite.CurrencyDataSource import com.brainwallet.tools.util.BRConstants import com.brainwallet.tools.util.BRCurrency @@ -41,10 +40,23 @@ class UnLockViewModel : BrainwalletViewModel() { it.copy(passcode = pinDigits) }.also { + if (it.isPasscodeFilled() && it.isUpdatePin) { + //if update pin from drawer + if (event.isValidPin.invoke(it.passcode.joinToString(""))) { + sendUiEffect( + UiEffect.Navigate( + destinationRoute = Route.SetPasscode() + ) + ) + } + return + } + if (it.isPasscodeFilled()) { viewModelScope.launch { EventBus.emit(EventBus.Event.LegacyUnLock(it.passcode)) } + return } } @@ -80,7 +92,12 @@ class UnLockViewModel : BrainwalletViewModel() { if (formattedCurrency != null) { _state.update { - it.copy(iso = iso, formattedCurrency = formattedCurrency) + it.copy( + iso = iso, + formattedCurrency = formattedCurrency, + isUpdatePin = event.isUpdatePin + ) + } } } 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 77104115..da80ef85 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 @@ -49,6 +49,7 @@ import com.brainwallet.navigation.Route import com.brainwallet.navigation.UiEffect import com.brainwallet.ui.composable.BorderedLargeButton import com.brainwallet.ui.composable.BrainwalletButton +import com.brainwallet.ui.composable.DarkModeToggleButton import com.brainwallet.ui.composable.bottomsheet.FiatSelectorBottomSheet import com.brainwallet.ui.composable.bottomsheet.LanguageSelectorBottomSheet import com.brainwallet.ui.theme.BrainwalletTheme @@ -157,32 +158,7 @@ fun WelcomeScreen( onCheckedChange = { viewModel.onEvent(WelcomeEvent.OnToggleDarkMode) } - ) { - - Box( - modifier = Modifier - .fillMaxSize() - .width(iconButtonSize.dp) - .aspectRatio(1f) - .clip(CircleShape) - .border( - 1.dp, - if (state.darkMode) BrainwalletTheme.colors.warn else BrainwalletTheme.colors.surface, - CircleShape - ) - .background(if (state.darkMode) BrainwalletTheme.colors.surface else BrainwalletTheme.colors.content) - ) { - Icon( - modifier = Modifier - .align(Alignment.Center) - .width(iconButtonSize.dp) - .aspectRatio(1f), - tint = if (state.darkMode) BrainwalletTheme.colors.warn else BrainwalletTheme.colors.surface, - painter = painterResource(if (state.darkMode) R.drawable.ic_light_mode else R.drawable.ic_dark_mode), - contentDescription = stringResource(R.string.toggle_dark_mode), - ) - } - } + ) Spacer(modifier = Modifier.weight(0.2f)) @@ -272,20 +248,6 @@ fun WelcomeScreen( } } -@Composable -fun DarkModeToggleButton( - checked: Boolean, - onCheckedChange: (Boolean) -> Unit, - modifier: Modifier = Modifier, - content: @Composable () -> Unit -) { - IconToggleButton( - checked = checked, - onCheckedChange = onCheckedChange, - modifier = modifier, - content = content - ) -} @Preview @Composable diff --git a/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeState.kt b/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeState.kt index 12ac4d0f..415f1333 100644 --- a/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeState.kt +++ b/app/src/main/java/com/brainwallet/ui/screens/welcome/WelcomeState.kt @@ -8,8 +8,9 @@ data class WelcomeState( val selectedLanguage: Language = Language.ENGLISH, val selectedCurrency: CurrencyEntity = CurrencyEntity( "USD", - "USD", - -1f + "US Dollar", + -1f, + "$" ), //-1 = need to fetch val languageSelectorBottomSheetVisible: Boolean = false, val fiatSelectorBottomSheetVisible: Boolean = false, diff --git a/app/src/main/java/com/brainwallet/ui/theme/Theme.kt b/app/src/main/java/com/brainwallet/ui/theme/Theme.kt index 315ab497..819eb43e 100644 --- a/app/src/main/java/com/brainwallet/ui/theme/Theme.kt +++ b/app/src/main/java/com/brainwallet/ui/theme/Theme.kt @@ -1,9 +1,11 @@ package com.brainwallet.ui.theme import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Typography import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable +import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.ComposeView @@ -79,6 +81,9 @@ object BrainwalletTheme { @Composable get() = LocalBrainwalletColors.current + val typography: Typography + @Composable @ReadOnlyComposable get() = MaterialTheme.typography + //todo: add typography, shape? for the design system } diff --git a/app/src/main/java/com/brainwallet/util/EventBus.kt b/app/src/main/java/com/brainwallet/util/EventBus.kt index 8c6ed440..313358db 100644 --- a/app/src/main/java/com/brainwallet/util/EventBus.kt +++ b/app/src/main/java/com/brainwallet/util/EventBus.kt @@ -28,7 +28,7 @@ object EventBus { //provide this for old flow data class LegacyPasscodeVerified( - val passcode: List + val passcode: List, ) : Event() data class LegacyUnLock( diff --git a/app/src/main/res/layout/activity_bread.xml b/app/src/main/res/layout/activity_bread.xml index 5fb9763b..7ad85ca9 100644 --- a/app/src/main/res/layout/activity_bread.xml +++ b/app/src/main/res/layout/activity_bread.xml @@ -1,139 +1,168 @@ - - - + + - - + + + + android:clipToPadding="false" + android:descendantFocusability="beforeDescendants" + android:filterTouchesWhenObscured="true" + android:fitsSystemWindows="true" + android:focusableInTouchMode="true" + tools:context="com.brainwallet.presenter.activities.BreadActivity"> - + android:elevation="8dp" + android:orientation="vertical"> - - - - -