Merge pull request #730 from m2049r/feature_sr_transitions_s

Send & Receive UI transitions
This commit is contained in:
m2049r 2021-03-14 21:24:18 +01:00 committed by GitHub
commit a6372f701d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 246 additions and 307 deletions

View File

@ -16,6 +16,7 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -43,6 +44,7 @@ import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.widget.ShareActionProvider; import androidx.appcompat.widget.ShareActionProvider;
import androidx.core.content.FileProvider; import androidx.core.content.FileProvider;
@ -50,13 +52,13 @@ import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import com.google.android.material.textfield.TextInputLayout; import com.google.android.material.textfield.TextInputLayout;
import com.google.android.material.transition.MaterialContainerTransform;
import com.google.zxing.BarcodeFormat; import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType; import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException; import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix; import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter; import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.m2049r.xmrwallet.BuildConfig;
import com.m2049r.xmrwallet.data.BarcodeData; import com.m2049r.xmrwallet.data.BarcodeData;
import com.m2049r.xmrwallet.data.Crypto; import com.m2049r.xmrwallet.data.Crypto;
import com.m2049r.xmrwallet.ledger.LedgerProgressDialog; import com.m2049r.xmrwallet.ledger.LedgerProgressDialog;
@ -64,6 +66,7 @@ import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor; import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.widget.ExchangeView; import com.m2049r.xmrwallet.widget.ExchangeView;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
@ -72,6 +75,7 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import timber.log.Timber; import timber.log.Timber;
@ -84,7 +88,6 @@ public class ReceiveFragment extends Fragment {
private ExchangeView evAmount; private ExchangeView evAmount;
private TextView tvQrCode; private TextView tvQrCode;
private ImageView ivQrCode; private ImageView ivQrCode;
private View cvQrCode;
private ImageView ivQrCodeFull; private ImageView ivQrCodeFull;
private EditText etDummy; private EditText etDummy;
private ImageButton bCopyAddress; private ImageButton bCopyAddress;
@ -112,7 +115,6 @@ public class ReceiveFragment extends Fragment {
tvAddress = view.findViewById(R.id.tvAddress); tvAddress = view.findViewById(R.id.tvAddress);
etNotes = view.findViewById(R.id.etNotes); etNotes = view.findViewById(R.id.etNotes);
evAmount = view.findViewById(R.id.evAmount); evAmount = view.findViewById(R.id.evAmount);
cvQrCode = view.findViewById(R.id.cvQrCode);
ivQrCode = view.findViewById(R.id.qrCode); ivQrCode = view.findViewById(R.id.qrCode);
tvQrCode = view.findViewById(R.id.tvQrCode); tvQrCode = view.findViewById(R.id.tvQrCode);
ivQrCodeFull = view.findViewById(R.id.qrCodeFull); ivQrCodeFull = view.findViewById(R.id.qrCodeFull);
@ -126,40 +128,31 @@ public class ReceiveFragment extends Fragment {
enableCopyAddress(false); enableCopyAddress(false);
enableSubaddressButton(false); enableSubaddressButton(false);
evAmount.setOnNewAmountListener(new ExchangeView.OnNewAmountListener() { evAmount.setOnNewAmountListener(xmr -> {
@Override Timber.d("new amount = %s", xmr);
public void onNewAmount(String xmr) { generateQr();
Timber.d("new amount = %s", xmr);
generateQr();
}
}); });
evAmount.setOnFailedExchangeListener(new ExchangeView.OnFailedExchangeListener() { evAmount.setOnFailedExchangeListener(() -> {
@Override if (isAdded()) {
public void onFailedExchange() { clearQR();
if (isAdded()) { Toast.makeText(getActivity(), getString(R.string.message_exchange_failed), Toast.LENGTH_LONG).show();
clearQR();
Toast.makeText(getActivity(), getString(R.string.message_exchange_failed), Toast.LENGTH_LONG).show();
}
} }
}); });
final EditText notesEdit = etNotes.getEditText(); final EditText notesEdit = etNotes.getEditText();
notesEdit.setRawInputType(InputType.TYPE_CLASS_TEXT); notesEdit.setRawInputType(InputType.TYPE_CLASS_TEXT);
notesEdit.setOnEditorActionListener(new TextView.OnEditorActionListener() { notesEdit.setOnEditorActionListener((v, actionId, event) -> {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
|| (actionId == EditorInfo.IME_ACTION_DONE)) { generateQr();
generateQr(); return true;
return true;
}
return false;
} }
return false;
}); });
notesEdit.addTextChangedListener(new TextWatcher() { notesEdit.addTextChangedListener(new TextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void beforeTextChanged(CharSequence s, int start, int count, int after) {
} }
@Override @Override
@ -169,47 +162,33 @@ public class ReceiveFragment extends Fragment {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
} }
}); });
bSubaddress.setOnClickListener(new View.OnClickListener() { bSubaddress.setOnClickListener(v -> {
@Override enableSubaddressButton(false);
public void onClick(View v) { enableCopyAddress(false);
enableSubaddressButton(false);
enableCopyAddress(false);
final Runnable newAddress = new Runnable() { final Runnable newAddress = this::getNewSubaddress;
public void run() {
getNewSubaddress();
}
};
tvAddress.animate().alpha(0).setDuration(250) tvAddress.animate().alpha(0).setDuration(250)
.withEndAction(newAddress).start(); .withEndAction(newAddress).start();
});
view.findViewById(R.id.cvQrCode).setOnClickListener(v -> {
Helper.hideKeyboard(getActivity());
etDummy.requestFocus();
if (qrValid) {
ivQrCodeFull.setImageBitmap(((BitmapDrawable) ivQrCode.getDrawable()).getBitmap());
ivQrCodeFull.setVisibility(View.VISIBLE);
} else {
evAmount.doExchange();
} }
}); });
cvQrCode.setOnClickListener(new View.OnClickListener() { ivQrCodeFull.setOnClickListener(v -> {
@Override ivQrCodeFull.setImageBitmap(null);
public void onClick(View v) { ivQrCodeFull.setVisibility(View.GONE);
Helper.hideKeyboard(getActivity());
etDummy.requestFocus();
if (qrValid) {
ivQrCodeFull.setImageBitmap(((BitmapDrawable) ivQrCode.getDrawable()).getBitmap());
ivQrCodeFull.setVisibility(View.VISIBLE);
} else {
evAmount.doExchange();
}
}
});
ivQrCodeFull.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ivQrCodeFull.setImageBitmap(null);
ivQrCodeFull.setVisibility(View.GONE);
}
}); });
showProgress(); showProgress();
@ -244,12 +223,17 @@ public class ReceiveFragment extends Fragment {
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setHasOptionsMenu(true); setHasOptionsMenu(true);
final MaterialContainerTransform transform = new MaterialContainerTransform();
transform.setDrawingViewId(R.id.fragment_container);
transform.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
transform.setAllContainerColors(ThemeHelper.getThemedColor(Objects.requireNonNull(getContext()), R.attr.colorSurface));
setSharedElementEnterTransition(transform);
} }
private ShareActionProvider shareActionProvider; private ShareActionProvider shareActionProvider;
@Override @Override
public void onCreateOptionsMenu(Menu menu, final MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, final MenuInflater inflater) {
inflater.inflate(R.menu.receive_menu, menu); inflater.inflate(R.menu.receive_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
@ -320,7 +304,7 @@ public class ReceiveFragment extends Fragment {
} }
void copyAddress() { void copyAddress() {
Helper.clipBoardCopy(getActivity(), getString(R.string.label_copy_address), tvAddress.getText().toString()); Helper.clipBoardCopy(Objects.requireNonNull(getActivity()), getString(R.string.label_copy_address), tvAddress.getText().toString());
Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show(); Toast.makeText(getActivity(), getString(R.string.message_copy_address), Toast.LENGTH_SHORT).show();
} }
@ -381,6 +365,7 @@ public class ReceiveFragment extends Fragment {
GenerateReviewFragment.ProgressListener progressCallback = null; GenerateReviewFragment.ProgressListener progressCallback = null;
@SuppressLint("StaticFieldLeak")
private class AsyncShow extends AsyncTask<Void, Void, Boolean> { private class AsyncShow extends AsyncTask<Void, Void, Boolean> {
final private String walletPath; final private String walletPath;
final private String password; final private String password;
@ -434,8 +419,8 @@ public class ReceiveFragment extends Fragment {
new AsyncStore().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR); new AsyncStore().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR);
} }
@SuppressLint("StaticFieldLeak")
private class AsyncStore extends AsyncTask<String, Void, Boolean> { private class AsyncStore extends AsyncTask<String, Void, Boolean> {
@Override @Override
protected Boolean doInBackground(String... params) { protected Boolean doInBackground(String... params) {
if (params.length != 0) return false; if (params.length != 0) return false;
@ -520,12 +505,12 @@ public class ReceiveFragment extends Fragment {
canvas.save(); canvas.save();
// figure out how to scale the logo // figure out how to scale the logo
float scaleSize = 1.0f; float scaleSize = 1.0f;
while ((logoWidth / scaleSize) > (qrWidth / 5) || (logoHeight / scaleSize) > (qrHeight / 5)) { while ((logoWidth / scaleSize) > (qrWidth / 5.) || (logoHeight / scaleSize) > (qrHeight / 5.)) {
scaleSize *= 2; scaleSize *= 2;
} }
float sx = 1.0f / scaleSize; float sx = 1.0f / scaleSize;
canvas.scale(sx, sx, qrWidth / 2, qrHeight / 2); canvas.scale(sx, sx, qrWidth / 2f, qrHeight / 2f);
canvas.drawBitmap(logo, (qrWidth - logoWidth) / 2, (qrHeight - logoHeight) / 2, null); canvas.drawBitmap(logo, (qrWidth - logoWidth) / 2f, (qrHeight - logoHeight) / 2f, null);
canvas.restore(); canvas.restore();
return logoBitmap; return logoBitmap;
} }
@ -550,7 +535,7 @@ public class ReceiveFragment extends Fragment {
Listener listenerCallback = null; Listener listenerCallback = null;
@Override @Override
public void onAttach(Context context) { public void onAttach(@NonNull Context context) {
super.onAttach(context); super.onAttach(context);
if (context instanceof Listener) { if (context instanceof Listener) {
this.listenerCallback = (Listener) context; this.listenerCallback = (Listener) context;
@ -585,6 +570,7 @@ public class ReceiveFragment extends Fragment {
new AsyncSubaddress().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR); new AsyncSubaddress().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR);
} }
@SuppressLint("StaticFieldLeak")
private class AsyncSubaddress extends AsyncTask<Void, Void, Boolean> { private class AsyncSubaddress extends AsyncTask<Void, Void, Boolean> {
private String newSubaddress; private String newSubaddress;
@ -619,11 +605,7 @@ public class ReceiveFragment extends Fragment {
wallet.getNumSubaddresses() - 1)); wallet.getNumSubaddresses() - 1));
generateQr(); generateQr();
enableCopyAddress(true); enableCopyAddress(true);
final Runnable resetSize = new Runnable() { final Runnable resetSize = () -> tvAddress.animate().setDuration(125).scaleX(1).scaleY(1).start();
public void run() {
tvAddress.animate().setDuration(125).scaleX(1).scaleY(1).start();
}
};
tvAddress.animate().alpha(1).setDuration(125) tvAddress.animate().alpha(1).setDuration(125)
.scaleX(1.2f).scaleY(1.2f) .scaleX(1.2f).scaleY(1.2f)
.withEndAction(resetSize).start(); .withEndAction(resetSize).start();

View File

@ -16,6 +16,7 @@
package com.m2049r.xmrwallet; package com.m2049r.xmrwallet;
import android.annotation.SuppressLint;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
@ -43,7 +44,6 @@ import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout; import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
@ -60,9 +60,9 @@ import com.m2049r.xmrwallet.model.TransactionInfo;
import com.m2049r.xmrwallet.model.Wallet; import com.m2049r.xmrwallet.model.Wallet;
import com.m2049r.xmrwallet.model.WalletManager; import com.m2049r.xmrwallet.model.WalletManager;
import com.m2049r.xmrwallet.service.WalletService; import com.m2049r.xmrwallet.service.WalletService;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor; import com.m2049r.xmrwallet.util.MoneroThreadPoolExecutor;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
import java.util.ArrayList; import java.util.ArrayList;
@ -206,7 +206,6 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
connectWalletService(walletId, password); connectWalletService(walletId, password);
} else { } else {
finish(); finish();
//throw new IllegalStateException("No extras passed! Panic!");
} }
} }
@ -271,47 +270,36 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) { final int itemId = item.getItemId();
case R.id.action_rescan: if (itemId == R.id.action_rescan) {
onWalletRescan(); onWalletRescan();
return true; } else if (itemId == R.id.action_info) {
case R.id.action_info: onWalletDetails();
onWalletDetails(); } else if (itemId == R.id.action_credits) {
return true; CreditsFragment.display(getSupportFragmentManager());
case R.id.action_credits: } else if (itemId == R.id.action_share) {
CreditsFragment.display(getSupportFragmentManager()); onShareTxInfo();
return true; } else if (itemId == R.id.action_help_tx_info) {
case R.id.action_share: HelpFragment.display(getSupportFragmentManager(), R.string.help_tx_details);
onShareTxInfo(); } else if (itemId == R.id.action_help_wallet) {
return true; HelpFragment.display(getSupportFragmentManager(), R.string.help_wallet);
case R.id.action_help_tx_info: } else if (itemId == R.id.action_details_help) {
HelpFragment.display(getSupportFragmentManager(), R.string.help_tx_details); HelpFragment.display(getSupportFragmentManager(), R.string.help_details);
return true; } else if (itemId == R.id.action_details_changepw) {
case R.id.action_help_wallet: onWalletChangePassword();
HelpFragment.display(getSupportFragmentManager(), R.string.help_wallet); } else if (itemId == R.id.action_help_send) {
return true; HelpFragment.display(getSupportFragmentManager(), R.string.help_send);
case R.id.action_details_help: } else if (itemId == R.id.action_rename) {
HelpFragment.display(getSupportFragmentManager(), R.string.help_details); onAccountRename();
return true; } else if (itemId == R.id.action_streetmode) {
case R.id.action_details_changepw: if (isStreetMode()) { // disable streetmode
onWalletChangePassword(); onDisableStreetMode();
return true; } else {
case R.id.action_help_send: onEnableStreetMode();
HelpFragment.display(getSupportFragmentManager(), R.string.help_send); }
return true; } else
case R.id.action_rename: return super.onOptionsItemSelected(item);
onAccountRename(); return true;
return true;
case R.id.action_streetmode:
if (isStreetMode()) { // disable streetmode
onDisableStreetMode();
} else {
onEnableStreetMode();
}
return true;
default:
return super.onOptionsItemSelected(item);
}
} }
private void updateStreetMode() { private void updateStreetMode() {
@ -327,12 +315,9 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
Helper.promptPassword(WalletActivity.this, getWallet().getName(), false, new Helper.PasswordAction() { Helper.promptPassword(WalletActivity.this, getWallet().getName(), false, new Helper.PasswordAction() {
@Override @Override
public void act(String walletName, String password, boolean fingerprintUsed) { public void act(String walletName, String password, boolean fingerprintUsed) {
runOnUiThread(new Runnable() { runOnUiThread(() -> {
@Override enableStreetMode(false);
public void run() { updateStreetMode();
enableStreetMode(false);
updateStreetMode();
}
}); });
} }
@ -423,10 +408,8 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
case NetworkType_Mainnet: case NetworkType_Mainnet:
toolbar.setBackgroundResource(R.drawable.backgound_toolbar_mainnet); toolbar.setBackgroundResource(R.drawable.backgound_toolbar_mainnet);
break; break;
case NetworkType_Testnet:
toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, R.attr.colorPrimaryDark));
break;
case NetworkType_Stagenet: case NetworkType_Stagenet:
case NetworkType_Testnet:
toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, R.attr.colorPrimaryDark)); toolbar.setBackgroundResource(ThemeHelper.getThemedResourceId(this, R.attr.colorPrimaryDark));
break; break;
default: default:
@ -443,7 +426,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
private WalletService mBoundService = null; private WalletService mBoundService = null;
private boolean mIsBound = false; private boolean mIsBound = false;
private ServiceConnection mConnection = new ServiceConnection() { private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) { public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been // This is called when the connection with the service has been
// established, giving us the service object we can use to // established, giving us the service object we can use to
@ -542,8 +525,8 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
} }
@Override @Override
public void onSendRequest() { public void onSendRequest(View view) {
replaceFragment(SendFragment.newInstance(uri), null, null); replaceFragmentWithTransition(view, SendFragment.newInstance(uri), null, null);
uri = null; // only use uri once uri = null; // only use uri once
} }
@ -591,18 +574,10 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
onProgress(-1); onProgress(-1);
saveWallet(); // save on first sync saveWallet(); // save on first sync
synced = true; synced = true;
runOnUiThread(new Runnable() { runOnUiThread(walletFragment::onSynced);
public void run() {
walletFragment.onSynced();
}
});
} }
} }
runOnUiThread(new Runnable() { runOnUiThread(() -> walletFragment.onRefreshed(wallet, full));
public void run() {
walletFragment.onRefreshed(wallet, full);
}
});
return true; return true;
} catch (ClassCastException ex) { } catch (ClassCastException ex) {
// not in wallet fragment (probably send monero) // not in wallet fragment (probably send monero)
@ -614,13 +589,11 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override @Override
public void onWalletStored(final boolean success) { public void onWalletStored(final boolean success) {
runOnUiThread(new Runnable() { runOnUiThread(() -> {
public void run() { if (success) {
if (success) { Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_unloaded), Toast.LENGTH_SHORT).show();
Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_unloaded), Toast.LENGTH_SHORT).show(); } else {
} else { Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_unload_failed), Toast.LENGTH_LONG).show();
Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_unload_failed), Toast.LENGTH_LONG).show();
}
} }
}); });
} }
@ -629,30 +602,23 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override @Override
public void onWalletOpen(final Wallet.Device device) { public void onWalletOpen(final Wallet.Device device) {
switch (device) { if (device == Wallet.Device.Device_Ledger) {
case Device_Ledger: runOnUiThread(() -> showLedgerProgressDialog(LedgerProgressDialog.TYPE_RESTORE));
runOnUiThread(new Runnable() {
public void run() {
showLedgerProgressDialog(LedgerProgressDialog.TYPE_RESTORE);
}
});
} }
} }
@Override @Override
public void onWalletStarted(final Wallet.Status walletStatus) { public void onWalletStarted(final Wallet.Status walletStatus) {
runOnUiThread(new Runnable() { runOnUiThread(() -> {
public void run() { dismissProgressDialog();
dismissProgressDialog(); if (walletStatus == null) {
if (walletStatus == null) { // guess what went wrong
// guess what went wrong Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_connect_failed), Toast.LENGTH_LONG).show();
Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_connect_failed), Toast.LENGTH_LONG).show(); } else {
} else { if (Wallet.ConnectionStatus.ConnectionStatus_WrongVersion == walletStatus.getConnectionStatus())
if (Wallet.ConnectionStatus.ConnectionStatus_WrongVersion == walletStatus.getConnectionStatus()) Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_connect_wrongversion), Toast.LENGTH_LONG).show();
Toast.makeText(WalletActivity.this, getString(R.string.status_wallet_connect_wrongversion), Toast.LENGTH_LONG).show(); else if (!walletStatus.isOk())
else if (!walletStatus.isOk()) Toast.makeText(WalletActivity.this, walletStatus.getErrorString(), Toast.LENGTH_LONG).show();
Toast.makeText(WalletActivity.this, walletStatus.getErrorString(), Toast.LENGTH_LONG).show();
}
} }
}); });
if ((walletStatus == null) || (Wallet.ConnectionStatus.ConnectionStatus_Connected != walletStatus.getConnectionStatus())) { if ((walletStatus == null) || (Wallet.ConnectionStatus.ConnectionStatus_Connected != walletStatus.getConnectionStatus())) {
@ -665,12 +631,10 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
final WalletFragment walletFragment = (WalletFragment) final WalletFragment walletFragment = (WalletFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
runOnUiThread(new Runnable() { runOnUiThread(() -> {
public void run() { updateAccountsHeader();
updateAccountsHeader(); if (walletFragment != null) {
if (walletFragment != null) { walletFragment.onLoaded();
walletFragment.onLoaded();
}
} }
}); });
} }
@ -681,17 +645,15 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
try { try {
final SendFragment sendFragment = (SendFragment) final SendFragment sendFragment = (SendFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
runOnUiThread(new Runnable() { runOnUiThread(() -> {
public void run() { dismissProgressDialog();
dismissProgressDialog(); PendingTransaction.Status status = pendingTransaction.getStatus();
PendingTransaction.Status status = pendingTransaction.getStatus(); if (status != PendingTransaction.Status.Status_Ok) {
if (status != PendingTransaction.Status.Status_Ok) { String errorText = pendingTransaction.getErrorString();
String errorText = pendingTransaction.getErrorString(); getWallet().disposePendingTransaction();
getWallet().disposePendingTransaction(); sendFragment.onCreateTransactionFailed(errorText);
sendFragment.onCreateTransactionFailed(errorText); } else {
} else { sendFragment.onTransactionCreated(txTag, pendingTransaction);
sendFragment.onTransactionCreated(txTag, pendingTransaction);
}
} }
}); });
} catch (ClassCastException ex) { } catch (ClassCastException ex) {
@ -707,11 +669,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
try { try {
final SendFragment sendFragment = (SendFragment) final SendFragment sendFragment = (SendFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
runOnUiThread(new Runnable() { runOnUiThread(() -> sendFragment.onSendTransactionFailed(error));
public void run() {
sendFragment.onSendTransactionFailed(error);
}
});
} catch (ClassCastException ex) { } catch (ClassCastException ex) {
// not in spend fragment // not in spend fragment
Timber.d(ex.getLocalizedMessage()); Timber.d(ex.getLocalizedMessage());
@ -723,11 +681,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
try { try {
final SendFragment sendFragment = (SendFragment) final SendFragment sendFragment = (SendFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_container); getSupportFragmentManager().findFragmentById(R.id.fragment_container);
runOnUiThread(new Runnable() { runOnUiThread(() -> sendFragment.onTransactionSent(txId));
public void run() {
sendFragment.onTransactionSent(txId);
}
});
} catch (ClassCastException ex) { } catch (ClassCastException ex) {
// not in spend fragment // not in spend fragment
Timber.d(ex.getLocalizedMessage()); Timber.d(ex.getLocalizedMessage());
@ -753,18 +707,16 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override @Override
public void onProgress(final int n) { public void onProgress(final int n) {
runOnUiThread(new Runnable() { runOnUiThread(() -> {
public void run() { try {
try { WalletFragment walletFragment = (WalletFragment)
WalletFragment walletFragment = (WalletFragment) getSupportFragmentManager().findFragmentByTag(WalletFragment.class.getName());
getSupportFragmentManager().findFragmentByTag(WalletFragment.class.getName()); if (walletFragment != null)
if (walletFragment != null) walletFragment.setProgress(n);
walletFragment.setProgress(n); } catch (ClassCastException ex) {
} catch (ClassCastException ex) { // not in wallet fragment (probably send monero)
// not in wallet fragment (probably send monero) Timber.d(ex.getLocalizedMessage());
Timber.d(ex.getLocalizedMessage()); // keep calm and carry on
// keep calm and carry on
}
} }
}); });
} }
@ -832,8 +784,18 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
if (extras != null) { if (extras != null) {
newFragment.setArguments(extras); newFragment.setArguments(extras);
} }
int transition;
if (newFragment instanceof TxFragment)
transition = R.string.tx_details_transition_name;
else if (newFragment instanceof ReceiveFragment)
transition = R.string.receive_transition_name;
else if (newFragment instanceof SendFragment)
transition = R.string.send_transition_name;
else
throw new IllegalStateException("expecting known transition");
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
.addSharedElement(view, getString(R.string.tx_details_transition_name)) .addSharedElement(view, getString(transition))
.replace(R.id.fragment_container, newFragment) .replace(R.id.fragment_container, newFragment)
.addToBackStack(stackName) .addToBackStack(stackName)
.commit(); .commit();
@ -843,10 +805,11 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
if (extras != null) { if (extras != null) {
newFragment.setArguments(extras); newFragment.setArguments(extras);
} }
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); getSupportFragmentManager()
transaction.replace(R.id.fragment_container, newFragment); .beginTransaction()
transaction.addToBackStack(stackName); .replace(R.id.fragment_container, newFragment)
transaction.commit(); .addToBackStack(stackName)
.commit();
} }
private void onWalletDetails() { private void onWalletDetails() {
@ -963,40 +926,28 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
} }
@Override @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
@NonNull int[] grantResults) {
Timber.d("onRequestPermissionsResult()"); Timber.d("onRequestPermissionsResult()");
switch (requestCode) { if (requestCode == Helper.PERMISSIONS_REQUEST_CAMERA) { // If request is cancelled, the result arrays are empty.
case Helper.PERMISSIONS_REQUEST_CAMERA: if (grantResults.length > 0
// If request is cancelled, the result arrays are empty. && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (grantResults.length > 0 startScanFragment = true;
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) { } else {
startScanFragment = true; String msg = getString(R.string.message_camera_not_permitted);
} else { Timber.e(msg);
String msg = getString(R.string.message_camera_not_permitted); Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
Timber.e(msg); }
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
break;
default:
} }
} }
@Override @Override
public void onWalletReceive() { public void onWalletReceive(View view) {
startReceive(getWallet().getAddress()); final String address = getWallet().getAddress();
}
void startReceive(String address) {
Timber.d("startReceive()"); Timber.d("startReceive()");
Bundle b = new Bundle(); Bundle b = new Bundle();
b.putString("address", address); b.putString("address", address);
b.putString("name", getWalletName()); b.putString("name", getWalletName());
startReceiveFragment(b); replaceFragmentWithTransition(view, new ReceiveFragment(), null, b);
}
void startReceiveFragment(Bundle extras) {
replaceFragment(new ReceiveFragment(), null, extras);
Timber.d("ReceiveFragment placed"); Timber.d("ReceiveFragment placed");
} }
@ -1031,7 +982,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
return getPreferences(Context.MODE_PRIVATE); return getPreferences(Context.MODE_PRIVATE);
} }
private List<Integer> accountIds = new ArrayList<>(); private final List<Integer> accountIds = new ArrayList<>();
// generate and cache unique ids for use in accounts list // generate and cache unique ids for use in accounts list
private int getAccountId(int accountIndex) { private int getAccountId(int accountIndex) {
@ -1112,39 +1063,33 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
alertDialogBuilder alertDialogBuilder
.setCancelable(false) .setCancelable(false)
.setPositiveButton(getString(R.string.label_ok), .setPositiveButton(getString(R.string.label_ok),
new DialogInterface.OnClickListener() { (dialog, id) -> {
public void onClick(DialogInterface dialog, int id) { Helper.hideKeyboardAlways(WalletActivity.this);
Helper.hideKeyboardAlways(WalletActivity.this); String newName = etRename.getText().toString();
String newName = etRename.getText().toString(); wallet.setAccountLabel(newName);
wallet.setAccountLabel(newName); updateAccountName();
updateAccountName();
}
}) })
.setNegativeButton(getString(R.string.label_cancel), .setNegativeButton(getString(R.string.label_cancel),
new DialogInterface.OnClickListener() { (dialog, id) -> {
public void onClick(DialogInterface dialog, int id) { Helper.hideKeyboardAlways(WalletActivity.this);
Helper.hideKeyboardAlways(WalletActivity.this); dialog.cancel();
dialog.cancel();
}
}); });
final AlertDialog dialog = alertDialogBuilder.create(); final AlertDialog dialog = alertDialogBuilder.create();
Helper.showKeyboard(dialog); Helper.showKeyboard(dialog);
// accept keyboard "ok" // accept keyboard "ok"
etRename.setOnEditorActionListener(new TextView.OnEditorActionListener() { etRename.setOnEditorActionListener((v, actionId, event) -> {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN))
if ((event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) && (event.getAction() == KeyEvent.ACTION_DOWN)) || (actionId == EditorInfo.IME_ACTION_DONE)) {
|| (actionId == EditorInfo.IME_ACTION_DONE)) { Helper.hideKeyboardAlways(WalletActivity.this);
Helper.hideKeyboardAlways(WalletActivity.this); String newName = etRename.getText().toString();
String newName = etRename.getText().toString(); dialog.cancel();
dialog.cancel(); wallet.setAccountLabel(newName);
wallet.setAccountLabel(newName); updateAccountName();
updateAccountName();
return false;
}
return false; return false;
} }
return false;
}); });
dialog.show(); dialog.show();
@ -1153,19 +1098,17 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
@Override @Override
public boolean onNavigationItemSelected(MenuItem item) { public boolean onNavigationItemSelected(MenuItem item) {
final int id = item.getItemId(); final int id = item.getItemId();
switch (id) { if (id == R.id.account_new) {
case R.id.account_new: addAccount();
addAccount(); } else {
break; Timber.d("NavigationDrawer ID=%d", id);
default: int accountIdx = accountIds.indexOf(id);
Timber.d("NavigationDrawer ID=%d", id); if (accountIdx >= 0) {
int accountIdx = accountIds.indexOf(id); Timber.d("found @%d", accountIdx);
if (accountIdx >= 0) { getWallet().setAccountIndex(accountIdx);
Timber.d("found @%d", accountIdx); }
getWallet().setAccountIndex(accountIdx); forceUpdate();
} drawer.closeDrawer(GravityCompat.START);
forceUpdate();
drawer.closeDrawer(GravityCompat.START);
} }
return true; return true;
} }
@ -1174,6 +1117,7 @@ public class WalletActivity extends BaseActivity implements WalletFragment.Liste
new AsyncAddAccount().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR); new AsyncAddAccount().executeOnExecutor(MoneroThreadPoolExecutor.MONERO_THREAD_POOL_EXECUTOR);
} }
@SuppressLint("StaticFieldLeak")
private class AsyncAddAccount extends AsyncTask<Void, Void, Boolean> { private class AsyncAddAccount extends AsyncTask<Void, Void, Boolean> {
boolean dialogOpened = false; boolean dialogOpened = false;

View File

@ -36,6 +36,7 @@ import android.widget.ProgressBar;
import android.widget.Spinner; import android.widget.Spinner;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
@ -57,13 +58,14 @@ import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects;
import timber.log.Timber; import timber.log.Timber;
public class WalletFragment extends Fragment public class WalletFragment extends Fragment
implements TransactionInfoAdapter.OnInteractionListener { implements TransactionInfoAdapter.OnInteractionListener {
private TransactionInfoAdapter adapter; private TransactionInfoAdapter adapter;
private NumberFormat formatter = NumberFormat.getInstance(); private final NumberFormat formatter = NumberFormat.getInstance();
private TextView tvStreetView; private TextView tvStreetView;
private LinearLayout llBalance; private LinearLayout llBalance;
@ -80,7 +82,7 @@ public class WalletFragment extends Fragment
private Spinner sCurrency; private Spinner sCurrency;
private List<String> dismissedTransactions = new ArrayList<>(); private final List<String> dismissedTransactions = new ArrayList<>();
public void resetDismissedTransactions() { public void resetDismissedTransactions() {
dismissedTransactions.clear(); dismissedTransactions.clear();
@ -93,7 +95,7 @@ public class WalletFragment extends Fragment
} }
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
if (activityCallback.hasWallet()) if (activityCallback.hasWallet())
inflater.inflate(R.menu.wallet_menu, menu); inflater.inflate(R.menu.wallet_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
@ -104,6 +106,13 @@ public class WalletFragment extends Fragment
Bundle savedInstanceState) { Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_wallet, container, false); View view = inflater.inflate(R.layout.fragment_wallet, container, false);
final MaterialElevationScale exitTransition = new MaterialElevationScale(false);
exitTransition.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
setExitTransition(exitTransition);
final MaterialElevationScale reenterTransition = new MaterialElevationScale(true);
reenterTransition.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
setReenterTransition(reenterTransition);
ivStreetGunther = view.findViewById(R.id.ivStreetGunther); ivStreetGunther = view.findViewById(R.id.ivStreetGunther);
tvStreetView = view.findViewById(R.id.tvStreetView); tvStreetView = view.findViewById(R.id.tvStreetView);
llBalance = view.findViewById(R.id.llBalance); llBalance = view.findViewById(R.id.llBalance);
@ -124,7 +133,7 @@ public class WalletFragment extends Fragment
List<String> currencies = new ArrayList<>(); List<String> currencies = new ArrayList<>();
currencies.add(Helper.BASE_CRYPTO); currencies.add(Helper.BASE_CRYPTO);
currencies.addAll(Arrays.asList(getResources().getStringArray(R.array.currency))); currencies.addAll(Arrays.asList(getResources().getStringArray(R.array.currency)));
ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(getContext(), R.layout.item_spinner_balance, currencies); ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(Objects.requireNonNull(getContext()), R.layout.item_spinner_balance, currencies);
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sCurrency.setAdapter(spinnerAdapter); sCurrency.setAdapter(spinnerAdapter);
@ -169,18 +178,8 @@ public class WalletFragment extends Fragment
recyclerView.addOnItemTouchListener(swipeTouchListener); recyclerView.addOnItemTouchListener(swipeTouchListener);
bSend.setOnClickListener(new View.OnClickListener() { bSend.setOnClickListener(v -> activityCallback.onSendRequest(v));
@Override bReceive.setOnClickListener(v -> activityCallback.onWalletReceive(v));
public void onClick(View v) {
activityCallback.onSendRequest();
}
});
bReceive.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
activityCallback.onWalletReceive();
}
});
sCurrency.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { sCurrency.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override @Override
@ -203,6 +202,16 @@ public class WalletFragment extends Fragment
return view; return view;
} }
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
postponeEnterTransition();
view.getViewTreeObserver().addOnPreDrawListener(() -> {
startPostponedEnterTransition();
return true;
});
}
void showBalance(String balance) { void showBalance(String balance) {
tvBalance.setText(balance); tvBalance.setText(balance);
final boolean streetMode = activityCallback.isStreetMode(); final boolean streetMode = activityCallback.isStreetMode();
@ -260,24 +269,14 @@ public class WalletFragment extends Fragment
@Override @Override
public void onSuccess(final ExchangeRate exchangeRate) { public void onSuccess(final ExchangeRate exchangeRate) {
if (isAdded()) if (isAdded())
new Handler(Looper.getMainLooper()).post(new Runnable() { new Handler(Looper.getMainLooper()).post(() -> exchange(exchangeRate));
@Override
public void run() {
exchange(exchangeRate);
}
});
} }
@Override @Override
public void onError(final Exception e) { public void onError(final Exception e) {
Timber.e(e.getLocalizedMessage()); Timber.e(e.getLocalizedMessage());
if (isAdded()) if (isAdded())
new Handler(Looper.getMainLooper()).post(new Runnable() { new Handler(Looper.getMainLooper()).post(() -> exchangeFailed());
@Override
public void run() {
exchangeFailed();
}
});
} }
}); });
} else { } else {
@ -418,7 +417,6 @@ public class WalletFragment extends Fragment
void setActivityTitle(Wallet wallet) { void setActivityTitle(Wallet wallet) {
if (wallet == null) return; if (wallet == null) return;
walletTitle = wallet.getName(); walletTitle = wallet.getName();
String watchOnly = (wallet.isWatchOnly() ? getString(R.string.label_watchonly) : "");
walletSubtitle = wallet.getAccountLabel(); walletSubtitle = wallet.getAccountLabel();
activityCallback.setTitle(walletTitle, walletSubtitle); activityCallback.setTitle(walletTitle, walletSubtitle);
Timber.d("wallet title is %s", walletTitle); Timber.d("wallet title is %s", walletTitle);
@ -442,7 +440,7 @@ public class WalletFragment extends Fragment
balance = wallet.getBalance(); balance = wallet.getBalance();
unlockedBalance = wallet.getUnlockedBalance(); unlockedBalance = wallet.getUnlockedBalance();
refreshBalance(); refreshBalance();
String sync = ""; String sync;
if (!activityCallback.hasBoundService()) if (!activityCallback.hasBoundService())
throw new IllegalStateException("WalletService not bound."); throw new IllegalStateException("WalletService not bound.");
Wallet.ConnectionStatus daemonConnected = activityCallback.getConnectionStatus(); Wallet.ConnectionStatus daemonConnected = activityCallback.getConnectionStatus();
@ -483,7 +481,7 @@ public class WalletFragment extends Fragment
long getDaemonHeight(); //mBoundService.getDaemonHeight(); long getDaemonHeight(); //mBoundService.getDaemonHeight();
void onSendRequest(); void onSendRequest(View view);
void onTxDetailsRequest(View view, TransactionInfo info); void onTxDetailsRequest(View view, TransactionInfo info);
@ -497,7 +495,7 @@ public class WalletFragment extends Fragment
String getTxKey(String txId); String getTxKey(String txId);
void onWalletReceive(); void onWalletReceive(View view);
boolean hasWallet(); boolean hasWallet();
@ -511,7 +509,7 @@ public class WalletFragment extends Fragment
} }
@Override @Override
public void onAttach(Context context) { public void onAttach(@NonNull Context context) {
super.onAttach(context); super.onAttach(context);
if (context instanceof Listener) { if (context instanceof Listener) {
this.activityCallback = (Listener) context; this.activityCallback = (Listener) context;
@ -554,7 +552,7 @@ public class WalletFragment extends Fragment
//TODO figure out why gunther disappears on return from send although he is still set //TODO figure out why gunther disappears on return from send although he is still set
if (enable) { if (enable) {
if (streetGunther == null) if (streetGunther == null)
streetGunther = ContextCompat.getDrawable(getContext(), R.drawable.ic_gunther_streetmode); streetGunther = ContextCompat.getDrawable(Objects.requireNonNull(getContext()), R.drawable.ic_gunther_streetmode);
ivStreetGunther.setImageDrawable(streetGunther); ivStreetGunther.setImageDrawable(streetGunther);
} else } else
ivStreetGunther.setImageDrawable(null); ivStreetGunther.setImageDrawable(null);

View File

@ -36,6 +36,7 @@ import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter; import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager; import androidx.viewpager.widget.ViewPager;
import com.google.android.material.transition.MaterialContainerTransform;
import com.m2049r.xmrwallet.OnBackPressedListener; import com.m2049r.xmrwallet.OnBackPressedListener;
import com.m2049r.xmrwallet.OnUriScannedListener; import com.m2049r.xmrwallet.OnUriScannedListener;
import com.m2049r.xmrwallet.R; import com.m2049r.xmrwallet.R;
@ -49,10 +50,12 @@ import com.m2049r.xmrwallet.layout.SpendViewPager;
import com.m2049r.xmrwallet.model.PendingTransaction; import com.m2049r.xmrwallet.model.PendingTransaction;
import com.m2049r.xmrwallet.util.Helper; import com.m2049r.xmrwallet.util.Helper;
import com.m2049r.xmrwallet.util.Notice; import com.m2049r.xmrwallet.util.Notice;
import com.m2049r.xmrwallet.util.ThemeHelper;
import com.m2049r.xmrwallet.widget.DotBar; import com.m2049r.xmrwallet.widget.DotBar;
import com.m2049r.xmrwallet.widget.Toolbar; import com.m2049r.xmrwallet.widget.Toolbar;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.Objects;
import timber.log.Timber; import timber.log.Timber;
@ -309,7 +312,7 @@ public class SendFragment extends Fragment
SparseArray<WeakReference<SendWizardFragment>> myFragments = new SparseArray<>(); SparseArray<WeakReference<SendWizardFragment>> myFragments = new SparseArray<>();
public SpendPagerAdapter(FragmentManager fm) { public SpendPagerAdapter(FragmentManager fm) {
super(fm); super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
} }
public void addSuccess() { public void addSuccess() {
@ -538,14 +541,18 @@ public class SendFragment extends Fragment
enableNavigation(); enableNavigation();
} }
@Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setHasOptionsMenu(true); setHasOptionsMenu(true);
final MaterialContainerTransform transform = new MaterialContainerTransform();
transform.setDrawingViewId(R.id.fragment_container);
transform.setDuration(getResources().getInteger(R.integer.tx_item_transition_duration));
transform.setAllContainerColors(ThemeHelper.getThemedColor(Objects.requireNonNull(getContext()), R.attr.colorSurface));
setSharedElementEnterTransition(transform);
} }
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(@NonNull Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.send_menu, menu); inflater.inflate(R.menu.send_menu, menu);
super.onCreateOptionsMenu(menu, inflater); super.onCreateOptionsMenu(menu, inflater);
} }

View File

@ -3,7 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:transitionName="@string/receive_transition_name">
<EditText <EditText
android:id="@+id/etDummy" android:id="@+id/etDummy"

View File

@ -4,7 +4,8 @@
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical"
android:transitionName="@string/send_transition_name">
<LinearLayout <LinearLayout
android:id="@+id/llNotice" android:id="@+id/llNotice"

View File

@ -165,6 +165,7 @@
android:layout_weight="1" android:layout_weight="1"
android:enabled="false" android:enabled="false"
android:text="@string/label_wallet_receive" android:text="@string/label_wallet_receive"
android:transitionName="@string/receive_btn_transition_name"
app:icon="@drawable/ic_hand" /> app:icon="@drawable/ic_hand" />
<Button <Button
@ -176,6 +177,7 @@
android:layout_weight="1" android:layout_weight="1"
android:enabled="false" android:enabled="false"
android:text="@string/label_wallet_send" android:text="@string/label_wallet_send"
android:transitionName="@string/send_btn_transition_name"
app:icon="@drawable/ic_send" /> app:icon="@drawable/ic_send" />
</LinearLayout> </LinearLayout>

View File

@ -474,5 +474,9 @@
<string name="tx_item_transition_name" translatable="false">tx_transition_%1$s</string> <string name="tx_item_transition_name" translatable="false">tx_transition_%1$s</string>
<string name="tx_details_transition_name" translatable="false">tx_transition</string> <string name="tx_details_transition_name" translatable="false">tx_transition</string>
<string name="receive_transition_name" translatable="false">receive_transition</string>
<string name="receive_btn_transition_name" translatable="false">receive_btn_transition</string>
<string name="send_transition_name" translatable="false">send_transition</string>
<string name="send_btn_transition_name" translatable="false">send_btn_transition</string>
</resources> </resources>