Refine Tasker features
This commit is contained in:
@@ -93,7 +93,7 @@ class ProfileManagerActivity extends AppCompatActivity with OnMenuItemClickListe
|
||||
private class ProfilesAdapter extends RecyclerView.Adapter[ProfileViewHolder] {
|
||||
private val recycleBin = new ArrayBuffer[(Int, Profile)]
|
||||
private var profiles = new ArrayBuffer[Profile]
|
||||
profiles ++= ShadowsocksApplication.profileManager.getAllProfiles.getOrElse(List[Profile]())
|
||||
profiles ++= ShadowsocksApplication.profileManager.getAllProfiles.getOrElse(List.empty[Profile])
|
||||
|
||||
def getItemCount = profiles.length
|
||||
|
||||
|
||||
@@ -39,25 +39,63 @@
|
||||
package com.github.shadowsocks
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.support.v4.app.{Fragment, ListFragment}
|
||||
import android.content.res.Resources
|
||||
import android.os.{Build, Bundle}
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.widget.Toolbar
|
||||
import android.util.Log
|
||||
import android.support.v7.widget.{DefaultItemAnimator, LinearLayoutManager, RecyclerView, Toolbar}
|
||||
import android.view.{LayoutInflater, View, ViewGroup}
|
||||
import android.widget.AdapterView.OnItemClickListener
|
||||
import android.widget._
|
||||
import android.widget.{Switch, CheckedTextView}
|
||||
import com.github.shadowsocks.database.Profile
|
||||
import com.github.shadowsocks.helper.TaskerSettings
|
||||
import com.twofortyfouram.locale.api.{Intent => ApiIntent}
|
||||
|
||||
/**
|
||||
* @author CzBiX
|
||||
*/
|
||||
class TaskerActivity extends AppCompatActivity {
|
||||
var taskerOption: TaskerSettings = _
|
||||
var actionSelected: Boolean = false
|
||||
private class ProfileViewHolder(val view: View) extends RecyclerView.ViewHolder(view) with View.OnClickListener {
|
||||
{
|
||||
val typedArray = obtainStyledAttributes(Array(android.R.attr.selectableItemBackground))
|
||||
view.setBackgroundResource(typedArray.getResourceId(0, 0))
|
||||
typedArray.recycle
|
||||
}
|
||||
private var item: Profile = _
|
||||
private val text = itemView.findViewById(android.R.id.text1).asInstanceOf[CheckedTextView]
|
||||
itemView.setOnClickListener(this)
|
||||
|
||||
def bindDefault {
|
||||
item = null
|
||||
text.setText(R.string.profile_default)
|
||||
text.setChecked(taskerOption.profileId < 0)
|
||||
}
|
||||
def bind(item: Profile) {
|
||||
this.item = item
|
||||
text.setText(item.name)
|
||||
text.setChecked(taskerOption.profileId == item.id)
|
||||
}
|
||||
|
||||
def onClick(v: View) {
|
||||
taskerOption.switchOn = switch.isChecked
|
||||
taskerOption.profileId = if (item == null) -1 else item.id
|
||||
setResult(Activity.RESULT_OK, taskerOption.toIntent(TaskerActivity.this))
|
||||
finish
|
||||
}
|
||||
}
|
||||
|
||||
private class ProfilesAdapter extends RecyclerView.Adapter[ProfileViewHolder] {
|
||||
private val profiles = ShadowsocksApplication.profileManager.getAllProfiles.getOrElse(List.empty[Profile])
|
||||
def getItemCount = 1 + profiles.length
|
||||
def onBindViewHolder(vh: ProfileViewHolder, i: Int) = i match {
|
||||
case 0 => vh.bindDefault
|
||||
case _ => vh.bind(profiles(i - 1))
|
||||
}
|
||||
private val name = "select_dialog_singlechoice_" + (if (Build.VERSION.SDK_INT >= 21) "material" else "holo")
|
||||
def onCreateViewHolder(vg: ViewGroup, i: Int) = new ProfileViewHolder(LayoutInflater.from(vg.getContext)
|
||||
.inflate(Resources.getSystem.getIdentifier(name, "layout", "android"), vg, false))
|
||||
}
|
||||
|
||||
private var taskerOption: TaskerSettings = _
|
||||
private var switch: Switch = _
|
||||
private val profilesAdapter = new ProfilesAdapter
|
||||
|
||||
override def onCreate(savedInstanceState: Bundle) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@@ -67,155 +105,14 @@ class TaskerActivity extends AppCompatActivity {
|
||||
toolbar.setTitle(R.string.app_name)
|
||||
toolbar.setNavigationIcon(R.drawable.ic_close)
|
||||
toolbar.setNavigationOnClickListener(_ => finish())
|
||||
toolbar.inflateMenu(R.menu.tasker_menu)
|
||||
toolbar.setOnMenuItemClickListener(_.getItemId match {
|
||||
case R.id.save =>
|
||||
saveResult()
|
||||
true
|
||||
case _ => false
|
||||
})
|
||||
|
||||
loadSettings()
|
||||
loadFragment()
|
||||
}
|
||||
|
||||
private def loadSettings() {
|
||||
val intent: Intent = getIntent
|
||||
if (intent.getAction != ApiIntent.ACTION_EDIT_SETTING) {
|
||||
Log.w(Shadowsocks.TAG, "unknown tasker action")
|
||||
finish()
|
||||
return
|
||||
}
|
||||
|
||||
taskerOption = TaskerSettings.fromIntent(intent)
|
||||
}
|
||||
|
||||
private def loadFragment() {
|
||||
actionSelected = !taskerOption.isEmpty
|
||||
val fragment: Fragment = taskerOption.action match {
|
||||
case TaskerSettings.ACTION_TOGGLE_SERVICE =>
|
||||
new ToggleServiceFragment
|
||||
case TaskerSettings.ACTION_SWITCH_PROFILE =>
|
||||
new ProfileChoiceFragment
|
||||
case _ =>
|
||||
val fragment: ActionChoiceFragment = new ActionChoiceFragment
|
||||
fragment.onItemClickedListener = (_, _, _, id) => {
|
||||
taskerOption.action = getResources.getStringArray(R.array.tasker_action_value)(id.toInt)
|
||||
loadFragment()
|
||||
actionSelected = true
|
||||
}
|
||||
fragment
|
||||
}
|
||||
|
||||
getSupportFragmentManager.beginTransaction()
|
||||
.replace(R.id.fragment, fragment)
|
||||
.commit()
|
||||
}
|
||||
|
||||
private def saveResult() {
|
||||
if (actionSelected) {
|
||||
val fragment: OptionFragment = getSupportFragmentManager.findFragmentById(R.id.fragment).asInstanceOf[OptionFragment]
|
||||
if (fragment.saveResult()) {
|
||||
setResult(Activity.RESULT_OK, taskerOption.toIntent(this))
|
||||
finish()
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(this, R.string.no_action_selected, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
private class ActionChoiceFragment extends ListFragment {
|
||||
var onItemClickedListener: OnItemClickListener = _
|
||||
|
||||
override def onActivityCreated(savedInstanceState: Bundle) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
val adapter = ArrayAdapter.createFromResource(getActivity, R.array.tasker_action_name, android.R.layout.simple_selectable_list_item)
|
||||
|
||||
setListAdapter(adapter)
|
||||
}
|
||||
|
||||
override def onListItemClick(l: ListView, v: View, position: Int, id: Long) {
|
||||
if (onItemClickedListener != null) {
|
||||
onItemClickedListener.onItemClick(l, v, position, id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ToggleServiceFragment extends Fragment with OptionFragment {
|
||||
var switch: Switch = _
|
||||
|
||||
override def onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle): View = {
|
||||
val view: View = inflater.inflate(R.layout.layout_tasker_toggle_service, container, false)
|
||||
|
||||
switch = view.findViewById(R.id.service_switch).asInstanceOf[Switch]
|
||||
view
|
||||
}
|
||||
|
||||
override def onActivityCreated(savedInstanceState: Bundle) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
if (!taskerOption.isEmpty) {
|
||||
switch.setChecked(taskerOption.isStart)
|
||||
}
|
||||
}
|
||||
|
||||
override def saveResult() = {
|
||||
taskerOption.action = TaskerSettings.ACTION_TOGGLE_SERVICE
|
||||
taskerOption.isStart = switch.isChecked
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
private class ProfileChoiceFragment extends ListFragment with OptionFragment {
|
||||
override def onActivityCreated(savedInstanceState: Bundle) {
|
||||
super.onActivityCreated(savedInstanceState)
|
||||
|
||||
import scala.collection.JavaConverters._
|
||||
val profiles = ShadowsocksApplication.profileManager.getAllProfiles.getOrElse(List.empty)
|
||||
val adapter = new ArrayAdapter[Profile](getActivity, 0, android.R.id.text1, profiles.asJava) {
|
||||
override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
|
||||
val view: TextView = if (convertView == null) {
|
||||
val inflater = LayoutInflater.from(parent.getContext)
|
||||
inflater.inflate(android.R.layout.simple_list_item_single_choice, parent, false).asInstanceOf[TextView]
|
||||
} else {
|
||||
convertView.asInstanceOf[TextView]
|
||||
}
|
||||
|
||||
view.setText(getItem(position).name)
|
||||
view
|
||||
}
|
||||
}
|
||||
|
||||
setListAdapter(adapter)
|
||||
|
||||
val listView: ListView = getListView
|
||||
listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE)
|
||||
|
||||
if (!taskerOption.isEmpty) {
|
||||
val index = profiles.indexWhere(_.id == taskerOption.profileId)
|
||||
if (index > -1) {
|
||||
listView.setItemChecked(index, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def saveResult() = {
|
||||
taskerOption.action = TaskerSettings.ACTION_SWITCH_PROFILE
|
||||
val listView = getListView
|
||||
val item = listView.getItemAtPosition(listView.getCheckedItemPosition)
|
||||
if (item == null) {
|
||||
Toast.makeText(getActivity, R.string.no_profile_selected, Toast.LENGTH_SHORT).show()
|
||||
false
|
||||
} else {
|
||||
taskerOption.profileId = item.asInstanceOf[Profile].id
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait OptionFragment extends Fragment {
|
||||
def saveResult(): Boolean
|
||||
taskerOption = TaskerSettings.fromIntent(getIntent)
|
||||
switch = findViewById(R.id.serviceSwitch).asInstanceOf[Switch]
|
||||
switch.setChecked(taskerOption.switchOn)
|
||||
val profilesList = findViewById(R.id.profilesList).asInstanceOf[RecyclerView]
|
||||
profilesList.setLayoutManager(new LinearLayoutManager(this))
|
||||
profilesList.setItemAnimator(new DefaultItemAnimator)
|
||||
profilesList.setAdapter(profilesAdapter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,6 @@
|
||||
package com.github.shadowsocks
|
||||
|
||||
import android.content.{BroadcastReceiver, Context, Intent}
|
||||
import android.util.Log
|
||||
import com.github.shadowsocks.helper.TaskerSettings
|
||||
import com.github.shadowsocks.utils.Utils
|
||||
|
||||
@@ -47,20 +46,15 @@ import com.github.shadowsocks.utils.Utils
|
||||
* @author CzBiX
|
||||
*/
|
||||
class TaskerReceiver extends BroadcastReceiver {
|
||||
override def onReceive(context: Context, intent: Intent): Unit = {
|
||||
val settings: TaskerSettings = TaskerSettings.fromIntent(intent)
|
||||
|
||||
settings.action match {
|
||||
case TaskerSettings.ACTION_TOGGLE_SERVICE =>
|
||||
if (settings.isStart) {
|
||||
Utils.startSsService(context)
|
||||
} else {
|
||||
Utils.stopSsService(context)
|
||||
}
|
||||
case TaskerSettings.ACTION_SWITCH_PROFILE =>
|
||||
override def onReceive(context: Context, intent: Intent) {
|
||||
val settings = TaskerSettings.fromIntent(intent)
|
||||
val switched = ShadowsocksApplication.profileManager.getProfile(settings.profileId) match {
|
||||
case Some(p) =>
|
||||
Utils.stopSsService(context)
|
||||
ShadowsocksApplication.switchProfile(settings.profileId)
|
||||
case _ =>
|
||||
Log.e(Shadowsocks.TAG, s"unknown tasker action: ${settings.action}")
|
||||
true
|
||||
case _ => false
|
||||
}
|
||||
if (settings.switchOn) Utils.startSsService(context) else if (!switched) Utils.stopSsService(context)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,78 +40,35 @@ package com.github.shadowsocks.helper
|
||||
|
||||
import android.content.{Context, Intent}
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import com.github.shadowsocks.{R, Shadowsocks, ShadowsocksApplication}
|
||||
import com.github.shadowsocks.{R, ShadowsocksApplication}
|
||||
import com.twofortyfouram.locale.api.{Intent => ApiIntent}
|
||||
|
||||
object TaskerSettings {
|
||||
val ACTION_UNKNOWN = "unknown"
|
||||
val ACTION_TOGGLE_SERVICE = "toggle_service"
|
||||
val ACTION_SWITCH_PROFILE = "switch_profile"
|
||||
private val KEY_ACTION = "action"
|
||||
private val KEY_SWITCH_ON = "switch_on"
|
||||
private val KEY_PROFILE_ID = "profile_id"
|
||||
|
||||
def fromIntent(intent: Intent): TaskerSettings = {
|
||||
val bundle: Bundle = if (intent.hasExtra(ApiIntent.EXTRA_BUNDLE))
|
||||
intent.getBundleExtra(ApiIntent.EXTRA_BUNDLE) else Bundle.EMPTY
|
||||
def fromIntent(intent: Intent) = new TaskerSettings(if (intent.hasExtra(ApiIntent.EXTRA_BUNDLE))
|
||||
intent.getBundleExtra(ApiIntent.EXTRA_BUNDLE) else Bundle.EMPTY)
|
||||
|
||||
new TaskerSettings(bundle)
|
||||
}
|
||||
|
||||
def fromBundle(bundle: Bundle): TaskerSettings = {
|
||||
new TaskerSettings(bundle)
|
||||
}
|
||||
def fromBundle(bundle: Bundle) = new TaskerSettings(bundle)
|
||||
}
|
||||
|
||||
class TaskerSettings(bundle: Bundle) {
|
||||
import TaskerSettings._
|
||||
|
||||
private val KEY_ACTION = "action"
|
||||
private val KEY_IS_START = "is_start"
|
||||
private val KEY_PROFILE_ID = "profile_id"
|
||||
var switchOn = bundle.getBoolean(KEY_SWITCH_ON, true)
|
||||
var profileId = bundle.getInt(KEY_PROFILE_ID, -1)
|
||||
|
||||
var action: String = bundle.getString(KEY_ACTION, ACTION_UNKNOWN)
|
||||
|
||||
var isStart: Boolean = _
|
||||
var profileId: Int = _
|
||||
|
||||
action match {
|
||||
case ACTION_TOGGLE_SERVICE =>
|
||||
isStart = bundle.getBoolean(KEY_IS_START, true)
|
||||
case ACTION_SWITCH_PROFILE =>
|
||||
profileId = bundle.getInt(KEY_PROFILE_ID, -1)
|
||||
assert(profileId != -1, "profile id was wrong")
|
||||
case _ =>
|
||||
Log.w(Shadowsocks.TAG, s"unknown tasker action settings: $action")
|
||||
}
|
||||
|
||||
def isEmpty = action == ACTION_UNKNOWN
|
||||
|
||||
def toIntent(context: Context): Intent = {
|
||||
def toIntent(context: Context) = {
|
||||
val bundle = new Bundle()
|
||||
|
||||
action match {
|
||||
case ACTION_TOGGLE_SERVICE =>
|
||||
bundle.putString(KEY_ACTION, action)
|
||||
bundle.putBoolean(KEY_IS_START, isStart)
|
||||
case ACTION_SWITCH_PROFILE =>
|
||||
bundle.putString(KEY_ACTION, action)
|
||||
bundle.putInt(KEY_PROFILE_ID, profileId)
|
||||
}
|
||||
|
||||
val desc: String = action match {
|
||||
case ACTION_TOGGLE_SERVICE =>
|
||||
context.getString(R.string.turn_service_state,
|
||||
context.getString(if (isStart) R.string.state_on else R.string.state_off))
|
||||
case ACTION_SWITCH_PROFILE =>
|
||||
val profileName = ShadowsocksApplication.profileManager.getProfile(profileId) match {
|
||||
case Some(p) => p.name
|
||||
case None => context.getString(R.string.removed)
|
||||
}
|
||||
context.getString(R.string.switch_profile_to, profileName)
|
||||
}
|
||||
|
||||
val intent: Intent = new Intent()
|
||||
intent.putExtra(ApiIntent.EXTRA_STRING_BLURB, desc)
|
||||
.putExtra(ApiIntent.EXTRA_BUNDLE, bundle)
|
||||
if (!switchOn) bundle.putBoolean(KEY_SWITCH_ON, false)
|
||||
if (profileId >= 0) bundle.putInt(KEY_PROFILE_ID, profileId)
|
||||
new Intent().putExtra(ApiIntent.EXTRA_BUNDLE, bundle).putExtra(ApiIntent.EXTRA_STRING_BLURB,
|
||||
ShadowsocksApplication.profileManager.getProfile(profileId) match {
|
||||
case Some(p) => context.getString(if (switchOn) R.string.start_service else R.string.stop_service, p.name)
|
||||
case None => context.getString(if (switchOn) R.string.start_service_default else R.string.stop)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user