diff --git a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ClientGiniCaptureFragment.kt b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ClientGiniCaptureFragment.kt index df84efb6c4..4cbf56c233 100644 --- a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ClientGiniCaptureFragment.kt +++ b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ClientGiniCaptureFragment.kt @@ -13,6 +13,7 @@ import net.gini.android.bank.sdk.capture.CaptureFlowFragmentListener import net.gini.android.bank.sdk.capture.CaptureResult import net.gini.android.bank.sdk.capture.ResultError import net.gini.android.bank.sdk.exampleapp.R +import net.gini.android.bank.sdk.exampleapp.core.ExampleUtil.isIntentActionViewOrSend import net.gini.android.bank.sdk.exampleapp.core.PermissionHandler import net.gini.android.capture.CaptureSDKResultError import net.gini.android.capture.DocumentImportEnabledFileTypes @@ -142,21 +143,21 @@ class ClientGiniCaptureFragment : else -> {} } -// if (isIntentActionViewOrSend(requireActivity().intent)) { -// requireActivity().finish() -// } + if (isIntentActionViewOrSend(requireActivity().intent)) { + requireActivity().finish() + } } CaptureResult.Empty -> { -// if (isIntentActionViewOrSend(requireActivity().intent)) { -// requireActivity().finish() -// } + if (isIntentActionViewOrSend(requireActivity().intent)) { + requireActivity().finish() + } } CaptureResult.Cancel -> { -// if (isIntentActionViewOrSend(requireActivity().intent)) { -// requireActivity().finish() -// } + if (isIntentActionViewOrSend(requireActivity().intent)) { + requireActivity().finish() + } } CaptureResult.EnterManually -> { @@ -165,9 +166,9 @@ class ClientGiniCaptureFragment : "Scan exited for manual enter mode", Toast.LENGTH_SHORT ).show() -// if (isIntentActionViewOrSend(requireActivity().intent)) { -// requireActivity().finish() -// } + if (isIntentActionViewOrSend(requireActivity().intent)) { + requireActivity().finish() + } } } } @@ -178,7 +179,6 @@ class ClientGiniCaptureFragment : } - } diff --git a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/MainActivity.kt b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/MainActivity.kt index 621c2dab70..173d73c178 100644 --- a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/MainActivity.kt +++ b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/MainActivity.kt @@ -21,7 +21,6 @@ import net.gini.android.bank.sdk.exampleapp.core.PermissionHandler import net.gini.android.bank.sdk.exampleapp.databinding.ActivityMainBinding import net.gini.android.bank.sdk.exampleapp.ui.data.Configuration import net.gini.android.capture.EntryPoint -import net.gini.android.capture.requirements.RequirementsReport import net.gini.android.capture.util.CancellationToken @@ -215,26 +214,6 @@ class MainActivity : AppCompatActivity() { configurationViewModel.configureGiniBank(this) } - private fun showUnfulfilledRequirementsToast(report: RequirementsReport) { - val stringBuilder = StringBuilder() - val requirementReports = report.requirementReports - for (i in requirementReports.indices) { - val requirementReport = requirementReports[i] - if (!requirementReport.isFulfilled) { - if (stringBuilder.isNotEmpty()) { - stringBuilder.append("\n") - } - stringBuilder.append(requirementReport.requirementId) - if (requirementReport.details.isNotEmpty()) { - stringBuilder.append(": ") - stringBuilder.append(requirementReport.details) - } - } - } - Toast.makeText( - this, "Requirements not fulfilled:\n$stringBuilder", Toast.LENGTH_LONG - ).show() - } override fun onActivityResult( requestCode: Int, resultCode: Int, data: Intent? diff --git a/capture-sdk/sdk/src/main/AndroidManifest.xml b/capture-sdk/sdk/src/main/AndroidManifest.xml index 811bfcb57e..6e6e27309f 100644 --- a/capture-sdk/sdk/src/main/AndroidManifest.xml +++ b/capture-sdk/sdk/src/main/AndroidManifest.xml @@ -5,11 +5,6 @@ - + * Interface used by {@link NoResultsFragmentCompat} and {@link ErrorFragment} to dispatch events to the hosting Activity. + *

