-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start implementation of
RunTests
flow
- Loading branch information
Showing
20 changed files
with
1,364 additions
and
542 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsActivity.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package org.openobservatory.ooniprobe.activity.runtests | ||
|
||
import android.content.Context | ||
import android.content.Intent | ||
import android.os.Bundle | ||
import android.text.TextUtils | ||
import org.openobservatory.ooniprobe.R | ||
import org.openobservatory.ooniprobe.activity.AbstractActivity | ||
import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_ALL | ||
import org.openobservatory.ooniprobe.activity.runtests.adapter.RunTestsExpandableListViewAdapter | ||
import org.openobservatory.ooniprobe.activity.runtests.models.ChildItem | ||
import org.openobservatory.ooniprobe.activity.runtests.models.GroupItem | ||
import org.openobservatory.ooniprobe.common.PreferenceManager | ||
import org.openobservatory.ooniprobe.databinding.ActivityRunTestsBinding | ||
import org.openobservatory.ooniprobe.test.suite.AbstractSuite | ||
import java.io.Serializable | ||
import javax.inject.Inject | ||
|
||
class RunTestsActivity : AbstractActivity() { | ||
lateinit var binding: ActivityRunTestsBinding | ||
lateinit var mAdapter: RunTestsExpandableListViewAdapter | ||
|
||
@Inject | ||
lateinit var preferenceManager: PreferenceManager | ||
|
||
@Inject | ||
lateinit var viewModel: RunTestsViewModel | ||
|
||
companion object { | ||
const val TESTS: String = "tests" | ||
|
||
@JvmStatic | ||
fun newIntent(context: Context, testSuites: List<AbstractSuite>): Intent { | ||
return Intent(context, RunTestsActivity::class.java).putExtras(Bundle().apply { | ||
putSerializable(TESTS, testSuites as Serializable) | ||
}) | ||
} | ||
} | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
binding = ActivityRunTestsBinding.inflate(layoutInflater) | ||
setContentView(binding.getRoot()) | ||
supportActionBar?.setDisplayHomeAsUpEnabled(true) | ||
|
||
activityComponent?.inject(this) | ||
|
||
var testSuites: List<AbstractSuite>? = intent.extras?.getParcelableArrayList(TESTS) | ||
testSuites?.let { ts -> | ||
val tsGroups: List<GroupItem> = ts.map { testSuite -> | ||
GroupItem( | ||
selected = false, | ||
name = testSuite.name, | ||
nettests = testSuite.getTestList(preferenceManager).map { nettest -> | ||
ChildItem( | ||
selected = preferenceManager.resolveStatus(nettest.name), | ||
name = nettest.name, | ||
inputs = nettest.inputs | ||
) | ||
}) | ||
} | ||
|
||
mAdapter = RunTestsExpandableListViewAdapter(this, tsGroups, viewModel) | ||
|
||
binding.elv.setAdapter(mAdapter) | ||
|
||
viewModel.selectedAllBtnStatus.observe(this) { selectAllBtnStatus -> | ||
if (!TextUtils.isEmpty(selectAllBtnStatus)) { | ||
if (selectAllBtnStatus == SELECT_ALL) { | ||
binding.ckbSelectAll.isChecked = true | ||
} else { | ||
binding.ckbSelectAll.isChecked = false | ||
} | ||
mAdapter.notifyDataSetChanged() | ||
updateStatusIndicator() | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
private fun updateStatusIndicator() { | ||
binding.bottomBar.setTitle(getString(R.string.OONIRun_URLs, getChildItemsSelectedIdList().size.toString())) | ||
} | ||
|
||
private fun getChildItemsSelectedIdList(): List<String> { | ||
val childItemSelectedIdList: MutableList<String> = ArrayList() | ||
for (i in 0 until mAdapter.groupCount) { | ||
val secondLevelItemList: List<ChildItem> = mAdapter.getGroup(i).nettests | ||
secondLevelItemList | ||
.asSequence() | ||
.filter { it.selected } | ||
.mapTo(childItemSelectedIdList) { it.name } | ||
} | ||
return childItemSelectedIdList | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsViewModel.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package org.openobservatory.ooniprobe.activity.runtests | ||
|
||
import androidx.lifecycle.MutableLiveData | ||
import androidx.lifecycle.ViewModel | ||
import org.openobservatory.ooniprobe.common.PreferenceManager | ||
import javax.inject.Inject | ||
|
||
|
||
class RunTestsViewModel() : ViewModel() { | ||
lateinit var preferenceManager: PreferenceManager | ||
|
||
@Inject | ||
constructor(preferenceManager: PreferenceManager) : this() { | ||
this.preferenceManager = preferenceManager | ||
} | ||
|
||
val selectedAllBtnStatus: MutableLiveData<String> = MutableLiveData() | ||
|
||
init { | ||
selectedAllBtnStatus.postValue(SELECT_SOME) | ||
} | ||
|
||
fun setSelectedAllBtnStatus(selectedStatus: String) { | ||
selectedAllBtnStatus.postValue(selectedStatus) | ||
} | ||
|
||
companion object { | ||
const val SELECT_ALL = "SELECT_ALL" | ||
const val SELECT_SOME = "SELECT_SOME" | ||
const val NOT_SELECT_ANY = "NOT_SELECT_ANY" | ||
} | ||
} |
232 changes: 232 additions & 0 deletions
232
.../openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,232 @@ | ||
package org.openobservatory.ooniprobe.activity.runtests.adapter | ||
|
||
import android.content.Context | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import android.widget.BaseExpandableListAdapter | ||
import android.widget.CheckBox | ||
import android.widget.ImageView | ||
import android.widget.TextView | ||
import org.openobservatory.ooniprobe.R | ||
import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel | ||
import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.NOT_SELECT_ANY | ||
import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_ALL | ||
import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_SOME | ||
import org.openobservatory.ooniprobe.activity.runtests.models.ChildItem | ||
import org.openobservatory.ooniprobe.activity.runtests.models.GroupItem | ||
import org.openobservatory.ooniprobe.test.suite.AbstractSuite | ||
import org.openobservatory.ooniprobe.test.suite.ExperimentalSuite | ||
import org.openobservatory.ooniprobe.test.test.AbstractTest | ||
|
||
|
||
class RunTestsExpandableListViewAdapter( | ||
private val mContext: Context, | ||
private val mGroupListData: List<GroupItem>, | ||
private val mViewModel: RunTestsViewModel | ||
) : BaseExpandableListAdapter() { | ||
override fun getGroupCount(): Int { | ||
return mGroupListData.size | ||
} | ||
|
||
override fun getChildrenCount(groupPosition: Int): Int { | ||
return mGroupListData[groupPosition].nettests.size | ||
} | ||
|
||
override fun getGroup(groupPosition: Int): GroupItem { | ||
return mGroupListData[groupPosition] | ||
} | ||
|
||
override fun getChild(groupPosition: Int, childPosition: Int): ChildItem { | ||
return mGroupListData[groupPosition].nettests[childPosition] | ||
} | ||
|
||
override fun getGroupId(groupPosition: Int): Long { | ||
return groupPosition.toLong() | ||
} | ||
|
||
override fun getChildId(groupPosition: Int, childPosition: Int): Long { | ||
return childPosition.toLong() | ||
} | ||
|
||
override fun hasStableIds(): Boolean { | ||
return false | ||
} | ||
|
||
override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View? { | ||
var convertView = | ||
convertView ?: LayoutInflater.from(mContext).inflate(R.layout.run_tests_group_list_item, parent, false) | ||
val groupItem = getGroup(groupPosition) | ||
val testSuite = AbstractSuite.getTestSuiteByName(groupItem.name) | ||
convertView.findViewById<TextView>(R.id.group_name).text = parent.context.resources.getText(testSuite.title) | ||
convertView.findViewById<ImageView>(R.id.group_icon).setImageResource(testSuite.icon) | ||
val groupIndicator = convertView.findViewById<ImageView>(R.id.group_indicator) | ||
val groupSelectionIndicator = convertView.findViewById<ImageView>(R.id.group_select_indicator) | ||
val selectedAllBtnStatus = mViewModel.selectedAllBtnStatus.getValue() | ||
if (selectedAllBtnStatus == SELECT_ALL) { | ||
groupItem.selected = true | ||
for (childItem in groupItem.nettests) { | ||
childItem.selected = true | ||
} | ||
} else if (selectedAllBtnStatus == NOT_SELECT_ANY) { | ||
groupItem.selected = false | ||
for (childItem in groupItem.nettests) { | ||
childItem.selected = false | ||
} | ||
} | ||
if (groupItem.selected) { | ||
if (isSelectAllChildItems(groupItem.nettests)) { | ||
groupSelectionIndicator.setImageResource(R.drawable.check_box) | ||
} else { | ||
groupSelectionIndicator.setImageResource(R.drawable.check_box_outline_blank) | ||
} | ||
} else { | ||
groupSelectionIndicator.setImageResource(R.drawable.check_box_outline_blank) | ||
} | ||
groupSelectionIndicator.setOnClickListener { | ||
if (groupItem.selected && isSelectAllChildItems(groupItem.nettests)) { | ||
groupItem.selected = false | ||
for (childItem in groupItem.nettests) { | ||
childItem.selected = false | ||
} | ||
if (isNotSelectedAnyGroupItem(mGroupListData)) { | ||
mViewModel.setSelectedAllBtnStatus(NOT_SELECT_ANY) | ||
} else { | ||
mViewModel.setSelectedAllBtnStatus(SELECT_SOME) | ||
} | ||
} else { | ||
groupItem.selected = true | ||
for (childItem in groupItem.nettests) { | ||
childItem.selected = true | ||
} | ||
if (isSelectedAllItems(mGroupListData)) { | ||
mViewModel.setSelectedAllBtnStatus(SELECT_ALL) | ||
} else { | ||
mViewModel.setSelectedAllBtnStatus(SELECT_SOME) | ||
} | ||
} | ||
notifyDataSetChanged() | ||
} | ||
if (isExpanded) { | ||
groupIndicator.setImageResource(R.drawable.expand_less) | ||
} else { | ||
groupIndicator.setImageResource(R.drawable.expand_more) | ||
} | ||
return convertView | ||
} | ||
|
||
override fun getChildView( | ||
groupPosition: Int, | ||
childPosition: Int, | ||
isLastChild: Boolean, | ||
convertView: View?, | ||
parent: ViewGroup | ||
): View? { | ||
var convertView = | ||
convertView ?: LayoutInflater.from(mContext).inflate(R.layout.run_tests_child_list_item, parent, false) | ||
val childItem = getChild(groupPosition, childPosition) | ||
val groupItem = getGroup(groupPosition) | ||
val nettest = AbstractTest.getTestByName(childItem.name) | ||
convertView.findViewById<TextView>(R.id.child_name)?.apply { | ||
text = when (groupItem.name) { | ||
ExperimentalSuite.NAME -> { | ||
childItem.name | ||
} | ||
|
||
else -> { | ||
parent.context.resources.getText(nettest.labelResId) | ||
} | ||
} | ||
} | ||
convertView.findViewById<CheckBox>(R.id.child_select).apply { | ||
isChecked = childItem.selected | ||
setOnCheckedChangeListener { buttonView, isChecked -> | ||
|
||
childItem.selected = isChecked | ||
if (childItem.selected) { | ||
if (isNotSelectedAnyChildItems(groupItem.nettests)) { | ||
groupItem.selected = false | ||
} | ||
if (isNotSelectedAnyItems(mGroupListData)) { | ||
mViewModel.setSelectedAllBtnStatus(NOT_SELECT_ANY) | ||
} else { | ||
mViewModel.setSelectedAllBtnStatus(SELECT_SOME) | ||
} | ||
} else { | ||
groupItem.selected = true | ||
if (isSelectedAllItems(mGroupListData)) { | ||
mViewModel.setSelectedAllBtnStatus(SELECT_ALL) | ||
} else { | ||
mViewModel.setSelectedAllBtnStatus(SELECT_SOME) | ||
} | ||
} | ||
notifyDataSetChanged() | ||
} | ||
} | ||
return convertView | ||
} | ||
|
||
override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean { | ||
return false | ||
} | ||
|
||
private fun isNotSelectedAnyGroupItem(groupItemsList: List<GroupItem>): Boolean { | ||
for (groupItem in groupItemsList) { | ||
if (groupItem.selected) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
private fun isSelectedAllGroupItems(groupItemsList: List<GroupItem>): Boolean { | ||
for (groupItem in groupItemsList) { | ||
if (!groupItem.selected) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
private fun isNotSelectedAnyChildItems(childItemList: List<ChildItem>): Boolean { | ||
for (childItem in childItemList) { | ||
if (childItem.selected) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
private fun isSelectAllChildItems(childItemList: List<ChildItem>): Boolean { | ||
for (childItem in childItemList) { | ||
if (!childItem.selected) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
private fun isSelectedAllItems(groupItemList: List<GroupItem>?): Boolean { | ||
for (groupItem in groupItemList!!) { | ||
if (!groupItem.selected) { | ||
return false | ||
} | ||
if (!isSelectAllChildItems(groupItem.nettests)) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
|
||
private fun isNotSelectedAnyItems(groupItemList: List<GroupItem>?): Boolean { | ||
for (groupItem in groupItemList!!) { | ||
if (groupItem.selected) { | ||
return false | ||
} | ||
if (!isNotSelectedAnyChildItems(groupItem.nettests)) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/models/GroupItems.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package org.openobservatory.ooniprobe.activity.runtests.models | ||
|
||
import org.openobservatory.engine.BaseDescriptor | ||
import org.openobservatory.engine.BaseNettest | ||
|
||
data class ChildItem( | ||
var selected: Boolean, | ||
var name: String, | ||
var inputs: List<String>? | ||
) | ||
|
||
data class GroupItem( | ||
var selected: Boolean, | ||
var name: String, | ||
var nettests: List<ChildItem> | ||
) |
Oops, something went wrong.