Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
43801ae
Merge pull request #47 from gruntsoftware/release/v4.4.0
kcw-grunt Mar 24, 2025
8bef463
feat: [WIP] implement new sync mechanism
andhikayuana Mar 23, 2025
9ac5b8a
chore: refactor keystore manager provide and inject using koin
andhikayuana Mar 24, 2025
f728a32
feat: implement new sync flow
andhikayuana Mar 24, 2025
3b1b270
chore: update comment for BRWalletManager.generateRandomSeed
andhikayuana Mar 24, 2025
f29867b
Added in Currency code and symbol in the Welcome screen
kcw-grunt Mar 24, 2025
5c248b5
tiny layout changes
kcw-grunt Mar 24, 2025
dcd544c
chore: change sync flow
andhikayuana Mar 24, 2025
b48e043
Merge pull request #48 from gruntsoftware/feat/issue-98
kcw-grunt Mar 24, 2025
767c6fb
Changed to BrainwalletTheme
kcw-grunt Mar 25, 2025
a9c50fe
Checks is Fagement is alive
kcw-grunt Mar 25, 2025
7c81469
Merge pull request #51 from gruntsoftware/fix/crash-on-FragmentSignal
kcw-grunt Mar 25, 2025
ea0a04e
Merge pull request #50 from gruntsoftware/techdebt/add-currency-symbo…
kcw-grunt Mar 25, 2025
0f61748
updated test
kcw-grunt Mar 25, 2025
4e252ac
Updated the APIManager
kcw-grunt Mar 25, 2025
45e822b
Added special header code
kcw-grunt Mar 25, 2025
68d0f36
Merge pull request #52 from gruntsoftware/fix/currency-entity-update-…
kcw-grunt Mar 26, 2025
6edd725
version and code bump
kcw-grunt Mar 26, 2025
53050d8
attempt bug fix of crash
kcw-grunt Mar 27, 2025
56adc5c
code bump
kcw-grunt Mar 28, 2025
2777eee
updated the analytic error
kcw-grunt Mar 29, 2025
fe9dbec
remove data library
kcw-grunt Mar 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,3 @@
[submodule "app/src/main/jni/core"]
path = app/src/main/jni/core
url = https://github.com/brainwallet-co/core.git
[submodule "app/src/main/remote_data"]
path = app/src/main/remote_data
url = https://github.com/brainwallet-co/data.git
7 changes: 5 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ android {
applicationId = "ltd.grunt.brainwallet"
minSdk = 29
targetSdk = 34
versionCode = 202503221
versionName = "v4.4.0"
versionCode = 202503281
versionName = "v4.4.1"

multiDexEnabled = true
base.archivesName.set("${defaultConfig.versionName}(${defaultConfig.versionCode})")
Expand Down Expand Up @@ -188,6 +188,7 @@ dependencies {
}

implementation("androidx.webkit:webkit:1.9.0")
implementation("com.squareup.moshi:moshi-kotlin:1.15.2")
implementation(libs.androidx.core)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.legacy.support)
Expand All @@ -199,12 +200,14 @@ dependencies {
implementation(libs.androidx.preference)
implementation(libs.androidx.lifecycle.runtime)
implementation(libs.bundles.androidx.lifecycle)
implementation(libs.androidx.work)
implementation(libs.androidx.browser)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.bundles.androidx.compose)
implementation(libs.google.material)
implementation(libs.google.zxing)
implementation(platform(libs.firebase.bom))
implementation(platform(libs.firebase.analytics))
implementation(libs.bundles.firebase)
implementation(libs.bundles.google.play.asset.delivery)
implementation(libs.bundles.google.play.feature.delivery)
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <!-- Allows changing locales -->
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />


<meta-data android:name="google_analytics_default_allow_analytics_storage" android:value="true" />
<meta-data android:name="google_analytics_default_allow_ad_storage" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_user_data" android:value="false" />
<meta-data android:name="google_analytics_default_allow_ad_personalization_signals" android:value="false" />

