Move receive/send to new bottom sheet dialogs, change theme stuff.

NOTE: This commit still logs seed phrases for development purposes
This commit is contained in:
pokkst 2022-09-07 16:36:18 -05:00
parent 832379aa94
commit ce5985bb47
No known key found for this signature in database
GPG key ID: 90C2ED85E67A50FF
17 changed files with 224 additions and 198 deletions

View file

@ -34,7 +34,7 @@
android:label="@string/app_name" android:label="@string/app_name"
android:preserveLegacyExternalStorage="true" android:preserveLegacyExternalStorage="true"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/MyMaterialThemeClassic" android:theme="@style/MyMaterialThemeOled"
android:usesCleartextTraffic="true"> android:usesCleartextTraffic="true">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"

View file

@ -0,0 +1,73 @@
package com.m2049r.xmrwallet.fragment.dialog;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.service.AddressService;
import java.util.HashMap;
import java.util.Map;
import timber.log.Timber;
public class ReceiveBottomSheetDialog extends BottomSheetDialogFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.receive_bottom_sheet_dialog, null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ImageView addressImageView = view.findViewById(R.id.monero_qr_imageview);
TextView addressTextView = view.findViewById(R.id.address_textview);
AddressService.getInstance().address.observe(getViewLifecycleOwner(), addr -> {
if (!addr.isEmpty()) {
addressTextView.setText(addr);
addressImageView.setImageBitmap(generate(addr, 256, 256));
}
});
}
public Bitmap generate(String text, int width, int height) {
if ((width <= 0) || (height <= 0)) return null;
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
try {
BitMatrix bitMatrix = new QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
int[] pixels = new int[width * height];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (bitMatrix.get(j, i)) {
pixels[i * width + j] = 0x00000000;
} else {
pixels[i * height + j] = 0xffffffff;
}
}
}
return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
} catch (WriterException ex) {
Timber.e(ex);
}
return null;
}
}

View file

@ -0,0 +1,51 @@
package com.m2049r.xmrwallet.fragment.dialog;
import android.os.Bundle;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.service.TxService;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class SendBottomSheetDialog extends BottomSheetDialogFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.send_bottom_sheet_dialog, null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
EditText addressEditText = view.findViewById(R.id.address_edittext);
EditText amountEditText = view.findViewById(R.id.amount_edittext);
Button sendButton = view.findViewById(R.id.send_button);
TxService.getInstance().clearSendEvent.observe(getViewLifecycleOwner(), o -> {
dismiss();
});
sendButton.setOnClickListener(view1 -> {
String address = addressEditText.getText().toString().trim();
String amount = amountEditText.getText().toString().trim();
boolean validAddress = Wallet.isAddressValid(address);
if (validAddress && !amount.isEmpty()) {
sendButton.setEnabled(false);
TxService.getInstance().sendTx(address, amount);
} else if (!validAddress) {
Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show();
} else if (amount.isEmpty()) {
Toast.makeText(getActivity(), getString(R.string.send_amount_empty), Toast.LENGTH_SHORT).show();
}
});
}
}

View file

