diff --git a/app/src/main/java/com/github/shadowsocks/plugin/v2ray/CertificatePreferenceDialogFragment.kt b/app/src/main/java/com/github/shadowsocks/plugin/v2ray/CertificatePreferenceDialogFragment.kt new file mode 100644 index 0000000..a1a18b1 --- /dev/null +++ b/app/src/main/java/com/github/shadowsocks/plugin/v2ray/CertificatePreferenceDialogFragment.kt @@ -0,0 +1,52 @@ +/******************************************************************************* + * * + * Copyright (C) 2019 by Max Lv * + * Copyright (C) 2019 by Mygod Studio * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +package com.github.shadowsocks.plugin.v2ray + +import android.content.ActivityNotFoundException +import android.content.Intent +import android.view.View +import androidx.appcompat.app.AlertDialog +import androidx.core.os.bundleOf +import androidx.preference.EditTextPreferenceDialogFragmentCompat +import com.google.android.material.snackbar.Snackbar + +class CertificatePreferenceDialogFragment : EditTextPreferenceDialogFragmentCompat() { + fun setKey(key: String) { + arguments = bundleOf(Pair(ARG_KEY, key)) + } + + override fun onPrepareDialogBuilder(builder: AlertDialog.Builder) { + super.onPrepareDialogBuilder(builder) + builder.setNeutralButton("Browse…") { _, _ -> + val activity = requireActivity() + try { + targetFragment!!.startActivityForResult(Intent(Intent.ACTION_GET_CONTENT).apply { + addCategory(Intent.CATEGORY_OPENABLE) + type = "application/pkix-cert" + }, ConfigFragment.REQUEST_BROWSE_CERTIFICATE) + return@setNeutralButton + } catch (_: ActivityNotFoundException) { } catch (_: SecurityException) { } + Snackbar.make(activity.findViewById(R.id.content), + "Please install a file manager like MiXplorer", + Snackbar.LENGTH_SHORT).show() + } + } +} diff --git a/app/src/main/java/com/github/shadowsocks/plugin/v2ray/ConfigFragment.kt b/app/src/main/java/com/github/shadowsocks/plugin/v2ray/ConfigFragment.kt index c7bc823..bbe2d9c 100644 --- a/app/src/main/java/com/github/shadowsocks/plugin/v2ray/ConfigFragment.kt +++ b/app/src/main/java/com/github/shadowsocks/plugin/v2ray/ConfigFragment.kt @@ -20,14 +20,23 @@ package com.github.shadowsocks.plugin.v2ray +import android.app.Activity +import android.content.Intent import android.os.Bundle +import android.view.View import androidx.preference.EditTextPreference import androidx.preference.ListPreference import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import com.github.shadowsocks.plugin.PluginOptions +import com.google.android.material.snackbar.Snackbar +import java.lang.RuntimeException class ConfigFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener { + companion object { + const val REQUEST_BROWSE_CERTIFICATE = 1 + } + private val mode by lazy { findPreference("mode") } private val host by lazy { findPreference("host") } private val path by lazy { findPreference("path") } @@ -53,7 +62,7 @@ class ConfigFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChange putWithDefault("tls", tls) putWithDefault("host", host.text, "cloudfront.com") putWithDefault("path", path.text, "/") - putWithDefault("certRaw", certRaw.text, "") + putWithDefault("certRaw", certRaw.text.replace("\n", ""), "") } fun onInitializePluginOptions(options: PluginOptions) { @@ -78,4 +87,29 @@ class ConfigFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChange certRaw.isEnabled = mode != null || tls != null return true } + + override fun onDisplayPreferenceDialog(preference: Preference?) { + if (preference == certRaw) CertificatePreferenceDialogFragment().apply { + setKey(certRaw.key) + setTargetFragment(this@ConfigFragment, 0) + }.show(fragmentManager ?: return, certRaw.key) else super.onDisplayPreferenceDialog(preference) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + when (requestCode) { + REQUEST_BROWSE_CERTIFICATE -> { + if (resultCode != Activity.RESULT_OK) return + val activity = requireActivity() + try { + // we read all its content here to avoid content URL permission issues + certRaw.text = activity.contentResolver.openInputStream(data!!.data!!)!! + .bufferedReader().readText() + } catch (e: RuntimeException) { + Snackbar.make(activity.findViewById(R.id.content), e.localizedMessage, Snackbar.LENGTH_LONG) + .show() + } + } + else -> super.onActivityResult(requestCode, resultCode, data) + } + } }