Commit 5ced4212 authored by Mygod's avatar Mygod

Implement ActionMode for CustomRulesFragment

parent 3f88b463
...@@ -20,21 +20,21 @@ ...@@ -20,21 +20,21 @@
package com.github.shadowsocks.acl package com.github.shadowsocks.acl
import android.annotation.TargetApi
import android.content.ClipData import android.content.ClipData
import android.content.ClipboardManager import android.content.ClipboardManager
import android.content.Context import android.content.Context
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.support.design.widget.Snackbar import android.support.design.widget.Snackbar
import android.support.v4.content.ContextCompat
import android.support.v7.app.AlertDialog import android.support.v7.app.AlertDialog
import android.support.v7.widget.DefaultItemAnimator import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView import android.support.v7.widget.RecyclerView
import android.support.v7.widget.Toolbar import android.support.v7.widget.Toolbar
import android.support.v7.widget.helper.ItemTouchHelper import android.support.v7.widget.helper.ItemTouchHelper
import android.view.LayoutInflater import android.view.*
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.EditText import android.widget.EditText
import android.widget.Spinner import android.widget.Spinner
import android.widget.TextView import android.widget.TextView
...@@ -48,12 +48,13 @@ import com.github.shadowsocks.ToolbarFragment ...@@ -48,12 +48,13 @@ import com.github.shadowsocks.ToolbarFragment
import com.github.shadowsocks.bg.BaseService import com.github.shadowsocks.bg.BaseService
import com.github.shadowsocks.utils.Subnet import com.github.shadowsocks.utils.Subnet
import com.github.shadowsocks.utils.asIterable import com.github.shadowsocks.utils.asIterable
import com.github.shadowsocks.utils.resolveResourceId
import com.github.shadowsocks.widget.UndoSnackbarManager import com.github.shadowsocks.widget.UndoSnackbarManager
import java.net.IDN import java.net.IDN
import java.net.URL import java.net.URL
import java.util.* import java.util.*
class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener, ActionMode.Callback {
companion object { companion object {
private const val TEMPLATE_REGEX_DOMAIN = "(^|\\.)%s$" private const val TEMPLATE_REGEX_DOMAIN = "(^|\\.)%s$"
...@@ -288,13 +289,12 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -288,13 +289,12 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
private val selectedItems = HashSet<Any>() private val selectedItems = HashSet<Any>()
private val adapter by lazy { AclRulesAdapter() } private val adapter by lazy { AclRulesAdapter() }
private lateinit var list: RecyclerView private lateinit var list: RecyclerView
private var selectionItem: MenuItem? = null private var mode: ActionMode? = null
private lateinit var undoManager: UndoSnackbarManager<Any> private lateinit var undoManager: UndoSnackbarManager<Any>
private val clipboard by lazy { activity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager } private val clipboard by lazy { activity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager }
private fun onSelectedItemsUpdated() { private fun onSelectedItemsUpdated() {
val selectionItem = selectionItem if (selectedItems.isEmpty()) mode?.finish() else if (mode == null) mode = toolbar.startActionMode(this)
if (selectionItem != null) selectionItem.isVisible = selectedItems.isNotEmpty()
} }
private fun createAclRuleDialog(item: Any = ""): Triple<Spinner, EditText, AlertDialog.Builder> { private fun createAclRuleDialog(item: Any = ""): Triple<Spinner, EditText, AlertDialog.Builder> {
...@@ -345,9 +345,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -345,9 +345,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
toolbar.setTitle(R.string.custom_rules) toolbar.setTitle(R.string.custom_rules)
toolbar.inflateMenu(R.menu.custom_rules_menu) toolbar.inflateMenu(R.menu.custom_rules_menu)
toolbar.setOnMenuItemClickListener(this) toolbar.setOnMenuItemClickListener(this)
val selectionItem = toolbar.menu.findItem(R.id.selection)
selectionItem.isVisible = selectedItems.isNotEmpty()
this.selectionItem = selectionItem
list = view.findViewById(R.id.list) list = view.findViewById(R.id.list)
list.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false) list.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
list.itemAnimator = DefaultItemAnimator() list.itemAnimator = DefaultItemAnimator()
...@@ -365,10 +362,9 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -365,10 +362,9 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
} }
override fun onBackPressed(): Boolean { override fun onBackPressed(): Boolean {
return if (selectedItems.isNotEmpty()) { val mode = mode
selectedItems.clear() return if (mode != null) {
onSelectedItemsUpdated() mode.finish()
adapter.notifyDataSetChanged()
true true
} else super.onBackPressed() } else super.onBackPressed()
} }
...@@ -395,24 +391,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -395,24 +391,6 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
} }
override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) { override fun onMenuItemClick(item: MenuItem): Boolean = when (item.itemId) {
R.id.action_select_all -> {
adapter.selectAll()
true
}
R.id.action_cut -> {
copySelected()
adapter.removeSelected()
true
}
R.id.action_copy -> {
copySelected()
true
}
R.id.action_delete -> {
adapter.removeSelected()
true
}
R.id.action_manual_settings -> { R.id.action_manual_settings -> {
val (templateSelector, editText, dialog) = createAclRuleDialog() val (templateSelector, editText, dialog) = createAclRuleDialog()
dialog.setPositiveButton(android.R.string.ok, { _, _ -> dialog.setPositiveButton(android.R.string.ok, { _, _ ->
...@@ -444,4 +422,50 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener { ...@@ -444,4 +422,50 @@ class CustomRulesFragment : ToolbarFragment(), Toolbar.OnMenuItemClickListener {
undoManager.flush() undoManager.flush()
super.onDetach() super.onDetach()
} }
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
val activity = activity!!
val window = activity.window
// In the end material_grey_100 is used for background, see AppCompatDrawableManager (very complicated)
if (Build.VERSION.SDK_INT >= 23) {
window.statusBarColor = ContextCompat.getColor(activity, R.color.material_grey_300)
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else window.statusBarColor = ContextCompat.getColor(activity, R.color.material_grey_600)
activity.menuInflater.inflate(R.menu.custom_rules_selection, menu)
toolbar.touchscreenBlocksFocus = true
return true
}
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean = false
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean = when (item.itemId) {
R.id.action_select_all -> {
adapter.selectAll()
true
}
R.id.action_cut -> {
copySelected()
adapter.removeSelected()
true
}
R.id.action_copy -> {
copySelected()
true
}
R.id.action_delete -> {
adapter.removeSelected()
true
}
else -> false
}
override fun onDestroyActionMode(mode: ActionMode) {
val activity = activity!!
val window = activity.window
window.statusBarColor = ContextCompat.getColor(activity,
activity.theme.resolveResourceId(android.R.attr.statusBarColor))
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
toolbar.touchscreenBlocksFocus = false
selectedItems.clear()
onSelectedItemsUpdated()
adapter.notifyDataSetChanged()
this.mode = null
}
} }
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path <path
android:fillColor="#FFFFFFFF" android:fillColor="#FFFFFFFF"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/> android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
<animated-vector <animated-vector
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools" android:drawable="@drawable/ic_service_busy">
android:drawable="@drawable/ic_service_busy"
tools:ignore="NewApi">
<target android:name="path"> <target android:name="path">
<aapt:attr name="android:animation"> <aapt:attr name="android:animation">
<objectAnimator <objectAnimator
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
<animated-vector <animated-vector
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools" android:drawable="@drawable/ic_service_idle">
android:drawable="@drawable/ic_service_idle"
tools:ignore="NewApi">
<target android:name="strike_thru_path"> <target android:name="strike_thru_path">
<aapt:attr name="android:animation"> <aapt:attr name="android:animation">
<objectAnimator <objectAnimator
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
<animated-vector <animated-vector
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools" android:drawable="@drawable/ic_service_idle">
android:drawable="@drawable/ic_service_idle"
tools:ignore="NewApi">
<target android:name="strike_thru_path"> <target android:name="strike_thru_path">
<aapt:attr name="android:animation"> <aapt:attr name="android:animation">
<objectAnimator <objectAnimator
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
<animated-vector <animated-vector
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt" xmlns:aapt="http://schemas.android.com/aapt"
xmlns:tools="http://schemas.android.com/tools" android:drawable="@drawable/ic_service_busy">
android:drawable="@drawable/ic_service_busy"
tools:ignore="NewApi">
<target android:name="path"> <target android:name="path">
<aapt:attr name="android:animation"> <aapt:attr name="android:animation">
<objectAnimator <objectAnimator
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/selection"
android:alphabeticShortcut="s"
android:icon="?attr/actionModeSelectAllDrawable"
android:numericShortcut="0"
android:title="@string/action_selection"
android:visible="false"
app:showAsAction="always">
<menu>
<item
android:id="@+id/action_select_all"
android:alphabeticShortcut="a"
android:numericShortcut="1"
android:title="@android:string/selectAll"
app:showAsAction="always"/>
<item
android:id="@+id/action_cut"
android:alphabeticShortcut="t"
android:numericShortcut="2"
android:title="@android:string/cut"
app:showAsAction="always"/>
<item
android:id="@+id/action_copy"
android:alphabeticShortcut="c"
android:numericShortcut="3"
android:title="@android:string/copy"
app:showAsAction="always"/>
<item
android:id="@+id/action_delete"
android:alphabeticShortcut="d"
android:numericShortcut="4"
android:title="@string/delete"
app:showAsAction="always"/>
</menu>
</item>
<item android:title="@string/action_add_rule" <item android:title="@string/action_add_rule"
android:icon="@drawable/ic_av_playlist_add" android:icon="@drawable/ic_av_playlist_add"
android:alphabeticShortcut="a" android:alphabeticShortcut="a"
......
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="AppCompatResource">
<item
android:id="@+id/action_select_all"
android:alphabeticShortcut="a"
android:icon="?attr/actionModeSelectAllDrawable"
android:numericShortcut="1"
android:title="@android:string/selectAll"
android:showAsAction="always"/>
<item
android:id="@+id/action_cut"
android:alphabeticShortcut="t"
android:icon="?attr/actionModeCutDrawable"
android:numericShortcut="2"
android:title="@android:string/cut"
android:showAsAction="always"/>
<item
android:id="@+id/action_copy"
android:alphabeticShortcut="c"
android:icon="?attr/actionModeCopyDrawable"
android:numericShortcut="3"
android:title="@android:string/copy"
android:showAsAction="always"/>
<item
android:id="@+id/action_delete"
android:alphabeticShortcut="d"
android:icon="@drawable/ic_action_delete"
android:numericShortcut="4"
android:title="@string/delete"
android:showAsAction="always"/>
</menu>
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="24.0" android:viewportWidth="24.0"
android:viewportHeight="24.0"> android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path <path
android:fillColor="#FFFFFFFF" android:fillColor="#FFFFFFFF"
android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/> android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<style name="Theme.Shadowsocks" parent="PreferenceFixTheme.Light.NoActionBar"> <style name="Theme.Shadowsocks" parent="PreferenceFixTheme.Light.NoActionBar">
<!--suppress NewApi -->
<item name="android:navigationBarColor">@color/material_primary_700</item> <item name="android:navigationBarColor">@color/material_primary_700</item>
<item name="actionModeCloseDrawable">@drawable/ic_navigation_close</item>
<item name="colorAccent">@color/material_accent_200</item> <item name="colorAccent">@color/material_accent_200</item>
<item name="colorButtonNormal">@color/material_accent_200</item> <item name="colorButtonNormal">@color/material_accent_200</item>
<item name="colorPrimary">@color/material_primary_500</item> <item name="colorPrimary">@color/material_primary_500</item>
<item name="colorPrimaryDark">@color/material_primary_700</item> <item name="colorPrimaryDark">@color/material_primary_700</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material.Fix</item> <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material.Fix</item>
<item name="preferenceCategory_marginBottom">8dp</item> <item name="preferenceCategory_marginBottom">8dp</item>
<item name="windowActionModeOverlay">true</item>
</style> </style>
</resources> </resources>
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