Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion app/src/main/java/com/github/kr328/clash/ProfilesActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class ProfilesActivity : BaseActivity<ProfilesDesign>() {

startActivity(PropertiesActivity::class.intent.setUUID(uuid))
}
is ProfilesDesign.Request.ShareQrCode ->
design.showProfileQrCode(it.profile)
}
}
if (activityStarted) {
Expand Down Expand Up @@ -124,4 +126,4 @@ class ProfilesActivity : BaseActivity<ProfilesDesign>() {
}
}
}
}
}
1 change: 1 addition & 0 deletions design/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ dependencies {
implementation(libs.androidx.fragment)
implementation(libs.androidx.viewpager)
implementation(libs.google.material)
implementation(libs.zxing.core)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,29 @@ package com.github.kr328.clash.design

import android.app.Dialog
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import com.github.kr328.clash.design.adapter.ProfileAdapter
import com.github.kr328.clash.design.databinding.DesignProfilesBinding
import com.github.kr328.clash.design.databinding.DialogProfilesMenuBinding
import com.github.kr328.clash.design.databinding.DialogProfileQrCodeBinding
import com.github.kr328.clash.design.dialog.AppBottomSheetDialog
import com.github.kr328.clash.design.ui.ToastDuration
import com.github.kr328.clash.design.util.*
import com.github.kr328.clash.service.model.Profile
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.zxing.BarcodeFormat
import com.google.zxing.EncodeHintType
import com.google.zxing.WriterException
import com.google.zxing.qrcode.QRCodeWriter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlin.coroutines.resume

class ProfilesDesign(context: Context) : Design<ProfilesDesign.Request>(context) {
sealed class Request {
Expand All @@ -24,6 +34,7 @@ class ProfilesDesign(context: Context) : Design<ProfilesDesign.Request>(context)
data class Update(val profile: Profile) : Request()
data class Edit(val profile: Profile) : Request()
data class Duplicate(val profile: Profile) : Request()
data class ShareQrCode(val profile: Profile) : Request()
data class Delete(val profile: Profile) : Request()
}

Expand Down Expand Up @@ -135,11 +146,55 @@ class ProfilesDesign(context: Context) : Design<ProfilesDesign.Request>(context)
dialog.dismiss()
}

fun requestShareQrCode(dialog: Dialog, profile: Profile) {
requests.trySend(Request.ShareQrCode(profile))

dialog.dismiss()
}

suspend fun showProfileQrCode(profile: Profile) {
if (profile.type != Profile.Type.Url || profile.source.isBlank()) return

val bitmap = try {
withContext(Dispatchers.Default) {
val matrix = QRCodeWriter().encode(
profile.source, BarcodeFormat.QR_CODE, 768, 768,
mapOf(EncodeHintType.CHARACTER_SET to "UTF-8")
)
val pixels = IntArray(matrix.width * matrix.height) { index ->
if (matrix[index % matrix.width, index / matrix.width]) Color.BLACK else Color.WHITE
}
Bitmap.createBitmap(pixels, matrix.width, matrix.height, Bitmap.Config.ARGB_8888)
}
} catch (_: WriterException) {
showToast(R.string.qr_code_generation_failed, ToastDuration.Long)
return
}

withContext(Dispatchers.Main) {
val binding = DialogProfileQrCodeBinding.inflate(context.layoutInflater)
binding.qrCode.setImageBitmap(bitmap)

suspendCancellableCoroutine<Unit> { continuation ->
val dialog = MaterialAlertDialogBuilder(context)
.setTitle(R.string.share_qr_code)
.setView(binding.root)
.setPositiveButton(R.string.close) { _, _ -> }
.setOnDismissListener {
if (continuation.isActive) continuation.resume(Unit)
}
.show()

continuation.invokeOnCancellation { dialog.dismiss() }
}
}
}

private fun changeUpdateAllButtonStatus() {
if (allUpdating) {
binding.updateView.startAnimation(rotateAnimation)
} else {
binding.updateView.clearAnimation()
}
}
}
}
17 changes: 17 additions & 0 deletions design/src/main/res/layout/dialog_profile_qr_code.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/dialog_padding">

<ImageView
android:id="@+id/qr_code"
android:layout_width="match_parent"
android:layout_height="240dp"
android:background="@android:color/white"
android:contentDescription="@string/share_qr_code"
android:forceDarkAllowed="false"
android:scaleType="fitCenter" />
</ScrollView>
</layout>
11 changes: 10 additions & 1 deletion design/src/main/res/layout/dialog_profiles_menu.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@
app:icon="@drawable/ic_baseline_content_copy"
app:text="@string/duplicate" />

<com.github.kr328.clash.design.view.LargeActionLabel
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="@{() -> master.requestShareQrCode(self, profile)}"
android:padding="@dimen/bottom_sheet_menu_items_padding"
android:visibility="@{profile.imported &amp;&amp; profile.type == Type.Url &amp;&amp; !profile.source.isEmpty() ? View.VISIBLE : View.GONE}"
app:icon="@drawable/baseline_qr_code_scanner"
app:text="@string/share_qr_code" />

