diff --git a/app/src/main/java/protect/card_locker/ScanActivity.kt b/app/src/main/java/protect/card_locker/ScanActivity.kt index 6625ea113..d80e94871 100644 --- a/app/src/main/java/protect/card_locker/ScanActivity.kt +++ b/app/src/main/java/protect/card_locker/ScanActivity.kt @@ -1,56 +1,46 @@ -package protect.card_locker; +package protect.card_locker -import static protect.card_locker.BarcodeSelectorActivity.BARCODE_CONTENTS; -import static protect.card_locker.BarcodeSelectorActivity.BARCODE_FORMAT; -import android.Manifest; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.graphics.Color; -import android.net.Uri; -import android.os.Bundle; -import android.provider.Settings; -import android.text.InputType; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.view.WindowManager; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.ListAdapter; -import android.widget.SimpleAdapter; -import android.widget.TextView; -import android.widget.Toast; - -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; -import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; -import androidx.appcompat.widget.Toolbar; -import androidx.core.content.ContextCompat; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.google.zxing.DecodeHintType; -import com.google.zxing.ResultPoint; -import com.google.zxing.client.android.Intents; -import com.journeyapps.barcodescanner.BarcodeCallback; -import com.journeyapps.barcodescanner.BarcodeResult; -import com.journeyapps.barcodescanner.CaptureManager; -import com.journeyapps.barcodescanner.DecoratedBarcodeView; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -import protect.card_locker.databinding.CustomBarcodeScannerBinding; -import protect.card_locker.databinding.ScanActivityBinding; +import android.Manifest +import android.content.ActivityNotFoundException +import android.content.Intent +import android.content.pm.PackageManager +import android.graphics.Color +import android.net.Uri +import android.os.Bundle +import android.provider.Settings +import android.text.InputType +import android.util.DisplayMetrics +import android.util.Log +import android.util.TypedValue +import android.view.KeyEvent +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import android.widget.EditText +import android.widget.LinearLayout +import android.widget.ListAdapter +import android.widget.SimpleAdapter +import android.widget.TextView +import android.widget.Toast +import androidx.activity.result.ActivityResultLauncher +import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AlertDialog +import androidx.core.content.ContextCompat +import androidx.core.widget.doAfterTextChanged +import androidx.core.widget.doOnTextChanged +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import com.google.zxing.DecodeHintType +import com.google.zxing.ResultPoint +import com.google.zxing.client.android.Intents +import com.journeyapps.barcodescanner.BarcodeCallback +import com.journeyapps.barcodescanner.BarcodeResult +import com.journeyapps.barcodescanner.CaptureManager +import com.journeyapps.barcodescanner.DecoratedBarcodeView +import protect.card_locker.databinding.CustomBarcodeScannerBinding +import protect.card_locker.databinding.ScanActivityBinding /** * Custom Scannner Activity extending from Activity to display a custom layout form scanner view. @@ -58,484 +48,552 @@ import protect.card_locker.databinding.ScanActivityBinding; * Based on https://github.com/journeyapps/zxing-android-embedded/blob/0fdfbce9fb3285e985bad9971c5f7c0a7a334e7b/sample/src/main/java/example/zxing/CustomScannerActivity.java * originally licensed under Apache 2.0 */ -public class ScanActivity extends CatimaAppCompatActivity { - private ScanActivityBinding binding; - private CustomBarcodeScannerBinding customBarcodeScannerBinding; - private static final String TAG = "Catima"; +class ScanActivity : CatimaAppCompatActivity() { + private lateinit var binding: ScanActivityBinding + private lateinit var customBarcodeScannerBinding: CustomBarcodeScannerBinding - private static final int MEDIUM_SCALE_FACTOR_DIP = 460; - private static final int COMPAT_SCALE_FACTOR_DIP = 320; + companion object { + private const val TAG = "Catima" - private static final int PERMISSION_SCAN_ADD_FROM_IMAGE = 100; - private static final int PERMISSION_SCAN_ADD_FROM_PDF = 101; - private static final int PERMISSION_SCAN_ADD_FROM_PKPASS = 102; + private const val MEDIUM_SCALE_FACTOR_DIP = 460 + private const val COMPAT_SCALE_FACTOR_DIP = 320 - private CaptureManager capture; - private DecoratedBarcodeView barcodeScannerView; + private const val PERMISSION_SCAN_ADD_FROM_IMAGE = 100 + private const val PERMISSION_SCAN_ADD_FROM_PDF = 101 + private const val PERMISSION_SCAN_ADD_FROM_PKPASS = 102 - private String cardId; - private String addGroup; - private boolean torch = false; - - private ActivityResultLauncher manualAddLauncher; - // can't use the pre-made contract because that launches the file manager for image type instead of gallery - private ActivityResultLauncher photoPickerLauncher; - private ActivityResultLauncher pdfPickerLauncher; - private ActivityResultLauncher pkpassPickerLauncher; - - static final String STATE_SCANNER_ACTIVE = "scannerActive"; - private boolean mScannerActive = true; - private boolean mHasError = false; - - private void extractIntentFields(Intent intent) { - final Bundle b = intent.getExtras(); - cardId = b != null ? b.getString(LoyaltyCard.BUNDLE_LOYALTY_CARD_CARD_ID) : null; - addGroup = b != null ? b.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) : null; - Log.d(TAG, "Scan activity: id=" + cardId); + private const val STATE_SCANNER_ACTIVE = "scannerActive" } - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - binding = ScanActivityBinding.inflate(getLayoutInflater()); - customBarcodeScannerBinding = CustomBarcodeScannerBinding.bind(binding.zxingBarcodeScanner); - setTitle(R.string.scanCardBarcode); - setContentView(binding.getRoot()); - Utils.applyWindowInsets(binding.getRoot()); - Toolbar toolbar = binding.toolbar; - setSupportActionBar(toolbar); - enableToolbarBackButton(); + private lateinit var capture: CaptureManager + private lateinit var barcodeScannerView: DecoratedBarcodeView + private var cardId: String? = null + private var addGroup: String? = null + private var torch = false - extractIntentFields(getIntent()); + private lateinit var manualAddLauncher: ActivityResultLauncher + private lateinit var photoPickerLauncher: ActivityResultLauncher + private lateinit var pdfPickerLauncher: ActivityResultLauncher + private lateinit var pkpassPickerLauncher: ActivityResultLauncher - manualAddLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.SELECT_BARCODE_REQUEST, result.getResultCode(), result.getData())); - photoPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_IMAGE_FILE, result.getResultCode(), result.getData())); - pdfPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_PDF_FILE, result.getResultCode(), result.getData())); - pkpassPickerLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> handleActivityResult(Utils.BARCODE_IMPORT_FROM_PKPASS_FILE, result.getResultCode(), result.getData())); - customBarcodeScannerBinding.fabOtherOptions.setOnClickListener(view -> { - setScannerActive(false); + private var mScannerActive = true + private var mHasError = false - ArrayList> list = new ArrayList<>(); - String[] texts = new String[]{ + private fun extractIntentFields(intent: Intent) { + val b = intent.extras + cardId = b?.getString(LoyaltyCard.BUNDLE_LOYALTY_CARD_CARD_ID) + addGroup = b?.getString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP) + Log.d(TAG, "Scan activity: id=$cardId") + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ScanActivityBinding.inflate(layoutInflater) + customBarcodeScannerBinding = CustomBarcodeScannerBinding.bind(binding.zxingBarcodeScanner) + setTitle(R.string.scanCardBarcode) + setContentView(binding.root) + Utils.applyWindowInsets(binding.root) + setSupportActionBar(binding.toolbar) + enableToolbarBackButton() + + extractIntentFields(intent) + + manualAddLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + handleActivityResult( + Utils.SELECT_BARCODE_REQUEST, + result.resultCode, + result.data + ) + } + photoPickerLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + handleActivityResult( + Utils.BARCODE_IMPORT_FROM_IMAGE_FILE, + result.resultCode, + result.data + ) + } + pdfPickerLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + handleActivityResult( + Utils.BARCODE_IMPORT_FROM_PDF_FILE, + result.resultCode, + result.data + ) + } + pkpassPickerLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + handleActivityResult( + Utils.BARCODE_IMPORT_FROM_PKPASS_FILE, + result.resultCode, + result.data + ) + } + + customBarcodeScannerBinding.fabOtherOptions.setOnClickListener { + setScannerActive(false) + + val list: ArrayList> = arrayListOf() + val texts = arrayOf( getString(R.string.addWithoutBarcode), getString(R.string.addManually), getString(R.string.addFromImage), getString(R.string.addFromPdfFile), getString(R.string.addFromPkpass) - }; - Object[] icons = new Object[]{ + ) + val icons = arrayOf( R.drawable.baseline_block_24, R.drawable.ic_edit, R.drawable.baseline_image_24, R.drawable.baseline_picture_as_pdf_24, R.drawable.local_activity_24px - }; - String[] columns = new String[]{"text", "icon"}; + ) + val columns = arrayOf("text", "icon") - for (int i = 0; i < texts.length; i++) { - HashMap map = new HashMap<>(); - map.put(columns[0], texts[i]); - map.put(columns[1], icons[i]); - list.add(map); + for (i in 0 until texts.size) { + val map: HashMap = hashMapOf() + map.put(columns[0], texts[i]) + map.put(columns[1], icons[i]) + list.add(map) } - ListAdapter adapter = new SimpleAdapter( - ScanActivity.this, + val adapter: ListAdapter = SimpleAdapter( + this, list, R.layout.alertdialog_row_with_icon, columns, - new int[]{R.id.textView, R.id.imageView} - ); + intArrayOf(R.id.textView, R.id.imageView) + ) - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ScanActivity.this); - builder.setTitle(getString(R.string.add_a_card_in_a_different_way)); - builder.setAdapter( - adapter, - (dialogInterface, i) -> { - switch (i) { - case 0: - addWithoutBarcode(); - break; - case 1: - addManually(); - break; - case 2: - addFromImage(); - break; - case 3: - addFromPdf(); - break; - case 4: - addFromPkPass(); - break; - default: - throw new IllegalArgumentException("Unknown 'Add a card in a different way' dialog option"); - } + val builder = MaterialAlertDialogBuilder(this).apply { + setTitle(getString(R.string.add_a_card_in_a_different_way)) + setAdapter(adapter) { _, i -> + when (i) { + 0 -> addWithoutBarcode() + 1 -> addManually() + 2 -> addFromImage() + 3 -> addFromPdf() + 4 -> addFromPkPass() + else -> throw IllegalArgumentException( + "Unknown 'Add a card in a different way' dialog option: $i" + ) } - ); - builder.setOnCancelListener(dialogInterface -> setScannerActive(true)); - builder.show(); - }); + } + setOnCancelListener { _ -> setScannerActive(true) } + } + builder.show() + } // Configure barcodeScanner - barcodeScannerView = binding.zxingBarcodeScanner; - Intent barcodeScannerIntent = new Intent(); - Bundle barcodeScannerIntentBundle = new Bundle(); - barcodeScannerIntentBundle.putBoolean(DecodeHintType.ALSO_INVERTED.name(), Boolean.TRUE); - barcodeScannerIntent.putExtras(barcodeScannerIntentBundle); - barcodeScannerView.initializeFromIntent(barcodeScannerIntent); + barcodeScannerView = binding.zxingBarcodeScanner + + val barcodeScannerIntent = Intent().apply { + val barcodeScannerIntentBundle = Bundle().apply { + putBoolean(DecodeHintType.ALSO_INVERTED.name, true) + } + putExtras(barcodeScannerIntentBundle) + } + barcodeScannerView.initializeFromIntent(barcodeScannerIntent) // Even though we do the actual decoding with the barcodeScannerView // CaptureManager needs to be running to show the camera and scanning bar - capture = new CatimaCaptureManager(this, barcodeScannerView, this::onCaptureManagerError); - Intent captureIntent = new Intent(); - Bundle captureIntentBundle = new Bundle(); - captureIntentBundle.putBoolean(Intents.Scan.BEEP_ENABLED, false); - captureIntent.putExtras(captureIntentBundle); - capture.initializeFromIntent(captureIntent, savedInstanceState); + capture = CatimaCaptureManager(this, barcodeScannerView, this::onCaptureManagerError) + val captureIntent = Intent().apply { + val captureIntentBundle = Bundle().apply { + putBoolean(DecodeHintType.ALSO_INVERTED.name, false) + } + putExtras(captureIntentBundle) + } + capture.initializeFromIntent(captureIntent, savedInstanceState) - barcodeScannerView.decodeSingle(new BarcodeCallback() { - @Override - public void barcodeResult(BarcodeResult result) { - LoyaltyCard loyaltyCard = new LoyaltyCard(); - loyaltyCard.setCardId(result.getText()); - loyaltyCard.setBarcodeType(CatimaBarcode.fromBarcode(result.getBarcodeFormat())); + barcodeScannerView.decodeSingle(object : BarcodeCallback { + override fun barcodeResult(result: BarcodeResult) { + val loyaltyCard = LoyaltyCard().apply { + setCardId(result.text) + setBarcodeType(CatimaBarcode.fromBarcode(result.barcodeFormat)) + } - returnResult(new ParseResult(ParseResultType.BARCODE_ONLY, loyaltyCard)); + returnResult(ParseResult(ParseResultType.BARCODE_ONLY, loyaltyCard)) } - @Override - public void possibleResultPoints(List resultPoints) { - - } - }); + override fun possibleResultPoints(resultPoints: List?) {} + }) } - @Override - protected void onResume() { - super.onResume(); + override fun onResume() { + super.onResume() if (mScannerActive) { - capture.onResume(); + capture.onResume() } if (!Utils.deviceHasCamera(this)) { - showCameraError(getString(R.string.noCameraFoundGuideText), false); - } else if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { - showCameraPermissionMissingText(); + showCameraError(getString(R.string.noCameraFoundGuideText), false) + } else if (ContextCompat.checkSelfPermission( + this, + Manifest.permission.CAMERA + ) != PackageManager.PERMISSION_GRANTED + ) { + showCameraPermissionMissingText() } else { - hideCameraError(); + hideCameraError() } - scaleScreen(); + scaleScreen() } - @Override - protected void onPause() { - super.onPause(); - capture.onPause(); + override fun onPause() { + super.onPause() + capture.onPause() } - @Override - protected void onDestroy() { - super.onDestroy(); - capture.onDestroy(); + override fun onDestroy() { + super.onDestroy() + capture.onDestroy() } - @Override - protected void onSaveInstanceState(Bundle savedInstanceState) { - super.onSaveInstanceState(savedInstanceState); - capture.onSaveInstanceState(savedInstanceState); + override fun onSaveInstanceState(savedInstanceState: Bundle) { + super.onSaveInstanceState(savedInstanceState) + capture.onSaveInstanceState(savedInstanceState) - savedInstanceState.putBoolean(STATE_SCANNER_ACTIVE, mScannerActive); + savedInstanceState.putBoolean(STATE_SCANNER_ACTIVE, mScannerActive) } - @Override - public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); + override fun onRestoreInstanceState(savedInstanceState: Bundle) { + super.onRestoreInstanceState(savedInstanceState) - mScannerActive = savedInstanceState.getBoolean(STATE_SCANNER_ACTIVE); + mScannerActive = savedInstanceState.getBoolean(STATE_SCANNER_ACTIVE) } - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - return barcodeScannerView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); + override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { + return barcodeScannerView.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event) } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) { - getMenuInflater().inflate(R.menu.scan_menu, menu); + override fun onCreateOptionsMenu(menu: Menu): Boolean { + if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)) { + menuInflater.inflate(R.menu.scan_menu, menu) } - barcodeScannerView.setTorchOff(); + barcodeScannerView.setTorchOff() - return super.onCreateOptionsMenu(menu); + return super.onCreateOptionsMenu(menu) } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == android.R.id.home) { - setResult(Activity.RESULT_CANCELED); - finish(); - return true; - } else if (item.getItemId() == R.id.action_toggle_flashlight) { + override fun onOptionsItemSelected(item: MenuItem): Boolean { + if (item.itemId == android.R.id.home) { + setResult(RESULT_CANCELED) + finish() + return true + } else if (item.itemId == R.id.action_toggle_flashlight) { if (torch) { - torch = false; - barcodeScannerView.setTorchOff(); - item.setTitle(R.string.turn_flashlight_on); - item.setIcon(R.drawable.ic_flashlight_off_white_24dp); + torch = false + barcodeScannerView.setTorchOff() + item.setTitle(R.string.turn_flashlight_on) + item.setIcon(R.drawable.ic_flashlight_off_white_24dp) } else { - torch = true; - barcodeScannerView.setTorchOn(); - item.setTitle(R.string.turn_flashlight_off); - item.setIcon(R.drawable.ic_flashlight_on_white_24dp); + torch = true + barcodeScannerView.setTorchOn() + item.setTitle(R.string.turn_flashlight_off) + item.setIcon(R.drawable.ic_flashlight_on_white_24dp) } } - return super.onOptionsItemSelected(item); + return super.onOptionsItemSelected(item) } - private void setScannerActive(boolean isActive) { + private fun setScannerActive(isActive: Boolean) { if (isActive) { - barcodeScannerView.resume(); + barcodeScannerView.resume() } else { - barcodeScannerView.pause(); + barcodeScannerView.pause() } - mScannerActive = isActive; + mScannerActive = isActive } - private void returnResult(ParseResult parseResult) { - Intent result = new Intent(); - Bundle bundle = parseResult.toLoyaltyCardBundle(ScanActivity.this); - if (addGroup != null) { - bundle.putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, addGroup); + private fun returnResult(parseResult: ParseResult) { + val bundle = parseResult.toLoyaltyCardBundle(this).apply { + addGroup?.let { putString(LoyaltyCardEditActivity.BUNDLE_ADDGROUP, it) } } - result.putExtras(bundle); - ScanActivity.this.setResult(RESULT_OK, result); - finish(); + val result = Intent().apply { putExtras(bundle) } + this.setResult(RESULT_OK, result) + finish() } - private void handleActivityResult(int requestCode, int resultCode, Intent intent) { - super.onActivityResult(requestCode, resultCode, intent); + private fun handleActivityResult(requestCode: Int, resultCode: Int, intent: Intent?) { + super.onActivityResult(resultCode, resultCode, intent) - List parseResultList = Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this); + val parseResultList: List = + Utils.parseSetBarcodeActivityResult(requestCode, resultCode, intent, this) if (parseResultList.isEmpty()) { - setScannerActive(true); - return; + setScannerActive(true) + return } - Utils.makeUserChooseParseResultFromList(this, parseResultList, new ParseResultListDisambiguatorCallback() { - @Override - public void onUserChoseParseResult(ParseResult parseResult) { - returnResult(parseResult); - } - @Override - public void onUserDismissedSelector() { - setScannerActive(true); - } - }); + Utils.makeUserChooseParseResultFromList( + this, + parseResultList, + object : ParseResultListDisambiguatorCallback { + override fun onUserChoseParseResult(parseResult: ParseResult) { + returnResult(parseResult) + } + + override fun onUserDismissedSelector() { + setScannerActive(true) + } + }) } - private void addWithoutBarcode() { - AlertDialog.Builder builder = new MaterialAlertDialogBuilder(this); - - builder.setOnCancelListener(dialogInterface -> setScannerActive(true)); - - // Header - builder.setTitle(R.string.addWithoutBarcode); + private fun addWithoutBarcode() { + val builder: AlertDialog.Builder = MaterialAlertDialogBuilder(this).apply { + setOnCancelListener { dialogInterface -> setScannerActive(true) } + // Header + setTitle(R.string.addWithoutBarcode) + } // Layout - LinearLayout layout = new LinearLayout(this); - layout.setOrientation(LinearLayout.VERTICAL); - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ); - int contentPadding = getResources().getDimensionPixelSize(R.dimen.alert_dialog_content_padding); - params.leftMargin = contentPadding; - params.topMargin = contentPadding / 2; - params.rightMargin = contentPadding; + val layout = LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL + } + val contentPadding = resources.getDimensionPixelSize(R.dimen.alert_dialog_content_padding) + val params = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT + ).apply { + leftMargin = contentPadding + topMargin = contentPadding / 2 + rightMargin = contentPadding + } // Description - TextView currentTextview = new TextView(this); - currentTextview.setText(getString(R.string.enter_card_id)); - currentTextview.setLayoutParams(params); - layout.addView(currentTextview); + val currentTextview = TextView(this).apply { + text = getString(R.string.enter_card_id) + layoutParams = params + } + layout.addView(currentTextview) - // EditText with spacing - final EditText input = new EditText(this); - input.setInputType(InputType.TYPE_CLASS_TEXT); - input.setLayoutParams(params); - layout.addView(input); + //EditText with spacing + val input = EditText(this).apply { + inputType = InputType.TYPE_CLASS_TEXT + layoutParams = params + } + layout.addView(input) // Set layout - builder.setView(layout); + builder.setView(layout).apply { - // Buttons - builder.setPositiveButton(getString(R.string.ok), (dialog, which) -> { - LoyaltyCard loyaltyCard = new LoyaltyCard(); - loyaltyCard.setCardId(input.getText().toString()); - returnResult(new ParseResult(ParseResultType.BARCODE_ONLY, loyaltyCard)); - }); - builder.setNegativeButton(getString(R.string.cancel), (dialog, which) -> dialog.cancel()); - AlertDialog dialog = builder.create(); + setPositiveButton(getString(R.string.ok)) { _, _ -> + val loyaltyCard = LoyaltyCard() + loyaltyCard.cardId = input.text.toString() + returnResult(ParseResult(ParseResultType.BARCODE_ONLY, loyaltyCard)) + } + setNegativeButton(getString(R.string.cancel)) { dialog, _ -> + dialog.cancel() + } + } + val dialog: AlertDialog = builder.create() // Now that the dialog exists, we can bind something that affects the OK button - input.addTextChangedListener(new SimpleTextWatcher() { - public void onTextChanged(CharSequence s, int start, int before, int count) { - if (s.length() == 0) { - input.setError(getString(R.string.card_id_must_not_be_empty)); - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); - } else { - input.setError(null); - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true); - } + input.doOnTextChanged { text, _, _, _ -> + if (text.isNullOrEmpty()) { + input.error = getString(R.string.card_id_must_not_be_empty) + dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false + } else { + input.error = null + dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = true } - }); + } - dialog.show(); + dialog.show() // Disable button (must be done **after** dialog is shown to prevent crash - dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false); + dialog.getButton(AlertDialog.BUTTON_POSITIVE).isEnabled = false // Set focus on input field - dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); - input.requestFocus(); + dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) + input.requestFocus() } - public void addManually() { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ScanActivity.this); - builder.setTitle(R.string.add_manually_warning_title); - builder.setMessage(R.string.add_manually_warning_message); - builder.setPositiveButton(R.string.continue_, (dialog, which) -> { - Intent i = new Intent(getApplicationContext(), BarcodeSelectorActivity.class); - if (cardId != null) { - final Bundle b = new Bundle(); - b.putString(LoyaltyCard.BUNDLE_LOYALTY_CARD_CARD_ID, cardId); - i.putExtras(b); + fun addManually() { + val builder = MaterialAlertDialogBuilder(this).apply { + setTitle(R.string.add_manually_warning_title) + setMessage(R.string.add_manually_warning_message) + setPositiveButton(R.string.continue_) { _, _ -> + val i = Intent(applicationContext, BarcodeSelectorActivity::class.java) + if (cardId != null) { + val b = Bundle() + b.putString(LoyaltyCard.BUNDLE_LOYALTY_CARD_CARD_ID, cardId) + i.putExtras(b) + } + manualAddLauncher.launch(i) } - manualAddLauncher.launch(i); - }); - builder.setNegativeButton(R.string.cancel, (dialog, which) -> setScannerActive(true)); - builder.setOnCancelListener(dialog -> setScannerActive(true)); - builder.show(); + setNegativeButton(R.string.cancel) { _, _ -> setScannerActive(true) } + setOnCancelListener { _ -> setScannerActive(true) } + } + builder.show() } - public void addFromImage() { - PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_IMAGE); + fun addFromImage() { + PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_IMAGE) } - public void addFromPdf() { - PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_PDF); + fun addFromPdf() { + PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_PDF) } - public void addFromPkPass() { - PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_PKPASS); + fun addFromPkPass() { + PermissionUtils.requestStorageReadPermission(this, PERMISSION_SCAN_ADD_FROM_PKPASS) } - private void addFromImageOrFileAfterPermission(String mimeType, ActivityResultLauncher launcher, int chooserText, int errorMessage) { - Intent photoPickerIntent = new Intent(Intent.ACTION_PICK); - photoPickerIntent.setType(mimeType); - Intent contentIntent = new Intent(Intent.ACTION_GET_CONTENT); - contentIntent.setType(mimeType); + private fun addFromImageOrFileAfterPermission( + mimeType: String, + launcher: ActivityResultLauncher, + chooserText: Int, + errorMessage: Int + ) { + val photoPickerIntent = Intent(Intent.ACTION_PICK) + photoPickerIntent.type = mimeType + val contentIntent = Intent(Intent.ACTION_GET_CONTENT) + contentIntent.type = mimeType - Intent chooserIntent = Intent.createChooser(photoPickerIntent, getString(chooserText)); - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { contentIntent }); + val chooserIntent = Intent.createChooser(photoPickerIntent, getString(chooserText)) + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, arrayOf(contentIntent)) try { - launcher.launch(chooserIntent); - } catch (ActivityNotFoundException e) { - setScannerActive(true); - Toast.makeText(getApplicationContext(), errorMessage, Toast.LENGTH_LONG).show(); - Log.e(TAG, "No activity found to handle intent", e); + launcher.launch(chooserIntent) + } catch (e: ActivityNotFoundException) { + setScannerActive(true) + Toast.makeText(applicationContext, errorMessage, Toast.LENGTH_LONG).show() + Log.e(TAG, "No activity found to handle intent", e) } } - public void onCaptureManagerError(String errorMessage) { + fun onCaptureManagerError(errorMessage: String) { if (mHasError) { // We're already showing an error, ignore this new error - return; + return } - showCameraError(errorMessage, false); + showCameraError(errorMessage, false) } - private void showCameraPermissionMissingText() { - showCameraError(getString(R.string.noCameraPermissionDirectToSystemSetting), true); + private fun showCameraPermissionMissingText() { + showCameraError(getString(R.string.noCameraPermissionDirectToSystemSetting), true) } - private void showCameraError(String message, boolean setOnClick) { - customBarcodeScannerBinding.cameraErrorLayout.cameraErrorMessage.setText(message); + private fun showCameraError(message: String, setOnClick: Boolean) { + customBarcodeScannerBinding.cameraErrorLayout.cameraErrorMessage.text = message - setCameraErrorState(true, setOnClick); + setCameraErrorState(true, setOnClick) } - private void hideCameraError() { - setCameraErrorState(false, false); + private fun hideCameraError() { + setCameraErrorState(false, false) } - private void setCameraErrorState(boolean visible, boolean setOnClick) { - mHasError = visible; - - customBarcodeScannerBinding.cameraErrorLayout.cameraErrorClickableArea.setOnClickListener(visible && setOnClick ? v -> { - navigateToSystemPermissionSetting(); - } : null); - customBarcodeScannerBinding.cardInputContainer.setBackgroundColor(visible ? obtainThemeAttribute(com.google.android.material.R.attr.colorSurface) : Color.TRANSPARENT); - customBarcodeScannerBinding.cameraErrorLayout.getRoot().setVisibility(visible ? View.VISIBLE : View.GONE); + private fun setCameraErrorState(visible: Boolean, setOnClick: Boolean) { + mHasError = visible + customBarcodeScannerBinding.cameraErrorLayout.cameraErrorClickableArea.setOnClickListener( + if (visible && setOnClick) { _ -> navigateToSystemPermissionSetting() } + else null + ) + customBarcodeScannerBinding.cardInputContainer.setBackgroundColor( + if (visible) obtainThemeAttribute(com.google.android.material.R.attr.colorSurface) + else Color.TRANSPARENT + ) + customBarcodeScannerBinding.cameraErrorLayout.root.visibility = + if (visible) View.VISIBLE else View.GONE } - private void scaleScreen() { - DisplayMetrics displayMetrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); - int screenHeight = displayMetrics.heightPixels; - float mediumSizePx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,MEDIUM_SCALE_FACTOR_DIP,getResources().getDisplayMetrics()); - boolean shouldScaleSmaller = screenHeight < mediumSizePx; + private fun scaleScreen() { + val displayMetrics = DisplayMetrics() + windowManager.defaultDisplay.getMetrics(displayMetrics) + val screenHeight: Int = displayMetrics.heightPixels + val mediumSizePx: Float = TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + MEDIUM_SCALE_FACTOR_DIP.toFloat(), + resources.displayMetrics + ) + val shouldScaleSmaller = screenHeight < mediumSizePx - customBarcodeScannerBinding.cameraErrorLayout.cameraErrorIcon.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE); - customBarcodeScannerBinding.cameraErrorLayout.cameraErrorTitle.setVisibility(shouldScaleSmaller ? View.GONE : View.VISIBLE); + customBarcodeScannerBinding.cameraErrorLayout.cameraErrorIcon.visibility = + if (shouldScaleSmaller) View.GONE else View.VISIBLE + customBarcodeScannerBinding.cameraErrorLayout.cameraErrorTitle.visibility = + if (shouldScaleSmaller) View.GONE else View.VISIBLE } - private int obtainThemeAttribute(int attribute) { - TypedValue typedValue = new TypedValue(); - getTheme().resolveAttribute(attribute, typedValue, true); - return typedValue.data; + private fun obtainThemeAttribute(attribute: Int): Int { + val typedValue = TypedValue() + theme.resolveAttribute(attribute, typedValue, true) + return typedValue.data } - private void navigateToSystemPermissionSetting() { - Intent permissionIntent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", getPackageName(), null)); - permissionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(permissionIntent); + private fun navigateToSystemPermissionSetting() { + val permissionIntent = Intent( + Settings.ACTION_APPLICATION_DETAILS_SETTINGS, + Uri.fromParts("package", getPackageName(), null) + ) + permissionIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + startActivity(permissionIntent) } - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) - onMockedRequestPermissionsResult(requestCode, permissions, grantResults); + onMockedRequestPermissionsResult(requestCode, permissions, grantResults) } - public void onMockedRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; + override fun onMockedRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + val granted = + grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED if (requestCode == CaptureManager.getCameraPermissionReqCode()) { if (granted) { - hideCameraError(); + hideCameraError() } else { - showCameraPermissionMissingText(); + showCameraPermissionMissingText() } - } else if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE || requestCode == PERMISSION_SCAN_ADD_FROM_PDF || requestCode == PERMISSION_SCAN_ADD_FROM_PKPASS) { + } else if (requestCode in listOf( + PERMISSION_SCAN_ADD_FROM_IMAGE, + PERMISSION_SCAN_ADD_FROM_PDF, + PERMISSION_SCAN_ADD_FROM_PKPASS + ) + ) { if (granted) { if (requestCode == PERMISSION_SCAN_ADD_FROM_IMAGE) { - addFromImageOrFileAfterPermission("image/*", photoPickerLauncher, R.string.addFromImage, R.string.failedLaunchingPhotoPicker); + addFromImageOrFileAfterPermission( + "image/*", + photoPickerLauncher, + R.string.addFromImage, + R.string.failedLaunchingPhotoPicker + ) } else if (requestCode == PERMISSION_SCAN_ADD_FROM_PDF) { - addFromImageOrFileAfterPermission("application/pdf", pdfPickerLauncher, R.string.addFromPdfFile, R.string.failedLaunchingFileManager); + addFromImageOrFileAfterPermission( + "application/pdf", + pdfPickerLauncher, + R.string.addFromPdfFile, + R.string.failedLaunchingFileManager + ) } else { - addFromImageOrFileAfterPermission("application/*", pkpassPickerLauncher, R.string.addFromPkpass, R.string.failedLaunchingFileManager); + addFromImageOrFileAfterPermission( + "application/*", + pkpassPickerLauncher, + R.string.addFromPkpass, + R.string.failedLaunchingFileManager + ) } } else { - setScannerActive(true); - Toast.makeText(this, R.string.storageReadPermissionRequired, Toast.LENGTH_LONG).show(); + setScannerActive(true) + Toast.makeText(this, R.string.storageReadPermissionRequired, Toast.LENGTH_LONG) + .show() } } }