Commit 72995830 authored by Mygod's avatar Mygod Committed by Max Lv

Move search view up into toolbar

parent 12527be0
......@@ -47,8 +47,7 @@
<string name="proxied_apps_summary">Configure VPN mode for selected apps</string>
<string name="on">On</string>
<string name="off">Off</string>
<string name="mode">Mode</string>
<string name="quick_search">Quick search</string>
<string name="proxied_apps_mode">Mode</string>
<string name="bypass_apps">Bypass</string>
<string name="bypass_apps_summary">Enable this option to bypass selected apps</string>
<string name="auto_connect">Auto Connect</string>
......
......@@ -32,13 +32,12 @@ import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.view.*
import android.widget.*
import android.widget.Filter
import android.widget.Filterable
import android.widget.SearchView
import androidx.annotation.UiThread
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.content.getSystemService
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
......@@ -51,6 +50,8 @@ import com.github.shadowsocks.utils.Key
import com.google.android.material.snackbar.Snackbar
import com.google.common.collect.Multimap
import com.google.common.collect.MultimapBuilder
import kotlinx.android.synthetic.main.layout_apps.*
import kotlinx.android.synthetic.main.layout_apps_item.view.*
import kotlinx.coroutines.*
class AppManager : AppCompatActivity() {
......@@ -93,30 +94,22 @@ class AppManager : AppCompatActivity() {
}
private inner class AppViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener {
private val icon = view.findViewById<ImageView>(R.id.itemicon)
private val check = view.findViewById<Switch>(R.id.itemcheck)
private val tvTitle = view.findViewById<TextView>(R.id.title)
private val tvDesc = view.findViewById<TextView>(R.id.desc)
private lateinit var item: ProxiedApp
init {
view.setOnClickListener(this)
}
@SuppressLint("SetTextI18n")
fun bind(app: ProxiedApp) {
this.item = app
icon.setImageDrawable(app.icon)
tvTitle.text = app.name
tvDesc.text = "${app.packageName} (${app.uid})"
check.isChecked = isProxiedApp(app)
item = app
itemView.itemicon.setImageDrawable(app.icon)
itemView.title.text = app.name
itemView.desc.text = "${app.packageName} (${app.uid})"
itemView.itemcheck.isChecked = isProxiedApp(app)
}
fun handlePayload(payloads: List<String>) {
if (payloads.contains("switch")) {
check.isChecked = isProxiedApp(item)
}
if (payloads.contains("switch")) itemView.itemcheck.isChecked = isProxiedApp(item)
}
override fun onClick(v: View?) {
......@@ -169,14 +162,10 @@ class AppManager : AppCompatActivity() {
override fun getFilter(): Filter {
return object : Filter() {
override fun performFiltering(constraint: CharSequence): FilterResults {
val filteredApps = if (constraint.isEmpty()) {
apps
} else {
apps.filter {
it.name.contains(constraint, true) ||
it.packageName.contains(constraint, true) ||
it.uid.toString().contains(constraint)
}
val filteredApps = if (constraint.isEmpty()) apps else apps.filter {
it.name.contains(constraint, true) ||
it.packageName.contains(constraint, true) ||
it.uid.toString().contains(constraint)
}
return FilterResults().also {
......@@ -196,11 +185,6 @@ class AppManager : AppCompatActivity() {
private lateinit var proxiedApps: HashSet<String>
private lateinit var proxiedUidMap: Multimap<Int, String>
private lateinit var toolbar: Toolbar
private lateinit var bypassGroup: RadioGroup
private lateinit var appListView: RecyclerView
private lateinit var loadingView: View
private lateinit var editQuery: EditText
private lateinit var appsAdapter: AppsAdapter
private val clipboard by lazy { getSystemService<ClipboardManager>()!! }
private var loader: Job? = null
......@@ -231,25 +215,24 @@ class AppManager : AppCompatActivity() {
private fun loadApps() {
loader?.cancel()
loader = GlobalScope.launch(Dispatchers.Main, CoroutineStart.UNDISPATCHED) {
loadingView.crossFadeFrom(appListView)
val adapter = appListView.adapter as AppsAdapter
loading.crossFadeFrom(list)
val adapter = list.adapter as AppsAdapter
withContext(Dispatchers.IO) { adapter.reload() }
val queryText = editQuery.text
if (queryText.isEmpty()) {
val queryText = search.query
if (queryText.isNullOrEmpty()) {
adapter.notifyDataSetChanged()
} else {
adapter.filter.filter(queryText)
}
appListView.crossFadeFrom(loadingView)
list.crossFadeFrom(loading)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.layout_apps)
toolbar = findViewById(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
......@@ -258,7 +241,6 @@ class AppManager : AppCompatActivity() {
DataStore.dirty = true
}
bypassGroup = findViewById(R.id.bypass_group)
bypassGroup.check(if (DataStore.bypass) R.id.btn_bypass else R.id.btn_on)
bypassGroup.setOnCheckedChangeListener { _, checkedId ->
DataStore.dirty = true
......@@ -273,24 +255,14 @@ class AppManager : AppCompatActivity() {
}
initProxiedApps()
loadingView = findViewById(R.id.loading)
appListView = findViewById(R.id.list)
appListView.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
appListView.itemAnimator = DefaultItemAnimator()
list.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false)
list.itemAnimator = DefaultItemAnimator()
appsAdapter = AppsAdapter()
appListView.adapter = appsAdapter
editQuery = findViewById(R.id.edit_query)
editQuery.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
list.adapter = appsAdapter
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
appsAdapter.filter.filter(s)
}
search.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?) = false
override fun onQueryTextChange(newText: String?) = true.also { appsAdapter.filter.filter(newText) }
})
instance = this
......@@ -312,14 +284,14 @@ class AppManager : AppCompatActivity() {
ProfileManager.updateProfile(it)
}
if (DataStore.directBootAware) DirectBoot.update()
Snackbar.make(appListView, R.string.action_apply_all, Snackbar.LENGTH_LONG).show()
} else Snackbar.make(appListView, R.string.action_export_err, Snackbar.LENGTH_LONG).show()
Snackbar.make(list, R.string.action_apply_all, Snackbar.LENGTH_LONG).show()
} else Snackbar.make(list, R.string.action_export_err, Snackbar.LENGTH_LONG).show()
return true
}
R.id.action_export_clipboard -> {
clipboard.primaryClip = ClipData.newPlainText(Key.individual,
"${DataStore.bypass}\n${DataStore.individual}")
Snackbar.make(appListView, R.string.action_export_msg, Snackbar.LENGTH_LONG).show()
Snackbar.make(list, R.string.action_export_msg, Snackbar.LENGTH_LONG).show()
return true
}
R.id.action_import_clipboard -> {
......@@ -332,13 +304,13 @@ class AppManager : AppCompatActivity() {
bypassGroup.check(if (enabled.toBoolean()) R.id.btn_bypass else R.id.btn_on)
DataStore.individual = apps
DataStore.dirty = true
Snackbar.make(appListView, R.string.action_import_msg, Snackbar.LENGTH_LONG).show()
Snackbar.make(list, R.string.action_import_msg, Snackbar.LENGTH_LONG).show()
initProxiedApps(apps)
loadApps()
return true
} catch (_: IllegalArgumentException) { }
}
Snackbar.make(appListView, R.string.action_import_err, Snackbar.LENGTH_LONG).show()
Snackbar.make(list, R.string.action_import_err, Snackbar.LENGTH_LONG).show()
}
}
return false
......
......@@ -7,10 +7,27 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:duplicateParentState="false">
<include layout="@layout/toolbar_light_dark"/>
<androidx.appcompat.widget.Toolbar
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:touchscreenBlocksFocus="false"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.DayNight"
android:id="@+id/toolbar">
<SearchView
android:id="@+id/search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:iconifiedByDefault="false"
android:queryHint="@android:string/search_go"/>
</androidx.appcompat.widget.Toolbar>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/linearLayout2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?android:colorBackground"
......@@ -22,13 +39,13 @@
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:minWidth="40dp"
android:text="@string/mode"
app:layout_constraintBottom_toBottomOf="@+id/bypass_group"
android:text="@string/proxied_apps_mode"
app:layout_constraintBottom_toBottomOf="@+id/bypassGroup"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/bypass_group" />
app:layout_constraintTop_toTopOf="@+id/bypassGroup" />
<RadioGroup
android:id="@+id/bypass_group"
android:id="@+id/bypassGroup"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
......@@ -62,20 +79,6 @@
android:tooltipText="@string/bypass_apps_summary" />
</RadioGroup>
<EditText
android:id="@+id/edit_query"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="68dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:hint="@string/quick_search"
android:inputType="textFilter"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/bypass_group" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.coordinatorlayout.widget.CoordinatorLayout
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment