From 4739b3aeb51491fb880bf3c7d1abbed6000c55a8 Mon Sep 17 00:00:00 2001 From: mozilla-l10n-automation-bot <54512241+mozilla-l10n-automation-bot@users.noreply.github.com> Date: Thu, 19 Dec 2019 03:36:01 -0700 Subject: [PATCH 1/3] Import l10n. (#2503) --- app/src/main/res/values-fr/strings.xml | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index c58fe36f6e..8993b8424b 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -164,7 +164,7 @@ 'Firefox Display Language' dialog window (accessible from the browser's Settings dialog window). Below this string appears a list of locales for the user to choose as their preferred display language for the application UI. --> - Langue d\'affichage de %1$s + Langue d’affichage de %1$s - Autoriser %1$s à envoyer des données techniques et d’interaction à Mozilla - + Autoriser %1$s à envoyer des données techniques et d’interaction à Mozilla @@ -646,7 +645,7 @@ - Recherche en cours... + Recherche en cours… @@ -662,7 +661,7 @@ - Rechercher sur Internet ou saisir une adresse + Rechercher sur le Web ou saisir une adresse @@ -1116,17 +1115,15 @@ - Lorsque vous naviguez dans une fenêtre privée, %1$s n’enregistre pas:

+ Lorsque vous naviguez dans une fenêtre privée, %1$s n’enregistre pas :

La navigation privée ne vous offre pas l’anonymat sur Internet. Votre fournisseur d’accès à Internet ou votre employeur peuvent toujours connaître les pages que vous visitez.

-

En savoir plus Navigation privée.

- ]]>
+