<uses-feature
android:name="android.hardware.location.gps"
android:required="false" />
Expand Down
19 changes: 7 additions & 12 deletions app/src/main/java/com/brainwallet/BrainwalletApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import android.app.Application
import android.content.Context
import android.content.res.Resources
import com.appsflyer.AppsFlyerLib
import com.brainwallet.di.appModule
import com.brainwallet.di.dataModule
import com.brainwallet.di.viewModelModule
import com.brainwallet.notification.setupNotificationChannels
Expand All @@ -15,9 +16,11 @@ import com.brainwallet.tools.listeners.SyncReceiver
import com.brainwallet.tools.manager.AnalyticsManager
import com.brainwallet.tools.util.BRConstants
import com.brainwallet.tools.util.Utils
import com.brainwallet.util.cryptography.KeyStoreKeyGenerator
import com.brainwallet.util.cryptography.KeyStoreManager
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.setConsent
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.google.firebase.ktx.Firebase
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.GlobalContext.startKoin
Expand All @@ -35,10 +38,8 @@ class BrainwalletApp : Application() {

initializeModule()

/** DEV: Top placement requirement. */
/** DEV: Top placement requirement. **/
val enableCrashlytics = !Utils.isEmulatorOrDebug(this)
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(enableCrashlytics)

setupNotificationChannels(this)

AnalyticsManager.init(this)
Expand Down Expand Up @@ -73,12 +74,10 @@ class BrainwalletApp : Application() {
}

protected fun initializeModule() {
keyStoreManager = KeyStoreManager(this, KeyStoreKeyGenerator.Impl())

startKoin {
androidLogger(if (BuildConfig.DEBUG) Level.DEBUG else Level.ERROR)
androidContext(this@BrainwalletApp)
modules(dataModule, viewModelModule)
modules(dataModule, viewModelModule, appModule)
}
}

Expand Down Expand Up @@ -109,10 +108,6 @@ class BrainwalletApp : Application() {
@SuppressLint("StaticFieldLeak")
private var currentActivity: Activity? = null

@SuppressLint("StaticFieldLeak")
@JvmField
var keyStoreManager: KeyStoreManager? = null

@JvmStatic
val breadContext: Context
get() = if (currentActivity == null) SyncReceiver.app else currentActivity!!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
public class CurrencyEntity implements Serializable {

//Change this after modifying the class
private static final long serialVersionUID = 7526472295622776147L;
private static final long serialVersionUID = 7526472295622777000L;

public static final String TAG = CurrencyEntity.class.getName();
public String code;
public String name;
public String name = "";
public float rate;
public String symbol;
public String symbol = "";

public CurrencyEntity(String code, String name, float rate, String symbol) {
this.code = code;
Expand Down
12 changes: 10 additions & 2 deletions app/src/main/java/com/brainwallet/di/Module.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@ import android.content.SharedPreferences
import com.brainwallet.BuildConfig
import com.brainwallet.data.repository.SettingRepository
import com.brainwallet.data.source.RemoteConfigSource
import com.brainwallet.tools.manager.BRApiManager
import com.brainwallet.tools.manager.APIManager
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.ready.ReadyViewModel
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.brainwallet.util.cryptography.KeyStoreKeyGenerator
import com.brainwallet.util.cryptography.KeyStoreManager
import com.google.firebase.ktx.Firebase
import com.google.firebase.remoteconfig.ktx.remoteConfig
import org.koin.android.ext.koin.androidApplication
Expand All @@ -29,7 +32,7 @@ val dataModule = module {
it.initialize()
}
}
single { BRApiManager(get()) }
single { APIManager(get()) }
single { CurrencyDataSource.getInstance(get()) }
single<SharedPreferences> { provideSharedPreferences(context = androidApplication()) }
single<SettingRepository> { SettingRepository.Impl(get(), get()) }
Expand All @@ -38,13 +41,18 @@ val dataModule = module {
val viewModelModule = module {
viewModelOf(::WelcomeViewModel)
viewModelOf(::SettingsViewModel)
viewModel { ReadyViewModel() }
viewModel { InputWordsViewModel() }
viewModel { SetPasscodeViewModel() }
viewModel { UnLockViewModel() }
viewModel { YourSeedProveItViewModel() }
viewModel { YourSeedWordsViewModel() }
}

val appModule = module {
single<KeyStoreManager> { KeyStoreManager(get(), KeyStoreKeyGenerator.Impl()) }
}

private fun provideSharedPreferences(
context: Context,
name: String = "${BuildConfig.APPLICATION_ID}.prefs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
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.APIManager;
import com.brainwallet.tools.manager.InternetManager;
import com.brainwallet.tools.security.AuthManager;
import com.brainwallet.tools.security.BRKeyStore;
Expand Down Expand Up @@ -148,7 +148,7 @@ public static void init(Activity app) {


if (!(app instanceof RecoverActivity || app instanceof WriteDownActivity)) {
BRApiManager apiManager = KoinJavaComponent.get(BRApiManager.class);
APIManager apiManager = KoinJavaComponent.get(APIManager.class);
apiManager.startTimer(app);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ enum class ServiceItems(val key: String) {
WALLETOPS("wallet-ops"),
OPSALL("wallet-ops"),
WALLETSTART("start-date"),
AFDEVID("af-dev-id")
AFDEVID("af-dev-id"),
CLIENTCODE("client-code"),
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
Expand All @@ -17,24 +18,33 @@
import com.brainwallet.R;
import com.brainwallet.presenter.interfaces.BROnSignalCompletion;

import timber.log.Timber;

public class FragmentSignal extends Fragment {
public static final String TITLE = "title";
public static final String ICON_DESCRIPTION = "iconDescription";
public static final String RES_ID = "resId";
public TextView mTitle;
// public TextView mDescription;
public ImageView mIcon;
private BROnSignalCompletion completion;
private LinearLayout signalLayout;

private final Handler handler = new Handler(Looper.getMainLooper());
private final Runnable popBackStackRunnable = new Runnable() {
@Override
public void run() {
if (isAdded()) {
getParentFragmentManager().popBackStack();
handler.postDelayed(completionRunnable, 300);
}
}
};

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, final Bundle savedInstanceState) {
// The last two arguments ensure LayoutParams are inflated
// properly.

View rootView = inflater.inflate(R.layout.fragment_signal, container, false);
mTitle = (TextView) rootView.findViewById(R.id.title);
// mDescription = (TextView) rootView.findViewById(R.id.description);
mIcon = (ImageView) rootView.findViewById(R.id.qr_image);
signalLayout = (LinearLayout) rootView.findViewById(R.id.signal_layout);
signalLayout.setOnClickListener(new View.OnClickListener() {
Expand All @@ -49,7 +59,6 @@ public void onClick(View v) {
if (bundle != null) {
String title = bundle.getString(TITLE, "");
int resId = bundle.getInt(RES_ID, 0);

mTitle.setText(title);
mIcon.setImageResource(resId);
}
Expand All @@ -64,24 +73,25 @@ public void setCompletion(BROnSignalCompletion completion) {
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
handler.postDelayed(popBackStackRunnable, 1000);
}

new Handler().postDelayed(new Runnable() {
@Override
public void run() {

getParentFragmentManager().popBackStack();

new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (completion != null) {
completion.onComplete();
completion = null;
}
}
}, 300);
private final Runnable completionRunnable = new Runnable() {
@Override
public void run() {
if (completion != null) {
completion.onComplete();
completion = null;
}
}, 1500);
}
};

@Override
public void onDestroyView() {
super.onDestroyView();
// Remove callbacks to prevent execution after the fragment is destroyed
handler.removeCallbacks(popBackStackRunnable);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! @kcw-grunt

What is popBackStsckRunnable and completionRunnable?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand it this creates an async process so the fragment can be created

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank for the explanation! @kcw-grunt

handler.removeCallbacks(completionRunnable);
}

@Override
Expand Down
43 changes: 30 additions & 13 deletions app/src/main/java/com/brainwallet/tools/animation/BRAnimator.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;

import com.brainwallet.navigation.LegacyNavigation;
import com.brainwallet.presenter.fragments.FragmentMoonpay;
import com.brainwallet.tools.manager.AnalyticsManager;
import com.brainwallet.tools.threads.BRExecutor;
import com.brainwallet.tools.util.BRConstants;
import com.brainwallet.R;
Expand All @@ -49,31 +51,46 @@
import timber.log.Timber;

public class BRAnimator {
private static FragmentSignal fragmentSignal;
private static boolean clickAllowed = true;
public static int SLIDE_ANIMATION_DURATION = 300;
public static boolean supportIsShowing;

private static boolean shouldShowSettingsComposable = false;
public static void showBreadSignal(@NonNull FragmentActivity activity,
@NonNull String title,
@NonNull String iconDescription,
int drawableId,
@Nullable BROnSignalCompletion completion) {
if (activity.isFinishing() || activity.isDestroyed()) {
return; // Avoid crashes if the activity is not in a valid state
}

public static void showBreadSignal(FragmentActivity activity, String title, String iconDescription, int drawableId, BROnSignalCompletion completion) {
fragmentSignal = new FragmentSignal();
FragmentSignal fragmentSignal = new FragmentSignal();
Bundle bundle = new Bundle();
bundle.putString(FragmentSignal.TITLE, title);
bundle.putString(FragmentSignal.ICON_DESCRIPTION, iconDescription);
fragmentSignal.setCompletion(completion);
bundle.putInt(FragmentSignal.RES_ID, drawableId);
fragmentSignal.setCompletion(completion);
fragmentSignal.setArguments(bundle);
androidx.fragment.app.FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.animator.from_bottom, R.animator.to_bottom, R.animator.from_bottom, R.animator.to_bottom);
transaction.add(android.R.id.content, fragmentSignal, fragmentSignal.getClass().getName());

FragmentManager fragmentManager = activity.getSupportFragmentManager();

if (fragmentManager.isStateSaved()) {
return;
}

androidx.fragment.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.animator.from_bottom, R.animator.to_bottom,
R.animator.from_bottom, R.animator.to_bottom);
transaction.add(android.R.id.content, fragmentSignal, FragmentSignal.class.getName());
transaction.addToBackStack(null);
if (!activity.isDestroyed())

try {
transaction.commit();
} catch (IllegalStateException e) {
transaction.commitAllowingStateLoss();
AnalyticsManager.logCustomEvent(BRConstants._20200112_ERR);
}
}


public static void showBalanceSeedFragment(@NonNull FragmentActivity app) {
public static void showBalanceSeedFragment(@NonNull FragmentActivity app) {
Timber.d("timber: fetched info");

androidx.fragment.app.FragmentManager fragmentManager = app.getSupportFragmentManager();
Expand Down
Loading