Copione merged onto master
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
2abc9d72d3
615
app/metrics.yaml
615
app/metrics.yaml
File diff suppressed because it is too large
Load Diff
|
@ -340,7 +340,7 @@ class BookmarksTest {
|
|||
}
|
||||
|
||||
multipleSelectionToolbar {
|
||||
}.clickOpenNewTab { }.openTabDrawer {
|
||||
}.clickOpenNewTab {
|
||||
verifyNormalModeSelected()
|
||||
verifyExistingTabList()
|
||||
}
|
||||
|
@ -363,7 +363,7 @@ class BookmarksTest {
|
|||
}
|
||||
|
||||
multipleSelectionToolbar {
|
||||
}.clickOpenPrivateTab { }.openTabDrawer {
|
||||
}.clickOpenPrivateTab {
|
||||
verifyPrivateModeSelected()
|
||||
verifyExistingTabList()
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ class HistoryTest {
|
|||
}
|
||||
|
||||
multipleSelectionToolbar {
|
||||
}.clickOpenNewTab { }.openTabDrawer {
|
||||
}.clickOpenNewTab {
|
||||
verifyExistingTabList()
|
||||
verifyNormalModeSelected()
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ class HistoryTest {
|
|||
}
|
||||
|
||||
multipleSelectionToolbar {
|
||||
}.clickOpenPrivateTab { }.openTabDrawer {
|
||||
}.clickOpenPrivateTab {
|
||||
verifyPrivateModeSelected()
|
||||
verifyExistingTabList()
|
||||
}
|
||||
|
|
|
@ -50,6 +50,12 @@ class SearchTest {
|
|||
@Test
|
||||
fun shortcutButtonTest() {
|
||||
homeScreen {
|
||||
}.openThreeDotMenu {
|
||||
}.openSettings {
|
||||
}.openSearchSubMenu {
|
||||
enableShowSearchShortcuts()
|
||||
}.goBack {
|
||||
}.goBack {
|
||||
}.openSearch {
|
||||
verifySearchWithText()
|
||||
clickSearchEngineButton("DuckDuckGo")
|
||||
|
@ -63,6 +69,12 @@ class SearchTest {
|
|||
@Test
|
||||
fun shortcutSearchEngineSettingsTest() {
|
||||
homeScreen {
|
||||
}.openThreeDotMenu {
|
||||
}.openSettings {
|
||||
}.openSearchSubMenu {
|
||||
enableShowSearchShortcuts()
|
||||
}.goBack {
|
||||
}.goBack {
|
||||
}.openSearch {
|
||||
scrollToSearchEngineSettings()
|
||||
clickSearchEngineSettings()
|
||||
|
|
|
@ -85,23 +85,26 @@ class LibrarySubMenusMultipleSelectionToolbarRobot {
|
|||
return BookmarksRobot.Transition()
|
||||
}
|
||||
|
||||
fun clickOpenNewTab(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
|
||||
fun clickOpenNewTab(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition {
|
||||
openInNewTabButton().click()
|
||||
mDevice.waitNotNull(Until.findObject(By.text("Collections")), waitingTime)
|
||||
|
||||
HomeScreenRobot().interact()
|
||||
return HomeScreenRobot.Transition()
|
||||
}
|
||||
|
||||
fun clickOpenPrivateTab(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
|
||||
openInPrivateTabButton().click()
|
||||
mDevice.waitNotNull(
|
||||
Until.findObject(By.text(PRIVATE_SESSION_MESSAGE)),
|
||||
Until.findObject(By.res("org.mozilla.fenix.debug:id/tab_layout")),
|
||||
waitingTime
|
||||
)
|
||||
|
||||
HomeScreenRobot().interact()
|
||||
return HomeScreenRobot.Transition()
|
||||
TabDrawerRobot().interact()
|
||||
return TabDrawerRobot.Transition()
|
||||
}
|
||||
|
||||
fun clickOpenPrivateTab(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition {
|
||||
openInPrivateTabButton().click()
|
||||
mDevice.waitNotNull(
|
||||
Until.findObject(By.res("org.mozilla.fenix.debug:id/tab_layout")),
|
||||
waitingTime
|
||||
)
|
||||
|
||||
TabDrawerRobot().interact()
|
||||
return TabDrawerRobot.Transition()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ class SettingsSubMenuSearchRobot {
|
|||
selectDefaultSearchEngine(searchEngineName)
|
||||
|
||||
fun disableShowSearchSuggestions() = toggleShowSearchSuggestions()
|
||||
fun enableShowSearchShortcuts() = toggleShowSearchShortcuts()
|
||||
|
||||
class Transition {
|
||||
val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
|
@ -142,5 +143,16 @@ private fun toggleShowSearchSuggestions() {
|
|||
.perform(click())
|
||||
}
|
||||
|
||||
private fun toggleShowSearchShortcuts() {
|
||||
onView(withId(androidx.preference.R.id.recycler_view)).perform(
|
||||
RecyclerViewActions.scrollTo<RecyclerView.ViewHolder>(
|
||||
hasDescendant(withText("Show search shortcuts"))
|
||||
)
|
||||
)
|
||||
|
||||
onView(withText("Show search shortcuts"))
|
||||
.perform(click())
|
||||
}
|
||||
|
||||
private fun goBackButton() =
|
||||
onView(CoreMatchers.allOf(withContentDescription("Navigate up")))
|
||||
|
|
|
@ -26,6 +26,7 @@ import androidx.test.platform.app.InstrumentationRegistry
|
|||
import androidx.test.uiautomator.By
|
||||
import androidx.test.uiautomator.By.text
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import androidx.test.uiautomator.Until
|
||||
import androidx.test.uiautomator.Until.findObject
|
||||
import org.hamcrest.CoreMatchers.allOf
|
||||
import org.mozilla.fenix.R
|
||||
|
@ -104,6 +105,20 @@ class TabDrawerRobot {
|
|||
return ThreeDotMenuMainRobot.Transition()
|
||||
}
|
||||
|
||||
fun openTabDrawer(interact: TabDrawerRobot.() -> Unit): TabDrawerRobot.Transition {
|
||||
org.mozilla.fenix.ui.robots.mDevice.waitForIdle()
|
||||
|
||||
tabsCounter().click()
|
||||
|
||||
org.mozilla.fenix.ui.robots.mDevice.waitNotNull(
|
||||
Until.findObject(By.res("org.mozilla.fenix.debug:id/tab_layout")),
|
||||
waitingTime
|
||||
)
|
||||
|
||||
TabDrawerRobot().interact()
|
||||
return TabDrawerRobot.Transition()
|
||||
}
|
||||
|
||||
fun openHomeScreen(interact: HomeScreenRobot.() -> Unit): HomeScreenRobot.Transition {
|
||||
mDevice.waitForIdle()
|
||||
|
||||
|
@ -196,3 +211,5 @@ private fun tab(title: String) =
|
|||
withText(title)
|
||||
)
|
||||
)
|
||||
|
||||
private fun tabsCounter() = onView(withId(R.id.tab_button))
|
||||
|
|
|
@ -23,7 +23,7 @@ object FeatureFlags {
|
|||
/**
|
||||
* Enable tab sync feature
|
||||
*/
|
||||
val syncedTabs = Config.channel.isNightlyOrDebug
|
||||
const val syncedTabs = true
|
||||
|
||||
/**
|
||||
* Enables new tab tray pref
|
||||
|
|
|
@ -173,6 +173,9 @@ open class FenixApplication : LocaleAwareApplication() {
|
|||
taskQueue.runIfReadyOrQueue {
|
||||
Experiments.initialize(
|
||||
applicationContext = applicationContext,
|
||||
onExperimentsUpdated = {
|
||||
ExperimentsManager.initSearchWidgetExperiment(this)
|
||||
},
|
||||
configuration = mozilla.components.service.experiments.Configuration(
|
||||
httpClient = components.core.client,
|
||||
kintoEndpoint = KINTO_ENDPOINT_PROD
|
||||
|
|
|
@ -174,10 +174,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
|||
lifecycle.addObserver(BreadcrumbsRecorder(components.analytics.crashReporter,
|
||||
navHost.navController, ::getBreadcrumbMessage))
|
||||
|
||||
intent
|
||||
?.toSafeIntent()
|
||||
val safeIntent = intent?.toSafeIntent()
|
||||
safeIntent
|
||||
?.let(::getIntentSource)
|
||||
?.also { components.analytics.metrics.track(Event.OpenedApp(it)) }
|
||||
// record on cold startup
|
||||
safeIntent
|
||||
?.let(::getIntentAllSource)
|
||||
?.also { components.analytics.metrics.track(Event.AppRecievedIntent(it)) }
|
||||
}
|
||||
supportActionBar?.hide()
|
||||
|
||||
|
@ -250,6 +254,15 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
|||
?.let { it as? TabTrayDialogFragment }
|
||||
?.also { it.dismissAllowingStateLoss() }
|
||||
}
|
||||
|
||||
// If there is a warm or hot startup, onNewIntent method is always called first.
|
||||
// Note: This does not work in case of an user sending an intent with ACTION_VIEW
|
||||
// for example, launch the application, and than use adb to send an intent with
|
||||
// ACTION_VIEW to open a link. In this case, we will get multiple telemetry events.
|
||||
intent
|
||||
.toSafeIntent()
|
||||
.let(::getIntentAllSource)
|
||||
?.also { components.analytics.metrics.track(Event.AppRecievedIntent(it)) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -320,6 +333,14 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
protected open fun getIntentAllSource(intent: SafeIntent): Event.AppRecievedIntent.Source? {
|
||||
return when {
|
||||
intent.isLauncherIntent -> Event.AppRecievedIntent.Source.APP_ICON
|
||||
intent.action == Intent.ACTION_VIEW -> Event.AppRecievedIntent.Source.LINK
|
||||
else -> Event.AppRecievedIntent.Source.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* External sources such as 3rd party links and shortcuts use this function to enter
|
||||
* private mode directly before the content view is created. Returns the mode set by the intent
|
||||
|
@ -490,11 +511,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
fun updateThemeForSession(session: Session) {
|
||||
val sessionMode = BrowsingMode.fromBoolean(session.private)
|
||||
browsingModeManager.mode = sessionMode
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
StrictMode.allowThreadDiskReads().resetPoliciesAfter {
|
||||
super.attachBaseContext(base)
|
||||
|
|
|
@ -9,8 +9,6 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import android.os.StrictMode
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.feature.intent.processing.IntentProcessor
|
||||
import org.mozilla.fenix.components.IntentProcessorType
|
||||
import org.mozilla.fenix.components.getType
|
||||
|
@ -33,19 +31,17 @@ class IntentReceiverActivity : Activity() {
|
|||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
MainScope().launch {
|
||||
// The intent property is nullable, but the rest of the code below
|
||||
// assumes it is not. If it's null, then we make a new one and open
|
||||
// the HomeActivity.
|
||||
val intent = intent?.let { Intent(it) } ?: Intent()
|
||||
intent.stripUnwantedFlags()
|
||||
processIntent(intent)
|
||||
}
|
||||
// The intent property is nullable, but the rest of the code below
|
||||
// assumes it is not. If it's null, then we make a new one and open
|
||||
// the HomeActivity.
|
||||
val intent = intent?.let { Intent(it) } ?: Intent()
|
||||
intent.stripUnwantedFlags()
|
||||
processIntent(intent)
|
||||
|
||||
StartupTimeline.onActivityCreateEndIntentReceiver()
|
||||
}
|
||||
|
||||
suspend fun processIntent(intent: Intent) {
|
||||
fun processIntent(intent: Intent) {
|
||||
// Call process for side effects, short on the first that returns true
|
||||
val processor = getIntentProcessors().firstOrNull { it.process(intent) }
|
||||
val intentProcessorType = components.intentProcessors.getType(processor)
|
||||
|
|
|
@ -78,6 +78,7 @@ import org.mozilla.fenix.HomeActivity
|
|||
import org.mozilla.fenix.IntentReceiverActivity
|
||||
import org.mozilla.fenix.NavGraphDirections
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
|
||||
import org.mozilla.fenix.browser.readermode.DefaultReaderModeController
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.components.FindInPageIntegration
|
||||
|
@ -690,7 +691,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
|
||||
@CallSuper
|
||||
override fun onSessionSelected(session: Session) {
|
||||
(activity as HomeActivity).updateThemeForSession(session)
|
||||
updateThemeForSession(session)
|
||||
if (!browserInitialized) {
|
||||
// Initializing a new coroutineScope to avoid ConcurrentModificationException in ObserverRegistry
|
||||
// This will be removed when ObserverRegistry is deprecated by browser-state.
|
||||
|
@ -720,6 +721,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
components.useCases.sessionUseCases.reload()
|
||||
}
|
||||
hideToolbar()
|
||||
|
||||
getSessionById()?.let { updateThemeForSession(it) }
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
|
@ -872,6 +875,14 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the activity normal/private theme to match the current session.
|
||||
*/
|
||||
private fun updateThemeForSession(session: Session) {
|
||||
val sessionMode = BrowsingMode.fromBoolean(session.private)
|
||||
(activity as HomeActivity).browsingModeManager.mode = sessionMode
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current session.
|
||||
*/
|
||||
|
@ -997,6 +1008,5 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
private const val REQUEST_CODE_DOWNLOAD_PERMISSIONS = 1
|
||||
private const val REQUEST_CODE_PROMPT_PERMISSIONS = 2
|
||||
private const val REQUEST_CODE_APP_PERMISSIONS = 3
|
||||
private const val SNACKBAR_ELEVATION = 80f
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ import mozilla.components.feature.tab.collections.TabCollection
|
|||
import mozilla.components.feature.tabs.WindowFeature
|
||||
import mozilla.components.support.base.feature.UserInteractionHandler
|
||||
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.addons.runIfFragmentIsAttached
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
|
@ -40,8 +39,8 @@ import org.mozilla.fenix.ext.components
|
|||
import org.mozilla.fenix.ext.nav
|
||||
import org.mozilla.fenix.ext.navigateSafe
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.ext.resetPoliciesAfter
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.shortcut.FirstTimePwaObserver
|
||||
import org.mozilla.fenix.trackingprotection.TrackingProtectionOverlay
|
||||
|
||||
|
@ -178,9 +177,6 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
getSessionById()?.let {
|
||||
(activity as HomeActivity).updateThemeForSession(it)
|
||||
}
|
||||
requireComponents.core.tabCollectionStorage.register(collectionStorageObserver, this)
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,12 @@ import mozilla.components.browser.session.SessionManager
|
|||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.metrics
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class UriOpenedObserver(
|
||||
private val settings: Settings,
|
||||
private val owner: LifecycleOwner,
|
||||
private val sessionManager: SessionManager,
|
||||
metrics: MetricController,
|
||||
|
@ -22,6 +25,7 @@ class UriOpenedObserver(
|
|||
) : SessionManager.Observer {
|
||||
|
||||
constructor(activity: FragmentActivity) : this(
|
||||
activity.applicationContext.settings(),
|
||||
activity,
|
||||
activity.components.core.sessionManager,
|
||||
activity.metrics,
|
||||
|
@ -41,20 +45,24 @@ class UriOpenedObserver(
|
|||
}
|
||||
|
||||
override fun onAllSessionsRemoved() {
|
||||
settings.setOpenTabsCount(sessionManager.sessions.filter { !it.private }.size)
|
||||
sessionManager.sessions.forEach {
|
||||
it.unregister(singleSessionObserver)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSessionAdded(session: Session) {
|
||||
settings.setOpenTabsCount(sessionManager.sessions.filter { !it.private }.size)
|
||||
session.register(singleSessionObserver, owner)
|
||||
}
|
||||
|
||||
override fun onSessionRemoved(session: Session) {
|
||||
settings.setOpenTabsCount(sessionManager.sessions.filter { !it.private }.size)
|
||||
session.unregister(singleSessionObserver)
|
||||
}
|
||||
|
||||
override fun onSessionsRestored() {
|
||||
settings.setOpenTabsCount(sessionManager.sessions.filter { !it.private }.size)
|
||||
sessionManager.sessions.forEach {
|
||||
it.register(singleSessionObserver, owner)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.mozilla.fenix.collections
|
|||
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
|
@ -62,13 +61,21 @@ fun List<Tab>.toSessionBundle(sessionManager: SessionManager): List<Session> {
|
|||
return this.mapNotNull { sessionManager.findSessionById(it.sessionId) }
|
||||
}
|
||||
|
||||
/**
|
||||
* @param store Store used to hold in-memory collection state.
|
||||
* @param dismiss Callback to dismiss the collection creation dialog.
|
||||
* @param metrics Controller that handles telemetry events.
|
||||
* @param tabCollectionStorage Storage used to save tab collections to disk.
|
||||
* @param sessionManager Used to query and serialize tabs.
|
||||
* @param ioScope Coroutine scope that launches on the IO thread.
|
||||
*/
|
||||
class DefaultCollectionCreationController(
|
||||
private val store: CollectionCreationStore,
|
||||
private val dismiss: () -> Unit,
|
||||
private val metrics: MetricController,
|
||||
private val tabCollectionStorage: TabCollectionStorage,
|
||||
private val sessionManager: SessionManager,
|
||||
private val scope: CoroutineScope
|
||||
private val ioScope: CoroutineScope
|
||||
) : CollectionCreationController {
|
||||
|
||||
companion object {
|
||||
|
@ -80,7 +87,7 @@ class DefaultCollectionCreationController(
|
|||
dismiss()
|
||||
|
||||
val sessionBundle = tabs.toSessionBundle(sessionManager)
|
||||
scope.launch(IO) {
|
||||
ioScope.launch {
|
||||
tabCollectionStorage.createCollection(name, sessionBundle)
|
||||
}
|
||||
|
||||
|
@ -91,7 +98,7 @@ class DefaultCollectionCreationController(
|
|||
|
||||
override fun renameCollection(collection: TabCollection, name: String) {
|
||||
dismiss()
|
||||
scope.launch(IO) {
|
||||
ioScope.launch {
|
||||
tabCollectionStorage.renameCollection(collection, name)
|
||||
}
|
||||
metrics.track(Event.CollectionRenamed)
|
||||
|
@ -121,7 +128,7 @@ class DefaultCollectionCreationController(
|
|||
override fun selectCollection(collection: TabCollection, tabs: List<Tab>) {
|
||||
dismiss()
|
||||
val sessionBundle = tabs.toList().toSessionBundle(sessionManager)
|
||||
scope.launch(IO) {
|
||||
ioScope.launch {
|
||||
tabCollectionStorage
|
||||
.addTabsToCollection(collection, sessionBundle)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,9 @@ import androidx.fragment.app.DialogFragment
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import kotlinx.android.synthetic.main.fragment_create_collection.view.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.plus
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||
|
@ -77,7 +79,7 @@ class CollectionCreationFragment : DialogFragment() {
|
|||
requireComponents.analytics.metrics,
|
||||
requireComponents.core.tabCollectionStorage,
|
||||
requireComponents.core.sessionManager,
|
||||
scope = lifecycleScope
|
||||
ioScope = lifecycleScope + Dispatchers.IO
|
||||
)
|
||||
)
|
||||
collectionCreationView = CollectionCreationView(
|
||||
|
|
|
@ -188,7 +188,7 @@ class Core(private val context: Context) {
|
|||
|
||||
WebNotificationFeature(
|
||||
context, engine, icons, R.drawable.ic_status_logo,
|
||||
HomeActivity::class.java
|
||||
permissionStorage.permissionsStorage, HomeActivity::class.java
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,16 +22,15 @@ import org.mozilla.fenix.GleanMetrics.CustomTab
|
|||
import org.mozilla.fenix.GleanMetrics.DownloadNotification
|
||||
import org.mozilla.fenix.GleanMetrics.ErrorPage
|
||||
import org.mozilla.fenix.GleanMetrics.Events
|
||||
import org.mozilla.fenix.GleanMetrics.Events.preferenceToggled
|
||||
import org.mozilla.fenix.GleanMetrics.FindInPage
|
||||
import org.mozilla.fenix.GleanMetrics.History
|
||||
import org.mozilla.fenix.GleanMetrics.Logins
|
||||
import org.mozilla.fenix.GleanMetrics.MediaNotification
|
||||
import org.mozilla.fenix.GleanMetrics.MediaState
|
||||
import org.mozilla.fenix.GleanMetrics.Metrics
|
||||
import org.mozilla.fenix.GleanMetrics.Onboarding
|
||||
import org.mozilla.fenix.GleanMetrics.Pings
|
||||
import org.mozilla.fenix.GleanMetrics.Pocket
|
||||
import org.mozilla.fenix.GleanMetrics.Onboarding
|
||||
import org.mozilla.fenix.GleanMetrics.Preferences
|
||||
import org.mozilla.fenix.GleanMetrics.PrivateBrowsingMode
|
||||
import org.mozilla.fenix.GleanMetrics.PrivateBrowsingShortcut
|
||||
|
@ -98,6 +97,10 @@ private val Event.wrapper: EventWrapper<*>?
|
|||
{ Events.appOpened.record(it) },
|
||||
{ Events.appOpenedKeys.valueOf(it) }
|
||||
)
|
||||
is Event.AppRecievedIntent -> EventWrapper(
|
||||
{ Events.appReceivedIntent.record(it) },
|
||||
{ Events.appReceivedIntentKeys.valueOf(it) }
|
||||
)
|
||||
is Event.SearchBarTapped -> EventWrapper(
|
||||
{ Events.searchBarTapped.record(it) },
|
||||
{ Events.searchBarTappedKeys.valueOf(it) }
|
||||
|
@ -602,6 +605,43 @@ private val Event.wrapper: EventWrapper<*>?
|
|||
{ ContextualHintTrackingProtection.outsideTap.record(it) }
|
||||
)
|
||||
|
||||
is Event.TabsTrayOpened -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.opened.record(it) }
|
||||
)
|
||||
is Event.TabsTrayClosed -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.closed.record(it) }
|
||||
)
|
||||
is Event.OpenedExistingTab -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.openedExistingTab.record(it) }
|
||||
)
|
||||
is Event.ClosedExistingTab -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.closedExistingTab.record(it) }
|
||||
)
|
||||
is Event.TabsTrayPrivateModeTapped -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.privateModeTapped.record(it) }
|
||||
)
|
||||
is Event.TabsTrayNormalModeTapped -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.normalModeTapped.record(it) }
|
||||
)
|
||||
is Event.NewTabTapped -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.newTabTapped.record(it) }
|
||||
)
|
||||
is Event.NewPrivateTabTapped -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.newPrivateTabTapped.record(it) }
|
||||
)
|
||||
is Event.TabsTrayMenuOpened -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.menuOpened.record(it) }
|
||||
)
|
||||
is Event.TabsTraySaveToCollectionPressed -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.saveToCollection.record(it) }
|
||||
)
|
||||
is Event.TabsTrayShareAllTabsPressed -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.shareAllTabs.record(it) }
|
||||
)
|
||||
is Event.TabsTrayCloseAllTabsPressed -> EventWrapper<NoExtraKeys>(
|
||||
{ org.mozilla.fenix.GleanMetrics.TabsTray.closeAllTabs.record(it) }
|
||||
)
|
||||
|
||||
// Don't record other events in Glean:
|
||||
is Event.AddBookmark -> null
|
||||
is Event.OpenedBookmark -> null
|
||||
|
@ -661,6 +701,12 @@ class GleanMetricsService(private val context: Context) : MetricsService {
|
|||
|
||||
searchWidgetInstalled.set(context.settings().searchWidgetInstalled)
|
||||
|
||||
val openTabsCount = context.settings().openTabsCount
|
||||
hasOpenTabs.set(openTabsCount > 0)
|
||||
if (openTabsCount > 0) {
|
||||
tabsOpenCount.add(openTabsCount)
|
||||
}
|
||||
|
||||
val topSitesSize = context.settings().topSitesSize
|
||||
hasTopSites.set(topSitesSize > 0)
|
||||
if (topSitesSize > 0) {
|
||||
|
|
|
@ -185,6 +185,19 @@ sealed class Event {
|
|||
object ContextualHintETPOutsideTap : Event()
|
||||
object ContextualHintETPInsideTap : Event()
|
||||
|
||||
object TabsTrayOpened : Event()
|
||||
object TabsTrayClosed : Event()
|
||||
object OpenedExistingTab : Event()
|
||||
object ClosedExistingTab : Event()
|
||||
object TabsTrayPrivateModeTapped : Event()
|
||||
object TabsTrayNormalModeTapped : Event()
|
||||
object NewTabTapped : Event()
|
||||
object NewPrivateTabTapped : Event()
|
||||
object TabsTrayMenuOpened : Event()
|
||||
object TabsTraySaveToCollectionPressed : Event()
|
||||
object TabsTrayShareAllTabsPressed : Event()
|
||||
object TabsTrayCloseAllTabsPressed : Event()
|
||||
|
||||
// Interaction events with extras
|
||||
data class OnboardingToolbarPosition(val position: Position) : Event() {
|
||||
enum class Position { TOP, BOTTOM }
|
||||
|
@ -296,6 +309,13 @@ sealed class Event {
|
|||
get() = hashMapOf(Events.appOpenedKeys.source to source.name)
|
||||
}
|
||||
|
||||
data class AppRecievedIntent(val source: Source) : Event() {
|
||||
enum class Source { APP_ICON, LINK, CUSTOM_TAB, UNKNOWN }
|
||||
|
||||
override val extras: Map<Events.appReceivedIntentKeys, String>?
|
||||
get() = hashMapOf(Events.appReceivedIntentKeys.source to source.name)
|
||||
}
|
||||
|
||||
data class CollectionSaveButtonPressed(val fromScreen: String) : Event() {
|
||||
override val extras: Map<Collections.saveButtonKeys, String>?
|
||||
get() = mapOf(Collections.saveButtonKeys.fromScreen to fromScreen)
|
||||
|
|
|
@ -19,6 +19,7 @@ import mozilla.components.browser.search.provider.SearchEngineList
|
|||
import mozilla.components.browser.search.provider.SearchEngineProvider
|
||||
import mozilla.components.browser.search.provider.filter.SearchEngineFilter
|
||||
import mozilla.components.browser.search.provider.localization.LocaleSearchLocalizationProvider
|
||||
import mozilla.components.browser.search.provider.localization.SearchLocalization
|
||||
import mozilla.components.browser.search.provider.localization.SearchLocalizationProvider
|
||||
import mozilla.components.service.location.LocationService
|
||||
import mozilla.components.service.location.MozillaLocationService
|
||||
|
@ -51,12 +52,18 @@ open class FenixSearchEngineProvider(
|
|||
AssetsSearchEngineProvider(localizationProvider).loadSearchEngines(context)
|
||||
}
|
||||
|
||||
private val loadedRegion = async { localizationProvider.determineRegion() }
|
||||
|
||||
// https://github.com/mozilla-mobile/fenix/issues/9935
|
||||
// Adds a Locale search engine provider as a fallback in case the MLS lookup takes longer
|
||||
// than the time it takes for a user to try to search.
|
||||
private val fallBackEngines = async {
|
||||
AssetsSearchEngineProvider(LocaleSearchLocalizationProvider()).loadSearchEngines(context)
|
||||
}
|
||||
private val fallbackLocationService: SearchLocalizationProvider = LocaleSearchLocalizationProvider()
|
||||
private val fallBackProvider =
|
||||
AssetsSearchEngineProvider(fallbackLocationService)
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
open val fallbackEngines = async { fallBackProvider.loadSearchEngines(context) }
|
||||
private val fallbackRegion = async { fallbackLocationService.determineRegion() }
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
open val bundledSearchEngines = async {
|
||||
|
@ -88,7 +95,15 @@ open class FenixSearchEngineProvider(
|
|||
if (loadedSearchEngines.isCompleted) {
|
||||
loadedSearchEngines
|
||||
} else {
|
||||
fallBackEngines
|
||||
fallbackEngines
|
||||
}
|
||||
|
||||
private val region: Deferred<SearchLocalization>
|
||||
get() =
|
||||
if (loadedRegion.isCompleted) {
|
||||
loadedRegion
|
||||
} else {
|
||||
fallbackRegion
|
||||
}
|
||||
|
||||
fun getDefaultEngine(context: Context): SearchEngine {
|
||||
|
@ -199,7 +214,11 @@ open class FenixSearchEngineProvider(
|
|||
}
|
||||
|
||||
if (!prefs.contains(installedEnginesKey)) {
|
||||
val defaultSet = baseSearchEngines.await()
|
||||
val searchEngines =
|
||||
if (baseSearchEngines.isCompleted) baseSearchEngines
|
||||
else fallbackEngines
|
||||
|
||||
val defaultSet = searchEngines.await()
|
||||
.list
|
||||
.map { it.identifier }
|
||||
.toSet()
|
||||
|
@ -215,7 +234,7 @@ open class FenixSearchEngineProvider(
|
|||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
suspend fun localeAwareInstalledEnginesKey(): String {
|
||||
val tag = localizationProvider.determineRegion().let {
|
||||
val tag = region.await().let {
|
||||
val region = it.region?.let { region ->
|
||||
if (region.isEmpty()) "" else "-$region"
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ class CustomTabsIntegration(
|
|||
)
|
||||
}
|
||||
|
||||
toolbar.background = getDrawable(activity, R.drawable.toolbar_background_private)
|
||||
toolbar.background = getDrawable(activity, R.drawable.toolbar_background)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ open class ExternalAppBrowserActivity : HomeActivity() {
|
|||
|
||||
final override fun getIntentSource(intent: SafeIntent) = Event.OpenedApp.Source.CUSTOM_TAB
|
||||
|
||||
final override fun getIntentAllSource(intent: SafeIntent) = Event.AppRecievedIntent.Source.CUSTOM_TAB
|
||||
|
||||
final override fun getIntentSessionId(intent: SafeIntent) = intent.getSessionId()
|
||||
|
||||
override fun getNavDirections(
|
||||
|
|
|
@ -9,6 +9,7 @@ import android.content.Intent
|
|||
import android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.core.content.ContextCompat
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.session.Session.Source
|
||||
import mozilla.components.browser.session.SessionManager
|
||||
|
@ -52,16 +53,17 @@ class FennecWebAppIntentProcessor(
|
|||
* A custom tab config is also set so a custom tab toolbar can be shown when the user leaves
|
||||
* the scope defined in the manifest.
|
||||
*/
|
||||
override suspend fun process(intent: Intent): Boolean {
|
||||
override fun process(intent: Intent): Boolean {
|
||||
val safeIntent = intent.toSafeIntent()
|
||||
val url = safeIntent.dataString
|
||||
|
||||
return if (!url.isNullOrEmpty() && matches(intent)) {
|
||||
val webAppManifest = loadManifest(safeIntent, url)
|
||||
val webAppManifest = runBlocking { loadManifest(safeIntent, url) }
|
||||
|
||||
val session = Session(url, private = false, source = Source.HOME_SCREEN)
|
||||
session.webAppManifest = webAppManifest
|
||||
session.customTabConfig = webAppManifest?.toCustomTabConfig() ?: createFallbackCustomTabConfig()
|
||||
session.customTabConfig =
|
||||
webAppManifest?.toCustomTabConfig() ?: createFallbackCustomTabConfig()
|
||||
|
||||
sessionManager.add(session)
|
||||
loadUrlUseCase(url, session, EngineSession.LoadUrlFlags.external())
|
||||
|
|
|
@ -35,7 +35,7 @@ class FennecBookmarkShortcutsIntentProcessor(
|
|||
* If this is an Intent for a Fennec pinned website shortcut
|
||||
* prepare it for opening website's URL in a new tab.
|
||||
*/
|
||||
override suspend fun process(intent: Intent): Boolean {
|
||||
override fun process(intent: Intent): Boolean {
|
||||
val safeIntent = intent.toSafeIntent()
|
||||
val url = safeIntent.dataString
|
||||
|
||||
|
|
|
@ -204,14 +204,14 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), UserInteractionHan
|
|||
R.id.open_bookmarks_in_new_tabs_multi_select -> {
|
||||
openItemsInNewTab { node -> node.url }
|
||||
|
||||
navigate(BookmarkFragmentDirections.actionGlobalHome())
|
||||
navigate(BookmarkFragmentDirections.actionGlobalTabTrayDialogFragment())
|
||||
metrics?.track(Event.OpenedBookmarksInNewTabs)
|
||||
true
|
||||
}
|
||||
R.id.open_bookmarks_in_private_tabs_multi_select -> {
|
||||
openItemsInNewTab(private = true) { node -> node.url }
|
||||
|
||||
navigate(BookmarkFragmentDirections.actionGlobalHome())
|
||||
navigate(BookmarkFragmentDirections.actionGlobalTabTrayDialogFragment())
|
||||
metrics?.track(Event.OpenedBookmarksInPrivateTabs)
|
||||
true
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ class HistoryFragment : LibraryPageFragment<HistoryItem>(), UserInteractionHandl
|
|||
|
||||
nav(
|
||||
R.id.historyFragment,
|
||||
HistoryFragmentDirections.actionGlobalHome()
|
||||
HistoryFragmentDirections.actionGlobalTabTrayDialogFragment()
|
||||
)
|
||||
true
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ class HistoryFragment : LibraryPageFragment<HistoryItem>(), UserInteractionHandl
|
|||
}
|
||||
nav(
|
||||
R.id.historyFragment,
|
||||
HistoryFragmentDirections.actionGlobalHome()
|
||||
HistoryFragmentDirections.actionGlobalTabTrayDialogFragment()
|
||||
)
|
||||
true
|
||||
}
|
||||
|
|
|
@ -294,8 +294,6 @@ class SearchFragment : Fragment(), UserInteractionHandler {
|
|||
|
||||
view.search_suggestions_onboarding.setOnInflateListener((stubListener))
|
||||
|
||||
view.toolbar_wrapper.clipToOutline = false
|
||||
|
||||
fill_link_from_clipboard.setOnClickListener {
|
||||
(activity as HomeActivity)
|
||||
.openToBrowserAndLoad(
|
||||
|
|
|
@ -8,7 +8,6 @@ import android.content.Context
|
|||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.BitmapDrawable
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
|
@ -16,7 +15,6 @@ import mozilla.components.concept.engine.Engine
|
|||
import mozilla.components.concept.storage.HistoryStorage
|
||||
import mozilla.components.feature.toolbar.ToolbarAutocompleteFeature
|
||||
import mozilla.components.support.ktx.android.content.getColorFromAttr
|
||||
import mozilla.components.support.ktx.android.util.dpToPx
|
||||
import mozilla.components.support.ktx.android.view.hideKeyboard
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.search.SearchFragmentState
|
||||
|
@ -64,8 +62,6 @@ class ToolbarView(
|
|||
view.apply {
|
||||
editMode()
|
||||
|
||||
elevation = TOOLBAR_ELEVATION_IN_DP.dpToPx(resources.displayMetrics).toFloat()
|
||||
|
||||
setOnUrlCommitListener {
|
||||
// We're hiding the keyboard as early as possible to prevent the engine view
|
||||
// from resizing in case the BrowserFragment is being displayed before the
|
||||
|
@ -80,8 +76,6 @@ class ToolbarView(
|
|||
context, ThemeManager.resolveAttribute(R.attr.foundation, context)
|
||||
)
|
||||
|
||||
layoutParams.height = CoordinatorLayout.LayoutParams.MATCH_PARENT
|
||||
|
||||
edit.hint = context.getString(R.string.search_hint)
|
||||
|
||||
edit.colors = edit.colors.copy(
|
||||
|
@ -156,8 +150,4 @@ class ToolbarView(
|
|||
|
||||
view.edit.setIcon(icon, searchState.searchEngineSource.searchEngine.name)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TOOLBAR_ELEVATION_IN_DP = 16
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,8 @@ import org.mozilla.fenix.ext.showToolbar
|
|||
/**
|
||||
* Lets the user customize Private browsing options.
|
||||
*/
|
||||
class SecretSettingsPreference : PreferenceFragmentCompat() {
|
||||
class SecretSettingsFragment : PreferenceFragmentCompat() {
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
showToolbar(getString(R.string.preferences_debug_settings))
|
|
@ -25,13 +25,13 @@ import org.mozilla.fenix.components.metrics.Event
|
|||
import org.mozilla.fenix.crashes.CrashListActivity
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.ext.settings
|
||||
import org.mozilla.fenix.utils.Do
|
||||
import org.mozilla.fenix.settings.SupportUtils
|
||||
import org.mozilla.fenix.settings.about.AboutItemType.LICENSING_INFO
|
||||
import org.mozilla.fenix.settings.about.AboutItemType.PRIVACY_NOTICE
|
||||
import org.mozilla.fenix.settings.about.AboutItemType.RIGHTS
|
||||
import org.mozilla.fenix.settings.about.AboutItemType.SUPPORT
|
||||
import org.mozilla.fenix.settings.about.AboutItemType.WHATS_NEW
|
||||
import org.mozilla.fenix.utils.Do
|
||||
import org.mozilla.fenix.whatsnew.WhatsNew
|
||||
import org.mozilla.geckoview.BuildConfig as GeckoViewBuildConfig
|
||||
|
||||
|
@ -145,39 +145,39 @@ class AboutFragment : Fragment(), AboutPageListener {
|
|||
val context = requireContext()
|
||||
|
||||
return listOf(
|
||||
AboutPageItem.Item(
|
||||
AboutPageItem(
|
||||
AboutItem.ExternalLink(
|
||||
WHATS_NEW,
|
||||
SupportUtils.getWhatsNewUrl(context)
|
||||
), getString(R.string.about_whats_new, getString(R.string.app_name))
|
||||
),
|
||||
AboutPageItem.Item(
|
||||
AboutPageItem(
|
||||
AboutItem.ExternalLink(
|
||||
SUPPORT,
|
||||
SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.HELP)
|
||||
), getString(R.string.about_support)
|
||||
),
|
||||
AboutPageItem.Item(
|
||||
AboutPageItem(
|
||||
AboutItem.Crashes,
|
||||
getString(R.string.about_crashes)
|
||||
),
|
||||
AboutPageItem.Item(
|
||||
AboutPageItem(
|
||||
AboutItem.ExternalLink(
|
||||
PRIVACY_NOTICE,
|
||||
SupportUtils.getMozillaPageUrl(SupportUtils.MozillaPage.PRIVATE_NOTICE)
|
||||
), getString(R.string.about_privacy_notice)
|
||||
),
|
||||
AboutPageItem.Item(
|
||||
AboutPageItem(
|
||||
AboutItem.ExternalLink(
|
||||
RIGHTS,
|
||||
SupportUtils.getSumoURLForTopic(context, SupportUtils.SumoTopic.YOUR_RIGHTS)
|
||||
), getString(R.string.about_know_your_rights)
|
||||
),
|
||||
AboutPageItem.Item(
|
||||
AboutPageItem(
|
||||
AboutItem.ExternalLink(LICENSING_INFO, ABOUT_LICENSE_URL),
|
||||
getString(R.string.about_licensing_information)
|
||||
),
|
||||
AboutPageItem.Item(
|
||||
AboutPageItem(
|
||||
AboutItem.Libraries,
|
||||
getString(R.string.about_other_open_source_libraries)
|
||||
)
|
||||
|
|
|
@ -14,6 +14,4 @@ enum class AboutItemType {
|
|||
WHATS_NEW, SUPPORT, PRIVACY_NOTICE, RIGHTS, LICENSING_INFO
|
||||
}
|
||||
|
||||
sealed class AboutPageItem {
|
||||
data class Item(val type: AboutItem, val title: String) : AboutPageItem()
|
||||
}
|
||||
data class AboutPageItem(val type: AboutItem, val title: String)
|
||||
|
|
|
@ -20,19 +20,16 @@ class AboutPageAdapter(private val listener: AboutPageListener) :
|
|||
}
|
||||
|
||||
override fun onBindViewHolder(holder: AboutItemViewHolder, position: Int) {
|
||||
holder.bind(getItem(position) as AboutPageItem.Item)
|
||||
holder.bind(getItem(position))
|
||||
}
|
||||
|
||||
private object DiffCallback : DiffUtil.ItemCallback<AboutPageItem>() {
|
||||
|
||||
override fun areItemsTheSame(oldItem: AboutPageItem, newItem: AboutPageItem) =
|
||||
oldItem === newItem
|
||||
oldItem.title == newItem.title
|
||||
|
||||
override fun areContentsTheSame(oldItem: AboutPageItem, newItem: AboutPageItem) =
|
||||
when (oldItem) {
|
||||
is AboutPageItem.Item ->
|
||||
newItem is AboutPageItem.Item && oldItem.title == newItem.title
|
||||
}
|
||||
oldItem == newItem
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class AboutItemViewHolder(
|
|||
) : RecyclerView.ViewHolder(view) {
|
||||
|
||||
private val title = view.about_item_title
|
||||
private lateinit var item: AboutPageItem.Item
|
||||
private lateinit var item: AboutPageItem
|
||||
|
||||
init {
|
||||
itemView.setOnClickListener {
|
||||
|
@ -25,7 +25,7 @@ class AboutItemViewHolder(
|
|||
}
|
||||
}
|
||||
|
||||
fun bind(item: AboutPageItem.Item) {
|
||||
fun bind(item: AboutPageItem) {
|
||||
this.item = item
|
||||
title.text = item.title
|
||||
}
|
||||
|
|
|
@ -23,9 +23,8 @@ class LocaleAdapter(private val interactor: LocaleSettingsViewInteractor) :
|
|||
private var selectedLocale: Locale = Locale.getDefault()
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseLocaleViewHolder {
|
||||
val view =
|
||||
LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.locale_settings_item, parent, false)
|
||||
val view = LayoutInflater.from(parent.context)
|
||||
.inflate(R.layout.locale_settings_item, parent, false)
|
||||
|
||||
return when (viewType) {
|
||||
ItemType.DEFAULT.ordinal -> SystemLocaleViewHolder(
|
||||
|
|
|
@ -10,7 +10,7 @@ import android.view.ViewGroup
|
|||
import androidx.core.content.ContextCompat.getColor
|
||||
import androidx.core.view.isVisible
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.quicksettings_website_info.view.*
|
||||
import kotlinx.android.synthetic.main.quicksettings_website_info.*
|
||||
import mozilla.components.support.ktx.android.content.getDrawableWithTint
|
||||
import org.mozilla.fenix.R
|
||||
|
||||
|
@ -19,13 +19,14 @@ import org.mozilla.fenix.R
|
|||
*
|
||||
* Currently it does not support any user interaction.
|
||||
*
|
||||
* @param containerView [ViewGroup] in which this View will inflate itself.
|
||||
* @param container [ViewGroup] in which this View will inflate itself.
|
||||
*/
|
||||
class WebsiteInfoView(
|
||||
override val containerView: ViewGroup
|
||||
container: ViewGroup
|
||||
) : LayoutContainer {
|
||||
val view: View = LayoutInflater.from(containerView.context)
|
||||
.inflate(R.layout.quicksettings_website_info, containerView, true)
|
||||
|
||||
override val containerView: View = LayoutInflater.from(container.context)
|
||||
.inflate(R.layout.quicksettings_website_info, container, true)
|
||||
|
||||
/**
|
||||
* Allows changing what this View displays.
|
||||
|
@ -39,25 +40,25 @@ class WebsiteInfoView(
|
|||
bindCertificateName(state.certificateName)
|
||||
}
|
||||
|
||||
private fun bindUrl(url: String) {
|
||||
view.url.text = url
|
||||
private fun bindUrl(websiteUrl: String) {
|
||||
url.text = websiteUrl
|
||||
}
|
||||
|
||||
private fun bindTitle(title: String) {
|
||||
view.title.text = title
|
||||
private fun bindTitle(websiteTitle: String) {
|
||||
title.text = websiteTitle
|
||||
}
|
||||
|
||||
private fun bindCertificateName(cert: String) {
|
||||
val certificateLabel = view.context.getString(R.string.certificate_info_verified_by, cert)
|
||||
view.certificateInfo.text = certificateLabel
|
||||
view.certificateInfo.isVisible = cert.isNotEmpty()
|
||||
val certificateLabel = containerView.context.getString(R.string.certificate_info_verified_by, cert)
|
||||
certificateInfo.text = certificateLabel
|
||||
certificateInfo.isVisible = cert.isNotEmpty()
|
||||
}
|
||||
|
||||
private fun bindSecurityInfo(uiValues: WebsiteSecurityUiValues) {
|
||||
val tint = getColor(view.context, uiValues.iconTintRes)
|
||||
view.securityInfo.setText(uiValues.securityInfoRes)
|
||||
view.securityInfoIcon.setImageDrawable(
|
||||
view.context.getDrawableWithTint(uiValues.iconRes, tint)
|
||||
val tint = getColor(containerView.context, uiValues.iconTintRes)
|
||||
securityInfo.setText(uiValues.securityInfoRes)
|
||||
securityInfoIcon.setImageDrawable(
|
||||
containerView.context.getDrawableWithTint(uiValues.iconRes, tint)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class NewTabShortcutIntentProcessor : IntentProcessor {
|
|||
* @param intent The intent to process.
|
||||
* @return True if the intent was processed, otherwise false.
|
||||
*/
|
||||
override suspend fun process(intent: Intent): Boolean {
|
||||
override fun process(intent: Intent): Boolean {
|
||||
val safeIntent = SafeIntent(intent)
|
||||
val (searchExtra, startPrivateMode) = when (safeIntent.action) {
|
||||
ACTION_OPEN_TAB -> StartSearchIntentProcessor.STATIC_SHORTCUT_NEW_TAB to false
|
||||
|
|
|
@ -10,11 +10,13 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatDialogFragment
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import kotlinx.android.synthetic.main.component_tabstray.view.*
|
||||
import kotlinx.android.synthetic.main.component_tabstray_fab.view.*
|
||||
import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.*
|
||||
import kotlinx.android.synthetic.main.fragment_tab_tray_dialog.view.*
|
||||
import mozilla.components.browser.session.Session
|
||||
|
@ -31,6 +33,7 @@ import org.mozilla.fenix.HomeActivity
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.FenixSnackbar
|
||||
import org.mozilla.fenix.components.TabCollectionStorage
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.utils.allowUndo
|
||||
|
@ -42,6 +45,10 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
|
|||
private val tabTrayView: TabTrayView
|
||||
get() = _tabTrayView!!
|
||||
|
||||
private val snackbarAnchor: View?
|
||||
get() = if (tabTrayView.fabView.new_tab_button.isVisible) tabTrayView.fabView.new_tab_button
|
||||
else null
|
||||
|
||||
private val collectionStorageObserver = object : TabCollectionStorage.Observer {
|
||||
override fun onCollectionCreated(title: String, sessions: List<Session>) {
|
||||
showCollectionSnackbar()
|
||||
|
@ -54,11 +61,13 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
|
|||
|
||||
private val selectTabUseCase = object : TabsUseCases.SelectTabUseCase {
|
||||
override fun invoke(tabId: String) {
|
||||
requireContext().components.analytics.metrics.track(Event.OpenedExistingTab)
|
||||
requireComponents.useCases.tabsUseCases.selectTab(tabId)
|
||||
navigateToBrowser()
|
||||
}
|
||||
|
||||
override fun invoke(session: Session) {
|
||||
requireContext().components.analytics.metrics.track(Event.OpenedExistingTab)
|
||||
requireComponents.useCases.tabsUseCases.selectTab(session)
|
||||
navigateToBrowser()
|
||||
}
|
||||
|
@ -66,11 +75,13 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
|
|||
|
||||
private val removeTabUseCase = object : TabsUseCases.RemoveTabUseCase {
|
||||
override fun invoke(sessionId: String) {
|
||||
requireContext().components.analytics.metrics.track(Event.ClosedExistingTab)
|
||||
showUndoSnackbarForTab(sessionId)
|
||||
requireComponents.useCases.tabsUseCases.removeTab(sessionId)
|
||||
}
|
||||
|
||||
override fun invoke(session: Session) {
|
||||
requireContext().components.analytics.metrics.track(Event.ClosedExistingTab)
|
||||
showUndoSnackbarForTab(session.id)
|
||||
requireComponents.useCases.tabsUseCases.removeTab(session)
|
||||
}
|
||||
|
@ -134,6 +145,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
|
|||
)
|
||||
|
||||
tabLayout.setOnClickListener {
|
||||
requireContext().components.analytics.metrics.track(Event.TabsTrayClosed)
|
||||
dismissAllowingStateLoss()
|
||||
}
|
||||
|
||||
|
@ -182,7 +194,8 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
|
|||
sessionManager.add(snapshot.session, isSelected, engineSessionState = state)
|
||||
},
|
||||
operation = { },
|
||||
elevation = ELEVATION
|
||||
elevation = ELEVATION,
|
||||
anchorView = snackbarAnchor
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -226,7 +239,8 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
|
|||
context?.components?.core?.sessionManager?.restore(snapshot)
|
||||
},
|
||||
operation = { },
|
||||
elevation = ELEVATION
|
||||
elevation = ELEVATION,
|
||||
anchorView = snackbarAnchor
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +253,7 @@ class TabTrayDialogFragment : AppCompatDialogFragment() {
|
|||
isDisplayedWithBrowserToolbar = true,
|
||||
view = (view as View)
|
||||
)
|
||||
.setAnchorView(snackbarAnchor)
|
||||
.setText(requireContext().getString(R.string.create_collection_tabs_saved))
|
||||
.setAction(requireContext().getString(R.string.create_collection_view)) {
|
||||
dismissAllowingStateLoss()
|
||||
|
|
|
@ -30,6 +30,7 @@ import mozilla.components.browser.state.state.BrowserState
|
|||
import mozilla.components.browser.state.state.TabSessionState
|
||||
import mozilla.components.browser.tabstray.BrowserTabsTray
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.settings
|
||||
|
||||
|
@ -64,6 +65,8 @@ class TabTrayView(
|
|||
get() = container
|
||||
|
||||
init {
|
||||
container.context.components.analytics.metrics.track(Event.TabsTrayOpened)
|
||||
|
||||
val hasAccessibilityEnabled = view.context.settings().accessibilityServicesEnabled
|
||||
|
||||
toggleFabText(isPrivate)
|
||||
|
@ -81,6 +84,7 @@ class TabTrayView(
|
|||
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
|
||||
container.context.components.analytics.metrics.track(Event.TabsTrayClosed)
|
||||
interactor.onTabTrayDismissed()
|
||||
}
|
||||
}
|
||||
|
@ -154,6 +158,7 @@ class TabTrayView(
|
|||
}
|
||||
|
||||
view.tab_tray_overflow.setOnClickListener {
|
||||
container.context.components.analytics.metrics.track(Event.TabsTrayMenuOpened)
|
||||
menu = tabTrayItemMenu.menuBuilder.build(container.context)
|
||||
menu?.show(it)
|
||||
?.also { pu ->
|
||||
|
@ -167,6 +172,7 @@ class TabTrayView(
|
|||
view.tab_tray_new_tab.apply {
|
||||
isVisible = hasAccessibilityEnabled
|
||||
setOnClickListener {
|
||||
sendNewTabEvent(isPrivateModeSelected)
|
||||
interactor.onNewTabTapped(isPrivateModeSelected)
|
||||
}
|
||||
}
|
||||
|
@ -174,11 +180,22 @@ class TabTrayView(
|
|||
fabView.new_tab_button.apply {
|
||||
isVisible = !hasAccessibilityEnabled
|
||||
setOnClickListener {
|
||||
sendNewTabEvent(isPrivateModeSelected)
|
||||
interactor.onNewTabTapped(isPrivateModeSelected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendNewTabEvent(isPrivateModeSelected: Boolean) {
|
||||
val eventToSend = if (isPrivateModeSelected) {
|
||||
Event.NewPrivateTabTapped
|
||||
} else {
|
||||
Event.NewTabTapped
|
||||
}
|
||||
|
||||
container.context.components.analytics.metrics.track(eventToSend)
|
||||
}
|
||||
|
||||
fun expand() {
|
||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||
}
|
||||
|
@ -195,6 +212,12 @@ class TabTrayView(
|
|||
|
||||
updateState(view.context.components.core.store.state)
|
||||
scrollToSelectedTab()
|
||||
|
||||
if (isPrivateModeSelected) {
|
||||
container.context.components.analytics.metrics.track(Event.TabsTrayPrivateModeTapped)
|
||||
} else {
|
||||
container.context.components.analytics.metrics.track(Event.TabsTrayNormalModeTapped)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTabReselected(tab: TabLayout.Tab?) { /*noop*/ }
|
||||
|
@ -294,6 +317,7 @@ class TabTrayItemMenu(
|
|||
context.getString(R.string.tab_tray_menu_item_save),
|
||||
textColorResource = R.color.primary_text_normal_theme
|
||||
) {
|
||||
context.components.analytics.metrics.track(Event.TabsTraySaveToCollectionPressed)
|
||||
onItemTapped.invoke(Item.SaveToCollection)
|
||||
}.apply { visible = shouldShowSaveToCollection },
|
||||
|
||||
|
@ -301,6 +325,7 @@ class TabTrayItemMenu(
|
|||
context.getString(R.string.tab_tray_menu_item_share),
|
||||
textColorResource = R.color.primary_text_normal_theme
|
||||
) {
|
||||
context.components.analytics.metrics.track(Event.TabsTrayShareAllTabsPressed)
|
||||
onItemTapped.invoke(Item.ShareAllTabs)
|
||||
},
|
||||
|
||||
|
@ -308,6 +333,7 @@ class TabTrayItemMenu(
|
|||
context.getString(R.string.tab_tray_menu_item_close),
|
||||
textColorResource = R.color.primary_text_normal_theme
|
||||
) {
|
||||
context.components.analytics.metrics.track(Event.TabsTrayCloseAllTabsPressed)
|
||||
onItemTapped.invoke(Item.CloseAllTabs)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -309,7 +309,7 @@ class Settings private constructor(
|
|||
|
||||
val shouldShowSearchShortcuts by booleanPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_show_search_shortcuts),
|
||||
default = true
|
||||
default = false
|
||||
)
|
||||
|
||||
val shouldUseDarkTheme by booleanPreference(
|
||||
|
@ -775,6 +775,19 @@ class Settings private constructor(
|
|||
default = 0
|
||||
)
|
||||
|
||||
fun setOpenTabsCount(count: Int) {
|
||||
preferences.edit().putInt(
|
||||
appContext.getPreferenceKey(R.string.pref_key_open_tabs_count),
|
||||
count
|
||||
).apply()
|
||||
}
|
||||
|
||||
val openTabsCount: Int
|
||||
get() = preferences.getInt(
|
||||
appContext.getPreferenceKey(R.string.pref_key_open_tabs_count),
|
||||
0
|
||||
)
|
||||
|
||||
private var savedLoginsSortingStrategyString by stringPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_saved_logins_sorting_strategy),
|
||||
default = SavedLoginsFragment.SORTING_STRATEGY_ALPHABETICALLY
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<translate
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="0"
|
||||
android:duration="900" />
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 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/. -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="45"
|
||||
android:startColor="@color/toolbar_start_gradient_private_theme"
|
||||
android:centerColor="@color/toolbar_center_gradient_private_theme"
|
||||
android:endColor="@color/toolbar_end_gradient_private_theme"
|
||||
android:type="linear" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:gravity="top">
|
||||
<shape android:shape="rectangle">
|
||||
<size android:height="1dp" />
|
||||
<solid android:color="@color/neutral_faded_private_theme" />
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
|
@ -46,10 +46,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/displayName"
|
||||
android:layout_alignStart="@id/displayName"
|
||||
android:textColor="?secondaryText"
|
||||
android:maxLines="4"
|
||||
android:text="@string/preferences_account_default_name"
|
||||
android:textColor="?primaryText"
|
||||
app:fontFamily="@font/metropolis_bold" />
|
||||
android:text="@string/preferences_account_default_name" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:minLines="2"
|
||||
android:textAppearance="@style/SubtitleTextStyle"
|
||||
android:textColor="?secondaryText"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="@+id/collection_item"
|
||||
app:layout_constraintStart_toStartOf="@+id/collection_item"
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
android:textAllCaps="false"
|
||||
android:textColor="@color/neutral_text"
|
||||
android:textSize="16sp"
|
||||
android:fontFamily="@font/metropolis_bold"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
|
@ -163,7 +164,7 @@
|
|||
android:text="@string/create_collection_save_to_collection_empty"
|
||||
android:textColor="?neutral"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/metropolis_semibold"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/save_button"
|
||||
app:layout_constraintStart_toEndOf="@id/bottom_bar_icon_button"
|
||||
|
@ -176,7 +177,8 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:text="@string/create_collection_save"
|
||||
android:textColor="?neutral"
|
||||
android:textColor="@color/photonWhite"
|
||||
app:fontFamily="@font/metropolis_medium"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
|
|
@ -140,6 +140,7 @@
|
|||
android:gravity="center_vertical"
|
||||
android:singleLine="true"
|
||||
android:text="@string/create_collection_add_new_collection"
|
||||
android:fontFamily="@font/metropolis"
|
||||
android:textColor="?neutral"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/history_wrapper"
|
||||
android:id="@+id/synced_tabs_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<ProgressBar
|
||||
|
@ -43,7 +43,7 @@
|
|||
android:id="@+id/synced_tabs_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/history_list_item"/>
|
||||
tools:listitem="@layout/sync_tabs_list_item"/>
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -11,38 +11,24 @@
|
|||
android:background="?foundation"
|
||||
tools:context=".search.SearchFragment">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/toolbar_wrapper"
|
||||
<mozilla.components.browser.toolbar.BrowserToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/browser_toolbar_height"
|
||||
android:layout_margin="0dp"
|
||||
android:outlineProvider="paddedBounds"
|
||||
android:background="@drawable/toolbar_background_top"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
app:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"
|
||||
app:browserToolbarClearColor="?primaryText"
|
||||
app:browserToolbarInsecureColor="?primaryText"
|
||||
app:browserToolbarMenuColor="?primaryText"
|
||||
app:browserToolbarProgressBarGravity="bottom"
|
||||
app:browserToolbarSecureColor="?primaryText"
|
||||
app:browserToolbarTrackingProtectionAndSecurityIndicatorSeparatorColor="?toolbarDivider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<mozilla.components.browser.toolbar.BrowserToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/browser_toolbar_height"
|
||||
android:layout_gravity="top"
|
||||
android:background="@drawable/toolbar_background_top"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
app:layout_scrollFlags="scroll|enterAlways|snap|exitUntilCollapsed"
|
||||
app:browserToolbarClearColor="?primaryText"
|
||||
app:browserToolbarInsecureColor="?primaryText"
|
||||
app:browserToolbarMenuColor="?primaryText"
|
||||
app:browserToolbarProgressBarGravity="bottom"
|
||||
app:browserToolbarSecureColor="?primaryText"
|
||||
app:browserToolbarTrackingProtectionAndSecurityIndicatorSeparatorColor="?toolbarDivider"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="0dp"
|
||||
|
@ -51,7 +37,7 @@
|
|||
app:layout_constraintBottom_toBottomOf="@id/search_divider"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar_wrapper">
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/scrollable_area"
|
||||
|
|
|
@ -14,14 +14,14 @@
|
|||
<TextView
|
||||
android:id="@+id/details_blocking_header"
|
||||
style="@style/QuickSettingsText"
|
||||
android:fontFamily="@font/metropolis_bold"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/tracking_protection_item_height"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:text="@string/enhanced_tracking_protection_blocked"
|
||||
android:textStyle="bold" />
|
||||
android:text="@string/enhanced_tracking_protection_blocked" />
|
||||
|
||||
<org.mozilla.fenix.trackingprotection.TrackingProtectionCategoryItem
|
||||
android:id="@+id/category_social_media"
|
||||
|
|
|
@ -20,8 +20,9 @@
|
|||
android:id="@+id/header_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="17sp"
|
||||
android:textSize="14sp"
|
||||
android:textColor="?primaryText"
|
||||
android:fontFamily="@font/metropolis_semibold"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
|
|
|
@ -30,10 +30,8 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="@string/no_collections_description1"
|
||||
android:textColor="?primaryText"
|
||||
android:textSize="14sp"
|
||||
android:textAlignment="viewStart"
|
||||
app:fontFamily="@font/metropolis_medium" />
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/add_tabs_to_collections_button"
|
||||
|
|
|
@ -8,34 +8,31 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="60dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:minHeight="@dimen/library_item_height"
|
||||
android:background="?android:attr/selectableItemBackground">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/synced_tab_item_title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginStart="72dp"
|
||||
android:layout_marginEnd="48dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?primaryText"
|
||||
android:textSize="18sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/synced_tab_item_url"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="Tab Title" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/synced_tab_item_url"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:ellipsize="end"
|
||||
android:layout_marginStart="72dp"
|
||||
android:layout_marginEnd="48dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?secondaryText"
|
||||
|
@ -43,21 +40,18 @@
|
|||
tools:text="https://example.com/"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/synced_tab_item_title"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/synced_tab_item_title" />
|
||||
|
||||
<View
|
||||
android:id="@+id/synced_tab_item_separator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="2dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:background="?syncedTabsSeparator"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:background="?neutralFaded"
|
||||
android:visibility="gone"/>
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/synced_tab_item_url" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -29,10 +29,20 @@
|
|||
android:layout_height="69dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:backgroundTint="?tabTrayThumbnailItemBackground"
|
||||
app:cardBackgroundColor="@color/photonWhite"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/default_tab_thumbnail"
|
||||
android:src="@drawable/mozac_ic_globe"
|
||||
android:tint="?tabTrayThumbnailIcon"
|
||||
android:padding="22dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<mozilla.components.browser.tabstray.thumbnail.TabThumbnailView
|
||||
android:id="@+id/mozac_browser_tabstray_thumbnail"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -2,30 +2,39 @@
|
|||
<!-- 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/. -->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/synced_tabs_group"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/synced_tabs_group_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:drawablePadding="15dp"
|
||||
app:drawableStartCompat="@drawable/mozac_ic_device_desktop"
|
||||
app:drawableTint="?primaryText"
|
||||
android:textSize="17sp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:drawablePadding="32dp"
|
||||
android:textAppearance="@style/Header14TextStyle"
|
||||
android:textColor="?primaryText"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textSize="12sp"
|
||||
android:gravity="center"
|
||||
app:drawableStartCompat="@drawable/mozac_ic_device_desktop"
|
||||
app:drawableTint="?primaryText"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="Header" />
|
||||
|
||||
</RelativeLayout>
|
||||
<View
|
||||
android:id="@+id/synced_tabs_group_separator"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:background="?syncedTabsSeparator"
|
||||
android:importantForAccessibility="no"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintTop_toBottomOf="@+id/synced_tabs_group_name" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
@ -544,7 +544,7 @@
|
|||
android:name="org.mozilla.fenix.settings.about.AboutFragment"/>
|
||||
<fragment
|
||||
android:id="@+id/secretSettingsPreference"
|
||||
android:name="org.mozilla.fenix.settings.SecretSettingsPreference"
|
||||
android:name="org.mozilla.fenix.settings.SecretSettingsFragment"
|
||||
android:label="@string/preferences_debug_settings" />
|
||||
<fragment
|
||||
android:id="@+id/crashReporterFragment"
|
||||
|
|
|
@ -58,12 +58,17 @@
|
|||
<color name="tab_tray_item_media_background_normal_theme">@color/tab_tray_item_media_background_dark_theme</color>
|
||||
<color name="tab_tray_heading_icon_normal_theme">@color/tab_tray_heading_icon_dark_theme</color>
|
||||
<color name="tab_tray_heading_icon_inactive_normal_theme">@color/tab_tray_heading_icon_inactive_dark_theme</color>
|
||||
<color name="tab_tray_item_thumbnail_background_normal_theme">@color/tab_tray_item_thumbnail_background_dark_theme</color>
|
||||
<color name="tab_tray_item_thumbnail_icon_normal_theme">@color/tab_tray_item_thumbnail_icon_dark_theme</color>
|
||||
|
||||
<!--Top site colors -->
|
||||
<color name="top_site_background">@color/top_site_background_dark_theme</color>
|
||||
<color name="top_site_border">@color/top_site_border_dark_theme</color>
|
||||
<color name="top_site_title_text">@color/top_site_title_text_dark_theme</color>
|
||||
|
||||
<!-- Synced tabs colors-->
|
||||
<color name="synced_tabs_separator">@color/synced_tabs_separator_dark_theme</color>
|
||||
|
||||
<!-- Collection icons-->
|
||||
<color name="collection_icon_color_violet">@color/collection_icon_color_violet_dark_theme</color>
|
||||
<color name="collection_icon_color_blue">@color/collection_icon_color_blue_dark_theme</color>
|
||||
|
|
|
@ -1062,24 +1062,139 @@
|
|||
<string name="sign_in_with_camera">Gāyì\'ì sēsiûn ngà si kamarât</string>
|
||||
<!-- Text shown for settings option for sign with email -->
|
||||
<string name="sign_in_with_email">Gārāsun si kōrreôt si lūgaj</string>
|
||||
<!-- Text shown in confirmation dialog to sign out of account -->
|
||||
<string name="sign_out_confirmation_message">Dūnâj Firefox si nāgi\'iaj nūguàn\'anj si kuentât, sanī si dure\'ej nej datô râj sunt ngà aché nunt riña aga\' nan.</string>
|
||||
<!-- Text shown in confirmation dialog to sign out of account. The first parameter is the name of the app (e.g. Firefox Preview) -->
|
||||
<string name="sign_out_confirmation_message_2">Dūnâj %s si nāgi\'iaj nūguàn\'anj si kuentât, sanī si dure\'ej nej datô râj sunt ngà aché nunt riña aga\' nan.</string>
|
||||
<!-- Option to continue signing out of account shown in confirmation dialog to sign out of account -->
|
||||
<string name="sign_out_disconnect">Gāhuī riña internet</string>
|
||||
<!-- Option to cancel signing out shown in confirmation dialog to sign out of account -->
|
||||
<string name="sign_out_cancel">Dūyichin\'</string>
|
||||
|
||||
<!-- Error message snackbar shown after the user tried to select a default folder which cannot be altered -->
|
||||
<string name="bookmark_cannot_edit_root">Sī ga\'ue nādūnāt sa mà riña nej karpetâ ngà nīka \'naj</string>
|
||||
|
||||
<!-- Enhanced Tracking Protection -->
|
||||
<!-- Link displayed in enhanced tracking protection panel to access tracking protection settings -->
|
||||
<string name="etp_settings">Riña gā\'ue nāgi\'iát riña sa dugumî sò\'</string>
|
||||
<!-- Preference title for enhanced tracking protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection">Sa huā hue\'ê doj guendâ nārán riña sa naga\'nāj a</string>
|
||||
<!-- Title for the description of enhanced tracking protection -->
|
||||
<string name="preference_enhanced_tracking_protection_explanation_title">Nitāj gà\' \'ngō ganikò\' sò\' si gāchē nunt</string>
|
||||
<!-- Description of enhanced tracking protection. The first parameter is the name of the application (For example: Fenix) -->
|
||||
<string name="preference_enhanced_tracking_protection_explanation">Duguminj nej si datôt. %s naran rayi\'ît riña nej sa naga\'nāj sa \'iát nga aché nunt.</string>
|
||||
<!-- Text displayed that links to website about enhanced tracking protection -->
|
||||
<string name="preference_enhanced_tracking_protection_explanation_learn_more">Gāhuin chrūn doj</string>
|
||||
|
||||
<!-- Preference for enhanced tracking protection for the standard protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection_standard_default_1">Sa huā chre\' (dàj huaj \'naj)</string>
|
||||
<!-- Preference description for enhanced tracking protection for the standard protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection_standard_description_3">Riña dòj sa naga\'nāj a naran. Dàj rû\' nayi\'nïnj riña pâjina nāyi\'nïn nīñanj.</string>
|
||||
<!-- Accessibility text for the Standard protection information icon -->
|
||||
<string name="preference_enhanced_tracking_protection_standard_info_button">Ahuin si riñā narán sa dugumî sò\' \'na\' niñā guendâ nej sa naga\'nāj a</string>
|
||||
<!-- Preference for enhanced tracking protection for the strict protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection_strict">Sa nùkuaj doj</string>
|
||||
|
||||
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection_strict_description_2">Narán man riña doj sa naga\'nāj a, nej nuguan\' nata\'a nī nej bēntanâ narugui\' man\'an. Hìo doj nayî\'nïnj riña nej pâjina, sanī huā sa sī ga\'ue gi\'iaj sun hue\'e.</string>
|
||||
<!-- Accessibility text for the Strict protection information icon -->
|
||||
<string name="preference_enhanced_tracking_protection_strict_info_button">Ahuin si riñā narán sa nùkuaj doj dugumî sò\' \'na\' niñā guendâ nej sa naga\'nāj a</string>
|
||||
<!-- Preference for enhanced tracking protection for the custom protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection_custom">Nāgi\'iaj mun\'ûn\'</string>
|
||||
<!-- Preference description for enhanced tracking protection for the strict protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection_custom_description_2">Nāguī nej sa naga\'nāj a asi a\'ngô sa riñā ruhuât naránt.</string>
|
||||
<!-- Accessibility text for the Strict protection information icon -->
|
||||
<string name="preference_enhanced_tracking_protection_custom_info_button">Nan huin sa riñā narán sa dugumî sò\' \'na\' niñā guendâ nej sa naga\'nāj a</string>
|
||||
<!-- Header for categories that are being blocked by current Enhanced Tracking Protection settings -->
|
||||
<!-- Preference for enhanced tracking protection for the custom protection settings for cookies-->
|
||||
<string name="preference_enhanced_tracking_protection_custom_cookies">Nej kôki</string>
|
||||
<!-- Option for enhanced tracking protection for the custom protection settings for cookies-->
|
||||
<string name="preference_enhanced_tracking_protection_custom_cookies_1">Sa naga\'nāj riña nej sîtio nī nej rêd sociâl</string>
|
||||
<!-- Option for enhanced tracking protection for the custom protection settings for cookies-->
|
||||
<string name="preference_enhanced_tracking_protection_custom_cookies_2">Si kokî nej sitiô nu atûjt</string>
|
||||
<!-- Option for enhanced tracking protection for the custom protection settings for cookies-->
|
||||
<string name="preference_enhanced_tracking_protection_custom_cookies_3">Daran\' nej kokî ânej e (ga\'ue gī\'iaj sun a\'nan\' web gī\'ia)</string>
|
||||
<!-- Option for enhanced tracking protection for the custom protection settings for cookies-->
|
||||
<string name="preference_enhanced_tracking_protection_custom_cookies_4">Daran\' nej kokî (ga\'ue dūre\'ej dā\'āj sîtio)</string>
|
||||
<!-- Preference for enhanced tracking protection for the custom protection settings for tracking content -->
|
||||
<string name="preference_enhanced_tracking_protection_custom_tracking_content">Sa nīkāj sa naga\'nāj a</string>
|
||||
<!-- Option for enhanced tracking protection for the custom protection settings for tracking content-->
|
||||
<string name="preference_enhanced_tracking_protection_custom_tracking_content_1">Riña daran\' nej rakïj ñanj</string>
|
||||
<!-- Option for enhanced tracking protection for the custom protection settings for tracking content-->
|
||||
<string name="preference_enhanced_tracking_protection_custom_tracking_content_2">Màn riña nej rakïj ñanj huìi</string>
|
||||
<!-- Option for enhanced tracking protection for the custom protection settings for tracking content-->
|
||||
<string name="preference_enhanced_tracking_protection_custom_tracking_content_3">Màn riña nej rakïj ñanj nagi\'iaj mān\'ânt</string>
|
||||
<!-- Preference for enhanced tracking protection for the custom protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection_custom_cryptominers">Nej kriptominêro</string>
|
||||
<!-- Preference for enhanced tracking protection for the custom protection settings -->
|
||||
<string name="preference_enhanced_tracking_protection_custom_fingerprinters">Nej da\'nga\' rā\'a</string>
|
||||
<string name="enhanced_tracking_protection_blocked">Nitāj si hūaj nāyi\'nïn</string>
|
||||
<!-- Header for categories that are being not being blocked by current Enhanced Tracking Protection settings -->
|
||||
<string name="enhanced_tracking_protection_allowed">Gā\'ue</string>
|
||||
|
||||
<!-- Category of trackers (social media trackers) that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_social_media_trackers_title">Nej sa naga\'nāj nej rêd sosiâl</string>
|
||||
|
||||
<!-- Description of social media trackers that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_social_media_trackers_description">Sī ga\'nïnjt riña nej rêd sōsiâl da\' nāga\'nāj nìko sa \'iát ngà aché nunt.</string>
|
||||
<!-- Category of trackers (cross-site tracking cookies) that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_cookies_title">Nej kokî naga\'nāj riña nej dūguì\' nej sîtio</string>
|
||||
|
||||
<!-- Description of cross-site tracking cookies that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_cookies_description">Nārán riña nej kokî arâj sun nej rêd duyinga\' sa ane\'e nī nej dukuâ sun nadigi\'ñûn sa anïn ruhuâ guìi da\' si naga\'nāj nìko man nej sa \'iát nga aché nunt.</string>
|
||||
<!-- Category of trackers (cryptominers) that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_cryptominers_title">Nej kriptominêro</string>
|
||||
<!-- Description of cryptominers that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_cryptominers_description">Nu â\'nïn riña nej skripts yi\'ìi da\' gātū nej man riña si āgâ\'t nī gīrī nej man san\'ānj nānèe.</string>
|
||||
<!-- Category of trackers (fingerprinters) that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_fingerprinters_title">Nej sa nani\'in nej da\'nga\' rā\'a</string>
|
||||
<!-- Description of fingerprinters that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_fingerprinters_description">Nu â\'nïn da\' sī nari a\'ngô sa yi\'ìi nej nuguan\' nīkāj si āgâ\'t nī ga\'ue nāga\'nāj nej man sò\'.</string>
|
||||
<!-- Category of trackers (tracking content) that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_tracking_content_title">Sa nīkāj sa naga\'nāj a</string>
|
||||
|
||||
<!-- Description of tracking content that can be blocked by Enhanced Tracking Protection -->
|
||||
<string name="etp_tracking_content_description">Naran riña nej nuguan\' duyinga\' nej sa ane\'e, sa ni\'io\' nī riña nej nuguan\' nīkāj sa naga\'nāj a. Ga\'ue gā\'uì\' yī\'ij dàj \'iaj sun nej sîtio.</string>
|
||||
<!-- Enhanced Tracking Protection Onboarding Message shown in a dialog above the toolbar. The first parameter is the name of the application (For example: Fenix) -->
|
||||
<string name="etp_onboarding_cfr_message">Da\' nanûn kolô dînda riña eskûdo, ngà narán %s sa naga\'nāj riña \'ngō sitio. Gūru\'man ra\'a da\' gīni\'înt doj sa huā rayi\'î man.</string>
|
||||
<!-- Enhanced Tracking Protection message that protection is currently on for this site -->
|
||||
<string name="etp_panel_on">Ngà \'IAJ SUN nej sa dugumî sò\' riña sitiô nan</string>
|
||||
<!-- Enhanced Tracking Protection message that protection is currently off for this site -->
|
||||
<string name="etp_panel_off">NITĀJ SI \'IAJ SUN nej sa dugumî sò\' riña sitiô nan</string>
|
||||
|
||||
<!-- Header for exceptions list for which sites enhanced tracking protection is always off -->
|
||||
<string name="enhanced_tracking_protection_exceptions">Nitāj si \'iaj sun sa nùkuaj narán riña sa naga\'nāj a riña nej sitiô nan</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): Navigate
|
||||
back from ETP details (Ex: Tracking content) -->
|
||||
<string name="etp_back_button_content_description">Gūij ne\' rūkùu</string>
|
||||
<!-- About page Your rights link text -->
|
||||
<string name="about_your_rights">Nej nuguan\' tna\'uēj rayi\'ît</string>
|
||||
<!-- About page link text to open open source licenses screen -->
|
||||
<string name="about_open_source_licenses">Dukuâ ñanj nīkāj kodigô huā nî\'nïnj arân sun ñûnj</string>
|
||||
<!-- About page link text to open what's new link -->
|
||||
<string name="about_whats_new">Sa nākà doj huā riña %s</string>
|
||||
<!-- Open source licenses page title
|
||||
The first parameter is the app name -->
|
||||
<string name="open_source_licenses_title">%s Dukuâ ñanj OSS</string>
|
||||
|
||||
<!-- About page link text to open support link -->
|
||||
<string name="about_support">Sa rugûñu\'ūnj un</string>
|
||||
<!-- About page link text to list of past crashes (like about:crashes on desktop) -->
|
||||
<string name="about_crashes">Nej sa gahui a\'nan\'</string>
|
||||
<!-- About page link text to open privacy notice link -->
|
||||
<string name="about_privacy_notice">Nuguan\' huì huin si dūkuan</string>
|
||||
|
||||
<!-- About page link text to open know your rights link -->
|
||||
<string name="about_know_your_rights">Gīni\'in nej nuguan\' tna\'uēj rayi\'ît</string>
|
||||
<!-- About page link text to open licensing information link -->
|
||||
<string name="about_licensing_information">Si nùguàn\' līsênsia</string>
|
||||
<!-- About page link text to open a screen with libraries that are used -->
|
||||
<string name="about_other_open_source_libraries">Nej dukuâ ñanj arâj sun ñûnj</string>
|
||||
<!-- Toast shown to the user when they are activating the secret dev menu
|
||||
The first parameter is number of long clicks left to enable the menu -->
|
||||
<string name="about_debug_menu_toast_progress">Menû nagi\'aj hìo: gūru\'man ra\'a %1$d da\' nāchrūnt</string>
|
||||
<string name="about_debug_menu_toast_done">Menû nagi\'aj hìo ngà \'iaj sun</string>
|
||||
|
||||
<!-- Content description of the tab counter toolbar button when one tab is open -->
|
||||
<string name="tab_counter_content_description_one_tab">1 rakïj ñanj</string>
|
||||
<!-- Content description of the tab counter toolbar button when multiple tabs are open. First parameter will be replaced with the number of tabs (always more than one) -->
|
||||
|
@ -1088,22 +1203,58 @@
|
|||
<!-- Browser long press popup menu -->
|
||||
<!-- Copy the current url -->
|
||||
<string name="browser_toolbar_long_press_popup_copy">Gūxūn nī nāchrūnt a\'ngô hiūj u</string>
|
||||
<!-- Paste & go the text in the clipboard. '&' is replaced with the ampersand symbol: & -->
|
||||
<string name="browser_toolbar_long_press_popup_paste_and_go">Gāchrūn & Gūij</string>
|
||||
<!-- Paste the text in the clipboard -->
|
||||
<string name="browser_toolbar_long_press_popup_paste">Gāchrūn</string>
|
||||
|
||||
<!-- Snackbar message shown after an URL has been copied to clipboard. -->
|
||||
<string name="browser_toolbar_url_copied_to_clipboard_snackbar">URL ngà nachîn riña portapapeles</string>
|
||||
|
||||
<!-- Title text for the Add To Homescreen dialog -->
|
||||
<string name="add_to_homescreen_title">Gāchrūn man riña pantâya</string>
|
||||
<!-- Cancel button text for the Add to Homescreen dialog -->
|
||||
<string name="add_to_homescreen_cancel">Dūyichin\'</string>
|
||||
<!-- Add button text for the Add to Homescreen dialog -->
|
||||
<string name="add_to_homescreen_add">Nūtà\'</string>
|
||||
|
||||
<!-- Continue to website button text for the first-time Add to Homescreen dialog -->
|
||||
<string name="add_to_homescreen_continue">Ginu ngè riña sitiô nan</string>
|
||||
<!-- Placeholder text for the TextView in the Add to Homescreen dialog -->
|
||||
<string name="add_to_homescreen_text_placeholder">Si yūgui aksêso dīrêkto</string>
|
||||
|
||||
<!-- Describes the add to homescreen functionality -->
|
||||
<string name="add_to_homescreen_description">Gā\'ue nāchrūnt sitiô nan riña pajinâ ayi\'ìt riña aga\' a\'min nīkājt da\' ga\'ue hìo gātūt riñanj dàj rû\' \'iaj \'ngō aplikāsiûn</string>
|
||||
|
||||
<!-- Preference for managing the settings for logins and passwords in Fenix -->
|
||||
<string name="preferences_passwords_logins_and_passwords">Nej riña gayi\'ìt sēsiûn nī nej da\'nga\' huìi</string>
|
||||
<!-- Preference for managing the saving of logins and passwords in Fenix -->
|
||||
<string name="preferences_passwords_save_logins">Nā\'nïnj sà\' nej riña gayi\'ìt sēsiûn nī nej da\'nga\' huìi</string>
|
||||
<!-- Preference option for asking to save passwords in Fenix -->
|
||||
<string name="preferences_passwords_save_logins_ask_to_save">Gāchìnj nì\'iaj nā\'nïnj sà\'t</string>
|
||||
<!-- Preference option for never saving passwords in Fenix -->
|
||||
<string name="preferences_passwords_save_logins_never_save">Nitāj āmān nā\'nïnj sà\'t</string>
|
||||
<!-- Preference for autofilling saved logins in Fenix -->
|
||||
<string name="preferences_passwords_autofill">Nāchra man\'an</string>
|
||||
<!-- Preference for syncing saved logins in Fenix -->
|
||||
<string name="preferences_passwords_sync_logins">Nāgi\'iaj nūguàn\'àn nej riña ayì\'ìt sēsiûn</string>
|
||||
<!-- Syncing saved logins in Fenix is on -->
|
||||
<string name="preferences_passwords_sync_logins_on">Nāchrūn</string>
|
||||
<!-- Syncing saved logins in Fenix is off -->
|
||||
<string name="preferences_passwords_sync_logins_off">Dūnâ\’àj</string>
|
||||
|
||||
<!-- Syncing saved logins in Fenix needs reconnect to sync -->
|
||||
<string name="preferences_passwords_sync_logins_reconnect">Gānātū ñû</string>
|
||||
<!-- Syncing saved logins in Fenix needs login -->
|
||||
<string name="preferences_passwords_sync_logins_sign_in">Gāyi\'ì sēsiûn riña Sync</string>
|
||||
<!-- Preference to access list of saved logins -->
|
||||
<string name="preferences_passwords_saved_logins">Sa gayi\'ìt sesiûn ngà naginu sà\'</string>
|
||||
<!-- Learn more link that will link to a page with more information displayed when a connection is insecure and we detect the user is entering a password -->
|
||||
<string name="logins_insecure_connection_warning_learn_more">Gāhuin chrūn doj</string>
|
||||
|
||||
<!-- Positive confirmation that Fenix should save the new or updated login -->
|
||||
<string name="logins_doorhanger_save_confirmation">Nā\'nïnj sà\'</string>
|
||||
|
||||
<!-- Content description (not visible, for screen readers etc.): Title for the button to add a search engine in the action bar -->
|
||||
<string name="search_engine_add_button_content_description">Nūtà\'</string>
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
<attr name="addOnPrivateBrowsingInteriorIconBackground" format="reference"/>
|
||||
<attr name="readerModeStartGradient" format="reference"/>
|
||||
<attr name="readerModeEndGradient" format="reference"/>
|
||||
<attr name="syncedTabsSeparator" format="reference"/>
|
||||
|
||||
<!-- Tab tray -->
|
||||
<attr name="tabTrayItemBackground" format="reference" />
|
||||
|
@ -59,6 +60,8 @@
|
|||
<attr name="tabTrayItemMediaBackground" format="reference" />
|
||||
<attr name="tabTrayHeadingIcon" format="reference" />
|
||||
<attr name="tabTrayHeadingIconInactive" format="reference" />
|
||||
<attr name="tabTrayThumbnailItemBackground" format="reference" />
|
||||
<attr name="tabTrayThumbnailIcon" format="reference" />
|
||||
|
||||
<declare-styleable name="TrackingProtectionCategory">
|
||||
<attr name="categoryItemTitle" format="reference" />
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
<color name="dark_grey_90_gradient_end">#0015141A</color>
|
||||
<color name="top_site_background_light_theme">@android:color/white</color>
|
||||
<color name="top_site_border_light_theme">@color/light_grey_30</color>
|
||||
<color name="synced_tabs_separator_light_theme">@color/light_grey_30</color>
|
||||
<color name="top_site_title_text_light_theme">@color/light_grey_80</color>
|
||||
<color name="collection_icon_color_violet_light_theme">#7542E5</color>
|
||||
<color name="collection_icon_color_blue_light_theme">#0250BB</color>
|
||||
|
@ -82,6 +83,8 @@
|
|||
<color name="tab_tray_item_media_background_light_theme">#312A65</color>
|
||||
<color name="tab_tray_heading_icon_light_theme">@color/ink_20</color>
|
||||
<color name="tab_tray_heading_icon_inactive_light_theme">@color/ink_20_48a</color>
|
||||
<color name="tab_tray_item_thumbnail_background_light_theme">@color/light_grey_10</color>
|
||||
<color name="tab_tray_item_thumbnail_icon_light_theme">@color/light_grey_60</color>
|
||||
|
||||
<!-- Dark theme color palette -->
|
||||
<color name="primary_text_dark_theme">#FBFBFE</color>
|
||||
|
@ -104,6 +107,7 @@
|
|||
<color name="scrimEnd_dark_theme">#F515141A</color>
|
||||
<color name="top_site_background_dark_theme">@color/dark_grey_50</color>
|
||||
<color name="top_site_border_dark_theme">@color/dark_grey_10</color>
|
||||
<color name="synced_tabs_separator_dark_theme">@color/dark_grey_10</color>
|
||||
<color name="top_site_title_text_dark_theme">@color/light_grey_90</color>
|
||||
<color name="collection_icon_color_violet_dark_theme">#AB71FF</color>
|
||||
<color name="collection_icon_color_blue_dark_theme">#00B3F4</color>
|
||||
|
@ -138,6 +142,8 @@
|
|||
<color name="tab_tray_item_media_background_dark_theme">#9059FF</color>
|
||||
<color name="tab_tray_heading_icon_dark_theme">@color/violet_50</color>
|
||||
<color name="tab_tray_heading_icon_inactive_dark_theme">@color/violet_50_48a</color>
|
||||
<color name="tab_tray_item_thumbnail_background_dark_theme">@color/dark_grey_50</color>
|
||||
<color name="tab_tray_item_thumbnail_icon_dark_theme">@color/dark_grey_05</color>
|
||||
|
||||
<!-- Private theme color palette -->
|
||||
<color name="primary_text_private_theme">#FBFBFE</color>
|
||||
|
@ -241,6 +247,8 @@
|
|||
<color name="tab_tray_item_media_background_normal_theme">@color/tab_tray_item_media_background_light_theme</color>
|
||||
<color name="tab_tray_heading_icon_normal_theme">@color/tab_tray_heading_icon_light_theme</color>
|
||||
<color name="tab_tray_heading_icon_inactive_normal_theme">@color/tab_tray_heading_icon_inactive_light_theme</color>
|
||||
<color name="tab_tray_item_thumbnail_background_normal_theme">@color/tab_tray_item_thumbnail_background_light_theme</color>
|
||||
<color name="tab_tray_item_thumbnail_icon_normal_theme">@color/tab_tray_item_thumbnail_icon_light_theme</color>
|
||||
|
||||
<!-- Bookmark buttons -->
|
||||
<color name="bookmark_favicon_background">#DFDFE3</color>
|
||||
|
@ -250,6 +258,9 @@
|
|||
<color name="top_site_border">@color/top_site_border_light_theme</color>
|
||||
<color name="top_site_title_text">@color/top_site_title_text_light_theme</color>
|
||||
|
||||
<!-- Synced tabs colors-->
|
||||
<color name="synced_tabs_separator">@color/synced_tabs_separator_light_theme</color>
|
||||
|
||||
<!-- Collection icons-->
|
||||
<color name="collection_icon_color_violet">@color/collection_icon_color_violet_light_theme</color>
|
||||
<color name="collection_icon_color_blue">@color/collection_icon_color_blue_light_theme</color>
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
<dimen name="search_fragment_clipboard_item_horizontal_margin">12dp</dimen>
|
||||
<dimen name="search_fragment_clipboard_item_vertical_margin">8dp</dimen>
|
||||
<dimen name="search_fragment_clipboard_item_title_margin_start">8dp</dimen>
|
||||
<dimen name="search_fragment_shortcuts_label_margin_horizontal">8dp</dimen>
|
||||
<dimen name="search_fragment_shortcuts_label_margin_horizontal">18dp</dimen>
|
||||
<dimen name="search_fragment_shortcuts_label_margin_vertical">18dp</dimen>
|
||||
<dimen name="search_fragment_pill_height">40dp</dimen>
|
||||
<dimen name="search_fragment_pill_padding_start">20dp</dimen>
|
||||
|
|
|
@ -177,6 +177,8 @@
|
|||
|
||||
<string name="pref_key_debug_settings" translatable="false">pref_key_debug_settings</string>
|
||||
|
||||
<string name="pref_key_open_tabs_count" translatable="false">pref_key_open_tabs_count</string>
|
||||
|
||||
<string name="pref_key_search_count" translatable="false">pref_key_search_count</string>
|
||||
<string name="pref_key_search_widget_cfr_display_count" translatable="false">pref_key_search_widget_cfr_display_count</string>
|
||||
<string name="pref_key_search_widget_cfr_dismiss_count" translatable="false">pref_key_search_widget_cfr_dismiss_count</string>
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<item name="alertDialogStyle">@style/DialogStyleNormal</item>
|
||||
<item name="alertDialogTheme">@style/DialogStyleNormal</item>
|
||||
<item name="android:windowEnableSplitTouch">false</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:splitMotionEvents">false</item>
|
||||
|
||||
<item name="mozacInputLayoutErrorTextColor"
|
||||
|
@ -75,7 +76,7 @@
|
|||
<item name="mozacPromptLoginEditTextCursorColor">@color/prompt_login_edit_text_cursor_color_normal_theme</item>
|
||||
<item name="readerModeStartGradient">@color/readermode_start_gradient_normal_theme</item>
|
||||
<item name="readerModeEndGradient">@color/readermode_end_gradient_normal_theme</item>
|
||||
|
||||
<item name="syncedTabsSeparator">@color/synced_tabs_separator</item>
|
||||
|
||||
<item name="tabTrayItemBackground">@color/tab_tray_item_background_normal_theme</item>
|
||||
<item name="tabTrayItemSelectedBackground">@color/tab_tray_item_selected_background_normal_theme</item>
|
||||
|
@ -83,6 +84,8 @@
|
|||
<item name="tabTrayItemMediaBackground">@color/tab_tray_item_media_background_normal_theme</item>
|
||||
<item name="tabTrayHeadingIcon">@color/tab_tray_heading_icon_normal_theme</item>
|
||||
<item name="tabTrayHeadingIconInactive">@color/tab_tray_heading_icon_inactive_normal_theme</item>
|
||||
<item name="tabTrayThumbnailItemBackground">@color/tab_tray_item_thumbnail_background_normal_theme</item>
|
||||
<item name="tabTrayThumbnailIcon">@color/tab_tray_item_thumbnail_icon_normal_theme</item>
|
||||
|
||||
<!-- Drawables -->
|
||||
<item name="fenixLogo">@drawable/ic_logo_wordmark_normal</item>
|
||||
|
@ -208,6 +211,8 @@
|
|||
<item name="tabTrayItemMediaBackground">@color/tab_tray_item_media_background_private_theme</item>
|
||||
<item name="tabTrayHeadingIcon">@color/tab_tray_heading_icon_dark_theme</item>
|
||||
<item name="tabTrayHeadingIconInactive">@color/tab_tray_heading_icon_inactive_dark_theme</item>
|
||||
<item name="tabTrayThumbnailItemBackground">@color/tab_tray_item_thumbnail_background_normal_theme</item>
|
||||
<item name="tabTrayThumbnailIcon">@color/tab_tray_item_thumbnail_icon_normal_theme</item>
|
||||
|
||||
<!-- Drawables -->
|
||||
<item name="fenixLogo">@drawable/ic_logo_wordmark_private</item>
|
||||
|
@ -445,7 +450,7 @@
|
|||
</style>
|
||||
|
||||
<style name="SearchShortcutsLabelStyle">
|
||||
<item name="android:fontFamily">Inter UI</item>
|
||||
<item name="android:fontFamily">@font/metropolis_semibold</item>
|
||||
<item name="android:letterSpacing">0.15</item>
|
||||
<item name="android:textAllCaps">true</item>
|
||||
<item name="android:textColor">?secondaryText</item>
|
||||
|
@ -480,6 +485,7 @@
|
|||
<item name="android:minHeight">40dp</item>
|
||||
<item name="android:layout_marginTop">32dp</item>
|
||||
<item name="android:textColor">?accentUsedOnDarkBackground</item>
|
||||
<item name="android:fontFamily">@font/metropolis_semibold</item>
|
||||
</style>
|
||||
|
||||
<style name="ShareHeaderTextStyle">
|
||||
|
|
|
@ -39,6 +39,6 @@ class MigrationDecisionActivity : Activity() {
|
|||
// and then we switch to the actual activity without an animation. This visually looks like
|
||||
// a faster start than launching this activity invisibly and switching to the actual
|
||||
// activity after that.
|
||||
overridePendingTransition(0, 0)
|
||||
overridePendingTransition(0, R.anim.placeholder_animation)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,11 @@ import org.junit.Test
|
|||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class TelemetrySessionObserverTest {
|
||||
|
||||
private val settings: Settings = mockk(relaxed = true)
|
||||
private val owner: LifecycleOwner = mockk(relaxed = true)
|
||||
private val sessionManager: SessionManager = mockk(relaxed = true)
|
||||
private val metrics: MetricController = mockk(relaxed = true)
|
||||
|
@ -29,7 +31,7 @@ class TelemetrySessionObserverTest {
|
|||
@Before
|
||||
fun setup() {
|
||||
singleSessionObserver =
|
||||
UriOpenedObserver(owner, sessionManager, metrics, ads).singleSessionObserver
|
||||
UriOpenedObserver(settings, owner, sessionManager, metrics, ads).singleSessionObserver
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -11,11 +11,13 @@ import mozilla.components.browser.session.Session
|
|||
import mozilla.components.browser.session.SessionManager
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
|
||||
import org.mozilla.fenix.components.metrics.MetricController
|
||||
import org.mozilla.fenix.search.telemetry.ads.AdsTelemetry
|
||||
import org.mozilla.fenix.utils.Settings
|
||||
|
||||
class UriOpenedObserverTest {
|
||||
|
||||
private val settings: Settings = mockk(relaxed = true)
|
||||
private val owner: LifecycleOwner = mockk(relaxed = true)
|
||||
private val sessionManager: SessionManager = mockk(relaxed = true)
|
||||
private val metrics: MetricController = mockk()
|
||||
|
@ -24,7 +26,7 @@ class UriOpenedObserverTest {
|
|||
|
||||
@Before
|
||||
fun setup() {
|
||||
observer = UriOpenedObserver(owner, sessionManager, metrics, ads)
|
||||
observer = UriOpenedObserver(settings, owner, sessionManager, metrics, ads)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -100,7 +100,7 @@ class IntentProcessorTypeTest {
|
|||
@Test
|
||||
fun `get type for generic intent processor`() {
|
||||
val processor = object : IntentProcessor {
|
||||
override suspend fun process(intent: Intent) = true
|
||||
override fun process(intent: Intent) = true
|
||||
}
|
||||
val type = testContext.components.intentProcessors.getType(processor)
|
||||
|
||||
|
|
|
@ -119,6 +119,21 @@ class FakeFenixSearchEngineProvider(context: Context) : FenixSearchEngineProvide
|
|||
)
|
||||
}
|
||||
|
||||
override val fallbackEngines: Deferred<SearchEngineList>
|
||||
get() {
|
||||
val google = mockSearchEngine(id = "google-b-1-m", n = "Google")
|
||||
|
||||
return CompletableDeferred(
|
||||
SearchEngineList(
|
||||
listOf(
|
||||
google,
|
||||
mockSearchEngine("bing", "Bing"),
|
||||
mockSearchEngine("amazondotcom", "Amazon.com")
|
||||
), default = google
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override val bundledSearchEngines = CompletableDeferred(
|
||||
SearchEngineList(
|
||||
listOf(
|
||||
|
|
|
@ -150,6 +150,10 @@ class DefaultSearchControllerTest {
|
|||
@Test
|
||||
fun `show search shortcuts when setting enabled AND query empty`() {
|
||||
val text = ""
|
||||
testContext.settings().preferences
|
||||
.edit()
|
||||
.putBoolean(testContext.getString(R.string.pref_key_show_search_shortcuts), true)
|
||||
.apply()
|
||||
|
||||
controller.handleTextChanged(text)
|
||||
|
||||
|
@ -160,6 +164,10 @@ class DefaultSearchControllerTest {
|
|||
fun `show search shortcuts when setting enabled AND query equals url`() {
|
||||
val text = "mozilla.org"
|
||||
every { session?.url } returns "mozilla.org"
|
||||
testContext.settings().preferences
|
||||
.edit()
|
||||
.putBoolean(testContext.getString(R.string.pref_key_show_search_shortcuts), true)
|
||||
.apply()
|
||||
|
||||
assertEquals(text, session?.url)
|
||||
|
||||
|
|
|
@ -17,20 +17,21 @@ import mozilla.components.support.test.robolectric.testContext
|
|||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.settings.about.viewholders.AboutItemViewHolder
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
import org.mozilla.fenix.settings.about.viewholders.AboutItemViewHolder
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class AboutPageAdapterTest {
|
||||
private var aboutList: List<AboutPageItem> =
|
||||
mutableListOf(
|
||||
AboutPageItem.Item(
|
||||
private val aboutList: List<AboutPageItem> =
|
||||
listOf(
|
||||
AboutPageItem(
|
||||
AboutItem.ExternalLink(
|
||||
AboutItemType.WHATS_NEW,
|
||||
"https://mozilla.org"
|
||||
), "Libraries"
|
||||
),
|
||||
AboutPageItem.Item(AboutItem.Libraries, "Libraries")
|
||||
AboutPageItem(AboutItem.Libraries, "Libraries"),
|
||||
AboutPageItem(AboutItem.Crashes, "Crashes")
|
||||
)
|
||||
private val listener: AboutPageListener = mockk(relaxed = true)
|
||||
|
||||
|
@ -47,7 +48,7 @@ class AboutPageAdapterTest {
|
|||
|
||||
adapter.submitList(aboutList)
|
||||
|
||||
assertEquals(2, adapter.itemCount)
|
||||
assertEquals(3, adapter.itemCount)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -78,6 +79,6 @@ class AboutPageAdapterTest {
|
|||
adapter.submitList(aboutList)
|
||||
adapter.bindViewHolder(viewHolder, 1)
|
||||
|
||||
verify { viewHolder.bind(aboutList[1] as AboutPageItem.Item) }
|
||||
verify { viewHolder.bind(aboutList[1]) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.mozilla.fenix.settings.about.AboutPageListener
|
|||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class AboutItemViewHolderTest {
|
||||
|
||||
private val item = AboutPageItem.Item(AboutItem.Libraries, "Libraries")
|
||||
private val item = AboutPageItem(AboutItem.Libraries, "Libraries")
|
||||
private lateinit var view: View
|
||||
private lateinit var listener: AboutPageListener
|
||||
|
||||
|
|
|
@ -6,10 +6,13 @@ package org.mozilla.fenix.settings.account
|
|||
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.NavDestination
|
||||
import io.mockk.Called
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.verify
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.mozilla.fenix.R
|
||||
|
||||
|
@ -34,6 +37,7 @@ class AccountSettingsInteractorTest {
|
|||
@Test
|
||||
fun onChangeDeviceName() {
|
||||
val store: AccountSettingsFragmentStore = mockk(relaxed = true)
|
||||
val invalidNameResponse = mockk<() -> Unit>(relaxed = true)
|
||||
|
||||
val interactor = AccountSettingsInteractor(
|
||||
mockk(),
|
||||
|
@ -42,9 +46,28 @@ class AccountSettingsInteractorTest {
|
|||
store
|
||||
)
|
||||
|
||||
interactor.onChangeDeviceName("New Name") {}
|
||||
assertTrue(interactor.onChangeDeviceName("New Name", invalidNameResponse))
|
||||
|
||||
verify { store.dispatch(AccountSettingsFragmentAction.UpdateDeviceName("New Name")) }
|
||||
verify { invalidNameResponse wasNot Called }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun onChangeDeviceNameSyncFalse() {
|
||||
val store: AccountSettingsFragmentStore = mockk(relaxed = true)
|
||||
val invalidNameResponse = mockk<() -> Unit>(relaxed = true)
|
||||
|
||||
val interactor = AccountSettingsInteractor(
|
||||
mockk(),
|
||||
mockk(),
|
||||
{ false },
|
||||
store
|
||||
)
|
||||
|
||||
assertFalse(interactor.onChangeDeviceName("New Name", invalidNameResponse))
|
||||
|
||||
verify { store wasNot Called }
|
||||
verify { invalidNameResponse() }
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/* 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.fenix.settings.quicksettings
|
||||
|
||||
import android.widget.FrameLayout
|
||||
import androidx.core.view.isVisible
|
||||
import kotlinx.android.synthetic.main.library_site_item.title
|
||||
import kotlinx.android.synthetic.main.library_site_item.url
|
||||
import kotlinx.android.synthetic.main.quicksettings_website_info.*
|
||||
import mozilla.components.support.test.robolectric.testContext
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mozilla.fenix.helpers.FenixRobolectricTestRunner
|
||||
|
||||
@RunWith(FenixRobolectricTestRunner::class)
|
||||
class WebsiteInfoViewTest {
|
||||
|
||||
private lateinit var view: WebsiteInfoView
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
view = WebsiteInfoView(FrameLayout(testContext))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bindUrlAndTitle() {
|
||||
view.update(WebsiteInfoState(
|
||||
websiteUrl = "https://mozilla.org",
|
||||
websiteTitle = "Mozilla",
|
||||
websiteSecurityUiValues = WebsiteSecurityUiValues.SECURE,
|
||||
certificateName = ""
|
||||
))
|
||||
|
||||
assertEquals("https://mozilla.org", view.url.text)
|
||||
assertEquals("Mozilla", view.title.text)
|
||||
assertEquals("Secure Connection", view.securityInfo.text)
|
||||
assertFalse(view.certificateInfo.isVisible)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun bindCert() {
|
||||
view.update(WebsiteInfoState(
|
||||
websiteUrl = "https://mozilla.org",
|
||||
websiteTitle = "Mozilla",
|
||||
websiteSecurityUiValues = WebsiteSecurityUiValues.INSECURE,
|
||||
certificateName = "Certificate"
|
||||
))
|
||||
|
||||
assertEquals("Insecure Connection", view.securityInfo.text)
|
||||
assertEquals("Verified By: Certificate", view.certificateInfo.text)
|
||||
assertTrue(view.certificateInfo.isVisible)
|
||||
}
|
||||
}
|
|
@ -254,7 +254,7 @@ class SettingsTest {
|
|||
fun shouldShowSearchShortcuts() {
|
||||
// When just created
|
||||
// Then
|
||||
assertTrue(settings.shouldShowSearchShortcuts)
|
||||
assertFalse(settings.shouldShowSearchShortcuts)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
object AndroidComponents {
|
||||
const val VERSION = "48.0.20200626130049"
|
||||
const val VERSION = "48.0.20200626213814"
|
||||
}
|
||||
|
|
435
docs/metrics.md
435
docs/metrics.md
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue