Copione merged onto master
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
commit
5419c2b08b
|
@ -29,6 +29,8 @@ import org.mozilla.fenix.ui.robots.DeepLinkRobot
|
|||
* - fenix://urls_bookmarks — take the user to the bookmarks list
|
||||
* - fenix://settings_logins — take the user to the settings page to do with logins (not the saved logins).
|
||||
**/
|
||||
|
||||
@Ignore("All tests perma-failing, see: https://github.com/mozilla-mobile/fenix/issues/13491")
|
||||
class DeepLinkTest {
|
||||
private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
private lateinit var mockWebServer: MockWebServer
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import mozilla.components.browser.engine.gecko.autofill.GeckoLoginDelegateWrapper
|
||||
import mozilla.components.browser.engine.gecko.ext.toContentBlockingSetting
|
||||
import mozilla.components.browser.engine.gecko.glean.GeckoAdapter
|
||||
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy
|
||||
import mozilla.components.concept.storage.LoginsStorage
|
||||
|
@ -50,8 +51,7 @@ object GeckoProvider {
|
|||
val runtimeSettings = builder
|
||||
.crashHandler(CrashHandlerService::class.java)
|
||||
.telemetryDelegate(GeckoAdapter())
|
||||
// TODO: Fix me!
|
||||
// .contentBlocking(policy.toContentBlockingSetting())
|
||||
.contentBlocking(policy.toContentBlockingSetting())
|
||||
.aboutConfigEnabled(Config.channel.isBeta)
|
||||
.debugLogging(Config.channel.isDebug)
|
||||
.build()
|
||||
|
|
|
@ -28,7 +28,14 @@ class AppRequestInterceptor(private val context: Context) : RequestInterceptor {
|
|||
): RequestInterceptor.InterceptionResponse? {
|
||||
return context.components.services.appLinksInterceptor
|
||||
.onLoadRequest(
|
||||
engineSession, uri, lastUri, hasUserGesture, isSameDomain, isRedirect, isDirectNavigation, isSubframeRequest
|
||||
engineSession,
|
||||
uri,
|
||||
lastUri,
|
||||
hasUserGesture,
|
||||
isSameDomain,
|
||||
isRedirect,
|
||||
isDirectNavigation,
|
||||
isSubframeRequest
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -48,4 +48,9 @@ object FeatureFlags {
|
|||
* Enables wait til first contentful paint
|
||||
*/
|
||||
val waitUntilPaintToDraw = Config.channel.isNightlyOrDebug
|
||||
|
||||
/**
|
||||
* Enables downloads with external download managers.
|
||||
*/
|
||||
val externalDownloadManager = Config.channel.isNightlyOrDebug
|
||||
}
|
||||
|
|
|
@ -252,10 +252,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
|||
lifecycleScope.launch(IO) {
|
||||
if (
|
||||
settings().isDefaultBrowser() &&
|
||||
settings().wasDefaultBrowserOnLastPause != settings().isDefaultBrowser()
|
||||
settings().wasDefaultBrowserOnLastResume != settings().isDefaultBrowser()
|
||||
) {
|
||||
metrics.track(Event.ChangedToDefaultBrowser)
|
||||
}
|
||||
|
||||
settings().wasDefaultBrowserOnLastResume = settings().isDefaultBrowser()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -264,11 +266,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
|||
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||
}
|
||||
|
||||
if (settings().wasDefaultBrowserOnLastPause != settings().isDefaultBrowser()
|
||||
) {
|
||||
settings().wasDefaultBrowserOnLastPause = settings().isDefaultBrowser()
|
||||
}
|
||||
|
||||
super.onPause()
|
||||
|
||||
// Every time the application goes into the background, it is possible that the user
|
||||
|
|
|
@ -21,6 +21,7 @@ import androidx.fragment.app.Fragment
|
|||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.fragment_browser.*
|
||||
import kotlinx.android.synthetic.main.fragment_browser.view.*
|
||||
|
@ -41,7 +42,6 @@ import mozilla.components.browser.state.selector.findTabOrCustomTabOrSelectedTab
|
|||
import mozilla.components.browser.state.state.SessionState
|
||||
import mozilla.components.browser.state.state.content.DownloadState
|
||||
import mozilla.components.browser.state.store.BrowserStore
|
||||
import mozilla.components.browser.thumbnails.BrowserThumbnails
|
||||
import mozilla.components.concept.engine.prompt.ShareData
|
||||
import mozilla.components.feature.accounts.FxaCapability
|
||||
import mozilla.components.feature.accounts.FxaWebChannelFeature
|
||||
|
@ -99,6 +99,7 @@ import org.mozilla.fenix.downloads.DynamicDownloadDialog
|
|||
import org.mozilla.fenix.ext.accessibilityManager
|
||||
import org.mozilla.fenix.ext.components
|
||||
import org.mozilla.fenix.ext.enterToImmersiveMode
|
||||
import org.mozilla.fenix.ext.getPreferenceKey
|
||||
import org.mozilla.fenix.ext.hideToolbar
|
||||
import org.mozilla.fenix.ext.metrics
|
||||
import org.mozilla.fenix.ext.nav
|
||||
|
@ -138,7 +139,6 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
private val appLinksFeature = ViewBoundFeatureWrapper<AppLinksFeature>()
|
||||
private val promptsFeature = ViewBoundFeatureWrapper<PromptFeature>()
|
||||
private val findInPageIntegration = ViewBoundFeatureWrapper<FindInPageIntegration>()
|
||||
private val thumbnailsFeature = ViewBoundFeatureWrapper<BrowserThumbnails>()
|
||||
private val toolbarIntegration = ViewBoundFeatureWrapper<ToolbarIntegration>()
|
||||
private val sitePermissionsFeature = ViewBoundFeatureWrapper<SitePermissionsFeature>()
|
||||
private val fullScreenFeature = ViewBoundFeatureWrapper<FullScreenFeature>()
|
||||
|
@ -279,12 +279,6 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
lifecycleOwner = viewLifecycleOwner
|
||||
)
|
||||
|
||||
thumbnailsFeature.set(
|
||||
feature = BrowserThumbnails(context, view.engineView, store),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
toolbarIntegration.set(
|
||||
feature = browserToolbarView.toolbarIntegration,
|
||||
owner = this,
|
||||
|
@ -346,6 +340,11 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
view = view
|
||||
)
|
||||
|
||||
val shouldForwardToThirdParties =
|
||||
PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
|
||||
context.getPreferenceKey(R.string.pref_key_external_download_manager), false
|
||||
)
|
||||
|
||||
val downloadFeature = DownloadsFeature(
|
||||
context.applicationContext,
|
||||
store = store,
|
||||
|
@ -357,6 +356,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
store,
|
||||
DownloadService::class
|
||||
),
|
||||
shouldForwardToThirdParties = { shouldForwardToThirdParties },
|
||||
promptsStyling = DownloadsFeature.PromptsStyling(
|
||||
gravity = Gravity.BOTTOM,
|
||||
shouldWidthMatchParent = true,
|
||||
|
@ -586,7 +586,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
.ifChanged { it.content.firstContentfulPaint }
|
||||
.collect {
|
||||
val showEngineView =
|
||||
it.content.firstContentfulPaint || it.content.progress == 100
|
||||
it.content.firstContentfulPaint || it.content.progress == LOADING_PROGRESS_COMPLETE
|
||||
|
||||
if (showEngineView) {
|
||||
engineView?.asView()?.isVisible = true
|
||||
|
@ -804,11 +804,8 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Session
|
|||
}
|
||||
|
||||
override fun onBackLongPressed(): Boolean {
|
||||
if (FeatureFlags.tabHistory) {
|
||||
findNavController().navigate(R.id.action_global_tabHistoryDialogFragment)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
findNavController().navigate(R.id.action_global_tabHistoryDialogFragment)
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1074,6 +1071,8 @@ 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 LOADING_PROGRESS_COMPLETE = 100
|
||||
}
|
||||
|
||||
override fun onAccessibilityStateChanged(enabled: Boolean) {
|
||||
|
|
|
@ -42,7 +42,7 @@ class BrowserAnimator(
|
|||
if (unwrappedSwipeRefresh?.context?.settings()?.waitToShowPageUntilFirstPaint == true) {
|
||||
if (firstContentfulHappened()) {
|
||||
viewLifecycleScope.get()?.launch {
|
||||
delay(100)
|
||||
delay(ANIMATION_DELAY)
|
||||
unwrappedEngineView?.asView()?.visibility = View.VISIBLE
|
||||
unwrappedSwipeRefresh?.background = null
|
||||
unwrappedSwipeRefresh?.alpha = 1f
|
||||
|
@ -91,6 +91,8 @@ class BrowserAnimator(
|
|||
}
|
||||
|
||||
companion object {
|
||||
private const val ANIMATION_DELAY = 100L
|
||||
|
||||
fun getToolbarNavOptions(context: Context): NavOptions {
|
||||
val navOptions = NavOptions.Builder()
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import kotlinx.android.synthetic.main.fragment_browser.view.*
|
|||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import mozilla.components.browser.session.Session
|
||||
import mozilla.components.browser.state.selector.findTab
|
||||
import mozilla.components.browser.thumbnails.BrowserThumbnails
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.feature.app.links.AppLinksUseCases
|
||||
import mozilla.components.feature.contextmenu.ContextMenuCandidate
|
||||
|
@ -55,6 +56,7 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
|
||||
private val windowFeature = ViewBoundFeatureWrapper<WindowFeature>()
|
||||
private val searchFeature = ViewBoundFeatureWrapper<SearchFeature>()
|
||||
private val thumbnailsFeature = ViewBoundFeatureWrapper<BrowserThumbnails>()
|
||||
|
||||
private var readerModeAvailable = false
|
||||
|
||||
|
@ -107,6 +109,12 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
|||
|
||||
browserToolbarView.view.addPageAction(readerModeAction)
|
||||
|
||||
thumbnailsFeature.set(
|
||||
feature = BrowserThumbnails(context, view.engineView, components.core.store),
|
||||
owner = this,
|
||||
view = view
|
||||
)
|
||||
|
||||
readerViewFeature.set(
|
||||
feature = StrictMode.allowThreadDiskReads().resetPoliciesAfter {
|
||||
ReaderViewFeature(
|
||||
|
|
|
@ -35,6 +35,7 @@ import kotlin.math.min
|
|||
* Handles intercepting touch events on the toolbar for swipe gestures and executes the
|
||||
* necessary animations.
|
||||
*/
|
||||
@Suppress("LargeClass", "TooManyFunctions")
|
||||
class ToolbarGestureHandler(
|
||||
private val activity: Activity,
|
||||
private val contentLayout: View,
|
||||
|
@ -76,6 +77,7 @@ class ToolbarGestureHandler(
|
|||
GestureDirection.LEFT_TO_RIGHT
|
||||
}
|
||||
|
||||
@Suppress("ComplexCondition")
|
||||
return if (
|
||||
!activity.window.decorView.isKeyboardVisible() &&
|
||||
start.isInToolbar() &&
|
||||
|
|
|
@ -95,6 +95,7 @@ class LeanplumMetricsService(
|
|||
deviceId
|
||||
}
|
||||
|
||||
@Suppress("ComplexMethod")
|
||||
override fun start() {
|
||||
|
||||
if (!application.settings().isMarketingTelemetryEnabled) return
|
||||
|
@ -255,7 +256,7 @@ class LeanplumMetricsService(
|
|||
"jpn" // Japanese
|
||||
)
|
||||
|
||||
private val PREFERENCE_NAME = "LEANPLUM_PREFERENCES"
|
||||
private val DEVICE_ID_KEY = "LP_DEVICE_ID"
|
||||
private const val PREFERENCE_NAME = "LEANPLUM_PREFERENCES"
|
||||
private const val DEVICE_ID_KEY = "LP_DEVICE_ID"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,6 +140,7 @@ internal class ReleaseMetricController(
|
|||
MetricServiceType.Marketing -> isMarketingDataTelemetryEnabled()
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun Fact.toEvent(): Event? = when (Pair(component, item)) {
|
||||
Component.FEATURE_PROMPTS to LoginDialogFacts.Items.DISPLAY -> Event.LoginDialogPromptDisplayed
|
||||
Component.FEATURE_PROMPTS to LoginDialogFacts.Items.CANCEL -> Event.LoginDialogPromptCancelled
|
||||
|
|
|
@ -23,7 +23,6 @@ import mozilla.components.concept.engine.prompt.ShareData
|
|||
import mozilla.components.feature.session.SessionFeature
|
||||
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
|
||||
import mozilla.components.support.ktx.kotlin.isUrl
|
||||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.NavGraphDirections
|
||||
import org.mozilla.fenix.R
|
||||
|
@ -204,14 +203,18 @@ class DefaultBrowserToolbarController(
|
|||
trackToolbarItemInteraction(item)
|
||||
|
||||
Do exhaustive when (item) {
|
||||
ToolbarMenu.Item.Back -> sessionUseCases.goBack.invoke(currentSession)
|
||||
is ToolbarMenu.Item.Forward -> {
|
||||
if (FeatureFlags.tabHistory && item.viewHistory) {
|
||||
is ToolbarMenu.Item.Back -> {
|
||||
if (item.viewHistory) {
|
||||
navController.navigate(R.id.action_global_tabHistoryDialogFragment)
|
||||
} else if (!item.viewHistory) {
|
||||
sessionUseCases.goForward.invoke(currentSession)
|
||||
} else {
|
||||
// Do nothing if tab history feature flag is off and item.viewHistory is true
|
||||
sessionUseCases.goBack.invoke(currentSession)
|
||||
}
|
||||
}
|
||||
is ToolbarMenu.Item.Forward -> {
|
||||
if (item.viewHistory) {
|
||||
navController.navigate(R.id.action_global_tabHistoryDialogFragment)
|
||||
} else {
|
||||
sessionUseCases.goForward.invoke(currentSession)
|
||||
}
|
||||
}
|
||||
is ToolbarMenu.Item.Reload -> {
|
||||
|
@ -383,7 +386,7 @@ class DefaultBrowserToolbarController(
|
|||
@Suppress("ComplexMethod")
|
||||
private fun trackToolbarItemInteraction(item: ToolbarMenu.Item) {
|
||||
val eventItem = when (item) {
|
||||
ToolbarMenu.Item.Back -> Event.BrowserMenuItemTapped.Item.BACK
|
||||
is ToolbarMenu.Item.Back -> Event.BrowserMenuItemTapped.Item.BACK
|
||||
is ToolbarMenu.Item.Forward -> Event.BrowserMenuItemTapped.Item.FORWARD
|
||||
is ToolbarMenu.Item.Reload -> Event.BrowserMenuItemTapped.Item.RELOAD
|
||||
ToolbarMenu.Item.Stop -> Event.BrowserMenuItemTapped.Item.STOP
|
||||
|
|
|
@ -250,8 +250,10 @@ class BrowserToolbarView(
|
|||
private const val TOOLBAR_ELEVATION = 16
|
||||
}
|
||||
|
||||
@Suppress("ComplexCondition")
|
||||
private fun ToolbarMenu.Item.performHapticIfNeeded(view: View) {
|
||||
if (this is ToolbarMenu.Item.Reload && this.bypassCache ||
|
||||
this is ToolbarMenu.Item.Back && this.viewHistory ||
|
||||
this is ToolbarMenu.Item.Forward && this.viewHistory
|
||||
) {
|
||||
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
|
||||
|
|
|
@ -74,6 +74,20 @@ class DefaultToolbarMenu(
|
|||
}
|
||||
|
||||
override val menuToolbar by lazy {
|
||||
val back = BrowserMenuItemToolbar.TwoStateButton(
|
||||
primaryImageResource = mozilla.components.ui.icons.R.drawable.mozac_ic_back,
|
||||
primaryContentDescription = context.getString(R.string.browser_menu_back),
|
||||
primaryImageTintResource = primaryTextColor(),
|
||||
isInPrimaryState = {
|
||||
session?.canGoBack ?: true
|
||||
},
|
||||
secondaryImageTintResource = ThemeManager.resolveAttribute(R.attr.disabled, context),
|
||||
disableInSecondaryState = true,
|
||||
longClickListener = { onItemTapped.invoke(ToolbarMenu.Item.Back(viewHistory = true)) }
|
||||
) {
|
||||
onItemTapped.invoke(ToolbarMenu.Item.Back(viewHistory = false))
|
||||
}
|
||||
|
||||
val forward = BrowserMenuItemToolbar.TwoStateButton(
|
||||
primaryImageResource = mozilla.components.ui.icons.R.drawable.mozac_ic_forward,
|
||||
primaryContentDescription = context.getString(R.string.browser_menu_forward),
|
||||
|
@ -135,7 +149,7 @@ class DefaultToolbarMenu(
|
|||
onItemTapped.invoke(ToolbarMenu.Item.Bookmark)
|
||||
}
|
||||
|
||||
BrowserMenuItemToolbar(listOf(bookmark, share, forward, refresh))
|
||||
BrowserMenuItemToolbar(listOf(back, forward, bookmark, share, refresh))
|
||||
}
|
||||
|
||||
// Predicates that need to be repeatedly called as the session changes
|
||||
|
|
|
@ -13,7 +13,7 @@ interface ToolbarMenu {
|
|||
data class RequestDesktop(val isChecked: Boolean) : Item()
|
||||
object FindInPage : Item()
|
||||
object Share : Item()
|
||||
object Back : Item()
|
||||
data class Back(val viewHistory: Boolean) : Item()
|
||||
data class Forward(val viewHistory: Boolean) : Item()
|
||||
data class Reload(val bypassCache: Boolean) : Item()
|
||||
object Stop : Item()
|
||||
|
|
|
@ -59,9 +59,10 @@ class CustomTabToolbarMenu(
|
|||
R.attr.disabled,
|
||||
context
|
||||
),
|
||||
disableInSecondaryState = true
|
||||
disableInSecondaryState = true,
|
||||
longClickListener = { onItemTapped.invoke(ToolbarMenu.Item.Back(viewHistory = true)) }
|
||||
) {
|
||||
onItemTapped.invoke(ToolbarMenu.Item.Back)
|
||||
onItemTapped.invoke(ToolbarMenu.Item.Back(viewHistory = false))
|
||||
}
|
||||
|
||||
val forward = BrowserMenuItemToolbar.TwoStateButton(
|
||||
|
|
|
@ -232,7 +232,10 @@ class DefaultSessionControlController(
|
|||
}
|
||||
|
||||
override fun handleCollectionShareTabsClicked(collection: TabCollection) {
|
||||
showShareFragment(collection.tabs.map { ShareData(url = it.url, title = it.title) })
|
||||
showShareFragment(
|
||||
collection.title,
|
||||
collection.tabs.map { ShareData(url = it.url, title = it.title) }
|
||||
)
|
||||
metrics.track(Event.CollectionShared)
|
||||
}
|
||||
|
||||
|
@ -366,8 +369,9 @@ class DefaultSessionControlController(
|
|||
showTabTrayCollectionCreation()
|
||||
}
|
||||
|
||||
private fun showShareFragment(data: List<ShareData>) {
|
||||
private fun showShareFragment(shareSubject: String, data: List<ShareData>) {
|
||||
val directions = HomeFragmentDirections.actionGlobalShareFragment(
|
||||
shareSubject = shareSubject,
|
||||
data = data.toTypedArray()
|
||||
)
|
||||
navController.nav(R.id.homeFragment, directions)
|
||||
|
|
|
@ -29,6 +29,7 @@ import mozilla.components.support.ktx.android.content.hasCamera
|
|||
import org.mozilla.fenix.BrowserDirection
|
||||
import org.mozilla.fenix.Config
|
||||
import org.mozilla.fenix.HomeActivity
|
||||
import org.mozilla.fenix.FeatureFlags
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.metrics.Event
|
||||
import org.mozilla.fenix.ext.application
|
||||
|
@ -301,7 +302,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
private fun setupPreferences() {
|
||||
val leakKey = getPreferenceKey(R.string.pref_key_leakcanary)
|
||||
val debuggingKey = getPreferenceKey(R.string.pref_key_remote_debugging)
|
||||
|
||||
val preferenceExternalDownloadManager = requirePreference<Preference>(R.string.pref_key_make_default_browser)
|
||||
val preferenceLeakCanary = findPreference<Preference>(leakKey)
|
||||
val preferenceRemoteDebugging = findPreference<Preference>(debuggingKey)
|
||||
val preferenceMakeDefaultBrowser = requirePreference<Preference>(R.string.pref_key_make_default_browser)
|
||||
|
@ -314,6 +315,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
|||
}
|
||||
}
|
||||
|
||||
preferenceExternalDownloadManager.isVisible = FeatureFlags.externalDownloadManager
|
||||
preferenceRemoteDebugging?.setOnPreferenceChangeListener<Boolean> { preference, newValue ->
|
||||
preference.context.settings().preferences.edit()
|
||||
.putBoolean(preference.key, newValue).apply()
|
||||
|
|
|
@ -55,6 +55,7 @@ interface ShareController {
|
|||
* Default behavior of [ShareController]. Other implementations are possible.
|
||||
*
|
||||
* @param context [Context] used for various Android interactions.
|
||||
* @param shareSubject desired message subject used when sharing through 3rd party apps, like email clients.
|
||||
* @param shareData the list of [ShareData]s that can be shared.
|
||||
* @param sendTabUseCases instance of [SendTabUseCases] which allows sending tabs to account devices.
|
||||
* @param snackbar - instance of [FenixSnackbar] for displaying styled snackbars
|
||||
|
@ -64,6 +65,7 @@ interface ShareController {
|
|||
@Suppress("TooManyFunctions")
|
||||
class DefaultShareController(
|
||||
private val context: Context,
|
||||
private val shareSubject: String?,
|
||||
private val shareData: List<ShareData>,
|
||||
private val sendTabUseCases: SendTabUseCases,
|
||||
private val snackbar: FenixSnackbar,
|
||||
|
@ -90,7 +92,7 @@ class DefaultShareController(
|
|||
|
||||
val intent = Intent(ACTION_SEND).apply {
|
||||
putExtra(EXTRA_TEXT, getShareText())
|
||||
putExtra(EXTRA_SUBJECT, shareData.map { it.title }.joinToString(", "))
|
||||
putExtra(EXTRA_SUBJECT, getShareSubject())
|
||||
type = "text/plain"
|
||||
flags = FLAG_ACTIVITY_NEW_TASK
|
||||
setClassName(app.packageName, app.activityName)
|
||||
|
@ -189,6 +191,9 @@ class DefaultShareController(
|
|||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun getShareSubject() = shareSubject ?: shareData.map { it.title }.joinToString(", ")
|
||||
|
||||
// Navigation between app fragments uses ShareTab as arguments. SendTabUseCases uses TabData.
|
||||
@VisibleForTesting
|
||||
internal fun List<ShareData>.toTabData() = map { data ->
|
||||
|
|
|
@ -67,6 +67,7 @@ class ShareFragment : AppCompatDialogFragment() {
|
|||
shareInteractor = ShareInteractor(
|
||||
DefaultShareController(
|
||||
context = requireContext(),
|
||||
shareSubject = args.shareSubject,
|
||||
shareData = shareData,
|
||||
snackbar = FenixSnackbar.make(
|
||||
view = requireActivity().getRootView()!!,
|
||||
|
|
|
@ -34,18 +34,25 @@ class TabHistoryView(
|
|||
|
||||
private val adapter = TabHistoryAdapter(interactor)
|
||||
private val layoutManager = object : LinearLayoutManager(containerView.context) {
|
||||
|
||||
private var shouldScrollToSelected = true
|
||||
|
||||
override fun onLayoutCompleted(state: RecyclerView.State?) {
|
||||
super.onLayoutCompleted(state)
|
||||
currentIndex?.let { index ->
|
||||
// Force expansion of the dialog, otherwise scrolling to the current history item
|
||||
// won't work when its position is near the bottom of the recyclerview.
|
||||
expandDialog.invoke()
|
||||
// Also, attempt to center the current history item.
|
||||
val itemView = tabHistoryRecyclerView.findViewHolderForLayoutPosition(
|
||||
findFirstCompletelyVisibleItemPosition()
|
||||
)?.itemView
|
||||
val offset = tabHistoryRecyclerView.height / 2 - (itemView?.height ?: 0) / 2
|
||||
scrollToPositionWithOffset(index, offset)
|
||||
// Attempt to center the current history item after the first layout is completed,
|
||||
// but not after subsequent layouts
|
||||
if (shouldScrollToSelected) {
|
||||
// Force expansion of the dialog, otherwise scrolling to the current history item
|
||||
// won't work when its position is near the bottom of the recyclerview.
|
||||
expandDialog.invoke()
|
||||
val itemView = tabHistoryRecyclerView.findViewHolderForLayoutPosition(
|
||||
findFirstCompletelyVisibleItemPosition()
|
||||
)?.itemView
|
||||
val offset = tabHistoryRecyclerView.height / 2 - (itemView?.height ?: 0) / 2
|
||||
scrollToPositionWithOffset(index, offset)
|
||||
shouldScrollToSelected = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}.apply {
|
||||
|
|
|
@ -33,7 +33,9 @@ class TabHistoryViewHolder(
|
|||
history_layout.loadFavicon(item.url)
|
||||
|
||||
if (item.isSelected) {
|
||||
history_layout.setBackgroundColor(history_layout.context.getColorFromAttr(R.attr.tabHistoryItemSelectedBackground))
|
||||
history_layout.setBackgroundColor(
|
||||
history_layout.context.getColorFromAttr(R.attr.tabHistoryItemSelectedBackground)
|
||||
)
|
||||
} else {
|
||||
history_layout.background = null
|
||||
}
|
||||
|
|
|
@ -8,7 +8,11 @@ import mozilla.components.support.ktx.android.content.PreferencesHolder
|
|||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
fun featureFlagPreference(key: String, default: Boolean, featureFlag: Boolean): ReadWriteProperty<PreferencesHolder, Boolean> =
|
||||
fun featureFlagPreference(
|
||||
key: String,
|
||||
default: Boolean,
|
||||
featureFlag: Boolean
|
||||
): ReadWriteProperty<PreferencesHolder, Boolean> =
|
||||
FeatureFlagPreferencePreference(key, default, featureFlag)
|
||||
|
||||
private class FeatureFlagPreferencePreference(
|
||||
|
|
|
@ -340,7 +340,7 @@ class Settings(private val appContext: Context) : PreferencesHolder {
|
|||
* Caches the last known "is default browser" state when the app was paused.
|
||||
* For an up to do date state use `isDefaultBrowser` instead.
|
||||
*/
|
||||
var wasDefaultBrowserOnLastPause by booleanPreference(
|
||||
var wasDefaultBrowserOnLastResume by booleanPreference(
|
||||
appContext.getPreferenceKey(R.string.pref_key_default_browser),
|
||||
default = isDefaultBrowser()
|
||||
)
|
||||
|
|
|
@ -53,7 +53,8 @@
|
|||
app:layout_constraintStart_toEndOf="@id/icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/url"
|
||||
app:layout_constraintVertical_chainStyle="packed"/>
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_goneMarginEnd="@dimen/library_item_icon_margin_horizontal" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/url"
|
||||
|
@ -69,7 +70,8 @@
|
|||
app:layout_constraintEnd_toStartOf="@id/overflow_menu"
|
||||
app:layout_constraintStart_toEndOf="@id/icon"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_goneMarginEnd="@dimen/library_item_icon_margin_horizontal" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/overflow_menu"
|
||||
|
|
|
@ -677,6 +677,11 @@
|
|||
android:defaultValue="null"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="shareSubject"
|
||||
android:defaultValue="@null"
|
||||
app:argType="string"
|
||||
app:nullable="true" />
|
||||
</dialog>
|
||||
<dialog
|
||||
android:id="@+id/quickSettingsSheetDialogFragment"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<resources>
|
||||
|
||||
<!-- App name for private browsing mode. The first parameter is the name of the app defined in app_name (for example: Fenix)-->
|
||||
<string name="app_name_private_5">Privado %s</string>
|
||||
<string name="app_name_private_5">%s privado</string>
|
||||
<!-- App name for private browsing mode. The first parameter is the name of the app defined in app_name (for example: Fenix)-->
|
||||
<string name="app_name_private_4">%s (Privado)</string>
|
||||
<!-- Home Fragment -->
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
<!-- Message announced to the user when tab tray is selected with 0 or 2+ tabs -->
|
||||
<string name="open_tab_tray_plural">%1$s pestañas abiertas. Tocar para cambiar de pestaña.</string>
|
||||
|
||||
<!-- Content description for checkmark while tab is selected while in multiselect mode in tab tray. The first parameter is the title of the tab selected -->
|
||||
<string name="tab_tray_item_selected_multiselect_content_description">%1$s seleccionado</string>
|
||||
|
||||
<!-- About content. The first parameter is the name of the application. (For example: Fenix) -->
|
||||
<string name="about_content">%1$s es producido por Mozilla.</string>
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
<string name="tab_tray_collection_button_multiselect_content_description">Tallenna valitut välilehdet kokoelmaan</string>
|
||||
<!-- Content description for checkmark while tab is selected while in multiselect mode in tab tray. The first parameter is the title of the tab selected -->
|
||||
<string name="tab_tray_item_selected_multiselect_content_description">Valittu %1$s</string>
|
||||
<!-- Content description when tab is unselected while in multiselect mode in tab tray. The first parameter is the title of the tab unselected -->
|
||||
<string name="tab_tray_item_unselected_multiselect_content_description">Kumottu valinta %1$s</string>
|
||||
<!-- Content description announcement when exiting multiselect mode in tab tray -->
|
||||
<string name="tab_tray_exit_multiselect_content_description">Poistuttiin monivalintatilasta</string>
|
||||
<!-- Content description announcement when entering multiselect mode in tab tray -->
|
||||
|
|
|
@ -37,9 +37,18 @@
|
|||
<string name="tab_tray_close_multiselect_content_description">मल्टीसेलेक्ट मोड से बाहर निकलें</string>
|
||||
<!-- Content description for save to collection button while in multiselect mode in tab tray -->
|
||||
<string name="tab_tray_collection_button_multiselect_content_description">चुने गए टैब को संग्रह में सहेजें</string>
|
||||
<!-- Content description for checkmark while tab is selected while in multiselect mode in tab tray. The first parameter is the title of the tab selected -->
|
||||
<string name="tab_tray_item_selected_multiselect_content_description">%1$s चयनित</string>
|
||||
<!-- Content description when tab is unselected while in multiselect mode in tab tray. The first parameter is the title of the tab unselected -->
|
||||
<string name="tab_tray_item_unselected_multiselect_content_description">%1$s अचयनित</string>
|
||||
<!-- Content description announcement when exiting multiselect mode in tab tray -->
|
||||
<string name="tab_tray_exit_multiselect_content_description">मल्टीसेलेक्ट मोड से बाहर निकल चुके</string>
|
||||
|
||||
<!-- Content description announcement when entering multiselect mode in tab tray -->
|
||||
<string name="tab_tray_enter_multiselect_content_description">मल्टीसेलेक्ट मोड में दाखिल, संग्रह में सहेजने के लिए टैबों को चुनें</string>
|
||||
<!-- Content description on checkmark while tab is selected in multiselect mode in tab tray -->
|
||||
<string name="tab_tray_multiselect_selected_content_description">चयनित</string>
|
||||
|
||||
<!-- About content. The first parameter is the name of the application. (For example: Fenix) -->
|
||||
<string name="about_content">%1$s को Mozilla द्वारा निर्मित किया गया है।</string>
|
||||
|
||||
|
@ -165,8 +174,8 @@
|
|||
<!-- Search Fragment -->
|
||||
<!-- Button in the search view that lets a user search by scanning a QR code -->
|
||||
<string name="search_scan_button">स्कैन करें</string>
|
||||
<!-- Button in the search view that lets a user search by using a shortcut -->
|
||||
<string name="search_engines_shortcut_button">खोज इंजन</string>
|
||||
<!-- Button in the search view that lets a user change their search engine -->
|
||||
<string name="search_engine_button">खोज इंजन</string>
|
||||
<!-- Button in the search view when shortcuts are displayed that takes a user to the search engine settings -->
|
||||
<string name="search_shortcuts_engine_settings">खोज इंजन सेटिंग्स</string>
|
||||
<!-- Header displayed when selecting a shortcut search engine -->
|
||||
|
@ -597,6 +606,8 @@
|
|||
<string name="bookmark_select_folder">फ़ोल्डर चुनें</string>
|
||||
<!-- Confirmation message for a dialog confirming if the user wants to delete the selected folder -->
|
||||
<string name="bookmark_delete_folder_confirmation_dialog">क्या आप वाकई इस फ़ोल्डर को हटाना चाहते हैं?</string>
|
||||
<!-- Confirmation message for a dialog confirming if the user wants to delete multiple items including folders. Parameter will be replaced by app name. -->
|
||||
<string name="bookmark_delete_multiple_folders_confirmation_dialog">%s चयनित वस्तुओं को मिटा देगा।</string>
|
||||
<!-- Snackbar title shown after a folder has been deleted. This first parameter is the name of the deleted folder -->
|
||||
<string name="bookmark_delete_folder_snackbar">%1$s मिटाया गया</string>
|
||||
<!-- Screen title for adding a bookmarks folder -->
|
||||
|
@ -655,6 +666,8 @@
|
|||
|
||||
<!-- Bookmark snackbar message on deleting multiple bookmarks not including folders-->
|
||||
<string name="bookmark_deletion_multiple_snackbar_message_2">बुकमार्क मिटा दिए गए</string>
|
||||
<!-- Bookmark snackbar message on deleting multiple bookmarks including folders-->
|
||||
<string name="bookmark_deletion_multiple_snackbar_message_3">चयनित फोल्डर मिटाए जा रहे हैं</string>
|
||||
<!-- Bookmark undo button for deletion snackbar action -->
|
||||
<string name="bookmark_undo_deletion">पूर्ववत करें</string>
|
||||
|
||||
|
@ -860,6 +873,8 @@
|
|||
<string name="tab_collection_dialog_message">क्या आप वाकई %1$s को हटाना चाहते हैं?</string>
|
||||
<!-- Collection and tab deletion prompt dialog message. This will show when the last tab from a collection is deleted -->
|
||||
<string name="delete_tab_and_collection_dialog_message">इस टैब को हटाने से संपूर्ण संग्रह मिट जाएगा। आप किसी भी समय नए संग्रह बना सकते हैं।</string>
|
||||
<!-- Collection and tab deletion prompt dialog title. Placeholder will be replaced with the collection name. This will show when the last tab from a collection is deleted -->
|
||||
<string name="delete_tab_and_collection_dialog_title">%1$s को मिटाएं?</string>
|
||||
<!-- Tab collection deletion prompt dialog option to delete the collection -->
|
||||
<string name="tab_collection_dialog_positive">मिटाएं</string>
|
||||
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
|
||||
|
@ -1269,6 +1284,8 @@
|
|||
<string name="preferences_passwords_exceptions_description_empty">लॉगिन और पासवर्ड जो सहेजे नहीं गए हैं उन्हें यहां दिखाये जायेंगे।</string>
|
||||
<!-- Description of list of login exceptions that we never save logins for -->
|
||||
<string name="preferences_passwords_exceptions_description">इन साइटों के लिए लॉगिन और पासवर्ड सहेजे नहीं जाएंगे।</string>
|
||||
<!-- Text on button to remove all saved login exceptions -->
|
||||
<string name="preferences_passwords_exceptions_remove_all">सभी अपवादों को मिटाएं</string>
|
||||
<!-- Hint for search box in logins list -->
|
||||
<string name="preferences_passwords_saved_logins_search">लॉगिन खोजें</string>
|
||||
<!-- Option to sort logins list A-Z, alphabetically -->
|
||||
|
@ -1472,9 +1489,7 @@
|
|||
<string name="saved_login_duplicate">एक लॉगिन इस उपयोगकर्ता नाम के साथ मौजूद है</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">Firefox खाते से कनेक्ट करें।</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">अन्य डिवाइस कनेक्ट करें</string>
|
||||
<!-- Text displayed asking user to re-authenticate -->
|
||||
<string name="synced_tabs_reauth">कृपया पुनः प्रमाणित करें।</string>
|
||||
|
@ -1495,13 +1510,4 @@
|
|||
<!-- Confirmation dialog button text when top sites limit is reached. -->
|
||||
<string name="top_sites_max_limit_confirmation_button">ठीक है, समझ गए</string>
|
||||
|
||||
<!-- DEPRECATED STRINGS -->
|
||||
<!-- Button in the search view that lets a user search by using a shortcut -->
|
||||
<string name="search_shortcuts_button">शॉर्टकट</string>
|
||||
<!-- DEPRECATED: Header displayed when selecting a shortcut search engine -->
|
||||
<string name="search_shortcuts_search_with">के साथ खोजें</string>
|
||||
<!-- Header displayed when selecting a shortcut search engine -->
|
||||
<string name="search_shortcuts_search_with_2">इस बार, इसके साथ खोजें:</string>
|
||||
<!-- Preference title for switch preference to show search shortcuts -->
|
||||
<string name="preferences_show_search_shortcuts">खोज शॉर्टकट्स दिखाएं</string>
|
||||
</resources>
|
||||
|
|
|
@ -734,7 +734,7 @@
|
|||
<!-- Content description (not visible, for screen readers etc.): Opens the collection menu when pressed -->
|
||||
<string name="collection_menu_button_content_description">Gyűjtemény menü</string>
|
||||
<!-- No Open Tabs Message Header -->
|
||||
<string name="no_collections_header1">Gyűjtsd össze a számára fontos dolgokat</string>
|
||||
<string name="no_collections_header1">Gyűjtse össze az Önnek fontos dolgokat</string>
|
||||
<!-- Label to describe what collections are to a new user without any collections -->
|
||||
<string name="no_collections_description1">Csoportosítsa a hasonló kereséseket, webhelyeket és lapokat a későbbi gyors elérés érdekében.</string>
|
||||
<!-- Title for the "select tabs" step of the collection creator -->
|
||||
|
|
|
@ -27,6 +27,29 @@
|
|||
<!-- Message announced to the user when tab tray is selected with 0 or 2+ tabs -->
|
||||
<string name="open_tab_tray_plural">%1$s tab terbuka. Ketuk untuk beralih tab.</string>
|
||||
|
||||
<!-- Tab tray multi select title in app bar. The first parameter is the number of tabs selected -->
|
||||
<string name="tab_tray_multi_select_title">%1$d terpilih</string>
|
||||
<!-- Label of button in create collection dialog for creating a new collection -->
|
||||
<string name="tab_tray_add_new_collection">Tambah koleksi baru</string>
|
||||
<!-- Label of editable text in create collection dialog for naming a new collection -->
|
||||
<string name="tab_tray_add_new_collection_name">Nama</string>
|
||||
<!-- Label of button in save to collection dialog for selecting a current collection -->
|
||||
<string name="tab_tray_select_collection">Pilih koleksi</string>
|
||||
<!-- Content description for close button while in multiselect mode in tab tray -->
|
||||
<string name="tab_tray_close_multiselect_content_description">Keluar mode seleksi ganda</string>
|
||||
<!-- Content description for save to collection button while in multiselect mode in tab tray -->
|
||||
<string name="tab_tray_collection_button_multiselect_content_description">Simpan tab terpilih ke koleksi</string>
|
||||
<!-- Content description for checkmark while tab is selected while in multiselect mode in tab tray. The first parameter is the title of the tab selected -->
|
||||
<string name="tab_tray_item_selected_multiselect_content_description">%1$s dipilih</string>
|
||||
<!-- Content description when tab is unselected while in multiselect mode in tab tray. The first parameter is the title of the tab unselected -->
|
||||
<string name="tab_tray_item_unselected_multiselect_content_description">%1$s tidak dipilih</string>
|
||||
<!-- Content description announcement when exiting multiselect mode in tab tray -->
|
||||
<string name="tab_tray_exit_multiselect_content_description">Keluar dari mode seleksi ganda</string>
|
||||
<!-- Content description announcement when entering multiselect mode in tab tray -->
|
||||
<string name="tab_tray_enter_multiselect_content_description">Memasuki mode seleksi ganda, pilih tab untuk menyimpannya ke koleksi</string>
|
||||
<!-- Content description on checkmark while tab is selected in multiselect mode in tab tray -->
|
||||
<string name="tab_tray_multiselect_selected_content_description">Terpilih</string>
|
||||
|
||||
<!-- About content. The first parameter is the name of the application. (For example: Fenix) -->
|
||||
<string name="about_content">%1$s diproduksi oleh Mozilla.</string>
|
||||
|
||||
|
@ -152,15 +175,13 @@
|
|||
<!-- Search Fragment -->
|
||||
<!-- Button in the search view that lets a user search by scanning a QR code -->
|
||||
<string name="search_scan_button">Pindai</string>
|
||||
<!-- Button in the search view that lets a user search by using a shortcut -->
|
||||
<string name="search_shortcuts_button">Pintasan</string>
|
||||
<!-- Button in the search view that lets a user change their search engine -->
|
||||
<string name="search_engine_button">Mesin pencari</string>
|
||||
<!-- Button in the search view when shortcuts are displayed that takes a user to the search engine settings -->
|
||||
<string name="search_shortcuts_engine_settings">Setelan mesin pencari</string>
|
||||
<!-- DEPRECATED: Header displayed when selecting a shortcut search engine -->
|
||||
<string name="search_shortcuts_search_with">Cari dengan</string>
|
||||
|
||||
<!-- Header displayed when selecting a shortcut search engine -->
|
||||
<string name="search_shortcuts_search_with_2">Kali ini, cari lewat:</string>
|
||||
<string name="search_engines_search_with">Saat ini, cari dengan:</string>
|
||||
<!-- Button in the search view that lets a user navigate to the site in their clipboard -->
|
||||
<string name="awesomebar_clipboard_title">Isi tautan dari papan klip</string>
|
||||
|
||||
|
@ -270,8 +291,8 @@
|
|||
<string name="developer_tools_category">Perangkat pengembang</string>
|
||||
<!-- Preference for developers -->
|
||||
<string name="preferences_remote_debugging">Pengawakutuan jarak jauh melalui USB</string>
|
||||
<!-- Preference title for switch preference to show search shortcuts -->
|
||||
<string name="preferences_show_search_shortcuts">Tampilkan pintasan pencarian</string>
|
||||
<!-- Preference title for switch preference to show search engines -->
|
||||
<string name="preferences_show_search_engines">Tampilkan mesin pencari</string>
|
||||
<!-- Preference title for switch preference to show search suggestions -->
|
||||
<string name="preferences_show_search_suggestions">Tampilkan saran pencarian</string>
|
||||
<!-- Preference title for switch preference to show voice search button -->
|
||||
|
@ -525,6 +546,9 @@
|
|||
<!-- Postfix for private WebApp titles, placeholder is replaced with app name -->
|
||||
<string name="pwa_site_controls_title_private">%1$s (Mode Privat)</string>
|
||||
|
||||
<!-- Button in the current tab tray header in multiselect mode. Saved the selected tabs to a collection when pressed. -->
|
||||
<string name="tab_tray_save_to_collection">Simpan</string>
|
||||
|
||||
<!-- History -->
|
||||
<!-- Text for the button to clear all history -->
|
||||
<string name="history_delete_all">Hapus riwayat</string>
|
||||
|
@ -592,6 +616,8 @@
|
|||
<string name="bookmark_select_folder">Pilih folder</string>
|
||||
<!-- Confirmation message for a dialog confirming if the user wants to delete the selected folder -->
|
||||
<string name="bookmark_delete_folder_confirmation_dialog">Yakin akan menghapus folder ini?</string>
|
||||
<!-- Confirmation message for a dialog confirming if the user wants to delete multiple items including folders. Parameter will be replaced by app name. -->
|
||||
<string name="bookmark_delete_multiple_folders_confirmation_dialog">%s akan menghapus item terpilih.</string>
|
||||
<!-- Snackbar title shown after a folder has been deleted. This first parameter is the name of the deleted folder -->
|
||||
<string name="bookmark_delete_folder_snackbar">%1$s terhapus</string>
|
||||
<!-- Screen title for adding a bookmarks folder -->
|
||||
|
@ -646,8 +672,10 @@
|
|||
<!-- Bookmark snackbar message on deletion
|
||||
The first parameter is the host part of the URL of the bookmark deleted, if any -->
|
||||
<string name="bookmark_deletion_snackbar_message">%1$s terhapus</string>
|
||||
<!-- Bookmark snackbar message on deleting multiple bookmarks -->
|
||||
<!-- Bookmark snackbar message on deleting multiple bookmarks not including folders-->
|
||||
<string name="bookmark_deletion_multiple_snackbar_message_2">Markah dihapus</string>
|
||||
<!-- Bookmark snackbar message on deleting multiple bookmarks including folders-->
|
||||
<string name="bookmark_deletion_multiple_snackbar_message_3">Menghapus folder terpilih</string>
|
||||
<!-- Bookmark undo button for deletion snackbar action -->
|
||||
<string name="bookmark_undo_deletion">URUNGKAN</string>
|
||||
|
||||
|
@ -743,6 +771,8 @@
|
|||
<string name="create_collection_save_to_collection_tab_selected">%d tab dipilih</string>
|
||||
<!-- Text shown in snackbar when multiple tabs have been saved in a collection -->
|
||||
<string name="create_collection_tabs_saved">Tab disimpan!</string>
|
||||
<!-- Text shown in snackbar when one or multiple tabs have been saved in a new collection -->
|
||||
<string name="create_collection_tabs_saved_new_collection">Koleksi disimpan!</string>
|
||||
<!-- Text shown in snackbar when one tab has been saved in a collection -->
|
||||
<string name="create_collection_tab_saved">Tab disimpan!</string>
|
||||
<!-- Content description (not visible, for screen readers etc.): button to close the collection creator -->
|
||||
|
@ -849,6 +879,10 @@
|
|||
<string name="qr_scanner_dialog_negative">TOLAK</string>
|
||||
<!-- Tab collection deletion prompt dialog message. Placeholder will be replaced with the collection name -->
|
||||
<string name="tab_collection_dialog_message">Yakin ingin menghapus %1$s?</string>
|
||||
<!-- Collection and tab deletion prompt dialog message. This will show when the last tab from a collection is deleted -->
|
||||
<string name="delete_tab_and_collection_dialog_message">Menghapus tab ini akan menghapus keseluruhan koleksi. Kamu dapat membuat koleksi baru kapan saja.</string>
|
||||
<!-- Collection and tab deletion prompt dialog title. Placeholder will be replaced with the collection name. This will show when the last tab from a collection is deleted -->
|
||||
<string name="delete_tab_and_collection_dialog_title">Hapus %1$s?</string>
|
||||
<!-- Tab collection deletion prompt dialog option to delete the collection -->
|
||||
<string name="tab_collection_dialog_positive">Hapus</string>
|
||||
<!-- Tab collection deletion prompt dialog option to cancel deleting the collection -->
|
||||
|
@ -1249,6 +1283,8 @@
|
|||
<string name="preferences_passwords_exceptions_description_empty">Info masuk dan kata sandi yang tidak disimpan akan ditampilkan di sini.</string>
|
||||
<!-- Description of list of login exceptions that we never save logins for -->
|
||||
<string name="preferences_passwords_exceptions_description">Info masuk dan kata sandi tidak akan disimpan untuk situs-situs ini.</string>
|
||||
<!-- Text on button to remove all saved login exceptions -->
|
||||
<string name="preferences_passwords_exceptions_remove_all">Hapus semua pengecualian</string>
|
||||
<!-- Hint for search box in logins list -->
|
||||
<string name="preferences_passwords_saved_logins_search">Cari log masuk</string>
|
||||
<!-- Option to sort logins list A-Z, alphabetically -->
|
||||
|
@ -1287,6 +1323,8 @@
|
|||
<string name="saved_login_copy_username">Salin nama pengguna</string>
|
||||
<!-- Content Description (for screenreaders etc) read for the button to copy a site in logins -->
|
||||
<string name="saved_login_copy_site">Salin situs</string>
|
||||
<!-- Content Description (for screenreaders etc) read for the button to open a site in logins -->
|
||||
<string name="saved_login_open_site">Buka situs di peramban</string>
|
||||
<!-- Content Description (for screenreaders etc) read for the button to reveal a password in logins -->
|
||||
<string name="saved_login_reveal_password">Tampilkan sandi</string>
|
||||
<!-- Content Description (for screenreaders etc) read for the button to hide a password in logins -->
|
||||
|
@ -1437,9 +1475,7 @@
|
|||
<string name="saved_login_duplicate">Sebuah info masuk dengan nama pengguna tersebut sudah ada</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed when user is not logged into a Firefox Account -->
|
||||
<string name="synced_tabs_connect_to_sync_account">Hubungkan dengan Firefox Account.</string>
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">Hubungkan perangkat lain</string>
|
||||
<!-- Text displayed asking user to re-authenticate -->
|
||||
<string name="synced_tabs_reauth">Harap autentikasi ulang.</string>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -33,12 +33,16 @@
|
|||
<string name="tab_tray_add_new_collection_name">Nom</string>
|
||||
<!-- Label of button in save to collection dialog for selecting a current collection -->
|
||||
<string name="tab_tray_select_collection">Seleccionar una colleccion</string>
|
||||
<!-- Content description for close button while in multiselect mode in tab tray -->
|
||||
<string name="tab_tray_close_multiselect_content_description">Sortir del mòde seleccion multipla</string>
|
||||
<!-- Content description for save to collection button while in multiselect mode in tab tray -->
|
||||
<string name="tab_tray_collection_button_multiselect_content_description">Enregistrar los onglets seleccionats dins la colleccion</string>
|
||||
<!-- Content description for checkmark while tab is selected while in multiselect mode in tab tray. The first parameter is the title of the tab selected -->
|
||||
<string name="tab_tray_item_selected_multiselect_content_description">%1$s seleccionat</string>
|
||||
<!-- Content description when tab is unselected while in multiselect mode in tab tray. The first parameter is the title of the tab unselected -->
|
||||
<string name="tab_tray_item_unselected_multiselect_content_description">%1$s deseleccionat</string>
|
||||
<!-- Content description announcement when exiting multiselect mode in tab tray -->
|
||||
<string name="tab_tray_exit_multiselect_content_description">Sortida del mòde seleccion multipla</string>
|
||||
<!-- Content description on checkmark while tab is selected in multiselect mode in tab tray -->
|
||||
<string name="tab_tray_multiselect_selected_content_description">Seleccionat</string>
|
||||
|
||||
|
@ -912,6 +916,8 @@
|
|||
|
||||
<!-- Dialog message to the user asking to delete browsing data. -->
|
||||
<string name="delete_browsing_data_prompt_message">Aquò suprimirà totas las donadas de navegacion.</string>
|
||||
<!-- Dialog message to the user asking to delete browsing data. Parameter will be replaced by app name. -->
|
||||
<string name="delete_browsing_data_prompt_message_3">%s suprimirà las donadas de navegacion seleccionadas.</string>
|
||||
<!-- Text for the cancel button for the data deletion dialog -->
|
||||
<string name="delete_browsing_data_prompt_cancel">Anullar</string>
|
||||
|
||||
|
@ -1123,6 +1129,10 @@
|
|||
<!-- About page link text to open what's new link -->
|
||||
<string name="about_whats_new">Qu’es nòu dins %s</string>
|
||||
|
||||
<!-- Open source licenses page title
|
||||
The first parameter is the app name -->
|
||||
<string name="open_source_licenses_title">%s | Bibliotècas liuras</string>
|
||||
|
||||
<!-- About page link text to open support link -->
|
||||
<string name="about_support">Assisténcia</string>
|
||||
|
||||
|
@ -1192,6 +1202,10 @@
|
|||
<string name="preferences_passwords_saved_logins_description_empty_learn_more_link">Per ne saber mai sus Sync.</string>
|
||||
<!-- Preference to access list of login exceptions that we never save logins for -->
|
||||
<string name="preferences_passwords_exceptions">Excepcions</string>
|
||||
<!-- Empty description of list of login exceptions that we never save logins for -->
|
||||
<string name="preferences_passwords_exceptions_description_empty">Los identificants e senhals pas salvats seràn mostrats aquí.</string>
|
||||
<!-- Description of list of login exceptions that we never save logins for -->
|
||||
<string name="preferences_passwords_exceptions_description">Los identificants e senhals seràn pas salvats per aquestes sites.</string>
|
||||
<!-- Text on button to remove all saved login exceptions -->
|
||||
<string name="preferences_passwords_exceptions_remove_all">Suprimir totas las excepcions</string>
|
||||
<!-- Hint for search box in logins list -->
|
||||
|
@ -1245,6 +1259,8 @@
|
|||
<string name="logins_warning_dialog_set_up_now">O configurar ara</string>
|
||||
<!-- Title of PIN verification dialog to direct users to re-enter their device credentials to access their logins -->
|
||||
<string name="logins_biometric_prompt_message_pin">Desverrolhatz lo periferic</string>
|
||||
<!-- Title for Accessibility Force Enable Zoom Preference -->
|
||||
<string name="preference_accessibility_force_enable_zoom">Zoom per totes los sites</string>
|
||||
<!-- Saved logins sorting strategy menu item -by name- (if selected, it will sort saved logins alphabetically) -->
|
||||
<string name="saved_logins_sort_strategy_alphabetically">Nom (A-Z)</string>
|
||||
<!-- Saved logins sorting strategy menu item -by last used- (if selected, it will sort saved logins by last used) -->
|
||||
|
@ -1274,6 +1290,8 @@
|
|||
<!-- Text for the button to learn more about adding a custom search engine -->
|
||||
<string name="search_add_custom_engine_learn_more_label">Ne saber mai</string>
|
||||
|
||||
<!-- Accessibility description for the form in which details about the custom search engine are entered -->
|
||||
<string name="search_add_custom_engine_form_description">Detalhs del motor de recèrca personalizat</string>
|
||||
<!-- Accessibility description for the 'Learn more' link -->
|
||||
<string name="search_add_custom_engine_learn_more_description">Ligam per ne saber mai</string>
|
||||
|
||||
|
@ -1360,6 +1378,9 @@
|
|||
<!-- Voice search prompt description displayed after the user presses the voice search button -->
|
||||
<string name="voice_search_explainer">Parlatz ara</string>
|
||||
|
||||
<!-- The error message in edit login view when a duplicate username exists. -->
|
||||
<string name="saved_login_duplicate">Un identificant amb aqueste nom d’utilizaire existís ja</string>
|
||||
|
||||
<!-- Synced Tabs -->
|
||||
<!-- Text displayed to ask user to connect another device as no devices found with account -->
|
||||
<string name="synced_tabs_connect_another_device">Connectatz un autre periferic.</string>
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
<!-- Message announced to the user when tab tray is selected with 0 or 2+ tabs -->
|
||||
<string name="open_tab_tray_plural">Odprtih zavihkov: %1$s. Tapnite za preklop zavihkov.</string>
|
||||
|
||||
<!-- Tab tray multi select title in app bar. The first parameter is the number of tabs selected -->
|
||||
<string name="tab_tray_multi_select_title">%1$d izbranih</string>
|
||||
<!-- Label of button in create collection dialog for creating a new collection -->
|
||||
<string name="tab_tray_add_new_collection">Dodaj novo zbirko</string>
|
||||
<!-- Label of editable text in create collection dialog for naming a new collection -->
|
||||
|
|
|
@ -149,6 +149,7 @@
|
|||
<!-- Privacy Settings -->
|
||||
<string name="pref_key_open_links_in_a_private_tab" translatable="false">pref_key_open_links_in_a_private_tab</string>
|
||||
<string name="pref_key_open_links_in_external_app" translatable="false">pref_key_open_links_in_external_app</string>
|
||||
<string name="pref_key_external_download_manager" translatable="false">pref_key_external_download_manager</string>
|
||||
<string name="pref_key_allow_screenshots_in_private_mode" translatable="false">pref_key_allow_screenshots_in_private_mode</string>
|
||||
|
||||
<!-- Quick Action Sheet -->
|
||||
|
|
|
@ -296,6 +296,8 @@
|
|||
<string name="preferences_account_settings">Account settings</string>
|
||||
<!-- Preference for open links in third party apps -->
|
||||
<string name="preferences_open_links_in_apps">Open links in apps</string>
|
||||
<!-- Preference for open download with an external download manager app -->
|
||||
<string name="preferences_external_download_manager">External download manager</string>
|
||||
<!-- Preference for add_ons -->
|
||||
<string name="preferences_addons">Add-ons</string>
|
||||
|
||||
|
|
|
@ -132,6 +132,12 @@
|
|||
android:key="@string/pref_key_open_links_in_external_app"
|
||||
android:title="@string/preferences_open_links_in_apps" />
|
||||
|
||||
<androidx.preference.SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_download"
|
||||
android:key="@string/pref_key_external_download_manager"
|
||||
android:title="@string/preferences_external_download_manager" />
|
||||
|
||||
<androidx.preference.SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_info"
|
||||
|
|
|
@ -217,7 +217,7 @@ class DefaultBrowserToolbarControllerTest {
|
|||
|
||||
@Test
|
||||
fun handleToolbarBackPress() = runBlockingTest {
|
||||
val item = ToolbarMenu.Item.Back
|
||||
val item = ToolbarMenu.Item.Back(false)
|
||||
|
||||
val controller = createController(scope = this)
|
||||
controller.handleToolbarItemInteraction(item)
|
||||
|
@ -226,6 +226,17 @@ class DefaultBrowserToolbarControllerTest {
|
|||
verify { sessionUseCases.goBack(currentSession) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleToolbarBackLongPress() = runBlockingTest {
|
||||
val item = ToolbarMenu.Item.Back(true)
|
||||
|
||||
val controller = createController(scope = this)
|
||||
controller.handleToolbarItemInteraction(item)
|
||||
|
||||
verify { metrics.track(Event.BrowserMenuItemTapped(Event.BrowserMenuItemTapped.Item.BACK)) }
|
||||
verify { navController.navigate(R.id.action_global_tabHistoryDialogFragment) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun handleToolbarForwardPress() = runBlockingTest {
|
||||
val item = ToolbarMenu.Item.Forward(false)
|
||||
|
|
|
@ -212,6 +212,7 @@ class DefaultSessionControlControllerTest {
|
|||
fun handleCollectionShareTabsClicked() {
|
||||
val collection = mockk<TabCollection> {
|
||||
every { tabs } returns emptyList()
|
||||
every { title } returns ""
|
||||
}
|
||||
controller.handleCollectionShareTabsClicked(collection)
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ class ShareControllerTest {
|
|||
// Need a valid context to retrieve Strings for example, but we also need it to return our "metrics"
|
||||
private val context: Context = spyk(testContext)
|
||||
private val metrics: MetricController = mockk(relaxed = true)
|
||||
private val shareSubject = "shareSubject"
|
||||
private val shareData = listOf(
|
||||
ShareData(url = "url0", title = "title0"),
|
||||
ShareData(url = "url1", title = "title1")
|
||||
|
@ -65,7 +66,7 @@ class ShareControllerTest {
|
|||
private val dismiss = mockk<(ShareController.Result) -> Unit>(relaxed = true)
|
||||
private val recentAppStorage = mockk<RecentAppsStorage>(relaxed = true)
|
||||
private val controller = DefaultShareController(
|
||||
context, shareData, sendTabUseCases, snackbar, navController,
|
||||
context, shareSubject, shareData, sendTabUseCases, snackbar, navController,
|
||||
recentAppStorage, testCoroutineScope, dismiss
|
||||
)
|
||||
|
||||
|
@ -91,8 +92,8 @@ class ShareControllerTest {
|
|||
// needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
|
||||
// need to use an Activity Context.
|
||||
val activityContext: Context = mockk<Activity>()
|
||||
val testController = DefaultShareController(activityContext, shareData, mockk(), mockk(), mockk(),
|
||||
recentAppStorage, testCoroutineScope, dismiss)
|
||||
val testController = DefaultShareController(activityContext, shareSubject, shareData, mockk(),
|
||||
mockk(), mockk(), recentAppStorage, testCoroutineScope, dismiss)
|
||||
every { activityContext.startActivity(capture(shareIntent)) } just Runs
|
||||
every { recentAppStorage.updateRecentApp(appShareOption.activityName) } just Runs
|
||||
|
||||
|
@ -101,6 +102,7 @@ class ShareControllerTest {
|
|||
// Check that the Intent used for querying apps has the expected structure
|
||||
assertTrue(shareIntent.isCaptured)
|
||||
assertEquals(Intent.ACTION_SEND, shareIntent.captured.action)
|
||||
assertEquals(shareSubject, shareIntent.captured.extras!![Intent.EXTRA_SUBJECT])
|
||||
assertEquals(textToShare, shareIntent.captured.extras!![Intent.EXTRA_TEXT])
|
||||
assertEquals("text/plain", shareIntent.captured.type)
|
||||
assertEquals(Intent.FLAG_ACTIVITY_NEW_TASK, shareIntent.captured.flags)
|
||||
|
@ -124,8 +126,8 @@ class ShareControllerTest {
|
|||
// needed for capturing the actual Intent used the `slot` one doesn't have this flag so we
|
||||
// need to use an Activity Context.
|
||||
val activityContext: Context = mockk<Activity>()
|
||||
val testController = DefaultShareController(activityContext, shareData, mockk(), snackbar,
|
||||
mockk(), mockk(), testCoroutineScope, dismiss)
|
||||
val testController = DefaultShareController(activityContext, shareSubject, shareData, mockk(),
|
||||
snackbar, mockk(), mockk(), testCoroutineScope, dismiss)
|
||||
every { activityContext.startActivity(capture(shareIntent)) } throws SecurityException()
|
||||
every { activityContext.getString(R.string.share_error_snackbar) } returns "Cannot share to this app"
|
||||
|
||||
|
@ -247,6 +249,7 @@ class ShareControllerTest {
|
|||
fun `getSuccessMessage should return different strings depending on the number of shared tabs`() {
|
||||
val controllerWithOneSharedTab = DefaultShareController(
|
||||
context,
|
||||
shareSubject,
|
||||
listOf(ShareData(url = "url0", title = "title0")),
|
||||
mockk(),
|
||||
mockk(),
|
||||
|
@ -280,7 +283,7 @@ class ShareControllerTest {
|
|||
ShareData(url = "url1")
|
||||
)
|
||||
val controller = DefaultShareController(
|
||||
context, shareData, sendTabUseCases, snackbar, navController,
|
||||
context, shareSubject, shareData, sendTabUseCases, snackbar, navController,
|
||||
recentAppStorage, testCoroutineScope, dismiss
|
||||
)
|
||||
|
||||
|
@ -288,6 +291,21 @@ class ShareControllerTest {
|
|||
assertEquals(expectedShareText, controller.getShareText())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getShareSubject will return "shareSubject" if that is non null`() {
|
||||
assertEquals(shareSubject, controller.getShareSubject())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `getShareSubject will return a concatenation of tab titles if "shareSubject" is null`() {
|
||||
val controller = DefaultShareController(
|
||||
context, null, shareData, sendTabUseCases, snackbar, navController,
|
||||
recentAppStorage, testCoroutineScope, dismiss
|
||||
)
|
||||
|
||||
assertEquals("title0, title1", controller.getShareSubject())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ShareTab#toTabData maps a list of ShareTab to a TabData list`() {
|
||||
var tabData: List<TabData>
|
||||
|
|
|
@ -76,7 +76,7 @@ complexity:
|
|||
# https://github.com/mozilla-mobile/fenix/issues/4861
|
||||
threshold: 75
|
||||
LongParameterList:
|
||||
active: trued
|
||||
active: true
|
||||
excludes: "**/*Controller.kt, **/*Integration.kt"
|
||||
functionThreshold: 6
|
||||
constructorThreshold: 7
|
||||
|
|
Loading…
Reference in New Issue