Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New Designs] Update Run button from dashboard to display new flow for selecting desired tests #632

Merged
merged 24 commits into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
66ffbc3
Upgrade gradle to `8.1.2` and add support for kotlin and `kapt`
aanorbel Oct 24, 2023
1c9db05
Merge branch 'master' of github.com:ooni/probe-android into chore/gra…
aanorbel Oct 31, 2023
9309eff
Start implementation of `RunTests` flow
aanorbel Nov 2, 2023
51f350e
Updated button status
aanorbel Nov 2, 2023
1461e29
Updated suite to run from `BaseDescriptor`
aanorbel Nov 2, 2023
1c5a84a
Modified views and refactored code
aanorbel Nov 2, 2023
20a3160
Modified preferences and activity actions
aanorbel Nov 2, 2023
5fbc024
Updated rules for storing preferences
aanorbel Nov 3, 2023
3902641
Modified Menu and toolbar views for `RunTestsActivity` with proper st…
aanorbel Nov 3, 2023
2044002
Updated the drawable tint for group icon indicator
aanorbel Nov 3, 2023
30d799b
Merge branch 'master' of github.com:ooni/probe-android into issues/2589
aanorbel Nov 3, 2023
2d4437d
revert changes on strings.xml
aanorbel Nov 8, 2023
4b51010
Updated documentation for `RunTestsExpandableListViewAdapter`
aanorbel Nov 22, 2023
1b0a716
rename variable
aanorbel Nov 22, 2023
c5a2db4
Update app/src/main/java/org/openobservatory/ooniprobe/common/Prefere…
aanorbel Nov 22, 2023
31f8d4c
Removed comment
aanorbel Nov 22, 2023
80731aa
Merge branch 'issues/2589' of github.com:ooni/probe-android into issu…
aanorbel Nov 22, 2023
01d8bc0
Updated code based on review
aanorbel Nov 27, 2023
8fe484b
Update tests suites
aanorbel Nov 28, 2023
2370a7c
Formated file
aanorbel Nov 28, 2023
294e968
Formated file
aanorbel Nov 28, 2023
778b593
Merge branch 'dev/design-update' of github.com:ooni/probe-android int…
aanorbel Dec 5, 2023
39383dc
Updated tests to reflect state of applicationn
aanorbel Dec 8, 2023
471e923
Updated code based on review
aanorbel Dec 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
441 changes: 174 additions & 267 deletions app/src/fdroid/res/xml/preferences_global.xml

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
android:name=".activity.OnboardingActivity"
android:screenOrientation="userPortrait"
android:theme="@style/Theme.MaterialComponents.NoActionBar.Onboarding" />
<activity
android:label="Run tests"
android:name=".activity.runtests.RunTestsActivity"
android:parentActivityName=".activity.MainActivity"
android:exported="false"
android:theme="@style/Theme.MaterialComponents.Light.DarkActionBar.App.NoActionBar"/>
<activity
android:name=".activity.PreferenceActivity"
android:launchMode="singleTop"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package org.openobservatory.ooniprobe.activity.runtests

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.text.TextUtils
import android.view.*
import org.openobservatory.ooniprobe.R
import org.openobservatory.ooniprobe.activity.AbstractActivity
import org.openobservatory.ooniprobe.activity.RunningActivity
import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_ALL
import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_NONE
import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_SOME
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.*
import java.io.Serializable
import javax.inject.Inject

class RunTestsActivity : AbstractActivity() {
lateinit var binding: ActivityRunTestsBinding

private 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())

setSupportActionBar(binding.toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)

activityComponent?.inject(this)

val testSuites: List<AbstractSuite>? = intent.extras?.getParcelableArrayList(TESTS)
aanorbel marked this conversation as resolved.
Show resolved Hide resolved
testSuites?.let { ts ->
val tsGroups: List<GroupItem> = ts.map { testSuite ->
return@map testSuite.runTestsGroupItem(preferenceManager)
aanorbel marked this conversation as resolved.
Show resolved Hide resolved
}

mAdapter = RunTestsExpandableListViewAdapter(this, tsGroups, viewModel)

binding.expandableListView.setAdapter(mAdapter)
for (i in 0 until mAdapter.groupCount) {
binding.expandableListView.expandGroup(i)
}
binding.selectAll.setOnClickListener { onSelectAllClickListener() }

binding.selectNone.setOnClickListener { onSelectNoneClickListener() }

viewModel.selectedAllBtnStatus.observe(this, this::selectAllBtnStatusObserver)

binding.bottomBar.setOnMenuItemClickListener { menuItem ->
onMenuItemClickListener(menuItem)
}
} ?: run {
aanorbel marked this conversation as resolved.
Show resolved Hide resolved
finish()
}

}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater: MenuInflater = menuInflater
inflater.inflate(R.menu.close, menu)
return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
return when (item.itemId) {
R.id.close_button -> {
finish()
true
}

else -> super.onOptionsItemSelected(item)
}
}

