diff --git a/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt b/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt index 739caf58d..5b4ee3afe 100644 --- a/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt +++ b/app/src/main/java/org/mozilla/fenix/BrowserDirection.kt @@ -28,5 +28,6 @@ enum class BrowserDirection(@IdRes val fragmentId: Int) { FromAddNewDeviceFragment(R.id.addNewDeviceFragment), FromAddSearchEngineFragment(R.id.addSearchEngineFragment), FromEditCustomSearchEngineFragment(R.id.editCustomSearchEngineFragment), - FromAddonDetailsFragment(R.id.addonDetailsFragment) + FromAddonDetailsFragment(R.id.addonDetailsFragment), + FromLoginDetailFragment(R.id.loginDetailFragment) } diff --git a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt index 1648cd7c4..e0ef1c075 100644 --- a/app/src/main/java/org/mozilla/fenix/HomeActivity.kt +++ b/app/src/main/java/org/mozilla/fenix/HomeActivity.kt @@ -53,6 +53,7 @@ import mozilla.components.support.utils.SafeIntent import mozilla.components.support.utils.toSafeIntent import mozilla.components.support.webextensions.WebExtensionPopupFeature import org.mozilla.fenix.GleanMetrics.Metrics +import org.mozilla.fenix.addons.AddonDetailsFragmentDirections import org.mozilla.fenix.browser.UriOpenedObserver import org.mozilla.fenix.browser.browsingmode.BrowsingMode import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager @@ -81,6 +82,7 @@ import org.mozilla.fenix.session.NotificationSessionObserver import org.mozilla.fenix.settings.SettingsFragmentDirections import org.mozilla.fenix.settings.TrackingProtectionFragmentDirections import org.mozilla.fenix.settings.about.AboutFragmentDirections +import org.mozilla.fenix.settings.logins.LoginDetailFragmentDirections import org.mozilla.fenix.settings.logins.SavedLoginsAuthFragmentDirections import org.mozilla.fenix.settings.search.AddSearchEngineFragmentDirections import org.mozilla.fenix.settings.search.EditCustomSearchEngineFragmentDirections @@ -165,14 +167,24 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } if (isActivityColdStarted(intent, savedInstanceState)) { - externalSourceIntentProcessors.any { it.process(intent, navHost.navController, this.intent) } + externalSourceIntentProcessors.any { + it.process( + intent, + navHost.navController, + this.intent + ) + } } Performance.processIntentIfPerformanceTest(intent, this) if (settings().isTelemetryEnabled) { - lifecycle.addObserver(BreadcrumbsRecorder(components.analytics.crashReporter, - navHost.navController, ::getBreadcrumbMessage)) + lifecycle.addObserver( + BreadcrumbsRecorder( + components.analytics.crashReporter, + navHost.navController, ::getBreadcrumbMessage + ) + ) val safeIntent = intent?.toSafeIntent() safeIntent @@ -209,7 +221,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { components.backgroundServices.accountManager.initAsync().await() // If we're authenticated, kick-off a sync and a device state refresh. components.backgroundServices.accountManager.authenticatedAccount()?.let { - components.backgroundServices.accountManager.syncNowAsync(SyncReason.Startup, debounce = true) + components.backgroundServices.accountManager.syncNowAsync( + SyncReason.Startup, + debounce = true + ) } } } @@ -241,8 +256,10 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { super.onNewIntent(intent) intent ?: return - val intentProcessors = listOf(CrashReporterIntentProcessor()) + externalSourceIntentProcessors - val intentHandled = intentProcessors.any { it.process(intent, navHost.navController, this.intent) } + val intentProcessors = + listOf(CrashReporterIntentProcessor()) + externalSourceIntentProcessors + val intentHandled = + intentProcessors.any { it.process(intent, navHost.navController, this.intent) } browsingModeManager.mode = getModeFromIntentOrLastKnown(intent) if (intentHandled) { @@ -474,7 +491,9 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { BrowserDirection.FromEditCustomSearchEngineFragment -> EditCustomSearchEngineFragmentDirections.actionGlobalBrowser(customTabSessionId) BrowserDirection.FromAddonDetailsFragment -> - EditCustomSearchEngineFragmentDirections.actionGlobalBrowser(customTabSessionId) + AddonDetailsFragmentDirections.actionGlobalBrowser(customTabSessionId) + BrowserDirection.FromLoginDetailFragment -> + LoginDetailFragmentDirections.actionGlobalBrowser(customTabSessionId) } private fun load( @@ -563,13 +582,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity { } @VisibleForTesting - internal fun isActivityColdStarted(startingIntent: Intent, activityIcicle: Bundle?): Boolean = + internal fun isActivityColdStarted(startingIntent: Intent, activityIcicle: Bundle?): Boolean { // First time opening this activity in the task. // Cold start / start from Recents after back press. - activityIcicle == null && - // Activity was restarted from Recents after it was destroyed by Android while in background - // in cases of memory pressure / "Don't keep activities". - startingIntent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0 + return activityIcicle == null && + // Activity was restarted from Recents after it was destroyed by Android while in background + // in cases of memory pressure / "Don't keep activities". + startingIntent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0 + } companion object { const val OPEN_TO_BROWSER = "open_to_browser" diff --git a/app/src/main/java/org/mozilla/fenix/settings/logins/LoginDetailFragment.kt b/app/src/main/java/org/mozilla/fenix/settings/logins/LoginDetailFragment.kt index c63db284f..f7c842978 100644 --- a/app/src/main/java/org/mozilla/fenix/settings/logins/LoginDetailFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/settings/logins/LoginDetailFragment.kt @@ -7,12 +7,12 @@ package org.mozilla.fenix.settings.logins import android.content.DialogInterface import android.os.Bundle import android.text.InputType -import android.view.MenuItem -import android.view.MenuInflater +import android.view.LayoutInflater import android.view.Menu +import android.view.MenuInflater +import android.view.MenuItem import android.view.View import android.view.ViewGroup -import android.view.LayoutInflater import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment @@ -21,23 +21,26 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.fragment_login_detail.* +import kotlinx.coroutines.CancellationException +import kotlinx.coroutines.Deferred import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.CancellationException -import kotlinx.coroutines.launch import kotlinx.coroutines.async +import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import mozilla.components.concept.storage.Login import mozilla.components.lib.state.ext.consumeFrom +import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.FeatureFlags +import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.redirectToReAuth import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.showToolbar @@ -119,6 +122,7 @@ class LoginDetailFragment : Fragment(R.layout.fragment_login_detail) { private fun setUpPasswordReveal() { passwordText.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + revealPasswordButton.increaseTapArea(BUTTON_INCREASE_DPS) revealPasswordButton.setOnClickListener { togglePasswordReveal() } @@ -126,9 +130,13 @@ class LoginDetailFragment : Fragment(R.layout.fragment_login_detail) { private fun setUpCopyButtons() { webAddressText.text = login?.origin - copyWebAddress.setOnClickListener( - CopyButtonListener(login?.origin, R.string.logins_site_copied) - ) + openWebAddress.increaseTapArea(BUTTON_INCREASE_DPS) + copyUsername.increaseTapArea(BUTTON_INCREASE_DPS) + copyPassword.increaseTapArea(BUTTON_INCREASE_DPS) + + openWebAddress.setOnClickListener { + navigateToBrowser(requireNotNull(login?.origin)) + } usernameText.text = login?.username copyUsername.setOnClickListener( @@ -189,6 +197,14 @@ class LoginDetailFragment : Fragment(R.layout.fragment_login_detail) { else -> false } + private fun navigateToBrowser(address: String) { + (activity as HomeActivity).openToBrowserAndLoad( + address, + newTab = true, + from = BrowserDirection.FromLoginDetailFragment + ) + } + private fun editLogin() { val directions = LoginDetailFragmentDirections @@ -281,4 +297,8 @@ class LoginDetailFragment : Fragment(R.layout.fragment_login_detail) { } } } + + private companion object { + private const val BUTTON_INCREASE_DPS = 24 + } } diff --git a/app/src/main/res/drawable/ic_copy.xml b/app/src/main/res/drawable/ic_copy.xml index 278049399..e6bdd9f94 100644 --- a/app/src/main/res/drawable/ic_copy.xml +++ b/app/src/main/res/drawable/ic_copy.xml @@ -3,12 +3,12 @@ - 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/. --> + android:width="17dp" + android:height="20dp" + android:viewportWidth="17" + android:viewportHeight="20"> + android:fillType="nonZero" + android:pathData="M10.69,3A3.313,3.313 0,0 1,14 6.31v10.38A3.313,3.313 0,0 1,10.69 20L3.31,20A3.313,3.313 0,0 1,0 16.69L0,6.31A3.313,3.313 0,0 1,3.31 3h7.38zM10.69,5L3.31,5C2.587,5 2,5.587 2,6.31v10.38c0,0.723 0.587,1.31 1.31,1.31h7.38c0.723,0 1.31,-0.587 1.31,-1.31L12,6.31C12,5.587 11.413,5 10.69,5zM10.995,0A6.003,6.003 0,0 1,17 6v0.016l-0.024,8.987a2,2 0,0 1,-2.005 1.994h-0.002l0.03,-10.986L14.999,6c0,-2.21 -1.793,-4 -4.004,-4L3,2a2,2 0,0 1,2 -2h5.995z" /> diff --git a/app/src/main/res/drawable/ic_open_in_new.xml b/app/src/main/res/drawable/ic_open_in_new.xml new file mode 100644 index 000000000..46bb28221 --- /dev/null +++ b/app/src/main/res/drawable/ic_open_in_new.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/app/src/main/res/layout/fragment_login_detail.xml b/app/src/main/res/layout/fragment_login_detail.xml index e6cfa17a5..3faa7205e 100644 --- a/app/src/main/res/layout/fragment_login_detail.xml +++ b/app/src/main/res/layout/fragment_login_detail.xml @@ -2,7 +2,6 @@ - + android:layout_marginEnd="12dp"> @@ -35,10 +34,10 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:gravity="center_vertical" - android:textColor="?primaryText" - android:textSize="16sp" android:paddingTop="@dimen/saved_logins_detail_menu_vertical_padding" android:paddingBottom="@dimen/saved_logins_detail_menu_vertical_padding" + android:textColor="?primaryText" + android:textSize="16sp" app:layout_constraintEnd_toEndOf="@id/webAddressHeader" app:layout_constraintStart_toStartOf="@id/webAddressHeader" app:layout_constraintTop_toBottomOf="@id/webAddressHeader" @@ -46,15 +45,15 @@ tools:text="Info" /> @@ -106,12 +106,12 @@ android:id="@+id/passwordHeader" android:layout_width="0dp" android:layout_height="24dp" + android:layout_marginTop="12dp" android:gravity="center_vertical" android:letterSpacing="0.05" android:text="@string/preferences_passwords_saved_logins_password" android:textColor="?primaryText" android:textSize="12sp" - android:layout_marginTop="12dp" app:fontFamily="@font/metropolis_semibold" app:layout_constraintBottom_toTopOf="@id/passwordText" app:layout_constraintEnd_toStartOf="@id/revealPasswordButton" @@ -123,14 +123,14 @@ android:id="@+id/passwordText" android:layout_width="0dp" android:layout_height="30dp" + android:layout_marginTop="2dp" android:gravity="center_vertical" android:letterSpacing="0.01" android:lineSpacingExtra="8sp" - android:layout_marginTop="2dp" android:textColor="?primaryText" android:textSize="16sp" app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="@id/passwordHeader" + app:layout_constraintEnd_toStartOf="@id/revealPasswordButton" app:layout_constraintStart_toStartOf="@id/passwordHeader" app:layout_constraintTop_toBottomOf="@id/passwordHeader" app:layout_constraintVertical_chainStyle="packed" @@ -138,25 +138,27 @@ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 738b529bc..d1feb77d5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1255,6 +1255,8 @@ Copy username Copy site + + Open site in browser Show password