@ -7,6 +7,7 @@ import android.view.ViewGroup;
import android.widget.Button; import android.widget.Button;
import android.widget.EditText; import android.widget.EditText;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
@ -18,8 +19,11 @@ import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment; import androidx.navigation.fragment.NavHostFragment;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.m2049r.xmrwallet.MainActivity; import com.m2049r.xmrwallet.MainActivity;
import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.R;
import com.m2049r.xmrwallet.fragment.dialog.ReceiveBottomSheetDialog;
import com.m2049r.xmrwallet.fragment.dialog.SendBottomSheetDialog;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.service.AddressService; import com.m2049r.xmrwallet.service.AddressService;
import com.m2049r.xmrwallet.service.BalanceService; import com.m2049r.xmrwallet.service.BalanceService;
@ -41,46 +45,26 @@ public class HomeFragment extends Fragment {
mViewModel = new ViewModelProvider(this).get(HomeViewModel.class); mViewModel = new ViewModelProvider(this).get(HomeViewModel.class);
ImageView settingsImageView = view.findViewById(R.id.settings_imageview); ImageView settingsImageView = view.findViewById(R.id.settings_imageview);
ImageView addressImageView = view.findViewById(R.id.monero_qr_imageview);
TextView addressTextView = view.findViewById(R.id.address_textview);
TextView balanceTextView = view.findViewById(R.id.balance_textview); TextView balanceTextView = view.findViewById(R.id.balance_textview);
EditText addressEditText = view.findViewById(R.id.address_edittext);
EditText amountEditText = view.findViewById(R.id.amount_edittext);
Button sendButton = view.findViewById(R.id.send_button); Button sendButton = view.findViewById(R.id.send_button);
Button receiveButton = view.findViewById(R.id.receive_button);
AddressService.getInstance().address.observe(getViewLifecycleOwner(), addr -> {
if (!addr.isEmpty()) {
addressTextView.setText(addr);
addressImageView.setImageBitmap(mViewModel.generate(addr, 256, 256));
}
});
BalanceService.getInstance().balance.observe(getViewLifecycleOwner(), balance -> { BalanceService.getInstance().balance.observe(getViewLifecycleOwner(), balance -> {
balanceTextView.setText(getString(R.string.wallet_balance_text, Wallet.getDisplayAmount(balance))); balanceTextView.setText(getString(R.string.wallet_balance_text, Wallet.getDisplayAmount(balance)));
}); });
TxService.getInstance().clearSendEvent.observe(getViewLifecycleOwner(), o -> {
addressEditText.setText(null);
amountEditText.setText(null);
sendButton.setEnabled(true);
});
settingsImageView.setOnClickListener(view12 -> { settingsImageView.setOnClickListener(view12 -> {
navigate(R.id.settings_fragment); navigate(R.id.settings_fragment);
}); });
sendButton.setOnClickListener(view1 -> { sendButton.setOnClickListener(view1 -> {
String address = addressEditText.getText().toString().trim(); SendBottomSheetDialog sendDialog = new SendBottomSheetDialog();
String amount = amountEditText.getText().toString().trim(); sendDialog.show(getActivity().getSupportFragmentManager(), null);
boolean validAddress = Wallet.isAddressValid(address); });
if (validAddress && !amount.isEmpty()) {
sendButton.setEnabled(false); receiveButton.setOnClickListener(view1 -> {
TxService.getInstance().sendTx(address, amount); ReceiveBottomSheetDialog receiveDialog = new ReceiveBottomSheetDialog();
} else if (!validAddress) { receiveDialog.show(getActivity().getSupportFragmentManager(), null);
Toast.makeText(getActivity(), getString(R.string.send_address_invalid), Toast.LENGTH_SHORT).show();
} else if (amount.isEmpty()) {
Toast.makeText(getActivity(), getString(R.string.send_amount_empty), Toast.LENGTH_SHORT).show();
}
}); });
} }

View file

@ -17,27 +17,5 @@ import java.util.Map;
import timber.log.Timber; import timber.log.Timber;
public class HomeViewModel extends ViewModel { public class HomeViewModel extends ViewModel {
public Bitmap generate(String text, int width, int height) {
if ((width <= 0) || (height <= 0)) return null;
Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
try {
BitMatrix bitMatrix = new QRCodeWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
int[] pixels = new int[width * height];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (bitMatrix.get(j, i)) {
pixels[i * width + j] = 0x00000000;
} else {
pixels[i * height + j] = 0xffffffff;
}
}
}
return Bitmap.createBitmap(pixels, 0, width, width, height, Bitmap.Config.RGB_565);
} catch (WriterException ex) {
Timber.e(ex);
}
return null;
}
} }

View file

