____ _ _______ __
/ __ \ | /| / / __/ |/ /
/ /_/ / |/ |/ / _// /
\____/|__/|__/___/_||_/
owenclave / app/src/main/java/com/github/shadowsocks/preference/PluginPreferenceDialogFragment.kt
/******************************************************************************
* *
* Copyright (C) 2021 by nekohasekai *
* Copyright (C) 2021 by Max Lv *
* Copyright (C) 2021 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.preference
import android.app.Dialog
import android.content.ActivityNotFoundException
import android.content.Intent
import android.graphics.Typeface
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.TooltipCompat
import androidx.core.os.bundleOf
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.setFragmentResult
import androidx.preference.PreferenceDialogFragmentCompat
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.github.shadowsocks.plugin.Plugin
import com.google.android.material.bottomsheet.BottomSheetDialog
import io.nekohasekai.sagernet.R
import io.nekohasekai.sagernet.database.DataStore
import io.nekohasekai.sagernet.databinding.LayoutIconListItem2Binding
class PluginPreferenceDialogFragment : PreferenceDialogFragmentCompat() {
companion object {
const val KEY_SELECTED_ID = "id"
}
private inner class IconListViewHolder(val dialog: BottomSheetDialog, binding: LayoutIconListItem2Binding) : RecyclerView.ViewHolder(binding.root), View.OnClickListener, View.OnLongClickListener {
private lateinit var plugin: Plugin
private val text1 = binding.text1
private val text2 = binding.text2
private val icon = binding.icon
private val unlock = binding.unlock
init {
binding.root.setOnClickListener(this)
binding.root.setOnLongClickListener(this)
}
fun bind(plugin: Plugin, selected: Boolean = false) {
this.plugin = plugin
val label = plugin.label
text1.text = label
text2.text = plugin.id
val typeface = if (selected) Typeface.BOLD else Typeface.NORMAL
text1.setTypeface(null, typeface)
text2.setTypeface(null, typeface)
text2.isVisible = plugin.id.isNotEmpty() && label != plugin.id
icon.setImageDrawable(plugin.icon)
unlock.isGone = true
}
override fun onClick(v: View?) {
clicked = plugin
dialog.dismiss()
}
override fun onLongClick(v: View?) = try {
startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.Builder()
.scheme("package").opaquePart(plugin.packageName).build()))
true
} catch (_: ActivityNotFoundException) {
false
}
}
private inner class IconListAdapter(private val dialog: BottomSheetDialog) : RecyclerView.Adapter() {
override fun getItemCount(): Int = preference.plugins.size
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
IconListViewHolder(dialog, LayoutIconListItem2Binding.inflate(layoutInflater, parent, false))
override fun onBindViewHolder(holder: IconListViewHolder, position: Int) {
if (selected < 0) holder.bind(preference.plugins[position]) else when (position) {
0 -> holder.bind(preference.selectedEntry!!, true)
in selected + 1..Int.MAX_VALUE -> holder.bind(preference.plugins[position])
else -> holder.bind(preference.plugins[position - 1])
}
}
}
fun setArg(key: String) {
arguments = bundleOf(ARG_KEY to key)
}
private val preference by lazy { getPreference() as PluginPreference }
private val selected by lazy { preference.plugins.indexOf(preference.selectedEntry) }
private var clicked: Plugin? = null
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val activity = requireActivity()
val dialog = BottomSheetDialog(activity, theme)
val recycler = RecyclerView(activity)
val padding = resources.getDimensionPixelOffset(R.dimen.bottom_sheet_padding)
recycler.setPadding(0, padding, 0, padding)
recycler.setHasFixedSize(true)
recycler.layoutManager = LinearLayoutManager(activity)
recycler.itemAnimator = DefaultItemAnimator()
recycler.adapter = IconListAdapter(dialog)
recycler.layoutParams =
ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
dialog.setContentView(recycler)
return dialog
}
override fun onDialogClosed(positiveResult: Boolean) {
val clicked = clicked
if (clicked != null && clicked != preference.selectedEntry) {
setFragmentResult(javaClass.name, bundleOf(KEY_SELECTED_ID to clicked.id))
}
}
}