From 91b58108dac0f3e97bf2cb18c96744625493bd31 Mon Sep 17 00:00:00 2001 From: Ephraim Kigamba Date: Thu, 6 Jun 2019 20:36:41 +0300 Subject: [PATCH 01/24] Update authentication screens & transfer progress screens --- .../p2p/activity/P2pModeSelectActivity.java | 79 ++++++---- .../ReceiverConnectionAuthenticator.java | 27 ++-- .../SenderConnectionAuthenticator.java | 25 +--- .../p2p/contract/P2pModeSelectContract.java | 20 ++- .../p2p/dialog/QRCodeGeneratorDialog.java | 141 ------------------ .../p2p/dialog/QRCodeScanningDialog.java | 112 -------------- .../p2p/dialog/SyncProgressDialog.java | 119 --------------- .../p2p/dialog/SyncProgressFragment.java | 100 +++++++++++++ .../p2p/fragment/QRCodeGeneratorFragment.java | 115 ++++++++++++++ .../p2p/fragment/QRCodeScanningFragment.java | 87 +++++++++++ .../SyncCompleteTransferFragment.java | 16 -- .../p2p/presenter/P2PReceiverPresenter.java | 11 +- .../p2p/presenter/P2PSenderPresenter.java | 9 +- .../p2p/sync/handler/SyncReceiverHandler.java | 9 +- .../p2p/sync/handler/SyncSenderHandler.java | 13 +- .../p2p/util/SyncDataConverterUtil.java | 9 +- .../main/res/drawable-hdpi/ic_icon_share.png | Bin 0 -> 2954 bytes .../main/res/drawable-mdpi/ic_icon_share.png | Bin 0 -> 1960 bytes .../main/res/drawable-xhdpi/ic_icon_share.png | Bin 0 -> 4416 bytes .../res/drawable-xxhdpi/ic_icon_share.png | Bin 0 -> 7617 bytes .../res/drawable-xxxhdpi/ic_icon_share.png | Bin 0 -> 12071 bytes .../res/layout/dialog_qr_code_generation.xml | 44 ++++-- .../res/layout/dialog_qr_code_scanning.xml | 39 +++-- .../main/res/layout/fragment_mode_select.xml | 9 ++ p2p-sync/src/main/res/values/strings.xml | 11 +- .../ReceiverConnectionAuthenticatorTest.java | 22 +-- .../SenderConnectionAuthenticatorTest.java | 24 +-- .../presenter/P2PReceiverPresenterTest.java | 10 +- .../p2p/presenter/P2PSenderPresenterTest.java | 10 +- .../p2p/sample/SampleApplication.java | 7 +- 30 files changed, 539 insertions(+), 529 deletions(-) delete mode 100644 p2p-sync/src/main/java/org/smartregister/p2p/dialog/QRCodeGeneratorDialog.java delete mode 100644 p2p-sync/src/main/java/org/smartregister/p2p/dialog/QRCodeScanningDialog.java delete mode 100644 p2p-sync/src/main/java/org/smartregister/p2p/dialog/SyncProgressDialog.java create mode 100644 p2p-sync/src/main/java/org/smartregister/p2p/dialog/SyncProgressFragment.java create mode 100644 p2p-sync/src/main/java/org/smartregister/p2p/fragment/QRCodeGeneratorFragment.java create mode 100644 p2p-sync/src/main/java/org/smartregister/p2p/fragment/QRCodeScanningFragment.java create mode 100755 p2p-sync/src/main/res/drawable-hdpi/ic_icon_share.png create mode 100755 p2p-sync/src/main/res/drawable-mdpi/ic_icon_share.png create mode 100755 p2p-sync/src/main/res/drawable-xhdpi/ic_icon_share.png create mode 100755 p2p-sync/src/main/res/drawable-xxhdpi/ic_icon_share.png create mode 100755 p2p-sync/src/main/res/drawable-xxxhdpi/ic_icon_share.png diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/activity/P2pModeSelectActivity.java b/p2p-sync/src/main/java/org/smartregister/p2p/activity/P2pModeSelectActivity.java index 80ba39e..0f918df 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/activity/P2pModeSelectActivity.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/activity/P2pModeSelectActivity.java @@ -33,11 +33,11 @@ import org.smartregister.p2p.P2PLibrary; import org.smartregister.p2p.R; import org.smartregister.p2p.contract.P2pModeSelectContract; -import org.smartregister.p2p.dialog.QRCodeGeneratorDialog; -import org.smartregister.p2p.dialog.QRCodeScanningDialog; +import org.smartregister.p2p.fragment.QRCodeGeneratorFragment; +import org.smartregister.p2p.fragment.QRCodeScanningFragment; import org.smartregister.p2p.dialog.StartDiscoveringModeProgressDialog; import org.smartregister.p2p.dialog.StartReceiveModeProgressDialog; -import org.smartregister.p2p.dialog.SyncProgressDialog; +import org.smartregister.p2p.dialog.SyncProgressFragment; import org.smartregister.p2p.fragment.P2PModeSelectFragment; import org.smartregister.p2p.fragment.SyncCompleteTransferFragment; import org.smartregister.p2p.handler.OnActivityRequestPermissionHandler; @@ -68,7 +68,7 @@ public class P2pModeSelectActivity extends AppCompatActivity implements P2pModeS private ArrayList onActivityRequestPermissionHandlers = new ArrayList<>(); private P2PModeSelectFragment p2PModeSelectFragment; - private SyncProgressDialog syncProgressDialog; + private SyncProgressFragment syncProgressFragment; @Override protected void onCreate(Bundle savedInstanceState) { @@ -140,19 +140,26 @@ public void showAdvertisingProgressDialog(@NonNull DialogCancelCallback dialogCa } @Override - public void showSyncProgressDialog(@NonNull String title, @NonNull SyncProgressDialog.SyncProgressDialogCallback syncProgressDialogCallback) { - FragmentManager fragmentManager = getSupportFragmentManager(); - syncProgressDialog = SyncProgressDialog.create(title); - syncProgressDialog.setSyncProgressDialogCallback(syncProgressDialogCallback); + public void showSyncProgressFragment(@NonNull String title, @NonNull SyncProgressFragment.SyncProgressDialogCallback syncProgressDialogCallback) { + syncProgressFragment = SyncProgressFragment.create(title); + syncProgressFragment.setSyncProgressDialogCallback(syncProgressDialogCallback); + + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + + // Replace whatever is in the fragment_container view with this fragment, + // and add the transaction to the back stack + transaction.replace(R.id.cl_p2pModeSelectActivity_parentLayout, syncProgressFragment); + + // Commit the transaction + transaction.commit(); - syncProgressDialog.show(fragmentManager, Constants.Dialog.SYNC_PROGRESS_DIALOG); } @Override public void updateProgressDialog(@NonNull String progress, @NonNull String summary) { - if (syncProgressDialog != null) { - syncProgressDialog.setProgressText(progress); - syncProgressDialog.setSummaryText(summary); + if (syncProgressFragment != null) { + syncProgressFragment.setProgressText(progress); + syncProgressFragment.setSummaryText(summary); } else { Timber.e("Could not update progress dialog with %s/%s because sync progress dialog is null", progress, summary); } @@ -160,8 +167,8 @@ public void updateProgressDialog(@NonNull String progress, @NonNull String summa @Override public void updateProgressDialog(int progress) { - if (syncProgressDialog != null) { - syncProgressDialog.setProgress(progress); + if (syncProgressFragment != null) { + syncProgressFragment.setProgress(progress); } else { Timber.e("Could not update progress dialog to %d because sync progress dialog is null", progress); } @@ -169,7 +176,7 @@ public void updateProgressDialog(int progress) { @Override public boolean removeSyncProgressDialog() { - syncProgressDialog = null; + syncProgressFragment = null; return removeDialog(Constants.Dialog.SYNC_PROGRESS_DIALOG); } @@ -223,24 +230,36 @@ private boolean removeDialog(@NonNull String tag) { } @Override - public void showQRCodeScanningDialog(@NonNull QRCodeScanningDialog.QRCodeScanDialogCallback qrCodeScanDialogCallback) { - FragmentManager fragmentManager = getSupportFragmentManager(); - QRCodeScanningDialog newFragment = new QRCodeScanningDialog(); + public void showQRCodeScanningFragment(@NonNull QRCodeScanningFragment.QRCodeScanDialogCallback qrCodeScanDialogCallback) { + QRCodeScanningFragment newFragment = new QRCodeScanningFragment(); newFragment.setOnQRRecognisedListener(qrCodeScanDialogCallback); - newFragment.show(fragmentManager, Constants.Dialog.QR_CODE_SCANNING); + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + + // Replace whatever is in the fragment_container view with this fragment, + // and add the transaction to the back stack + transaction.replace(R.id.cl_p2pModeSelectActivity_parentLayout, newFragment); + + // Commit the transaction + transaction.commit(); } @Override - public void showQRCodeGeneratorDialog(@NonNull String authenticationCode, @NonNull String deviceName - , @NonNull QRCodeGeneratorDialog.QRCodeAuthenticationCallback qrCodeAuthenticationCallback) { - FragmentManager fragmentManager = getSupportFragmentManager(); - QRCodeGeneratorDialog newFragment = new QRCodeGeneratorDialog(); + public void showQRCodeGeneratorFragment(@NonNull String authenticationCode, @NonNull String deviceName + , @NonNull QRCodeGeneratorFragment.QRCodeGeneratorCallback qrCodeGeneratorCallback) { + QRCodeGeneratorFragment newFragment = new QRCodeGeneratorFragment(); newFragment.setAuthenticationCode(authenticationCode); newFragment.setDeviceName(deviceName); - newFragment.setQrCodeAuthenticationCallback(qrCodeAuthenticationCallback); + newFragment.setQrCodeGeneratorCallback(qrCodeGeneratorCallback); + + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); + + // Replace whatever is in the fragment_container view with this fragment, + // and add the transaction to the back stack + transaction.replace(R.id.cl_p2pModeSelectActivity_parentLayout, newFragment); - newFragment.show(fragmentManager, Constants.Dialog.AUTHENTICATION_QR_CODE_GENERATOR); + // Commit the transaction + transaction.commit(); } @Override @@ -437,6 +456,16 @@ public void onClick(DialogInterface dialog, int which) { .show(); } + @Override + public void showConnectingDialog() { + + } + + @Override + public void removeConnectingDialog() { + + } + @Override protected void onResume() { super.onResume(); diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/authenticator/ReceiverConnectionAuthenticator.java b/p2p-sync/src/main/java/org/smartregister/p2p/authenticator/ReceiverConnectionAuthenticator.java index b716876..7085dd7 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/authenticator/ReceiverConnectionAuthenticator.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/authenticator/ReceiverConnectionAuthenticator.java @@ -1,10 +1,9 @@ package org.smartregister.p2p.authenticator; -import android.content.DialogInterface; import android.support.annotation.NonNull; import org.smartregister.p2p.contract.P2pModeSelectContract; -import org.smartregister.p2p.dialog.QRCodeGeneratorDialog; +import org.smartregister.p2p.fragment.QRCodeGeneratorFragment; import org.smartregister.p2p.sync.DiscoveredDevice; /** @@ -22,18 +21,20 @@ public void authenticate(@NonNull final DiscoveredDevice discoveredDevice, @NonN if (discoveredDevice.getConnectionInfo() != null && discoveredDevice.getConnectionInfo().isIncomingConnection()) { - getPresenter().getView().showQRCodeGeneratorDialog(discoveredDevice.getConnectionInfo().getAuthenticationToken() + getPresenter().getView().showQRCodeGeneratorFragment(discoveredDevice.getConnectionInfo().getAuthenticationToken() , discoveredDevice.getEndpointName() - , new QRCodeGeneratorDialog.QRCodeAuthenticationCallback() { - @Override - public void onAccepted(@NonNull DialogInterface dialogInterface) { - authenticationCallback.onAuthenticationSuccessful(); - } - - @Override - public void onRejected(@NonNull DialogInterface dialogInterface) { - authenticationCallback.onAuthenticationFailed(new Exception("User rejected the connection")); - } + , new QRCodeGeneratorFragment.QRCodeGeneratorCallback() { + + @Override + public void onSkipped() { + //authenticationCallback.onAuthenticationCancelled("Skip was clicked"); + authenticationCallback.onAuthenticationSuccessful(); + } + + @Override + public void onErrorOccurred(@NonNull Exception e) { + authenticationCallback.onAuthenticationFailed(e); + } }); } else { diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/authenticator/SenderConnectionAuthenticator.java b/p2p-sync/src/main/java/org/smartregister/p2p/authenticator/SenderConnectionAuthenticator.java index 6f1f4f9..19702bd 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/authenticator/SenderConnectionAuthenticator.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/authenticator/SenderConnectionAuthenticator.java @@ -3,14 +3,12 @@ import android.content.DialogInterface; import android.support.annotation.NonNull; import android.util.SparseArray; -import android.widget.Toast; import com.google.android.gms.nearby.connection.ConnectionInfo; import com.google.android.gms.vision.barcode.Barcode; -import org.smartregister.p2p.R; import org.smartregister.p2p.contract.P2pModeSelectContract; -import org.smartregister.p2p.dialog.QRCodeScanningDialog; +import org.smartregister.p2p.fragment.QRCodeScanningFragment; import org.smartregister.p2p.sync.DiscoveredDevice; /** @@ -29,14 +27,12 @@ public void authenticate(@NonNull final DiscoveredDevice discoveredDevice, @NonN && !discoveredDevice.getConnectionInfo().isIncomingConnection()) { final ConnectionInfo connectionInfo = discoveredDevice.getConnectionInfo(); - getPresenter().getView().showQRCodeScanningDialog(new QRCodeScanningDialog.QRCodeScanDialogCallback() { + getPresenter().getView().showQRCodeScanningFragment(new QRCodeScanningFragment.QRCodeScanDialogCallback() { @Override - public void qrCodeScanned(final @NonNull SparseArray qrCodeResult, final @NonNull DialogInterface dialogInterface) { + public void qrCodeScanned(final @NonNull SparseArray qrCodeResult) { getPresenter().getView().runOnUiThread(new Runnable() { @Override public void run() { - dialogInterface.dismiss(); - String authenticationCode = connectionInfo.getAuthenticationToken(); boolean authenticationCodeFound = false; @@ -47,31 +43,24 @@ public void run() { } } - String message = getPresenter().getView() - .getString(R.string.device_authentication_failed); - if (authenticationCodeFound) { - message = getPresenter().getView() - .getString(R.string.device_authenticated_successfully); authenticationCallback.onAuthenticationSuccessful(); } else { authenticationCallback.onAuthenticationFailed(new Exception("Authentication tokens do not match")); } - getPresenter().getView().showToast(String.format(message, connectionInfo.getEndpointName()), Toast.LENGTH_LONG); + //getPresenter().getView().showToast(String.format(message, connectionInfo.getEndpointName()), Toast.LENGTH_LONG); } }); } @Override - public void onCancelClicked(@NonNull DialogInterface dialogInterface) { - dialogInterface.dismiss(); - authenticationCallback.onAuthenticationFailed(new Exception("User rejected the connection")); + public void onErrorOccurred(@NonNull Exception e) { + } @Override - public void onSkipClicked(@NonNull DialogInterface dialogInterface) { - dialogInterface.dismiss(); + public void onSkipClicked() { getPresenter().getView().showConnectionAcceptDialog(discoveredDevice.getEndpointName(), connectionInfo.getAuthenticationToken(), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/contract/P2pModeSelectContract.java b/p2p-sync/src/main/java/org/smartregister/p2p/contract/P2pModeSelectContract.java index d9a0b99..fb501ea 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/contract/P2pModeSelectContract.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/contract/P2pModeSelectContract.java @@ -11,9 +11,9 @@ import com.google.android.gms.nearby.connection.PayloadCallback; import org.smartregister.p2p.callback.OnResultCallback; -import org.smartregister.p2p.dialog.QRCodeGeneratorDialog; -import org.smartregister.p2p.dialog.QRCodeScanningDialog; -import org.smartregister.p2p.dialog.SyncProgressDialog; +import org.smartregister.p2p.fragment.QRCodeGeneratorFragment; +import org.smartregister.p2p.fragment.QRCodeScanningFragment; +import org.smartregister.p2p.dialog.SyncProgressFragment; import org.smartregister.p2p.fragment.SyncCompleteTransferFragment; import org.smartregister.p2p.model.SendingDevice; import org.smartregister.p2p.sync.DiscoveredDevice; @@ -37,7 +37,7 @@ interface View extends BaseView { void showAdvertisingProgressDialog(@NonNull DialogCancelCallback dialogCancelCallback); - void showSyncProgressDialog(@NonNull String title, @NonNull SyncProgressDialog.SyncProgressDialogCallback syncProgressDialogCallback); + void showSyncProgressFragment(@NonNull String title, @NonNull SyncProgressFragment.SyncProgressDialogCallback syncProgressDialogCallback); void updateProgressDialog(@NonNull String progress, @NonNull String summary); @@ -53,14 +53,18 @@ interface View extends BaseView { boolean removeDiscoveringProgressDialog(); - void showQRCodeScanningDialog(@NonNull QRCodeScanningDialog.QRCodeScanDialogCallback qrCodeScanDialogCallback); + void showQRCodeScanningFragment(@NonNull QRCodeScanningFragment.QRCodeScanDialogCallback qrCodeScanDialogCallback); - void showQRCodeGeneratorDialog(@NonNull String authenticationCode, @NonNull String deviceName - , @NonNull QRCodeGeneratorDialog.QRCodeAuthenticationCallback qrCodeAuthenticationCallback); + void showQRCodeGeneratorFragment(@NonNull String authenticationCode, @NonNull String deviceName + , @NonNull QRCodeGeneratorFragment.QRCodeGeneratorCallback qrCodeGeneratorCallback); void showConnectionAcceptDialog(@NonNull String receiverDeviceName, @NonNull String authenticationCode , @NonNull DialogInterface.OnClickListener onClickListener); + void showConnectingDialog(); + + void removeConnectingDialog(); + void requestPermissions(@NonNull List unauthorisedPermissions); @NonNull @@ -120,6 +124,8 @@ interface BasePresenter { void rejectDeviceOnAuthentication(@NonNull String endpointId); void disconnectAndReset(@NonNull String endpointId); + + void startTransfer(); } interface ReceiverPresenter extends BasePresenter { diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/dialog/QRCodeGeneratorDialog.java b/p2p-sync/src/main/java/org/smartregister/p2p/dialog/QRCodeGeneratorDialog.java deleted file mode 100644 index 3bd7065..0000000 --- a/p2p-sync/src/main/java/org/smartregister/p2p/dialog/QRCodeGeneratorDialog.java +++ /dev/null @@ -1,141 +0,0 @@ -package org.smartregister.p2p.dialog; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; -import android.view.LayoutInflater; -import android.widget.ImageView; -import android.widget.TextView; - -import com.google.zxing.BarcodeFormat; -import com.google.zxing.WriterException; -import com.journeyapps.barcodescanner.BarcodeEncoder; - -import org.smartregister.p2p.R; - -import timber.log.Timber; - -/** - * Created by Ephraim Kigamba - ekigamba@ona.io on 08/03/2019 - */ - -public class QRCodeGeneratorDialog extends DialogFragment { - - private DialogInterface dialogInterface; - private String authenticationCode; - private QRCodeAuthenticationCallback qrCodeAuthenticationCallback; - private String deviceName; - - public QRCodeGeneratorDialog() { - dialogInterface = new DialogInterface() { - @Override - public void cancel() { - QRCodeGeneratorDialog.this.dismiss(); - } - - @Override - public void dismiss() { - QRCodeGeneratorDialog.this.dismiss(); - } - }; - } - - public void setAuthenticationCode(@NonNull String authenticationCode) { - this.authenticationCode = authenticationCode; - } - - public void setDeviceName(String deviceName) { - this.deviceName = deviceName; - } - - public void setQrCodeAuthenticationCallback(QRCodeAuthenticationCallback qrCodeAuthenticationCallback) { - this.qrCodeAuthenticationCallback = qrCodeAuthenticationCallback; - } - - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - LayoutInflater inflater = requireActivity().getLayoutInflater(); - builder.setView(inflater.inflate(R.layout.dialog_qr_code_generation, null)) - .setPositiveButton(R.string.skip_this_step, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (qrCodeAuthenticationCallback != null) { - qrCodeAuthenticationCallback.onAccepted(dialogInterface); - } - } - }) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (qrCodeAuthenticationCallback != null) { - qrCodeAuthenticationCallback.onRejected(dialogInterface); - } - } - }); - AlertDialog dialog = builder.create(); - setCancelable(false); - - return dialog; - } - - - @Override - public void onStart() { - super.onStart(); - - // Generate the QR Code - BarcodeEncoder barcodeEncoder = new BarcodeEncoder(); - Bitmap bitmap = null; - try { - int screenHeight = getResources().getDisplayMetrics().heightPixels; - int screenWidth = getResources().getDisplayMetrics().widthPixels; - - int barcodeSize = 800; - - if (screenHeight/2 < barcodeSize) { - barcodeSize = screenHeight/2; - } - - if (screenWidth/2 < barcodeSize) { - barcodeSize = screenWidth/2; - } - - bitmap = barcodeEncoder.encodeBitmap(authenticationCode, BarcodeFormat.QR_CODE, barcodeSize, barcodeSize); - - ImageView imageViewQrCode = getDialog().findViewById(R.id.iv_qrCodeGenDialog_qrCode); - imageViewQrCode.setImageBitmap(bitmap); - - ((TextView) getDialog().findViewById(R.id.tv_qrCodeGenDialog_authCode)) - .setText(String.format(getString(R.string.scan_this_qr_code_using_sending_device), deviceName)); - } catch (WriterException e) { - Timber.e(e); - - // TODO: Show error toast - if (qrCodeAuthenticationCallback != null) { - qrCodeAuthenticationCallback.onRejected(dialogInterface); - } - dismiss(); - } - - } - - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - } - - public interface QRCodeAuthenticationCallback { - - void onAccepted(@NonNull DialogInterface dialogInterface); - - void onRejected(@NonNull DialogInterface dialogInterface); - } -} diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/dialog/QRCodeScanningDialog.java b/p2p-sync/src/main/java/org/smartregister/p2p/dialog/QRCodeScanningDialog.java deleted file mode 100644 index 70f8683..0000000 --- a/p2p-sync/src/main/java/org/smartregister/p2p/dialog/QRCodeScanningDialog.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.smartregister.p2p.dialog; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; -import android.util.SparseArray; -import android.view.LayoutInflater; - -import com.google.android.gms.vision.barcode.Barcode; - -import org.smartregister.p2p.R; -import org.smartregister.p2p.view.QRCodeScannerView; - -/** - * Created by Ephraim Kigamba - ekigamba@ona.io on 08/03/2019 - */ - -public class QRCodeScanningDialog extends DialogFragment { - - private QRCodeScanDialogCallback qrCodeScanDialogCallback; - private QRCodeScannerView qrCodeScannerView; - private DialogInterface dialogInterface; - - public QRCodeScanningDialog() { - dialogInterface = new DialogInterface() { - @Override - public void cancel() { - QRCodeScanningDialog.this.dismiss(); - } - - @Override - public void dismiss() { - QRCodeScanningDialog.this.dismiss(); - } - }; - } - - public void setOnQRRecognisedListener(@NonNull QRCodeScanDialogCallback qrCodeScanDialogCallback) { - this.qrCodeScanDialogCallback = qrCodeScanDialogCallback; - } - - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - LayoutInflater inflater = requireActivity().getLayoutInflater(); - builder.setView(inflater.inflate(R.layout.dialog_qr_code_scanning, null)) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (qrCodeScanDialogCallback != null) { - qrCodeScanDialogCallback.onCancelClicked(dialogInterface); - } - } - }) - .setPositiveButton(R.string.skip_this_step, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (qrCodeScanDialogCallback != null) { - qrCodeScanDialogCallback.onSkipClicked(dialogInterface); - } - } - }); - - AlertDialog dialog = builder.create(); - setCancelable(false); - - return dialog; - } - - @Override - public void onStart() { - super.onStart(); - - qrCodeScannerView = getDialog().findViewById(R.id.bsv_qrCodeScanningDialog_barcodeScanner); - qrCodeScannerView.addOnBarcodeRecognisedListener(new QRCodeScannerView.OnQRRecognisedListener() { - @Override - public void onBarcodeRecognised(SparseArray recognisedItems) { - if (qrCodeScanDialogCallback != null) { - qrCodeScanDialogCallback.qrCodeScanned(recognisedItems, dialogInterface); - } - } - }); - - getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - qrCodeScannerView.onPause(); - qrCodeScannerView.onDestroy(); - } - }); - } - - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - } - - public interface QRCodeScanDialogCallback { - - void onSkipClicked(@NonNull DialogInterface dialogInterface); - - void qrCodeScanned(@NonNull SparseArray qrCodeResult, @NonNull DialogInterface dialogInterface); - - void onCancelClicked(@NonNull DialogInterface dialogInterface); - } -} diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/dialog/SyncProgressDialog.java b/p2p-sync/src/main/java/org/smartregister/p2p/dialog/SyncProgressDialog.java deleted file mode 100644 index 3da5cc7..0000000 --- a/p2p-sync/src/main/java/org/smartregister/p2p/dialog/SyncProgressDialog.java +++ /dev/null @@ -1,119 +0,0 @@ -package org.smartregister.p2p.dialog; - -import android.app.Dialog; -import android.content.DialogInterface; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; -import android.support.v7.app.AlertDialog; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.ProgressBar; -import android.widget.TextView; - -import org.smartregister.p2p.R; - -/** - * Created by Ephraim Kigamba - ekigamba@ona.io on 08/03/2019 - */ - -public class SyncProgressDialog extends DialogFragment { - - private DialogInterface dialogInterface; - private SyncProgressDialogCallback syncProgressDialogCallback; - - private ProgressBar progressBar; - private TextView progressTextView; - private TextView summaryTextView; - private TextView startingTextView; - private String title; - - public static SyncProgressDialog create(@NonNull String title) { - SyncProgressDialog syncProgressDialog = new SyncProgressDialog(); - syncProgressDialog.title = title; - - return syncProgressDialog; - } - - public SyncProgressDialog() { - dialogInterface = new DialogInterface() { - @Override - public void cancel() { - SyncProgressDialog.this.dismiss(); - } - - @Override - public void dismiss() { - SyncProgressDialog.this.dismiss(); - } - }; - } - - public void setSummaryText(@NonNull String summaryText) { - if (summaryTextView != null) { - startingTextView.setVisibility(View.GONE); - summaryTextView.setText(summaryText); - } - } - - public void setProgressText(@NonNull String progressText) { - if (progressTextView != null) { - startingTextView.setVisibility(View.GONE); - progressTextView.setText(progressText); - } - } - - public void setProgress(int progress) { - if (progressBar != null) { - progressBar.setIndeterminate(false); - progressBar.setProgress(progress); - } - } - - public void setSyncProgressDialogCallback(@NonNull SyncProgressDialogCallback syncProgressDialogCallback) { - this.syncProgressDialogCallback = syncProgressDialogCallback; - } - - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - - LayoutInflater inflater = requireActivity().getLayoutInflater(); - builder.setView(inflater.inflate(R.layout.dialog_sync_progress, null)) - .setTitle(title) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - if (syncProgressDialogCallback != null) { - syncProgressDialogCallback.onCancelClicked(dialogInterface); - } - } - }); - - AlertDialog dialog = builder.create(); - setCancelable(false); - - return dialog; - } - - @Override - public void onStart() { - super.onStart(); - progressBar = getDialog().findViewById(R.id.pb_syncProgressDialog_progressBar); - progressTextView = getDialog().findViewById(R.id.tv_syncProgressDialog_progressText); - summaryTextView = getDialog().findViewById(R.id.tv_syncProgressDialog_summaryText); - startingTextView = getDialog().findViewById(R.id.tv_syncProgressDialog_startingText); - } - - @Override - public void onDismiss(DialogInterface dialog) { - super.onDismiss(dialog); - } - - public interface SyncProgressDialogCallback { - - void onCancelClicked(@NonNull DialogInterface dialogInterface); - } -} diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/dialog/SyncProgressFragment.java b/p2p-sync/src/main/java/org/smartregister/p2p/dialog/SyncProgressFragment.java new file mode 100644 index 0000000..96860e8 --- /dev/null +++ b/p2p-sync/src/main/java/org/smartregister/p2p/dialog/SyncProgressFragment.java @@ -0,0 +1,100 @@ +package org.smartregister.p2p.dialog; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ProgressBar; +import android.widget.TextView; + +import org.smartregister.p2p.R; + +/** + * Created by Ephraim Kigamba - ekigamba@ona.io on 08/03/2019 + */ + +public class SyncProgressFragment extends Fragment { + + private SyncProgressDialogCallback syncProgressDialogCallback; + + private ProgressBar progressBar; + private TextView progressTextView; + private TextView summaryTextView; + private TextView startingTextView; + private String title; + + public static SyncProgressFragment create(@NonNull String title) { + SyncProgressFragment syncProgressFragment = new SyncProgressFragment(); + syncProgressFragment.title = title; + + return syncProgressFragment; + } + + public SyncProgressFragment() { + } + + public void setSummaryText(@NonNull String summaryText) { + if (summaryTextView != null) { + startingTextView.setVisibility(View.GONE); + summaryTextView.setText(summaryText); + } + } + + public void setProgressText(@NonNull String progressText) { + if (progressTextView != null) { + startingTextView.setVisibility(View.GONE); + progressTextView.setText(progressText); + } + } + + public void setProgress(int progress) { + if (progressBar != null) { + if (progress > -1) { + progressBar.setIndeterminate(false); + progressBar.setProgress(progress); + } else { + progressBar.setIndeterminate(true); + } + } + } + + public void setSyncProgressDialogCallback(@NonNull SyncProgressDialogCallback syncProgressDialogCallback) { + this.syncProgressDialogCallback = syncProgressDialogCallback; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.dialog_sync_progress, container, false); + + progressBar = view.findViewById(R.id.pb_syncProgressDialog_progressBar); + progressTextView = view.findViewById(R.id.tv_syncProgressDialog_progressText); + summaryTextView = view.findViewById(R.id.tv_syncProgressDialog_summaryText); + startingTextView = view.findViewById(R.id.tv_syncProgressDialog_startingText); + + return view; + } + + @Override + public void onDestroy() { + if (syncProgressDialogCallback != null) { + syncProgressDialogCallback.onCancelClicked(); + } + + super.onDestroy(); + } + + public void closeFragment() { + if (getActivity() != null) { + getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit(); + } + } + + public interface SyncProgressDialogCallback { + + void onCancelClicked(); + } +} diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/fragment/QRCodeGeneratorFragment.java b/p2p-sync/src/main/java/org/smartregister/p2p/fragment/QRCodeGeneratorFragment.java new file mode 100644 index 0000000..b8da5b0 --- /dev/null +++ b/p2p-sync/src/main/java/org/smartregister/p2p/fragment/QRCodeGeneratorFragment.java @@ -0,0 +1,115 @@ +package org.smartregister.p2p.fragment; + +import android.graphics.Bitmap; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.WriterException; +import com.journeyapps.barcodescanner.BarcodeEncoder; + +import org.smartregister.p2p.R; + +import timber.log.Timber; + +/** + * Created by Ephraim Kigamba - ekigamba@ona.io on 08/03/2019 + */ + +public class QRCodeGeneratorFragment extends Fragment { + + private String authenticationCode; + private QRCodeGeneratorCallback qrCodeGeneratorCallback; + private String deviceName; + + public void setAuthenticationCode(@NonNull String authenticationCode) { + this.authenticationCode = authenticationCode; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public void setQrCodeGeneratorCallback(QRCodeGeneratorCallback qrCodeGeneratorCallback) { + this.qrCodeGeneratorCallback = qrCodeGeneratorCallback; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.dialog_qr_code_generation, container, false); + + // Generate the QR Code + BarcodeEncoder barcodeEncoder = new BarcodeEncoder(); + Bitmap bitmap = null; + try { + int screenHeight = getResources().getDisplayMetrics().heightPixels; + int screenWidth = getResources().getDisplayMetrics().widthPixels; + + int barcodeSize = 800; + + if (screenHeight/2 < barcodeSize) { + barcodeSize = screenHeight/2; + } + + if (screenWidth/2 < barcodeSize) { + barcodeSize = screenWidth/2; + } + + bitmap = barcodeEncoder.encodeBitmap(authenticationCode, BarcodeFormat.QR_CODE, barcodeSize, barcodeSize); + + ImageView imageViewQrCode = view.findViewById(R.id.iv_qrCodeGenDialog_qrCode); + imageViewQrCode.setImageBitmap(bitmap); + + ((TextView) view.findViewById(R.id.tv_qrCodeGenDialog_authCode)) + .setText(String.format(getString(R.string.scan_this_qr_code_using_sending_device), deviceName)); + } catch (WriterException e) { + Timber.e(e); + + // TODO: Show error toast + if (qrCodeGeneratorCallback != null) { + qrCodeGeneratorCallback.onErrorOccurred(e); + } + + closeFragment(); + } + + Button skip = view.findViewById(R.id.btn_qrCodeGenDialog_skipBtn); + skip.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (qrCodeGeneratorCallback != null) { + qrCodeGeneratorCallback.onSkipped(); + } + } + }); + + return view; + } + + public void closeFragment() { + if (getActivity() != null) { + getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit(); + } + } + + @Override + public void onStart() { + super.onStart(); + } + + public interface QRCodeGeneratorCallback { + + void onSkipped(); + + void onErrorOccurred(@NonNull Exception e); + } +} diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/fragment/QRCodeScanningFragment.java b/p2p-sync/src/main/java/org/smartregister/p2p/fragment/QRCodeScanningFragment.java new file mode 100644 index 0000000..5622e6b --- /dev/null +++ b/p2p-sync/src/main/java/org/smartregister/p2p/fragment/QRCodeScanningFragment.java @@ -0,0 +1,87 @@ +package org.smartregister.p2p.fragment; + +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; + +import com.google.android.gms.vision.barcode.Barcode; + +import org.smartregister.p2p.R; +import org.smartregister.p2p.view.QRCodeScannerView; + +/** + * Created by Ephraim Kigamba - ekigamba@ona.io on 08/03/2019 + */ + +public class QRCodeScanningFragment extends Fragment { + + private QRCodeScanDialogCallback qrCodeScanDialogCallback; + private QRCodeScannerView qrCodeScannerView; + + public QRCodeScanningFragment() { + } + + public void setOnQRRecognisedListener(@NonNull QRCodeScanDialogCallback qrCodeScanDialogCallback) { + this.qrCodeScanDialogCallback = qrCodeScanDialogCallback; + } + + @Nullable + @Override + public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.dialog_qr_code_scanning, container, false); + + Button skipBtn = view.findViewById(R.id.btn_qrCodeScanningDialog_skipBtn); + skipBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + closeFragment(); + if (qrCodeScanDialogCallback != null) { + qrCodeScanDialogCallback.onSkipClicked(); + } + } + }); + + qrCodeScannerView = view.findViewById(R.id.bsv_qrCodeScanningDialog_barcodeScanner); + qrCodeScannerView.addOnBarcodeRecognisedListener(new QRCodeScannerView.OnQRRecognisedListener() { + @Override + public void onBarcodeRecognised(SparseArray recognisedItems) { + closeFragment(); + if (qrCodeScanDialogCallback != null) { + qrCodeScanDialogCallback.qrCodeScanned(recognisedItems); + } + } + }); + + return view; + } + + private void closeFragment() { + if (getActivity() != null) { + getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit(); + } + } + + @Override + public void onPause() { + if (qrCodeScannerView != null) { + qrCodeScannerView.onPause(); + qrCodeScannerView.onDestroy(); + } + super.onPause(); + } + + public interface QRCodeScanDialogCallback { + + void onSkipClicked(); + + void qrCodeScanned(@NonNull SparseArray qrCodeResult); + + void onErrorOccurred(@NonNull Exception e); + } +} diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/fragment/SyncCompleteTransferFragment.java b/p2p-sync/src/main/java/org/smartregister/p2p/fragment/SyncCompleteTransferFragment.java index affc740..cae15a9 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/fragment/SyncCompleteTransferFragment.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/fragment/SyncCompleteTransferFragment.java @@ -35,12 +35,6 @@ public void setOnCloseClickListener(@Nullable OnCloseClickListener onCloseClickL this.onCloseClickListener = onCloseClickListener; } - @Nullable - @Override - public View getView() { - return super.getView(); - } - @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { @@ -69,16 +63,6 @@ public void onClick(View v) { return view; } - @Override - public void onStart() { - super.onStart(); - } - - @Override - public void onStop() { - super.onStop(); - } - public interface OnCloseClickListener { void onCloseClicked(); diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/presenter/P2PReceiverPresenter.java b/p2p-sync/src/main/java/org/smartregister/p2p/presenter/P2PReceiverPresenter.java index fbcb769..61a4c1c 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/presenter/P2PReceiverPresenter.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/presenter/P2PReceiverPresenter.java @@ -21,7 +21,7 @@ import org.smartregister.p2p.authorizer.P2PAuthorizationService; import org.smartregister.p2p.callback.SyncFinishedCallback; import org.smartregister.p2p.contract.P2pModeSelectContract; -import org.smartregister.p2p.dialog.SyncProgressDialog; +import org.smartregister.p2p.dialog.SyncProgressFragment; import org.smartregister.p2p.fragment.SyncCompleteTransferFragment; import org.smartregister.p2p.handler.OnActivityRequestPermissionHandler; import org.smartregister.p2p.model.AppDatabase; @@ -369,6 +369,11 @@ public void disconnectAndReset(@NonNull String endpointId) { disconnectAndReset(endpointId, true); } + @Override + public void startTransfer() { + + } + private void checkIfDeviceKeyHasChanged(@NonNull final Map basicDeviceDetails, final @NonNull String endpointId) { Tasker.run(new Callable() { @Override @@ -564,9 +569,9 @@ public void onConnectionAuthorized() { view.showToast(String.format(view.getContext().getString(R.string.you_are_connected_to_sender), currentSender.getEndpointName()) , Toast.LENGTH_LONG); - view.showSyncProgressDialog(view.getString(R.string.receiving_data), new SyncProgressDialog.SyncProgressDialogCallback() { + view.showSyncProgressFragment(view.getString(R.string.receiving_data), new SyncProgressFragment.SyncProgressDialogCallback() { @Override - public void onCancelClicked(@NonNull DialogInterface dialogInterface) { + public void onCancelClicked() { if (interactor.getCurrentEndpoint() != null) { onSyncFailed(new Exception("User cancelled sync process")); } else { diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/presenter/P2PSenderPresenter.java b/p2p-sync/src/main/java/org/smartregister/p2p/presenter/P2PSenderPresenter.java index 55dd508..1005031 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/presenter/P2PSenderPresenter.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/presenter/P2PSenderPresenter.java @@ -25,7 +25,7 @@ import org.smartregister.p2p.callback.OnResultCallback; import org.smartregister.p2p.callback.SyncFinishedCallback; import org.smartregister.p2p.contract.P2pModeSelectContract; -import org.smartregister.p2p.dialog.SyncProgressDialog; +import org.smartregister.p2p.dialog.SyncProgressFragment; import org.smartregister.p2p.fragment.SyncCompleteTransferFragment; import org.smartregister.p2p.handler.OnActivityRequestPermissionHandler; import org.smartregister.p2p.model.DataType; @@ -537,13 +537,16 @@ private void resetState() { @Override public void onConnectionAuthorized() { connectionLevel = ConnectionLevel.AUTHORIZED; + startTransfer(); + } + public void startTransfer() { // Send the hash key sendBasicDeviceDetails(); - view.showSyncProgressDialog(view.getString(R.string.sending_data), new SyncProgressDialog.SyncProgressDialogCallback() { + view.showSyncProgressFragment(view.getString(R.string.sending_data), new SyncProgressFragment.SyncProgressDialogCallback() { @Override - public void onCancelClicked(@NonNull DialogInterface dialogInterface) { + public void onCancelClicked() { if (interactor.getCurrentEndpoint() != null) { errorOccurredSync(new Exception("User cancelled sync process")); } else { diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/sync/handler/SyncReceiverHandler.java b/p2p-sync/src/main/java/org/smartregister/p2p/sync/handler/SyncReceiverHandler.java index 7b490c1..4fa80ba 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/sync/handler/SyncReceiverHandler.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/sync/handler/SyncReceiverHandler.java @@ -78,6 +78,13 @@ public void onPayloadTransferUpdate(@NonNull String endpointId, @NonNull Payload finishProcessingData(endpointId, payloadId); sendPayloadReceived(payloadId); } + } else if (update.getStatus() == PayloadTransferUpdate.Status.IN_PROGRESS) { + long payloadId = update.getPayloadId(); + SyncPackageManifest syncPackageManifest = awaitingPayloadManifests.get(payloadId); + if (syncPackageManifest != null) { + receiverPresenter.getView().updateProgressDialog( + ((int) update.getBytesTransferred())/syncPackageManifest.getRecordsSize()); + } } } @@ -89,7 +96,7 @@ public void processManifest(@NonNull String endpointId, @NonNull Payload payload awaitingManifestReceipt = false; receiverPresenter.getView().updateProgressDialog(String.format(receiverPresenter.getView().getString(R.string.receiving_progress_text) - , syncPackageManifest.getRecordsSize(), syncPackageManifest.getDataType().getName()), ""); + , syncPackageManifest.getRecordsSize()), ""); } catch (JsonParseException e) { Timber.e(e, receiverPresenter.getView().getString(R.string.log_received_invalid_manifest_from_endpoint), endpointId); } diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/sync/handler/SyncSenderHandler.java b/p2p-sync/src/main/java/org/smartregister/p2p/sync/handler/SyncSenderHandler.java index 6a1aeb2..68d4289 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/sync/handler/SyncSenderHandler.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/sync/handler/SyncSenderHandler.java @@ -259,6 +259,7 @@ public void run() { uiHandler.post(new Runnable() { @Override public void run() { + presenter.getView().updateProgressDialog(-1); presenter.getView().updateProgressDialog(String.format(presenter.getView().getString(R.string.sending_progress_text), awaitingDataTypeRecordsBatchSize, awaitingDataTypeName), ""); } }); @@ -293,7 +294,9 @@ public void run() { uiHandler.post(new Runnable() { @Override public void run() { - presenter.getView().updateProgressDialog(String.format("Sending %,d %ss", awaitingDataTypeRecordsBatchSize, awaitingDataTypeName), ""); + presenter.getView().updateProgressDialog(-1); + presenter.getView().updateProgressDialog(String.format(presenter.getView().getString(R.string.sending_progress_text) + , awaitingDataTypeRecordsBatchSize), ""); } }); } @@ -376,6 +379,14 @@ public void onPayloadTransferUpdate(@NonNull final PayloadTransferUpdate update) } } else if (update.getStatus() == PayloadTransferUpdate.Status.CANCELED) { presenter.errorOccurredSync(new Exception("Payload sending has been cancelled")); + } else if (update.getStatus() == PayloadTransferUpdate.Status.IN_PROGRESS) { + // I should update them here + if (awaitingBytes != null) { + int maxSize = awaitingBytes.length; + int transferredSize = (int) update.getBytesTransferred(); + + presenter.getView().updateProgressDialog(transferredSize/maxSize); + } } } } diff --git a/p2p-sync/src/main/java/org/smartregister/p2p/util/SyncDataConverterUtil.java b/p2p-sync/src/main/java/org/smartregister/p2p/util/SyncDataConverterUtil.java index 9f01603..367bd46 100644 --- a/p2p-sync/src/main/java/org/smartregister/p2p/util/SyncDataConverterUtil.java +++ b/p2p-sync/src/main/java/org/smartregister/p2p/util/SyncDataConverterUtil.java @@ -36,15 +36,18 @@ public static String readInputStreamAsString(InputStream in) @NonNull public static String generateSummaryReport(@NonNull Context context, @Nullable HashMap transferItems) { String transferSummary = context.getString(R.string.transfer_summary_content); + if (transferItems != null) { StringBuilder stringBuilder = new StringBuilder(); + int total = 0; for (String key: transferItems.keySet()) { - stringBuilder.append(String.format(Locale.US, "\n%s: %,d records", key, transferItems.get(key))); + total += transferItems.get(key); + } - return String.format(transferSummary, stringBuilder.toString()); + return String.format(transferSummary, String.format(Locale.US, "\n%,d records", total)); } - return String.format(transferSummary, "\n0 Items"); + return String.format(transferSummary, "\n0 records transferred"); } } diff --git a/p2p-sync/src/main/res/drawable-hdpi/ic_icon_share.png b/p2p-sync/src/main/res/drawable-hdpi/ic_icon_share.png new file mode 100755 index 0000000000000000000000000000000000000000..8424fa71c249545f0a1f39f7b0b550031b49baa9 GIT binary patch literal 2954 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 literal 0 HcmV?d00001 diff --git a/p2p-sync/src/main/res/drawable-xhdpi/ic_icon_share.png b/p2p-sync/src/main/res/drawable-xhdpi/ic_icon_share.png new file mode 100755 index 0000000000000000000000000000000000000000..4caa7c1eabe7687ae70855ff6f1ea67cb48dd38c GIT binary patch literal 4416 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 literal 0 HcmV?d00001 diff --git a/p2p-sync/src/main/res/drawable-xxhdpi/ic_icon_share.png b/p2p-sync/src/main/res/drawable-xxhdpi/ic_icon_share.png new file mode 100755 index 0000000000000000000000000000000000000000..96c3e6f815a3f669b3bc398657fe36740ab2dafd GIT binary patch literal 7617 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 LseYxdBj!H - + - + android:layout_height="wrap_content" + android:layout_centerInParent="true" + android:orientation="vertical"> + + + + + + - + android:layout_alignParentRight="true" + android:layout_alignParentBottom="true" + android:layout_marginRight="20dp" + android:layout_marginBottom="20dp" + android:text="@string/skip" /> - \ No newline at end of file + \ No newline at end of file diff --git a/p2p-sync/src/main/res/layout/dialog_qr_code_scanning.xml b/p2p-sync/src/main/res/layout/dialog_qr_code_scanning.xml index 66aa71c..bb8ca3a 100644 --- a/p2p-sync/src/main/res/layout/dialog_qr_code_scanning.xml +++ b/p2p-sync/src/main/res/layout/dialog_qr_code_scanning.xml @@ -1,21 +1,36 @@ - + android:layout_height="match_parent"> - + android:orientation="vertical" + android:layout_centerInParent="true"> - + + + + + +