private fun onMenuItemClickListener(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.runButton -> {
val selectedChildItems: List<String> = getChildItemsSelectedIdList()
if (selectedChildItems.isNotEmpty()) {
val testSuitesToRun = getGroupItemsAtLeastOneChildEnabled().map { groupItem ->
return@map AbstractSuite.getTestSuiteByName(groupItem.name).dynamicTestSuite(
nettests = groupItem.nettests.filter { nattest -> nattest.selected }
)
}
RunningActivity.runAsForegroundService(
this@RunTestsActivity,
java.util.ArrayList(testSuitesToRun),
{ finish() },
preferenceManager
)

}
true
}

else -> false
}
}

// TODO(aanorbel) Update button color from theme
private fun selectAllBtnStatusObserver(selectAllBtnStatus: String?) {
if (!TextUtils.isEmpty(selectAllBtnStatus)) {
when (selectAllBtnStatus) {
SELECT_ALL -> {
binding.selectNone.isActivated = true
binding.selectAll.isActivated = false
}

SELECT_NONE -> {
binding.selectNone.isActivated = true
binding.selectAll.isActivated = false
}

SELECT_SOME -> {
binding.selectNone.isActivated = true
binding.selectAll.isActivated = true
}
}
mAdapter.notifyDataSetChanged()
aanorbel marked this conversation as resolved.
Show resolved Hide resolved
updateStatusIndicator()
}
}

private fun onSelectNoneClickListener() {
viewModel.setSelectedAllBtnStatus(SELECT_NONE)
mAdapter.notifyDataSetChanged()
updateStatusIndicator()
}

private fun onSelectAllClickListener() {
viewModel.setSelectedAllBtnStatus(SELECT_ALL)
mAdapter.notifyDataSetChanged()
updateStatusIndicator()
}


private fun updateStatusIndicator() {
//TODO(aanorbel): translate status indicator
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to do this in the same PR or in a subsequent one?

binding.bottomBar.setTitle("${getChildItemsSelectedIdList().size} Tests")
}

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
}

private fun getGroupItemsAtLeastOneChildEnabled(): List<GroupItem> {
val items: MutableList<GroupItem> = ArrayList()
for (i in 0 until mAdapter.groupCount) {
if (mAdapter.getGroup(i).nettests.any { it.selected }) {
items.add(mAdapter.getGroup(i).apply {
nettests = nettests.filter { it.selected }
})
}
}
return items
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.openobservatory.ooniprobe.activity.runtests

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.openobservatory.ooniprobe.common.PreferenceManager
import org.openobservatory.ooniprobe.common.disableTest
import org.openobservatory.ooniprobe.common.enableTest
import org.openobservatory.ooniprobe.test.suite.CircumventionSuite
import org.openobservatory.ooniprobe.test.suite.ExperimentalSuite
import org.openobservatory.ooniprobe.test.suite.InstantMessagingSuite
import org.openobservatory.ooniprobe.test.suite.PerformanceSuite
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)
when (selectedStatus) {
SELECT_ALL -> {
InstantMessagingSuite().getTestList(preferenceManager).forEach {
enableTest(it.name)
}
CircumventionSuite().getTestList(preferenceManager).forEach {
enableTest(it.name)
}
PerformanceSuite().getTestList(preferenceManager).forEach {
enableTest(it.name)
}
enableTest(ExperimentalSuite.NAME)
}

SELECT_NONE -> {
InstantMessagingSuite().getTestList(preferenceManager).forEach {
disableTest(it.name)
}
CircumventionSuite().getTestList(preferenceManager).forEach {
disableTest(it.name)
}
PerformanceSuite().getTestList(preferenceManager).forEach {
disableTest(it.name)
}
disableTest(ExperimentalSuite.NAME)
}
}
}

fun disableTest(name: String) {
preferenceManager.disableTest(name)
}

fun enableTest(name: String) {
preferenceManager.enableTest(name)
}

companion object {
const val SELECT_ALL = "SELECT_ALL"
const val SELECT_SOME = "SELECT_SOME"
const val SELECT_NONE = "SELECT_NONE"
}
}
Loading
Loading