From 16cca8ddc3cd1c99c254b26851e4cd3cc8edca67 Mon Sep 17 00:00:00 2001 From: Norbel AMBANUMBEN Date: Tue, 25 Jun 2024 22:26:39 +0100 Subject: [PATCH 1/7] fix: checkbox size, share icon, and result display --- .../adapter/RunTestsExpandableListViewAdapter.kt | 11 ++++++----- .../ooniprobe/fragment/ResultListFragment.java | 11 ++++++++++- .../ooniprobe/item/WebsiteItem.java | 15 +++++++++++++++ .../main/res/drawable-xxxhdpi/ic_menu_share.png | Bin 7247 -> 0 bytes app/src/main/res/drawable/ic_menu_share.xml | 5 +++++ app/src/main/res/layout/activity_run_tests.xml | 2 ++ app/src/main/res/layout/activity_running.xml | 4 ++-- app/src/main/res/layout/item_websites.xml | 1 + .../main/res/layout/nettest_group_list_item.xml | 5 +++-- .../res/layout/overview_test_group_list_item.xml | 5 +++-- .../res/layout/run_tests_child_list_item.xml | 1 + .../res/layout/run_tests_group_list_item.xml | 1 + app/src/main/res/menu/share.xml | 4 ++-- 13 files changed, 51 insertions(+), 14 deletions(-) delete mode 100644 app/src/main/res/drawable-xxxhdpi/ic_menu_share.png create mode 100644 app/src/main/res/drawable/ic_menu_share.xml diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt index 5c94b71c3..0d4afadbf 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt @@ -85,7 +85,6 @@ class RunTestsExpandableListViewAdapter( val icon = convertView.findViewById(R.id.group_icon) icon.setImageResource(groupItem.getDisplayIcon(parent.context)) icon.setColorFilter(groupItem.color) - val groupIndicator = convertView.findViewById(R.id.group_indicator) val groupSelectionIndicator = convertView.findViewById(R.id.group_select_indicator) val selectedAllBtnStatus = viewModel.selectedAllBtnStatus.getValue() if (selectedAllBtnStatus == SELECT_ALL) { @@ -134,10 +133,12 @@ class RunTestsExpandableListViewAdapter( } notifyDataSetChanged() } - if (isExpanded) { - groupIndicator.setImageResource(R.drawable.expand_less) - } else { - groupIndicator.setImageResource(R.drawable.expand_more) + convertView.findViewById(R.id.group_indicator)?.let { groupIndicator -> + if (isExpanded) { + groupIndicator.setImageResource(R.drawable.expand_less) + } else { + groupIndicator.setImageResource(R.drawable.expand_more) + } } return convertView } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ResultListFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ResultListFragment.java index 10cc8a8e8..ac54a3201 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ResultListFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ResultListFragment.java @@ -24,6 +24,7 @@ import com.raizlabs.android.dbflow.sql.language.Method; import com.raizlabs.android.dbflow.sql.language.SQLite; +import org.openobservatory.engine.OONIRunNettest; import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.activity.AbstractActivity; import org.openobservatory.ooniprobe.activity.ResultDetailActivity; @@ -50,11 +51,14 @@ import org.openobservatory.ooniprobe.model.database.Network; import org.openobservatory.ooniprobe.model.database.Result; import org.openobservatory.ooniprobe.model.database.Result_Table; +import org.openobservatory.ooniprobe.model.database.TestDescriptorKt; +import org.openobservatory.ooniprobe.test.test.WebConnectivity; import java.io.Serializable; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import javax.inject.Inject; @@ -204,7 +208,12 @@ void queryList(ResultListSpinnerItem filterItem) { } else if (result.test_group_name.equals(OONITests.EXPERIMENTAL.toString())) { items.add(new ExperimentalItem(result, this, this)); } else if (result.descriptor!=null) { - items.add(new RunItem(result, this, this)); + List nettests = TestDescriptorKt.getNettests(result.descriptor); + if (nettests.size()==1 && Objects.equals(nettests.get(0).getName(), WebConnectivity.NAME)){ + items.add(new WebsiteItem(result, this, this)); + } else { + items.add(new RunItem(result, this, this)); + } } else { items.add(new FailedItem(result, this, this)); } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/item/WebsiteItem.java b/app/src/main/java/org/openobservatory/ooniprobe/item/WebsiteItem.java index 60d9f0589..c992edde0 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/item/WebsiteItem.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/item/WebsiteItem.java @@ -1,5 +1,6 @@ package org.openobservatory.ooniprobe.item; +import android.content.Context; import android.text.format.DateFormat; import android.view.LayoutInflater; import android.view.View; @@ -7,8 +8,14 @@ import androidx.core.content.ContextCompat; import androidx.core.graphics.drawable.DrawableCompat; import androidx.recyclerview.widget.RecyclerView; + +import com.google.common.base.Optional; + import localhost.toolkit.widget.recyclerview.HeterogeneousRecyclerItem; + +import org.openobservatory.engine.BaseNettest; import org.openobservatory.ooniprobe.R; +import org.openobservatory.ooniprobe.common.AbstractDescriptor; import org.openobservatory.ooniprobe.databinding.ItemWebsitesBinding; import org.openobservatory.ooniprobe.model.database.Measurement; import org.openobservatory.ooniprobe.model.database.Network; @@ -49,6 +56,14 @@ public void onBindViewHolder(ViewHolder viewHolder) { for (Measurement m : extra.getMeasurements()) allUploaded = allUploaded && (m.isUploaded() || m.is_failed); viewHolder.binding.startTime.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, allUploaded ? 0 : R.drawable.cloudoff, 0); + Context context = viewHolder.itemView.getContext(); + Optional> optionalDescriptor = extra.getDescriptor(context); + if (optionalDescriptor.isPresent()){ + viewHolder.binding.icon.setImageResource(optionalDescriptor.get().getDisplayIcon(context)); + viewHolder.binding.icon.setColorFilter(optionalDescriptor.get().getColor()); + viewHolder.binding.name.setText(optionalDescriptor.get().getTitle()); + viewHolder.binding.name.setTextColor(optionalDescriptor.get().getColor()); + } } public static class ViewHolder extends RecyclerView.ViewHolder { diff --git a/app/src/main/res/drawable-xxxhdpi/ic_menu_share.png b/app/src/main/res/drawable-xxxhdpi/ic_menu_share.png deleted file mode 100644 index ad160e43306b1b84cb3fa3005a1929eb855acc53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7247 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 diff --git a/app/src/main/res/drawable/ic_menu_share.xml b/app/src/main/res/drawable/ic_menu_share.xml new file mode 100644 index 000000000..74753b7ae --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_share.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/layout/activity_run_tests.xml b/app/src/main/res/layout/activity_run_tests.xml index f67c1ec09..cae28d12c 100644 --- a/app/src/main/res/layout/activity_run_tests.xml +++ b/app/src/main/res/layout/activity_run_tests.xml @@ -79,6 +79,8 @@ android:divider="@android:color/transparent" android:groupIndicator="@null" android:nestedScrollingEnabled="true" + android:listSelector="@android:color/transparent" + android:cacheColorHint="@android:color/transparent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="parent" diff --git a/app/src/main/res/layout/activity_running.xml b/app/src/main/res/layout/activity_running.xml index 0e721bf1b..d362cc6b3 100644 --- a/app/src/main/res/layout/activity_running.xml +++ b/app/src/main/res/layout/activity_running.xml @@ -21,8 +21,8 @@ android:layout_margin="8dp" android:minWidth="0dp" android:src="@drawable/chevron_right" - android:rotation="90" - android:tint="@android:color/white" /> + android:rotation="180" + app:tint="@android:color/white" /> + android:orientation="horizontal" + android:paddingEnd="16dp" > + android:padding="@dimen/item_padding_small"/> \ No newline at end of file diff --git a/app/src/main/res/layout/overview_test_group_list_item.xml b/app/src/main/res/layout/overview_test_group_list_item.xml index 93e960a07..2594fbb1a 100644 --- a/app/src/main/res/layout/overview_test_group_list_item.xml +++ b/app/src/main/res/layout/overview_test_group_list_item.xml @@ -5,7 +5,8 @@ tools:context=".activity.overview.OverviewTestsExpandableListViewAdapter" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal"> + android:orientation="horizontal" + android:paddingEnd="16dp" > + android:padding="@dimen/item_padding_small" /> \ No newline at end of file diff --git a/app/src/main/res/layout/run_tests_child_list_item.xml b/app/src/main/res/layout/run_tests_child_list_item.xml index 04c77b105..d092f7b9d 100644 --- a/app/src/main/res/layout/run_tests_child_list_item.xml +++ b/app/src/main/res/layout/run_tests_child_list_item.xml @@ -24,6 +24,7 @@ android:layout_centerVertical="true" android:layout_marginVertical="8dp" android:layout_marginEnd="16dp" + android:padding="@dimen/item_padding_small" android:src="@drawable/check_box_outline_blank" app:tint="@color/color_base" android:contentDescription="checkbox" /> diff --git a/app/src/main/res/layout/run_tests_group_list_item.xml b/app/src/main/res/layout/run_tests_group_list_item.xml index ea9552ab4..a086b60b6 100644 --- a/app/src/main/res/layout/run_tests_group_list_item.xml +++ b/app/src/main/res/layout/run_tests_group_list_item.xml @@ -45,6 +45,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="16dp" + android:padding="@dimen/item_padding_small" android:layout_alignParentEnd="true" android:layout_centerVertical="true" android:src="@drawable/check_box_outline_blank" diff --git a/app/src/main/res/menu/share.xml b/app/src/main/res/menu/share.xml index e8b78dd6b..806aeacdd 100644 --- a/app/src/main/res/menu/share.xml +++ b/app/src/main/res/menu/share.xml @@ -4,8 +4,8 @@ Date: Thu, 27 Jun 2024 17:27:12 +0100 Subject: [PATCH 2/7] fix: checkbox padding and activity launch from external app. --- .../ooniprobe/activity/adddescriptor/AddDescriptorActivity.kt | 4 ++-- .../ooniprobe/activity/oonirun/OoniRunV2Activity.kt | 1 + app/src/main/res/layout/activity_overview.xml | 2 +- app/src/main/res/layout/nettest_group_list_item.xml | 3 +-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/adddescriptor/AddDescriptorActivity.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/adddescriptor/AddDescriptorActivity.kt index 5f424377a..99552ca87 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/adddescriptor/AddDescriptorActivity.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/adddescriptor/AddDescriptorActivity.kt @@ -159,8 +159,8 @@ class AddDescriptorActivity : AbstractActivity() { finish() } - viewModel.selectedAllBtnStatus.observe(this) { state -> - binding.testsCheckbox.checkedState = state; + binding.expandableListView.viewTreeObserver.addOnGlobalLayoutListener { + binding.testsCheckbox.checkedState = viewModel.selectedAllBtnStatus.value!! } // This observer is used to change the state of the "Select All" button when a checkbox is clicked. diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/oonirun/OoniRunV2Activity.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/oonirun/OoniRunV2Activity.kt index e832525af..f505d9ebc 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/oonirun/OoniRunV2Activity.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/oonirun/OoniRunV2Activity.kt @@ -133,6 +133,7 @@ class OoniRunV2Activity : AbstractActivity() { private fun fetchDescriptorComplete(descriptorResponse: TestDescriptor?) { descriptorResponse?.let { startActivity(AddDescriptorActivity.newIntent(this, descriptorResponse)) + finish() } ?: run { finishWithError() } diff --git a/app/src/main/res/layout/activity_overview.xml b/app/src/main/res/layout/activity_overview.xml index fb50caea0..e5b321a69 100644 --- a/app/src/main/res/layout/activity_overview.xml +++ b/app/src/main/res/layout/activity_overview.xml @@ -243,7 +243,7 @@ android:childDivider="@android:color/transparent" android:divider="@android:color/transparent" android:groupIndicator="@null" - android:paddingHorizontal="16dp" + android:paddingStart="16dp" app:layout_constraintTop_toBottomOf="@id/header" tools:listitem="@layout/overview_test_group_list_item" /> diff --git a/app/src/main/res/layout/nettest_group_list_item.xml b/app/src/main/res/layout/nettest_group_list_item.xml index 6f25be8f4..dab4ab20b 100644 --- a/app/src/main/res/layout/nettest_group_list_item.xml +++ b/app/src/main/res/layout/nettest_group_list_item.xml @@ -4,8 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="horizontal" - android:paddingEnd="16dp" > + android:orientation="horizontal"> Date: Fri, 28 Jun 2024 14:34:33 +0100 Subject: [PATCH 3/7] feat: add support for dividers in run test screen --- .../activity/runtests/RunTestsActivity.kt | 78 +++++--- .../RunTestsExpandableListViewAdapter.kt | 188 ++++++++++-------- .../res/layout/run_tests_group_divider.xml | 31 +++ 3 files changed, 185 insertions(+), 112 deletions(-) create mode 100644 app/src/main/res/layout/run_tests_group_divider.xml diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsActivity.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsActivity.kt index 22d6e603d..56a433bfe 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsActivity.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsActivity.kt @@ -18,6 +18,7 @@ import org.openobservatory.ooniprobe.activity.runtests.adapter.RunTestsExpandabl import org.openobservatory.ooniprobe.activity.runtests.models.ChildItem import org.openobservatory.ooniprobe.activity.runtests.models.GroupItem import org.openobservatory.ooniprobe.common.AbstractDescriptor +import org.openobservatory.ooniprobe.common.OONIDescriptor import org.openobservatory.ooniprobe.common.OONITests import org.openobservatory.ooniprobe.common.PreferenceManager import org.openobservatory.ooniprobe.common.disableTest @@ -82,10 +83,20 @@ class RunTestsActivity : AbstractActivity() { intent.extras?.getSerializable(TESTS) as List>? descriptors?.let { _descriptors -> - adapter = RunTestsExpandableListViewAdapter( - _descriptors.map { descriptor -> + val groupedItemList = mutableListOf() + + _descriptors.groupBy { it.javaClass }.forEach { (type, itemList) -> + if (type == OONIDescriptor::class.java){ + groupedItemList.add("OONI Tests".uppercase()) + } else { + groupedItemList.add("OONI RUN Links".uppercase()) + } + groupedItemList.addAll(itemList.map { descriptor -> descriptor.toRunTestsGroupItem(preferenceManager = preferenceManager) - }, + }) + } + adapter = RunTestsExpandableListViewAdapter( + groupedItemList, viewModel ) @@ -137,22 +148,25 @@ class RunTestsActivity : AbstractActivity() { */ private fun updatePreferences() { for (i in 0 until adapter.groupCount) { - val group = adapter.getGroup(i) - when (group.name) { - OONITests.EXPERIMENTAL.label -> { - val testNames = OONITests.EXPERIMENTAL.nettests.map { it.name }; - when(group.nettests.filter { testNames.contains(it.name) }.map { it.selected }.all { it }) { - true -> preferenceManager.enableTest(OONITests.EXPERIMENTAL.label) - false -> preferenceManager.disableTest(OONITests.EXPERIMENTAL.label) - } - } - else -> group.nettests.forEach { nettest -> - when(nettest.selected) { - true -> preferenceManager.enableTest(nettest.name, group.preferencePrefix()) - false -> preferenceManager.disableTest(nettest.name, group.preferencePrefix()) - } - } - } + when(val group = adapter.getGroup(i)) { + is GroupItem ->{ + when (group.name) { + OONITests.EXPERIMENTAL.label -> { + val testNames = OONITests.EXPERIMENTAL.nettests.map { it.name }; + when(group.nettests.filter { testNames.contains(it.name) }.map { it.selected }.all { it }) { + true -> preferenceManager.enableTest(OONITests.EXPERIMENTAL.label) + false -> preferenceManager.disableTest(OONITests.EXPERIMENTAL.label) + } + } + else -> group.nettests.forEach { nettest -> + when(nettest.selected) { + true -> preferenceManager.enableTest(nettest.name, group.preferencePrefix()) + false -> preferenceManager.disableTest(nettest.name, group.preferencePrefix()) + } + } + } + } + } } } @@ -197,11 +211,15 @@ class RunTestsActivity : AbstractActivity() { private fun getChildItemsSelectedIdList(): List { val childItemSelectedIdList: MutableList = ArrayList() for (i in 0 until adapter.groupCount) { - val secondLevelItemList: List = adapter.getGroup(i).nettests - secondLevelItemList - .asSequence() - .filter { it.selected } - .mapTo(childItemSelectedIdList) { it.name } + when(val group = adapter.getGroup(i)) { + is GroupItem ->{ + val secondLevelItemList: List = group.nettests + secondLevelItemList + .asSequence() + .filter { it.selected } + .mapTo(childItemSelectedIdList) { it.name } + } + } } return childItemSelectedIdList } @@ -209,10 +227,14 @@ class RunTestsActivity : AbstractActivity() { private fun getGroupItemsAtLeastOneChildEnabled(): List { val items: MutableList = ArrayList() for (i in 0 until adapter.groupCount) { - if (adapter.getGroup(i).nettests.any { it.selected }) { - items.add(adapter.getGroup(i).apply { - nettests = nettests.filter { it.selected } - }) + when(val group = adapter.getGroup(i)) { + is GroupItem ->{ + if (group.nettests.any { it.selected }) { + items.add(group.apply { + nettests = nettests.filter { it.selected } + }) + } + } } } return items diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt index 0d4afadbf..f6b7d5e75 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt @@ -6,6 +6,7 @@ import android.view.ViewGroup import android.widget.BaseExpandableListAdapter import android.widget.ImageView import android.widget.TextView +import androidx.core.content.ContextCompat import org.openobservatory.ooniprobe.R import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_ALL @@ -22,7 +23,7 @@ import org.openobservatory.ooniprobe.test.test.AbstractTest * @param viewModel RunTestsViewModel object. */ class RunTestsExpandableListViewAdapter( - private val groupedListData: List, + private val groupedListData: List, private val viewModel: RunTestsViewModel ) : BaseExpandableListAdapter() { /** @@ -36,21 +37,26 @@ class RunTestsExpandableListViewAdapter( * @param groupPosition Position of the group in the list. * @return Number of children in the group. */ - override fun getChildrenCount(groupPosition: Int): Int = groupedListData[groupPosition].nettests.size + override fun getChildrenCount(groupPosition: Int): Int = when (val group = groupedListData[groupPosition]) { + is GroupItem -> group.nettests.size + else -> 0 + } /** * @param groupPosition Position of the group in the list. * @return GroupItem object. */ - override fun getGroup(groupPosition: Int): GroupItem = groupedListData[groupPosition] + override fun getGroup(groupPosition: Int): Any = groupedListData[groupPosition] /** * @param groupPosition Position of the group in the list. * @param childPosition Position of the child in the group. * @return ChildItem object. */ - override fun getChild(groupPosition: Int, childPosition: Int): ChildItem = - groupedListData[groupPosition].nettests[childPosition] + override fun getChild(groupPosition: Int, childPosition: Int): ChildItem = when (val group = groupedListData[groupPosition]) { + is GroupItem -> group.nettests[childPosition] + else -> throw IllegalArgumentException("GroupItem expected") + } /** * @param groupPosition Position of the group in the list. @@ -78,69 +84,79 @@ class RunTestsExpandableListViewAdapter( * @return View object. */ override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View? { - var convertView = - convertView ?: LayoutInflater.from(parent.context).inflate(R.layout.run_tests_group_list_item, parent, false) + val groupItem = getGroup(groupPosition) - convertView.findViewById(R.id.group_name).text = groupItem.title - val icon = convertView.findViewById(R.id.group_icon) - icon.setImageResource(groupItem.getDisplayIcon(parent.context)) - icon.setColorFilter(groupItem.color) - val groupSelectionIndicator = convertView.findViewById(R.id.group_select_indicator) - val selectedAllBtnStatus = viewModel.selectedAllBtnStatus.getValue() - if (selectedAllBtnStatus == SELECT_ALL) { - groupItem.selected = true - for (childItem in groupItem.nettests) { - childItem.selected = true - } - } else if (selectedAllBtnStatus == SELECT_NONE) { - groupItem.selected = false - for (childItem in groupItem.nettests) { - childItem.selected = false - } - } else if (isSelectAllChildItems(groupItem.nettests)) { - groupItem.selected = true - } - 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 + + when(groupItem){ + is GroupItem -> { + var convertView = LayoutInflater.from(parent.context).inflate(R.layout.run_tests_group_list_item, parent, false) + convertView.findViewById(R.id.group_name).text = groupItem.title + val icon = convertView.findViewById(R.id.group_icon) + icon.setImageResource(groupItem.getDisplayIcon(parent.context)) + icon.setColorFilter(groupItem.color) + val groupSelectionIndicator = convertView.findViewById(R.id.group_select_indicator) + val selectedAllBtnStatus = viewModel.selectedAllBtnStatus.getValue() + if (selectedAllBtnStatus == SELECT_ALL) { + groupItem.selected = true + for (childItem in groupItem.nettests) { + childItem.selected = true + } + } else if (selectedAllBtnStatus == SELECT_NONE) { + groupItem.selected = false + for (childItem in groupItem.nettests) { + childItem.selected = false + } + } else if (isSelectAllChildItems(groupItem.nettests)) { + groupItem.selected = true } - if (isNotSelectedAnyGroupItem(groupedListData)) { - viewModel.setSelectedAllBtnStatus(SELECT_NONE) + if (groupItem.selected) { + if (isSelectAllChildItems(groupItem.nettests)) { + groupSelectionIndicator.setImageResource(R.drawable.check_box) + } else { + groupSelectionIndicator.setImageResource(R.drawable.check_box_outline_blank) + } } else { - viewModel.setSelectedAllBtnStatus(SELECT_SOME) + groupSelectionIndicator.setImageResource(R.drawable.check_box_outline_blank) } - } else { - groupItem.selected = true - for (childItem in groupItem.nettests) { - childItem.selected = true + groupSelectionIndicator.setOnClickListener { + if (groupItem.selected && isSelectAllChildItems(groupItem.nettests)) { + groupItem.selected = false + for (childItem in groupItem.nettests) { + childItem.selected = false + } + if (isNotSelectedAnyGroupItem(groupedListData)) { + viewModel.setSelectedAllBtnStatus(SELECT_NONE) + } else { + viewModel.setSelectedAllBtnStatus(SELECT_SOME) + } + } else { + groupItem.selected = true + for (childItem in groupItem.nettests) { + childItem.selected = true + } + if (isSelectedAllItems(groupedListData)) { + viewModel.setSelectedAllBtnStatus(SELECT_ALL) + } else { + viewModel.setSelectedAllBtnStatus(SELECT_SOME) + } + } + notifyDataSetChanged() } - if (isSelectedAllItems(groupedListData)) { - viewModel.setSelectedAllBtnStatus(SELECT_ALL) - } else { - viewModel.setSelectedAllBtnStatus(SELECT_SOME) + convertView.findViewById(R.id.group_indicator)?.let { groupIndicator -> + if (isExpanded) { + groupIndicator.setImageResource(R.drawable.expand_less) + } else { + groupIndicator.setImageResource(R.drawable.expand_more) + } } + return convertView } - notifyDataSetChanged() - } - convertView.findViewById(R.id.group_indicator)?.let { groupIndicator -> - if (isExpanded) { - groupIndicator.setImageResource(R.drawable.expand_less) - } else { - groupIndicator.setImageResource(R.drawable.expand_more) + else -> { + return LayoutInflater.from(parent.context).inflate(R.layout.run_tests_group_divider, parent, false).apply { + findViewById(R.id.name).text = groupItem.toString() + } } } - return convertView } /** @@ -181,27 +197,31 @@ class RunTestsExpandableListViewAdapter( false -> R.drawable.check_box_outline_blank } ) - setOnClickListener { - if (childItem.selected) { - childItem.selected = false - if (isNotSelectedAnyChildItems(groupItem.nettests)) { - groupItem.selected = false - } - if (isNotSelectedAnyItems(groupedListData)) { - viewModel.setSelectedAllBtnStatus(SELECT_NONE) - } else { - viewModel.setSelectedAllBtnStatus(SELECT_SOME) - } - } else { - childItem.selected = true - groupItem.selected = true - if (isSelectedAllItems(groupedListData)) { - viewModel.setSelectedAllBtnStatus(SELECT_ALL) - } else { - viewModel.setSelectedAllBtnStatus(SELECT_SOME) + when (groupItem) { + is GroupItem -> { + setOnClickListener { + if (childItem.selected) { + childItem.selected = false + if (isNotSelectedAnyChildItems(groupItem.nettests)) { + groupItem.selected = false + } + if (isNotSelectedAnyItems(groupedListData)) { + viewModel.setSelectedAllBtnStatus(SELECT_NONE) + } else { + viewModel.setSelectedAllBtnStatus(SELECT_SOME) + } + } else { + childItem.selected = true + groupItem.selected = true + if (isSelectedAllItems(groupedListData)) { + viewModel.setSelectedAllBtnStatus(SELECT_ALL) + } else { + viewModel.setSelectedAllBtnStatus(SELECT_SOME) + } + } + notifyDataSetChanged() } } - notifyDataSetChanged() } } return convertView @@ -218,8 +238,8 @@ class RunTestsExpandableListViewAdapter( * @param groupItemsList List of GroupItem objects. * @return True if no group item in the list is selected. */ - private fun isNotSelectedAnyGroupItem(groupItemsList: List): Boolean { - for (groupItem in groupItemsList) { + private fun isNotSelectedAnyGroupItem(groupItemsList: List): Boolean { + for (groupItem in groupItemsList.filterIsInstance()) { if (groupItem.selected) { return false } @@ -257,8 +277,8 @@ class RunTestsExpandableListViewAdapter( * @param groupItemList List of GroupItem objects. * @return True if all group items in the list are selected. */ - private fun isSelectedAllItems(groupItemList: List?): Boolean { - for (groupItem in groupItemList!!) { + private fun isSelectedAllItems(groupItemList: List): Boolean { + for (groupItem in groupItemList.filterIsInstance()) { if (!groupItem.selected) { return false } @@ -273,8 +293,8 @@ class RunTestsExpandableListViewAdapter( * @param groupItemList List of GroupItem objects. * @return True if no group item in the list is selected. */ - private fun isNotSelectedAnyItems(groupItemList: List?): Boolean { - for (groupItem in groupItemList!!) { + private fun isNotSelectedAnyItems(groupItemList: List): Boolean { + for (groupItem in groupItemList.filterIsInstance()) { if (groupItem.selected) { return false } diff --git a/app/src/main/res/layout/run_tests_group_divider.xml b/app/src/main/res/layout/run_tests_group_divider.xml new file mode 100644 index 000000000..ef14eaef6 --- /dev/null +++ b/app/src/main/res/layout/run_tests_group_divider.xml @@ -0,0 +1,31 @@ + + + + + + + + + From b34e79940ec7bd9951dc4fb67f8ef83435e833fd Mon Sep 17 00:00:00 2001 From: Norbel AMBANUMBEN Date: Mon, 1 Jul 2024 21:51:16 +0100 Subject: [PATCH 4/7] fix: experimental test name --- .../ooniprobe/activity/RunningActivity.java | 2 +- .../adapters/ResultDetailExpandableListAdapter.kt | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 53d5b9558..4291f772d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -171,7 +171,7 @@ private void applyUIChanges(RunTestService service) { binding.eta.setText(R.string.Dashboard_Running_CalculatingETA); } - if (Objects.equals(service.task.currentTest.getLabelResId(),R.string.Test_Experimental_Fullname)) { + if (Objects.equals(service.task.currentSuite.getName(),OONITests.EXPERIMENTAL.getLabel())) { binding.name.setText(service.task.currentTest.getName()); } else { binding.name.setText(getString(service.task.currentTest.getLabelResId())); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/adapters/ResultDetailExpandableListAdapter.kt b/app/src/main/java/org/openobservatory/ooniprobe/adapters/ResultDetailExpandableListAdapter.kt index 61742dff4..4a25daea3 100755 --- a/app/src/main/java/org/openobservatory/ooniprobe/adapters/ResultDetailExpandableListAdapter.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/adapters/ResultDetailExpandableListAdapter.kt @@ -92,10 +92,15 @@ class ResultDetailExpandableListAdapter( else -> { val groupMeasurement = (items[groupPosition] as MeasurementGroup) + val groupTitle = root.findViewById(R.id.text) + groupMeasurement.measurements.firstOrNull()?.let { - root.findViewById(R.id.text).setText(it.getTest().labelResId) + when (it.getTest().labelResId){ + R.string.Test_Experimental_Fullname -> groupTitle.text = groupMeasurement.title + else -> groupTitle.setText(it.getTest().labelResId) + } } ?: run { - root.findViewById(R.id.text).text = groupMeasurement.title + groupTitle.text = groupMeasurement.title } root.findViewById(R.id.indicator).apply { visibility = View.VISIBLE From 2b83ad1045da2644ca52338b777c11127cfd6a01 Mon Sep 17 00:00:00 2001 From: Norbel AMBANUMBEN Date: Thu, 4 Jul 2024 21:36:12 +0100 Subject: [PATCH 5/7] feat: add `eta` to progress fragment and test complete snackbar --- .../ooniprobe/activity/MainActivity.java | 4 +++ .../ooniprobe/activity/RunningActivity.java | 4 +-- .../ooniprobe/fragment/ProgressFragment.kt | 26 ++++++++++++++++--- app/src/main/res/layout/fragment_progress.xml | 26 +++++++++++++++++++ app/src/main/res/values/dimens.xml | 1 + 5 files changed, 56 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java index ab002d2bd..2e39b4938 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java @@ -428,4 +428,8 @@ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent d } } } + + public void showResults() { + binding.bottomNavigation.setSelectedItemId(R.id.testResults); + } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java index 4291f772d..eca1476b3 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/RunningActivity.java @@ -288,8 +288,8 @@ public void onEnd(Context context) { } @NonNull - private static String readableTimeRemaining(double timeLeft) { + public static String readableTimeRemaining(double timeLeft) { long letaValue = Math.round(timeLeft); - return String.format(ENGLISH,"%dm %02ds", letaValue/60, letaValue%60); + return String.format(ENGLISH," %dm %02ds", letaValue/60, letaValue%60); } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.kt b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.kt index 7de0bbce5..0f3455224 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.kt @@ -13,7 +13,9 @@ import androidx.core.content.ContextCompat import androidx.core.text.bold import androidx.fragment.app.Fragment import androidx.localbroadcastmanager.content.LocalBroadcastManager +import com.google.android.material.snackbar.Snackbar import org.openobservatory.ooniprobe.R +import org.openobservatory.ooniprobe.activity.MainActivity import org.openobservatory.ooniprobe.activity.RunningActivity import org.openobservatory.ooniprobe.common.Application import org.openobservatory.ooniprobe.common.OONITests @@ -47,8 +49,14 @@ class ProgressFragment : Fragment() { ActivityCompat.startActivity(requireContext(), intent, null) } testProgressRepository.progress.observe(viewLifecycleOwner) { progressValue: Int? -> - if (progressValue != null) { - biding.progress.progress = progressValue + progressValue?.let { progress -> + biding.progress.progress = progress + } + } + testProgressRepository.eta.observe(viewLifecycleOwner) { etaValue: Double? -> + etaValue?.let { eta -> + biding.etaLayout.visibility = View.VISIBLE + biding.eta.text = RunningActivity.readableTimeRemaining(eta) } } return biding.root @@ -133,7 +141,8 @@ class ProgressFragment : Fragment() { biding.testImage.visibility = View.GONE } } - biding.name.text = when (task.currentSuite.name.equals(OONITests.EXPERIMENTAL.label)) { + biding.name.text = + when (task.currentSuite.name.equals(OONITests.EXPERIMENTAL.label)) { true -> SpannableStringBuilder().bold { append(currentTest.name) } false -> SpannableStringBuilder().bold { append(getString(currentTest.labelResId)) } }.append(" ") @@ -201,6 +210,17 @@ class ProgressFragment : Fragment() { override fun onEnd(context: Context) { biding.progressLayout.visibility = View.GONE + Snackbar.make( + requireView(), + "Run finished. Tap to view results.", + Snackbar.LENGTH_LONG + ).setAnchorView(R.id.run_all) + .setAction("Results") { + if(requireActivity() is MainActivity) { + (requireActivity() as MainActivity).showResults() + } + } + .show() } } } diff --git a/app/src/main/res/layout/fragment_progress.xml b/app/src/main/res/layout/fragment_progress.xml index 48e21d485..4369f001b 100644 --- a/app/src/main/res/layout/fragment_progress.xml +++ b/app/src/main/res/layout/fragment_progress.xml @@ -10,10 +10,35 @@ + + + + + + + + @@ -36,6 +61,7 @@ android:gravity="center_vertical" android:text="@string/Dashboard_Running_PreparingTest" android:textColor="@color/color_gray9" /> + + 4dp 8dp 16dp \ No newline at end of file From 8a661241b016a2c0f31ce638709216fb0367d13c Mon Sep 17 00:00:00 2001 From: Norbel AMBANUMBEN Date: Fri, 5 Jul 2024 08:43:26 +0100 Subject: [PATCH 6/7] feat: change position of eta and added test complete banner --- .../ooniprobe/activity/MainActivity.java | 5 +- .../ooniprobe/activity/OverviewActivity.java | 5 +- .../ReviewDescriptorUpdatesActivity.kt | 4 +- .../AppUpdatesViewModel.kt} | 5 +- .../ooniprobe/fragment/DashboardFragment.kt | 15 +++++- .../ooniprobe/fragment/ProgressFragment.kt | 16 ++---- .../main/res/layout/fragment_dashboard.xml | 21 +++++++- app/src/main/res/layout/fragment_progress.xml | 53 +++++++++---------- 8 files changed, 73 insertions(+), 51 deletions(-) rename app/src/main/java/org/openobservatory/ooniprobe/{activity/reviewdescriptorupdates/AvailableUpdatesViewModel.kt => common/AppUpdatesViewModel.kt} (78%) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java index 2e39b4938..e3f7bf8d8 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java @@ -33,7 +33,7 @@ import com.google.android.material.snackbar.Snackbar; import org.openobservatory.ooniprobe.R; -import org.openobservatory.ooniprobe.activity.reviewdescriptorupdates.AvailableUpdatesViewModel; +import org.openobservatory.ooniprobe.common.AppUpdatesViewModel; import org.openobservatory.ooniprobe.activity.reviewdescriptorupdates.ReviewDescriptorUpdatesActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.NotificationUtility; @@ -78,7 +78,7 @@ public class MainActivity extends ReviewUpdatesAbstractActivity implements Confi TestDescriptorManager descriptorManager; @Inject - AvailableUpdatesViewModel updatesViewModel; + AppUpdatesViewModel updatesViewModel; private ActivityResultLauncher requestPermissionLauncher; @@ -109,6 +109,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { getSupportFragmentManager().beginTransaction().replace(R.id.content, new DashboardFragment()).commit(); return true; case R.id.testResults: + updatesViewModel.getTestRunComplete().setValue(false); getSupportFragmentManager().beginTransaction().replace(R.id.content, new ResultListFragment()).commit(); return true; case R.id.settings: diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java b/app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java index ed14e65c1..95c1fcf82 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/OverviewActivity.java @@ -10,7 +10,6 @@ import android.content.Intent; import android.os.Bundle; import android.os.Parcelable; -import android.text.TextUtils; import android.view.View; import android.view.Window; import android.widget.ImageView; @@ -37,7 +36,7 @@ import org.openobservatory.ooniprobe.activity.overview.OverviewTestsExpandableListViewAdapter; import org.openobservatory.ooniprobe.activity.overview.OverviewViewModel; import org.openobservatory.ooniprobe.activity.overview.RevisionsFragment; -import org.openobservatory.ooniprobe.activity.reviewdescriptorupdates.AvailableUpdatesViewModel; +import org.openobservatory.ooniprobe.common.AppUpdatesViewModel; import org.openobservatory.ooniprobe.activity.reviewdescriptorupdates.ReviewDescriptorUpdatesActivity; import org.openobservatory.ooniprobe.common.AbstractDescriptor; import org.openobservatory.ooniprobe.common.OONITests; @@ -71,7 +70,7 @@ public class OverviewActivity extends ReviewUpdatesAbstractActivity implements C OverviewViewModel viewModel; @Inject - AvailableUpdatesViewModel updatesViewModel; + AppUpdatesViewModel updatesViewModel; @Inject TestDescriptorManager testDescriptorManager; diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/reviewdescriptorupdates/ReviewDescriptorUpdatesActivity.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/reviewdescriptorupdates/ReviewDescriptorUpdatesActivity.kt index 6a47df898..267ad3da7 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/reviewdescriptorupdates/ReviewDescriptorUpdatesActivity.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/reviewdescriptorupdates/ReviewDescriptorUpdatesActivity.kt @@ -13,7 +13,6 @@ import android.view.ViewGroup import android.widget.BaseExpandableListAdapter import android.widget.ImageView import android.widget.TextView -import androidx.appcompat.widget.Toolbar import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.viewpager2.adapter.FragmentStateAdapter @@ -24,6 +23,7 @@ import com.google.gson.internal.LinkedTreeMap import org.openobservatory.engine.BaseNettest import org.openobservatory.ooniprobe.R import org.openobservatory.ooniprobe.activity.AbstractActivity +import org.openobservatory.ooniprobe.common.AppUpdatesViewModel import org.openobservatory.ooniprobe.common.TestDescriptorManager import org.openobservatory.ooniprobe.databinding.ActivityReviewDescriptorUpdatesBinding import org.openobservatory.ooniprobe.databinding.FragmentDescriptorUpdateBinding @@ -79,7 +79,7 @@ class ReviewDescriptorUpdatesActivity : AbstractActivity() { lateinit var gson: Gson @Inject - lateinit var updatesViewModel: AvailableUpdatesViewModel + lateinit var updatesViewModel: AppUpdatesViewModel private lateinit var reviewUpdatesPagingAdapter: ReviewUpdatesPagingAdapter diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/reviewdescriptorupdates/AvailableUpdatesViewModel.kt b/app/src/main/java/org/openobservatory/ooniprobe/common/AppUpdatesViewModel.kt similarity index 78% rename from app/src/main/java/org/openobservatory/ooniprobe/activity/reviewdescriptorupdates/AvailableUpdatesViewModel.kt rename to app/src/main/java/org/openobservatory/ooniprobe/common/AppUpdatesViewModel.kt index 34435682a..50bab2e09 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/reviewdescriptorupdates/AvailableUpdatesViewModel.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/AppUpdatesViewModel.kt @@ -1,4 +1,4 @@ -package org.openobservatory.ooniprobe.activity.reviewdescriptorupdates +package org.openobservatory.ooniprobe.common import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel @@ -8,8 +8,9 @@ import javax.inject.Inject import javax.inject.Singleton @Singleton -class AvailableUpdatesViewModel @Inject() constructor(var gson: Gson) : ViewModel() { +class AppUpdatesViewModel @Inject() constructor(var gson: Gson) : ViewModel() { var descriptors: MutableLiveData> = MutableLiveData() + var testRunComplete: MutableLiveData = MutableLiveData() fun setDescriptorsWith(descriptorJson: String) { descriptors.value = gson.fromJson(descriptorJson, Array::class.java).toList() diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.kt b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.kt index 1173c409e..01099370c 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.kt @@ -7,6 +7,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.core.app.ActivityCompat +import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import org.openobservatory.engine.BaseNettest @@ -14,7 +15,7 @@ import org.openobservatory.ooniprobe.R import org.openobservatory.ooniprobe.activity.AbstractActivity import org.openobservatory.ooniprobe.activity.MainActivity import org.openobservatory.ooniprobe.activity.OverviewActivity -import org.openobservatory.ooniprobe.activity.reviewdescriptorupdates.AvailableUpdatesViewModel +import org.openobservatory.ooniprobe.common.AppUpdatesViewModel import org.openobservatory.ooniprobe.activity.runtests.RunTestsActivity import org.openobservatory.ooniprobe.adapters.DashboardAdapter import org.openobservatory.ooniprobe.common.AbstractDescriptor @@ -42,7 +43,7 @@ class DashboardFragment : Fragment(), View.OnClickListener { lateinit var testStateRepository: TestStateRepository @Inject - lateinit var updatesViewModel: AvailableUpdatesViewModel + lateinit var updatesViewModel: AppUpdatesViewModel private lateinit var binding: FragmentDashboardBinding @@ -92,6 +93,13 @@ class DashboardFragment : Fragment(), View.OnClickListener { binding.swipeRefresh.isRefreshing = false } + binding.testsCompleted.setOnClickListener{ + (requireActivity() as MainActivity).showResults() + } + + updatesViewModel.testRunComplete.observe(viewLifecycleOwner) { testRunComplete -> + binding.testsCompleted.isVisible = testRunComplete ?: false + } updatesViewModel.descriptors.observe(viewLifecycleOwner) { descriptors -> descriptors.let { viewModel.updateDescriptorWith(it) } } @@ -110,6 +118,9 @@ class DashboardFragment : Fragment(), View.OnClickListener { ) binding.vpn.visibility = View.VISIBLE else binding.vpn.visibility = View.GONE updateDescriptors() + + binding.testsCompleted.isVisible = updatesViewModel.testRunComplete.value ?: false + } fun updateDescriptors() { diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.kt b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.kt index 0f3455224..aff9e330a 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/ProgressFragment.kt @@ -17,6 +17,7 @@ import com.google.android.material.snackbar.Snackbar import org.openobservatory.ooniprobe.R import org.openobservatory.ooniprobe.activity.MainActivity import org.openobservatory.ooniprobe.activity.RunningActivity +import org.openobservatory.ooniprobe.common.AppUpdatesViewModel import org.openobservatory.ooniprobe.common.Application import org.openobservatory.ooniprobe.common.OONITests import org.openobservatory.ooniprobe.common.PreferenceManager @@ -39,6 +40,9 @@ class ProgressFragment : Fragment() { @Inject lateinit var testProgressRepository: TestProgressRepository + @Inject + lateinit var appUpdatesViewModel: AppUpdatesViewModel + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { @@ -210,17 +214,7 @@ class ProgressFragment : Fragment() { override fun onEnd(context: Context) { biding.progressLayout.visibility = View.GONE - Snackbar.make( - requireView(), - "Run finished. Tap to view results.", - Snackbar.LENGTH_LONG - ).setAnchorView(R.id.run_all) - .setAction("Results") { - if(requireActivity() is MainActivity) { - (requireActivity() as MainActivity).showResults() - } - } - .show() + appUpdatesViewModel.testRunComplete.postValue(true) } } } diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml index aa4c63494..eb6d8c521 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_dashboard.xml @@ -99,10 +99,12 @@ android:layout_marginTop="18dp" /> - - + + + - - - - - - - - - @@ -74,4 +48,29 @@ android:minHeight="8dp" android:progressDrawable="@drawable/progress_blue" /> + + + + + + + + From f3b944fc8c3b5bf52dc4ab8ad847db65b4d33146 Mon Sep 17 00:00:00 2001 From: Norbel AMBANUMBEN Date: Fri, 5 Jul 2024 16:27:27 +0100 Subject: [PATCH 7/7] feat: limit number of revisions displayed --- app/build.gradle | 4 +++- .../ooniprobe/activity/overview/RevisionsView.kt | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 86658f169..e76aebcd0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,6 +18,7 @@ android { testInstrumentationRunner "org.openobservatory.ooniprobe.TestAndroidJUnitRunner" buildConfigField 'String', 'OONI_API_BASE_URL', '"https://api.ooni.io/"' buildConfigField 'String', 'NOTIFICATION_SERVER', '"https://countly.ooni.io"' + buildConfigField 'String', 'OONI_RUN_DASHBOARD_URL', '"https://run.test.ooni.org"' resValue "string", "APP_ID", 'org.openobservatory.ooniprobe' resValue "string", "APP_NAME", "OONI Probe" buildConfigField 'String', 'SOFTWARE_NAME', 'BASE_SOFTWARE_NAME+IS_DEBUG' @@ -51,7 +52,8 @@ android { stable { dimension 'testing' buildConfigField 'String', 'BASE_SOFTWARE_NAME', '"ooniprobe-android"' - buildConfigField 'String', 'OONI_API_BASE_URL', '"https://api.dev.ooni.io"' + buildConfigField 'String', 'OONI_API_BASE_URL', '"https://api.prod.ooni.io/"' + buildConfigField 'String', 'OONI_RUN_DASHBOARD_URL', '"https://run-v2.ooni.org"' } dev { dimension 'testing' diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/overview/RevisionsView.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/overview/RevisionsView.kt index 09a37fcf2..aeb425846 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/activity/overview/RevisionsView.kt +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/overview/RevisionsView.kt @@ -13,6 +13,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.google.gson.Gson import org.openobservatory.engine.OONIRunRevisions +import org.openobservatory.ooniprobe.BuildConfig import org.openobservatory.ooniprobe.R import org.openobservatory.ooniprobe.databinding.FragmentRevisionsBinding import org.openobservatory.ooniprobe.databinding.ItemTextBinding @@ -63,14 +64,15 @@ class RevisionsFragment : Fragment() { with(binding.list) { layoutManager = LinearLayoutManager(context) - adapter = revisions?.revisions?.let { + adapter = revisions?.revisions?.take(5)?.let { RevisionsRecyclerViewAdapter(it, object : OnItemClickListener { override fun onItemClick(position: Int) { startActivity( Intent( Intent.ACTION_VIEW, Uri.parse( - "https://run.test.ooni.org/revisions/%s?revision=%s".format( + "%s/revisions/%s?revision=%s".format( + BuildConfig.OONI_RUN_DASHBOARD_URL, runId, it[position] )