<com.github.kr328.clash.design.view.LargeActionLabel
android:layout_width="match_parent"
android:layout_height="wrap_content"
Expand All @@ -56,4 +65,4 @@
app:icon="@drawable/ic_outline_delete"
app:text="@string/delete" />
</LinearLayout>
</layout>
</layout>
2 changes: 2 additions & 0 deletions design/src/main/res/values-ja-rJP/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
<string name="import_">インポート</string>
<string name="properties">プロパティ</string>
<string name="duplicate">複製</string>
<string name="share_qr_code">QRコードで共有</string>
<string name="qr_code_generation_failed">このリンクのQRコードを生成できません。</string>
<string name="active_unsaved_tips">プロファイルを有効にする前に保存する必要があります</string>
<string name="exit_without_save">保存せずに閉じる</string>
<string name="exit_without_save_warning">すべての変更は失われます</string>
Expand Down
2 changes: 2 additions & 0 deletions design/src/main/res/values-ko-rKR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
<string name="import_">가져오기</string>
<string name="properties">속성</string>
<string name="duplicate">복제</string>
<string name="share_qr_code">QR 코드로 공유</string>
<string name="qr_code_generation_failed">이 링크의 QR 코드를 생성할 수 없습니다.</string>
<string name="active_unsaved_tips">활성화하기 전에 구성 파일을 저장해야합니다.</string>
<string name="exit_without_save">저장없이 종료</string>
<string name="exit_without_save_warning">모든 변경 사항이 저장되지 않습니다.</string>
Expand Down
2 changes: 2 additions & 0 deletions design/src/main/res/values-ru/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
<string name="import_">Импорт</string>
<string name="properties">Свойства</string>
<string name="duplicate">Создать копию</string>
<string name="share_qr_code">Поделиться QR-кодом</string>
<string name="qr_code_generation_failed">Не удалось создать QR-код для этой ссылки.</string>
<string name="active_unsaved_tips">Профиль должен быть сохранён перед активацией</string>

<string name="exit_without_save">Выйти без сохранения</string>
Expand Down
2 changes: 2 additions & 0 deletions design/src/main/res/values-vi/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@
<string name="donate">Quyên góp</string>
<string name="dont_modify">Chưa sửa đổi</string>
<string name="duplicate">Tạo bản sao</string>
<string name="share_qr_code">Chia sẻ mã QR</string>
<string name="qr_code_generation_failed">Không thể tạo mã QR cho liên kết này.</string>
<string name="edit">Sửa</string>
<string name="empty">Trống</string>
<string name="empty_name">Tên trống</string>
Expand Down
2 changes: 2 additions & 0 deletions design/src/main/res/values-zh-rHK/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
<string name="dns_hijacking">DNS 劫持</string>
<string name="dns_hijacking_summary">處理所有 DNS 數據包</string>
<string name="duplicate">複製</string>
<string name="share_qr_code">二維碼分享</string>
<string name="qr_code_generation_failed">無法為此連結產生二維碼。</string>
<string name="edit">編輯</string>
<string name="empty_name">空名稱</string>
<string name="exit_without_save">退出而不保存</string>
Expand Down
2 changes: 2 additions & 0 deletions design/src/main/res/values-zh-rTW/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
<string name="dns_hijacking">DNS 攔截攻擊</string>
<string name="dns_hijacking_summary">處理所有 DNS 封包</string>
<string name="duplicate">複製</string>
<string name="share_qr_code">分享 QR 碼</string>
<string name="qr_code_generation_failed">無法為此連結產生 QR 碼。</string>
<string name="edit">編輯</string>
<string name="empty_name">空白名稱</string>
<string name="exit_without_save">退出而不儲存</string>
Expand Down
2 changes: 2 additions & 0 deletions design/src/main/res/values-zh/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
<string name="dns_hijacking">DNS 劫持</string>
<string name="dns_hijacking_summary">处理所有 DNS 数据包</string>
<string name="duplicate">复制</string>
<string name="share_qr_code">二维码分享</string>
<string name="qr_code_generation_failed">无法为此链接生成二维码。</string>
<string name="edit">编辑</string>
<string name="empty_name">空名称</string>
<string name="exit_without_save">退出而不保存</string>
Expand Down
2 changes: 2 additions & 0 deletions design/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
<string name="import_">Import</string>
<string name="properties">Properties</string>
<string name="duplicate">Duplicate</string>
<string name="share_qr_code">Share QR code</string>
<string name="qr_code_generation_failed">Unable to generate a QR code for this link.</string>
<string name="active_unsaved_tips">Profile needs to be saved before activation</string>

<string name="exit_without_save">Exit without Save</string>
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ kaidl = "1.15"
room = "2.4.2"
multiprocess = "1.0.0"
quickie = "1.11.0"
zxing = "3.5.3"
androidx-activity-ktx = "1.9.0"

[libraries]
Expand All @@ -42,6 +43,7 @@ kaidl-compiler = { module = "com.github.kr328.kaidl:kaidl", version.ref = "kaidl
kaidl-runtime = { module = "com.github.kr328.kaidl:kaidl-runtime", version.ref = "kaidl" }
rikkax-multiprocess = { module = "dev.rikka.rikkax.preference:multiprocess", version.ref = "multiprocess" }
quickie-bundled = { group = "io.github.g00fy2.quickie", name = "quickie-bundled", version.ref = "quickie" }
zxing-core = { module = "com.google.zxing:core", version.ref = "zxing" }
androidx-activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref = "androidx-activity-ktx" }

[plugins]