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: - *

- * 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, 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 @@ + + + + + + + + + + + + + + +