@ -46,14 +46,7 @@ public class ThemeHelper {
} }
public static void setTheme(@NonNull Activity activity, @NonNull String theme) { public static void setTheme(@NonNull Activity activity, @NonNull String theme) {
switch (theme) {
case "Classic":
activity.setTheme(R.style.MyMaterialThemeClassic);
break;
case "Oled":
activity.setTheme(R.style.MyMaterialThemeOled); activity.setTheme(R.style.MyMaterialThemeOled);
break;
}
} }
public static void setPreferred(Activity activity) { public static void setPreferred(Activity activity) {

View file

@ -16,76 +16,40 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent"/>
<ImageView
android:id="@+id/monero_qr_imageview"
android:layout_width="256dp"
android:layout_height="256dp"
android:layout_marginTop="16dp"
android:src="@drawable/ic_fingerprint"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<ImageView
android:id="@+id/monero_logo_imageview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_monero_qr"
app:layout_constraintBottom_toBottomOf="@id/monero_qr_imageview"
app:layout_constraintEnd_toEndOf="@id/monero_qr_imageview"
app:layout_constraintTop_toTopOf="@id/monero_qr_imageview"
app:layout_constraintStart_toStartOf="@id/monero_qr_imageview"/>
<TextView
android:id="@+id/address_textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:textAlignment="center"
tools:text="ADDRESS"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/monero_qr_imageview" />
<TextView <TextView
android:id="@+id/balance_textview" android:id="@+id/balance_textview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="24dp" android:layout_marginStart="24dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="24dp"
android:layout_marginTop="8dp"
android:textAlignment="center" android:textAlignment="center"
tools:text="BALANCE" tools:text="BALANCE"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/address_textview" /> app:layout_constraintTop_toTopOf="@id/settings_imageview"
app:layout_constraintBottom_toBottomOf="@id/settings_imageview"/>
<EditText <Button
android:id="@+id/address_edittext" android:id="@+id/receive_button"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="24dp" android:layout_marginStart="24dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="24dp"
android:hint="Address" android:layout_marginBottom="16dp"
app:layout_constraintBottom_toTopOf="@id/amount_edittext"/> android:text="Receive"
<EditText app:layout_constraintStart_toStartOf="parent"
android:id="@+id/amount_edittext" app:layout_constraintEnd_toStartOf="@id/send_button"
android:layout_width="match_parent" app:layout_constraintBottom_toBottomOf="parent"/>
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:hint="Amount"
android:inputType="numberDecimal"
app:layout_constraintBottom_toTopOf="@id/send_button"/>
<Button <Button
android:id="@+id/send_button" android:id="@+id/send_button"
android:layout_width="match_parent" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="24dp" android:layout_marginStart="24dp"
android:layout_marginEnd="24dp" android:layout_marginEnd="24dp"
android:layout_marginBottom="16dp" android:layout_marginBottom="16dp"
android:text="Send" android:text="Send"
app:layout_constraintStart_toEndOf="@id/receive_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/> app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:fitsSystemWindows="true"
android:padding="16dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/address_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:hint="Address"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/amount_edittext"/>
<EditText
android:id="@+id/amount_edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:hint="Amount"
android:inputType="numberDecimal"
app:layout_constraintBottom_toTopOf="@id/send_button"/>
<Button
android:id="@+id/send_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:text="Send"
app:layout_constraintTop_toBottomOf="@id/amount_edittext"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View file

@ -1,3 +0,0 @@
<resources>
<dimen name="fab_margin">48dp</dimen>
</resources>

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyMaterialTheme" parent="Theme.MaterialComponents.DayNight">
<item name="android:windowLightStatusBar">false</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="materialCardViewStyle">@style/AppCard</item>
<item name="materialButtonStyle">@style/AppButton</item>
</style>
</resources>

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyMaterialTheme" parent="Theme.MaterialComponents.DayNight">
<item name="android:windowLightStatusBar">false</item>
<item name="android:windowLightNavigationBar">false</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="materialCardViewStyle">@style/AppCard</item>
<item name="materialButtonStyle">@style/AppButton</item>
</style>
</resources>

View file

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyMaterialTheme" parent="Theme.MaterialComponents.DayNight">
<item name="android:windowLightStatusBar">true</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="materialCardViewStyle">@style/AppCard</item>
<item name="materialButtonStyle">@style/AppButton</item>
</style>
</resources>

View file

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MyMaterialTheme" parent="Theme.MaterialComponents.DayNight">
<item name="android:windowLightStatusBar">true</item>
<item name="android:windowLightNavigationBar">true</item>
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="materialCardViewStyle">@style/AppCard</item>
<item name="materialButtonStyle">@style/AppButton</item>
</style>
</resources>

View file

@ -1,3 +0,0 @@
<resources>
<dimen name="fab_margin">200dp</dimen>
</resources>

View file

@ -1,3 +0,0 @@
<resources>
<dimen name="fab_margin">48dp</dimen>
</resources>

View file

@ -36,36 +36,32 @@
<item name="android:navigationBarColor">@color/oled_navigationBarColor</item> <item name="android:navigationBarColor">@color/oled_navigationBarColor</item>
<item name="android:textColorPrimary">@color/oled_textColorPrimary</item> <item name="android:textColorPrimary">@color/oled_textColorPrimary</item>
<item name="android:textColorSecondary">@color/oled_textColorSecondary</item> <item name="android:textColorSecondary">@color/oled_textColorSecondary</item>
<item name="bottomSheetDialogTheme">@style/BottomSheetDialog_Rounded</item>
</style> </style>
<style name="MyMaterialThemeClassic" parent="MyMaterialTheme"> <!-- BottomSheet Dialog-->
<item name="toolbarTextColor">@color/classic_toolbarTextColor</item> <style name="BottomSheetDialog_Rounded" parent="MyMaterialThemeOled">
<item name="gradientTopColor">@color/classic_gradientTopColor</item> <item name="android:windowBackground">@android:color/transparent</item>
<item name="gradientBottomColor">@color/classic_gradientBottomColor</item> <item name="android:windowIsFloating">false</item>
<item name="favouriteColor">@color/classic_favouriteColor</item> <item name="android:windowAnimationStyle">@style/Animation.MaterialComponents.BottomSheetDialog</item>
<item name="softFavouriteColor">@color/classic_softFavouriteColor</item> <item name="enableEdgeToEdge">true</item>
<item name="positiveColor">@color/classic_positiveColor</item> <item name="paddingBottomSystemWindowInsets">true</item>
<item name="negativeColor">@color/classic_negativeColor</item> <item name="paddingLeftSystemWindowInsets">true</item>
<item name="neutralColor">@color/classic_neutralColor</item> <item name="paddingRightSystemWindowInsets">true</item>
<item name="streetColorA">@color/classic_streetColorA</item> <item name="paddingTopSystemWindowInsets">true</item>
<item name="streetColorB">@color/classic_streetColorB</item> <item name="bottomSheetStyle">@style/BottomSheet_Rounded</item>
<item name="noticeColor">@color/classic_noticeColor</item> </style>
<item name="colorPrimary">@color/classic_colorPrimary</item>
<item name="colorPrimaryVariant">@color/classic_colorPrimaryVariant</item> <style name="BottomSheet_Rounded" parent="Widget.MaterialComponents.BottomSheet">
<item name="colorOnPrimary">@color/classic_colorOnPrimary</item> <item name="shapeAppearanceOverlay">@style/ShapeAppearanceBottomSheetDialog_Rounded</item>
<item name="colorSecondary">@color/classic_colorSecondary</item> </style>
<item name="colorSecondaryVariant">@color/classic_colorSecondaryVariant</item>
<item name="colorOnSecondary">@color/classic_colorOnSecondary</item> <style name="ShapeAppearanceBottomSheetDialog_Rounded" parent="">
<item name="colorError">@color/classic_colorError</item> <item name="cornerFamily">rounded</item>
<item name="colorOnError">@color/classic_colorOnError</item> <item name="cornerSizeTopRight">16dp</item>
<item name="colorSurface">@color/classic_colorSurface</item> <item name="cornerSizeTopLeft">16dp</item>
<item name="colorOnSurface">@color/classic_colorOnSurface</item> <item name="cornerSizeBottomRight">0dp</item>
<item name="android:colorBackground">@color/classic_colorBackground</item> <item name="cornerSizeBottomLeft">0dp</item>
<item name="colorOnBackground">@color/classic_colorOnBackground</item>
<item name="android:statusBarColor">@color/classic_statusBarColor</item>
<item name="android:navigationBarColor">@color/classic_navigationBarColor</item>
<item name="android:textColorSecondary">@color/classic_textColorSecondary</item>
<item name="android:textColorPrimary">@color/classic_textColorPrimary</item>
</style> </style>
<style name="MonerujoToolbar" parent="Widget.MaterialComponents.Toolbar"> <style name="MonerujoToolbar" parent="Widget.MaterialComponents.Toolbar">

View file

@ -1,10 +1,5 @@
<resources> <resources>
<style name="MyMaterialThemeClassic.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="MyMaterialThemeClassic.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" /> <style name="MyMaterialThemeClassic.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="MyMaterialThemeClassic.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" /> <style name="MyMaterialThemeClassic.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />