owenclave / app/src/main/java/com/github/shadowsocks/preference/PluginPreferenceDialogFragment.kt

github - dev - back to tree - upstream
/****************************************************************************** * * * 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)) } } }