+ */ +public interface EnterManuallyButtonListener { + + + /** + *

+ * Called when the button on the bottom of the No Results/Error Screen was pressed. This button + * should lead the user to the manual data input form/site. + *

+ */ + void onEnterManuallyPressed(); +} diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/GiniCapture.java b/capture-sdk/sdk/src/main/java/net/gini/android/capture/GiniCapture.java index e77606d795..bae75c3282 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/GiniCapture.java +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/GiniCapture.java @@ -664,30 +664,30 @@ public static GiniCaptureFragment createGiniCaptureFragment() { return GiniCaptureFragment.Companion.createInstance(null); } - public CancellationToken createGiniCaptureFragmentForIntent(Context context, Intent intent, TheCallback the) { + public CancellationToken createGiniCaptureFragmentForIntent(Context context, Intent intent, GiniCaptureIntentCallback captureIntentCallback) { return createIntentForImportedFiles(intent, context, new AsyncCallback() { @Override public void onSuccess(Intent result) { if (result.getComponent().getClassName().equals(AnalysisActivity.class.getName())) { - the.callback(new CreateCaptureFlowFragmentForIntentResult.Success(GiniCaptureFragment.Companion.createInstance(result))); + captureIntentCallback.callback(new CreateCaptureFlowFragmentForIntentResult.Success(GiniCaptureFragment.Companion.createInstance(result))); } else { - the.callback(new CreateCaptureFlowFragmentForIntentResult.Error(new ImportedFileValidationException("Unknown activity class: ${result.component?.className}"))); + captureIntentCallback.callback(new CreateCaptureFlowFragmentForIntentResult.Error(new ImportedFileValidationException("Unknown activity class: ${result.component?.className}"))); } } @Override public void onError(ImportedFileValidationException exception) { - the.callback(new CreateCaptureFlowFragmentForIntentResult.Error(exception)); + captureIntentCallback.callback(new CreateCaptureFlowFragmentForIntentResult.Error(exception)); } @Override public void onCancelled() { - the.callback(new CreateCaptureFlowFragmentForIntentResult.Cancelled()); + captureIntentCallback.callback(new CreateCaptureFlowFragmentForIntentResult.Cancelled()); } }); } - interface TheCallback { + interface GiniCaptureIntentCallback { void callback(CreateCaptureFlowFragmentForIntentResult result); } diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/GiniCaptureFragment.kt b/capture-sdk/sdk/src/main/java/net/gini/android/capture/GiniCaptureFragment.kt index ac0e7882a5..fe406bcc6c 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/GiniCaptureFragment.kt +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/GiniCaptureFragment.kt @@ -19,6 +19,7 @@ import net.gini.android.capture.camera.CameraFragmentListener import net.gini.android.capture.document.GiniCaptureDocumentError import net.gini.android.capture.document.GiniCaptureMultiPageDocument import net.gini.android.capture.document.QRCodeDocument +import net.gini.android.capture.error.ErrorFragment import net.gini.android.capture.network.model.GiniCaptureCompoundExtraction import net.gini.android.capture.network.model.GiniCaptureReturnReason import net.gini.android.capture.network.model.GiniCaptureSpecificExtraction @@ -30,7 +31,8 @@ class GiniCaptureFragment(private val analysisIntent: Intent? = null) : Fragment(), CameraFragmentListener, MultiPageReviewFragmentListener, - AnalysisFragmentListener { + AnalysisFragmentListener, + EnterManuallyButtonListener { internal companion object { fun createInstance(intent: Intent? = null): GiniCaptureFragment { @@ -76,7 +78,7 @@ class GiniCaptureFragment(private val analysisIntent: Intent? = null) : } override fun onCreate(savedInstanceState: Bundle?) { - childFragmentManager.fragmentFactory = CaptureFragmentFactory(this, this, this) + childFragmentManager.fragmentFactory = CaptureFragmentFactory(this, this, this, this) super.onCreate(savedInstanceState) } @@ -219,12 +221,17 @@ class GiniCaptureFragment(private val analysisIntent: Intent? = null) : // TODO("Not yet implemented") } + override fun onEnterManuallyPressed() { + giniCaptureFragmentListener.onFinishedWithResult(CaptureSDKResult.EnterManually) + } + } class CaptureFragmentFactory( private val cameraListener: CameraFragmentListener, private val multiPageReviewFragmentListener: MultiPageReviewFragmentListener, - private val analysisFragmentListener: AnalysisFragmentListener + private val analysisFragmentListener: AnalysisFragmentListener, + private val enterManuallyButtonListener: EnterManuallyButtonListener ) : FragmentFactory() { override fun instantiate(classLoader: ClassLoader, className: String): Fragment { when (className) { @@ -245,6 +252,11 @@ class CaptureFragmentFactory( analysisFragmentListener ) } + ErrorFragment::class.java.name -> return ErrorFragment().apply { + setListener( + enterManuallyButtonListener + ) + } else -> return super.instantiate(classLoader, className) } diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/ImageRetakeOptionsListener.java b/capture-sdk/sdk/src/main/java/net/gini/android/capture/ImageRetakeOptionsListener.java deleted file mode 100644 index 319b0553a6..0000000000 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/ImageRetakeOptionsListener.java +++ /dev/null @@ -1,27 +0,0 @@ -package net.gini.android.capture; - -import net.gini.android.capture.noresults.NoResultsFragmentCompat; - -/** - *

- * Interface used by {@link NoResultsFragmentCompat} and (@link ErrorFragmentCompat} to dispatch events to the hosting Activity. - *

- */ -public interface ImageRetakeOptionsListener { - - /** - *

- * Called when the button on the bottom of the No Results/Error Screen was pressed. This button - * should lead the user back to the Camera Screen. - *

- */ - void onBackToCameraPressed(); - - /** - *

- * Called when the button on the bottom of the No Results/Error Screen was pressed. This button - * should lead the user to the manual data input form/site. - *

- */ - void onEnterManuallyPressed(); -} diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisActivity.java b/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisActivity.java index 727ecc5a8a..51aa37531c 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisActivity.java +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisActivity.java @@ -3,7 +3,12 @@ import android.content.Intent; import android.os.Bundle; import android.view.MenuItem; -import android.view.View; + +import androidx.activity.OnBackPressedCallback; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import androidx.appcompat.app.AppCompatActivity; import net.gini.android.capture.Document; import net.gini.android.capture.GiniCapture; @@ -21,15 +26,8 @@ import java.util.List; import java.util.Map; -import androidx.activity.OnBackPressedCallback; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; -import androidx.appcompat.app.AppCompatActivity; - import static net.gini.android.capture.camera.CameraActivity.RESULT_CAMERA_SCREEN; import static net.gini.android.capture.camera.CameraActivity.RESULT_ENTER_MANUALLY; -import static net.gini.android.capture.error.ErrorActivity.ERROR_SCREEN_REQUEST; import static net.gini.android.capture.internal.util.ActivityHelper.enableHomeAsUp; import static net.gini.android.capture.internal.util.ActivityHelper.interceptOnBackPressed; import static net.gini.android.capture.noresults.NoResultsActivity.NO_RESULT_CANCEL_KEY; @@ -252,7 +250,7 @@ public void onDefaultPDFAppAlertDialogCancelled() { @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { - if ((requestCode == NO_RESULT_REQUEST || requestCode == ERROR_SCREEN_REQUEST) && + if ((requestCode == NO_RESULT_REQUEST) && ((resultCode == RESULT_CANCELED && data != null && data.hasExtra(NO_RESULT_CANCEL_KEY)) || resultCode == RESULT_ENTER_MANUALLY || resultCode == RESULT_CAMERA_SCREEN)) { if (resultCode == RESULT_CAMERA_SCREEN) { if (GiniCapture.hasInstance()) { diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisFragmentImpl.java b/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisFragmentImpl.java index 7bb08c3e5c..7aabce684c 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisFragmentImpl.java +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisFragmentImpl.java @@ -22,6 +22,8 @@ import net.gini.android.capture.Document; import net.gini.android.capture.GiniCapture; import net.gini.android.capture.R; +import net.gini.android.capture.error.ErrorFragment; +import net.gini.android.capture.error.ErrorType; import net.gini.android.capture.internal.ui.FragmentImplCallback; import net.gini.android.capture.internal.ui.IntervalClickListener; import net.gini.android.capture.internal.util.Size; @@ -159,6 +161,22 @@ void showHints(final List hints) { mHintsAnimator.start(); } + @Override + void showError(String error, Document document) { + ErrorFragment.Companion.navigateToErrorFragment( + mFragment.findNavController(), + AnalysisFragmentCompatDirections.toErrorFragmentWithErrorMessage(error, document) + ); + } + + @Override + void showError(ErrorType errorType, Document document) { + ErrorFragment.Companion.navigateToErrorFragment( + mFragment.findNavController(), + AnalysisFragmentCompatDirections.toErrorFragmentWithErrorType(errorType, document) + ); + } + private void rotateDocumentImageView(final int rotationForDisplay) { if (rotationForDisplay == 0) { return; diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisScreenContract.java b/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisScreenContract.java index 6f04076d02..bc6c516d4b 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisScreenContract.java +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisScreenContract.java @@ -4,14 +4,17 @@ import android.content.DialogInterface; import android.graphics.Bitmap; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import net.gini.android.capture.Document; import net.gini.android.capture.GiniCaptureBasePresenter; import net.gini.android.capture.GiniCaptureBaseView; +import net.gini.android.capture.error.ErrorType; import net.gini.android.capture.internal.util.Size; import java.util.List; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import jersey.repackaged.jsr166e.CompletableFuture; /** @@ -57,6 +60,9 @@ abstract void showAlertDialog(@NonNull final String message, @Nullable final DialogInterface.OnCancelListener cancelListener); abstract void showHints(List hints); + + abstract void showError(String errorMessage, Document document); + abstract void showError(ErrorType errorType, Document document); } abstract class Presenter extends GiniCaptureBasePresenter implements diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisScreenPresenter.java b/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisScreenPresenter.java index e89ef5579a..6738c68c84 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisScreenPresenter.java +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/analysis/AnalysisScreenPresenter.java @@ -1,8 +1,6 @@ package net.gini.android.capture.analysis; import android.app.Activity; -import android.content.DialogInterface; -import android.graphics.Bitmap; import android.net.Uri; import androidx.annotation.NonNull; @@ -18,7 +16,6 @@ import net.gini.android.capture.document.GiniCaptureDocumentError; import net.gini.android.capture.document.GiniCaptureMultiPageDocument; import net.gini.android.capture.document.PdfDocument; -import net.gini.android.capture.error.ErrorActivity; import net.gini.android.capture.error.ErrorType; import net.gini.android.capture.internal.camera.photo.ParcelableMemoryCache; import net.gini.android.capture.internal.document.DocumentRenderer; @@ -53,7 +50,7 @@ /** * Created by Alpar Szotyori on 08.05.2019. - * + *

* Copyright (c) 2019 Gini GmbH. */ @@ -268,32 +265,17 @@ String getPdfFilename(final PdfDocument pdfDocument) { @VisibleForTesting void analyzeDocument() { showAlertIfOpenWithDocumentAndAppIsDefault(mMultiPageDocument, - new FileImportHelper.ShowAlertCallback() { - @Override - public void showAlertDialog(@NonNull final String message, - @NonNull final String positiveButtonTitle, - @NonNull final DialogInterface.OnClickListener - positiveButtonClickListener, - @Nullable final String negativeButtonTitle, - @Nullable final DialogInterface.OnClickListener - negativeButtonClickListener, - @Nullable final DialogInterface.OnCancelListener cancelListener) { - getView().showAlertDialog(message, positiveButtonTitle, - positiveButtonClickListener, negativeButtonTitle, - negativeButtonClickListener, cancelListener); - } - }) - .handle(new CompletableFuture.BiFun() { - @Override - public Void apply(final Void aVoid, final Throwable throwable) { - if (throwable != null) { - getAnalysisFragmentListenerOrNoOp() - .onDefaultPDFAppAlertDialogCancelled(); - } else { - showErrorIfAvailableAndAnalyzeDocument(); - } - return null; + (message, positiveButtonTitle, positiveButtonClickListener, negativeButtonTitle, negativeButtonClickListener, cancelListener) -> getView().showAlertDialog(message, positiveButtonTitle, + positiveButtonClickListener, negativeButtonTitle, + negativeButtonClickListener, cancelListener)) + .handle((CompletableFuture.BiFun) (aVoid, throwable) -> { + if (throwable != null) { + getAnalysisFragmentListenerOrNoOp() + .onDefaultPDFAppAlertDialogCancelled(); + } else { + showErrorIfAvailableAndAnalyzeDocument(); } + return null; }); } @@ -432,21 +414,17 @@ private void showPdfInfoForPdfDocument() { private void showDocument() { LOG.debug("Rendering the document"); mDocumentRenderer.toBitmap(getActivity(), getView().getPdfPreviewSize(), - new DocumentRenderer.Callback() { - @Override - public void onBitmapReady(@Nullable final Bitmap bitmap, - final int rotationForDisplay) { - LOG.debug("Document rendered"); - if (isStopped()) { - return; - } - - if (mMultiPageDocument.getType() == Document.Type.IMAGE_MULTI_PAGE || mMultiPageDocument.getType() == Document.Type.IMAGE) { - return; - } + (bitmap, rotationForDisplay) -> { + LOG.debug("Document rendered"); + if (isStopped()) { + return; + } - getView().showBitmap(bitmap, rotationForDisplay); + if (mMultiPageDocument.getType() == Document.Type.IMAGE_MULTI_PAGE || mMultiPageDocument.getType() == Document.Type.IMAGE) { + return; } + + getView().showBitmap(bitmap, rotationForDisplay); }); } @@ -463,7 +441,7 @@ private void showErrorIfAvailableAndAnalyzeDocument() { } } - ErrorActivity.startErrorActivity(getActivity(), mDocumentAnalysisErrorMessage, mMultiPageDocument); + getView().showError(mDocumentAnalysisErrorMessage, mMultiPageDocument); } else { doAnalyzeDocument(); } @@ -482,6 +460,6 @@ private void handleAnalysisError(final Throwable throwable) { } else { errorType = ErrorType.GENERAL; } - ErrorActivity.startErrorActivity(getActivity(), errorType, mMultiPageDocument); + getView().showError(errorType, mMultiPageDocument); } } diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/camera/CameraActivity.java b/capture-sdk/sdk/src/main/java/net/gini/android/capture/camera/CameraActivity.java index 34a93f7a86..c23d2040ec 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/camera/CameraActivity.java +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/camera/CameraActivity.java @@ -33,7 +33,6 @@ import java.util.Map; import static net.gini.android.capture.analysis.AnalysisActivity.RESULT_NO_EXTRACTIONS; -import static net.gini.android.capture.error.ErrorActivity.ERROR_SCREEN_REQUEST; import static net.gini.android.capture.internal.util.ActivityHelper.interceptOnBackPressed; import static net.gini.android.capture.internal.util.FeatureConfiguration.shouldShowOnboarding; import static net.gini.android.capture.internal.util.FeatureConfiguration.shouldShowOnboardingAtFirstRun; @@ -357,7 +356,6 @@ protected void onActivityResult(final int requestCode, final int resultCode, case REVIEW_DOCUMENT_REQUEST: case ANALYSE_DOCUMENT_REQUEST: case MULTI_PAGE_REVIEW_REQUEST: - case ERROR_SCREEN_REQUEST: case NO_RESULT_REQUEST: // The first CameraActivity instance is invisible to the user // after we navigate to the review or analysis activity. diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/camera/CameraFragmentImpl.java b/capture-sdk/sdk/src/main/java/net/gini/android/capture/camera/CameraFragmentImpl.java index 9dcc931569..600ee42fae 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/camera/CameraFragmentImpl.java +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/camera/CameraFragmentImpl.java @@ -47,9 +47,8 @@ import net.gini.android.capture.document.ImageDocument; import net.gini.android.capture.document.ImageMultiPageDocument; import net.gini.android.capture.document.QRCodeDocument; -import net.gini.android.capture.error.ErrorActivity; +import net.gini.android.capture.error.ErrorFragment; import net.gini.android.capture.error.ErrorType; -import net.gini.android.capture.help.HelpFragment; import net.gini.android.capture.internal.camera.api.CameraException; import net.gini.android.capture.internal.camera.api.CameraInterface; import net.gini.android.capture.internal.camera.api.OldCameraController; @@ -336,6 +335,7 @@ public void onCreate(final Bundle savedInstanceState) { if (savedInstanceState != null) { restoreSavedState(savedInstanceState); } + } private void initFlashState() { @@ -1016,9 +1016,15 @@ private void handleAnalysisError(Throwable throwable, Document document) { final FailureException failureException = FailureException.tryCastFromCompletableFutureThrowable(throwable); trackAnalysisScreenEvent(AnalysisScreenEvent.ERROR); if (failureException != null) { - ErrorActivity.startErrorActivity(mFragment.getActivity(), failureException.getErrorType(), document); + ErrorFragment.Companion.navigateToErrorFragment( + mFragment.findNavController(), + CameraFragmentDirections.toErrorFragment(failureException.getErrorType(), document) + ); } else { - ErrorActivity.startErrorActivity(mFragment.getActivity(), ErrorType.GENERAL, document); + ErrorFragment.Companion.navigateToErrorFragment( + mFragment.findNavController(), + CameraFragmentDirections.toErrorFragment(ErrorType.GENERAL, document) + ); } } diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorActivity.kt b/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorActivity.kt deleted file mode 100644 index 1bf011d81f..0000000000 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorActivity.kt +++ /dev/null @@ -1,172 +0,0 @@ -package net.gini.android.capture.error - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import android.os.Parcelable -import android.view.MenuItem -import androidx.activity.OnBackPressedCallback -import androidx.appcompat.app.AppCompatActivity -import net.gini.android.capture.* -import net.gini.android.capture.camera.CameraActivity.RESULT_CAMERA_SCREEN -import net.gini.android.capture.camera.CameraActivity.RESULT_ENTER_MANUALLY -import net.gini.android.capture.internal.ui.IntervalClickListener -import net.gini.android.capture.internal.util.ActivityHelper -import net.gini.android.capture.noresults.NoResultsActivity -import net.gini.android.capture.noresults.NoResultsActivity.EXTRA_IN_DOCUMENT -import net.gini.android.capture.view.InjectedViewAdapterHolder -import net.gini.android.capture.view.InjectedViewContainer -import net.gini.android.capture.view.NavButtonType -import net.gini.android.capture.view.NavigationBarTopAdapter - -/** - * Internal use only - */ -class ErrorActivity : AppCompatActivity(), - ImageRetakeOptionsListener, ErrorFragmentListener { - - private var mDocument: Document? = null - private var mErrorType: ErrorType? = null - private var mCustomError: String? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.gc_activity_error) - - readExtras() - - setInjectedTopBarContainer() - if (savedInstanceState == null) { - initFragment() - } - - handleOnBackPressed() - } - - private fun setInjectedTopBarContainer() { - val topBarContainer = - findViewById>(R.id.gc_injected_navigation_bar_container_top) - if (GiniCapture.hasInstance()) { - topBarContainer.injectedViewAdapterHolder = InjectedViewAdapterHolder(GiniCapture.getInstance().internal().navigationBarTopAdapterInstance) { injectedViewAdapter -> - injectedViewAdapter.apply { - setTitle(getString(R.string.gc_title_error)) - - setNavButtonType(NavButtonType.CLOSE) - setOnNavButtonClickListener(IntervalClickListener { - onBackPressed() - }) - } - } - } - } - - override fun onBackToCameraPressed() { - setResult(RESULT_CAMERA_SCREEN) - finish() - } - - override fun onEnterManuallyPressed() { - setResult(RESULT_ENTER_MANUALLY) - finish() - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - if (item.itemId == android.R.id.home) { - finish() - return true - } - return super.onOptionsItemSelected(item) - } - - private fun initFragment() { - val errorFragment = ErrorFragmentCompat.createInstance(mErrorType, mDocument, mCustomError) - supportFragmentManager - .beginTransaction() - .add(R.id.gc_fragment_error, errorFragment) - .commit() - } - - private fun readExtras() { - val extras = intent.extras - if (extras != null) { - mDocument = extras.getParcelable(NoResultsActivity.EXTRA_IN_DOCUMENT) - mErrorType = extras.getSerializable(EXTRA_IN_ERROR) as? ErrorType - mCustomError = extras.getString(EXTRA_ERROR_STRING) - } - } - - private fun handleOnBackPressed() { - ActivityHelper.interceptOnBackPressed(this, object : OnBackPressedCallback(true) { - override fun handleOnBackPressed() { - val noResultsIntent = Intent() - noResultsIntent.putExtra(NoResultsActivity.NO_RESULT_CANCEL_KEY, true) - setResult(RESULT_CANCELED, noResultsIntent) - finish() - } - }) - } - - override fun onDestroy() { - super.onDestroy() - isActivityShown = false - } - - override fun onError(error: GiniCaptureError) { - val result = Intent() - result.putExtra(EXTRA_OUT_ERROR, error) - setResult(RESULT_ERROR, result) - finish() - } - - companion object { - /** - * Internal use only. - * - * @suppress - */ - const val ERROR_REQUEST = 999 - - const val ERROR_SCREEN_REQUEST = 111 - - const val EXTRA_IN_ERROR = "GC_EXTRA_IN_ERROR" - - const val EXTRA_OUT_ERROR = "GC_EXTRA_OUT_ERROR" - - const val EXTRA_ERROR_STRING = "GC_EXTRA_ERROR_STRING" - - const val RESULT_ERROR = RESULT_FIRST_USER + 1 - - var isActivityShown: Boolean = false - - @JvmStatic - fun startErrorActivity(context: Activity, errorType: ErrorType, document: Parcelable?) { - - //Error activity is already shown don't start new one - if (isActivityShown) - return - - isActivityShown = true - - val intent = Intent(context, ErrorActivity::class.java) - intent.putExtra(EXTRA_IN_ERROR, errorType) - intent.putExtra(EXTRA_IN_DOCUMENT, document) - context.startActivityForResult(intent, ERROR_SCREEN_REQUEST) - } - - @JvmStatic - fun startErrorActivity(context: Activity, errorMessage: String, document: Parcelable?) { - - //Error activity is already shown don't start new one - if (isActivityShown) - return - - isActivityShown = true - - val intent = Intent(context, ErrorActivity::class.java) - intent.putExtra(EXTRA_ERROR_STRING, errorMessage) - intent.putExtra(EXTRA_IN_DOCUMENT, document) - context.startActivityForResult(intent, ERROR_SCREEN_REQUEST) - } - - } -} diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentCompat.kt b/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragment.kt similarity index 54% rename from capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentCompat.kt rename to capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragment.kt index 2f84d06de0..b9a3178049 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentCompat.kt +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragment.kt @@ -7,10 +7,11 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.navigation.NavController +import androidx.navigation.NavDirections import androidx.navigation.fragment.NavHostFragment import net.gini.android.capture.Document -import net.gini.android.capture.GiniCapture -import net.gini.android.capture.GiniCaptureError +import net.gini.android.capture.EnterManuallyButtonListener +import net.gini.android.capture.R import net.gini.android.capture.internal.ui.FragmentImplCallback import net.gini.android.capture.internal.util.AlertDialogHelperCompat @@ -32,22 +33,19 @@ import net.gini.android.capture.internal.util.AlertDialogHelperCompat * Your Activity is automatically set as the listener in {@link ErrorFragmentCompat#onCreate(Bundle)}. *

*/ -class ErrorFragmentCompat : Fragment(), FragmentImplCallback { +class ErrorFragment : Fragment(), FragmentImplCallback, + EnterManuallyButtonListener { private lateinit var fragmentImpl: ErrorFragmentImpl - private var errorListener: ErrorFragmentListener? = null + private lateinit var listener: EnterManuallyButtonListener override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - fragmentImpl = ErrorFragmentHelper.createFragmentImpl(this, arguments) - activity?.let { - ErrorFragmentHelper.setListener(fragmentImpl, it) - if (it is ErrorFragmentListener) errorListener = it - } + fragmentImpl = createFragmentImpl(this, arguments) + fragmentImpl.setListener(listener) fragmentImpl.onCreate(savedInstanceState) - checkGiniCaptureInstance() } override fun onCreateView( @@ -58,6 +56,13 @@ class ErrorFragmentCompat : Fragment(), FragmentImplCallback { return fragmentImpl.onCreateView(inflater, container, savedInstanceState) } + fun setListener( + listener: EnterManuallyButtonListener + ) { + this.listener = listener + + } + override fun showAlertDialog( message: String, positiveButtonTitle: String, @@ -67,8 +72,15 @@ class ErrorFragmentCompat : Fragment(), FragmentImplCallback { cancelListener: DialogInterface.OnCancelListener? ) { activity?.let { - AlertDialogHelperCompat.showAlertDialog(it, message, positiveButtonTitle, - positiveButtonClickListener, negativeButtonTitle, negativeButtonClickListener, cancelListener) + AlertDialogHelperCompat.showAlertDialog( + it, + message, + positiveButtonTitle, + positiveButtonClickListener, + negativeButtonTitle, + negativeButtonClickListener, + cancelListener + ) } } @@ -76,30 +88,39 @@ class ErrorFragmentCompat : Fragment(), FragmentImplCallback { return NavHostFragment.findNavController(this) } - private fun checkGiniCaptureInstance() { - if (!GiniCapture.hasInstance()) { - errorListener?.onError(GiniCaptureError( - GiniCaptureError.ErrorCode.MISSING_GINI_CAPTURE_INSTANCE, - "Missing GiniCapture instance. It was not created or there was an application process restart." - )) - } + fun createFragmentImpl( + fragment: FragmentImplCallback, + arguments: Bundle? + ): ErrorFragmentImpl { + val document = arguments?.getParcelable(ARGS_DOCUMENT) + val error = arguments?.getSerializable(ARGS_ERROR) as? ErrorType + val customError = arguments?.getString(ARGS_CUSTOM_ERROR) + return ErrorFragmentImpl(fragment, document, error, customError) } companion object { - /** - * - * - * Factory method for creating a new instance of the Fragment. - * - * - * @param document a [Document] for which no valid extractions were received - * - * @return a new instance of the Fragment - */ - fun createInstance(errorType: ErrorType?, document: Document?, customError: String?): ErrorFragmentCompat { - val fragment = ErrorFragmentCompat() - fragment.arguments = ErrorFragmentHelper.createArguments(errorType, document, customError) - return fragment + private const val ARGS_ERROR = "GC_ARGS_ERROR" + private const val ARGS_DOCUMENT = "ARGS_DOCUMENT" + private const val ARGS_CUSTOM_ERROR = "ARGS_CUSTOM_ERROR" + + + fun navigateToErrorFragment( + navController: NavController, + direction: NavDirections + ) { + if (navController.currentDestination?.id == R.id.gc_destination_error_fragment) { + return + } + navController.navigate(direction) } + + + } + + + override fun onEnterManuallyPressed() { + } + + } diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentHelper.kt b/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentHelper.kt deleted file mode 100644 index e9d1a784c7..0000000000 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentHelper.kt +++ /dev/null @@ -1,52 +0,0 @@ -package net.gini.android.capture.error - -import android.content.Context -import android.os.Bundle -import net.gini.android.capture.Document -import net.gini.android.capture.internal.ui.FragmentImplCallback -import net.gini.android.capture.ImageRetakeOptionsListener - -/** - * Helper class for setting arguments to error fragment. - * Internal use only. - */ -class ErrorFragmentHelper { - - companion object { - private const val ARGS_ERROR = "GC_ARGS_ERROR" - private const val ARGS_DOCUMENT = "ARGS_DOCUMENT" - private const val ARGS_CUSTOM_ERROR = "ARGS_CUSTOM_ERROR" - - - fun createArguments(errorType: ErrorType?, document: Document?, customError: String?): Bundle { - val arguments = Bundle() - arguments.putSerializable(ARGS_ERROR, errorType) - arguments.putParcelable(ARGS_DOCUMENT, document) - arguments.putString(ARGS_CUSTOM_ERROR, customError) - return arguments - } - - fun createFragmentImpl( - fragment: FragmentImplCallback, - arguments: Bundle? - ): ErrorFragmentImpl { - val document = arguments?.getParcelable(ARGS_DOCUMENT) - val error = arguments?.getSerializable(ARGS_ERROR) as? ErrorType - val customError = arguments?.getString(ARGS_CUSTOM_ERROR) - return ErrorFragmentImpl(fragment, document, error, customError) - } - - fun setListener( - fragmentImpl: ErrorFragmentImpl, - context: Context - ) { - if (context is ImageRetakeOptionsListener) { - fragmentImpl.setListener(context as ImageRetakeOptionsListener) - } else { - throw IllegalStateException( - "Hosting activity must implement ImageRetakeOptionsListener." - ) - } - } - } -} diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentImpl.kt b/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentImpl.kt index fc8c0eaeeb..83f2e6c91b 100644 --- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentImpl.kt +++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/error/ErrorFragmentImpl.kt @@ -8,7 +8,7 @@ import android.widget.Button import android.widget.ImageView import android.widget.TextView import net.gini.android.capture.Document -import net.gini.android.capture.ImageRetakeOptionsListener +import net.gini.android.capture.EnterManuallyButtonListener import net.gini.android.capture.R import net.gini.android.capture.document.ImageMultiPageDocument import net.gini.android.capture.internal.ui.FragmentImplCallback @@ -28,13 +28,9 @@ class ErrorFragmentImpl( private val customError: String? ) { - private val defaultListener: ImageRetakeOptionsListener = object : - ImageRetakeOptionsListener { - override fun onBackToCameraPressed() {} - override fun onEnterManuallyPressed() {} - } + private val defaultListener: EnterManuallyButtonListener = EnterManuallyButtonListener { } - private var imageRetakeOptionsListener: ImageRetakeOptionsListener? = null + private var enterManuallyButtonListener: EnterManuallyButtonListener? = null private lateinit var retakeImagesButton: Button fun onCreate(savedInstanceState: Bundle?) { @@ -52,19 +48,22 @@ class ErrorFragmentImpl( if (shouldAllowRetakeImages()) { retakeImagesButton.setIntervalClickListener { EventTrackingHelper.trackAnalysisScreenEvent(AnalysisScreenEvent.RETRY) - imageRetakeOptionsListener?.onBackToCameraPressed() } } else { retakeImagesButton.visibility = View.GONE } val enterManuallyButton = view.findViewById(R.id.gc_button_error_enter_manually) - enterManuallyButton.setIntervalClickListener { imageRetakeOptionsListener?.onEnterManuallyPressed() } + enterManuallyButton.setIntervalClickListener { enterManuallyButtonListener?.onEnterManuallyPressed() } customError?.let { view.findViewById(R.id.gc_error_header).text = it } + view.findViewById