Add import profile from file

This commit is contained in:
世界 2024-03-17 01:00:21 +08:00
parent 720b5621d2
commit ae7166a699
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
14 changed files with 105 additions and 14 deletions

View file

@ -2,10 +2,12 @@ package io.nekohasekai.sfa.ui.main
import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.widget.PopupMenu
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
@ -84,12 +86,18 @@ class ConfigurationFragment : Fragment() {
class AddProfileDialog : BottomSheetDialogFragment(R.layout.sheet_add_profile) {
private val importFromFile =
registerForActivityResult(ActivityResultContracts.GetContent(), ::onImportResult)
private val scanQrCode =
registerForActivityResult(QRScanActivity.Contract(), ::onScanResult)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val binding = SheetAddProfileBinding.bind(view)
binding.importFromFile.setOnClickListener {
importFromFile.launch("*/*")
}
binding.scanQrCode.setOnClickListener {
scanQrCode.launch(null)
}
@ -99,6 +107,11 @@ class ConfigurationFragment : Fragment() {
}
}
private fun onImportResult(result: Uri?) {
dismiss()
(activity as? MainActivity ?: return).onNewIntent(Intent(Intent.ACTION_VIEW, result))
}
private fun onScanResult(result: Intent?) {
dismiss()
(activity as? MainActivity ?: return).onNewIntent(result ?: return)

View file

@ -15,7 +15,9 @@ import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.Preview
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.view.PreviewView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import io.nekohasekai.libbox.Libbox
import io.nekohasekai.sfa.R
@ -36,6 +38,13 @@ class QRScanActivity : AbstractActivity<ActivityQrScanBinding>() {
setTitle(R.string.profile_add_scan_qr_code)
analysisExecutor = Executors.newSingleThreadExecutor()
binding.previewView.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
binding.previewView.previewStreamState.observe(this) {
if (it === PreviewView.StreamState.STREAMING) {
binding.progress.isVisible = false
binding.previewView.implementationMode = PreviewView.ImplementationMode.PERFORMANCE
}
}
if (ContextCompat.checkSelfPermission(
this, Manifest.permission.CAMERA
) == PackageManager.PERMISSION_GRANTED

View file

@ -30,10 +30,13 @@ import io.nekohasekai.sfa.databinding.ViewAppListItemBinding
import io.nekohasekai.sfa.ktx.clipboardText
import io.nekohasekai.sfa.ui.shared.AbstractActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.util.concurrent.atomic.AtomicInteger
import java.util.zip.ZipFile
class PerAppProxyActivity : AbstractActivity<ActivityPerAppProxyBinding>() {
@ -530,18 +533,26 @@ class PerAppProxyActivity : AbstractActivity<ActivityPerAppProxyBinding>() {
).setView(binding.root).setCancelable(false).create()
progress.show()
lifecycleScope.launch {
val foundApps = withContext(Dispatchers.IO) {
val startTime = System.currentTimeMillis()
val foundApps = withContext(Dispatchers.Default) {
mutableMapOf<String, PackageCache>().also { foundApps ->
currentPackages.forEachIndexed { index, it ->
if (scanChinaPackage(it.packageName)) {
foundApps[it.packageName] = it
val progressInt = AtomicInteger()
currentPackages.map { it ->
async {
if (scanChinaPackage(it.packageName)) {
foundApps[it.packageName] = it
}
runOnUiThread {
binding.progress.progress = progressInt.addAndGet(1)
}
}
withContext(Dispatchers.Main) {
binding.progress.progress = index + 1
}
}
}.awaitAll()
}
}
Log.d(
"PerAppProxyActivity",
"Scan China apps took ${(System.currentTimeMillis() - startTime).toDouble() / 1000}s"
)
withContext(Dispatchers.Main) {
progress.dismiss()
if (foundApps.isEmpty()) {

View file

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:tint="#000000"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp">
<path
android:fillColor="@android:color/white"
android:pathData="M14,2H6C4.9,2 4,2.9 4,4v16c0,1.1 0.89,2 1.99,2H15v-8h5V8L14,2zM13,9V3.5L18.5,9H13zM17,21.66V16h5.66v2h-2.24l2.95,2.95l-1.41,1.41L19,19.41l0,2.24H17z" />
</vector>

View file

@ -28,6 +28,7 @@
android:id="@+id/profileLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="vertical"
android:padding="16dp"

View file

@ -8,6 +8,19 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?colorSurface"
android:gravity="center">
<com.google.android.material.progressindicator.CircularProgressIndicator
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
</LinearLayout>
<include layout="@layout/view_appbar" />
</FrameLayout>

View file

@ -4,7 +4,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_layout"
android:layout_width="match_parent"
@ -31,9 +30,10 @@
android:id="@+id/scanVPNResult"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingBottom="16dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />

View file

@ -24,6 +24,7 @@
android:id="@+id/profileList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:padding="16dp"
android:scrollbars="vertical" />

View file

@ -14,6 +14,9 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/container"
android:clipToPadding="false"
android:padding="16dp"
android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View file

@ -23,6 +23,7 @@
android:id="@+id/logView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:padding="16dp"
android:visibility="gone" />

View file

@ -15,6 +15,31 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:id="@+id/import_from_file"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="?selectableItemBackground"
android:orientation="horizontal">
<ImageView
android:layout_width="64dp"
android:padding="18dp"
app:tint="?colorControlNormal"
android:layout_height="match_parent"
android:src="@drawable/ic_baseline_file_open_24" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceListItem"
android:text="@string/profile_add_import_file"
android:gravity="center_vertical"
android:layout_height="match_parent">
</TextView>
</LinearLayout>
<LinearLayout
android:id="@+id/scan_qr_code"
android:layout_width="match_parent"
@ -32,7 +57,7 @@
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:textSize="16sp"
android:textAppearance="?android:attr/textAppearanceListItem"
android:text="@string/profile_add_scan_qr_code"
android:gravity="center_vertical"
android:layout_height="match_parent">
@ -57,7 +82,7 @@
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:textSize="16sp"
android:textAppearance="?android:attr/textAppearanceListItem"
android:text="@string/profile_add_create_manually"
android:gravity="center_vertical"
android:layout_height="match_parent">

View file

@ -6,8 +6,8 @@
android:clipChildren="false"
android:clipToPadding="false"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
android:layout_marginBottom="16dp"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewElevatedStyle"

View file

@ -4,6 +4,7 @@
style="?attr/preferenceFragmentListStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingTop="0dp"
android:paddingBottom="0dp" />

View file

@ -41,6 +41,7 @@
<string name="profile_source_create_new">Create New</string>
<string name="profile_source_import">Import</string>
<string name="profile_add_import_file">Import from file</string>
<string name="profile_add_scan_qr_code">Scan QR code</string>
<string name="profile_add_scan_use_front_camera">Front camera</string>
<string name="profile_add_scan_use_vendor_analyzer">MLKit analyzer</string>