En savoir plus sur la navigation privée.

]]>
From d655b7eb77fcf549825cfed6502ed67547515c11 Mon Sep 17 00:00:00 2001 From: Daosheng Mu Date: Thu, 19 Dec 2019 03:31:47 -0800 Subject: [PATCH 2/3] Support Glean metric unit tests (#2444) * Support Glean unit test. * Run Glean unit test in Taskcluster. --- .taskcluster.yml | 1 + app/build.gradle | 18 ++- .../org/mozilla/vrbrowser/browser/Accounts.kt | 7 +- .../org/mozilla/vrbrowser/browser/Services.kt | 9 +- .../telemetry/GleanMetricsService.java | 6 + .../vrbrowser/GleanMetricsServiceTest.kt | 135 ++++++++++++++++++ versions.gradle | 15 ++ 7 files changed, 182 insertions(+), 9 deletions(-) create mode 100644 app/src/test/java/org/mozilla/vrbrowser/GleanMetricsServiceTest.kt diff --git a/.taskcluster.yml b/.taskcluster.yml index bbdee725c1..7fe7e771aa 100644 --- a/.taskcluster.yml +++ b/.taskcluster.yml @@ -43,6 +43,7 @@ tasks: && rm -rf gvr-android-sdk && git clone https://github.com/MozillaReality/FirefoxReality-gvr-android-sdk.git gvr-android-sdk && git submodule update && ./gradlew --no-daemon --console=plain clean `python tools/taskcluster/build_targets.py =all+googlevr+noapi` + && ./gradlew app:testNoapiArm64DebugUnitTest metadata: name: Firefox Reality for Android - Build - Pull Request description: Building Firefox Reality for Android (via Gradle) - triggered by a pull request. diff --git a/app/build.gradle b/app/build.gradle index 538002c842..b010f0df9b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -414,6 +414,10 @@ android { ] } } + + testOptions { + unitTests.includeAndroidResources = true + } } configurations { @@ -460,6 +464,7 @@ dependencies { implementation deps.android_components.support_rustlog implementation deps.android_components.support_rusthttp implementation deps.android_components.glean + implementation deps.app_services.rustlog // For production builds, the native code for all `org.mozilla.appservices` // dependencies gets compiled together into a single "megazord" build, and @@ -467,14 +472,10 @@ dependencies { // https://mozilla.github.io/application-services/docs/applications/consuming-megazord-libraries.html // For now we can jut use the one that's specifically designed for Fenix. implementation deps.app_services.megazord - testImplementation deps.app_services.megazord_forUnitTests modules { module('org.mozilla.appservices:full-megazord') { replacedBy('org.mozilla.appservices:fenix-megazord', 'prefer the fenix megazord, to reduce final application size') } - module('org.mozilla.appservices:fenix-megazord') { - replacedBy('org.mozilla.appservices:fenix-megazord-forUnitTests', 'prefer the forUnitTests variant if present') - } } // TODO this should not be necessary at all, see Services.kt @@ -495,9 +496,16 @@ dependencies { implementation deps.disklrucache.disklrucache // Testing - testImplementation deps.junit androidTestImplementation deps.atsl.runner androidTestImplementation deps.espresso.core + testImplementation deps.junit + testImplementation deps.atsl.core + testImplementation deps.robolectric + testImplementation deps.app_services.megazord_forUnitTests + testImplementation deps.app_services.rustlog + testImplementation deps.android_components.support_test + testImplementation deps.telemetry.glean_unittests + testImplementation deps.work.testing // Daydream googlevrImplementation deps.google_vr.sdk_base diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt index 604eac7e63..3d1cadf04d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Accounts.kt @@ -229,7 +229,12 @@ class Accounts constructor(val context: Context) { private fun loadDefaultProfilePicture(): BitmapDrawable? { BitmapFactory.decodeResource(context.resources, R.drawable.ic_icon_settings_account)?.let { - BitmapCache.getInstance(context).addBitmap(PROFILE_PICTURE_TAG, it) + try { + BitmapCache.getInstance(context).addBitmap(PROFILE_PICTURE_TAG, it) + } catch (e: NullPointerException) { + Log.w(LOGTAG, "Bitmap is a null pointer.") + return null + } profilePicture = BitmapDrawable(context.resources, ViewUtils.getRoundedCroppedBitmap(it)) } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt index e8eb141103..c8c9ec72e3 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt @@ -15,6 +15,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import mozilla.appservices.Megazord +import mozilla.appservices.rustlog.LogAdapterCannotEnable import mozilla.components.concept.sync.* import mozilla.components.service.fxa.* import mozilla.components.service.fxa.manager.FxaAccountManager @@ -29,8 +30,6 @@ import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoSession import org.mozilla.vrbrowser.R import org.mozilla.vrbrowser.browser.engine.EngineProvider -import org.mozilla.vrbrowser.browser.engine.GeckoViewFetchClient -import org.mozilla.vrbrowser.browser.engine.SessionStore import org.mozilla.vrbrowser.utils.SystemUtils import org.mozilla.vrbrowser.telemetry.GleanMetricsService @@ -52,7 +51,11 @@ class Services(val context: Context, places: Places): GeckoSession.NavigationDel // This makes bookmarks storage accessible to background sync workers. init { Megazord.init() - RustLog.enable() + try { + RustLog.enable() + } catch (e: LogAdapterCannotEnable) { + android.util.Log.w(LOGTAG, "RustLog has been enabled.") + } RustHttpConfig.setClient(lazy { EngineProvider.createClient(context) }) // Make sure we get logs out of our android-components. diff --git a/app/src/common/shared/org/mozilla/vrbrowser/telemetry/GleanMetricsService.java b/app/src/common/shared/org/mozilla/vrbrowser/telemetry/GleanMetricsService.java index 8e2a361b12..6e065a49c7 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/telemetry/GleanMetricsService.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/telemetry/GleanMetricsService.java @@ -5,6 +5,7 @@ import androidx.annotation.NonNull; import androidx.annotation.UiThread; +import androidx.annotation.VisibleForTesting; import org.mozilla.vrbrowser.BuildConfig; import org.mozilla.vrbrowser.GleanMetrics.Distribution; @@ -159,6 +160,11 @@ private static void setStartupMetrics() { Distribution.INSTANCE.getChannelName().set(DeviceType.isOculusBuild() ? "oculusvr" : BuildConfig.FLAVOR_platform); } + @VisibleForTesting + public static void testSetStartupMetrics() { + setStartupMetrics(); + } + public static class FxA { public static void signIn() { diff --git a/app/src/test/java/org/mozilla/vrbrowser/GleanMetricsServiceTest.kt b/app/src/test/java/org/mozilla/vrbrowser/GleanMetricsServiceTest.kt new file mode 100644 index 0000000000..f48ee03946 --- /dev/null +++ b/app/src/test/java/org/mozilla/vrbrowser/GleanMetricsServiceTest.kt @@ -0,0 +1,135 @@ +package org.mozilla.vrbrowser + +import androidx.test.core.app.ApplicationProvider +import mozilla.components.concept.sync.DeviceType +import mozilla.components.service.glean.testing.GleanTestRule +import org.junit.Assert.* +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.vrbrowser.GleanMetrics.* +import org.mozilla.vrbrowser.telemetry.GleanMetricsService +import org.robolectric.RobolectricTestRunner +import org.robolectric.annotation.Config + + +@RunWith(RobolectricTestRunner::class) +@Config(manifest = Config.NONE) +class GleanMetricsServiceTest { + + @get:Rule + val gleanRule = GleanTestRule(ApplicationProvider.getApplicationContext()) + + @Test + fun testURLTelemetry() { + assertFalse(Url.domains.testHasValue()) + assertFalse(Url.visits.testHasValue()) + GleanMetricsService.stopPageLoadTimeWithURI("https://www.example.com/test.html"); + assertTrue(Url.domains.testHasValue()) + assertEquals(Url.domains.testGetValue(), 1) + + assertTrue(Url.visits.testHasValue()) + assertEquals(Url.visits.testGetValue(), 1) + + assertFalse(Url.queryType["type_link"].testHasValue()) + assertFalse(Url.queryType["type_query"].testHasValue()) + GleanMetricsService.urlBarEvent(true) + assertTrue(Url.queryType["type_link"].testHasValue()) + assertEquals(Url.queryType["type_link"].testGetValue(), 1) + GleanMetricsService.urlBarEvent(false) + assertTrue(Url.queryType["type_query"].testHasValue()) + assertEquals(Url.queryType["type_query"].testGetValue(), 1) + + assertFalse(Url.queryType["voice_query"].testHasValue()) + GleanMetricsService.voiceInputEvent() + assertTrue(Url.queryType["voice_query"].testHasValue()) + assertEquals(Url.queryType["voice_query"].testGetValue(), 1) + } + + @Test + fun testDistributionChannelTelemetry() { + assertFalse(Distribution.channelName.testHasValue()) + GleanMetricsService.testSetStartupMetrics() + assertTrue(Distribution.channelName.testHasValue()) + assertEquals(Distribution.channelName.testGetValue(), BuildConfig.FLAVOR_platform) + } + + @Test + fun testFxAAccountTelemetry() { + assertFalse(FirefoxAccount.signIn.testHasValue()) + GleanMetricsService.FxA.signIn() + assertTrue(FirefoxAccount.signIn.testHasValue()) + var events = FirefoxAccount.signIn.testGetValue() + assertEquals(events.size, 1) + + assertFalse(FirefoxAccount.signInResult.testHasValue()) + GleanMetricsService.FxA.signInResult(false) + assertTrue(FirefoxAccount.signInResult.testHasValue()) + events = FirefoxAccount.signInResult.testGetValue() + assertEquals(events.size, 1) + // We only expect 1 extra key. + assertEquals(events[0].extra!!.size, 1) + assertEquals(events[0].extra!!["state"], "false") + + GleanMetricsService.FxA.signInResult(true) + events = FirefoxAccount.signInResult.testGetValue() + assertEquals(events.size, 2) + // We only expect 1 extra key. + assertEquals(events[1].extra!!.size, 1) + assertEquals(events[1].extra!!["state"], "true") + + assertFalse(FirefoxAccount.signOut.testHasValue()) + GleanMetricsService.FxA.signOut() + assertTrue(FirefoxAccount.signOut.testHasValue()) + events = FirefoxAccount.signOut.testGetValue() + assertEquals(events.size, 1) + } + + @Test + fun testFxABookmarkTelemetry() { + assertFalse(FirefoxAccount.bookmarksSyncStatus.testHasValue()) + GleanMetricsService.FxA.bookmarksSyncStatus(false) + assertTrue(FirefoxAccount.bookmarksSyncStatus.testHasValue()) + assertEquals(FirefoxAccount.bookmarksSyncStatus.testGetValue(), false) + + GleanMetricsService.FxA.bookmarksSyncStatus(true) + assertEquals(FirefoxAccount.bookmarksSyncStatus.testGetValue(), true) + } + + @Test + fun testFxAHistoryTelemetry() { + assertFalse(FirefoxAccount.historySyncStatus.testHasValue()) + GleanMetricsService.FxA.historySyncStatus(false) + assertTrue(FirefoxAccount.historySyncStatus.testHasValue()) + assertEquals(FirefoxAccount.historySyncStatus.testGetValue(), false) + + GleanMetricsService.FxA.historySyncStatus(true) + assertEquals(FirefoxAccount.historySyncStatus.testGetValue(), true) + } + + @Test + fun testFxATabTelemetry() { + assertFalse(FirefoxAccount.tabSent.testHasValue()) + GleanMetricsService.FxA.sentTab() + assertTrue(FirefoxAccount.tabSent.testHasValue()) + assertEquals(FirefoxAccount.tabSent.testGetValue(), 1) + + assertFalse(FirefoxAccount.receivedTab[DeviceType.MOBILE.name].testHasValue()) + GleanMetricsService.FxA.receivedTab(DeviceType.MOBILE) + assertTrue(FirefoxAccount.receivedTab[DeviceType.MOBILE.name].testHasValue()) + assertEquals(FirefoxAccount.receivedTab[DeviceType.MOBILE.name].testGetValue(), 1) + } + + @Test + fun testTabTelemetry() { + assertFalse(Tabs.opened[GleanMetricsService.Tabs.TabSource.BOOKMARKS.name].testHasValue()) + GleanMetricsService.Tabs.openedCounter(GleanMetricsService.Tabs.TabSource.BOOKMARKS) + assertTrue(Tabs.opened[GleanMetricsService.Tabs.TabSource.BOOKMARKS.name].testHasValue()) + assertEquals(Tabs.opened[GleanMetricsService.Tabs.TabSource.BOOKMARKS.name].testGetValue(), 1) + + assertFalse(Tabs.activated.testHasValue()) + GleanMetricsService.Tabs.activatedEvent() + assertTrue(Tabs.activated.testHasValue()) + assertEquals(Tabs.activated.testGetValue(), 1) + } +} diff --git a/versions.gradle b/versions.gradle index 902d8fb826..a70b00e742 100644 --- a/versions.gradle +++ b/versions.gradle @@ -42,6 +42,7 @@ versions.support = "1.0.0" versions.recyclerview = "1.1.0" versions.constraint_layout = "2.0.0-alpha2" versions.junit = "4.12" +versions.atsl_core = "1.2.0" versions.atsl_runner = "1.1.0-alpha4" versions.atsl_rules = "1.1.0-alpha4" versions.espresso = "3.1.0-alpha4" @@ -50,7 +51,11 @@ versions.kotlin = "1.3.31" versions.kotlin_coroutines = "1.2.1" versions.snakeyaml = "1.24" versions.gson = "2.8.5" +versions.robolectric = "4.2.1" +versions.work = "2.2.0" +versions.telemetry = "22.0.0" ext.versions = versions + def deps = [:] def gecko_view = [:] @@ -72,11 +77,13 @@ android_components.concept_fetch = "org.mozilla.components:concept-fetch:$versio android_components.lib_fetch = "org.mozilla.components:lib-fetch-httpurlconnection:$versions.android_components" android_components.support_rustlog = "org.mozilla.components:support-rustlog:$versions.android_components" android_components.support_rusthttp = "org.mozilla.components:support-rusthttp:$versions.android_components" +android_components.support_test = "org.mozilla.components:support-test:$versions.android_components" deps.android_components = android_components def app_services = [:] app_services.megazord = "org.mozilla.appservices:fenix-megazord:${versions.mozilla_appservices}" app_services.megazord_forUnitTests = "org.mozilla.appservices:fenix-megazord-forUnitTests:${versions.mozilla_appservices}" +app_services.rustlog = "org.mozilla.appservices:rustlog:${versions.mozilla_appservices}" deps.app_services = app_services deps.mozilla_speech = "com.github.mozilla:mozillaspeechlibrary:$versions.mozilla_speech" @@ -102,6 +109,7 @@ deps.support = support // TODO this should not be necessary at all, see Services.kt def work = [:] work.runtime = "androidx.work:work-runtime-ktx:$versions.work" +work.testing = "androidx.work:work-testing:$versions.work" deps.work = work def room = [:] @@ -124,6 +132,7 @@ espresso.intents = "androidx.test.espresso:espresso-intents:$versions.espresso" deps.espresso = espresso def atsl = [:] +atsl.core = "androidx.test:core-ktx:$versions.atsl_core" atsl.runner = "androidx.test:runner:$versions.atsl_runner" atsl.rules = "androidx.test:rules:$versions.atsl_runner" deps.atsl = atsl @@ -145,6 +154,10 @@ kotlin.coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$versions.kot kotlin.coroutines_jdk8 = "org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$versions.kotlin_coroutines" deps.kotlin = kotlin +def telemetry = [:] +telemetry.glean_unittests = "org.mozilla.telemetry:glean-forUnitTests:$versions.telemetry" +deps.telemetry = telemetry + deps.constraint_layout = "androidx.constraintlayout:constraintlayout:$versions.constraint_layout" deps.junit = "junit:junit:$versions.junit" @@ -157,6 +170,8 @@ deps.snakeyaml = "org.yaml:snakeyaml:$versions.snakeyaml:android" deps.gson = "com.google.code.gson:gson:$versions.gson" +deps.robolectric = "org.robolectric:robolectric:$versions.robolectric" + ext.deps = deps def build_versions = [:] From c7f86edb88b80e4e8771692c013a698dd4e22030 Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Thu, 19 Dec 2019 13:43:17 +0100 Subject: [PATCH 3/3] Dialogs refactoring (#2468) * Dialogs refactoring Restart dialog refactored Crash dialog refactored Removed Max Windows dialog PopUp block dialog refactored Collect voice samples refactored Open Settings links in new tabs What's new and Sign Out dialogs refactored Voice Search Dialog refactored Added empty popup exceptions panel text Position adjustments Clear Cache dialog refactored Removed unused resources Browser alert and confirm refactor * Restore the Restart dialog checkbox * Fix broken crashcontent crashes receiver * Rename ClearCacheDialogWidget to ClearHistoryDialogWidget wip * Restore the Sad Fox icon for the crash dialog * Ensure that the crash dialog checkbox is always unchecked when showing * Move the sad fox icon it to the right folder --- .../mozilla/vrbrowser/VRBrowserActivity.java | 111 ++------- .../vrbrowser/browser/PermissionDelegate.java | 1 - .../vrbrowser/browser/PromptDelegate.java | 23 +- .../crashreporting/CrashReporterService.java | 9 +- .../ui/widgets/NavigationBarWidget.java | 2 - .../ui/widgets/NoInternetWidget.java | 56 ----- .../vrbrowser/ui/widgets/WindowWidget.java | 189 +++++++-------- .../widgets/dialogs/BaseAppDialogWidget.java | 146 ----------- .../dialogs/ClearCacheDialogWidget.java | 48 ---- .../dialogs/ClearHistoryDialogWidget.java | 78 ++++++ .../ui/widgets/dialogs/CrashDialogWidget.java | 130 ++++------ .../ui/widgets/dialogs/MaxWindowsWidget.java | 40 --- .../widgets/dialogs/MessageDialogWidget.java | 59 ----- .../ui/widgets/dialogs/PermissionWidget.java | 73 +++--- .../dialogs/PopUpBlockDialogWidget.java | 20 +- ...logWidget.java => PromptDialogWidget.java} | 106 +++++--- .../widgets/dialogs/RestartDialogWidget.java | 69 ++---- .../widgets/dialogs/SendTabDialogWidget.java | 30 +-- .../widgets/dialogs/SettingDialogWidget.java | 20 +- .../widgets/dialogs/SignOutDialogWidget.java | 87 +++++++ .../ui/widgets/dialogs/UIDialog.java | 6 +- .../ui/widgets/dialogs/VoiceSearchWidget.java | 122 ++++------ .../ui/widgets/dialogs/WhatsNewWidget.java | 60 ++--- .../ui/widgets/prompts/PromptWidget.java | 10 +- .../settings/ContentLanguageOptionsView.java | 5 +- .../settings/DisplayLanguageOptionsView.java | 4 +- .../settings/FxAAccountOptionsView.java | 44 +--- .../widgets/settings/LanguageOptionsView.java | 4 +- ...w.java => PopUpExceptionsOptionsView.java} | 12 +- .../widgets/settings/PrivacyOptionsView.java | 2 +- .../ui/widgets/settings/SettingsWidget.java | 35 +-- .../VoiceSearchLanguageOptionsView.java | 4 +- .../mozilla/vrbrowser/utils/SystemUtils.java | 75 ++++++ .../res/color/context_menu_icon_color.xml | 4 - .../res/color/context_menu_text_color.xml | 4 - app/src/main/res/color/rhino_void_tint.xml | 6 - app/src/main/res/color/void_fog_tint.xml | 6 - .../context_menu_item_background_color.xml | 24 -- .../dialog_close_button_background.xml | 21 -- .../dialog_close_button_icon_color.xml | 9 - .../drawable/ic_context_menu_new_window.xml | 10 - app/src/main/res/drawable/ic_icon_browser.xml | 11 - .../res/drawable/ic_icon_dialog_cancel.xml | 4 - .../drawable/ic_icon_dialog_tabs_active.xml | 12 - app/src/main/res/drawable/ic_icon_empty.xml | 5 - .../main/res/drawable/ic_icon_move_down.xml | 8 +- app/src/main/res/drawable/ic_icon_move_up.xml | 15 +- .../ic_keyboard_arrow_left_black_24px.xml | 9 - .../ic_keyboard_arrow_right_black_24px.xml | 9 - .../res/drawable/ic_keyboard_keyboard.xml | 101 -------- .../drawable/microphone_icon_background.xml | 4 - .../res/drawable/navigation_button_color.xml | 10 - .../res/drawable/panel_button_background.xml | 27 --- .../res/drawable/radio_unchecked_pressed.xml | 18 -- .../settings_list_row_background_color.xml | 24 -- .../res/drawable/url_button_end_private.xml | 23 -- .../main/res/drawable/url_button_private.xml | 20 -- .../res/drawable/url_button_start_private.xml | 23 -- app/src/main/res/layout/base_app_dialog.xml | 118 --------- ...he_dialog.xml => clear_history_dialog.xml} | 3 +- app/src/main/res/layout/close_button.xml | 16 -- app/src/main/res/layout/context_menu.xml | 18 -- app/src/main/res/layout/crash_dialog.xml | 95 -------- app/src/main/res/layout/language_item.xml | 10 +- app/src/main/res/layout/message_dialog.xml | 19 -- app/src/main/res/layout/no_internet.xml | 72 ------ .../res/layout/options_privacy_popups.xml | 78 ++++-- app/src/main/res/layout/permission.xml | 72 ------ .../main/res/layout/popup_block_dialog.xml | 54 ----- ...{checkbox_dialog.xml => prompt_dialog.xml} | 50 +++- .../main/res/layout/prompt_max_windows.xml | 43 ---- app/src/main/res/layout/restart_dialog.xml | 79 ------ app/src/main/res/layout/send_tabs_display.xml | 4 +- .../main/res/layout/voice_search_dialog.xml | 228 +++++++++++------- app/src/main/res/layout/whats_new.xml | 104 -------- app/src/main/res/values/dimen.xml | 99 ++------ app/src/main/res/values/non_L10n.xml | 2 +- app/src/main/res/values/strings.xml | 17 +- app/src/main/res/values/styles.xml | 51 +--- 79 files changed, 965 insertions(+), 2354 deletions(-) delete mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NoInternetWidget.java delete mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/BaseAppDialogWidget.java delete mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/ClearCacheDialogWidget.java create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/ClearHistoryDialogWidget.java delete mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/MaxWindowsWidget.java delete mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/MessageDialogWidget.java rename app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/{CheckboxDialogWidget.java => PromptDialogWidget.java} (57%) create mode 100644 app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SignOutDialogWidget.java rename app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/{AllowedPopUpsOptionsView.java => PopUpExceptionsOptionsView.java} (90%) delete mode 100644 app/src/main/res/color/context_menu_icon_color.xml delete mode 100644 app/src/main/res/color/context_menu_text_color.xml delete mode 100644 app/src/main/res/color/rhino_void_tint.xml delete mode 100644 app/src/main/res/color/void_fog_tint.xml delete mode 100644 app/src/main/res/drawable/context_menu_item_background_color.xml delete mode 100644 app/src/main/res/drawable/dialog_close_button_background.xml delete mode 100644 app/src/main/res/drawable/dialog_close_button_icon_color.xml delete mode 100644 app/src/main/res/drawable/ic_context_menu_new_window.xml delete mode 100644 app/src/main/res/drawable/ic_icon_browser.xml delete mode 100644 app/src/main/res/drawable/ic_icon_dialog_cancel.xml delete mode 100644 app/src/main/res/drawable/ic_icon_dialog_tabs_active.xml delete mode 100644 app/src/main/res/drawable/ic_icon_empty.xml delete mode 100644 app/src/main/res/drawable/ic_keyboard_arrow_left_black_24px.xml delete mode 100644 app/src/main/res/drawable/ic_keyboard_arrow_right_black_24px.xml delete mode 100644 app/src/main/res/drawable/ic_keyboard_keyboard.xml delete mode 100644 app/src/main/res/drawable/microphone_icon_background.xml delete mode 100644 app/src/main/res/drawable/navigation_button_color.xml delete mode 100644 app/src/main/res/drawable/panel_button_background.xml delete mode 100644 app/src/main/res/drawable/radio_unchecked_pressed.xml delete mode 100644 app/src/main/res/drawable/settings_list_row_background_color.xml delete mode 100644 app/src/main/res/drawable/url_button_end_private.xml delete mode 100644 app/src/main/res/drawable/url_button_private.xml delete mode 100644 app/src/main/res/drawable/url_button_start_private.xml delete mode 100644 app/src/main/res/layout/base_app_dialog.xml rename app/src/main/res/layout/{clear_cache_dialog.xml => clear_history_dialog.xml} (85%) delete mode 100644 app/src/main/res/layout/close_button.xml delete mode 100644 app/src/main/res/layout/context_menu.xml delete mode 100644 app/src/main/res/layout/crash_dialog.xml delete mode 100644 app/src/main/res/layout/message_dialog.xml delete mode 100644 app/src/main/res/layout/no_internet.xml delete mode 100644 app/src/main/res/layout/permission.xml delete mode 100644 app/src/main/res/layout/popup_block_dialog.xml rename app/src/main/res/layout/{checkbox_dialog.xml => prompt_dialog.xml} (69%) delete mode 100644 app/src/main/res/layout/prompt_max_windows.xml delete mode 100644 app/src/main/res/layout/restart_dialog.xml delete mode 100644 app/src/main/res/layout/whats_new.xml diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 12f3882011..af5c49e83c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -36,9 +36,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import org.mozilla.gecko.util.ThreadUtils; -import org.mozilla.geckoview.CrashReporter; -import org.mozilla.geckoview.GeckoResult; import org.mozilla.geckoview.GeckoRuntime; import org.mozilla.geckoview.GeckoSession; import org.mozilla.geckoview.GeckoVRManager; @@ -62,15 +59,15 @@ import org.mozilla.vrbrowser.ui.widgets.TrayWidget; import org.mozilla.vrbrowser.ui.widgets.UISurfaceTextureRenderer; import org.mozilla.vrbrowser.ui.widgets.UIWidget; -import org.mozilla.vrbrowser.ui.widgets.menus.VideoProjectionMenuWidget; import org.mozilla.vrbrowser.ui.widgets.Widget; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.ui.widgets.WindowWidget; import org.mozilla.vrbrowser.ui.widgets.Windows; import org.mozilla.vrbrowser.ui.widgets.dialogs.CrashDialogWidget; +import org.mozilla.vrbrowser.ui.widgets.dialogs.PromptDialogWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.WhatsNewWidget; -import org.mozilla.vrbrowser.ui.widgets.prompts.ConfirmPromptWidget; +import org.mozilla.vrbrowser.ui.widgets.menus.VideoProjectionMenuWidget; import org.mozilla.vrbrowser.utils.BitmapCache; import org.mozilla.vrbrowser.utils.ConnectivityReceiver; import org.mozilla.vrbrowser.utils.ConnectivityReceiver.Delegate; @@ -79,13 +76,6 @@ import org.mozilla.vrbrowser.utils.ServoUtils; import org.mozilla.vrbrowser.utils.SystemUtils; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -127,7 +117,6 @@ public void run() { static final int GestureSwipeRight = 1; static final int SwipeDelay = 1000; // milliseconds static final long RESET_CRASH_COUNT_DELAY = 5000; - static final String CRASH_STATS_URL = "https://crash-stats.mozilla.com/report/index/"; static final String LOGTAG = SystemUtils.createLogtag(VRBrowserActivity.class); HashMap mWidgets; @@ -230,7 +219,7 @@ protected void onCreate(Bundle savedInstanceState) { // Create broadcast receiver for getting crash messages from crash process IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(CrashReporterService.CRASH_ACTION); - registerReceiver(mCrashReceiver, intentFilter, getString(R.string.app_permission_name), null); + registerReceiver(mCrashReceiver, intentFilter, BuildConfig.APPLICATION_ID + "." + getString(R.string.app_permission_name), null); mLastGesture = NoGesture; super.onCreate(savedInstanceState); @@ -594,27 +583,12 @@ private void checkForCrash() { } boolean isCrashReportingEnabled = SettingsStore.getInstance(this).isCrashReportingEnabled(); if (isCrashReportingEnabled) { - postCrashFiles(files); + SystemUtils.postCrashFiles(this, files); + } else { if (mCrashDialog == null) { - mCrashDialog = new CrashDialogWidget(this); + mCrashDialog = new CrashDialogWidget(this, files); } - mCrashDialog.setCrashDialogDelegate( - new CrashDialogWidget.CrashDialogDelegate() { - @Override - public void onSendData() { - postCrashFiles(files); - } - - @Override - public void onDoNotSendData() { - for (String file : files) { - Log.e(LOGTAG, "Deleting crashfile: " + file); - getBaseContext().deleteFile(file); - } - } - } - ); mCrashDialog.show(UIWidget.REQUEST_FOCUS); } } @@ -629,65 +603,16 @@ private void handleContentCrashIntent(@NonNull final Intent intent) { boolean isCrashReportingEnabled = SettingsStore.getInstance(this).isCrashReportingEnabled(); if (isCrashReportingEnabled) { - postCrashFiles(dumpFile, extraFile); + SystemUtils.postCrashFiles(this, dumpFile, extraFile); + } else { if (mCrashDialog == null) { - mCrashDialog = new CrashDialogWidget(this); + mCrashDialog = new CrashDialogWidget(this, dumpFile, extraFile); } - mCrashDialog.setCrashDialogDelegate(() -> postCrashFiles(dumpFile, extraFile)); mCrashDialog.show(UIWidget.REQUEST_FOCUS); } } - private void sendCrashFiles(@NonNull final String aDumpFile, @NonNull final String aExtraFile) { - try { - GeckoResult result = CrashReporter.sendCrashReport(VRBrowserActivity.this, new File(aDumpFile), new File(aExtraFile), getString(R.string.crash_app_name)); - - result.accept(crashID -> { - Log.e(LOGTAG, "Submitted crash report id: " + crashID); - Log.e(LOGTAG, "Report available at: " + CRASH_STATS_URL + crashID); - }, ex -> { - Log.e(LOGTAG, "Failed to submit crash report: " + (ex != null ? ex.getMessage() : "Exception is NULL")); - }); - } catch (IOException | URISyntaxException e) { - Log.e(LOGTAG, "Failed to send crash report: " + e.toString()); - } - } - - private void postCrashFiles(@NonNull final String aDumpFile, @NonNull final String aExtraFile) { - ThreadUtils.postToBackgroundThread(() -> { - sendCrashFiles(aDumpFile, aExtraFile); - }); - } - - private void postCrashFiles(final ArrayList aFiles) { - ThreadUtils.postToBackgroundThread(() -> { - for (String file: aFiles) { - try { - ArrayList list = new ArrayList<>(2); - try (FileInputStream in = getBaseContext().openFileInput(file)) { - try(BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { - String line; - while((line = br.readLine()) != null) { - list.add(line); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - if (list.size() < 2) { - Log.e(LOGTAG, "Failed read crash dump file names from: " + file); - return; - } - sendCrashFiles(list.get(0), list.get(1)); - } finally { - Log.d(LOGTAG,"Removing crash file: " + file); - getBaseContext().deleteFile(file); - } - } - }); - } - @Override public void onTrimMemory(int level) { @@ -1109,7 +1034,7 @@ private void haltActivity(final int aReason) { mWindows.getFocusedWindow().showAlert( getString(R.string.not_entitled_title), getString(R.string.not_entitled_message, getString(R.string.app_name)), - () -> VRBrowserActivity.this.finish()); + index -> finish()); } }); } @@ -1135,18 +1060,10 @@ private void handlePoorPerformance() { } window.getSession().loadHomePage(); final String[] buttons = {getString(R.string.ok_button), getString(R.string.performance_unblock_page)}; - window.showButtonPrompt(getString(R.string.performance_title), getString(R.string.performance_message), buttons, new ConfirmPromptWidget.ConfirmPromptDelegate() { - @Override - public void confirm(int index) { - if (index == GeckoSession.PromptDelegate.ButtonPrompt.Type.NEGATIVE) { - mPoorPerformanceWhiteList.add(originalUri); - window.getSession().loadUri(originalUri); - } - } - - @Override - public void dismiss() { - + window.showConfirmPrompt(getString(R.string.performance_title), getString(R.string.performance_message), buttons, index -> { + if (index == PromptDialogWidget.NEGATIVE) { + mPoorPerformanceWhiteList.add(originalUri); + window.getSession().loadUri(originalUri); } }); }); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/PermissionDelegate.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/PermissionDelegate.java index 47d17a3ee4..f79df3cceb 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/PermissionDelegate.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/PermissionDelegate.java @@ -68,7 +68,6 @@ public void handlePermission(final String aUri, final PermissionWidget.Permissio mWidgetManager.addWidget(mPermissionWidget); } - mPermissionWidget.getPlacement().parentHandle = mParentWidgetHandle; mPermissionWidget.showPrompt(aUri, aType, aCallback); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java index b42c7a3556..d42062be59 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java @@ -132,7 +132,7 @@ public GeckoResult onAlertPrompt(@NonNull GeckoSession geckoSess mPrompt = new AlertPromptWidget(mContext); mPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle(); mPrompt.getPlacement().parentAnchorY = 0.0f; - mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance); + mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.js_prompt_y_distance); mPrompt.setTitle(alertPrompt.title); mPrompt.setMessage(alertPrompt.message); mPrompt.setPromptDelegate(() -> result.complete(alertPrompt.dismiss())); @@ -149,7 +149,7 @@ public GeckoResult onButtonPrompt(@NonNull GeckoSession geckoSes mPrompt = new ConfirmPromptWidget(mContext); mPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle(); mPrompt.getPlacement().parentAnchorY = 0.0f; - mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance); + mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.js_prompt_y_distance); mPrompt.setTitle(buttonPrompt.title); mPrompt.setMessage(buttonPrompt.message); ((ConfirmPromptWidget)mPrompt).setButtons(new String[] { @@ -180,7 +180,7 @@ public GeckoResult onTextPrompt(@NonNull GeckoSession geckoSessi mPrompt = new TextPromptWidget(mContext); mPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle(); mPrompt.getPlacement().parentAnchorY = 0.0f; - mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance); + mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.js_prompt_y_distance); mPrompt.setTitle(textPrompt.title); mPrompt.setMessage(textPrompt.message); ((TextPromptWidget)mPrompt).setDefaultText(textPrompt.defaultValue); @@ -208,7 +208,7 @@ public GeckoResult onAuthPrompt(@NonNull GeckoSession geckoSessi mPrompt = new AuthPromptWidget(mContext); mPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle(); mPrompt.getPlacement().parentAnchorY = 0.0f; - mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance); + mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.js_prompt_y_distance); mPrompt.setTitle(authPrompt.title); mPrompt.setMessage(authPrompt.message); ((AuthPromptWidget)mPrompt).setAuthOptions(authPrompt.authOptions); @@ -241,7 +241,7 @@ public GeckoResult onChoicePrompt(@NonNull GeckoSession geckoSes mPrompt = new ChoicePromptWidget(mContext); mPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle(); mPrompt.getPlacement().parentAnchorY = 0.0f; - mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance); + mPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.js_prompt_y_distance); mPrompt.setTitle(choicePrompt.title); mPrompt.setMessage(choicePrompt.message); ((ChoicePromptWidget)mPrompt).setChoices(choicePrompt.choices); @@ -352,10 +352,6 @@ private void showPopUp(int sessionId, @NonNull Pair site = mAllowedPopUpSites.stream().filter((item) -> item.url.equals(uri)).findFirst(); if (!site.isPresent()) { mPopUpPrompt = new PopUpBlockDialogWidget(mContext); - mPopUpPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle(); - mPopUpPrompt.getPlacement().parentAnchorY = 0.0f; - mPopUpPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance); - mPopUpPrompt.setTitle(uri); mPopUpPrompt.setButtonsDelegate(index -> { boolean allowed = index != PopUpBlockDialogWidget.NEGATIVE; boolean askAgain = mPopUpPrompt.askAgain(); @@ -384,7 +380,14 @@ private void showPopUp(int sessionId, @NonNull Pair mExecutors.mainThread().execute(() -> { + if (mPopupDelegate != null) { + mPopupDelegate.onPopUpAvailable(); + } + })); mPopUpPrompt.show(UIWidget.REQUEST_FOCUS); } else { @@ -407,7 +410,7 @@ public GeckoResult onSlowScript(@NonNull GeckoSession aSessi mSlowScriptPrompt = new ConfirmPromptWidget(mContext); mSlowScriptPrompt.getPlacement().parentHandle = mAttachedWindow.getHandle(); mSlowScriptPrompt.getPlacement().parentAnchorY = 0.0f; - mSlowScriptPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.base_app_dialog_y_distance); + mSlowScriptPrompt.getPlacement().translationY = WidgetPlacement.unitFromMeters(mContext, R.dimen.js_prompt_y_distance); mSlowScriptPrompt.setTitle(mContext.getResources().getString(R.string.slow_script_dialog_title)); mSlowScriptPrompt.setMessage(mContext.getResources().getString(R.string.slow_script_dialog_description, aScriptFileName)); mSlowScriptPrompt.setButtons(new String[]{ diff --git a/app/src/common/shared/org/mozilla/vrbrowser/crashreporting/CrashReporterService.java b/app/src/common/shared/org/mozilla/vrbrowser/crashreporting/CrashReporterService.java index 16a217e360..275ba82555 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/crashreporting/CrashReporterService.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/crashreporting/CrashReporterService.java @@ -6,6 +6,9 @@ import android.os.Build; import android.util.Log; +import androidx.annotation.NonNull; +import androidx.core.app.JobIntentService; + import org.mozilla.geckoview.GeckoRuntime; import org.mozilla.vrbrowser.BuildConfig; import org.mozilla.vrbrowser.R; @@ -13,15 +16,11 @@ import org.mozilla.vrbrowser.browser.SettingsStore; import org.mozilla.vrbrowser.utils.SystemUtils; - import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.UUID; -import androidx.annotation.NonNull; -import androidx.core.app.JobIntentService; - public class CrashReporterService extends JobIntentService { private static final String LOGTAG = SystemUtils.createLogtag(CrashReporterService.class); @@ -128,7 +127,7 @@ protected void onHandleWork(@NonNull Intent intent) { Log.d(LOGTAG, "Content process crash " + intent); Intent broadcastIntent = new Intent(CRASH_ACTION); broadcastIntent.putExtra(DATA_TAG, intent); - sendBroadcast(broadcastIntent, getString(R.string.app_permission_name)); + sendBroadcast(broadcastIntent, BuildConfig.APPLICATION_ID + "." + getString(R.string.app_permission_name)); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java index 743526735d..2e289f2ffc 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NavigationBarWidget.java @@ -331,8 +331,6 @@ private void initialize(@NonNull Context aContext) { mWidgetManager.addConnectivityListener(mConnectivityDelegate); mVoiceSearchWidget = createChild(VoiceSearchWidget.class, false); - mVoiceSearchWidget.getPlacement().parentAnchorY = 0.0f; - mVoiceSearchWidget.getPlacement().translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_y_distance); mVoiceSearchWidget.setDelegate(this); mSuggestionsProvider = new SuggestionsProvider(getContext()); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NoInternetWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NoInternetWidget.java deleted file mode 100644 index c5c1292c47..0000000000 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/NoInternetWidget.java +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.vrbrowser.ui.widgets; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.Button; - -import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.ui.widgets.dialogs.UIDialog; - -public class NoInternetWidget extends UIDialog { - - public NoInternetWidget(Context aContext) { - super(aContext); - initialize(aContext); - } - - public NoInternetWidget(Context aContext, AttributeSet aAttrs) { - super(aContext, aAttrs); - initialize(aContext); - } - - public NoInternetWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { - super(aContext, aAttrs, aDefStyle); - initialize(aContext); - } - - private void initialize(Context aContext) { - inflate(aContext, R.layout.no_internet, this); - - Button mAcceptButton = findViewById(R.id.acceptButton); - mAcceptButton.setOnClickListener(view -> { - view.requestFocusFromTouch(); - hide(REMOVE_WIDGET); - }); - } - - @Override - protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { - Context context = getContext(); - aPlacement.width = WidgetPlacement.dpDimension(context, R.dimen.no_internet_width); - aPlacement.height = WidgetPlacement.dpDimension(context, R.dimen.no_internet_height); - aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_z_distance); - aPlacement.anchorX = 0.5f; - aPlacement.anchorY = 0.5f; - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.5f; - aPlacement.opaque = false; - aPlacement.visible = false; - } - -} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java index 5e07b2ddbe..52f1c77dea 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java @@ -33,7 +33,6 @@ import org.mozilla.geckoview.PanZoomController; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.VRBrowserApplication; -import org.mozilla.vrbrowser.browser.HistoryStore; import org.mozilla.vrbrowser.browser.PromptDelegate; import org.mozilla.vrbrowser.browser.SessionChangeListener; import org.mozilla.vrbrowser.browser.SettingsStore; @@ -48,24 +47,17 @@ import org.mozilla.vrbrowser.ui.callbacks.LibraryItemContextMenuClickCallback; import org.mozilla.vrbrowser.ui.views.BookmarksView; import org.mozilla.vrbrowser.ui.views.HistoryView; -import org.mozilla.vrbrowser.ui.widgets.dialogs.BaseAppDialogWidget; -import org.mozilla.vrbrowser.ui.widgets.dialogs.ClearCacheDialogWidget; -import org.mozilla.vrbrowser.ui.widgets.dialogs.MessageDialogWidget; +import org.mozilla.vrbrowser.ui.widgets.dialogs.ClearHistoryDialogWidget; +import org.mozilla.vrbrowser.ui.widgets.dialogs.PromptDialogWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.SelectionActionWidget; import org.mozilla.vrbrowser.ui.widgets.menus.ContextMenuWidget; import org.mozilla.vrbrowser.ui.widgets.menus.LibraryMenuWidget; -import org.mozilla.vrbrowser.ui.widgets.prompts.AlertPromptWidget; -import org.mozilla.vrbrowser.ui.widgets.prompts.ConfirmPromptWidget; -import org.mozilla.vrbrowser.ui.widgets.prompts.PromptWidget; import org.mozilla.vrbrowser.ui.widgets.settings.SettingsWidget; import org.mozilla.vrbrowser.utils.ConnectivityReceiver; -import org.mozilla.vrbrowser.utils.SystemUtils; import org.mozilla.vrbrowser.utils.ViewUtils; import java.util.ArrayList; import java.util.Arrays; -import java.util.Calendar; -import java.util.GregorianCalendar; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; @@ -108,11 +100,11 @@ default void onBookmarksHidden(WindowWidget aWindow) {} private TopBarWidget mTopBar; private TitleBarWidget mTitleBar; private WidgetManagerDelegate mWidgetManager; - private AlertPromptWidget mAlertPrompt; - private ConfirmPromptWidget mConfirmPrompt; - private NoInternetWidget mNoInternetToast; - private MessageDialogWidget mAppDialog; - private ClearCacheDialogWidget mClearCacheDialog; + private PromptDialogWidget mAlertDialog; + private PromptDialogWidget mConfirmDialog; + private PromptDialogWidget mNoInternetDialog; + private PromptDialogWidget mAppDialog; + private ClearHistoryDialogWidget mClearHistoryDialog; private ContextMenuWidget mContextMenu; private SelectionActionWidget mSelectionMenu; private LibraryMenuWidget mLibraryItemContextMenu; @@ -341,17 +333,25 @@ public void close() { private ConnectivityReceiver.Delegate mConnectivityDelegate = connected -> { if (mActive) { - if (mNoInternetToast == null) { - mNoInternetToast = new NoInternetWidget(getContext()); - mNoInternetToast.mWidgetPlacement.parentHandle = getHandle(); - mNoInternetToast.mWidgetPlacement.parentAnchorY = 0.0f; - mNoInternetToast.mWidgetPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_y_distance); + if (mNoInternetDialog == null) { + mNoInternetDialog = new PromptDialogWidget(getContext()); + mNoInternetDialog.setButtons(new int[] { + R.string.ok_button + }); + mNoInternetDialog.setCheckboxVisible(false); + mNoInternetDialog.setDescriptionVisible(false); + mNoInternetDialog.setTitle(R.string.no_internet_title); + mNoInternetDialog.setBody(R.string.no_internet_message); + mNoInternetDialog.setButtonsDelegate(index -> { + mNoInternetDialog.hide(REMOVE_WIDGET); + }); } - if (!connected && !mNoInternetToast.isVisible()) { - mNoInternetToast.show(REQUEST_FOCUS); - } else if (connected && mNoInternetToast.isVisible()) { - mNoInternetToast.hide(REMOVE_WIDGET); + if (!connected && !mNoInternetDialog.isVisible()) { + mNoInternetDialog.show(REQUEST_FOCUS); + + } else if (connected && mNoInternetDialog.isVisible()) { + mNoInternetDialog.hide(REMOVE_WIDGET); } } }; @@ -1226,88 +1226,77 @@ public boolean onGenericMotionEvent(MotionEvent aEvent) { private void setPrivateBrowsingEnabled(boolean isEnabled) { } - public void showAlert(String title, @NonNull String msg, @NonNull PromptWidget.PromptDelegate callback) { - mAlertPrompt = new AlertPromptWidget(getContext()); - mAlertPrompt.mWidgetPlacement.parentHandle = getHandle(); - mAlertPrompt.mWidgetPlacement.parentAnchorY = 0.0f; - mAlertPrompt.mWidgetPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_y_distance); - mAlertPrompt.setTitle(title); - mAlertPrompt.setMessage(msg); - mAlertPrompt.setPromptDelegate(callback); - mAlertPrompt.show(REQUEST_FOCUS); - } - - public void showButtonPrompt(String title, @NonNull String msg, @NonNull String[] btnMsg, @NonNull ConfirmPromptWidget.ConfirmPromptDelegate callback) { - mConfirmPrompt = new ConfirmPromptWidget(getContext()); - mConfirmPrompt.mWidgetPlacement.parentHandle = getHandle(); - mConfirmPrompt.mWidgetPlacement.parentAnchorY = 0.0f; - mConfirmPrompt.mWidgetPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_y_distance); - mConfirmPrompt.setTitle(title); - mConfirmPrompt.setMessage(msg); - mConfirmPrompt.setButtons(btnMsg); - mConfirmPrompt.setPromptDelegate(callback); - mConfirmPrompt.show(REQUEST_FOCUS); - } - - public void showAppDialog(@NonNull String title, @NonNull @StringRes int description, @NonNull @StringRes int [] btnMsg, - @NonNull BaseAppDialogWidget.Delegate buttonsCallback, @NonNull MessageDialogWidget.Delegate messageCallback) { - mAppDialog = new MessageDialogWidget(getContext()); - mAppDialog.mWidgetPlacement.parentHandle = getHandle(); - mAppDialog.mWidgetPlacement.parentAnchorY = 0.0f; - mAppDialog.mWidgetPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_y_distance); + public void showAlert(String title, @NonNull String msg, @Nullable PromptDialogWidget.Delegate callback) { + if (mAlertDialog == null) { + mAlertDialog = new PromptDialogWidget(getContext()); + mAlertDialog.setButtons(new int[] { + R.string.ok_button + }); + mAlertDialog.setCheckboxVisible(false); + mAlertDialog.setDescriptionVisible(false); + } + mAlertDialog.setTitle(title); + mAlertDialog.setBody(msg); + mAlertDialog.setButtonsDelegate(index -> { + mAlertDialog.hide(REMOVE_WIDGET); + if (callback != null) { + callback.onButtonClicked(index); + } + }); + mAlertDialog.show(REQUEST_FOCUS); + } + + public void showConfirmPrompt(String title, @NonNull String msg, @NonNull String[] btnMsg, @Nullable PromptDialogWidget.Delegate callback) { + if (mConfirmDialog == null) { + mConfirmDialog = new PromptDialogWidget(getContext()); + mAlertDialog.setButtons(new int[] { + R.string.cancel_button, + R.string.ok_button + }); + mConfirmDialog.setCheckboxVisible(false); + mConfirmDialog.setDescriptionVisible(false); + } + mConfirmDialog.setTitle(title); + mConfirmDialog.setBody(msg); + mConfirmDialog.setButtons(btnMsg); + mAlertDialog.setButtonsDelegate(index -> { + mAlertDialog.hide(REMOVE_WIDGET); + if (callback != null) { + callback.onButtonClicked(index); + } + }); + mConfirmDialog.show(REQUEST_FOCUS); + } + + public void showDialog(@NonNull String title, @NonNull @StringRes int description, @NonNull @StringRes int [] btnMsg, + @Nullable PromptDialogWidget.Delegate buttonsCallback, @Nullable Runnable linkCallback) { + mAppDialog = new PromptDialogWidget(getContext()); + mAppDialog.setIconVisible(false); + mAppDialog.setCheckboxVisible(false); + mAppDialog.setDescriptionVisible(false); mAppDialog.setTitle(title); - mAppDialog.setMessage(description); + mAppDialog.setBody(description); mAppDialog.setButtons(btnMsg); - mAppDialog.setButtonsDelegate(buttonsCallback); - mAppDialog.setMessageDelegate(messageCallback); + mAppDialog.setButtonsDelegate(index -> { + mAppDialog.hide(REMOVE_WIDGET); + if (buttonsCallback != null) { + buttonsCallback.onButtonClicked(index); + } + }); + mAppDialog.setLinkDelegate(() -> { + mAppDialog.hide(REMOVE_WIDGET); + if (linkCallback != null) { + linkCallback.run(); + } + }); mAppDialog.show(REQUEST_FOCUS); } public void showClearCacheDialog() { - mClearCacheDialog = new ClearCacheDialogWidget(getContext()); - mClearCacheDialog.mWidgetPlacement.parentHandle = getHandle(); - mClearCacheDialog.mWidgetPlacement.parentAnchorY = 0.0f; - mClearCacheDialog.mWidgetPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_y_distance); - mClearCacheDialog.setTitle(R.string.history_clear); - mClearCacheDialog.setButtons(new int[] { - R.string.history_clear_cancel, - R.string.history_clear_now - }); - mClearCacheDialog.setButtonsDelegate((index) -> { - if (index == BaseAppDialogWidget.NEGATIVE) { - mClearCacheDialog.hide(REMOVE_WIDGET); - - } else { - Calendar date = new GregorianCalendar(); - date.set(Calendar.HOUR_OF_DAY, 0); - date.set(Calendar.MINUTE, 0); - date.set(Calendar.SECOND, 0); - date.set(Calendar.MILLISECOND, 0); - - long currentTime = System.currentTimeMillis(); - long todayLimit = date.getTimeInMillis(); - long yesterdayLimit = todayLimit - SystemUtils.ONE_DAY_MILLIS; - long oneWeekLimit = todayLimit - SystemUtils.ONE_WEEK_MILLIS; - - HistoryStore store = SessionStore.get().getHistoryStore(); - switch (mClearCacheDialog.getSelectedRange()) { - case ClearCacheDialogWidget.TODAY: - store.deleteVisitsBetween(todayLimit, currentTime); - break; - case ClearCacheDialogWidget.YESTERDAY: - store.deleteVisitsBetween(yesterdayLimit, currentTime); - break; - case ClearCacheDialogWidget.LAST_WEEK: - store.deleteVisitsBetween(oneWeekLimit, currentTime); - break; - case ClearCacheDialogWidget.EVERYTHING: - store.deleteEverything(); - break; - } - SessionStore.get().purgeSessionHistory(); - } - }); - mClearCacheDialog.show(REQUEST_FOCUS); + if (mClearHistoryDialog == null) { + mClearHistoryDialog = new ClearHistoryDialogWidget(getContext()); + } + mClearHistoryDialog.show(REQUEST_FOCUS); } public void setMaxWindowScale(float aScale) { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/BaseAppDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/BaseAppDialogWidget.java deleted file mode 100644 index 0864e6c568..0000000000 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/BaseAppDialogWidget.java +++ /dev/null @@ -1,146 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.vrbrowser.ui.widgets.dialogs; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewTreeObserver; - -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; -import androidx.databinding.DataBindingUtil; - -import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.browser.engine.SessionStore; -import org.mozilla.vrbrowser.databinding.BaseAppDialogBinding; -import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; -import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; - -public class BaseAppDialogWidget extends UIDialog { - - public interface Delegate { - void onButtonClicked(int index); - default void onDismiss() {} - } - - public static final int NEGATIVE = 0; - public static final int POSITIVE = 1; - - protected BaseAppDialogBinding mBinding; - private Delegate mAppDialogDelegate; - private String mHelpLink; - - public BaseAppDialogWidget(Context aContext) { - super(aContext); - initialize(aContext); - } - - protected void initialize(Context aContext) { - LayoutInflater inflater = LayoutInflater.from(aContext); - - // Inflate this data binding layout - mBinding = DataBindingUtil.inflate(inflater, R.layout.base_app_dialog, this, true); - - mBinding.leftButton.setOnClickListener(v -> { - if (mAppDialogDelegate != null) { - mAppDialogDelegate.onButtonClicked(NEGATIVE); - } - - BaseAppDialogWidget.this.onDismiss(); - }); - mBinding.rightButton.setOnClickListener(v -> { - if (mAppDialogDelegate != null) { - mAppDialogDelegate.onButtonClicked(POSITIVE); - } - - BaseAppDialogWidget.this.onDismiss(); - }); - mBinding.helpButton.setOnClickListener(v -> SessionStore.get().getActiveSession().loadUri(mHelpLink)); - } - - @Override - protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { - aPlacement.visible = false; - aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.base_app_dialog_width); - aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.base_app_dialog_height); - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.5f; - aPlacement.anchorX = 0.5f; - aPlacement.anchorY = 0.5f; - aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_z_distance); - } - - @Override - public void show(@ShowFlags int aShowFlags) { - measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - super.show(aShowFlags); - - ViewTreeObserver viewTreeObserver = getViewTreeObserver(); - if (viewTreeObserver.isAlive()) { - viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - getViewTreeObserver().removeOnGlobalLayoutListener(this); - mWidgetPlacement.height = (int)(getHeight()/mWidgetPlacement.density); - mWidgetManager.updateWidget(BaseAppDialogWidget.this); - } - }); - } - } - - public void setButtonsDelegate(Delegate delegate) { - mAppDialogDelegate = delegate; - } - - public void setTitle(@StringRes int title) { - mBinding.title.setText(title); - } - - public void setTitle(String title) { - mBinding.title.setText(title); - } - - public void setDescription(String title) { - mBinding.description.setVisibility(VISIBLE); - mBinding.description.setText(title); - } - - public void setDescription(@StringRes int title) { - mBinding.description.setVisibility(VISIBLE); - mBinding.description.setText(title); - } - - public void setHelpLink(@NonNull String text) { - mBinding.helpButton.setVisibility(VISIBLE); - mHelpLink = text; - } - - public void setHelpLink(@StringRes int textRes) { - mBinding.helpButton.setVisibility(VISIBLE); - mHelpLink = getResources().getString(textRes); - } - - public void setButtons(@NonNull @StringRes int[] buttons) { - if (buttons.length > 0) { - mBinding.leftButton.setText(buttons[NEGATIVE]); - } - if (buttons.length > 1) { - mBinding.rightButton.setText(buttons[POSITIVE]); - } - } - - public void setButtons(@NonNull String[] buttons) { - if (buttons.length > 0) { - mBinding.leftButton.setText(buttons[NEGATIVE]); - } - if (buttons.length > 1) { - mBinding.rightButton.setText(buttons[POSITIVE]); - } - } - -} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/ClearCacheDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/ClearCacheDialogWidget.java deleted file mode 100644 index f2828dec30..0000000000 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/ClearCacheDialogWidget.java +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.vrbrowser.ui.widgets.dialogs; - -import android.content.Context; -import android.view.LayoutInflater; - -import androidx.annotation.IntDef; -import androidx.databinding.DataBindingUtil; - -import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.databinding.ClearCacheDialogBinding; -import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; - -public class ClearCacheDialogWidget extends BaseAppDialogWidget { - - @IntDef(value = { TODAY, YESTERDAY, LAST_WEEK, EVERYTHING}) - public @interface ClearCacheRange {} - public static final int TODAY = 0; - public static final int YESTERDAY = 1; - public static final int LAST_WEEK = 2; - public static final int EVERYTHING = 3; - - private ClearCacheDialogBinding mClearCacheBinding; - - public ClearCacheDialogWidget(Context aContext) { - super(aContext); - } - - @Override - protected void initialize(Context aContext) { - super.initialize(aContext); - - LayoutInflater inflater = LayoutInflater.from(aContext); - - // Inflate this data binding layout - mClearCacheBinding = DataBindingUtil.inflate(inflater, R.layout.clear_cache_dialog, mBinding.dialogContent, true); - mClearCacheBinding.clearCacheRadio.setChecked(0, false); - } - - public @ClearCacheRange int getSelectedRange() { - return mClearCacheBinding.clearCacheRadio.getCheckedRadioButtonId(); - } - -} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/ClearHistoryDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/ClearHistoryDialogWidget.java new file mode 100644 index 0000000000..e767303863 --- /dev/null +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/ClearHistoryDialogWidget.java @@ -0,0 +1,78 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.vrbrowser.ui.widgets.dialogs; + +import android.content.Context; +import android.view.LayoutInflater; + +import androidx.databinding.DataBindingUtil; + +import org.mozilla.vrbrowser.R; +import org.mozilla.vrbrowser.browser.HistoryStore; +import org.mozilla.vrbrowser.browser.engine.SessionStore; +import org.mozilla.vrbrowser.databinding.ClearHistoryDialogBinding; +import org.mozilla.vrbrowser.utils.SystemUtils; + +import java.util.Calendar; +import java.util.GregorianCalendar; + +public class ClearHistoryDialogWidget extends SettingDialogWidget { + + public static final int TODAY = 0; + public static final int YESTERDAY = 1; + public static final int LAST_WEEK = 2; + public static final int EVERYTHING = 3; + + private ClearHistoryDialogBinding mClearHistoryBinding; + + public ClearHistoryDialogWidget(Context aContext) { + super(aContext); + } + + @Override + protected void initialize(Context aContext) { + super.initialize(aContext); + + LayoutInflater inflater = LayoutInflater.from(aContext); + + // Inflate this data binding layout + mClearHistoryBinding = DataBindingUtil.inflate(inflater, R.layout.clear_history_dialog, mBinding.content, true); + mClearHistoryBinding.clearHistoryRadio.setChecked(0, false); + + mBinding.headerLayout.setTitle(R.string.history_clear); + mBinding.footerLayout.setFooterButtonText(R.string.history_clear_now); + mBinding.footerLayout.setFooterButtonClickListener((view -> { + Calendar date = new GregorianCalendar(); + date.set(Calendar.HOUR_OF_DAY, 0); + date.set(Calendar.MINUTE, 0); + date.set(Calendar.SECOND, 0); + date.set(Calendar.MILLISECOND, 0); + + long currentTime = System.currentTimeMillis(); + long todayLimit = date.getTimeInMillis(); + long yesterdayLimit = todayLimit - SystemUtils.ONE_DAY_MILLIS; + long oneWeekLimit = todayLimit - SystemUtils.ONE_WEEK_MILLIS; + + HistoryStore store = SessionStore.get().getHistoryStore(); + switch (mClearHistoryBinding.clearHistoryRadio.getCheckedRadioButtonId()) { + case ClearHistoryDialogWidget.TODAY: + store.deleteVisitsBetween(todayLimit, currentTime); + break; + case ClearHistoryDialogWidget.YESTERDAY: + store.deleteVisitsBetween(yesterdayLimit, currentTime); + break; + case ClearHistoryDialogWidget.LAST_WEEK: + store.deleteVisitsBetween(oneWeekLimit, currentTime); + break; + case ClearHistoryDialogWidget.EVERYTHING: + store.deleteEverything(); + break; + } + SessionStore.get().purgeSessionHistory(); + })); + } + +} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CrashDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CrashDialogWidget.java index 419be32e20..acb0f0446c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CrashDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CrashDialogWidget.java @@ -6,117 +6,83 @@ package org.mozilla.vrbrowser.ui.widgets.dialogs; import android.content.Context; -import android.util.AttributeSet; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.TextView; + +import androidx.annotation.NonNull; import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.browser.SettingsStore; -import org.mozilla.vrbrowser.browser.engine.SessionStore; -import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; +import org.mozilla.vrbrowser.utils.SystemUtils; -public class CrashDialogWidget extends UIDialog { +import java.util.ArrayList; - public interface CrashDialogDelegate { - void onSendData(); - default void onDoNotSendData() {} - } +public class CrashDialogWidget extends PromptDialogWidget { - private Button mLearnMoreButton; - private Button mDoNotSendButton; - private Button mSendDataButton; - private CheckBox mSendDataCheckBox; - private AudioEngine mAudio; - private CrashDialogDelegate mCrashDialogDelegate; - private TextView mCrashMessage; + private String mDumpFile; + private String mExtraFile; + private ArrayList mFiles; - public CrashDialogWidget(Context aContext) { + public CrashDialogWidget(@NonNull Context aContext, @NonNull String dumpFile, @NonNull String extraFile) { super(aContext); - initialize(aContext); - } - public CrashDialogWidget(Context aContext, AttributeSet aAttrs) { - super(aContext, aAttrs); - initialize(aContext); - } + mDumpFile = dumpFile; + mExtraFile = extraFile; - public CrashDialogWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { - super(aContext, aAttrs, aDefStyle); initialize(aContext); } - private void initialize(Context aContext) { - inflate(aContext, R.layout.crash_dialog, this); - - mLearnMoreButton = findViewById(R.id.learnMoreButton); - mDoNotSendButton = findViewById(R.id.dontSendButton); - mSendDataButton = findViewById(R.id.sendDataButton); - mSendDataCheckBox = findViewById(R.id.crashSendDataCheckbox); - mCrashMessage = findViewById(R.id.crashMessage); - - mLearnMoreButton.setOnClickListener(view -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } + public CrashDialogWidget(@NonNull Context aContext, @NonNull ArrayList files) { + super(aContext); - SessionStore.get().getActiveSession().loadUri(getContext().getString(R.string.crash_dialog_learn_more_url)); + mFiles = files; - onDismiss(); - }); + initialize(aContext); + } - mDoNotSendButton.setOnClickListener(view -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } + @Override + protected void initialize(Context aContext) { + super.initialize(aContext); - if(mCrashDialogDelegate != null) { - mCrashDialogDelegate.onDoNotSendData(); - } - onDismiss(); + setButtons(new int[] { + R.string.do_not_sent_button, + R.string.send_data_button }); + setButtonsDelegate(index -> { + if (index == PromptDialogWidget.NEGATIVE) { + if (mFiles != null) { + SystemUtils.clearCrashFiles(getContext(), mFiles); + } + onDismiss(); - mSendDataButton.setOnClickListener(view -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } - - hide(REMOVE_WIDGET); + } else if (index == PromptDialogWidget.POSITIVE) { + if (mFiles != null) { + SystemUtils.postCrashFiles(getContext(), mFiles); - if(mCrashDialogDelegate != null) { - mCrashDialogDelegate.onSendData(); - } + } else { + SystemUtils.postCrashFiles(getContext(), mDumpFile, mExtraFile); + } - SettingsStore.getInstance(getContext()).setCrashReportingEnabled(mSendDataCheckBox.isChecked()); - }); + SettingsStore.getInstance(getContext()).setCrashReportingEnabled(mBinding.checkbox.isChecked()); - mSendDataCheckBox.setChecked(SettingsStore.getInstance(getContext()).isCrashReportingEnabled()); - mSendDataCheckBox.setOnCheckedChangeListener((compoundButton, b) -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); + onDismiss(); } }); - mCrashMessage.setText(getContext().getString(R.string.crash_dialog_message, getContext().getString(R.string.app_name))); + setDescriptionVisible(false); - mAudio = AudioEngine.fromContext(aContext); + setIcon(R.drawable.sad_fox); + setTitle(R.string.crash_dialog_heading); + setBody(getContext().getString(R.string.crash_dialog_message, getContext().getString(R.string.app_name))); + setCheckboxText(R.string.crash_dialog_send_data); + setLinkDelegate(() -> { + mWidgetManager.openNewTabForeground(getContext().getString(R.string.crash_dialog_learn_more_url)); + onDismiss(); + }); } @Override - protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { - aPlacement.visible = false; - aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.crash_dialog_width); - aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.crash_dialog_width); - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.5f; - aPlacement.anchorX = 0.5f; - aPlacement.anchorY = 0.5f; - aPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.crash_dialog_world_y); - aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.crash_dialog_world_z); - } + public void show(int aShowFlags) { + mBinding.checkbox.setChecked(false); - public void setCrashDialogDelegate(CrashDialogDelegate aDelegate) { - mCrashDialogDelegate = aDelegate; + super.show(aShowFlags); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/MaxWindowsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/MaxWindowsWidget.java deleted file mode 100644 index cf3aec70fc..0000000000 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/MaxWindowsWidget.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.mozilla.vrbrowser.ui.widgets.dialogs; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.Button; - -import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.ui.widgets.prompts.PromptWidget; - -public class MaxWindowsWidget extends PromptWidget { - - private Button mButton; - - public MaxWindowsWidget(Context aContext) { - super(aContext); - initialize(aContext); - } - - public MaxWindowsWidget(Context aContext, AttributeSet aAttrs) { - super(aContext, aAttrs); - initialize(aContext); - } - - public MaxWindowsWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { - super(aContext, aAttrs, aDefStyle); - initialize(aContext); - } - - protected void initialize(Context aContext) { - inflate(aContext, R.layout.prompt_max_windows, this); - - mLayout = findViewById(R.id.layout); - - mMessage = findViewById(R.id.alertMessage); - - mButton = findViewById(R.id.exitButton); - mButton.setOnClickListener(view -> onDismiss()); - } - -} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/MessageDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/MessageDialogWidget.java deleted file mode 100644 index 8ab5c56ac5..0000000000 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/MessageDialogWidget.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.vrbrowser.ui.widgets.dialogs; - -import android.content.Context; -import android.view.LayoutInflater; - -import androidx.annotation.NonNull; -import androidx.annotation.StringRes; -import androidx.databinding.DataBindingUtil; - -import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.databinding.MessageDialogBinding; -import org.mozilla.vrbrowser.utils.ViewUtils; - -public class MessageDialogWidget extends BaseAppDialogWidget { - - public interface Delegate { - void onMessageLinkClicked(@NonNull String url); - } - - private MessageDialogBinding mMessageBinding; - private Delegate mMessageDialogDelegate; - - public MessageDialogWidget(Context aContext) { - super(aContext); - } - - @Override - protected void initialize(Context aContext) { - super.initialize(aContext); - - LayoutInflater inflater = LayoutInflater.from(aContext); - - // Inflate this data binding layout - mMessageBinding = DataBindingUtil.inflate(inflater, R.layout.message_dialog, mBinding.dialogContent, true); - } - - public void setMessageDelegate(Delegate delegate) { - mMessageDialogDelegate = delegate; - } - - public void setMessage(@StringRes int message) { - ViewUtils.setTextViewHTML(mMessageBinding.message, getResources().getString(message), (widget, url) -> { - if (mMessageDialogDelegate != null) { - mMessageDialogDelegate.onMessageLinkClicked(url); - onDismiss(); - } - }); - } - - public void setMessage(String message) { - mMessageBinding.message.setText(message); - } - -} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PermissionWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PermissionWidget.java index d5295934bc..8d84b1d517 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PermissionWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PermissionWidget.java @@ -8,22 +8,15 @@ import android.content.Context; import android.text.Spannable; import android.text.SpannableStringBuilder; -import android.util.AttributeSet; import android.util.Log; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; import org.mozilla.geckoview.GeckoSession; import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import java.net.URI; -public class PermissionWidget extends UIDialog { +public class PermissionWidget extends PromptDialogWidget { - private TextView mPermissionMessage; - private ImageView mPermissionIcon; private GeckoSession.PermissionDelegate.Callback mPermissionCallback; public enum PermissionType { @@ -40,67 +33,60 @@ public PermissionWidget(Context aContext) { initialize(aContext); } - public PermissionWidget(Context aContext, AttributeSet aAttrs) { - super(aContext, aAttrs); - initialize(aContext); - } - - public PermissionWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { - super(aContext, aAttrs, aDefStyle); - initialize(aContext); - } - - private void initialize(Context aContext) { - inflate(aContext, R.layout.permission, this); - - mPermissionIcon = findViewById(R.id.permissionIcon); - mPermissionMessage = findViewById(R.id.permissionText); - - Button cancelButton = findViewById(R.id.permissionCancelButton); - cancelButton.setOnClickListener(v -> handlePermissionResult(false)); - - Button allowButton = findViewById(R.id.permissionAllowButton); - allowButton.setOnClickListener(v -> handlePermissionResult(true)); - } - @Override - protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { - Context context = getContext(); - aPlacement.width = WidgetPlacement.dpDimension(context, R.dimen.permission_width); - aPlacement.height = WidgetPlacement.dpDimension(context, R.dimen.permission_height); - aPlacement.worldWidth = WidgetPlacement.floatDimension(context, R.dimen.permission_world_width); - aPlacement.translationZ = WidgetPlacement.unitFromMeters(context, R.dimen.browser_children_z_distance); - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.5f; - aPlacement.anchorX = 0.5f; - aPlacement.anchorY = 0.5f; + protected void initialize(Context aContext) { + super.initialize(aContext); + + setButtons(new int[] { + R.string.permission_reject, + R.string.permission_allow + }); + setButtonsDelegate(index -> { + if (index == PromptDialogWidget.NEGATIVE) { + // Do not allow + handlePermissionResult(false); + + } else if (index == PromptDialogWidget.POSITIVE) { + // Allow + handlePermissionResult(true); + } + }); + setCheckboxVisible(false); + setDescriptionVisible(false); } public void showPrompt(String aUri, PermissionType aType, GeckoSession.PermissionDelegate.Callback aCallback) { + int titleId; int messageId; int iconId; switch (aType) { case Camera: + titleId = R.string.security_options_permission_camera; messageId = R.string.permission_camera; iconId = R.drawable.ic_icon_dialog_camera; break; case Microphone: + titleId = R.string.security_options_permission_microphone; messageId = R.string.permission_microphone; iconId = R.drawable.ic_icon_microphone; break; case CameraAndMicrophone: + titleId = R.string.security_options_permission_camera_and_microphone; messageId = R.string.permission_camera_and_microphone; iconId = R.drawable.ic_icon_dialog_camera; break; case Location: + titleId = R.string.security_options_permission_location; messageId = R.string.permission_location; iconId = R.drawable.ic_icon_dialog_geolocation; break; case Notification: + titleId = R.string.security_options_permission_notifications; messageId = R.string.permission_notification; iconId = R.drawable.ic_icon_dialog_notification; break; case ReadExternalStorage: + titleId = R.string.security_options_permission_storage; messageId = R.string.permission_read_external_storage; iconId = R.drawable.ic_icon_storage; break; @@ -119,8 +105,9 @@ public void showPrompt(String aUri, PermissionType aType, GeckoSession.Permissio SpannableStringBuilder str = new SpannableStringBuilder(message); str.setSpan(new android.text.style.StyleSpan(android.graphics.Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); - mPermissionMessage.setText(str); - mPermissionIcon.setImageResource(iconId); + setIcon(iconId); + setTitle(titleId); + setBody(str); show(REQUEST_FOCUS); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PopUpBlockDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PopUpBlockDialogWidget.java index a7574dc6ee..e444c2727c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PopUpBlockDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PopUpBlockDialogWidget.java @@ -6,16 +6,11 @@ package org.mozilla.vrbrowser.ui.widgets.dialogs; import android.content.Context; -import android.view.LayoutInflater; - -import androidx.databinding.DataBindingUtil; import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.databinding.PopupBlockDialogBinding; -public class PopUpBlockDialogWidget extends BaseAppDialogWidget { +public class PopUpBlockDialogWidget extends PromptDialogWidget { - private PopupBlockDialogBinding mPopUpBinding; private boolean mIsChecked; public PopUpBlockDialogWidget(Context aContext) { @@ -26,17 +21,20 @@ public PopUpBlockDialogWidget(Context aContext) { protected void initialize(Context aContext) { super.initialize(aContext); - LayoutInflater inflater = LayoutInflater.from(aContext); - - // Inflate this data binding layout - mPopUpBinding = DataBindingUtil.inflate(inflater, R.layout.popup_block_dialog, mBinding.dialogContent, true); - mPopUpBinding.contentCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> mIsChecked = isChecked); + setDescriptionVisible(false); setButtons(new int[] { R.string.popup_block_button_cancel, R.string.popup_block_button_show }); + setIcon(R.drawable.ff_logo); + setTitle(String.format(getContext().getString(R.string.popup_block_title), getContext().getString(R.string.app_name))); + setBody(R.string.popup_block_description); + setCheckboxText(R.string.popup_block_checkbox); + + mBinding.checkbox.setOnCheckedChangeListener((buttonView, isChecked) -> mIsChecked = isChecked); + } public boolean askAgain() { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CheckboxDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PromptDialogWidget.java similarity index 57% rename from app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CheckboxDialogWidget.java rename to app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PromptDialogWidget.java index ec49cc85f6..239e280439 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/CheckboxDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/PromptDialogWidget.java @@ -8,7 +8,7 @@ import android.content.Context; import android.graphics.drawable.Drawable; import android.view.LayoutInflater; -import android.view.ViewTreeObserver; +import android.view.View; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; @@ -16,11 +16,11 @@ import androidx.databinding.DataBindingUtil; import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.databinding.CheckboxDialogBinding; -import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; +import org.mozilla.vrbrowser.databinding.PromptDialogBinding; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; +import org.mozilla.vrbrowser.utils.ViewUtils; -public class CheckboxDialogWidget extends UIDialog { +public class PromptDialogWidget extends UIDialog { public interface Delegate { void onButtonClicked(int index); @@ -30,10 +30,11 @@ default void onDismiss() {} public static final int NEGATIVE = 0; public static final int POSITIVE = 1; - protected CheckboxDialogBinding mBinding; + protected PromptDialogBinding mBinding; private Delegate mAppDialogDelegate; + private Runnable mLinkDelegate; - public CheckboxDialogWidget(Context aContext) { + public PromptDialogWidget(Context aContext) { super(aContext); initialize(aContext); } @@ -42,7 +43,7 @@ protected void initialize(Context aContext) { LayoutInflater inflater = LayoutInflater.from(aContext); // Inflate this data binding layout - mBinding = DataBindingUtil.inflate(inflater, R.layout.checkbox_dialog, this, true); + mBinding = DataBindingUtil.inflate(inflater, R.layout.prompt_dialog, this, true); mBinding.leftButton.setOnClickListener(v -> { if (mAppDialogDelegate != null) { @@ -58,44 +59,37 @@ protected void initialize(Context aContext) { @Override protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { + // We align it at the same position as the settings panel aPlacement.visible = false; - aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.checkbox_dialog_width); - aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.checkbox_dialog_height); - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.5f; + aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.prompt_dialog_width); + aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.prompt_dialog_height); aPlacement.anchorX = 0.5f; aPlacement.anchorY = 0.5f; - aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_z_distance); + aPlacement.parentAnchorY = 0.0f; + aPlacement.parentAnchorX = 0.5f; + aPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_y) - + WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_y); + aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_z) - + WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_z); } @Override public void show(@ShowFlags int aShowFlags) { - measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); + mWidgetPlacement.parentHandle = mWidgetManager.getFocusedWindow().getHandle(); + super.show(aShowFlags); + } - mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS); - - ViewTreeObserver viewTreeObserver = getViewTreeObserver(); - if (viewTreeObserver.isAlive()) { - viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - getViewTreeObserver().removeOnGlobalLayoutListener(this); - mWidgetPlacement.height = (int)(getHeight()/mWidgetPlacement.density); - mWidgetManager.updateWidget(CheckboxDialogWidget.this); - } - }); - } + public void setButtonsDelegate(Delegate delegate) { + mAppDialogDelegate = delegate; } - public void hide(@HideFlags int aHideFlags) { - super.hide(aHideFlags); - mWidgetManager.popWorldBrightness(this); + public void setLinkDelegate(@NonNull Runnable delegate) { + mLinkDelegate = delegate; } - public void setButtonsDelegate(Delegate delegate) { - mAppDialogDelegate = delegate; + public void setIconVisible(boolean visible) { + mBinding.imageContainer.setVisibility(visible ? VISIBLE: GONE); } public void setIcon(Drawable icon) { @@ -114,12 +108,28 @@ public void setTitle(String title) { mBinding.title.setText(title); } - public void setBody(String body) { + public void setBody(@NonNull String body) { + ViewUtils.setTextViewHTML(mBinding.body, body, (widget, url) -> { + if (mLinkDelegate != null) { + mLinkDelegate.run(); + } + }); + } + + public void setBody(@StringRes int body) { + ViewUtils.setTextViewHTML(mBinding.body, getResources().getString(body), (widget, url) -> { + if (mLinkDelegate != null) { + mLinkDelegate.run(); + } + }); + } + + public void setBody(@NonNull CharSequence body) { mBinding.body.setText(body); } - public void setBody(@StringRes int title) { - mBinding.body.setText(title); + public void setCheckboxVisible(boolean visible) { + mBinding.checkboxContainer.setVisibility(visible ? View.VISIBLE : View.GONE); } public void setCheckboxText(@StringRes int text) { @@ -130,21 +140,47 @@ public void setCheckboxText(String text) { mBinding.checkbox.setText(text); } + public void setDescriptionVisible(boolean visible) { + mBinding.descriptionContainer.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + public void setDescription(@StringRes int description) { + mBinding.description.setText(description); + } + + public void setDescription(String description) { + mBinding.title.setText(description); + } + public void setButtons(@NonNull @StringRes int[] buttons) { if (buttons.length > 0) { mBinding.leftButton.setText(buttons[NEGATIVE]); + + } else { + mBinding.leftButton.setVisibility(View.GONE); } + if (buttons.length > 1) { mBinding.rightButton.setText(buttons[POSITIVE]); + + } else { + mBinding.rightButton.setVisibility(View.GONE); } } public void setButtons(@NonNull String[] buttons) { if (buttons.length > 0) { mBinding.leftButton.setText(buttons[NEGATIVE]); + + } else { + mBinding.leftButton.setVisibility(View.GONE); } + if (buttons.length > 1) { mBinding.rightButton.setText(buttons[POSITIVE]); + + } else { + mBinding.rightButton.setVisibility(View.GONE); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/RestartDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/RestartDialogWidget.java index bacb68e3af..66c7e0ea0c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/RestartDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/RestartDialogWidget.java @@ -6,72 +6,39 @@ package org.mozilla.vrbrowser.ui.widgets.dialogs; import android.content.Context; -import android.util.AttributeSet; -import android.widget.Button; -import android.widget.TextView; import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.audio.AudioEngine; -import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; -import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.SystemUtils; -public class RestartDialogWidget extends UIDialog { - - private AudioEngine mAudio; +public class RestartDialogWidget extends PromptDialogWidget { public RestartDialogWidget(Context aContext) { super(aContext); initialize(aContext); } - public RestartDialogWidget(Context aContext, AttributeSet aAttrs) { - super(aContext, aAttrs); - initialize(aContext); - } - - public RestartDialogWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { - super(aContext, aAttrs, aDefStyle); - initialize(aContext); - } - - private void initialize(Context aContext) { - inflate(aContext, R.layout.restart_dialog, this); - - Button acceptButton = findViewById(R.id.restartNowButton); - Button cancelButton = findViewById(R.id.restartLaterButton); - TextView restartText = findViewById(R.id.restartText); - - acceptButton.setOnClickListener(view -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } + @Override + protected void initialize(Context aContext) { + super.initialize(aContext); - postDelayed(() -> SystemUtils.scheduleRestart(getContext(), 100), 500); + setButtons(new int[] { + R.string.restart_later_dialog_button, + R.string.restart_now_dialog_button }); - cancelButton.setOnClickListener(view -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } + setButtonsDelegate(index -> { + if (index == PromptDialogWidget.NEGATIVE) { + onDismiss(); - onDismiss(); + } else if (index == PromptDialogWidget.POSITIVE) { + postDelayed(() -> SystemUtils.scheduleRestart(getContext(), 100), 500); + } }); - restartText.setText(getContext().getString(R.string.restart_dialog_text, getContext().getString(R.string.app_name))); - - mAudio = AudioEngine.fromContext(aContext); - } + setCheckboxVisible(false); + setDescriptionVisible(false); - @Override - protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { - aPlacement.visible = false; - aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.restart_dialog_width); - aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.restart_dialog_height); - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.5f; - aPlacement.anchorX = 0.5f; - aPlacement.anchorY = 0.5f; - aPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.restart_dialog_world_y); - aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.restart_dialog_world_z); + setIcon(R.drawable.ff_logo); + setTitle(R.string.restart_dialog_restart); + setBody(getContext().getString(R.string.restart_dialog_text, getContext().getString(R.string.app_name))); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SendTabDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SendTabDialogWidget.java index b8ad445174..4e2fecf094 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SendTabDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SendTabDialogWidget.java @@ -21,8 +21,6 @@ import org.mozilla.vrbrowser.browser.engine.SessionStore; import org.mozilla.vrbrowser.databinding.SendTabsDisplayBinding; import org.mozilla.vrbrowser.ui.widgets.UIWidget; -import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; -import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import java.util.ArrayList; import java.util.Collections; @@ -40,8 +38,7 @@ public class SendTabDialogWidget extends SettingDialogWidget implements DeviceConstellationObserver, - AccountObserver, - WidgetManagerDelegate.WorldClickListener { + AccountObserver { private SendTabsDisplayBinding mSendTabsDialogBinding; private Accounts mAccounts; @@ -72,19 +69,6 @@ protected void initialize(@NonNull Context aContext) { mBinding.headerLayout.setDescription(R.string.send_tab_dialog_description); mBinding.footerLayout.setFooterButtonText(R.string.send_tab_dialog_button); mBinding.footerLayout.setFooterButtonClickListener(this::sendTabButtonClick); - - mWidgetPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.cache_app_dialog_width); - } - - @Override - protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { - super.initializeWidgetPlacement(aPlacement); - - mWidgetPlacement.parentAnchorY = 0.0f; - mWidgetPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_y) - - WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_y); - mWidgetPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_z) - - WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_z); } @Override @@ -102,9 +86,6 @@ public void show(int aShowFlags) { mAccounts.refreshDevicesAsync(); mSendTabsDialogBinding.setIsSyncing(true); - mWidgetManager.addWorldClickListener(this); - mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS); - super.show(aShowFlags); } else { @@ -116,7 +97,6 @@ public void show(int aShowFlags) { public void hide(int aHideFlags) { super.hide(aHideFlags); - mWidgetManager.popWorldBrightness(this); mWidgetManager.removeWorldClickListener(this); } @@ -143,7 +123,6 @@ private void sendTabButtonClick(View v) { private void showWhatsNewDialog() { mWhatsNew = new WhatsNewWidget(getContext()); mWhatsNew.setLoginOrigin(Accounts.LoginOrigin.SEND_TABS); - mWhatsNew.getPlacement().parentHandle = mWidgetManager.getFocusedWindow().getHandle(); mWhatsNew.setStartBrowsingCallback(() -> { mWhatsNew.hide(REMOVE_WIDGET); mWhatsNew.releaseWidget(); @@ -221,11 +200,4 @@ public void onAuthenticationProblems() { } showWhatsNewDialog(); } - - // WidgetManagerDelegate.WorldClickListener - - @Override - public void onWorldClick() { - onDismiss(); - } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SettingDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SettingDialogWidget.java index 57de2bebe1..f4da4982db 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SettingDialogWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SettingDialogWidget.java @@ -34,13 +34,23 @@ protected void initialize(Context aContext) { @Override protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { aPlacement.visible = false; - aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.base_app_dialog_width); - aPlacement.height = WidgetPlacement.pixelDimension(getContext(), R.dimen.browser_width_pixels)/2; - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.5f; + aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_width); + aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_height); aPlacement.anchorX = 0.5f; aPlacement.anchorY = 0.5f; - aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_z_distance); + aPlacement.parentAnchorX = 0.5f; + aPlacement.parentAnchorY = 0.0f; + aPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_y) - + WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_y); + aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_z) - + WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_z); + } + + @Override + public void show(@ShowFlags int aShowFlags) { + mWidgetPlacement.parentHandle = mWidgetManager.getFocusedWindow().getHandle(); + + super.show(aShowFlags); } protected void onFooterButton() { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SignOutDialogWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SignOutDialogWidget.java new file mode 100644 index 0000000000..f84cce38e5 --- /dev/null +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/SignOutDialogWidget.java @@ -0,0 +1,87 @@ +/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.vrbrowser.ui.widgets.dialogs; + +import android.content.Context; +import android.graphics.drawable.BitmapDrawable; + +import org.mozilla.vrbrowser.R; +import org.mozilla.vrbrowser.VRBrowserApplication; +import org.mozilla.vrbrowser.browser.Accounts; +import org.mozilla.vrbrowser.browser.Places; +import org.mozilla.vrbrowser.ui.widgets.UIWidget; +import org.mozilla.vrbrowser.ui.widgets.settings.SettingsWidget; + +import java.util.Objects; +import java.util.concurrent.Executor; + +public class SignOutDialogWidget extends PromptDialogWidget { + + private Accounts mAccounts; + private Executor mUIThreadExecutor; + private Places mPlaces; + + public SignOutDialogWidget(Context aContext) { + super(aContext); + initialize(aContext); + } + + @Override + protected void initialize(Context aContext) { + super.initialize(aContext); + + mUIThreadExecutor = ((VRBrowserApplication)getContext().getApplicationContext()).getExecutors().mainThread(); + mAccounts = ((VRBrowserApplication)getContext().getApplicationContext()).getAccounts(); + mPlaces = ((VRBrowserApplication)getContext().getApplicationContext()).getPlaces(); + + setButtons(new int[] { + R.string.fxa_signout_confirmation_signout, + R.string.fxa_signout_confirmation_cancel + }); + setButtonsDelegate(index -> { + if (index == PromptDialogWidget.NEGATIVE) { + try { + Objects.requireNonNull(mAccounts.logoutAsync()).thenAcceptAsync(unit -> { + if (isChecked()) { + // Clear History and Bookmarks + mPlaces.clear(); + } + hide(UIWidget.REMOVE_WIDGET); + mWidgetManager.getTray().toggleSettingsDialog(); + + }, mUIThreadExecutor); + + } catch(NullPointerException e) { + e.printStackTrace(); + } + + } else if (index == PromptDialogWidget.POSITIVE) { + hide(UIWidget.REMOVE_WIDGET); + mWidgetManager.getTray().toggleSettingsDialog(SettingsWidget.SettingDialog.FXA); + } + }); + setDelegate(() -> mWidgetManager.getTray().toggleSettingsDialog(SettingsWidget.SettingDialog.FXA)); + + setDescriptionVisible(false); + + setTitle(R.string.fxa_signout_confirmation_title); + setBody(R.string.fxa_signout_confirmation_body); + setCheckboxText(R.string.fxa_signout_confirmation_checkbox); + } + + @Override + public void show(int aShowFlags) { + BitmapDrawable profilePicture = mAccounts.getProfilePicture(); + if (profilePicture != null) { + setIcon(profilePicture); + + } else { + setIcon(R.drawable.ic_icon_settings_account); + } + + super.show(aShowFlags); + } +} diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/UIDialog.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/UIDialog.java index 55be266251..d87b1445bb 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/UIDialog.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/UIDialog.java @@ -39,9 +39,11 @@ public boolean isDialog() { @Override public void show(int aShowFlags) { - super.show(aShowFlags); + if (!isVisible()) { + super.show(aShowFlags); - mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS); + mWidgetManager.pushWorldBrightness(this, WidgetManagerDelegate.DEFAULT_DIM_BRIGHTNESS); + } } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java index 180d4b7531..714556073e 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/VoiceSearchWidget.java @@ -12,14 +12,13 @@ import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; -import android.view.View; +import android.view.LayoutInflater; import android.view.animation.Animation; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; -import android.widget.ImageView; -import android.widget.TextView; import androidx.core.app.ActivityCompat; +import androidx.databinding.DataBindingUtil; import com.mozilla.speechlibrary.ISpeechRecognitionListener; import com.mozilla.speechlibrary.MozillaSpeechService; @@ -27,10 +26,9 @@ import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.vrbrowser.R; -import org.mozilla.vrbrowser.audio.AudioEngine; import org.mozilla.vrbrowser.browser.SettingsStore; import org.mozilla.vrbrowser.browser.engine.SessionStore; -import org.mozilla.vrbrowser.ui.views.UIButton; +import org.mozilla.vrbrowser.databinding.VoiceSearchDialogBinding; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.LocaleUtils; @@ -38,7 +36,14 @@ public class VoiceSearchWidget extends UIDialog implements WidgetManagerDelegate.PermissionListener, Application.ActivityLifecycleCallbacks { - private static final int VOICESEARCH_AUDIO_REQUEST_CODE = 7455; + public enum State { + LISTENING, + SEARCHING, + ERROR, + PERMISSIONS + } + + private static final int VOICE_SEARCH_AUDIO_REQUEST_CODE = 7455; private static final int ANIMATION_DURATION = 1000; private static int MAX_CLIPPING = 10000; @@ -51,20 +56,13 @@ public interface VoiceSearchDelegate { default void OnVoiceSearchError() {}; } + private VoiceSearchDialogBinding mBinding; private MozillaSpeechService mMozillaSpeechService; private VoiceSearchDelegate mDelegate; - private ImageView mVoiceSearchInput; - private ImageView mVoiceSearchSearching; - private Drawable mVoiceInputBackgroundDrawable; private ClipDrawable mVoiceInputClipDrawable; - private int mVoiceInputGravity; - private TextView mVoiceSearchText1; - private TextView mVoiceSearchText2; - private TextView mVoiceSearchText3; private RotateAnimation mSearchingAnimation; private boolean mIsSpeechRecognitionRunning = false; private boolean mWasSpeechRecognitionRunning = false; - private AudioEngine mAudio; public VoiceSearchWidget(Context aContext) { super(aContext); @@ -82,26 +80,21 @@ public VoiceSearchWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { } private void initialize(Context aContext) { - inflate(aContext, R.layout.voice_search_dialog, this); + LayoutInflater inflater = LayoutInflater.from(aContext); - mAudio = AudioEngine.fromContext(aContext); + // Inflate this data binding layout + mBinding = DataBindingUtil.inflate(inflater, R.layout.voice_search_dialog, this, true); mWidgetManager.addPermissionListener(this); mMozillaSpeechService = MozillaSpeechService.getInstance(); mMozillaSpeechService.setProductTag(getContext().getString(R.string.voice_app_id)); - mVoiceSearchText1 = findViewById(R.id.voiceSearchText1); - mVoiceSearchText2 = findViewById(R.id.voiceSearchText2); - mVoiceSearchText3 = findViewById(R.id.voiceSearchText3); - - mVoiceInputGravity = 0; - mVoiceInputBackgroundDrawable = getResources().getDrawable(R.drawable.ic_voice_search_volume_input_black, getContext().getTheme()); + Drawable mVoiceInputBackgroundDrawable = getResources().getDrawable(R.drawable.ic_voice_search_volume_input_black, getContext().getTheme()); mVoiceInputClipDrawable = new ClipDrawable(getContext().getDrawable(R.drawable.ic_voice_search_volume_input_clip), Gravity.START, ClipDrawable.HORIZONTAL); Drawable[] layers = new Drawable[] {mVoiceInputBackgroundDrawable, mVoiceInputClipDrawable }; - mVoiceSearchInput = findViewById(R.id.voiceSearchInput); - mVoiceSearchInput.setImageDrawable(new LayerDrawable(layers)); - mVoiceInputClipDrawable.setLevel(mVoiceInputGravity); + mBinding.voiceSearchAnimationListening.setImageDrawable(new LayerDrawable(layers)); + mVoiceInputClipDrawable.setLevel(0); mSearchingAnimation = new RotateAnimation(0, 360f, Animation.RELATIVE_TO_SELF, 0.5f, @@ -110,16 +103,8 @@ private void initialize(Context aContext) { mSearchingAnimation.setInterpolator(new LinearInterpolator()); mSearchingAnimation.setDuration(ANIMATION_DURATION); mSearchingAnimation.setRepeatCount(Animation.INFINITE); - mVoiceSearchSearching = findViewById(R.id.voiceSearchSearching); - UIButton backButton = findViewById(R.id.backButton); - backButton.setOnClickListener(view -> { - if (mAudio != null) { - mAudio.playSound(AudioEngine.Sound.CLICK); - } - - onDismiss(); - }); + mBinding.closeButton.setOnClickListener(view -> onDismiss()); mMozillaSpeechService.addListener(mVoiceSearchListener); ((Application)aContext.getApplicationContext()).registerActivityLifecycleCallbacks(this); @@ -141,13 +126,16 @@ public void releaseWidget() { @Override protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { aPlacement.visible = false; - aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.voice_search_width); - aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.voice_search_height); - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.5f; + aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.prompt_dialog_width); + aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.prompt_dialog_height); aPlacement.anchorX = 0.5f; aPlacement.anchorY = 0.5f; - aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.voice_search_world_z); + aPlacement.parentAnchorX = 0.5f; + aPlacement.parentAnchorY = 0.0f; + aPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_y) - + WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_y); + aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_z) - + WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_z); } public void setPlacementForKeyboard(int aHandle) { @@ -224,7 +212,7 @@ public void startVoiceSearch() { if (ActivityCompat.checkSelfPermission(getContext().getApplicationContext(), Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions((Activity)getContext(), new String[]{Manifest.permission.RECORD_AUDIO}, - VOICESEARCH_AUDIO_REQUEST_CODE); + VOICE_SEARCH_AUDIO_REQUEST_CODE); } else { String locale = LocaleUtils.getVoiceSearchLocale(getContext()); mMozillaSpeechService.setLanguage(LocaleUtils.mapToMozillaSpeechLocales(locale)); @@ -253,7 +241,7 @@ public void stopVoiceSearch() { @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { boolean granted = false; - if (requestCode == VOICESEARCH_AUDIO_REQUEST_CODE) { + if (requestCode == VOICE_SEARCH_AUDIO_REQUEST_CODE) { for (int result: grantResults) { if (result == PackageManager.PERMISSION_GRANTED) { granted = true; @@ -275,6 +263,7 @@ public void onRequestPermissionsResult(int requestCode, String[] permissions, in public void show(@ShowFlags int aShowFlags) { if (SettingsStore.getInstance(getContext()).isSpeechDataCollectionEnabled() || SettingsStore.getInstance(getContext()).isSpeechDataCollectionReviewed()) { + mWidgetPlacement.parentHandle = mWidgetManager.getFocusedWindow().getHandle(); super.show(aShowFlags); setStartListeningState(); @@ -282,7 +271,7 @@ public void show(@ShowFlags int aShowFlags) { startVoiceSearch(); } else { - mWidgetManager.getFocusedWindow().showAppDialog( + mWidgetManager.getFocusedWindow().showDialog( getResources().getString(R.string.voice_samples_collect_data_dialog_title, getResources().getString(R.string.app_name)), R.string.voice_samples_collect_dialog_description2, new int[]{ @@ -290,14 +279,13 @@ public void show(@ShowFlags int aShowFlags) { R.string.voice_samples_collect_dialog_allow}, index -> { SettingsStore.getInstance(getContext()).setSpeechDataCollectionReviewed(true); - if (index == MessageDialogWidget.POSITIVE) { + if (index == PromptDialogWidget.POSITIVE) { SettingsStore.getInstance(getContext()).setSpeechDataCollectionEnabled(true); } ThreadUtils.postToUiThread(() -> show(aShowFlags)); }, - url -> { - mWidgetManager.getFocusedWindow().getSession().loadUri(getResources().getString(R.string.private_policy_url)); - onDismiss(); + () -> { + mWidgetManager.openNewTabForeground(getResources().getString(R.string.private_policy_url)); }); } } @@ -307,53 +295,37 @@ public void hide(@HideFlags int aHideFlags) { super.hide(aHideFlags); stopVoiceSearch(); + mBinding.setState(State.LISTENING); } private void setStartListeningState() { - mVoiceSearchText1.setText(R.string.voice_search_start); - mVoiceSearchText1.setVisibility(View.VISIBLE); - mVoiceSearchText2.setVisibility(View.GONE); - mVoiceSearchText3.setVisibility(View.VISIBLE); - mVoiceSearchInput.setVisibility(View.VISIBLE); - mVoiceSearchSearching.clearAnimation(); - mVoiceSearchSearching.setVisibility(View.INVISIBLE); + mBinding.setState(State.LISTENING); + mBinding.voiceSearchAnimationSearching.clearAnimation(); + mBinding.executePendingBindings(); } private void setDecodingState() { - mVoiceSearchText1.setText(R.string.voice_search_decoding); - mVoiceSearchText1.setVisibility(View.VISIBLE); - mVoiceSearchText2.setVisibility(View.GONE); - mVoiceSearchText3.setVisibility(View.INVISIBLE); - mVoiceSearchInput.setVisibility(View.INVISIBLE); - mVoiceSearchSearching.startAnimation(mSearchingAnimation); - mVoiceSearchSearching.setVisibility(View.VISIBLE); + mBinding.setState(State.SEARCHING); + mBinding.voiceSearchAnimationSearching.startAnimation(mSearchingAnimation); + mBinding.executePendingBindings(); } private void setResultState() { stopVoiceSearch(); postDelayed(() -> { - mVoiceSearchText1.setText(R.string.voice_search_error); - mVoiceSearchText1.setVisibility(View.VISIBLE); - mVoiceSearchText2.setText(R.string.voice_search_try_again); - mVoiceSearchText2.setVisibility(View.VISIBLE); - mVoiceSearchText3.setVisibility(View.VISIBLE); - mVoiceSearchInput.setVisibility(View.VISIBLE); - mVoiceSearchSearching.clearAnimation(); - mVoiceSearchSearching.setVisibility(View.INVISIBLE); + mBinding.setState(State.ERROR); + mBinding.voiceSearchAnimationSearching.clearAnimation(); + mBinding.executePendingBindings(); startVoiceSearch(); }, 100); } private void setPermissionNotGranted() { - mVoiceSearchText1.setText(R.string.voice_search_permission_after_decline); - mVoiceSearchText1.setVisibility(View.VISIBLE); - mVoiceSearchText2.setVisibility(View.GONE); - mVoiceSearchText3.setVisibility(View.INVISIBLE); - mVoiceSearchInput.setVisibility(View.INVISIBLE); - mVoiceSearchSearching.clearAnimation(); - mVoiceSearchSearching.setVisibility(View.INVISIBLE); + mBinding.setState(State.PERMISSIONS); + mBinding.voiceSearchAnimationSearching.clearAnimation(); + mBinding.executePendingBindings(); } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java index ecd0d05f15..03aa702830 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/dialogs/WhatsNewWidget.java @@ -5,29 +5,22 @@ package org.mozilla.vrbrowser.ui.widgets.dialogs; -import android.annotation.SuppressLint; import android.content.Context; import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; import androidx.annotation.NonNull; -import androidx.databinding.DataBindingUtil; import org.mozilla.geckoview.GeckoSessionSettings; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.VRBrowserApplication; import org.mozilla.vrbrowser.browser.Accounts; import org.mozilla.vrbrowser.browser.SettingsStore; -import org.mozilla.vrbrowser.databinding.WhatsNewBinding; import org.mozilla.vrbrowser.telemetry.GleanMetricsService; -import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; -import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; -public class WhatsNewWidget extends UIDialog { +public class WhatsNewWidget extends PromptDialogWidget { private Accounts mAccounts; private Runnable mSignInCallback; @@ -37,7 +30,8 @@ public class WhatsNewWidget extends UIDialog { public WhatsNewWidget(Context aContext) { super(aContext); - initialize(); + + initialize(aContext); } public void setSignInCallback(@NonNull Runnable callback) { @@ -48,40 +42,38 @@ public void setStartBrowsingCallback(@NonNull Runnable callback) { mStartBrowsingCallback = callback; } - @SuppressLint("ClickableViewAccessibility") - private void initialize() { - LayoutInflater inflater = LayoutInflater.from(getContext()); + @Override + protected void initialize(Context aContext) { + super.initialize(aContext); mUIThreadExecutor = ((VRBrowserApplication)getContext().getApplicationContext()).getExecutors().mainThread(); - mAccounts = ((VRBrowserApplication)getContext().getApplicationContext()).getAccounts(); - // Inflate this data binding layout - WhatsNewBinding mBinding = DataBindingUtil.inflate(inflater, R.layout.whats_new, this, true); + setButtons(new int[] { + R.string.whats_new_button_start_browsing, + R.string.whats_new_button_sign_in + }); + setButtonsDelegate(index -> { + if (index == PromptDialogWidget.NEGATIVE) { + startBrowsing(); + + } else if (index == PromptDialogWidget.POSITIVE) { + signIn(); + } + }); - mBinding.signInButton.setOnClickListener(this::signIn); - mBinding.startBrowsingButton.setOnClickListener(this::startBrowsing); + setCheckboxVisible(false); + + setIcon(R.drawable.ic_asset_image_accounts); + setTitle(R.string.whats_new_title_1); + setBody(R.string.whats_new_body_1); + setDescription(R.string.whats_new_body_sub_1); } public void setLoginOrigin(Accounts.LoginOrigin origin) { mLoginOrigin = origin; } - @Override - protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { - aPlacement.visible = false; - aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.whats_new_width); - aPlacement.height = WidgetPlacement.dpDimension(getContext(), R.dimen.whats_new_height); - aPlacement.parentAnchorX = 0.5f; - aPlacement.parentAnchorY = 0.0f; - aPlacement.anchorX = 0.5f; - aPlacement.anchorY = 0.5f; - aPlacement.translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_y) - - WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_y); - aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.settings_world_z) - - WidgetPlacement.unitFromMeters(getContext(), R.dimen.window_world_z); - } - @Override public void hide(@HideFlags int aHideFlags) { super.hide(aHideFlags); @@ -89,7 +81,7 @@ public void hide(@HideFlags int aHideFlags) { SettingsStore.getInstance(getContext()).setWhatsNewDisplayed(true); } - private void signIn(View view) { + private void signIn() { if (mAccounts.getAccountStatus() == Accounts.AccountStatus.SIGNED_IN) { mAccounts.logoutAsync(); @@ -123,7 +115,7 @@ private void signIn(View view) { } } - private void startBrowsing(View view) { + private void startBrowsing() { if (mStartBrowsingCallback != null) { mStartBrowsingCallback.run(); } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/PromptWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/PromptWidget.java index ab1d806eeb..a2b0162fe0 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/PromptWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/prompts/PromptWidget.java @@ -7,12 +7,15 @@ import android.view.ViewTreeObserver; import android.widget.TextView; -import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.ui.widgets.dialogs.UIDialog; +/** + * Base widget used for the browser triggered prompts: alert, confirm, prompt, auth and select + */ public class PromptWidget extends UIDialog { public interface PromptDelegate { @@ -37,7 +40,7 @@ public PromptWidget(Context aContext, AttributeSet aAttrs, int aDefStyle) { super(aContext, aAttrs, aDefStyle); } - public void setPromptDelegate(@NonNull PromptDelegate delegate) { + public void setPromptDelegate(@Nullable PromptDelegate delegate) { mPromptDelegate = delegate; } @@ -62,7 +65,7 @@ public void setMessage(String message) { @Override protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { aPlacement.visible = false; - aPlacement.width = WidgetPlacement.pixelDimension(getContext(), R.dimen.browser_width_pixels)/2; + aPlacement.width = WidgetPlacement.dpDimension(getContext(), R.dimen.prompt_width); mMaxHeight = WidgetPlacement.dpDimension(getContext(), R.dimen.prompt_height); aPlacement.height = mMaxHeight; aPlacement.parentAnchorX = 0.5f; @@ -72,7 +75,6 @@ protected void initializeWidgetPlacement(WidgetPlacement aPlacement) { aPlacement.translationZ = WidgetPlacement.unitFromMeters(getContext(), R.dimen.browser_children_z_distance); } - @Override public void show(@ShowFlags int aShowFlags) { mLayout.measure(View.MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java index bf92088225..6053f2a1f7 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java @@ -24,7 +24,6 @@ import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.utils.LocaleUtils; -import java.util.Arrays; import java.util.Collections; public class ContentLanguageOptionsView extends SettingsView { @@ -77,8 +76,8 @@ private void initialize(Context aContext) { @Override public Point getDimensions() { - return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_width), - WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_height)); + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_height)); } private LanguageItemCallback mLanguageItemCallback = new LanguageItemCallback() { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayLanguageOptionsView.java index 60ba2cb00e..5eaae59c5a 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/DisplayLanguageOptionsView.java @@ -99,7 +99,7 @@ private void setLanguage(int checkedId, boolean doApply) { @Override public Point getDimensions() { - return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_width), - WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_height)); + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_height)); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/FxAAccountOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/FxAAccountOptionsView.java index 69fb5084d4..d213769873 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/FxAAccountOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/FxAAccountOptionsView.java @@ -6,7 +6,6 @@ package org.mozilla.vrbrowser.ui.widgets.settings; import android.content.Context; -import android.graphics.drawable.BitmapDrawable; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -24,8 +23,7 @@ import org.mozilla.vrbrowser.ui.views.settings.SwitchSetting; import org.mozilla.vrbrowser.ui.widgets.UIWidget; import org.mozilla.vrbrowser.ui.widgets.WidgetManagerDelegate; -import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; -import org.mozilla.vrbrowser.ui.widgets.dialogs.CheckboxDialogWidget; +import org.mozilla.vrbrowser.ui.widgets.dialogs.SignOutDialogWidget; import org.mozilla.vrbrowser.utils.SystemUtils; import java.util.Objects; @@ -49,7 +47,7 @@ class FxAAccountOptionsView extends SettingsView { private Executor mUIThreadExecutor; private boolean mInitialBookmarksState; private boolean mInitialHistoryState; - private CheckboxDialogWidget mSignOutDialog; + private SignOutDialogWidget mSignOutDialog; public FxAAccountOptionsView(Context aContext, WidgetManagerDelegate aWidgetManager) { super(aContext, aWidgetManager); @@ -214,43 +212,7 @@ private void sync(View view) { private void signOut(View view) { if (mSignOutDialog == null) { - mSignOutDialog = new CheckboxDialogWidget(getContext()); - mSignOutDialog.getPlacement().parentHandle = mWidgetManager.getFocusedWindow().getHandle(); - mSignOutDialog.getPlacement().parentAnchorY = 0.0f; - mSignOutDialog.getPlacement().translationY = WidgetPlacement.unitFromMeters(getContext(), R.dimen.base_app_dialog_y_distance); - BitmapDrawable profilePicture = mAccounts.getProfilePicture(); - if (profilePicture != null) { - mSignOutDialog.setIcon(profilePicture); - - } else { - mSignOutDialog.setIcon(R.drawable.ic_icon_settings_account); - } - mSignOutDialog.setTitle(R.string.fxa_signout_confirmation_title); - mSignOutDialog.setBody(R.string.fxa_signout_confirmation_body); - mSignOutDialog.setCheckboxText(R.string.fxa_signout_confirmation_checkbox); - mSignOutDialog.setButtons(new int[] { - R.string.fxa_signout_confirmation_signout, - R.string.fxa_signout_confirmation_cancel - }); - mSignOutDialog.setButtonsDelegate(index -> { - // Sign out button pressed - if (index == CheckboxDialogWidget.NEGATIVE) { - mAccounts.logoutAsync().thenAcceptAsync(unit -> { - if (mSignOutDialog.isChecked()) { - // Clear History and Bookmarks - mPlaces.clear(); - } - mSignOutDialog.hide(UIWidget.REMOVE_WIDGET); - mWidgetManager.getTray().toggleSettingsDialog(); - - }, mUIThreadExecutor); - - } else if (index == CheckboxDialogWidget.POSITIVE) { - mSignOutDialog.hide(UIWidget.REMOVE_WIDGET); - mWidgetManager.getTray().toggleSettingsDialog(SettingsWidget.SettingDialog.FXA); - } - }); - mSignOutDialog.setDelegate(() -> mWidgetManager.getTray().toggleSettingsDialog(SettingsWidget.SettingDialog.FXA)); + mSignOutDialog = new SignOutDialogWidget(getContext()); } exitWholeSettings(); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/LanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/LanguageOptionsView.java index 4455e01faf..2925bceda0 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/LanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/LanguageOptionsView.java @@ -149,8 +149,8 @@ private SpannableStringBuilder getSpannedLanguageText(@NonNull String language) @Override public Point getDimensions() { - return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_width), - WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_height)); + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_height)); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/AllowedPopUpsOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PopUpExceptionsOptionsView.java similarity index 90% rename from app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/AllowedPopUpsOptionsView.java rename to app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PopUpExceptionsOptionsView.java index 4b6a91a425..f40d83c2b5 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/AllowedPopUpsOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PopUpExceptionsOptionsView.java @@ -25,13 +25,13 @@ import java.util.List; -class AllowedPopUpsOptionsView extends SettingsView { +class PopUpExceptionsOptionsView extends SettingsView { private OptionsPrivacyPopupsBinding mBinding; private PopUpAdapter mAdapter; private PopUpsViewModel mViewModel; - public AllowedPopUpsOptionsView(Context aContext, WidgetManagerDelegate aWidgetManager) { + public PopUpExceptionsOptionsView(Context aContext, WidgetManagerDelegate aWidgetManager) { super(aContext, aWidgetManager); initialize(aContext); } @@ -68,8 +68,8 @@ private void initialize(Context aContext) { @Override public Point getDimensions() { - return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_width), - WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_height)); + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_height)); } @Override @@ -99,6 +99,10 @@ public void onHidden() { public void onChanged(List popUpSites) { if (popUpSites != null) { mAdapter.setSites(popUpSites); + mBinding.setIsEmpty(popUpSites.isEmpty()); + + } else { + mBinding.setIsEmpty(true); } } }; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java index 5bff7bd235..da1c6e271f 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java @@ -78,7 +78,7 @@ private void initialize(Context aContext) { TextView permissionsTitleText = findViewById(R.id.permissionsTitle); permissionsTitleText.setText(getContext().getString(R.string.security_options_permissions_title, getContext().getString(R.string.app_name))); - mPopUpsBlockingExceptions = new AllowedPopUpsOptionsView(getContext(), mWidgetManager); + mPopUpsBlockingExceptions = new PopUpExceptionsOptionsView(getContext(), mWidgetManager); mPermissionButtons = new ArrayList<>(); mPermissionButtons.add(Pair.create(findViewById(R.id.cameraPermissionSwitch), Manifest.permission.CAMERA)); diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java index a24433dcce..93f4afbf87 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/SettingsWidget.java @@ -41,7 +41,6 @@ import org.mozilla.vrbrowser.ui.widgets.WidgetPlacement; import org.mozilla.vrbrowser.ui.widgets.dialogs.RestartDialogWidget; import org.mozilla.vrbrowser.ui.widgets.dialogs.UIDialog; -import org.mozilla.vrbrowser.ui.widgets.prompts.AlertPromptWidget; import org.mozilla.vrbrowser.utils.StringUtils; import java.io.UnsupportedEncodingException; @@ -65,8 +64,7 @@ public enum SettingDialog { private SettingsView mCurrentView; private int mViewMarginH; private int mViewMarginV; - private int mRestartDialogHandle = -1; - private int mAlertDialogHandle = -1; + private RestartDialogWidget mRestartDialog; private Accounts mAccounts; private Executor mUIThreadExecutor; @@ -180,7 +178,7 @@ private void initialize() { }); mBinding.surveyLink.setOnClickListener(v -> { - mWidgetManager.getFocusedWindow().getSession().loadUri(getResources().getString(R.string.survey_link)); + mWidgetManager.openNewTabForeground(getResources().getString(R.string.survey_link)); exitWholeSettings(); }); @@ -188,7 +186,7 @@ private void initialize() { if (mAudio != null) { mAudio.playSound(AudioEngine.Sound.CLICK); } - SessionStore.get().getActiveSession().loadUri(getContext().getString(R.string.help_url)); + mWidgetManager.openNewTabForeground(getContext().getString(R.string.help_url)); onDismiss(); }); @@ -267,7 +265,7 @@ private void onSettingsReportClick() { Log.e(LOGTAG, "Cannot encode URL"); } - session.loadUri(getContext().getString(R.string.private_report_url, url)); + mWidgetManager.openNewTabForeground(getContext().getString(R.string.private_report_url, url)); onDismiss(); } @@ -496,32 +494,19 @@ public void exitWholeSettings() { public void showRestartDialog() { hide(UIWidget.REMOVE_WIDGET); - UIWidget widget = getChild(mRestartDialogHandle); - if (widget == null) { - widget = createChild(RestartDialogWidget.class, false); - mRestartDialogHandle = widget.getHandle(); - widget.setDelegate(() -> show(REQUEST_FOCUS)); + if (mRestartDialog == null) { + mRestartDialog = new RestartDialogWidget(getContext()); + mRestartDialog.setDelegate(() -> SettingsWidget.this.show(REQUEST_FOCUS)); } - widget.show(REQUEST_FOCUS); + mRestartDialog.show(REQUEST_FOCUS); } @Override public void showAlert(String aTitle, String aMessage) { hide(UIWidget.KEEP_WIDGET); - AlertPromptWidget widget = getChild(mAlertDialogHandle); - if (widget == null) { - widget = createChild(AlertPromptWidget.class, false); - mAlertDialogHandle = widget.getHandle(); - widget.setDelegate(() -> show(REQUEST_FOCUS)); - } - widget.getPlacement().translationZ = 0; - widget.getPlacement().parentHandle = mHandle; - widget.setTitle(aTitle); - widget.setMessage(aMessage); - - widget.show(REQUEST_FOCUS); + mWidgetManager.getFocusedWindow().showAlert(aTitle, aMessage, index -> show(REQUEST_FOCUS)); } private boolean isLanguagesSubView(View view) { @@ -535,7 +520,7 @@ private boolean isLanguagesSubView(View view) { } private boolean isPrivacySubView(View view) { - if (view instanceof AllowedPopUpsOptionsView) { + if (view instanceof PopUpExceptionsOptionsView) { return true; } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java index 95e8282c5e..711fa7fb9d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/VoiceSearchLanguageOptionsView.java @@ -83,7 +83,7 @@ private void setLanguage(int checkedId, boolean doApply) { @Override public Point getDimensions() { - return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_width), - WidgetPlacement.dpDimension(getContext(), R.dimen.language_options_height)); + return new Point( WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_width), + WidgetPlacement.dpDimension(getContext(), R.dimen.settings_dialog_height)); } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/utils/SystemUtils.java b/app/src/common/shared/org/mozilla/vrbrowser/utils/SystemUtils.java index e5503348c4..9866f7150e 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/utils/SystemUtils.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/utils/SystemUtils.java @@ -4,14 +4,31 @@ import android.app.PendingIntent; import android.content.Context; import android.content.Intent; +import android.util.Log; import androidx.annotation.NonNull; +import org.mozilla.geckoview.CrashReporter; +import org.mozilla.geckoview.GeckoResult; import org.mozilla.vrbrowser.BuildConfig; +import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.VRBrowserActivity; +import org.mozilla.vrbrowser.VRBrowserApplication; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.concurrent.Executor; public class SystemUtils { + private static final String LOGTAG = SystemUtils.createLogtag(SystemUtils.class); + public static final long ONE_DAY_MILLIS = 86400000; public static final long TWO_DAYS_MILLIS = 172800000; public static final long ONE_WEEK_MILLIS = 604800000; @@ -40,4 +57,62 @@ public static final void scheduleRestart(@NonNull Context context, long delay) { public static String createLogtag(@NonNull Class aClass) { return "VRB[" + aClass.getSimpleName() + "]"; } + + private static final String CRASH_STATS_URL = "https://crash-stats.mozilla.com/report/index/"; + + private static void sendCrashFiles(@NonNull Context context, @NonNull final String aDumpFile, @NonNull final String aExtraFile) { + try { + GeckoResult result = CrashReporter.sendCrashReport(context, new File(aDumpFile), new File(aExtraFile), context.getString(R.string.crash_app_name)); + + result.accept(crashID -> { + Log.e(LOGTAG, "Submitted crash report id: " + crashID); + Log.e(LOGTAG, "Report available at: " + CRASH_STATS_URL + crashID); + }, ex -> { + Log.e(LOGTAG, "Failed to submit crash report: " + (ex != null ? ex.getMessage() : "Exception is NULL")); + }); + } catch (IOException | URISyntaxException e) { + Log.e(LOGTAG, "Failed to send crash report: " + e.toString()); + } + } + + public static void postCrashFiles(@NonNull Context context, @NonNull final String aDumpFile, @NonNull final String aExtraFile) { + Executor executor = ((VRBrowserApplication)context.getApplicationContext()).getExecutors().mainThread(); + executor.execute(() -> sendCrashFiles(context, aDumpFile, aExtraFile)); + } + + public static void postCrashFiles(@NonNull Context context, final ArrayList aFiles) { + Executor executor = ((VRBrowserApplication)context.getApplicationContext()).getExecutors().mainThread(); + executor.execute(() -> { + for (String file: aFiles) { + try { + ArrayList list = new ArrayList<>(2); + try (FileInputStream in = context.openFileInput(file)) { + try(BufferedReader br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8))) { + String line; + while((line = br.readLine()) != null) { + list.add(line); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + if (list.size() < 2) { + Log.e(LOGTAG, "Failed read crash dump file names from: " + file); + return; + } + sendCrashFiles(context, list.get(0), list.get(1)); + } finally { + Log.d(LOGTAG,"Removing crash file: " + file); + context.deleteFile(file); + } + } + }); + } + + public static void clearCrashFiles(@NonNull Context context, final ArrayList aFiles) { + for (String file : aFiles) { + Log.e(LOGTAG, "Deleting crash file: " + file); + context.deleteFile(file); + } + } } diff --git a/app/src/main/res/color/context_menu_icon_color.xml b/app/src/main/res/color/context_menu_icon_color.xml deleted file mode 100644 index abd65d1b13..0000000000 --- a/app/src/main/res/color/context_menu_icon_color.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/color/context_menu_text_color.xml b/app/src/main/res/color/context_menu_text_color.xml deleted file mode 100644 index abd65d1b13..0000000000 --- a/app/src/main/res/color/context_menu_text_color.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/color/rhino_void_tint.xml b/app/src/main/res/color/rhino_void_tint.xml deleted file mode 100644 index bc67a9dd51..0000000000 --- a/app/src/main/res/color/rhino_void_tint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/color/void_fog_tint.xml b/app/src/main/res/color/void_fog_tint.xml deleted file mode 100644 index e3c37f6126..0000000000 --- a/app/src/main/res/color/void_fog_tint.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/context_menu_item_background_color.xml b/app/src/main/res/drawable/context_menu_item_background_color.xml deleted file mode 100644 index 489461eaa9..0000000000 --- a/app/src/main/res/drawable/context_menu_item_background_color.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/dialog_close_button_background.xml b/app/src/main/res/drawable/dialog_close_button_background.xml deleted file mode 100644 index 564ea037e6..0000000000 --- a/app/src/main/res/drawable/dialog_close_button_background.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/dialog_close_button_icon_color.xml b/app/src/main/res/drawable/dialog_close_button_icon_color.xml deleted file mode 100644 index af1298c814..0000000000 --- a/app/src/main/res/drawable/dialog_close_button_icon_color.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_context_menu_new_window.xml b/app/src/main/res/drawable/ic_context_menu_new_window.xml deleted file mode 100644 index f9d08e0620..0000000000 --- a/app/src/main/res/drawable/ic_context_menu_new_window.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_icon_browser.xml b/app/src/main/res/drawable/ic_icon_browser.xml deleted file mode 100644 index eb6a7cbdae..0000000000 --- a/app/src/main/res/drawable/ic_icon_browser.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_icon_dialog_cancel.xml b/app/src/main/res/drawable/ic_icon_dialog_cancel.xml deleted file mode 100644 index 0253d7f25d..0000000000 --- a/app/src/main/res/drawable/ic_icon_dialog_cancel.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_icon_dialog_tabs_active.xml b/app/src/main/res/drawable/ic_icon_dialog_tabs_active.xml deleted file mode 100644 index 99ecee26eb..0000000000 --- a/app/src/main/res/drawable/ic_icon_dialog_tabs_active.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_icon_empty.xml b/app/src/main/res/drawable/ic_icon_empty.xml deleted file mode 100644 index e541f4f057..0000000000 --- a/app/src/main/res/drawable/ic_icon_empty.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_icon_move_down.xml b/app/src/main/res/drawable/ic_icon_move_down.xml index 19281d6616..f32ca761b5 100644 --- a/app/src/main/res/drawable/ic_icon_move_down.xml +++ b/app/src/main/res/drawable/ic_icon_move_down.xml @@ -1,9 +1,11 @@ + android:viewportWidth="24" + android:viewportHeight="24"> + android:pathData="M20.1176,5.4475 L12,13.5475 3.8824,5.4475 1.3887,7.9412 12,18.5525 22.6113,7.9412Z" + android:strokeWidth="1.76854455" /> + diff --git a/app/src/main/res/drawable/ic_icon_move_up.xml b/app/src/main/res/drawable/ic_icon_move_up.xml index 4f16e43fac..ff5a1cc8d6 100644 --- a/app/src/main/res/drawable/ic_icon_move_up.xml +++ b/app/src/main/res/drawable/ic_icon_move_up.xml @@ -1,9 +1,10 @@ - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + diff --git a/app/src/main/res/drawable/ic_keyboard_arrow_left_black_24px.xml b/app/src/main/res/drawable/ic_keyboard_arrow_left_black_24px.xml deleted file mode 100644 index 3867d83e66..0000000000 --- a/app/src/main/res/drawable/ic_keyboard_arrow_left_black_24px.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_keyboard_arrow_right_black_24px.xml b/app/src/main/res/drawable/ic_keyboard_arrow_right_black_24px.xml deleted file mode 100644 index a02d8320af..0000000000 --- a/app/src/main/res/drawable/ic_keyboard_arrow_right_black_24px.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_keyboard_keyboard.xml b/app/src/main/res/drawable/ic_keyboard_keyboard.xml deleted file mode 100644 index 5dc167ac27..0000000000 --- a/app/src/main/res/drawable/ic_keyboard_keyboard.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/microphone_icon_background.xml b/app/src/main/res/drawable/microphone_icon_background.xml deleted file mode 100644 index 71c7f59b17..0000000000 --- a/app/src/main/res/drawable/microphone_icon_background.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/navigation_button_color.xml b/app/src/main/res/drawable/navigation_button_color.xml deleted file mode 100644 index 2e065ccfed..0000000000 --- a/app/src/main/res/drawable/navigation_button_color.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/app/src/main/res/drawable/panel_button_background.xml b/app/src/main/res/drawable/panel_button_background.xml deleted file mode 100644 index 8452fb7e43..0000000000 --- a/app/src/main/res/drawable/panel_button_background.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/radio_unchecked_pressed.xml b/app/src/main/res/drawable/radio_unchecked_pressed.xml deleted file mode 100644 index e565923743..0000000000 --- a/app/src/main/res/drawable/radio_unchecked_pressed.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/settings_list_row_background_color.xml b/app/src/main/res/drawable/settings_list_row_background_color.xml deleted file mode 100644 index 7835fe2888..0000000000 --- a/app/src/main/res/drawable/settings_list_row_background_color.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/url_button_end_private.xml b/app/src/main/res/drawable/url_button_end_private.xml deleted file mode 100644 index de9ec0b5ef..0000000000 --- a/app/src/main/res/drawable/url_button_end_private.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/url_button_private.xml b/app/src/main/res/drawable/url_button_private.xml deleted file mode 100644 index 73614bcaa8..0000000000 --- a/app/src/main/res/drawable/url_button_private.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/url_button_start_private.xml b/app/src/main/res/drawable/url_button_start_private.xml deleted file mode 100644 index 0b31d59c90..0000000000 --- a/app/src/main/res/drawable/url_button_start_private.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/base_app_dialog.xml b/app/src/main/res/layout/base_app_dialog.xml deleted file mode 100644 index bf1c4e30de..0000000000 --- a/app/src/main/res/layout/base_app_dialog.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -