diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index fb3bae01f..4903fd7ed 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -33,6 +33,12 @@
+
+
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 641f0fb6f..a139150cc 100644
--- a/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java
+++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/MainActivity.java
@@ -306,171 +306,22 @@ private void requestNotificationPermission() {
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
/**
- * Check if we are starting the activity from a link [Intent.ACTION_VIEW].
- * This is invoked when a v2 link is opened.
- * @see {@link org.openobservatory.ooniprobe.activity.OoniRunActivity#newIntent}. for v1 links.
+ * Check if we are starting the activity with an intent extra.
+ * This is invoked when we are starting the activity from a notification or
+ * when the activity is launched from the onboarding fragment
+ * @see {@link org.openobservatory.ooniprobe.fragment.onboarding.Onboarding3Fragment#masterClick}.
*/
- if (Intent.ACTION_VIEW.equals(intent.getAction())) {
- Uri uri = intent.getData();
- // If the intent does not contain a link, do nothing.
- if (uri == null) {
- return;
- }
-
- Optional possibleRunId = getRunId(uri);
-
- // If the intent contains a link, but it is not a supported link or has a non-numerical `link_id`.
- if (!possibleRunId.isPresent()) {
- return;
- }
-
- // If the intent contains a link, but the `link_id` is zero.
- if (possibleRunId.get() == 0) {
- return;
- }
-
- TaskExecutor executor = new TaskExecutor();
-
- displayAddLinkProgressFragment(executor);
-
- executor.executeTask(() -> {
- try {
- return descriptorManager.fetchDescriptorFromRunId(possibleRunId.get(), this);
- } catch (Exception exception) {
- exception.printStackTrace();
- ThirdPartyServices.logException(exception);
- return null;
- }
- }, this::fetchDescriptorComplete);
- } else {
- /**
- * Check if we are starting the activity with an intent extra.
- * This is invoked when we are starting the activity from a notification or
- * when the activity is launched from the onboarding fragment
- * @see {@link org.openobservatory.ooniprobe.fragment.onboarding.Onboarding3Fragment#masterClick}.
- */
- if (intent.getExtras() != null) {
- if (intent.getExtras().containsKey(RES_ITEM)) {
- binding.bottomNavigation.setSelectedItemId(intent.getIntExtra(RES_ITEM, R.id.dashboard));
- } else if (intent.getExtras().containsKey(NOTIFICATION_DIALOG)) {
- new ConfirmDialogFragment.Builder()
- .withTitle(intent.getExtras().getString("title"))
- .withMessage(intent.getExtras().getString("message"))
- .withNegativeButton("")
- .withPositiveButton(getString(R.string.Modal_OK))
- .build().show(getSupportFragmentManager(), null);
- }
- }
- }
- }
-
- /**
- * The task to fetch the descriptor from the link is completed.
- *
- * This method is called when the `fetchDescriptorFromRunId` task is completed.
- * The `descriptorResponse` is the result of the task.
- * If the task is successful, the `descriptorResponse` is the descriptor.
- * Otherwise, the `descriptorResponse` is null.
- *
- * If the `descriptorResponse` is not null, start the `AddDescriptorActivity`.
- * Otherwise, show an error message.
- *
- * @param descriptorResponse The result of the task.
- * @return null.
- */
- private Unit fetchDescriptorComplete(TestDescriptor descriptorResponse) {
- if (descriptorResponse != null) {
- startActivity(AddDescriptorActivity.newIntent(this, descriptorResponse));
- } else {
- // TODO(aanorbel): Provide a better error message.
- Snackbar.make(binding.getRoot(), R.string.Modal_Error, Snackbar.LENGTH_LONG)
- .setAnchorView(binding.bottomNavigation) // NOTE:To avoid the `snackbar` from covering the bottom navigation.
- .show();
- }
- removeProgressFragment(R.id.dynamic_progress_fragment);
- return Unit.INSTANCE;
-
- }
-
- /**
- * Display the progress fragment.
- *
- * The progress fragment is used to display the progress of the task.
- * e.g. Fetching the descriptor from the link.
- *
- * @param executor The executor that will be used to execute the task.
- */
- private void displayAddLinkProgressFragment(TaskExecutor executor) {
- binding.dynamicProgressFragment.setVisibility(View.VISIBLE);
- getSupportFragmentManager().beginTransaction()
- .add(
- R.id.dynamic_progress_fragment,
- OONIRunDynamicProgressBar.newInstance(ProgressType.ADD_LINK, new OnActionListener() {
- @Override
- public void onActionButtonCLicked() {
- executor.cancelTask();
- removeProgressFragment(R.id.dynamic_progress_fragment);
- }
-
- @Override
- public void onCloseButtonClicked() {
- removeProgressFragment(R.id.dynamic_progress_fragment);
- }
- }),
- OONIRunDynamicProgressBar.getTAG()
- ).commit();
- }
-
- /**
- * Extracts the run id from the provided Uri.
- * The run id can be in two different formats:
- *
- * The run id is the `link_id` in the link.
- * If the Uri contains a link, but the `link_id` is not a number, an empty Optional is returned.
- * If the Uri contains a link, but it is not a supported link, an empty Optional is returned.
- *
- *
- * @param uri The Uri data.
- * @return An Optional containing the run id if the Uri contains a link with a valid `link_id`, or an empty Optional otherwise.
- */
- private Optional getRunId(Uri uri) {
- String host = uri.getHost();
-
- try {
- if ("runv2".equals(host)) {
- /**
- * The run id is the first segment of the path.
- * Launched when `Open Link in OONI Probe` is clicked.
- * e.g. ooni://runv2/link_id
- */
- return Optional.of(
- Long.parseLong(
- uri.getPathSegments().get(0)
- )
- );
- } else if ("run.test.ooni.org".equals(host)) {
- /**
- * The run id is the second segment of the path.
- * Launched when the system recognizes this app can open this link
- * and launches the app when a link is clicked.
- * e.g. https://run.test.ooni.org/v2/link_id
- */
- return Optional.of(
- Long.parseLong(
- uri.getPathSegments().get(1)
- )
- );
- } else {
- // If the intent contains a link, but it is not a supported link.
- return Optional.absent();
+ if (intent.getExtras() != null) {
+ if (intent.getExtras().containsKey(RES_ITEM)) {
+ binding.bottomNavigation.setSelectedItemId(intent.getIntExtra(RES_ITEM, R.id.dashboard));
+ } else if (intent.getExtras().containsKey(NOTIFICATION_DIALOG)) {
+ new ConfirmDialogFragment.Builder()
+ .withTitle(intent.getExtras().getString("title"))
+ .withMessage(intent.getExtras().getString("message"))
+ .withNegativeButton("")
+ .withPositiveButton(getString(R.string.Modal_OK))
+ .build().show(getSupportFragmentManager(), null);
}
- } catch (Exception e) {
- // If the intent contains a link, but the `link_id` is not a number.
- e.printStackTrace();
- return Optional.absent();
}
}
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 2524c1c8e..5b2a0a8d8 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
@@ -21,10 +21,12 @@ import org.openobservatory.engine.OONIRunDescriptor
import org.openobservatory.engine.OONIRunNettest
import org.openobservatory.ooniprobe.R
import org.openobservatory.ooniprobe.activity.AbstractActivity
+import org.openobservatory.ooniprobe.activity.MainActivity
import org.openobservatory.ooniprobe.activity.adddescriptor.adapter.AddDescriptorExpandableListAdapter
import org.openobservatory.ooniprobe.activity.adddescriptor.adapter.GroupedItem
import org.openobservatory.ooniprobe.common.PreferenceManager
import org.openobservatory.ooniprobe.common.ReadMorePlugin
+import org.openobservatory.ooniprobe.common.StringUtils
import org.openobservatory.ooniprobe.common.TestDescriptorManager
import org.openobservatory.ooniprobe.databinding.ActivityAddDescriptorBinding
import org.openobservatory.ooniprobe.model.database.TestDescriptor
@@ -87,7 +89,13 @@ class AddDescriptorActivity : AbstractActivity() {
fun setImageViewResource(imageView: ImageView, iconName: String?) {
/* TODO(aanorbel): Update to parse the icon name and set the correct icon.
* Remember to ignore icons generated when generated doing this.*/
- imageView.setImageResource(R.drawable.ooni_empty_state)
+ imageView.setImageResource(
+ imageView.context.resources.getIdentifier(
+ StringUtils.camelToSnake(
+ iconName
+ ), "drawable", imageView.context.packageName
+ )
+ )
}
}
@@ -191,4 +199,14 @@ class AddDescriptorActivity : AbstractActivity() {
else -> super.onOptionsItemSelected(item)
}
}
+
+ override fun onBackPressed() {
+ startActivity(MainActivity.newIntent(applicationContext, R.id.dashboard))
+ super.onBackPressed()
+ }
+
+ override fun finish() {
+ startActivity(MainActivity.newIntent(applicationContext, R.id.dashboard))
+ super.finish()
+ }
}
\ No newline at end of file
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
new file mode 100644
index 000000000..5b4dc61bc
--- /dev/null
+++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/oonirun/OoniRunV2Activity.kt
@@ -0,0 +1,187 @@
+package org.openobservatory.ooniprobe.activity.oonirun
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.widget.Toast
+import org.openobservatory.ooniprobe.R
+import org.openobservatory.ooniprobe.activity.AbstractActivity
+import org.openobservatory.ooniprobe.activity.adddescriptor.AddDescriptorActivity
+import org.openobservatory.ooniprobe.common.TaskExecutor
+import org.openobservatory.ooniprobe.common.TestDescriptorManager
+import org.openobservatory.ooniprobe.common.ThirdPartyServices
+import org.openobservatory.ooniprobe.databinding.ActivityOoniRunV2Binding
+import org.openobservatory.ooniprobe.model.database.TestDescriptor
+import javax.inject.Inject
+
+/**
+ * Activity to handle a v2 link.
+ *
+ * A v2 link has the following format:
+ *
+ * 1. ooni://runv2/link_id
+ * 2. https://run.test.ooni.org/v2/link_id
+ *
+ * The activity is started when the user clicks on `Open Link in OONI Probe` or
+ * when the system recognizes this app can open this link and launches the app when a link is clicked.
+ *
+ * It fetches the descriptor from the link and starts the `AddDescriptorActivity`.
+ * If the link is invalid, it shows an error message and ends the activity.
+ *
+ * @see {@link org.openobservatory.ooniprobe.activity.OoniRunActivity} for v1 links.
+ */
+class OoniRunV2Activity : AbstractActivity() {
+ lateinit var binding: ActivityOoniRunV2Binding
+
+ @Inject
+ lateinit var descriptorManager: TestDescriptorManager
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ activityComponent.inject(this)
+ binding = ActivityOoniRunV2Binding.inflate(layoutInflater)
+ setContentView(binding.root)
+ onNewIntent(intent)
+ }
+
+ override fun onNewIntent(intent: Intent) {
+ super.onNewIntent(intent)
+ /**
+ * Check if we are starting the activity from a link [Intent.ACTION_VIEW].
+ * This is invoked when a v2 link is opened.
+ * @see {@link org.openobservatory.ooniprobe.activity.OoniRunActivity.newIntent} for v1 links.
+ */
+ if (Intent.ACTION_VIEW == intent.action) {
+ manageIntent(intent)
+ } else {
+ // If the intent action is not `Intent.ACTION_VIEW`, end activity.
+ Toast.makeText(this, getString(R.string.Modal_Error), Toast.LENGTH_LONG).show()
+ finish()
+ }
+ }
+
+ /**
+ * Parses the intent data to extract the link.
+ * If the intent does not contain a link, show an error message and end the activity.
+ * If the intent contains a link, but it is not a supported link or has a non-numerical `link_id`,
+ * show an error message and end the activity.
+ * If the intent contains a link, but the `link_id` is zero,
+ * show an error message and end the activity.
+ * If the intent contains a link with a valid `link_id`,
+ * fetch the descriptor from the link and start the `AddDescriptorActivity`.
+ *
+ * @param intent The intent data.
+ */
+ private fun manageIntent(intent: Intent) {
+ // If the intent does not contain a link, do nothing.
+ val uri = intent.data ?: finishWithError().run { return }
+ // If the intent contains a link, but it is not a supported link or has a non-numerical `link_id`.
+ val possibleRunId: Long = getRunId(uri) ?: finishWithError().run { return }
+
+ // If the intent contains a link, but the `link_id` is zero.
+ if (possibleRunId == 0L) {
+ finishWithError().run { return }
+ }
+ val executor = TaskExecutor()
+ binding.cancelButton.setOnClickListener {
+ executor.cancelTask()
+ finishWithError(message = getString(R.string.Modal_Cancel))
+ }
+ executor.executeTask({
+ try {
+ return@executeTask descriptorManager.fetchDescriptorFromRunId(
+ possibleRunId,
+ this
+ )
+ } catch (exception: Exception) {
+ exception.printStackTrace()
+ ThirdPartyServices.logException(exception)
+ return@executeTask null
+ }
+ }) { descriptorResponse: TestDescriptor? ->
+ fetchDescriptorComplete(
+ descriptorResponse
+ )
+ }
+ }
+
+ /**
+ * Shows an error message and ends the activity.
+ *
+ * @param message The error message to be shown.
+ */
+ private fun finishWithError(message: String = getString(R.string.Modal_Error)) {
+ Toast.makeText(this, message, Toast.LENGTH_LONG).show()
+ finish()
+ }
+
+ /**
+ * The task to fetch the descriptor from the link is completed.
+ *
+ *
+ * This method is called when the `fetchDescriptorFromRunId` task is completed.
+ * The `descriptorResponse` is the result of the task.
+ * If the task is successful, the `descriptorResponse` is the descriptor.
+ * Otherwise, the `descriptorResponse` is null.
+ *
+ * If the `descriptorResponse` is not null, start the `AddDescriptorActivity`.
+ * Otherwise, show an error message.
+ *
+ * @param descriptorResponse The result of the task.
+ * @return null.
+ */
+ private fun fetchDescriptorComplete(descriptorResponse: TestDescriptor?) {
+ descriptorResponse?.let {
+ startActivity(AddDescriptorActivity.newIntent(this, descriptorResponse))
+ } ?: run {
+ Toast.makeText(this, getString(R.string.Modal_Error), Toast.LENGTH_LONG).show()
+ }
+ }
+
+ /**
+ * Extracts the run id from the provided Uri.
+ * The run id can be in two different formats:
+ *
+ * 1. ooni://runv2/link_id
+ * 2. https://run.test.ooni.org/v2/link_id
+ *
+ * The run id is the `link_id` in the link.
+ * If the Uri contains a link, but the `link_id` is not a number, null is returned.
+ * If the Uri contains a link, but it is not a supported link, null is returned.
+ *
+ * @param uri The Uri data.
+ * @return The run id if the Uri contains a link with a valid `link_id`, or null otherwise.
+ */
+ private fun getRunId(uri: Uri): Long? {
+ val host = uri.host
+ try {
+ when (host) {
+ "runv2" -> {
+ /*
+ * The run id is the first segment of the path.
+ * Launched when `Open Link in OONI Probe` is clicked.
+ * e.g. ooni://runv2/link_id
+ */
+ return uri.pathSegments[0].toLong()
+ }
+
+ "run.test.ooni.org" -> {
+ /*
+ * The run id is the second segment of the path.
+ * Launched when the system recognizes this app can open this link
+ * and launches the app when a link is clicked.
+ * e.g. https://run.test.ooni.org/v2/link_id
+ */
+ return uri.pathSegments[1].toLong()
+ }
+
+ else -> return null
+ }
+ } catch (e: Exception) {
+ // If the intent contains a link, but the `link_id` is not a number.
+ e.printStackTrace()
+ return null
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/OONIDescriptor.kt b/app/src/main/java/org/openobservatory/ooniprobe/common/OONIDescriptor.kt
index ebe74fd26..95e0f53ae 100644
--- a/app/src/main/java/org/openobservatory/ooniprobe/common/OONIDescriptor.kt
+++ b/app/src/main/java/org/openobservatory/ooniprobe/common/OONIDescriptor.kt
@@ -63,7 +63,11 @@ abstract class AbstractDescriptor(
* @return Int representing the display icon for the current descriptor.
*/
open fun getDisplayIcon(context: Context): Int {
- return context.resources.getIdentifier(icon, "drawable", context.packageName).let {
+ return context.resources.getIdentifier(
+ StringUtils.camelToSnake(
+ icon
+ ), "drawable", context.packageName
+ ).let {
if (it == 0) R.drawable.ooni_empty_state else it
}
}
diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/StringUtils.java b/app/src/main/java/org/openobservatory/ooniprobe/common/StringUtils.java
new file mode 100644
index 000000000..0de33c475
--- /dev/null
+++ b/app/src/main/java/org/openobservatory/ooniprobe/common/StringUtils.java
@@ -0,0 +1,28 @@
+package org.openobservatory.ooniprobe.common;
+
+public class StringUtils {
+ public static String camelToSnake(String camelCase) {
+
+ try {
+ final char[] name = camelCase.toCharArray();
+ final StringBuilder builder = new StringBuilder();
+
+ for (int i = 0; i < name.length; i++) {
+ if (Character.isUpperCase(name[i]) || name[i] == '.' || name[i] == '$') {
+ if (i != 0 && name[i - 1] != '.' && name[i - 1] != '$') {
+ builder.append('_');
+ }
+ if (name[i] != '.' && name[i] != '$') {
+ builder.append(Character.toLowerCase(name[i]));
+ }
+ } else {
+ builder.append(name[i]);
+ }
+ }
+
+ return builder.toString();
+ } catch (Exception e){
+ return "ooni_empty_state";
+ }
+ }
+}
diff --git a/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java b/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java
index 8b0a10d22..a88f13c2d 100644
--- a/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java
+++ b/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java
@@ -11,6 +11,7 @@
import org.openobservatory.ooniprobe.activity.ProxyActivity;
import org.openobservatory.ooniprobe.activity.ResultDetailActivity;
import org.openobservatory.ooniprobe.activity.reviewdescriptorupdates.ReviewDescriptorUpdatesActivity;
+import org.openobservatory.ooniprobe.activity.oonirun.OoniRunV2Activity;
import org.openobservatory.ooniprobe.activity.runtests.RunTestsActivity;
import org.openobservatory.ooniprobe.activity.RunningActivity;
import org.openobservatory.ooniprobe.activity.TextActivity;
@@ -22,6 +23,7 @@
@Subcomponent()
public interface ActivityComponent {
void inject(ReviewDescriptorUpdatesActivity activity);
+ void inject(OoniRunV2Activity activity);
void inject(AddDescriptorActivity activity);
void inject(CustomWebsiteActivity activity);
void inject(MainActivity activity);
diff --git a/app/src/main/java/org/openobservatory/ooniprobe/model/database/Result.java b/app/src/main/java/org/openobservatory/ooniprobe/model/database/Result.java
index 36d5a7ba4..898cf761a 100644
--- a/app/src/main/java/org/openobservatory/ooniprobe/model/database/Result.java
+++ b/app/src/main/java/org/openobservatory/ooniprobe/model/database/Result.java
@@ -251,7 +251,7 @@ public Optional> getDescriptor(Context context)
* If there is an {@link IllegalArgumentException}
* This should only happen when the test_group_name is not a valid {@link OONITests} value,
* Which means the `test_group_name` is not an OONI provided test or an installed `Descriptor`.
- * Orphan results for an uninstalled OONI Run v2 descriptor would fall into this category and thus should not exist.
+ * Orphan resulta for an uninstalled OONI Run v2 descriptor would fall into this category and thus should not exist.
* We return an {@link Optional#absent()} object.
*/
return Optional.absent();
diff --git a/app/src/main/java/org/openobservatory/ooniprobe/model/database/TestDescriptor.kt b/app/src/main/java/org/openobservatory/ooniprobe/model/database/TestDescriptor.kt
index 6c9efd627..94bde022f 100644
--- a/app/src/main/java/org/openobservatory/ooniprobe/model/database/TestDescriptor.kt
+++ b/app/src/main/java/org/openobservatory/ooniprobe/model/database/TestDescriptor.kt
@@ -241,4 +241,4 @@ class ITestDescriptor(
nettests = nettests ?: emptyList()
)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/res/drawable/fa_anchor.xml b/app/src/main/res/drawable/fa_anchor.xml
new file mode 100644
index 000000000..d4c71aa43
--- /dev/null
+++ b/app/src/main/res/drawable/fa_anchor.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_award.xml b/app/src/main/res/drawable/fa_award.xml
new file mode 100644
index 000000000..81260d336
--- /dev/null
+++ b/app/src/main/res/drawable/fa_award.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_bed.xml b/app/src/main/res/drawable/fa_bed.xml
new file mode 100644
index 000000000..45b7c6ebb
--- /dev/null
+++ b/app/src/main/res/drawable/fa_bed.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_bone.xml b/app/src/main/res/drawable/fa_bone.xml
new file mode 100644
index 000000000..dae5e661d
--- /dev/null
+++ b/app/src/main/res/drawable/fa_bone.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_book_reader.xml b/app/src/main/res/drawable/fa_book_reader.xml
new file mode 100644
index 000000000..1f17693a4
--- /dev/null
+++ b/app/src/main/res/drawable/fa_book_reader.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_brush.xml b/app/src/main/res/drawable/fa_brush.xml
new file mode 100644
index 000000000..47a019528
--- /dev/null
+++ b/app/src/main/res/drawable/fa_brush.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_building.xml b/app/src/main/res/drawable/fa_building.xml
new file mode 100644
index 000000000..4254f9646
--- /dev/null
+++ b/app/src/main/res/drawable/fa_building.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_cake_candles.xml b/app/src/main/res/drawable/fa_cake_candles.xml
new file mode 100644
index 000000000..b31b7f87f
--- /dev/null
+++ b/app/src/main/res/drawable/fa_cake_candles.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_car.xml b/app/src/main/res/drawable/fa_car.xml
new file mode 100644
index 000000000..bfcc15eb6
--- /dev/null
+++ b/app/src/main/res/drawable/fa_car.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_carrot.xml b/app/src/main/res/drawable/fa_carrot.xml
new file mode 100644
index 000000000..4b4321cf8
--- /dev/null
+++ b/app/src/main/res/drawable/fa_carrot.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_cloud_showers_heavy.xml b/app/src/main/res/drawable/fa_cloud_showers_heavy.xml
new file mode 100644
index 000000000..c6b759dd3
--- /dev/null
+++ b/app/src/main/res/drawable/fa_cloud_showers_heavy.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_cloud_sun.xml b/app/src/main/res/drawable/fa_cloud_sun.xml
new file mode 100644
index 000000000..51055dad4
--- /dev/null
+++ b/app/src/main/res/drawable/fa_cloud_sun.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_compass.xml b/app/src/main/res/drawable/fa_compass.xml
new file mode 100644
index 000000000..e56c503e9
--- /dev/null
+++ b/app/src/main/res/drawable/fa_compass.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_computer.xml b/app/src/main/res/drawable/fa_computer.xml
new file mode 100644
index 000000000..20d95ed3e
--- /dev/null
+++ b/app/src/main/res/drawable/fa_computer.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_crown.xml b/app/src/main/res/drawable/fa_crown.xml
new file mode 100644
index 000000000..db056c763
--- /dev/null
+++ b/app/src/main/res/drawable/fa_crown.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_cube.xml b/app/src/main/res/drawable/fa_cube.xml
new file mode 100644
index 000000000..e0dc78136
--- /dev/null
+++ b/app/src/main/res/drawable/fa_cube.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_dove.xml b/app/src/main/res/drawable/fa_dove.xml
new file mode 100644
index 000000000..02fd67b06
--- /dev/null
+++ b/app/src/main/res/drawable/fa_dove.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_dragon.xml b/app/src/main/res/drawable/fa_dragon.xml
new file mode 100644
index 000000000..523b2add4
--- /dev/null
+++ b/app/src/main/res/drawable/fa_dragon.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_droplet.xml b/app/src/main/res/drawable/fa_droplet.xml
new file mode 100644
index 000000000..8fabc656f
--- /dev/null
+++ b/app/src/main/res/drawable/fa_droplet.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_faucet.xml b/app/src/main/res/drawable/fa_faucet.xml
new file mode 100644
index 000000000..31ec4b0da
--- /dev/null
+++ b/app/src/main/res/drawable/fa_faucet.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_feather.xml b/app/src/main/res/drawable/fa_feather.xml
new file mode 100644
index 000000000..43fa96de7
--- /dev/null
+++ b/app/src/main/res/drawable/fa_feather.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_film.xml b/app/src/main/res/drawable/fa_film.xml
new file mode 100644
index 000000000..8611526cb
--- /dev/null
+++ b/app/src/main/res/drawable/fa_film.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_fire.xml b/app/src/main/res/drawable/fa_fire.xml
new file mode 100644
index 000000000..12374376d
--- /dev/null
+++ b/app/src/main/res/drawable/fa_fire.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_fish.xml b/app/src/main/res/drawable/fa_fish.xml
new file mode 100644
index 000000000..e6abd769a
--- /dev/null
+++ b/app/src/main/res/drawable/fa_fish.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_flag_checkered.xml b/app/src/main/res/drawable/fa_flag_checkered.xml
new file mode 100644
index 000000000..29b560fd7
--- /dev/null
+++ b/app/src/main/res/drawable/fa_flag_checkered.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_gauge.xml b/app/src/main/res/drawable/fa_gauge.xml
new file mode 100644
index 000000000..398f619e1
--- /dev/null
+++ b/app/src/main/res/drawable/fa_gauge.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_ghost.xml b/app/src/main/res/drawable/fa_ghost.xml
new file mode 100644
index 000000000..e4db79a04
--- /dev/null
+++ b/app/src/main/res/drawable/fa_ghost.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_gift.xml b/app/src/main/res/drawable/fa_gift.xml
new file mode 100644
index 000000000..a403ac6b8
--- /dev/null
+++ b/app/src/main/res/drawable/fa_gift.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_glasses.xml b/app/src/main/res/drawable/fa_glasses.xml
new file mode 100644
index 000000000..67e221708
--- /dev/null
+++ b/app/src/main/res/drawable/fa_glasses.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_graduation_cap.xml b/app/src/main/res/drawable/fa_graduation_cap.xml
new file mode 100644
index 000000000..4730971eb
--- /dev/null
+++ b/app/src/main/res/drawable/fa_graduation_cap.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_guitar.xml b/app/src/main/res/drawable/fa_guitar.xml
new file mode 100644
index 000000000..fe7247ad1
--- /dev/null
+++ b/app/src/main/res/drawable/fa_guitar.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_hammer.xml b/app/src/main/res/drawable/fa_hammer.xml
new file mode 100644
index 000000000..430262cc0
--- /dev/null
+++ b/app/src/main/res/drawable/fa_hammer.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_hand.xml b/app/src/main/res/drawable/fa_hand.xml
new file mode 100644
index 000000000..df2d00345
--- /dev/null
+++ b/app/src/main/res/drawable/fa_hand.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_handshake.xml b/app/src/main/res/drawable/fa_handshake.xml
new file mode 100644
index 000000000..fc7c60c98
--- /dev/null
+++ b/app/src/main/res/drawable/fa_handshake.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_hippo.xml b/app/src/main/res/drawable/fa_hippo.xml
new file mode 100644
index 000000000..fa35d6ffe
--- /dev/null
+++ b/app/src/main/res/drawable/fa_hippo.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_ice_cream.xml b/app/src/main/res/drawable/fa_ice_cream.xml
new file mode 100644
index 000000000..d50d59cc6
--- /dev/null
+++ b/app/src/main/res/drawable/fa_ice_cream.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_industry.xml b/app/src/main/res/drawable/fa_industry.xml
new file mode 100644
index 000000000..9b57b66f9
--- /dev/null
+++ b/app/src/main/res/drawable/fa_industry.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_kiwi_bird.xml b/app/src/main/res/drawable/fa_kiwi_bird.xml
new file mode 100644
index 000000000..025b1d1da
--- /dev/null
+++ b/app/src/main/res/drawable/fa_kiwi_bird.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_magnet.xml b/app/src/main/res/drawable/fa_magnet.xml
new file mode 100644
index 000000000..9a3a6bd91
--- /dev/null
+++ b/app/src/main/res/drawable/fa_magnet.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_map.xml b/app/src/main/res/drawable/fa_map.xml
new file mode 100644
index 000000000..f40243a69
--- /dev/null
+++ b/app/src/main/res/drawable/fa_map.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_map_signs.xml b/app/src/main/res/drawable/fa_map_signs.xml
new file mode 100644
index 000000000..9dca18713
--- /dev/null
+++ b/app/src/main/res/drawable/fa_map_signs.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_meteor.xml b/app/src/main/res/drawable/fa_meteor.xml
new file mode 100644
index 000000000..0e1ea7044
--- /dev/null
+++ b/app/src/main/res/drawable/fa_meteor.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_microscope.xml b/app/src/main/res/drawable/fa_microscope.xml
new file mode 100644
index 000000000..efed4ff46
--- /dev/null
+++ b/app/src/main/res/drawable/fa_microscope.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_moon.xml b/app/src/main/res/drawable/fa_moon.xml
new file mode 100644
index 000000000..1d0cb335d
--- /dev/null
+++ b/app/src/main/res/drawable/fa_moon.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_mountain_sun.xml b/app/src/main/res/drawable/fa_mountain_sun.xml
new file mode 100644
index 000000000..99caa011a
--- /dev/null
+++ b/app/src/main/res/drawable/fa_mountain_sun.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_mug_hot.xml b/app/src/main/res/drawable/fa_mug_hot.xml
new file mode 100644
index 000000000..4a3c8a442
--- /dev/null
+++ b/app/src/main/res/drawable/fa_mug_hot.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_music.xml b/app/src/main/res/drawable/fa_music.xml
new file mode 100644
index 000000000..41e0a80e2
--- /dev/null
+++ b/app/src/main/res/drawable/fa_music.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_paw.xml b/app/src/main/res/drawable/fa_paw.xml
new file mode 100644
index 000000000..dad4cbb75
--- /dev/null
+++ b/app/src/main/res/drawable/fa_paw.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_pen_nib.xml b/app/src/main/res/drawable/fa_pen_nib.xml
new file mode 100644
index 000000000..0927a15ce
--- /dev/null
+++ b/app/src/main/res/drawable/fa_pen_nib.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_pepper_hot.xml b/app/src/main/res/drawable/fa_pepper_hot.xml
new file mode 100644
index 000000000..7890e7f97
--- /dev/null
+++ b/app/src/main/res/drawable/fa_pepper_hot.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_person_biking.xml b/app/src/main/res/drawable/fa_person_biking.xml
new file mode 100644
index 000000000..d971ab9e1
--- /dev/null
+++ b/app/src/main/res/drawable/fa_person_biking.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_pills.xml b/app/src/main/res/drawable/fa_pills.xml
new file mode 100644
index 000000000..81a8a3278
--- /dev/null
+++ b/app/src/main/res/drawable/fa_pills.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_plane.xml b/app/src/main/res/drawable/fa_plane.xml
new file mode 100644
index 000000000..fc5a16a07
--- /dev/null
+++ b/app/src/main/res/drawable/fa_plane.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_plug.xml b/app/src/main/res/drawable/fa_plug.xml
new file mode 100644
index 000000000..115302dd1
--- /dev/null
+++ b/app/src/main/res/drawable/fa_plug.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_radio.xml b/app/src/main/res/drawable/fa_radio.xml
new file mode 100644
index 000000000..e3508650b
--- /dev/null
+++ b/app/src/main/res/drawable/fa_radio.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_rainbow.xml b/app/src/main/res/drawable/fa_rainbow.xml
new file mode 100644
index 000000000..2e3bd8a31
--- /dev/null
+++ b/app/src/main/res/drawable/fa_rainbow.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_ribbon.xml b/app/src/main/res/drawable/fa_ribbon.xml
new file mode 100644
index 000000000..efe92f454
--- /dev/null
+++ b/app/src/main/res/drawable/fa_ribbon.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_road.xml b/app/src/main/res/drawable/fa_road.xml
new file mode 100644
index 000000000..60f571f83
--- /dev/null
+++ b/app/src/main/res/drawable/fa_road.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_rocket.xml b/app/src/main/res/drawable/fa_rocket.xml
new file mode 100644
index 000000000..5fbcec2a4
--- /dev/null
+++ b/app/src/main/res/drawable/fa_rocket.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_sack_dollar.xml b/app/src/main/res/drawable/fa_sack_dollar.xml
new file mode 100644
index 000000000..39e4fba30
--- /dev/null
+++ b/app/src/main/res/drawable/fa_sack_dollar.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_school.xml b/app/src/main/res/drawable/fa_school.xml
new file mode 100644
index 000000000..9e0d3d294
--- /dev/null
+++ b/app/src/main/res/drawable/fa_school.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_scissors.xml b/app/src/main/res/drawable/fa_scissors.xml
new file mode 100644
index 000000000..4ad5a1163
--- /dev/null
+++ b/app/src/main/res/drawable/fa_scissors.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_seedling.xml b/app/src/main/res/drawable/fa_seedling.xml
new file mode 100644
index 000000000..dc04ab510
--- /dev/null
+++ b/app/src/main/res/drawable/fa_seedling.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_shield.xml b/app/src/main/res/drawable/fa_shield.xml
new file mode 100644
index 000000000..667bd6b62
--- /dev/null
+++ b/app/src/main/res/drawable/fa_shield.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_skull.xml b/app/src/main/res/drawable/fa_skull.xml
new file mode 100644
index 000000000..db0d0b3cd
--- /dev/null
+++ b/app/src/main/res/drawable/fa_skull.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_smile.xml b/app/src/main/res/drawable/fa_smile.xml
new file mode 100644
index 000000000..03ee29dba
--- /dev/null
+++ b/app/src/main/res/drawable/fa_smile.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_snowflake.xml b/app/src/main/res/drawable/fa_snowflake.xml
new file mode 100644
index 000000000..b6c51a6e9
--- /dev/null
+++ b/app/src/main/res/drawable/fa_snowflake.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_socks.xml b/app/src/main/res/drawable/fa_socks.xml
new file mode 100644
index 000000000..1768e9cac
--- /dev/null
+++ b/app/src/main/res/drawable/fa_socks.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_spider.xml b/app/src/main/res/drawable/fa_spider.xml
new file mode 100644
index 000000000..ae82070ae
--- /dev/null
+++ b/app/src/main/res/drawable/fa_spider.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_suitcase_medical.xml b/app/src/main/res/drawable/fa_suitcase_medical.xml
new file mode 100644
index 000000000..697ebf040
--- /dev/null
+++ b/app/src/main/res/drawable/fa_suitcase_medical.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_sun.xml b/app/src/main/res/drawable/fa_sun.xml
new file mode 100644
index 000000000..5e051a84e
--- /dev/null
+++ b/app/src/main/res/drawable/fa_sun.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_temperature_three_quarters.xml b/app/src/main/res/drawable/fa_temperature_three_quarters.xml
new file mode 100644
index 000000000..e5abcbc54
--- /dev/null
+++ b/app/src/main/res/drawable/fa_temperature_three_quarters.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_tractor.xml b/app/src/main/res/drawable/fa_tractor.xml
new file mode 100644
index 000000000..46737d840
--- /dev/null
+++ b/app/src/main/res/drawable/fa_tractor.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_tree.xml b/app/src/main/res/drawable/fa_tree.xml
new file mode 100644
index 000000000..e466e8fc8
--- /dev/null
+++ b/app/src/main/res/drawable/fa_tree.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_trophy.xml b/app/src/main/res/drawable/fa_trophy.xml
new file mode 100644
index 000000000..29ca3332a
--- /dev/null
+++ b/app/src/main/res/drawable/fa_trophy.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_umbrella.xml b/app/src/main/res/drawable/fa_umbrella.xml
new file mode 100644
index 000000000..48e9420fa
--- /dev/null
+++ b/app/src/main/res/drawable/fa_umbrella.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_user_astronaut.xml b/app/src/main/res/drawable/fa_user_astronaut.xml
new file mode 100644
index 000000000..e39692128
--- /dev/null
+++ b/app/src/main/res/drawable/fa_user_astronaut.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_utensils.xml b/app/src/main/res/drawable/fa_utensils.xml
new file mode 100644
index 000000000..1bf4c8bec
--- /dev/null
+++ b/app/src/main/res/drawable/fa_utensils.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_volcano.xml b/app/src/main/res/drawable/fa_volcano.xml
new file mode 100644
index 000000000..5ebebe8b7
--- /dev/null
+++ b/app/src/main/res/drawable/fa_volcano.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/fa_wine_glass.xml b/app/src/main/res/drawable/fa_wine_glass.xml
new file mode 100644
index 000000000..9d19cd03d
--- /dev/null
+++ b/app/src/main/res/drawable/fa_wine_glass.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_ooni_run_v2.xml b/app/src/main/res/layout/activity_ooni_run_v2.xml
new file mode 100644
index 000000000..0dfc63c1d
--- /dev/null
+++ b/app/src/main/res/layout/activity_ooni_run_v2.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_overview.xml b/app/src/main/res/layout/activity_overview.xml
index 3e2ecf88c..68e64eefa 100644
--- a/app/src/main/res/layout/activity_overview.xml
+++ b/app/src/main/res/layout/activity_overview.xml
@@ -247,4 +247,4 @@
android:layout_gravity="bottom"
app:layout_anchorGravity="bottom" />
-
\ No newline at end of file
+