From ef60299bc0e3e876f76a0eff4fbe740a86191e06 Mon Sep 17 00:00:00 2001 From: asherwu Date: Mon, 2 Sep 2024 18:54:07 +0800 Subject: [PATCH 1/4] feat: add qrcode scanner --- android/app/build.gradle | 1 + android/app/src/main/AndroidManifest.xml | 5 +++ .../main/java/com/httpsms/LoginActivity.kt | 25 +++++++++++ .../src/main/res/layout/activity_login.xml | 13 +++--- web/package.json | 1 + web/pages/settings/index.vue | 43 +++++++++++++++++++ web/pnpm-lock.yaml | 3 ++ 7 files changed, 85 insertions(+), 6 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 7416c22e..ceb73cbb 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -52,6 +52,7 @@ android { dependencies { implementation platform('com.google.firebase:firebase-bom:32.7.4') + implementation 'com.journeyapps:zxing-android-embedded:4.3.0' implementation 'com.google.firebase:firebase-analytics-ktx' implementation 'com.google.firebase:firebase-messaging-ktx' implementation 'com.squareup.okhttp3:okhttp:4.10.0' diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index f04d6f26..cf5ef65c 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -45,6 +45,11 @@ tools:ignore="LockedOrientationActivity" /> + (R.id.loginApiKeyTextInputLayout) + apiKeyInputLayout.setEndIconOnClickListener { + startQrCodeScan() + } + } + + private val barcodeLauncher = registerForActivityResult(ScanContract()) { result -> + if (result.contents != null) { + val apiKeyInput = findViewById(R.id.loginApiKeyTextInput) + apiKeyInput.setText(result.contents) + Toast.makeText(this, "Scanned: ${result.contents}", Toast.LENGTH_LONG).show() + } else { + Toast.makeText(this, "Scan cancelled", Toast.LENGTH_SHORT).show() + } + } + + private fun startQrCodeScan() { + val options = ScanOptions() + options.setPrompt("Scan a QR code") + options.setBeepEnabled(true) + options.setOrientationLocked(false) + options.setCameraId(0) + barcodeLauncher.launch(options) } override fun onStart() { diff --git a/android/app/src/main/res/layout/activity_login.xml b/android/app/src/main/res/layout/activity_login.xml index 0a1f046c..ccfa768e 100644 --- a/android/app/src/main/res/layout/activity_login.xml +++ b/android/app/src/main/res/layout/activity_login.xml @@ -41,10 +41,13 @@ style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" - app:errorEnabled="true" android:hint="@string/text_area_api_key" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toTopOf="parent" + app:errorEnabled="true" + app:endIconMode="custom" + app:endIconDrawable="@android:drawable/ic_menu_camera" + app:endIconContentDescription="cameraButton" + app:layout_constraintBottom_toTopOf="@+id/loginPhoneNumberLayoutSIM1" + app:layout_constraintTop_toBottomOf="@+id/textView" tools:layout_editor_absoluteX="16dp"> - - + \ No newline at end of file diff --git a/web/package.json b/web/package.json index 32c0d6e2..02180213 100644 --- a/web/package.json +++ b/web/package.json @@ -38,6 +38,7 @@ "moment": "^2.30.1", "nuxt": "^2.18.1", "nuxt-highlightjs": "^1.0.3", + "qrcode": "^1.5.0", "ufo": "^1.5.4", "vue": "^2.7.16", "vue-chartjs": "^5.3.1", diff --git a/web/pages/settings/index.vue b/web/pages/settings/index.vue index 1771182f..1fe294b4 100644 --- a/web/pages/settings/index.vue +++ b/web/pages/settings/index.vue @@ -82,6 +82,26 @@ copy-text="Copy API Key" notification-text="API Key copied successfully" > + + {{ mdiQrcode }} + Show QR Code + + + + API Key QR Code + + + + + + Close + + + { + this.generateQrCode(this.apiKey); + }); + } + }, + }, async mounted() { await Promise.all([ this.$store.dispatch('clearAxiosError'), @@ -818,6 +851,16 @@ export default Vue.extend({ }, methods: { + generateQrCode(text) { + const canvas = this.$refs.qrCodeCanvas; + if (canvas) { + QRCode.toCanvas(canvas, text, { errorCorrectionLevel: 'H' }, (err) => { + if (err) { + console.error(err); + } + }); + } + }, updateEmailNotifications() { this.notificationSettings = { webhook_enabled: diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index b4e47417..926b6825 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -56,6 +56,9 @@ importers: nuxt-highlightjs: specifier: ^1.0.3 version: 1.0.3 + qrcode: + specifier: ^1.5.0 + version: 1.5.0 ufo: specifier: ^1.5.4 version: 1.5.4 From 2740b28113d7a35f650d98a7fb7526a9aa5f0b2a Mon Sep 17 00:00:00 2001 From: asherwu Date: Mon, 2 Sep 2024 18:57:01 +0800 Subject: [PATCH 2/4] feat: add qrcode scanner --- android/app/src/main/res/layout/activity_login.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/res/layout/activity_login.xml b/android/app/src/main/res/layout/activity_login.xml index ccfa768e..cc4d4eb1 100644 --- a/android/app/src/main/res/layout/activity_login.xml +++ b/android/app/src/main/res/layout/activity_login.xml @@ -56,6 +56,7 @@ android:layout_height="wrap_content" android:inputType="textMultiLine" tools:ignore="TextContrastCheck" /> + - \ No newline at end of file + From 6cf8f03beeaf792aed2cee80810070a8b5d9e818 Mon Sep 17 00:00:00 2001 From: asherwu Date: Mon, 2 Sep 2024 19:05:24 +0800 Subject: [PATCH 3/4] feat: package setupApiKeyInput function --- .../app/src/main/java/com/httpsms/LoginActivity.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/android/app/src/main/java/com/httpsms/LoginActivity.kt b/android/app/src/main/java/com/httpsms/LoginActivity.kt index 5cae08e7..96b1dc76 100644 --- a/android/app/src/main/java/com/httpsms/LoginActivity.kt +++ b/android/app/src/main/java/com/httpsms/LoginActivity.kt @@ -38,8 +38,22 @@ class LoginActivity : AppCompatActivity() { setPhoneNumber() disableSim2() setServerURL() + setupApiKeyInput() + } + + private fun setupApiKeyInput() { val apiKeyInputLayout = findViewById(R.id.loginApiKeyTextInputLayout) + val apiKeyInput = findViewById(R.id.loginApiKeyTextInput) + + // 设置点击监听器启动扫描 + apiKeyInput.setOnClickListener { + startQrCodeScan() // 触发 QR Code 扫描 + } + + // 设置 endIcon 的点击事件监听器 apiKeyInputLayout.setEndIconOnClickListener { + Toast.makeText(this, "End icon clicked", Toast.LENGTH_SHORT).show() + // 在这里处理 endIcon 的点击事件,例如启动相机扫描 startQrCodeScan() } } From fd02dce00821d75f2da45ce9fa48a6f3a1ef1a06 Mon Sep 17 00:00:00 2001 From: asherwu Date: Mon, 2 Sep 2024 19:08:58 +0800 Subject: [PATCH 4/4] feat: clean code --- android/app/src/main/java/com/httpsms/LoginActivity.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/android/app/src/main/java/com/httpsms/LoginActivity.kt b/android/app/src/main/java/com/httpsms/LoginActivity.kt index 96b1dc76..ae257ee7 100644 --- a/android/app/src/main/java/com/httpsms/LoginActivity.kt +++ b/android/app/src/main/java/com/httpsms/LoginActivity.kt @@ -45,15 +45,11 @@ class LoginActivity : AppCompatActivity() { val apiKeyInputLayout = findViewById(R.id.loginApiKeyTextInputLayout) val apiKeyInput = findViewById(R.id.loginApiKeyTextInput) - // 设置点击监听器启动扫描 apiKeyInput.setOnClickListener { - startQrCodeScan() // 触发 QR Code 扫描 + startQrCodeScan() } - // 设置 endIcon 的点击事件监听器 apiKeyInputLayout.setEndIconOnClickListener { - Toast.makeText(this, "End icon clicked", Toast.LENGTH_SHORT).show() - // 在这里处理 endIcon 的点击事件,例如启动相机扫描 startQrCodeScan() } }