diff options
Diffstat (limited to 'mobile/android/android-components/components/compose')
446 files changed, 6321 insertions, 0 deletions
diff --git a/mobile/android/android-components/components/compose/awesomebar/README.md b/mobile/android/android-components/components/compose/awesomebar/README.md new file mode 100644 index 0000000000..6d1e606e39 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/README.md @@ -0,0 +1,19 @@ +# [Android Components](../../../README.md) > Compose > Awesomebar + +A customizable awesomebar for browsers using Jetpack Compose. + +## Usage + +### Setting up the dependency + +Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)): + +```Groovy +implementation "org.mozilla.components:compose-awesomebar:{latest-version}" +``` + +## License + + 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/ diff --git a/mobile/android/android-components/components/compose/awesomebar/build.gradle b/mobile/android/android-components/components/compose/awesomebar/build.gradle new file mode 100644 index 0000000000..65691db0e5 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/build.gradle @@ -0,0 +1,68 @@ +/* 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/. */ + +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-parcelize' + +android { + defaultConfig { + minSdkVersion config.minSdkVersion + compileSdk config.compileSdkVersion + targetSdkVersion config.targetSdkVersion + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + buildFeatures { + compose true + } + + composeOptions { + kotlinCompilerExtensionVersion = Versions.compose_compiler + } + + namespace 'mozilla.components.compose.browser.awesomebar' + +} + +tasks.withType(KotlinCompile).configureEach { + kotlinOptions.freeCompilerArgs += "-Xjvm-default=all" +} + +dependencies { + implementation platform(ComponentsDependencies.androidx_compose_bom) + implementation project(":concept-awesomebar") + implementation project(":browser-state") + implementation project(":support-base") + implementation project(":support-utils") + implementation project(":ui-icons") + + implementation ComponentsDependencies.kotlin_coroutines + + implementation ComponentsDependencies.androidx_core_ktx + implementation ComponentsDependencies.androidx_compose_ui + implementation ComponentsDependencies.androidx_compose_ui_tooling_preview + implementation ComponentsDependencies.androidx_compose_foundation + implementation ComponentsDependencies.androidx_compose_material + + debugImplementation ComponentsDependencies.androidx_compose_ui_tooling + + testImplementation project(':support-test') + testImplementation ComponentsDependencies.androidx_compose_ui_test + testImplementation ComponentsDependencies.androidx_test_core + testImplementation ComponentsDependencies.androidx_test_junit + testImplementation ComponentsDependencies.testing_robolectric +} + +apply from: '../../../android-lint.gradle' +apply from: '../../../publish.gradle' +ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description) diff --git a/mobile/android/android-components/components/compose/awesomebar/proguard-rules.pro b/mobile/android/android-components/components/compose/awesomebar/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e16cda1d34 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ +<!-- 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/. --> +<manifest /> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBar.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBar.kt new file mode 100644 index 0000000000..a5d3f10e2a --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBar.kt @@ -0,0 +1,121 @@ +/* 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 mozilla.components.compose.browser.awesomebar + +import android.annotation.SuppressLint +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import mozilla.components.compose.browser.awesomebar.internal.SuggestionFetcher +import mozilla.components.compose.browser.awesomebar.internal.Suggestions +import mozilla.components.concept.awesomebar.AwesomeBar +import mozilla.components.concept.base.profiler.Profiler + +/** + * An awesome bar displaying suggestions from the list of provided [AwesomeBar.SuggestionProvider]s. + * + * @param text The text entered by the user and for which the AwesomeBar should show suggestions for. + * @param colors The color scheme the AwesomeBar will use for the UI. + * @param providers The list of suggestion providers to query whenever the [text] changes. + * @param orientation Whether the AwesomeBar is oriented to the top or the bottom of the screen. + * @param onSuggestionClicked Gets invoked whenever the user clicks on a suggestion in the AwesomeBar. + * @param onAutoComplete Gets invoked when the user clicks on the "autocomplete" icon of a suggestion. + * @param onVisibilityStateUpdated Gets invoked when the list of currently displayed suggestions changes. + * @param onScroll Gets invoked at the beginning of the user performing a scroll gesture. + */ +@Composable +fun AwesomeBar( + text: String, + colors: AwesomeBarColors = AwesomeBarDefaults.colors(), + providers: List<AwesomeBar.SuggestionProvider>, + orientation: AwesomeBarOrientation = AwesomeBarOrientation.TOP, + onSuggestionClicked: (AwesomeBar.Suggestion) -> Unit, + onAutoComplete: (AwesomeBar.Suggestion) -> Unit, + onVisibilityStateUpdated: (AwesomeBar.VisibilityState) -> Unit = {}, + onScroll: () -> Unit = {}, + profiler: Profiler? = null, +) { + val groups = remember(providers) { + providers + .groupBy { it.groupTitle() } + .map { + AwesomeBar.SuggestionProviderGroup( + providers = it.value, + title = it.key, + ) + } + } + + AwesomeBar( + text = text, + colors = colors, + groups = groups, + orientation = orientation, + onSuggestionClicked = { _, suggestion -> onSuggestionClicked(suggestion) }, + onAutoComplete = { _, suggestion -> onAutoComplete(suggestion) }, + onVisibilityStateUpdated = onVisibilityStateUpdated, + onScroll = onScroll, + profiler = profiler, + ) +} + +/** + * An awesome bar displaying suggestions in groups from the list of provided [AwesomeBar.SuggestionProviderGroup]s. + * + * @param text The text entered by the user and for which the AwesomeBar should show suggestions for. + * @param colors The color scheme the AwesomeBar will use for the UI. + * @param groups The list of groups of suggestion providers to query whenever the [text] changes. + * @param orientation Whether the AwesomeBar is oriented to the top or the bottom of the screen. + * @param onSuggestionClicked Gets invoked whenever the user clicks on a suggestion in the AwesomeBar. + * @param onAutoComplete Gets invoked when the user clicks on the "autocomplete" icon of a suggestion. + * @param onVisibilityStateUpdated Gets invoked when the list of currently displayed suggestions changes. + * @param onScroll Gets invoked at the beginning of the user performing a scroll gesture. + */ +@Composable +fun AwesomeBar( + text: String, + colors: AwesomeBarColors = AwesomeBarDefaults.colors(), + groups: List<AwesomeBar.SuggestionProviderGroup>, + orientation: AwesomeBarOrientation = AwesomeBarOrientation.TOP, + onSuggestionClicked: (AwesomeBar.SuggestionProviderGroup, AwesomeBar.Suggestion) -> Unit, + onAutoComplete: (AwesomeBar.SuggestionProviderGroup, AwesomeBar.Suggestion) -> Unit, + onVisibilityStateUpdated: (AwesomeBar.VisibilityState) -> Unit = {}, + onScroll: () -> Unit = {}, + profiler: Profiler? = null, +) { + Column( + modifier = Modifier + .fillMaxWidth() + .testTag("mozac.awesomebar") + .background(colors.background), + ) { + val fetcher = remember(groups) { SuggestionFetcher(groups, profiler) } + + // This state does not need to be remembered, because it can change if the providers list changes. + @SuppressLint("UnrememberedMutableState") + val suggestions = derivedStateOf { fetcher.state.value }.value.toList() + .sortedByDescending { it.first.priority }.toMap(LinkedHashMap()) + + LaunchedEffect(text, fetcher) { + fetcher.fetch(text) + } + + Suggestions( + suggestions, + colors, + orientation, + onSuggestionClicked, + onAutoComplete, + onVisibilityStateUpdated, + onScroll, + ) + } +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarColors.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarColors.kt new file mode 100644 index 0000000000..fe31e36153 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarColors.kt @@ -0,0 +1,18 @@ +/* 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 mozilla.components.compose.browser.awesomebar + +import androidx.compose.ui.graphics.Color + +/** + * Represents the colors used by the AwesomeBar. + */ +data class AwesomeBarColors( + val background: Color, + val title: Color, + val description: Color, + val autocompleteIcon: Color, + val groupTitle: Color, +) diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarDefaults.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarDefaults.kt new file mode 100644 index 0000000000..a804ad86df --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarDefaults.kt @@ -0,0 +1,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/. */ + +package mozilla.components.compose.browser.awesomebar + +import androidx.compose.material.ContentAlpha +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +/** + * Contains the default values used by the AwesomeBar. + */ +object AwesomeBarDefaults { + /** + * Creates an [AwesomeBarColors] that represents the default colors used in an AwesomeBar. + * + * @param background The background of the AwesomeBar. + * @param title The text color for the title of a suggestion. + * @param description The text color for the description of a suggestion. + */ + @Composable + fun colors( + background: Color = MaterialTheme.colors.background, + title: Color = MaterialTheme.colors.onBackground, + description: Color = MaterialTheme.colors.onBackground.copy( + alpha = ContentAlpha.medium, + ), + autocompleteIcon: Color = MaterialTheme.colors.onSurface, + groupTitle: Color = MaterialTheme.colors.onBackground, + ) = AwesomeBarColors( + background, + title, + description, + autocompleteIcon, + groupTitle, + ) +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarFacts.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarFacts.kt new file mode 100644 index 0000000000..bfa748cb06 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarFacts.kt @@ -0,0 +1,44 @@ +/* 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 mozilla.components.compose.browser.awesomebar + +import mozilla.components.support.base.Component +import mozilla.components.support.base.facts.Action +import mozilla.components.support.base.facts.Fact +import mozilla.components.support.base.facts.collect + +/** + * Facts emitted for telemetry related to the AwesomeBar composable. + */ +object AwesomeBarFacts { + /** + * Specific types of telemetry items. + */ + object Items { + const val PROVIDER_DURATION = "provider_duration" + } + + /** + * Keys used to record metadata about [Items]. + */ + object MetadataKeys { + const val DURATION_PAIR = "duration_pair" + } + + internal fun emitAwesomeBarFact( + action: Action, + item: String, + value: String? = null, + metadata: Map<String, Any>? = null, + ) { + Fact( + Component.COMPOSE_AWESOMEBAR, + action, + item, + value, + metadata, + ).collect() + } +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarOrientation.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarOrientation.kt new file mode 100644 index 0000000000..246f917c1e --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/AwesomeBarOrientation.kt @@ -0,0 +1,13 @@ +/* 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 mozilla.components.compose.browser.awesomebar + +/** + * The orientation of the AwesomeBar, whether it's oriented to the bottom or the top. + */ +enum class AwesomeBarOrientation { + TOP, + BOTTOM, +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestion.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestion.kt new file mode 100644 index 0000000000..275e336414 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestion.kt @@ -0,0 +1,184 @@ +/* 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 mozilla.components.compose.browser.awesomebar.internal + +import android.graphics.Bitmap +import android.graphics.drawable.Drawable +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.graphics.drawable.toBitmap +import mozilla.components.compose.browser.awesomebar.AwesomeBarColors +import mozilla.components.compose.browser.awesomebar.AwesomeBarOrientation +import mozilla.components.compose.browser.awesomebar.R +import mozilla.components.concept.awesomebar.AwesomeBar +import mozilla.components.ui.icons.R as iconsR + +// We only show one row of text, covering at max screen width. +// Limit bigger texts that could cause slowdowns or even crashes. +private const val SUGGESTION_TEXT_MAX_LENGTH = 100 + +@Composable +internal fun Suggestion( + suggestion: AwesomeBar.Suggestion, + colors: AwesomeBarColors, + orientation: AwesomeBarOrientation, + onSuggestionClicked: () -> Unit, + onAutoComplete: () -> Unit, +) { + Row( + modifier = Modifier + .clickable { onSuggestionClicked() } + .defaultMinSize(minHeight = 56.dp) + .testTag("mozac.awesomebar.suggestion") + .padding(start = 16.dp, top = 8.dp, bottom = 8.dp, end = 8.dp), + ) { + val icon = suggestion.icon + if (icon != null) { + SuggestionIcon( + icon = icon, + indicator = suggestion.indicatorIcon, + ) + } + SuggestionTitleAndDescription( + title = suggestion.title?.take(SUGGESTION_TEXT_MAX_LENGTH), + description = suggestion.description?.take(SUGGESTION_TEXT_MAX_LENGTH), + colors = colors, + modifier = Modifier + .weight(1f) + .align(Alignment.CenterVertically), + ) + if (suggestion.editSuggestion != null) { + AutocompleteButton( + onAutoComplete = onAutoComplete, + orientation = orientation, + colors = colors, + modifier = Modifier.align(Alignment.CenterVertically), + ) + } + } +} + +@Composable +private fun SuggestionTitleAndDescription( + title: String?, + description: String?, + colors: AwesomeBarColors, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier, + ) { + Text( + text = if (title.isNullOrEmpty()) { + description ?: "" + } else { + title + }, + color = colors.title, + fontSize = 15.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier + .width(IntrinsicSize.Max) + .padding(start = 2.dp, end = 8.dp), + ) + if (description?.isNotEmpty() == true) { + Text( + text = description, + color = colors.description, + fontSize = 12.sp, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier + .width(IntrinsicSize.Max) + .padding(start = 2.dp, end = 8.dp), + ) + } + } +} + +@Composable +private fun SuggestionIcon( + icon: Bitmap, + indicator: Drawable?, +) { + Box( + modifier = Modifier + .width(30.dp) + .height(38.dp), + ) { + Image( + icon.asImageBitmap(), + contentDescription = null, + modifier = Modifier + .padding(top = 8.dp) + .clip(RoundedCornerShape(2.dp)) + .width(24.dp) + .height(24.dp), + contentScale = ContentScale.Crop, + ) + if (indicator != null) { + Image( + indicator.toBitmap().asImageBitmap(), + contentDescription = null, + modifier = Modifier + .padding(top = 22.dp, start = 14.dp) + .width(16.dp) + .height(16.dp), + ) + } + } +} + +@Composable +@Suppress("MagicNumber") +private fun AutocompleteButton( + onAutoComplete: () -> Unit, + colors: AwesomeBarColors, + orientation: AwesomeBarOrientation, + modifier: Modifier, +) { + Image( + painterResource(iconsR.drawable.mozac_ic_append_up_left_24), + colorFilter = ColorFilter.tint(colors.autocompleteIcon), + contentDescription = stringResource(R.string.mozac_browser_awesomebar_edit_suggestion), + modifier = modifier + .size(48.dp) + .rotate( + if (orientation == AwesomeBarOrientation.BOTTOM) { + 270f + } else { + 0f + }, + ) + .clickable { onAutoComplete() } + .padding(12.dp), + ) +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcher.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcher.kt new file mode 100644 index 0000000000..354d2a25c5 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcher.kt @@ -0,0 +1,160 @@ +/* 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 mozilla.components.compose.browser.awesomebar.internal + +import android.os.SystemClock +import androidx.annotation.VisibleForTesting +import androidx.compose.runtime.RememberObserver +import androidx.compose.runtime.mutableStateOf +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.asCoroutineDispatcher +import kotlinx.coroutines.launch +import mozilla.components.compose.browser.awesomebar.AwesomeBarFacts +import mozilla.components.compose.browser.awesomebar.AwesomeBarFacts.emitAwesomeBarFact +import mozilla.components.concept.awesomebar.AwesomeBar +import mozilla.components.concept.base.profiler.Profiler +import mozilla.components.support.base.facts.Action +import mozilla.components.support.base.utils.NamedThreadFactory +import mozilla.components.support.utils.ThreadUtils +import java.util.concurrent.Executors + +/** + * Class responsible for fetching search suggestions and exposing a [state] to observe the current + * list of suggestions from a composable. + */ +internal class SuggestionFetcher( + private val groups: List<AwesomeBar.SuggestionProviderGroup>, + private val profiler: Profiler?, +) : RememberObserver { + private val dispatcher = Executors.newFixedThreadPool( + groups.fold(0, { acc, group -> acc + group.providers.size }), + NamedThreadFactory("SuggestionFetcher"), + ).asCoroutineDispatcher() + + @VisibleForTesting + internal var fetchJob: Job? = null + + /** + * The current list of suggestions as an observable list. + */ + val state = mutableStateOf<Map<AwesomeBar.SuggestionProviderGroup, List<AwesomeBar.Suggestion>>>(emptyMap()) + + /** + * Fetches suggestions for [text] from all providers in all [groups] asynchronously. + * + * The [state] property will be updated whenever new suggestions are available. + */ + suspend fun fetch(text: String) { + profiler?.addMarker("SuggestionFetcher.fetch") // DO NOT ADD ANYTHING ABOVE THIS addMarker CALL. + + fetchJob?.cancel() + + fetchJob = CoroutineScope(dispatcher).launch { + groups.forEach { group -> + group.providers.forEach { provider -> + val profilerStartTime = profiler?.getProfilerTime() // DO NOT ADD ANYTHING ABOVE getProfilerTime. + launch(dispatcher) { fetchFrom(group, provider, text, profilerStartTime) } + } + } + } + } + + /** + * Fetches suggestions from [provider]. + */ + @VisibleForTesting + internal suspend fun fetchFrom( + group: AwesomeBar.SuggestionProviderGroup, + provider: AwesomeBar.SuggestionProvider, + text: String, + profilerStartTime: Double?, + ) { + // At this point, we have a timing value for a provider. + // We have a choice here - we can try grouping different timings together for a + // single user input value, or we can just treat them as entirely independent values. + // These timings are correlated with each other in a sense that they act on the same + // inputs, and are executed at the same time. However, our goal here is to track performance + // of the providers. Each provider acts independently from another; recording their performance + // at an individual level will allow us to track that performance over time. + // Tracked value will be reflected both in perceived user experience (how quickly results from + // a provider show up), and in a purely technical interpretation of how quickly providers + // fulfill requests. + // Grouping also poses timing challenges - as user is typing, we're trying to cancel these + // provider requests. Given that each request can take an arbitrary amount of time to execute, + // grouping correctly becomes tricky and we run a risk of omitting certain values - or, of + // adding a bunch of complexity just for the sake of "correct grouping". + val start = SystemClock.elapsedRealtimeNanos() + val suggestions = provider.onInputChanged(text) + val end = SystemClock.elapsedRealtimeNanos() + emitProviderQueryTimingFact(provider, timingNs = end - start) + + processResultFrom(group, provider, suggestions, profilerStartTime) + } + + /** + * Updates [state] to include the [suggestions] from [provider]. + */ + @Synchronized + @VisibleForTesting + internal fun processResultFrom( + group: AwesomeBar.SuggestionProviderGroup, + provider: AwesomeBar.SuggestionProvider, + suggestions: List<AwesomeBar.Suggestion>, + profilerStartTime: Double?, + ) { + val suggestionMap = state.value + + val updatedSuggestions = (suggestionMap[group] ?: emptyList()) + .filter { suggestion -> suggestion.provider != provider } + .toMutableList() + + updatedSuggestions.addAll(suggestions) + updatedSuggestions.sortByDescending { suggestion -> suggestion.score } + + if (updatedSuggestions.isNotEmpty()) { + group.priority = updatedSuggestions[0].score + } + + val updatedSuggestionMap = suggestionMap.toMutableMap() + updatedSuggestionMap[group] = updatedSuggestions + state.value = updatedSuggestionMap + val profilerEndTime = profiler?.getProfilerTime() // THIS MUST OCCUR RIGHT AFTER STATE UPDATE. + + // Markers can only be added on the main thread right now. + profiler?.let { + ThreadUtils.postToMainThread { + profiler.addMarker( + "Suggestion update", + profilerStartTime, + profilerEndTime, + provider::class.simpleName, + ) + } + } + } + + override fun onAbandoned() { + dispatcher.close() + } + + override fun onForgotten() { + dispatcher.close() + } + + override fun onRemembered() = Unit +} + +@Suppress("MagicNumber") +internal fun emitProviderQueryTimingFact(provider: AwesomeBar.SuggestionProvider, timingNs: Long) { + emitAwesomeBarFact( + Action.INTERACTION, + AwesomeBarFacts.Items.PROVIDER_DURATION, + metadata = mapOf( + // We only care about millisecond precision here, so convert from ns to ms before emitting. + AwesomeBarFacts.MetadataKeys.DURATION_PAIR to (provider to (timingNs / 1_000_000L)), + ), + ) +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionGroup.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionGroup.kt new file mode 100644 index 0000000000..0d76d0c21a --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionGroup.kt @@ -0,0 +1,35 @@ +/* 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 mozilla.components.compose.browser.awesomebar.internal + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import mozilla.components.compose.browser.awesomebar.AwesomeBarColors + +/** + * Renders a header for a group of suggestions. + */ +@Composable +internal fun SuggestionGroup( + title: String, + colors: AwesomeBarColors, +) { + Text( + title, + color = colors.groupTitle, + modifier = Modifier + .padding( + vertical = 12.dp, + horizontal = 16.dp, + ) + .fillMaxWidth(), + fontSize = 14.sp, + ) +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestions.kt b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestions.kt new file mode 100644 index 0000000000..b505d1503f --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/java/mozilla/components/compose/browser/awesomebar/internal/Suggestions.kt @@ -0,0 +1,168 @@ +/* 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 mozilla.components.compose.browser.awesomebar.internal + +import android.os.Parcelable +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.RememberObserver +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberUpdatedState +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.testTag +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChangedBy +import kotlinx.parcelize.Parcelize +import mozilla.components.compose.browser.awesomebar.AwesomeBarColors +import mozilla.components.compose.browser.awesomebar.AwesomeBarOrientation +import mozilla.components.concept.awesomebar.AwesomeBar + +@Composable +internal fun Suggestions( + suggestions: Map<AwesomeBar.SuggestionProviderGroup, List<AwesomeBar.Suggestion>>, + colors: AwesomeBarColors, + orientation: AwesomeBarOrientation, + onSuggestionClicked: (AwesomeBar.SuggestionProviderGroup, AwesomeBar.Suggestion) -> Unit, + onAutoComplete: (AwesomeBar.SuggestionProviderGroup, AwesomeBar.Suggestion) -> Unit, + onVisibilityStateUpdated: (AwesomeBar.VisibilityState) -> Unit, + onScroll: () -> Unit, +) { + val state = rememberLazyListState() + + ScrollHandler(state, onScroll) + + LazyColumn( + state = state, + modifier = Modifier.testTag("mozac.awesomebar.suggestions"), + ) { + suggestions.forEach { (group, suggestions) -> + val title = group.title + if (suggestions.isNotEmpty() && !title.isNullOrEmpty()) { + item(ItemKey.SuggestionGroup(group.id)) { + SuggestionGroup(title, colors) + } + } + + items( + items = suggestions.take(group.limit), + key = { suggestion -> ItemKey.Suggestion(group.id, suggestion.provider.id, suggestion.id) }, + ) { suggestion -> + Suggestion( + suggestion, + colors, + orientation, + onSuggestionClicked = { onSuggestionClicked(group, suggestion) }, + onAutoComplete = { onAutoComplete(group, suggestion) }, + ) + } + } + } + + val currentSuggestions by rememberUpdatedState(suggestions) + val currentOnVisibilityStateUpdated by rememberUpdatedState(onVisibilityStateUpdated) + + LaunchedEffect(Unit) { + // This effect is launched on the initial composition, and cancelled when `Suggestions` leaves the Composition. + // The flow below emits new values when either the latest list of suggestions changes, or the visibility or + // position of any suggestion in that list changes. + snapshotFlow { currentSuggestions } + .combine(snapshotFlow { state.layoutInfo.visibleItemsInfo }) { suggestions, visibleItemsInfo -> + VisibleItems( + suggestions = suggestions, + visibleItemKeys = visibleItemsInfo.map { it.key as ItemKey }, + ) + } + .distinctUntilChangedBy { it.visibleItemKeys } + .collect { currentOnVisibilityStateUpdated(it.toVisibilityState()) } + } +} + +/** + * An effect for handling scrolls in a [LazyColumn]. Will invoke [onScroll] at the beginning + * of a scroll gesture. + */ +@Composable +private fun ScrollHandler( + state: LazyListState, + onScroll: () -> Unit, +) { + val scrollInProgress = state.isScrollInProgress + remember(scrollInProgress) { + ScrollHandlerImpl(scrollInProgress, onScroll) + } +} + +/** + * [RememberObserver] implementation that will make sure that [onScroll] get called only once as + * long as [scrollInProgress] doesn't change. + */ +private class ScrollHandlerImpl( + private val scrollInProgress: Boolean, + private val onScroll: () -> Unit, +) : RememberObserver { + override fun onAbandoned() = Unit + override fun onForgotten() = Unit + + override fun onRemembered() { + if (scrollInProgress) { + onScroll() + } + } +} + +/** + * A stable, unique key for an item in the [Suggestions] list. + */ +internal sealed interface ItemKey { + @Parcelize + data class SuggestionGroup(val id: String) : ItemKey, Parcelable + + @Parcelize + data class Suggestion( + val groupId: String, + val providerId: String, + val suggestionId: String, + ) : ItemKey, Parcelable +} + +/** + * A snapshot of all the fetched suggestions to show in the [Suggestions] list, and the keys of the visible items + * in that list, ordered top to bottom. The intersection of the two is the current [AwesomeBar.VisibilityState]. + */ +internal data class VisibleItems( + val suggestions: Map<AwesomeBar.SuggestionProviderGroup, List<AwesomeBar.Suggestion>>, + val visibleItemKeys: List<ItemKey>, +) { + fun toVisibilityState(): AwesomeBar.VisibilityState = + if (visibleItemKeys.isEmpty()) { + AwesomeBar.VisibilityState() + } else { + AwesomeBar.VisibilityState( + // `suggestions` is insertion-ordered, and `toMap()` preserves that order, so the groups in + // `visibleProviderGroups` are in the same order as they're shown in the awesomebar. + visibleProviderGroups = suggestions.mapNotNull { (group, suggestions) -> + val visibleSuggestions = suggestions.filter { suggestion -> + val suggestionItemKey = ItemKey.Suggestion( + groupId = group.id, + providerId = suggestion.provider.id, + suggestionId = suggestion.id, + ) + visibleItemKeys.contains(suggestionItemKey) + } + if (visibleSuggestions.isNotEmpty()) { + group to visibleSuggestions + } else { + null + } + }.toMap(), + ) + } +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-am/strings.xml new file mode 100644 index 0000000000..9c811b081b --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-am/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">ጥቆማን ተቀበል እና አርትዕ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ar/strings.xml new file mode 100644 index 0000000000..fca9a6d723 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ar/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">اقبل الاقتراح وحرّره</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ast/strings.xml new file mode 100644 index 0000000000..c3681052e8 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ast/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar ya editar la suxerencia</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-azb/strings.xml new file mode 100644 index 0000000000..6856d82e37 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-azb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">تکلیفلری قبول و دوزهلیش ائدین</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ban/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ban/strings.xml new file mode 100644 index 0000000000..5592ff756e --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ban/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Cumpu miwah uah saran</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml new file mode 100644 index 0000000000..7a05d5c150 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-be/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Прыняць і рэдагаваць прапанову</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bg/strings.xml new file mode 100644 index 0000000000..fee7ceb76d --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bg/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Приемане и редакция на предложението</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-br/strings.xml new file mode 100644 index 0000000000..647d3ccc51 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-br/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Asantiñ hag embann ar c‘hinnig</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bs/strings.xml new file mode 100644 index 0000000000..12124a89c9 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-bs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Prihvati i uredi prijedlog</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ca/strings.xml new file mode 100644 index 0000000000..db7a40ac20 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ca/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Accepta i edita el suggeriment</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cak/strings.xml new file mode 100644 index 0000000000..e0ec236f51 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cak/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Tik\'ul chuqa\' tinuk\' chilab\'enïk</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ceb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ceb/strings.xml new file mode 100644 index 0000000000..33fd4d981a --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ceb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Dawata ug usba ang sugyot</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ckb/strings.xml new file mode 100644 index 0000000000..32a9820f12 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ckb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">ڕازیبە و پێشنیارەکە دەستکاریبکە</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-co/strings.xml new file mode 100644 index 0000000000..7485b24bbe --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-co/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Accettà è mudificà a suggestione</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cs/strings.xml new file mode 100644 index 0000000000..ef57156331 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Přijmout a upravit návrh</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cy/strings.xml new file mode 100644 index 0000000000..8476dd6ad7 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-cy/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Derbyn a golygu awgrym</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-da/strings.xml new file mode 100644 index 0000000000..4dd702661c --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-da/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Accepter og rediger forslag</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-de/strings.xml new file mode 100644 index 0000000000..a3e5839463 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-de/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Vorschlag annehmen und bearbeiten</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-dsb/strings.xml new file mode 100644 index 0000000000..6e0d778296 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-dsb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Naraźenje akceptěrowaś a wobźěłaś</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-el/strings.xml new file mode 100644 index 0000000000..f66fb02587 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-el/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Αποδοχή και επεξεργασία πρότασης</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rCA/strings.xml new file mode 100644 index 0000000000..a5fd6b47e3 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rCA/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Accept and edit suggestion</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 0000000000..a5fd6b47e3 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Accept and edit suggestion</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eo/strings.xml new file mode 100644 index 0000000000..79f9e026ed --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Akcepti kaj modifi sugeston</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 0000000000..76061a6811 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rCL/strings.xml new file mode 100644 index 0000000000..76061a6811 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rCL/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rES/strings.xml new file mode 100644 index 0000000000..76061a6811 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rES/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rMX/strings.xml new file mode 100644 index 0000000000..76061a6811 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es-rMX/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es/strings.xml new file mode 100644 index 0000000000..76061a6811 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-es/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar y editar sugerencia</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-et/strings.xml new file mode 100644 index 0000000000..30d1bc57c6 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-et/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Nõustu ja muuda soovitust</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eu/strings.xml new file mode 100644 index 0000000000..c2d90b206e --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-eu/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Onartu eta editatu iradokizuna</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fa/strings.xml new file mode 100644 index 0000000000..51d494d857 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fa/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">پذیرش و ویرایش پیشنهاد</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fi/strings.xml new file mode 100644 index 0000000000..26c1bf745d --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fi/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Hyväksy ehdotus ja muokkaa sitä</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000000..4854ede352 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Accepter et modifier la suggestion</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fur/strings.xml new file mode 100644 index 0000000000..3fce06ba6c --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fur/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Acete e modifiche sugjeriment</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fy-rNL/strings.xml new file mode 100644 index 0000000000..e3be14f405 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-fy-rNL/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Suggestje akseptearje en bewurkje</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gd/strings.xml new file mode 100644 index 0000000000..48b3251c4b --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gd/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Gabh ris is deasaich am moladh</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gl/strings.xml new file mode 100644 index 0000000000..cc1aafdc78 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceptar e editar a suxestión</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gn/strings.xml new file mode 100644 index 0000000000..041524a8c8 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-gn/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Emoneĩ ha embosako’i ñe’ẽporã</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hi-rIN/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hi-rIN/strings.xml new file mode 100644 index 0000000000..4bcd2e4b94 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hi-rIN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">सुझाव को स्वीकारें और संपादित करें</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hr/strings.xml new file mode 100644 index 0000000000..12124a89c9 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Prihvati i uredi prijedlog</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hsb/strings.xml new file mode 100644 index 0000000000..e83f6c018c --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hsb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Namjet přiwzać a wobdźěłać</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hu/strings.xml new file mode 100644 index 0000000000..bc890be834 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hu/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Elfogadás és a javaslat szerkesztése</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000000..5283d8d707 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-hy-rAM/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Ընդունել և խմբագրել առաջարկությունը</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ia/strings.xml new file mode 100644 index 0000000000..5631621fdc --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ia/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Acceptar e rediger suggestion</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-in/strings.xml new file mode 100644 index 0000000000..54967054e7 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-in/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Terima dan ubah saran</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-is/strings.xml new file mode 100644 index 0000000000..10c6b79c14 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-is/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Samþykkja og breyta tillögu</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-it/strings.xml new file mode 100644 index 0000000000..c6812c4865 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-it/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Accetta e modifica suggerimento</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-iw/strings.xml new file mode 100644 index 0000000000..d595def498 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-iw/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">לקבל ולערוך את ההצעה</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ja/strings.xml new file mode 100644 index 0000000000..ea9a12d306 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ja/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">提案を受け入れて編集</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ka/strings.xml new file mode 100644 index 0000000000..1a1664e0a0 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ka/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">მიღება და შემოთავაზების ჩასწორება</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kaa/strings.xml new file mode 100644 index 0000000000..450efcd9a1 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kaa/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Usınıslardı qabıllaw hám ózgertiw</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kab/strings.xml new file mode 100644 index 0000000000..3117f7591b --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kab/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Qbel syen ẓreg asumer</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kk/strings.xml new file mode 100644 index 0000000000..83d4d9261a --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Ұсынысты қабылдау және түзету</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kmr/strings.xml new file mode 100644 index 0000000000..d7dc068c21 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-kmr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Pêşniyarê bipejirîne û sererast bike</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ko/strings.xml new file mode 100644 index 0000000000..308e45797f --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ko/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">제안 수락 및 편집</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lo/strings.xml new file mode 100644 index 0000000000..eed7f6e8c0 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">ຍອມຮັບ ແລະ ແກ້ໄຂຄຳແນະນຳ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lt/strings.xml new file mode 100644 index 0000000000..2b5c72b442 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-lt/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Priimti ir redaguoti pasiūlymą</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-mr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-mr/strings.xml new file mode 100644 index 0000000000..42c0a8df5b --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-mr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">सूचना स्वीकारा व संपादित करा</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-my/strings.xml new file mode 100644 index 0000000000..63b5bee53a --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-my/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">အကြံပြုချက်အားလက်ခံ၍တည်းဖြတ်မည်</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nb-rNO/strings.xml new file mode 100644 index 0000000000..f141385354 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nb-rNO/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Godta og rediger forslag</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ne-rNP/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ne-rNP/strings.xml new file mode 100644 index 0000000000..905e09f84b --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ne-rNP/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">सुझाव स्वीकार्नुहोस् र सम्पादन गर्नुहोस्</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nl/strings.xml new file mode 100644 index 0000000000..f2379344d1 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Suggestie accepteren en bewerken</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nn-rNO/strings.xml new file mode 100644 index 0000000000..f141385354 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-nn-rNO/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Godta og rediger forslag</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-oc/strings.xml new file mode 100644 index 0000000000..fce8718fd2 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-oc/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Acceptar e modificar la suggestion</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-or/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-or/strings.xml new file mode 100644 index 0000000000..2e861cce89 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-or/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">ସ୍ୱୀକାର କରି ପରାମର୍ଶଟିକୁ ସମ୍ପାଦନ କରନ୍ତୁ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 0000000000..ba64f33a8a --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">ਸੁਝਾਅ ਮੰਨੋ ਤੇ ਸੋਧੋ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rPK/strings.xml new file mode 100644 index 0000000000..1ea85cff8d --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pa-rPK/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">تجویز منو تے سودھو</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pl/strings.xml new file mode 100644 index 0000000000..7de1109e3d --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Przyjmij i modyfikuj podpowiedź</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000000..478fab2ca3 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceitar e editar sugestão</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000..478fab2ca3 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Aceitar e editar sugestão</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-rm/strings.xml new file mode 100644 index 0000000000..693ab380d5 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-rm/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Acceptar la proposta e modifitgar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000000..c690872c02 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ru/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Выбрать и изменить подсказку</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sat/strings.xml new file mode 100644 index 0000000000..a57202cf0c --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sat/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">ᱵᱟᱛᱟᱣᱢᱮ ᱟᱨ ᱥᱩᱡᱷᱟᱹᱣ ᱥᱟᱯᱲᱟᱣ ᱢᱮ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sc/strings.xml new file mode 100644 index 0000000000..ea90dc6e82 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sc/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Atzeta e modìfica su cussìgiu</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-si/strings.xml new file mode 100644 index 0000000000..2ebd54bc30 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-si/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">යෝජනාව පිළිගෙන සංස්කරණය</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sk/strings.xml new file mode 100644 index 0000000000..e9b00f0de7 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Akceptovať návrh a pokračovať v úprave</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-skr/strings.xml new file mode 100644 index 0000000000..10bff0878f --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-skr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">تجویز کوں قبول کرو تے تبدیلی کرو</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sl/strings.xml new file mode 100644 index 0000000000..7fe0c78a16 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Sprejmi in uredi predlog</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sq/strings.xml new file mode 100644 index 0000000000..d4a0920d65 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sq/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Pranoni dhe përpunoni sugjerimin</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sr/strings.xml new file mode 100644 index 0000000000..f361a3045d --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Прихвати и уреди предлог</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-su/strings.xml new file mode 100644 index 0000000000..4b049e8e1f --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-su/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Tampa jeung édit saran</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sv-rSE/strings.xml new file mode 100644 index 0000000000..e9e8f2d57e --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-sv-rSE/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Acceptera och redigera förslag</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-szl/strings.xml new file mode 100644 index 0000000000..01a3221de9 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-szl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Akceptuj i edytuj dorada</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ta/strings.xml new file mode 100644 index 0000000000..822e2ca5da --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ta/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">பரிந்துரையை ஏற்று திருத்து</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tg/strings.xml new file mode 100644 index 0000000000..d7716c120b --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tg/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Пешниҳодро қабул ва таҳрир намоед</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-th/strings.xml new file mode 100644 index 0000000000..4f22694ca9 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-th/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">ยอมรับและแก้ไขข้อเสนอแนะ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tl/strings.xml new file mode 100644 index 0000000000..5df1097dc7 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Tanggapin at i-edit ang mungkahi</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tok/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tok/strings.xml new file mode 100644 index 0000000000..1cdbb57528 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tok/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">o kama jo, o ante</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tr/strings.xml new file mode 100644 index 0000000000..a50a78776c --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Öneriyi kabul et ve düzenle</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-trs/strings.xml new file mode 100644 index 0000000000..087edecc87 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-trs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Gārāyina nī nādūnāt nuguan\’ narikij</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tt/strings.xml new file mode 100644 index 0000000000..c15a889dbb --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-tt/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Тәкъдимне кабул итү һәм үзгәртү</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ug/strings.xml new file mode 100644 index 0000000000..476b29d8a2 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ug/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">تەكلىپنى قوبۇل قىلىپ تەھرىرلەيدۇ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uk/strings.xml new file mode 100644 index 0000000000..0ae5b6ef4f --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Прийняти та змінити пропозицію</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ur/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ur/strings.xml new file mode 100644 index 0000000000..defe8f4812 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-ur/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">تجویز کو قبول کریں اور ترمیم کریں</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uz/strings.xml new file mode 100644 index 0000000000..4dcf317d8c --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-uz/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Tavsiyani qabul qilish va tahrir qilish</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-vi/strings.xml new file mode 100644 index 0000000000..292a5cd7fb --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-vi/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Chấp nhận và chỉnh sửa đề xuất</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-yo/strings.xml new file mode 100644 index 0000000000..9112ee0856 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-yo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Gbà á, kí o sì ṣe àtuṣe àbá</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000..b21cab3d6c --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">接受并编辑建议</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000..87481af094 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">接受並編輯建議</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/main/res/values/strings.xml b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values/strings.xml new file mode 100644 index 0000000000..467a778b07 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ +<?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/. --> +<resources> + <!-- Description for the button to accept the search suggestion and continue editing the search. --> + <string name="mozac_browser_awesomebar_edit_suggestion">Accept and edit suggestion</string> +</resources> diff --git a/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcherTest.kt b/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcherTest.kt new file mode 100644 index 0000000000..489b13c834 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionFetcherTest.kt @@ -0,0 +1,69 @@ +/* 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 mozilla.components.compose.browser.awesomebar.internal + +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.Job +import mozilla.components.concept.awesomebar.AwesomeBar +import mozilla.components.concept.awesomebar.AwesomeBar.SuggestionProvider +import mozilla.components.concept.awesomebar.AwesomeBar.SuggestionProviderGroup +import mozilla.components.support.test.any +import mozilla.components.support.test.mock +import mozilla.components.support.test.rule.MainCoroutineRule +import mozilla.components.support.test.rule.runTestOnMain +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.mockito.Mockito.doAnswer +import org.mockito.Mockito.inOrder +import org.mockito.Mockito.spy + +@ExperimentalCoroutinesApi // for runTestOnMain +class SuggestionFetcherTest { + @get:Rule + val coroutinesTestRule = MainCoroutineRule() + + @Test + fun `GIVEN a new fetch request THEN all previous queries are cancelled`() = runTestOnMain { + val provider: SuggestionProvider = mock() + val providerGroup = SuggestionProviderGroup(listOf(provider)) + val fetcher = spy(SuggestionFetcher(listOf(providerGroup), null)) + val previousFetchJob: Job = mock() + fetcher.fetchJob = previousFetchJob + doAnswer {}.`when`(fetcher).fetchFrom(any(), any(), any(), any()) + val orderVerifier = inOrder(previousFetchJob, fetcher) + + fetcher.fetch("test") + + orderVerifier.verify(previousFetchJob)!!.cancel() + orderVerifier.verify(fetcher).fetchFrom(providerGroup, provider, "test", null) + } + + @Test + fun `GIVEN a suggestion group THEN the group's priority becomes highest suggestions' score within the group`() = runTestOnMain { + val provider: SuggestionProvider = mock() + val providerGroup = SuggestionProviderGroup(listOf(provider)) + val suggestions = listOf( + AwesomeBar.Suggestion( + provider = provider, + score = Int.MAX_VALUE, + ), + AwesomeBar.Suggestion( + provider = provider, + score = Int.MIN_VALUE, + ), + ) + val fetcher = spy(SuggestionFetcher(listOf(providerGroup), null)) + + fetcher.processResultFrom( + group = providerGroup, + provider = provider, + suggestions = suggestions, + profilerStartTime = null, + ) + + assertEquals(providerGroup.priority, Int.MAX_VALUE) + } +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionsTest.kt b/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionsTest.kt new file mode 100644 index 0000000000..488103f99a --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/test/java/mozilla/components/compose/browser/awesomebar/internal/SuggestionsTest.kt @@ -0,0 +1,173 @@ +/* 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 mozilla.components.compose.browser.awesomebar.internal + +import mozilla.components.concept.awesomebar.AwesomeBar.Suggestion +import mozilla.components.concept.awesomebar.AwesomeBar.SuggestionProvider +import mozilla.components.concept.awesomebar.AwesomeBar.SuggestionProviderGroup +import mozilla.components.support.test.mock +import mozilla.components.support.test.whenever +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test + +class SuggestionsTest { + @Test + fun `GIVEN 1 suggestion in 1 group WHEN neither are visible THEN return an empty visibility state`() { + val provider: SuggestionProvider = mock() + + val visibleItems = VisibleItems( + suggestions = mapOf(SuggestionProviderGroup(listOf(provider)) to listOf(Suggestion(provider))), + visibleItemKeys = emptyList(), + ) + + val visibilityState = visibleItems.toVisibilityState() + assertTrue(visibilityState.visibleProviderGroups.isEmpty()) + } + + @Test + fun `GIVEN 1 suggestion in 1 group WHEN both are visible THEN return a visibility state containing the suggestion`() { + val provider: SuggestionProvider = mock() + whenever(provider.id).thenReturn("provider") + val providerGroup = SuggestionProviderGroup(listOf(provider)) + val providerGroupSuggestions = listOf(Suggestion(provider)) + + val visibleItems = VisibleItems( + suggestions = mapOf(providerGroup to providerGroupSuggestions), + visibleItemKeys = listOf( + ItemKey.SuggestionGroup(providerGroup.id), + ItemKey.Suggestion(providerGroup.id, provider.id, providerGroupSuggestions[0].id), + ), + ) + + val visibilityState = visibleItems.toVisibilityState() + assertEquals( + visibilityState.visibleProviderGroups, + mapOf( + providerGroup to providerGroupSuggestions, + ), + ) + } + + @Test + fun `GIVEN 1 suggestion in 1 group WHEN only the suggestion is visible THEN return a visibility state containing the suggestion`() { + val provider: SuggestionProvider = mock() + whenever(provider.id).thenReturn("provider") + val providerGroup = SuggestionProviderGroup(listOf(provider)) + val providerGroupSuggestions = listOf(Suggestion(provider)) + + val visibleItems = VisibleItems( + suggestions = mapOf(providerGroup to providerGroupSuggestions), + visibleItemKeys = listOf( + ItemKey.Suggestion(providerGroup.id, provider.id, providerGroupSuggestions[0].id), + ), + ) + + val visibilityState = visibleItems.toVisibilityState() + assertEquals( + visibilityState.visibleProviderGroups, + mapOf( + providerGroup to providerGroupSuggestions, + ), + ) + } + + @Test + fun `GIVEN 2 suggestions in 1 group WHEN all are visible THEN return a visibility state containing the suggestions`() { + val provider: SuggestionProvider = mock() + whenever(provider.id).thenReturn("provider") + val providerGroup = SuggestionProviderGroup(listOf(provider)) + val providerGroupSuggestions = listOf(Suggestion(provider), Suggestion(provider)) + + val visibleItems = VisibleItems( + suggestions = mapOf(providerGroup to providerGroupSuggestions), + visibleItemKeys = listOf( + ItemKey.SuggestionGroup(providerGroup.id), + ItemKey.Suggestion(providerGroup.id, provider.id, providerGroupSuggestions[0].id), + ItemKey.Suggestion(providerGroup.id, provider.id, providerGroupSuggestions[1].id), + ), + ) + + val visibilityState = visibleItems.toVisibilityState() + assertEquals( + visibilityState.visibleProviderGroups, + mapOf( + providerGroup to providerGroupSuggestions, + ), + ) + } + + @Test + fun `GIVEN 2 suggestions in 2 groups WHEN 1 suggestion is visible in 1 group THEN return a visibility state containing the suggestion`() { + val firstProvider: SuggestionProvider = mock() + whenever(firstProvider.id).thenReturn("firstProvider") + val secondProvider: SuggestionProvider = mock() + whenever(secondProvider.id).thenReturn("secondProvider") + val thirdProvider: SuggestionProvider = mock() + whenever(thirdProvider.id).thenReturn("thirdProvider") + val firstProviderGroup = SuggestionProviderGroup(listOf(firstProvider, secondProvider)) + val firstProviderGroupSuggestions = listOf(Suggestion(firstProvider), Suggestion(secondProvider)) + val secondProviderGroup = SuggestionProviderGroup(listOf(secondProvider, thirdProvider)) + val secondProviderGroupSuggestions = listOf(Suggestion(secondProvider), Suggestion(thirdProvider)) + + val visibleItems = VisibleItems( + suggestions = mapOf( + firstProviderGroup to firstProviderGroupSuggestions, + secondProviderGroup to secondProviderGroupSuggestions, + ), + visibleItemKeys = listOf( + ItemKey.SuggestionGroup(firstProviderGroup.id), + ItemKey.Suggestion(firstProviderGroup.id, secondProvider.id, firstProviderGroupSuggestions[1].id), + ), + ) + + val visibilityState = visibleItems.toVisibilityState() + assertEquals( + visibilityState.visibleProviderGroups, + mapOf( + firstProviderGroup to listOf(firstProviderGroupSuggestions[1]), + ), + ) + } + + @Test + fun `GIVEN 2 suggestions in 2 groups WHEN 1 suggestion is visible in each group THEN return a visibility state containing the suggestions`() { + val firstProvider: SuggestionProvider = mock() + whenever(firstProvider.id).thenReturn("firstProvider") + + val secondProvider: SuggestionProvider = mock() + whenever(secondProvider.id).thenReturn("secondProvider") + + val thirdProvider: SuggestionProvider = mock() + whenever(thirdProvider.id).thenReturn("thirdProvider") + + val firstProviderGroup = SuggestionProviderGroup(listOf(firstProvider, secondProvider)) + val firstProviderGroupSuggestions = listOf(Suggestion(firstProvider), Suggestion(secondProvider)) + + val secondProviderGroup = SuggestionProviderGroup(listOf(secondProvider, thirdProvider)) + val secondProviderGroupSuggestions = listOf(Suggestion(secondProvider), Suggestion(thirdProvider)) + + val visibleItems = VisibleItems( + suggestions = mapOf( + firstProviderGroup to firstProviderGroupSuggestions, + secondProviderGroup to secondProviderGroupSuggestions, + ), + visibleItemKeys = listOf( + ItemKey.SuggestionGroup(firstProviderGroup.id), + ItemKey.Suggestion(firstProviderGroup.id, firstProvider.id, firstProviderGroupSuggestions[0].id), + ItemKey.SuggestionGroup(secondProviderGroup.id), + ItemKey.Suggestion(secondProviderGroup.id, thirdProvider.id, secondProviderGroupSuggestions[1].id), + ), + ) + val visibilityState = visibleItems.toVisibilityState() + assertEquals( + visibilityState.visibleProviderGroups, + mapOf( + firstProviderGroup to listOf(firstProviderGroupSuggestions[0]), + secondProviderGroup to listOf(secondProviderGroupSuggestions[1]), + ), + ) + } +} diff --git a/mobile/android/android-components/components/compose/awesomebar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/awesomebar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..cf1c399ea8 --- /dev/null +++ b/mobile/android/android-components/components/compose/awesomebar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1,2 @@ +mock-maker-inline +// This allows mocking final classes (classes are final by default in Kotlin) diff --git a/mobile/android/android-components/components/compose/browser-toolbar/README.md b/mobile/android/android-components/components/compose/browser-toolbar/README.md new file mode 100644 index 0000000000..1f6bdde813 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/README.md @@ -0,0 +1,19 @@ +# [Android Components](../../../README.md) > Compose > Browser Toolbar + +A customizable toolbar for browsers using Jetpack Compose. + +## Usage + +### Setting up the dependency + +Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)): + +```Groovy +implementation "org.mozilla.components:compose-browser-toolbar:{latest-version}" +``` + +## License + + 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/ diff --git a/mobile/android/android-components/components/compose/browser-toolbar/build.gradle b/mobile/android/android-components/components/compose/browser-toolbar/build.gradle new file mode 100644 index 0000000000..cf81cb173f --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/build.gradle @@ -0,0 +1,54 @@ +/* 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/. */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + defaultConfig { + minSdkVersion config.minSdkVersion + compileSdk config.compileSdkVersion + targetSdkVersion config.targetSdkVersion + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + buildFeatures { + compose true + } + + composeOptions { + kotlinCompilerExtensionVersion = Versions.compose_compiler + } + + namespace 'mozilla.components.compose.browser.toolbar' +} + +dependencies { + implementation project(":concept-engine") + implementation project(":browser-state") + implementation project(":feature-session") + implementation project(":ui-icons") + implementation ComponentsDependencies.androidx_compose_ui + implementation ComponentsDependencies.androidx_compose_ui_tooling_preview + implementation ComponentsDependencies.androidx_compose_foundation + implementation ComponentsDependencies.androidx_compose_material + + debugImplementation ComponentsDependencies.androidx_compose_ui_tooling + + testImplementation project(':support-test') + testImplementation ComponentsDependencies.androidx_compose_ui_test + testImplementation ComponentsDependencies.androidx_test_core + testImplementation ComponentsDependencies.androidx_test_junit + testImplementation ComponentsDependencies.testing_robolectric +} + +apply from: '../../../android-lint.gradle' +apply from: '../../../publish.gradle' +ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description) diff --git a/mobile/android/android-components/components/compose/browser-toolbar/proguard-rules.pro b/mobile/android/android-components/components/compose/browser-toolbar/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e16cda1d34 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ +<!-- 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/. --> +<manifest /> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserDisplayToolbar.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserDisplayToolbar.kt new file mode 100644 index 0000000000..f4169184aa --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserDisplayToolbar.kt @@ -0,0 +1,62 @@ +/* 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 mozilla.components.compose.browser.toolbar + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Button +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.contentColorFor +import androidx.compose.material.primarySurface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +/** + * Sub-component of the [BrowserToolbar] responsible for displaying the URL and related + * controls ("display mode"). + * + * @param url The URL to be displayed. + * @param onUrlClicked Will be called when the user clicks on the URL. + * @param onMenuClicked Will be called when the user clicks on the menu button. + * @param browserActions Additional browser actions to be displayed on the right side of the toolbar + * (outside of the URL bounding box) in display mode. Also see: + * [MDN docs](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Browser_action) + */ +@Composable +fun BrowserDisplayToolbar( + url: String, + onUrlClicked: () -> Unit = {}, + onMenuClicked: () -> Unit = {}, + browserActions: @Composable () -> Unit = {}, +) { + val backgroundColor = MaterialTheme.colors.primarySurface + val foregroundColor = contentColorFor(backgroundColor) + + Row( + Modifier.background(backgroundColor), + ) { + Text( + url, + color = foregroundColor, + modifier = Modifier + .clickable { onUrlClicked() } + .padding(8.dp) + .weight(1f) + .align(Alignment.CenterVertically), + maxLines = 1, + ) + + browserActions() + + Button(onClick = { onMenuClicked() }) { + Text(":") + } + } +} diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserEditToolbar.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserEditToolbar.kt new file mode 100644 index 0000000000..455fc1b2a0 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserEditToolbar.kt @@ -0,0 +1,93 @@ +/* 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 mozilla.components.compose.browser.toolbar + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.TextField +import androidx.compose.material.TextFieldDefaults +import androidx.compose.material.contentColorFor +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import mozilla.components.ui.icons.R as iconsR + +/** + * Sub-component of the [BrowserToolbar] responsible for allowing the user to edit the current + * URL ("edit mode"). + * + * @param url The initial URL to be edited. + * @param onUrlEdit Will be called when the URL value changes. An updated text value comes as a + * parameter of the callback. + * @param onUrlCommitted Will be called when the user has finished editing and wants to initiate + * loading the entered URL. The committed text value comes as a parameter of the callback. + * @param editActions Optional actions to be displayed on the right side of the toolbar. + */ +@Composable +fun BrowserEditToolbar( + url: String, + onUrlEdit: (String) -> Unit = {}, + onUrlCommitted: (String) -> Unit = {}, + editActions: @Composable () -> Unit = {}, +) { + val backgroundColor = MaterialTheme.colors.surface + val foregroundColor = contentColorFor(backgroundColor) + + TextField( + url, + onValueChange = { value -> + onUrlEdit(value) + }, + colors = TextFieldDefaults.textFieldColors( + textColor = foregroundColor, + backgroundColor = backgroundColor, + ), + singleLine = true, + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Uri, + imeAction = ImeAction.Go, + ), + keyboardActions = KeyboardActions( + onGo = { onUrlCommitted(url) }, + ), + modifier = Modifier.fillMaxWidth(), + trailingIcon = { + editActions() + + if (url.isNotEmpty()) { + ClearButton(onButtonClicked = { onUrlEdit("") }) + } + }, + ) +} + +/** + * Sub-component of the [BrowserEditToolbar] responsible for displaying a clear icon button. + * + * @param onButtonClicked Will be called when the user clicks on the button. + */ +@Composable +fun ClearButton(onButtonClicked: () -> Unit = {}) { + IconButton( + modifier = Modifier.requiredSize(40.dp), + onClick = { onButtonClicked() }, + ) { + Icon( + painter = painterResource(iconsR.drawable.mozac_ic_cross_circle_fill_24), + contentDescription = stringResource(R.string.mozac_clear_button_description), + tint = Color.Black, + ) + } +} diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserToolbar.kt b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserToolbar.kt new file mode 100644 index 0000000000..37c4b8f19f --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/java/mozilla/components/compose/browser/toolbar/BrowserToolbar.kt @@ -0,0 +1,77 @@ +/* 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 mozilla.components.compose.browser.toolbar + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import mozilla.components.browser.state.helper.Target +import mozilla.components.browser.state.state.SessionState +import mozilla.components.browser.state.store.BrowserStore + +/** + * A customizable toolbar for browsers. + * + * The toolbar can switch between two modes: display and edit. The display mode displays the current + * URL and controls for navigation. In edit mode the current URL can be edited. Those two modes are + * implemented by the [BrowserDisplayToolbar] and [BrowserEditToolbar] composables. + * + * @param store The store to observe the [target] from. + * @param target The target tab to observe. + * @param onDisplayMenuClicked Function to get executed when the user clicks on the menu button in + * "display" mode. + * @param onTextEdit Function to get executed whenever the user edits the text in the toolbar in + * "edit" mode. + * @param onTextCommit Function to get executed when the user has finished editing the URL and wants + * to load the entered text. + * @param onDisplayToolbarClick Function to get executed when the user clicks on the URL in "display" + * mode. + * @param hint Text displayed in the toolbar when there's no URL to display (no tab or empty URL) + * @param editMode Whether the toolbar is in "edit" or "display" mode. + * @param editText The text the user is editing in "edit" mode. + * @param browserActions Additional browser actions to be displayed on the right side of the toolbar + * (outside of the URL bounding box) in display mode. Also see: + * [MDN docs](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/user_interface/Browser_action) + */ +@Composable +fun BrowserToolbar( + store: BrowserStore, + target: Target, + onDisplayMenuClicked: () -> Unit, + onTextEdit: (String) -> Unit, + onTextCommit: (String) -> Unit, + onDisplayToolbarClick: () -> Unit, + hint: String = "", + editMode: Boolean = false, + editText: String? = null, + browserActions: @Composable () -> Unit = {}, +) { + val selectedTab: SessionState? by target.observeAsComposableStateFrom( + store = store, + observe = { tab -> tab?.content?.url }, + ) + + val url = selectedTab?.content?.url ?: "" + val input = when (editText) { + null -> url + else -> editText + } + + if (editMode) { + BrowserEditToolbar( + url = input, + onUrlCommitted = { text -> onTextCommit(text) }, + onUrlEdit = { text -> onTextEdit(text) }, + ) + } else { + BrowserDisplayToolbar( + url = selectedTab?.content?.url ?: hint, + onUrlClicked = { + onDisplayToolbarClick() + }, + onMenuClicked = { onDisplayMenuClicked() }, + browserActions = browserActions, + ) + } +} diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-am/strings.xml new file mode 100644 index 0000000000..cc83ed16e6 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-am/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">አጽዳ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ar/strings.xml new file mode 100644 index 0000000000..c9d3504f7a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ar/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">امسح</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ast/strings.xml new file mode 100644 index 0000000000..8969801e9c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ast/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Borrar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-azb/strings.xml new file mode 100644 index 0000000000..6f4f648a48 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-azb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">تمیزله</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ban/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ban/strings.xml new file mode 100644 index 0000000000..d5f16e8163 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ban/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Puyung</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-be/strings.xml new file mode 100644 index 0000000000..70c10b132a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-be/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Ачысціць</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bg/strings.xml new file mode 100644 index 0000000000..0f5a47334b --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bg/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Изчистване</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-br/strings.xml new file mode 100644 index 0000000000..d38dc27f6b --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-br/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Skarzhañ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bs/strings.xml new file mode 100644 index 0000000000..8bc86d499b --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-bs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Očisti</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ca/strings.xml new file mode 100644 index 0000000000..018996c9c9 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ca/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Esborra</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cak/strings.xml new file mode 100644 index 0000000000..bbd7009b91 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cak/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Tijosq\'ïx</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ceb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ceb/strings.xml new file mode 100644 index 0000000000..2925ea5493 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ceb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">i-Clear</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ckb/strings.xml new file mode 100644 index 0000000000..086ca6fc70 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ckb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">پاککردنەوە</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-co/strings.xml new file mode 100644 index 0000000000..b5fe5d43e5 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-co/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Squassà</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cs/strings.xml new file mode 100644 index 0000000000..32faa95f9c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Vymazat</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cy/strings.xml new file mode 100644 index 0000000000..69f49ff160 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-cy/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Clirio</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-da/strings.xml new file mode 100644 index 0000000000..3b0a1d032f --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-da/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Ryd</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-de/strings.xml new file mode 100644 index 0000000000..6858b4ca9c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-de/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Löschen</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-dsb/strings.xml new file mode 100644 index 0000000000..b63020c065 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-dsb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Lašowaś</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-el/strings.xml new file mode 100644 index 0000000000..081fa1408f --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-el/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Απαλοιφή</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rCA/strings.xml new file mode 100644 index 0000000000..4623e3ea6f --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rCA/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Clear</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 0000000000..4623e3ea6f --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Clear</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eo/strings.xml new file mode 100644 index 0000000000..147fe28ba9 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Viŝi</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 0000000000..3bee2874ce --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Eliminar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rCL/strings.xml new file mode 100644 index 0000000000..4d4c14d193 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rCL/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Limpiar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rES/strings.xml new file mode 100644 index 0000000000..8969801e9c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rES/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Borrar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rMX/strings.xml new file mode 100644 index 0000000000..4d4c14d193 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es-rMX/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Limpiar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es/strings.xml new file mode 100644 index 0000000000..8969801e9c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-es/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Borrar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-et/strings.xml new file mode 100644 index 0000000000..2257c3c05b --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-et/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Tühjenda</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eu/strings.xml new file mode 100644 index 0000000000..ff2b1734b6 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-eu/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Garbitu</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fa/strings.xml new file mode 100644 index 0000000000..d5f3070338 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fa/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">پاک کردن</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fi/strings.xml new file mode 100644 index 0000000000..a2b754496a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fi/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Tyhjennä</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000000..2fa9bb437d --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Effacer</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fur/strings.xml new file mode 100644 index 0000000000..0dac627d5a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fur/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Nete</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fy-rNL/strings.xml new file mode 100644 index 0000000000..91cb2126f6 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-fy-rNL/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Wiskje</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gd/strings.xml new file mode 100644 index 0000000000..f3515f5318 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gd/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Falamhaich</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gl/strings.xml new file mode 100644 index 0000000000..8969801e9c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Borrar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gn/strings.xml new file mode 100644 index 0000000000..f1f838a3fa --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-gn/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Mopotĩ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hi-rIN/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hi-rIN/strings.xml new file mode 100644 index 0000000000..3066768614 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hi-rIN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">साफ करें</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hil/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hil/strings.xml new file mode 100644 index 0000000000..f213be78ce --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hil/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Maathag</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hr/strings.xml new file mode 100644 index 0000000000..8bc86d499b --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Očisti</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hsb/strings.xml new file mode 100644 index 0000000000..db7ed389d1 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hsb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Zhašeć</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hu/strings.xml new file mode 100644 index 0000000000..240457e51a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hu/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Törlés</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000000..3161e41469 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-hy-rAM/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Մաքրել</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ia/strings.xml new file mode 100644 index 0000000000..9e74fc636d --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ia/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Vacuar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-in/strings.xml new file mode 100644 index 0000000000..5b7255a507 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-in/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Bersihkan</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-is/strings.xml new file mode 100644 index 0000000000..937c569911 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-is/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Hreinsa</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-it/strings.xml new file mode 100644 index 0000000000..50fac45c09 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-it/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Cancella</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-iw/strings.xml new file mode 100644 index 0000000000..6d2a870121 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-iw/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">ניקוי</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ja/strings.xml new file mode 100644 index 0000000000..aac287abba --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ja/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">消去</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ka/strings.xml new file mode 100644 index 0000000000..8f2d68db5a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ka/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">გასუფთავება</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kaa/strings.xml new file mode 100644 index 0000000000..d353a36ede --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kaa/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Tazalaw</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kab/strings.xml new file mode 100644 index 0000000000..57e718ffd4 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kab/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Sfeḍ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kk/strings.xml new file mode 100644 index 0000000000..f37edf1617 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Тазарту</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kmr/strings.xml new file mode 100644 index 0000000000..ea5900bfd7 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-kmr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Paqij bike</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ko/strings.xml new file mode 100644 index 0000000000..35026ad285 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ko/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">지우기</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lo/strings.xml new file mode 100644 index 0000000000..fc861c9736 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">ລົບລ້າງ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lt/strings.xml new file mode 100644 index 0000000000..b13f1a2607 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-lt/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Išvalyti</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mix/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mix/strings.xml new file mode 100644 index 0000000000..32ec654860 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mix/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Stòo</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mr/strings.xml new file mode 100644 index 0000000000..15f1015506 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-mr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">पुसा</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-my/strings.xml new file mode 100644 index 0000000000..e6d5127701 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-my/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">ရှင်းမည်</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nb-rNO/strings.xml new file mode 100644 index 0000000000..cc9fc95eaf --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nb-rNO/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Tøm</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ne-rNP/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ne-rNP/strings.xml new file mode 100644 index 0000000000..5701e65481 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ne-rNP/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">मेटाउनुहोस्</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nl/strings.xml new file mode 100644 index 0000000000..d0a8d68480 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Wissen</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nn-rNO/strings.xml new file mode 100644 index 0000000000..cc9fc95eaf --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-nn-rNO/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Tøm</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-oc/strings.xml new file mode 100644 index 0000000000..7c2f957fea --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-oc/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Escafar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 0000000000..146f91fc44 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">ਮਿਟਾਓ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rPK/strings.xml new file mode 100644 index 0000000000..638b35e354 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pa-rPK/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">صاف کرو</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pl/strings.xml new file mode 100644 index 0000000000..fba0dba88d --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Wyczyść</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000000..2bc6e2c75c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Limpar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000..2bc6e2c75c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Limpar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-rm/strings.xml new file mode 100644 index 0000000000..119b5bb88a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-rm/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Stizzar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000000..0047495c9b --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ru/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Очистить</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sat/strings.xml new file mode 100644 index 0000000000..45acd3ce30 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sat/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">ᱯᱷᱟᱨᱪᱟ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sc/strings.xml new file mode 100644 index 0000000000..5714c62681 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sc/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Isbòida</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-si/strings.xml new file mode 100644 index 0000000000..f293461379 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-si/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">මකන්න</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sk/strings.xml new file mode 100644 index 0000000000..0947ba13c0 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Vymazať</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-skr/strings.xml new file mode 100644 index 0000000000..638b35e354 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-skr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">صاف کرو</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sl/strings.xml new file mode 100644 index 0000000000..a7c9e71591 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Počisti</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sq/strings.xml new file mode 100644 index 0000000000..a64bf5d1cd --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sq/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Spastroje</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sr/strings.xml new file mode 100644 index 0000000000..c177a14273 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Избриши</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-su/strings.xml new file mode 100644 index 0000000000..ff2dd9505c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-su/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Beresihan</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sv-rSE/strings.xml new file mode 100644 index 0000000000..5c48a34f29 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-sv-rSE/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Rensa</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-szl/strings.xml new file mode 100644 index 0000000000..2d780d888d --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-szl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Wypucuj</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ta/strings.xml new file mode 100644 index 0000000000..5b59215996 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ta/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">துடை</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-te/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-te/strings.xml new file mode 100644 index 0000000000..d7291694e8 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-te/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">తుడిచివేయి</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tg/strings.xml new file mode 100644 index 0000000000..04bcc69e4c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tg/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Пок кардан</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-th/strings.xml new file mode 100644 index 0000000000..19dfaf0570 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-th/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">ล้าง</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tl/strings.xml new file mode 100644 index 0000000000..2c4826414a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Malinaw</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tok/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tok/strings.xml new file mode 100644 index 0000000000..bfb8cb0176 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tok/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">o weka ale</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tr/strings.xml new file mode 100644 index 0000000000..7f12eb014a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Temizle</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-trs/strings.xml new file mode 100644 index 0000000000..d4117dca83 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-trs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Nā\'nïn\'</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tt/strings.xml new file mode 100644 index 0000000000..38e4b155a9 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tt/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Чистарту</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tzm/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tzm/strings.xml new file mode 100644 index 0000000000..57e718ffd4 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-tzm/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Sfeḍ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ug/strings.xml new file mode 100644 index 0000000000..b77a27beb2 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ug/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">تازىلاش</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uk/strings.xml new file mode 100644 index 0000000000..21148d9315 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Очистити</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ur/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ur/strings.xml new file mode 100644 index 0000000000..9ba273e59b --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-ur/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">صاف کریں</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uz/strings.xml new file mode 100644 index 0000000000..2424d47c2a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-uz/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Tozalash</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vec/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vec/strings.xml new file mode 100644 index 0000000000..5f2923d53a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vec/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Pulisi</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vi/strings.xml new file mode 100644 index 0000000000..192ec68ca5 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-vi/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Xóa</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-yo/strings.xml new file mode 100644 index 0000000000..e49144b27c --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-yo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Paárẹ́</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000..21720f256a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">清除</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000..21720f256a --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">清除</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values/strings.xml b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values/strings.xml new file mode 100644 index 0000000000..ae85fd5c80 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ +<?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/. --> +<resources> + <!-- Content description for the clear URL text button. --> + <string name="mozac_clear_button_description">Clear</string> +</resources> diff --git a/mobile/android/android-components/components/compose/browser-toolbar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/browser-toolbar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..cf1c399ea8 --- /dev/null +++ b/mobile/android/android-components/components/compose/browser-toolbar/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1,2 @@ +mock-maker-inline +// This allows mocking final classes (classes are final by default in Kotlin) diff --git a/mobile/android/android-components/components/compose/cfr/README.md b/mobile/android/android-components/components/compose/cfr/README.md new file mode 100644 index 0000000000..843ac13f7f --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/README.md @@ -0,0 +1,49 @@ +# [Android Components](../../../README.md) > Compose > Tabs tray + +A standard Contextual Feature Recommendation popup using Jetpack Compose. + +## Usage + +```kotlin +CFRPopup( + anchor = <View>, + properties = CFRPopupProperties( + popupWidth = 256.dp, + popupAlignment = INDICATOR_CENTERED_IN_ANCHOR, + popupBodyColors = listOf( + ContextCompat.getColor(context, R.color.color1), + ContextCompat.getColor(context, R.color.color2) + ), + dismissButtonColor = ContextCompat.getColor(context, R.color.color3), + ), + onDismiss = { <method call> }, + text = { + Text( + text = stringResource(R.string.string1), + style = MaterialTheme.typography.body2, + ) + }, + action = { + Button(onClick = { <method call> }) { + Text(text = stringResource(R.string.string2)) + } + }, +).apply { + show() +} +``` + + +### Setting up the dependency + +Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)): + +```Groovy +implementation "org.mozilla.components:compose-cfr:{latest-version}" +``` + +## License + + 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/ diff --git a/mobile/android/android-components/components/compose/cfr/build.gradle b/mobile/android/android-components/components/compose/cfr/build.gradle new file mode 100644 index 0000000000..84e722924e --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/build.gradle @@ -0,0 +1,63 @@ +/* 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/. */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + defaultConfig { + minSdkVersion config.minSdkVersion + compileSdk config.compileSdkVersion + targetSdkVersion config.targetSdkVersion + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + buildFeatures { + compose true + } + + composeOptions { + kotlinCompilerExtensionVersion = Versions.compose_compiler + } + + kotlinOptions { + freeCompilerArgs += "-Xjvm-default=all" + } + + namespace 'mozilla.components.compose.cfr' +} + +dependencies { + implementation platform(ComponentsDependencies.androidx_compose_bom) + implementation project(':support-ktx') + implementation project(':ui-icons') + + implementation ComponentsDependencies.androidx_compose_ui + implementation ComponentsDependencies.androidx_compose_ui_tooling_preview + implementation ComponentsDependencies.androidx_compose_foundation + implementation ComponentsDependencies.androidx_compose_material + implementation ComponentsDependencies.androidx_core + implementation ComponentsDependencies.androidx_core_ktx + implementation ComponentsDependencies.androidx_lifecycle_runtime + implementation ComponentsDependencies.androidx_savedstate + + debugImplementation ComponentsDependencies.androidx_compose_ui_tooling + + testImplementation project(':support-test') + testImplementation ComponentsDependencies.testing_coroutines + testImplementation ComponentsDependencies.androidx_test_core + testImplementation ComponentsDependencies.androidx_test_junit + testImplementation ComponentsDependencies.testing_junit + testImplementation ComponentsDependencies.testing_robolectric +} + +apply from: '../../../publish.gradle' +ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description) diff --git a/mobile/android/android-components/components/compose/cfr/proguard-rules.pro b/mobile/android/android-components/components/compose/cfr/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/mobile/android/android-components/components/compose/cfr/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/cfr/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e16cda1d34 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ +<!-- 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/. --> +<manifest /> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopup.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopup.kt new file mode 100644 index 0000000000..7d18e795b3 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopup.kt @@ -0,0 +1,195 @@ +/* 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 mozilla.components.compose.cfr + +import android.view.View +import androidx.annotation.VisibleForTesting +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection +import mozilla.components.compose.cfr.CFRPopup.PopupAlignment +import java.lang.ref.WeakReference + +/** + * Properties used to customize the behavior of a [CFRPopup]. + * + * @property popupWidth Width of the popup. Defaults to [CFRPopup.DEFAULT_WIDTH]. To be used as maximum + * width when alignment is set to [PopupAlignment.BODY_CENTERED_IN_SCREEN]. + * @property popupAlignment Where in relation to it's anchor should the popup be placed. + * @property popupBodyColors One or more colors serving as the popup background. + * If more colors are provided they will be used in a gradient. + * @property popupVerticalOffset Vertical distance between the indicator arrow and the anchor. + * This only applies if [overlapAnchor] is `false`. + * @property dismissButtonColor The tint color that should be applied to the dismiss button. + * @property dismissOnBackPress Whether the popup can be dismissed by pressing the back button. + * If true, pressing the back button will also call onDismiss(). + * @property dismissOnClickOutside Whether the popup can be dismissed by clicking outside the + * popup's bounds. If true, clicking outside the popup will call onDismiss(). + * @property overlapAnchor How the popup's indicator will be shown in relation to the anchor: + * - true - indicator will be shown exactly in the middle horizontally and vertically + * - false - indicator will be shown horizontally in the middle of the anchor but immediately below or above it + * @property indicatorDirection The direction the indicator arrow is pointing. + * @property indicatorArrowStartOffset Maximum distance between the popup start and the indicator arrow. + * If there isn't enough space this could automatically be overridden up to 0 such that + * the indicator arrow will be pointing to the middle of the anchor. + */ +data class CFRPopupProperties( + val popupWidth: Dp = CFRPopup.DEFAULT_WIDTH.dp, + val popupAlignment: PopupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER, + val popupBodyColors: List<Int> = listOf(Color.Blue.toArgb()), + val popupVerticalOffset: Dp = CFRPopup.DEFAULT_VERTICAL_OFFSET.dp, + val showDismissButton: Boolean = true, + val dismissButtonColor: Int = Color.Black.toArgb(), + val dismissOnBackPress: Boolean = false, + val dismissOnClickOutside: Boolean = false, + val overlapAnchor: Boolean = false, + val indicatorDirection: IndicatorDirection = IndicatorDirection.UP, + val indicatorArrowStartOffset: Dp = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp, +) + +/** + * CFR - Contextual Feature Recommendation popup. + * + * @param anchor [View] that will serve as the anchor of the popup and serve as lifecycle owner + * for this popup also. + * @param properties [CFRPopupProperties] allowing to customize the popup appearance and behavior. + * @param onDismiss Callback for when the popup is dismissed indicating also if the dismissal + * was explicit - by tapping the "X" button or not. + * @param text [Text] already styled and ready to be shown in the popup. + * @param action Optional other composable to show just below the popup text. + */ +class CFRPopup( + @get:VisibleForTesting internal val anchor: View, + @get:VisibleForTesting internal val properties: CFRPopupProperties, + @get:VisibleForTesting internal val onDismiss: (Boolean) -> Unit = {}, + @get:VisibleForTesting internal val text: @Composable (() -> Unit), + @get:VisibleForTesting internal val action: @Composable (() -> Unit) = {}, +) { + // This is just a facade for the CFRPopupFullScreenLayout composable offering a cleaner API. + + @VisibleForTesting + internal var popup: WeakReference<CFRPopupFullscreenLayout>? = null + + /** + * Construct and display a styled CFR popup shown at the coordinates of [anchor]. + * This popup will be dismissed when the user clicks on the "x" button or based on other user actions + * with such behavior set in [CFRPopupProperties]. + */ + fun show() { + anchor.post { + // When we're in this Runnable, the 'show' method might have been called right before + // the activity is no longer attached to the WindowManager. When we get to calling + // the CFRPopupFullscreenLayout#show method below, we are now trying to attach the View + // with the WindowManager that has an unusable Activity. + // + // To protect against this, within this same Runnable, we check if the anchor view is + // safe to use before continuing. + // + // See: https://bugzilla.mozilla.org/show_bug.cgi?id=1799996 + if (anchor.context == null || !anchor.isAttachedToWindow) { + return@post + } + + CFRPopupFullscreenLayout(anchor, properties, onDismiss, text, action).apply { + this.show() + popup = WeakReference(this) + } + } + } + + /** + * Immediately dismiss this CFR popup. + * The [onDismiss] callback won't be fired. + */ + fun dismiss() { + popup?.get()?.dismiss() + } + + /** + * Possible direction for the arrow indicator of a CFR popup. + * The direction is expressed in relation with the popup body containing the text. + */ + enum class IndicatorDirection { + UP, + DOWN, + } + + /** + * Possible alignments of the popup in relation to it's anchor. + */ + enum class PopupAlignment { + /** + * The popup body will be centered in the space occupied by the anchor. + * Recommended to be used when the anchor is wider than the popup. + */ + BODY_TO_ANCHOR_CENTER, + + /** + * The popup body will be shown aligned to exactly the anchor start. + */ + BODY_TO_ANCHOR_START, + + /** + * The popup will be aligned such that the indicator arrow will point to exactly the middle of the anchor. + * Recommended to be used when there are multiple widgets displayed horizontally so that this will allow + * to indicate exactly which widget the popup refers to. + */ + INDICATOR_CENTERED_IN_ANCHOR, + + /** + * If the popup doesn't have enough space to expand to its full [CFRPopupProperties.popupWidth], + * it will be centred in the screen. + * If the popup does have enough space, it defaults to [INDICATOR_CENTERED_IN_ANCHOR]. + * Recommended to be used when the popup text is very long. + */ + BODY_CENTERED_IN_SCREEN, + } + + companion object { + /** + * Default width for all CFRs. + */ + internal const val DEFAULT_WIDTH = 335 + + /** + * Fixed horizontal padding. + * Allows the close button to extend with 10dp more to the end and intercept touches to + * a bit outside of the popup to ensure it respects a11y recommendations of 48dp size while + * also offer a bit more space to the text. + */ + internal const val DEFAULT_EXTRA_HORIZONTAL_PADDING = 10 + + /** + * How tall the indicator arrow should be. + * This will also affect the width of the indicator's base which is double the height value. + */ + internal const val DEFAULT_INDICATOR_HEIGHT = 7 + + /** + * Maximum distance between the popup start and the indicator. + */ + internal const val DEFAULT_INDICATOR_START_OFFSET = 30 + + /** + * Corner radius for the popup body. + */ + internal const val DEFAULT_CORNER_RADIUS = 12 + + /** + * Vertical distance between the indicator arrow and the anchor. + */ + internal const val DEFAULT_VERTICAL_OFFSET = 9 + + /** + * Horizontal margin between the popup and viewport edges used to center the popup when alignment + * is set to [PopupAlignment.BODY_CENTERED_IN_SCREEN]. + */ + internal const val DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP = 16 + } +} diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupContent.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupContent.kt new file mode 100644 index 0000000000..318bf16829 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupContent.kt @@ -0,0 +1,186 @@ +/* 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 mozilla.components.compose.cfr + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTag +import androidx.compose.ui.semantics.testTagsAsResourceId +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.DOWN +import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.UP +import mozilla.components.ui.icons.R as iconsR + +/** + * Complete content of the popup. + * [CFRPopupShape] with a gradient background containing [text] and a dismiss ("X") button. + * + * @param popupBodyColors One or more colors serving as the popup background. + * @param dismissButtonColor The tint color that should be applied to the dismiss button. + * @param indicatorDirection The direction the indicator arrow is pointing to. + * @param indicatorArrowStartOffset Maximum distance between the popup start and the indicator arrow. + * If there isn't enough space this could automatically be overridden up to 0. + * @param onDismiss Callback for when the popup is dismissed indicating also if the dismissal + * was explicit - by tapping the "X" button or not. + * @param text [Text] already styled and ready to be shown in the popup. + * @param action Optional other composable to show just below the popup text. + */ +@OptIn(ExperimentalComposeUiApi::class) +@Composable +@Suppress("LongMethod") +fun CFRPopupContent( + popupBodyColors: List<Int>, + showDismissButton: Boolean, + dismissButtonColor: Int, + indicatorDirection: CFRPopup.IndicatorDirection, + indicatorArrowStartOffset: Dp, + onDismiss: (Boolean) -> Unit, + popupWidth: Dp = CFRPopup.DEFAULT_WIDTH.dp, + text: @Composable (() -> Unit), + action: @Composable (() -> Unit) = {}, +) { + val popupShape = CFRPopupShape( + indicatorDirection, + indicatorArrowStartOffset, + CFRPopup.DEFAULT_INDICATOR_HEIGHT.dp, + CFRPopup.DEFAULT_CORNER_RADIUS.dp, + ) + + Box(modifier = Modifier.width(popupWidth + CFRPopup.DEFAULT_EXTRA_HORIZONTAL_PADDING.dp)) { + Surface( + color = Color.Transparent, + // Need to override the default RectangleShape to avoid casting shadows for that shape. + shape = popupShape, + modifier = Modifier + .align(Alignment.CenterStart) + .background( + shape = popupShape, + brush = Brush.linearGradient( + colors = popupBodyColors.map { Color(it) }, + end = Offset(0f, Float.POSITIVE_INFINITY), + start = Offset(Float.POSITIVE_INFINITY, 0f), + ), + ) + .wrapContentHeight() + .width(popupWidth), + ) { + Column( + modifier = Modifier + .padding( + start = 16.dp, + top = 16.dp + if (indicatorDirection == CFRPopup.IndicatorDirection.UP) { + CFRPopup.DEFAULT_INDICATOR_HEIGHT.dp + } else { + 0.dp + }, + end = 16.dp, + bottom = 16.dp + + if (indicatorDirection == CFRPopup.IndicatorDirection.DOWN) { + CFRPopup.DEFAULT_INDICATOR_HEIGHT.dp + } else { + 0.dp + }, + ), + ) { + Box( + modifier = Modifier.padding( + end = if (showDismissButton) 24.dp else 16.dp, // 8.dp extra padding to the "X" icon + ), + ) { + text() + } + + action() + } + } + + if (showDismissButton) { + IconButton( + onClick = { onDismiss(true) }, + modifier = Modifier + .align(Alignment.TopEnd) + .padding( + end = 6.dp, + ) + .size(48.dp) + .semantics { + testTagsAsResourceId = true + testTag = "cfr.dismiss" + }, + ) { + Icon( + painter = painterResource(iconsR.drawable.mozac_ic_cross_20), + contentDescription = stringResource(R.string.mozac_cfr_dismiss_button_content_description), + modifier = Modifier + // Following alignment and padding are intended to visually align the middle + // of the "X" button with the top of the text. + .align(Alignment.Center) + .padding( + top = if (indicatorDirection == CFRPopup.IndicatorDirection.UP) 9.dp else 0.dp, + ) + .size(24.dp), + tint = Color(dismissButtonColor), + ) + } + } + } +} + +@Composable +@Preview(locale = "en", name = "LTR") +@Preview(locale = "ar", name = "RTL") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme") +private fun CFRPopupAbovePreview() { + CFRPopupContent( + popupBodyColors = listOf(Color.Cyan.toArgb(), Color.Blue.toArgb()), + showDismissButton = true, + dismissButtonColor = Color.Black.toArgb(), + indicatorDirection = DOWN, + indicatorArrowStartOffset = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp, + onDismiss = { }, + text = { Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod") }, + ) +} + +@Composable +@Preview(locale = "en", name = "LTR") +@Preview(locale = "ar", name = "RTL") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme") +private fun CFRPopupBelowPreview() { + CFRPopupContent( + popupBodyColors = listOf(Color.Cyan.toArgb(), Color.Blue.toArgb()), + showDismissButton = true, + dismissButtonColor = Color.Black.toArgb(), + indicatorDirection = UP, + indicatorArrowStartOffset = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp, + onDismiss = { }, + text = { Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod") }, + ) +} diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayout.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayout.kt new file mode 100644 index 0000000000..2ef47182ab --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayout.kt @@ -0,0 +1,537 @@ +/* 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 mozilla.components.compose.cfr + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.PixelFormat +import android.view.View +import android.view.WindowManager +import androidx.annotation.Px +import androidx.annotation.VisibleForTesting +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.AbstractComposeView +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.ViewRootForInspector +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntRect +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.LayoutDirection.Ltr +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Popup +import androidx.compose.ui.window.PopupPositionProvider +import androidx.compose.ui.window.PopupProperties +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import androidx.lifecycle.findViewTreeLifecycleOwner +import androidx.lifecycle.setViewTreeLifecycleOwner +import androidx.savedstate.findViewTreeSavedStateRegistryOwner +import androidx.savedstate.setViewTreeSavedStateRegistryOwner +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.DOWN +import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.UP +import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.BODY_CENTERED_IN_SCREEN +import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.BODY_TO_ANCHOR_CENTER +import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.BODY_TO_ANCHOR_START +import mozilla.components.compose.cfr.CFRPopup.PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR +import mozilla.components.compose.cfr.CFRPopupShape.Companion +import mozilla.components.compose.cfr.helper.DisplayOrientationListener +import mozilla.components.compose.cfr.helper.ViewDetachedListener +import mozilla.components.support.ktx.android.util.dpToPx +import mozilla.components.support.ktx.android.view.toScope +import kotlin.math.absoluteValue +import kotlin.math.roundToInt + +@VisibleForTesting +internal const val SHOW_AFTER_SCREEN_ORIENTATION_CHANGE_DELAY = 500L + +/** + * Value class allowing to easily reason about what an `Int` represents. + * This is compiled to the underlying `Int` type so incurs no performance penalty. + */ +@JvmInline +@VisibleForTesting +internal value class Pixels(val value: Int) + +/** + * Simple wrapper over the absolute x-coordinates of the popup. Includes any paddings. + */ +@VisibleForTesting +internal data class PopupHorizontalBounds( + val startCoord: Pixels, + val endCoord: Pixels, +) + +/** + * [AbstractComposeView] that can be added or removed dynamically in the current window to display + * a [Composable] based popup anywhere on the screen. + * + * @param anchor [View] that will serve as the anchor of the popup and serve as lifecycle owner + * for this popup also. + * @param properties [CFRPopupProperties] allowing to customize the popup behavior. + * @param onDismiss Callback for when the popup is dismissed indicating also if the dismissal + * was explicit - by tapping the "X" button or not. + * @param text [Text] already styled and ready to be shown in the popup. + * @param action Optional other composable to show just below the popup text. + */ +@SuppressLint("ViewConstructor") // Intended to be used only in code, don't need a View constructor +internal class CFRPopupFullscreenLayout( + private val anchor: View, + private val properties: CFRPopupProperties, + private val onDismiss: (Boolean) -> Unit, + private val text: @Composable (() -> Unit), + private val action: @Composable (() -> Unit) = {}, +) : AbstractComposeView(anchor.context), ViewRootForInspector { + private val windowManager = anchor.context.getSystemService(Context.WINDOW_SERVICE) as WindowManager + + /** + * Listener for when the anchor is removed from the screen. + * Useful in the following situations: + * - lack of purpose - if there is no anchor the context/action to which this popup refers to disappeared + * - leak from WindowManager - if removing the app from task manager while the popup is shown. + * + * Will not inform client about this since the user did not expressly dismissed this popup. + */ + private val anchorDetachedListener = ViewDetachedListener { + dismiss() + } + + /** + * When the screen is rotated the popup may get improperly anchored + * because of the async nature of insets and screen rotation. + * To avoid any improper anchorage the popups are automatically dismissed. + * + * Will not inform client about this since the user did not expressly dismissed this popup. + * + * Since a UX decision has been made here: + * [link](https://github.com/mozilla-mobile/fenix/issues/27033#issuecomment-1302363014) + * to redisplay any **implicitly** dismissed CFRs, a short delay will be added, + * after which the CFR will be shown again. + * + */ + @VisibleForTesting + internal lateinit var orientationChangeListener: DisplayOrientationListener + + override var shouldCreateCompositionOnAttachedToWindow: Boolean = false + private set + + /** + * Add a new CFR popup to the current window overlaying everything already displayed. + * This popup will be dismissed when the user clicks on the "x" button or based on other user actions + * with such behavior set in [CFRPopupProperties]. + */ + fun show() { + setViewTreeLifecycleOwner(anchor.findViewTreeLifecycleOwner()) + this.setViewTreeSavedStateRegistryOwner(anchor.findViewTreeSavedStateRegistryOwner()) + anchor.addOnAttachStateChangeListener(anchorDetachedListener) + orientationChangeListener = getDisplayOrientationListener(anchor.context).also { + it.start() + } + windowManager.addView(this, createLayoutParams()) + } + + @Composable + override fun Content() { + val anchorLocation = IntArray(2).apply { + anchor.getLocationInWindow(this) + } + + val anchorXCoordMiddle = Pixels(anchorLocation.first() + anchor.width / 2) + val indicatorArrowHeight = Pixels( + CFRPopup.DEFAULT_INDICATOR_HEIGHT.dp.toPx(), + ) + + val popupBounds = computePopupHorizontalBounds( + anchorMiddleXCoord = anchorXCoordMiddle, + arrowIndicatorWidth = Pixels(Companion.getIndicatorBaseWidthForHeight(indicatorArrowHeight.value)), + screenWidth = Pixels(LocalConfiguration.current.screenWidthDp.dp.toPx()), + layoutDirection = LocalConfiguration.current.layoutDirection, + ) + + val indicatorOffset = computeIndicatorArrowStartCoord( + anchorMiddleXCoord = anchorXCoordMiddle, + popupStartCoord = popupBounds.startCoord, + arrowIndicatorWidth = Pixels( + Companion.getIndicatorBaseWidthForHeight(indicatorArrowHeight.value), + ), + ) + + Popup( + popupPositionProvider = getPopupPositionProvider( + anchorLocation = anchorLocation, + popupBounds = popupBounds, + ), + properties = PopupProperties( + focusable = true, + dismissOnBackPress = properties.dismissOnBackPress, + dismissOnClickOutside = properties.dismissOnClickOutside, + ), + onDismissRequest = { + // For when tapping outside the popup. + dismiss() + onDismiss(false) + }, + ) { + CFRPopupContent( + popupBodyColors = properties.popupBodyColors, + showDismissButton = properties.showDismissButton, + dismissButtonColor = properties.dismissButtonColor, + indicatorDirection = properties.indicatorDirection, + indicatorArrowStartOffset = with(LocalDensity.current) { + indicatorOffset.value.toDp() + }, + onDismiss = { + // For when tapping the "X" button. + dismiss() + onDismiss(true) + }, + popupWidth = if (shouldCenterPopup(LocalConfiguration.current.screenWidthDp.dp.toPx())) { + (LocalConfiguration.current.screenWidthDp - 2 * CFRPopup.DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP).dp + } else { + properties.popupWidth + }, + text = text, + action = action, + ) + } + } + + @Composable + private fun getPopupPositionProvider( + anchorLocation: IntArray, + popupBounds: PopupHorizontalBounds, + ): PopupPositionProvider { + return object : PopupPositionProvider { + override fun calculatePosition( + anchorBounds: IntRect, + windowSize: IntSize, + layoutDirection: LayoutDirection, + popupContentSize: IntSize, + ): IntOffset { + // Popup will be anchored such that the indicator arrow will point to the middle of the anchor View + // but the popup is allowed some space as start padding in which it can be displayed such that the + // indicator arrow is exactly at the top-start/bottom-start corner but slightly translated to end. + // Values are in pixels. + return IntOffset( + when (layoutDirection) { + Ltr -> popupBounds.startCoord.value + else -> popupBounds.endCoord.value + }, + when (properties.indicatorDirection) { + UP -> { + when (properties.overlapAnchor) { + true -> anchorLocation.last() + anchor.height / 2 + else -> anchorLocation.last() + anchor.height + properties.popupVerticalOffset.toPx() + } + } + DOWN -> { + when (properties.overlapAnchor) { + true -> anchorLocation.last() - popupContentSize.height + anchor.height / 2 + else -> anchorLocation.last() - popupContentSize.height - + properties.popupVerticalOffset.toPx() + } + } + }, + ) + } + } + } + + /** + * Whether or not the popup body should be centered in the screen, this is only true if the screen does not + * allow the popup to be centered at its maximum width. + */ + private fun shouldCenterPopup( + screenWidth: Int, + ): Boolean { + val maximumPopupWidth = properties.popupWidth.toPx() + + 2 * CFRPopup.DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP.dp.toPx() + return properties.popupAlignment == BODY_CENTERED_IN_SCREEN && maximumPopupWidth > screenWidth + } + + /** + * Compute the x-coordinates for the absolute start and end position of the popup, including any padding. + * This assumes anchoring is indicated with an arrow to the horizontal middle of the anchor with the popup's + * body potentially extending to the `start` of the arrow indicator. + * + * @param anchorMiddleXCoord x-coordinate for the middle of the anchor. + * @param arrowIndicatorWidth x-distance the arrow indicator occupies. + * @param screenWidth available width in which the popup will be shown. + * @param layoutDirection the layout direction of the anchor layout. + */ + @VisibleForTesting + @Suppress("LongMethod") + internal fun computePopupHorizontalBounds( + anchorMiddleXCoord: Pixels, + arrowIndicatorWidth: Pixels, + screenWidth: Pixels, + layoutDirection: Int, + ): PopupHorizontalBounds { + val arrowIndicatorHalfWidth = arrowIndicatorWidth.value / 2 + + return if (layoutDirection == View.LAYOUT_DIRECTION_LTR) { + computeHorizontalBoundsLTR( + anchorStart = Pixels(anchorMiddleXCoord.value - arrowIndicatorHalfWidth), + screenWidth = screenWidth, + ) + } else { + computeHorizontalBoundsRTL( + anchorStart = Pixels(anchorMiddleXCoord.value + arrowIndicatorHalfWidth), + screenWidth = screenWidth, + ) + } + } + + private fun computeHorizontalBoundsLTR( + anchorStart: Pixels, + screenWidth: Pixels, + ): PopupHorizontalBounds { + val popupPadding = Pixels(CFRPopup.DEFAULT_EXTRA_HORIZONTAL_PADDING.dp.toPx()) + val leftInsets = Pixels(getLeftInsets()) + val popupWidth = Pixels(properties.popupWidth.toPx()) + val viewportMargin = + CFRPopup.DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP.dpToPx(anchor.resources.displayMetrics) + var startCoord = when (properties.popupAlignment) { + BODY_TO_ANCHOR_START -> { + Pixels(anchor.x.roundToInt() + leftInsets.value) + } + + BODY_TO_ANCHOR_CENTER -> { + Pixels( + anchor.x.roundToInt() + .plus((anchor.width - popupWidth.value) / 2) + .plus(leftInsets.value), + ) + } + + INDICATOR_CENTERED_IN_ANCHOR, + BODY_CENTERED_IN_SCREEN, + -> { + if (shouldCenterPopup(screenWidth.value)) { + Pixels(viewportMargin + leftInsets.value) + } else { + Pixels( + (anchorStart.value) + .minus(properties.indicatorArrowStartOffset.toPx()) + .coerceAtLeast(leftInsets.value), + ) + } + } + } + + val endCoord = when (properties.popupAlignment) { + BODY_CENTERED_IN_SCREEN, + INDICATOR_CENTERED_IN_ANCHOR, + -> { + if (shouldCenterPopup(screenWidth.value)) { + Pixels(screenWidth.value - viewportMargin) + } else { + var maybeEndCoord = Pixels( + startCoord.value + .plus(popupWidth.value) + .plus(popupPadding.value), + ) + // Handle the scenario in which the popup would get pass the end of the screen. + // Allow it to only be shown between [0, screenWidth] and if these bounds are surpassed + // translate it horizontally to the start to show as much of it as possible. + val endCoordOverflow = maybeEndCoord.value - screenWidth.value + if (endCoordOverflow > 0) { + startCoord = Pixels( + startCoord.value + .minus(endCoordOverflow) + .coerceAtLeast(leftInsets.value), + ) + maybeEndCoord = + Pixels(maybeEndCoord.value.coerceAtMost(screenWidth.value + leftInsets.value)) + } + maybeEndCoord + } + } + + else -> { + Pixels( + startCoord.value + .plus(popupWidth.value) + .plus(popupPadding.value) + .coerceAtMost(screenWidth.value + leftInsets.value), + ) + } + } + + return PopupHorizontalBounds( + startCoord = startCoord, + endCoord = endCoord, + ) + } + + private fun computeHorizontalBoundsRTL( + anchorStart: Pixels, + screenWidth: Pixels, + ): PopupHorizontalBounds { + val popupPadding = Pixels(CFRPopup.DEFAULT_EXTRA_HORIZONTAL_PADDING.dp.toPx()) + val leftInsets = Pixels(getLeftInsets()) + val popupWidth = Pixels(properties.popupWidth.toPx()) + val viewportMargin = + CFRPopup.DEFAULT_HORIZONTAL_VIEWPORT_MARGIN_DP.dpToPx(anchor.resources.displayMetrics) + var startCoord = when (properties.popupAlignment) { + BODY_TO_ANCHOR_START -> { + Pixels(anchor.x.roundToInt() + anchor.width + leftInsets.value) + } + BODY_TO_ANCHOR_CENTER -> { + val anchorEndCoord = anchor.x.roundToInt() + anchor.width + Pixels( + anchorEndCoord + .minus((anchor.width - popupWidth.value) / 2) + .plus(leftInsets.value), + ) + } + + BODY_CENTERED_IN_SCREEN, + INDICATOR_CENTERED_IN_ANCHOR, + -> { + if (shouldCenterPopup(screenWidth.value)) { + Pixels(screenWidth.value - viewportMargin) + } else { + Pixels( + // Push the popup as far to the start (in RTL) as possible. + anchorStart.value + .plus(properties.indicatorArrowStartOffset.toPx()) + .coerceAtMost(screenWidth.value + leftInsets.value), + ) + } + } + } + + val endCoord = when (properties.popupAlignment) { + BODY_CENTERED_IN_SCREEN, + INDICATOR_CENTERED_IN_ANCHOR, + -> { + if (shouldCenterPopup(screenWidth.value)) { + Pixels(viewportMargin - leftInsets.value) + } else { + var maybeEndCoord = Pixels( + startCoord.value + .minus(popupWidth.value) + .minus(popupPadding.value), + ) + val endCoordOverflow = leftInsets.value - maybeEndCoord.value + // Handle the scenario in which the popup would get pass the end of the screen (in RTL) + // Allow it to only be shown between [0, screenWidth] and if these bounds are surpassed + // translate it horizontally to the start to show as much of it as possible. + if (endCoordOverflow > 0) { + startCoord = Pixels( + startCoord.value + .plus(endCoordOverflow.absoluteValue) + .coerceAtMost(screenWidth.value + leftInsets.value), + ) + maybeEndCoord = + Pixels(maybeEndCoord.value.coerceAtLeast(leftInsets.value)) + } + maybeEndCoord + } + } + + else -> { + Pixels( + startCoord.value + .minus(popupWidth.value) + .minus(popupPadding.value) + .coerceAtLeast(leftInsets.value), + ) + } + } + + return PopupHorizontalBounds(startCoord, endCoord) + } + + /** + * Compute the x-coordinate for where the popup's indicator arrow should start + * relative to the available distance between it and the popup's starting x-coordinate. + * + * @param anchorMiddleXCoord x-coordinate for the middle of the anchor. + * @param popupStartCoord x-coordinate for the popup start + * @param arrowIndicatorWidth Width of the arrow indicator. + */ + @Composable + private fun computeIndicatorArrowStartCoord( + anchorMiddleXCoord: Pixels, + popupStartCoord: Pixels, + arrowIndicatorWidth: Pixels, + ): Pixels { + return when (properties.popupAlignment) { + BODY_TO_ANCHOR_START, + BODY_TO_ANCHOR_CENTER, + -> Pixels(properties.indicatorArrowStartOffset.toPx()) + BODY_CENTERED_IN_SCREEN, + INDICATOR_CENTERED_IN_ANCHOR, + -> { + val arrowIndicatorHalfWidth = arrowIndicatorWidth.value / 2 + if (LocalConfiguration.current.layoutDirection == View.LAYOUT_DIRECTION_LTR) { + Pixels(anchorMiddleXCoord.value - arrowIndicatorHalfWidth - popupStartCoord.value) + } else { + val visiblePopupEndCoord = popupStartCoord.value + Pixels(visiblePopupEndCoord - anchorMiddleXCoord.value - arrowIndicatorHalfWidth) + } + } + } + } + + /** + * Cleanup and remove the current popup from the screen. + * Clients are not automatically informed about this. Use a separate call to [onDismiss] if needed. + */ + internal fun dismiss() { + anchor.removeOnAttachStateChangeListener(anchorDetachedListener) + orientationChangeListener.stop() + disposeComposition() + setViewTreeLifecycleOwner(null) + this.setViewTreeSavedStateRegistryOwner(null) + windowManager.removeViewImmediate(this) + } + + /** + * Create fullscreen translucent layout params. + * This will allow placing the visible popup anywhere on the screen. + */ + @VisibleForTesting + internal fun createLayoutParams(): WindowManager.LayoutParams = + WindowManager.LayoutParams().apply { + type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL + token = anchor.applicationWindowToken + width = WindowManager.LayoutParams.MATCH_PARENT + height = WindowManager.LayoutParams.MATCH_PARENT + format = PixelFormat.TRANSLUCENT + flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN or + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED + } + + private fun getDisplayOrientationListener(context: Context) = DisplayOrientationListener(context) { + dismiss() + anchor.toScope().launch { + delay(SHOW_AFTER_SCREEN_ORIENTATION_CHANGE_DELAY) + show() + } + } + + /** + * Intended to allow querying the insets of the navigation bar. + * Value will be `0` except for when the screen is rotated by 90 degrees. + */ + private fun getLeftInsets() = ViewCompat.getRootWindowInsets(anchor) + ?.getInsets(WindowInsetsCompat.Type.systemBars())?.left + ?: 0.coerceAtLeast(0) + + @Px + internal fun Dp.toPx(): Int { + return this.value + .dpToPx(anchor.resources.displayMetrics) + .roundToInt() + } +} diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupShape.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupShape.kt new file mode 100644 index 0000000000..8606bdcebc --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupShape.kt @@ -0,0 +1,272 @@ +/* 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 mozilla.components.compose.cfr + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.geometry.Size +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Outline +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp +import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.DOWN +import mozilla.components.compose.cfr.CFRPopup.IndicatorDirection.UP +import kotlin.math.roundToInt + +/** + * How wide the base of the indicator should be in relation with the indicator's height. + */ +private const val INDICATOR_BASE_TO_HEIGHT_RATIO = 2f + +/** + * A [Shape] describing a popup with an indicator triangle shown above or below the popup. + * + * @param indicatorDirection The direction the indicator arrow is pointing to. + * @param indicatorArrowStartOffset Distance between the popup start and the indicator arrow start + * @param indicatorArrowHeight Height of the indicator triangle. This influences the base length. + * @param cornerRadius The radius of the popup's corners. + * If [indicatorArrowStartOffset] is `0` then the top-start corner will not be rounded. + */ +class CFRPopupShape( + private val indicatorDirection: CFRPopup.IndicatorDirection, + private val indicatorArrowStartOffset: Dp, + private val indicatorArrowHeight: Dp, + private val cornerRadius: Dp, +) : Shape { + @Suppress("LongMethod") + override fun createOutline( + size: Size, + layoutDirection: LayoutDirection, + density: Density, + ): Outline { + val indicatorArrowStartOffsetPx = indicatorArrowStartOffset.value * density.density + val indicatorArrowHeightPx = indicatorArrowHeight.value * density.density + val indicatorArrowBasePx = + getIndicatorBaseWidthForHeight((indicatorArrowHeight.value * density.density).roundToInt()) + val cornerRadiusPx = cornerRadius.value * density.density + val indicatorCornerRadiusPx = cornerRadiusPx.coerceAtMost(indicatorArrowStartOffsetPx) + + // All outlines are drawn in a LTR space but with accounting for the LTR direction. + return when (indicatorDirection) { + CFRPopup.IndicatorDirection.UP -> { + Outline.Generic( + path = Path().apply { + reset() + + lineTo(0f, size.height - cornerRadiusPx) + quadraticBezierTo( + 0f, + size.height, + cornerRadiusPx, + size.height, + ) + + lineTo(size.width - cornerRadiusPx, size.height) + quadraticBezierTo( + size.width, + size.height, + size.width, + size.height - cornerRadiusPx, + ) + + if (layoutDirection == LayoutDirection.Ltr) { + lineTo(size.width, cornerRadiusPx + indicatorArrowHeightPx) + quadraticBezierTo( + size.width, + indicatorArrowHeightPx, + size.width - cornerRadiusPx, + indicatorArrowHeightPx, + ) + + lineTo(indicatorArrowStartOffsetPx + indicatorArrowBasePx, indicatorArrowHeightPx) + lineTo(indicatorArrowStartOffsetPx + indicatorArrowBasePx / 2, 0f) + lineTo(indicatorArrowStartOffsetPx, indicatorArrowHeightPx) + + lineTo(indicatorCornerRadiusPx, indicatorArrowHeightPx) + quadraticBezierTo( + 0f, + indicatorArrowHeightPx, + 0f, + indicatorArrowHeightPx + indicatorCornerRadiusPx, + ) + } else { + lineTo(size.width, indicatorCornerRadiusPx + indicatorArrowHeightPx) + quadraticBezierTo( + size.width, + indicatorArrowHeightPx, + size.width - indicatorCornerRadiusPx, + indicatorArrowHeightPx, + ) + + val indicatorEnd = size.width - indicatorArrowStartOffsetPx + lineTo(indicatorEnd, indicatorArrowHeightPx) + lineTo(indicatorEnd - indicatorArrowBasePx / 2, 0f) + lineTo(indicatorEnd - indicatorArrowBasePx, indicatorArrowHeightPx) + + lineTo(cornerRadiusPx, indicatorArrowHeightPx) + quadraticBezierTo( + 0f, + indicatorArrowHeightPx, + 0f, + indicatorArrowHeightPx + cornerRadiusPx, + ) + } + + close() + }, + ) + } + CFRPopup.IndicatorDirection.DOWN -> { + val messageBodyHeightPx = size.height - indicatorArrowHeightPx + + Outline.Generic( + path = Path().apply { + reset() + + if (layoutDirection == LayoutDirection.Ltr) { + lineTo(0f, messageBodyHeightPx - indicatorCornerRadiusPx) + quadraticBezierTo( + 0f, + size.height - indicatorArrowHeightPx, + indicatorCornerRadiusPx, + size.height - indicatorArrowHeightPx, + ) + + lineTo(indicatorArrowStartOffsetPx, messageBodyHeightPx) + lineTo(indicatorArrowStartOffsetPx + indicatorArrowBasePx / 2, size.height) + lineTo(indicatorArrowStartOffsetPx + indicatorArrowBasePx, messageBodyHeightPx) + + lineTo(size.width - cornerRadiusPx, messageBodyHeightPx) + quadraticBezierTo( + size.width, + messageBodyHeightPx, + size.width, + messageBodyHeightPx - cornerRadiusPx, + ) + } else { + lineTo(0f, messageBodyHeightPx - cornerRadiusPx) + quadraticBezierTo( + 0f, + messageBodyHeightPx, + cornerRadiusPx, + messageBodyHeightPx, + ) + + val indicatorStartPx = size.width - indicatorArrowStartOffsetPx - indicatorArrowBasePx + lineTo(indicatorStartPx, messageBodyHeightPx) + lineTo(indicatorStartPx + indicatorArrowBasePx / 2, size.height) + lineTo(indicatorStartPx + indicatorArrowBasePx, messageBodyHeightPx) + + lineTo(size.width - indicatorCornerRadiusPx, messageBodyHeightPx) + quadraticBezierTo( + size.width, + messageBodyHeightPx, + size.width, + messageBodyHeightPx - indicatorCornerRadiusPx, + ) + } + + lineTo(size.width, cornerRadiusPx) + quadraticBezierTo( + size.width, + 0f, + size.width - cornerRadiusPx, + 0f, + ) + + lineTo(cornerRadiusPx, 0f) + quadraticBezierTo( + 0f, + 0f, + 0f, + cornerRadiusPx, + ) + + close() + }, + ) + } + } + } + + companion object { + /** + * This [Shape]'s arrow indicator will have an automatic width depending on the set height. + * This method allows knowing what the base width will be before instantiating the class. + */ + fun getIndicatorBaseWidthForHeight(height: Int): Int { + return (height * INDICATOR_BASE_TO_HEIGHT_RATIO).roundToInt() + } + } +} + +@Composable +@Preview(locale = "en", name = "LTR") +@Preview(locale = "ar", name = "RTL") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme") +private fun CFRPopupBelowShapePreview() { + Box( + modifier = Modifier + .height(100.dp) + .width(200.dp) + .background( + shape = CFRPopupShape(UP, 10.dp, 10.dp, 10.dp), + brush = Brush.linearGradient( + colors = listOf(Color.Cyan, Color.Blue), + end = Offset(0f, Float.POSITIVE_INFINITY), + start = Offset(Float.POSITIVE_INFINITY, 0f), + ), + ), + contentAlignment = Alignment.Center, + ) { + Text( + text = "This is just a test", + color = MaterialTheme.colors.onPrimary, + ) + } +} + +@Composable +@Preview(locale = "en", name = "LTR") +@Preview(locale = "ar", name = "RTL") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, name = "Dark theme") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, name = "Light theme") +private fun CFRPopupAboveShapePreview() { + Box( + modifier = Modifier + .height(100.dp) + .width(200.dp) + .background( + shape = CFRPopupShape(DOWN, 10.dp, 10.dp, 10.dp), + brush = Brush.linearGradient( + colors = listOf(Color.Cyan, Color.Blue), + end = Offset(0f, Float.POSITIVE_INFINITY), + start = Offset(Float.POSITIVE_INFINITY, 0f), + ), + ), + contentAlignment = Alignment.Center, + ) { + Text( + text = "This is just a test", + color = MaterialTheme.colors.onPrimary, + ) + } +} diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/DisplayOrientationListener.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/DisplayOrientationListener.kt new file mode 100644 index 0000000000..4a44ac6127 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/DisplayOrientationListener.kt @@ -0,0 +1,65 @@ +/* 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 mozilla.components.compose.cfr.helper + +import android.content.Context +import android.hardware.display.DisplayManager +import android.hardware.display.DisplayManager.DisplayListener +import android.os.Build +import androidx.annotation.VisibleForTesting + +/** + * Inform when the rotation of the screen changes. + * Since this is using a [DisplayManager] listener it's important to call [start] and [stop] + * at the appropriate moments to register and unregister said listener. + * + * @param context Android context needed to interact with the [DisplayManager] + * @param onDisplayRotationChanged Listener for when the display rotation changes. + * This will be called when the display changes to any of the four main orientations: + * [PORTRAIT, LANDSCAPE, REVERSE_PORTRAIT, REVERSE_LANDSCAPE]. + * No updates will be triggered if the "Auto-rotate" functionality is disabled for the device. + */ +internal class DisplayOrientationListener( + private val context: Context, + val onDisplayRotationChanged: () -> Unit, +) : DisplayListener { + private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager + + @VisibleForTesting + internal var currentOrientation = getCurrentOrientation() + + /** + * Start listening for display orientation changes. + * It's important to also call [stop] when done listening to prevent leaking the listener. + */ + fun start() { + displayManager.registerDisplayListener(this, null) + } + + /** + * Stop listening for display orientation changes and cleanup the current [DisplayManager] listener. + */ + fun stop() { + displayManager.unregisterDisplayListener(this) + } + + override fun onDisplayAdded(displayId: Int) = Unit + + override fun onDisplayRemoved(displayId: Int) = Unit + + override fun onDisplayChanged(displayId: Int) { + val newOrientation = getCurrentOrientation(displayId) + + if (newOrientation != this.currentOrientation) { + this.currentOrientation = newOrientation + onDisplayRotationChanged() + } + } + + private fun getCurrentOrientation(displayId: Int = 0): Int = when (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + true -> context.resources.configuration.orientation + false -> displayManager.getDisplay(displayId)?.rotation ?: currentOrientation + } +} diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/ViewDetachedListener.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/ViewDetachedListener.kt new file mode 100644 index 0000000000..da6782604a --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/helper/ViewDetachedListener.kt @@ -0,0 +1,19 @@ +/* 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 mozilla.components.compose.cfr.helper + +import android.view.View + +/** + * Simpler [View.OnAttachStateChangeListener] only informing about + * [View.OnAttachStateChangeListener.onViewDetachedFromWindow]. + */ +internal class ViewDetachedListener(val onDismiss: () -> Unit) : View.OnAttachStateChangeListener { + override fun onViewAttachedToWindow(v: View) = Unit + + override fun onViewDetachedFromWindow(v: View) { + onDismiss() + } +} diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-am/strings.xml new file mode 100644 index 0000000000..c97e99ec94 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-am/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">አሰናብት</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ast/strings.xml new file mode 100644 index 0000000000..0676ead800 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ast/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Escartar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-azb/strings.xml new file mode 100644 index 0000000000..77a2c88eb2 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-azb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">باغلا</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-be/strings.xml new file mode 100644 index 0000000000..19d6f18471 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-be/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Адхіліць</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-bg/strings.xml new file mode 100644 index 0000000000..12463e5dda --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-bg/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Прекратяване</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-br/strings.xml new file mode 100644 index 0000000000..6b257c25c7 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-br/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Argas</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-bs/strings.xml new file mode 100644 index 0000000000..d8b54cb34b --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-bs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Odbaci</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ca/strings.xml new file mode 100644 index 0000000000..c5e24af615 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ca/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Descarta</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cak/strings.xml new file mode 100644 index 0000000000..3152b578ba --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cak/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Tichup ruwäch</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ckb/strings.xml new file mode 100644 index 0000000000..437dd527f5 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ckb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">پشتگوێخستن</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-co/strings.xml new file mode 100644 index 0000000000..6ac10d7f41 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-co/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Ricusà</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cs/strings.xml new file mode 100644 index 0000000000..7931a04581 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Zavřít</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cy/strings.xml new file mode 100644 index 0000000000..cc82da5e42 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-cy/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Cau</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-da/strings.xml new file mode 100644 index 0000000000..d03d570df3 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-da/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Afvis</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-de/strings.xml new file mode 100644 index 0000000000..fc26b597f7 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-de/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Schließen</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-dsb/strings.xml new file mode 100644 index 0000000000..2c84c274e2 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-dsb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Zachyśiś</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-el/strings.xml new file mode 100644 index 0000000000..5a3bba4948 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-el/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Απόρριψη</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rCA/strings.xml new file mode 100644 index 0000000000..d3515657b4 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rCA/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Dismiss</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 0000000000..d3515657b4 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Dismiss</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-eo/strings.xml new file mode 100644 index 0000000000..af51005a75 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-eo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Ignori</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 0000000000..f14c6e05a9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Descartar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rCL/strings.xml new file mode 100644 index 0000000000..e4a97a05b3 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rCL/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Ocultar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rES/strings.xml new file mode 100644 index 0000000000..f14c6e05a9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rES/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Descartar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rMX/strings.xml new file mode 100644 index 0000000000..f14c6e05a9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es-rMX/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Descartar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es/strings.xml new file mode 100644 index 0000000000..f14c6e05a9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-es/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Descartar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-et/strings.xml new file mode 100644 index 0000000000..e6ef08c0b2 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-et/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Peida</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-eu/strings.xml new file mode 100644 index 0000000000..6002549de1 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-eu/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Baztertu</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fa/strings.xml new file mode 100644 index 0000000000..7d50c5d847 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fa/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">رد کردن</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fi/strings.xml new file mode 100644 index 0000000000..dae33bc1fd --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fi/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Hylkää</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000000..68a4823ca3 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Fermer</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fur/strings.xml new file mode 100644 index 0000000000..4a414e4c5b --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fur/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Siere</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fy-rNL/strings.xml new file mode 100644 index 0000000000..105ba034c4 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-fy-rNL/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Slute</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gd/strings.xml new file mode 100644 index 0000000000..13c3244a40 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gd/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Leig seachad</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gl/strings.xml new file mode 100644 index 0000000000..fdc1c7e79f --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Rexeitar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gn/strings.xml new file mode 100644 index 0000000000..9615457637 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-gn/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Mboyke</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hr/strings.xml new file mode 100644 index 0000000000..d8b54cb34b --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Odbaci</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hsb/strings.xml new file mode 100644 index 0000000000..d4b638b5be --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hsb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Zaćisnyć</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hu/strings.xml new file mode 100644 index 0000000000..00bc0d7781 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hu/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Eltüntetés</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000000..6a33629dd2 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-hy-rAM/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Բաց թողնել</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ia/strings.xml new file mode 100644 index 0000000000..716e14b9a7 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ia/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Dimitter</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-in/strings.xml new file mode 100644 index 0000000000..a1d014b221 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-in/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Tutup</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-is/strings.xml new file mode 100644 index 0000000000..6ef45a90ca --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-is/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Hafna</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-it/strings.xml new file mode 100644 index 0000000000..07debd3b5c --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-it/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Chiudi</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-iw/strings.xml new file mode 100644 index 0000000000..d7c5324959 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-iw/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">סגירה</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ja/strings.xml new file mode 100644 index 0000000000..a1efc5c03d --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ja/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">閉じる</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ka/strings.xml new file mode 100644 index 0000000000..49bea70e48 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ka/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">არიდება</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kaa/strings.xml new file mode 100644 index 0000000000..927fa4b2d3 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kaa/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Jabıw</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kab/strings.xml new file mode 100644 index 0000000000..05b7c36c7a --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kab/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Zgel</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kk/strings.xml new file mode 100644 index 0000000000..1e137a1fb1 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Тайдыру</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kmr/strings.xml new file mode 100644 index 0000000000..0a59a2e76f --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-kmr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Bigire</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ko/strings.xml new file mode 100644 index 0000000000..a8f2e61c9b --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ko/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">닫기</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-lo/strings.xml new file mode 100644 index 0000000000..1200deb331 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-lo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">ປິດ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-lt/strings.xml new file mode 100644 index 0000000000..d2d923b1b9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-lt/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Paslėpti</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nb-rNO/strings.xml new file mode 100644 index 0000000000..a403088daf --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nb-rNO/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Ignorer</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nl/strings.xml new file mode 100644 index 0000000000..db4b674192 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Sluiten</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nn-rNO/strings.xml new file mode 100644 index 0000000000..a403088daf --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-nn-rNO/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Ignorer</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-oc/strings.xml new file mode 100644 index 0000000000..7726a050b9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-oc/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Ignorar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 0000000000..495a1e811e --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">ਖਾਰਜ ਕਰੋ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rPK/strings.xml new file mode 100644 index 0000000000..27ee637bfd --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pa-rPK/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">بند کرو</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pl/strings.xml new file mode 100644 index 0000000000..6fb5777d89 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Zamknij</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000000..f14c6e05a9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Descartar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000..da76c02be9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Dispensar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-rm/strings.xml new file mode 100644 index 0000000000..12c3220442 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-rm/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Serrar</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000000..c9748091ec --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ru/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Скрыть</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sat/strings.xml new file mode 100644 index 0000000000..e432bced8a --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sat/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">ᱵᱚᱱᱫ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sc/strings.xml new file mode 100644 index 0000000000..2cf10b5097 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sc/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Iscarta</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-si/strings.xml new file mode 100644 index 0000000000..692fe43d68 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-si/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">ඉවතලන්න</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sk/strings.xml new file mode 100644 index 0000000000..335a45ecc7 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Zavrieť</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-skr/strings.xml new file mode 100644 index 0000000000..ed279b9081 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-skr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">فارغ کرو</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sl/strings.xml new file mode 100644 index 0000000000..b476df56f0 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Zapri</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sq/strings.xml new file mode 100644 index 0000000000..23c71495b1 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sq/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Hidhe tej</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sr/strings.xml new file mode 100644 index 0000000000..f535bf88e7 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Одбаци</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-su/strings.xml new file mode 100644 index 0000000000..a1d014b221 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-su/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Tutup</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sv-rSE/strings.xml new file mode 100644 index 0000000000..87506c9962 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-sv-rSE/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Ignorera</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-szl/strings.xml new file mode 100644 index 0000000000..ca2214b892 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-szl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Ôdkoż</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tg/strings.xml new file mode 100644 index 0000000000..e77dfe593c --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tg/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Нодида гузарондан</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-th/strings.xml new file mode 100644 index 0000000000..4ab6fc629d --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-th/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">ปิด</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tr/strings.xml new file mode 100644 index 0000000000..76f55fe0e8 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Kapat</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-trs/strings.xml new file mode 100644 index 0000000000..b5bdf60de2 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-trs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Si gi\'hiaj guendô\'</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tt/strings.xml new file mode 100644 index 0000000000..acdeb1ed5b --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-tt/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Яшерү</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ug/strings.xml new file mode 100644 index 0000000000..1eaac24e2a --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-ug/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">بولدىلا</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-uk/strings.xml new file mode 100644 index 0000000000..1d1f11dbbb --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-uk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Відхилити</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-uz/strings.xml new file mode 100644 index 0000000000..716312dfd9 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-uz/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Rad qilish</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-vec/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-vec/strings.xml new file mode 100644 index 0000000000..8c4ff51166 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-vec/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Sara</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-vi/strings.xml new file mode 100644 index 0000000000..3d9e560fee --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-vi/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Bỏ qua</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000..1c5ff52f06 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">知道了</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000..9414216213 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">知道了!</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/main/res/values/strings.xml b/mobile/android/android-components/components/compose/cfr/src/main/res/values/strings.xml new file mode 100644 index 0000000000..86c00ee3c0 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/main/res/values/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<!-- 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/. --> +<resources> + <!-- Content description (not visible, for screen readers etc.): Description for the close button of a Contextual Feature Recommendation Popup. --> + <string name="mozac_cfr_dismiss_button_content_description">Dismiss</string> +</resources> diff --git a/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayoutTest.kt b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayoutTest.kt new file mode 100644 index 0000000000..a0259e0bc5 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/CFRPopupFullscreenLayoutTest.kt @@ -0,0 +1,561 @@ +/* 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 mozilla.components.compose.cfr + +import android.content.Context +import android.content.pm.ActivityInfo +import android.graphics.PixelFormat +import android.view.View +import android.view.ViewManager +import android.view.WindowManager +import android.view.WindowManager.LayoutParams +import androidx.compose.ui.unit.dp +import androidx.lifecycle.findViewTreeLifecycleOwner +import androidx.lifecycle.setViewTreeLifecycleOwner +import androidx.savedstate.findViewTreeSavedStateRegistryOwner +import androidx.savedstate.setViewTreeSavedStateRegistryOwner +import androidx.test.ext.junit.runners.AndroidJUnit4 +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.advanceTimeBy +import mozilla.components.compose.cfr.CFRPopup.PopupAlignment +import mozilla.components.support.test.argumentCaptor +import mozilla.components.support.test.eq +import mozilla.components.support.test.mock +import mozilla.components.support.test.robolectric.testContext +import mozilla.components.support.test.rule.MainCoroutineRule +import mozilla.components.support.test.rule.runTestOnMain +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.doReturn +import org.mockito.Mockito.spy +import org.mockito.Mockito.times +import org.mockito.Mockito.verify + +@ExperimentalCoroutinesApi +@RunWith(AndroidJUnit4::class) +class CFRPopupFullscreenLayoutTest { + @get:Rule + val coroutinesTestRule = MainCoroutineRule() + + @Test + fun `WHEN the popup is shown THEN setup lifecycle owners`() { + val anchor = View(testContext).apply { + setViewTreeLifecycleOwner(mock()) + this.setViewTreeSavedStateRegistryOwner(mock()) + } + + val popupView = spy( + CFRPopupFullscreenLayout( + anchor = anchor, + properties = mock(), + onDismiss = mock(), + text = { }, + action = { }, + ), + ) + popupView.show() + + assertNotNull(popupView.findViewTreeLifecycleOwner()) + assertEquals( + anchor.findViewTreeLifecycleOwner(), + popupView.findViewTreeLifecycleOwner(), + ) + assertNotNull(popupView.findViewTreeSavedStateRegistryOwner()) + assertEquals( + assertNotNull(anchor.findViewTreeSavedStateRegistryOwner()), + assertNotNull(popupView.findViewTreeSavedStateRegistryOwner()), + ) + } + + @Test + fun `WHEN the popup is dismissed THEN cleanup lifecycle owners and detach from window`() { + val context = spy(testContext) + val anchor = View(context).apply { + setViewTreeLifecycleOwner(mock()) + this.setViewTreeSavedStateRegistryOwner(mock()) + } + val windowManager = spy(context.getSystemService(Context.WINDOW_SERVICE) as WindowManager) + doReturn(windowManager).`when`(context).getSystemService(Context.WINDOW_SERVICE) + val popupView = CFRPopupFullscreenLayout(anchor, mock(), mock(), { }, { }) + popupView.show() + assertNotNull(popupView.findViewTreeLifecycleOwner()) + assertNotNull(popupView.findViewTreeSavedStateRegistryOwner()) + + popupView.dismiss() + + assertNull(popupView.findViewTreeLifecycleOwner()) + assertNull(popupView.findViewTreeSavedStateRegistryOwner()) + verify(windowManager).removeViewImmediate(popupView) + } + + @Test + fun `GIVEN a popup WHEN adding it to window THEN use translucent layout params`() { + val context = spy(testContext) + val anchor = View(context) + val windowManager = spy(context.getSystemService(Context.WINDOW_SERVICE)) + doReturn(windowManager).`when`(context).getSystemService(Context.WINDOW_SERVICE) + val popupView = CFRPopupFullscreenLayout(anchor, mock(), mock(), { }, { }) + val layoutParamsCaptor = argumentCaptor<LayoutParams>() + + popupView.show() + + verify(windowManager as ViewManager).addView(eq(popupView), layoutParamsCaptor.capture()) + assertEquals(LayoutParams.TYPE_APPLICATION_PANEL, layoutParamsCaptor.value.type) + assertEquals(anchor.applicationWindowToken, layoutParamsCaptor.value.token) + assertEquals(LayoutParams.MATCH_PARENT, layoutParamsCaptor.value.width) + assertEquals(LayoutParams.MATCH_PARENT, layoutParamsCaptor.value.height) + assertEquals(PixelFormat.TRANSLUCENT, layoutParamsCaptor.value.format) + assertEquals( + LayoutParams.FLAG_LAYOUT_IN_SCREEN or LayoutParams.FLAG_HARDWARE_ACCELERATED, + layoutParamsCaptor.value.flags, + ) + } + + @Test + fun `WHEN creating layout params THEN get fullscreen translucent layout params`() { + val anchor = View(testContext) + val popupView = CFRPopupFullscreenLayout(anchor, mock(), mock(), { }, { }) + + val result = popupView.createLayoutParams() + + assertEquals(LayoutParams.TYPE_APPLICATION_PANEL, result.type) + assertEquals(anchor.applicationWindowToken, result.token) + assertEquals(LayoutParams.MATCH_PARENT, result.width) + assertEquals(LayoutParams.MATCH_PARENT, result.height) + assertEquals(PixelFormat.TRANSLUCENT, result.format) + assertEquals( + LayoutParams.FLAG_LAYOUT_IN_SCREEN or LayoutParams.FLAG_HARDWARE_ACCELERATED, + result.flags, + ) + } + + @Test + fun `GIVEN LTR and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds THEN return the right X coordinates`() { + val anchor = View(testContext) + val properties = CFRPopupProperties( + popupWidth = 200.dp, + popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(200), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + assertEquals(190, result.startCoord.value) + assertEquals(400, result.endCoord.value) + } + + @Test + fun `GIVEN LTR and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds THEN account for the provided indicator offset`() { + val anchor = View(testContext) + val properties = CFRPopupProperties( + popupWidth = 200.dp, + popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR, + indicatorArrowStartOffset = 50.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(200), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + // The popup should be translated to the start to ensure the offset to the indicator is respected. + assertEquals(140, result.startCoord.value) + assertEquals(350, result.endCoord.value) + } + + @Test + fun `GIVEN LTR and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds and the popup doesn't fit THEN return the right X coordinates`() { + val anchor = View(testContext) + val properties = CFRPopupProperties( + popupWidth = 900.dp, + popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(200), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + // The popup should be translated to the start to ensure it fits the screen. + assertEquals(90, result.startCoord.value) + assertEquals(1000, result.endCoord.value) + } + + @Test + fun `GIVEN RTL and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds THEN return the right X coordinates`() { + val anchor = View(testContext) + val properties = CFRPopupProperties( + popupWidth = 200.dp, + popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(800), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + assertEquals(810, result.startCoord.value) + assertEquals(600, result.endCoord.value) + } + + @Test + fun `GIVEN RTL and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds THEN account for the provided indicator offset`() { + val anchor = View(testContext) + val properties = CFRPopupProperties( + popupWidth = 200.dp, + popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR, + indicatorArrowStartOffset = 50.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(800), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + // The popup should be translated to the start to ensure the offset to the indicator is respected. + assertEquals(860, result.startCoord.value) + assertEquals(650, result.endCoord.value) + } + + @Test + fun `GIVEN RTL and INDICATOR_CENTERED_IN_ANCHOR WHEN computing popup bounds and the popup doesn't fit THEN return the right X coordinates`() { + val anchor = View(testContext) + val properties = CFRPopupProperties( + popupWidth = 900.dp, + popupAlignment = PopupAlignment.INDICATOR_CENTERED_IN_ANCHOR, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(800), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + // The popup should be translated to the start to ensure it fits the screen. + assertEquals(910, result.startCoord.value) + assertEquals(0, result.endCoord.value) + } + + @Test + fun `GIVEN LTR and BODY_TO_ANCHOR_START WHEN computing popup bounds THEN return the right X coordinates`() { + val anchor = spy(View(testContext)) + doReturn(400).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 300.dp, + popupAlignment = PopupAlignment.BODY_TO_ANCHOR_START, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(300), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + assertEquals(200, result.startCoord.value) + assertEquals(510, result.endCoord.value) + } + + @Test + fun `GIVEN LTR and BODY_TO_ANCHOR_START WHEN computing popup bounds THEN return the right X coordinates and don't account for the provided indicator offset`() { + val anchor = spy(View(testContext)) + doReturn(400).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 300.dp, + popupAlignment = PopupAlignment.BODY_TO_ANCHOR_START, + indicatorArrowStartOffset = 50.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(300), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + assertEquals(200, result.startCoord.value) + assertEquals(510, result.endCoord.value) + } + + @Test + fun `GIVEN RTL and BODY_TO_ANCHOR_START WHEN computing popup bounds THEN return the right X coordinates`() { + val anchor = spy(View(testContext)) + doReturn(400).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 200.dp, + popupAlignment = PopupAlignment.BODY_TO_ANCHOR_START, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(300), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + assertEquals(600, result.startCoord.value) + assertEquals(390, result.endCoord.value) + } + + @Test + fun `GIVEN RTL and BODY_TO_ANCHOR_START WHEN computing popup bounds THEN return the right X coordinates and don't account for the provided indicator offset`() { + val anchor = spy(View(testContext)) + doReturn(400).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 200.dp, + popupAlignment = PopupAlignment.BODY_TO_ANCHOR_START, + indicatorArrowStartOffset = 50.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(300), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + assertEquals(600, result.startCoord.value) + assertEquals(390, result.endCoord.value) + } + + @Test + fun `GIVEN LTR and BODY_TO_ANCHOR_CENTER WHEN computing popup bounds THEN return the right X coordinates`() { + val anchor = spy(View(testContext)) + doReturn(600).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 400.dp, + popupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(400), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + assertEquals(300, result.startCoord.value) + assertEquals(710, result.endCoord.value) + } + + @Test + fun `GIVEN LTR and BODY_TO_ANCHOR_CENTER WHEN computing popup bounds THEN return the right X coordinates and don't account for the provided indicator offset`() { + val anchor = spy(View(testContext)) + doReturn(600).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 400.dp, + popupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER, + indicatorArrowStartOffset = 50.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(400), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + assertEquals(300, result.startCoord.value) + assertEquals(710, result.endCoord.value) + } + + @Test + fun `GIVEN RTL and BODY_TO_ANCHOR_CENTER WHEN computing popup bounds THEN return the right X coordinates`() { + val anchor = spy(View(testContext)) + doReturn(600).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 400.dp, + popupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(300), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + assertEquals(700, result.startCoord.value) + assertEquals(290, result.endCoord.value) + } + + @Test + fun `GIVEN RTL and BODY_TO_ANCHOR_CENTER WHEN computing popup bounds THEN return the right X coordinates and don't account for the provided indicator offset`() { + val anchor = spy(View(testContext)) + doReturn(600).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 400.dp, + popupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER, + indicatorArrowStartOffset = 50.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(300), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + assertEquals(700, result.startCoord.value) + assertEquals(290, result.endCoord.value) + } + + @Test + fun `GIVEN LTR direction and popup is larger than viewport width WHEN computing popup bounds for CENTERED_IN_SCREEN alignment THEN return the correct horizontal bounds`() { + val anchor = spy(View(testContext)) + doReturn(400).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 500.dp, + popupAlignment = PopupAlignment.BODY_CENTERED_IN_SCREEN, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(400), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(500), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + assertEquals(16, result.startCoord.value) + // The screen width minus the viewport margin + assertEquals(484, result.endCoord.value) + } + + @Test + fun `GIVEN LTR direction and popup fits inside the viewport WHEN computing popup bounds for CENTERED_IN_SCREEN alignment THEN the horizontal bounds are calculated for BODY_TO_ANCHOR_CENTER alignment`() { + val anchor = View(testContext) + val properties = CFRPopupProperties( + popupWidth = 400.dp, + popupAlignment = PopupAlignment.BODY_CENTERED_IN_SCREEN, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(200), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_LTR, + ) + + assertEquals(190, result.startCoord.value) + assertEquals(600, result.endCoord.value) + } + + @Test + fun `GIVEN RTL direction and popup is larger than viewport width WHEN computing popup bounds for CENTERED_IN_SCREEN alignment THEN return the correct horizontal bounds`() { + val anchor = spy(View(testContext)) + doReturn(400).`when`(anchor).width + doReturn(200f).`when`(anchor).x + val properties = CFRPopupProperties( + popupWidth = 500.dp, + popupAlignment = PopupAlignment.BODY_CENTERED_IN_SCREEN, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(400), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(500), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + // The screen width minus the viewport margin + assertEquals(484, result.startCoord.value) + assertEquals(16, result.endCoord.value) + } + + @Test + fun `GIVEN RTL direction and popup fits inside the viewport WHEN computing popup bounds for CENTERED_IN_SCREEN alignment THEN the horizontal bounds are calculated for BODY_TO_ANCHOR_CENTER alignment`() { + val anchor = View(testContext) + val properties = CFRPopupProperties( + popupWidth = 400.dp, + popupAlignment = PopupAlignment.BODY_CENTERED_IN_SCREEN, + indicatorArrowStartOffset = 0.dp, + ) + val popupView = CFRPopupFullscreenLayout(anchor, properties, mock(), { }, { }) + + val result = popupView.computePopupHorizontalBounds( + anchorMiddleXCoord = Pixels(700), + arrowIndicatorWidth = Pixels(20), + screenWidth = Pixels(1000), + layoutDirection = View.LAYOUT_DIRECTION_RTL, + ) + + assertEquals(710, result.startCoord.value) + assertEquals(300, result.endCoord.value) + } + + @OptIn(ExperimentalCoroutinesApi::class) + @Test + fun `GIVEN there is a CFR Popup showing WHEN the orientation of the device changes THEN the CFR will be dismissed and shown again after a delay`() = runTestOnMain { + val context = spy(testContext) + val anchor = View(context).apply { + setViewTreeLifecycleOwner(mock()) + this.setViewTreeSavedStateRegistryOwner(mock()) + } + val popupView = spy(CFRPopupFullscreenLayout(anchor, mock(), mock(), { }, { })) + popupView.show() + + testContext.resources.configuration.orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE + popupView.orientationChangeListener.onDisplayChanged(1) + + advanceTimeBy(SHOW_AFTER_SCREEN_ORIENTATION_CHANGE_DELAY) + verify(popupView, times(1)).dismiss() + verify(popupView, times(1)).show() + // Test that show() is called the second time after exactly the expected delay. + advanceTimeBy(1) + verify(popupView, times(2)).show() + } +} diff --git a/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/DisplayOrientationListenerTest.kt b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/DisplayOrientationListenerTest.kt new file mode 100644 index 0000000000..5f8a0874e0 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/DisplayOrientationListenerTest.kt @@ -0,0 +1,136 @@ +/* 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 mozilla.components.compose.cfr.helper + +import android.content.Context +import android.content.pm.ActivityInfo +import android.content.res.Configuration +import android.content.res.Resources +import android.hardware.display.DisplayManager +import android.os.Build +import android.view.Display +import androidx.test.ext.junit.runners.AndroidJUnit4 +import mozilla.components.support.test.mock +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.mockito.Mockito.doReturn +import org.mockito.Mockito.verify +import org.mockito.Mockito.verifyNoInteractions +import org.robolectric.annotation.Config + +@RunWith(AndroidJUnit4::class) +@Config(sdk = [Build.VERSION_CODES.N]) +class DisplayOrientationListenerTest { + private val context: Context = mock() + private val displayManager: DisplayManager = mock() + + @Before + fun setup() { + doReturn(displayManager).`when`(context).getSystemService(Context.DISPLAY_SERVICE) + + val display: Display = mock() + doReturn(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT).`when`(display).rotation + doReturn(display).`when`(displayManager).getDisplay(0) + } + + @Test + fun `WHEN started THEN register it as a display listener`() { + val listener = DisplayOrientationListener(context) { } + + listener.start() + + verify(displayManager).registerDisplayListener(listener, null) + } + + @Test + fun `WHEN stopped THEN unregister from being a display listener`() { + val listener = DisplayOrientationListener(context) { } + + listener.stop() + + verify(displayManager).unregisterDisplayListener(listener) + } + + @Test + fun `WHEN a display is added THEN don't inform the client`() { + var hasRotationChanged = false + val listener = DisplayOrientationListener(context) { hasRotationChanged = true } + + listener.onDisplayAdded(1) + + assertFalse(hasRotationChanged) + } + + @Test + fun `WHEN a display is removed THEN don't inform the client`() { + var hasRotationChanged = false + val listener = DisplayOrientationListener(context) { hasRotationChanged = true } + + listener.onDisplayRemoved(1) + + assertFalse(hasRotationChanged) + } + + @Test + fun `GIVEN display is null WHEN a display is changed THEN don't inform the client`() { + val onDisplayRotationChanged = mock<() -> Unit>() + val listener = DisplayOrientationListener(context, onDisplayRotationChanged) + doReturn(null).`when`(displayManager).getDisplay(1) + + listener.onDisplayChanged(1) + + verifyNoInteractions(onDisplayRotationChanged) + } + + @Test + fun `WHEN a display is changed but doesn't have a new rotation THEN don't inform the client`() { + var hasRotationChanged = false + val listener = DisplayOrientationListener(context) { hasRotationChanged = true } + val display: Display = mock() + doReturn(listener.currentOrientation).`when`(display).rotation + doReturn(display).`when`(displayManager).getDisplay(1) + + listener.onDisplayChanged(1) + + assertFalse(hasRotationChanged) + } + + @Test + fun `GIVEN an old Android version WHEN a display is changed and has a new rotation THEN inform the client and remember the new rotation`() { + var hasRotationChanged = false + val listener = DisplayOrientationListener(context) { hasRotationChanged = true } + val display: Display = mock() + doReturn(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE).`when`(display).rotation + doReturn(display).`when`(displayManager).getDisplay(1) + + listener.onDisplayChanged(1) + + assertTrue(hasRotationChanged) + assertEquals(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, listener.currentOrientation) + } + + @Test + @Config(sdk = [Build.VERSION_CODES.S]) + fun `GIVEN a new Android version WHEN a display is changed and has a new rotation THEN inform the client and remember the new rotation`() { + var hasRotationChanged = false + val config = Configuration().apply { + orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + } + val resources: Resources = mock() + doReturn(config).`when`(resources).configuration + doReturn(resources).`when`(context).resources + val listener = DisplayOrientationListener(context) { hasRotationChanged = true } + + config.orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE + listener.onDisplayChanged(1) + + assertTrue(hasRotationChanged) + assertEquals(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE, listener.currentOrientation) + } +} diff --git a/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/ViewDetachedListenerTest.kt b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/ViewDetachedListenerTest.kt new file mode 100644 index 0000000000..bb6467f44c --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/test/java/mozilla/components/compose/cfr/helper/ViewDetachedListenerTest.kt @@ -0,0 +1,32 @@ +/* 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 mozilla.components.compose.cfr.helper + +import mozilla.components.support.test.mock +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test + +class ViewDetachedListenerTest { + @Test + fun `WHEN the View is attached THEN don't inform the client`() { + var wasCallbackCalled = false + val listener = ViewDetachedListener { wasCallbackCalled = true } + + listener.onViewAttachedToWindow(mock()) + + assertFalse(wasCallbackCalled) + } + + @Test + fun `WHEN the View is detached THEN don't inform the client`() { + var wasCallbackCalled = false + val listener = ViewDetachedListener { wasCallbackCalled = true } + + listener.onViewDetachedFromWindow(mock()) + + assertTrue(wasCallbackCalled) + } +} diff --git a/mobile/android/android-components/components/compose/cfr/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/cfr/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..cf1c399ea8 --- /dev/null +++ b/mobile/android/android-components/components/compose/cfr/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1,2 @@ +mock-maker-inline +// This allows mocking final classes (classes are final by default in Kotlin) diff --git a/mobile/android/android-components/components/compose/engine/README.md b/mobile/android/android-components/components/compose/engine/README.md new file mode 100644 index 0000000000..4ea4cd1be2 --- /dev/null +++ b/mobile/android/android-components/components/compose/engine/README.md @@ -0,0 +1,19 @@ +# [Android Components](../../../README.md) > Compose > Engine + +A component for integrating a `concept-engine` implementation into Jetpack Compose UI. + +## Usage + +### Setting up the dependency + +Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)): + +```Groovy +implementation "org.mozilla.components:compose-engine:{latest-version}" +``` + +## License + + 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/ diff --git a/mobile/android/android-components/components/compose/engine/build.gradle b/mobile/android/android-components/components/compose/engine/build.gradle new file mode 100644 index 0000000000..5bbeb6d699 --- /dev/null +++ b/mobile/android/android-components/components/compose/engine/build.gradle @@ -0,0 +1,61 @@ +/* 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/. */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + defaultConfig { + minSdkVersion config.minSdkVersion + compileSdk config.compileSdkVersion + targetSdkVersion config.targetSdkVersion + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + buildFeatures { + compose true + } + + composeOptions { + kotlinCompilerExtensionVersion = Versions.compose_compiler + } + + namespace 'mozilla.components.compose.engine' +} + +dependencies { + implementation project(":browser-state") + implementation project(":concept-engine") + implementation project(":support-ktx") + + implementation ComponentsDependencies.androidx_compose_ui + implementation ComponentsDependencies.androidx_compose_ui_tooling_preview + implementation ComponentsDependencies.androidx_compose_foundation + implementation ComponentsDependencies.androidx_compose_material + + debugImplementation ComponentsDependencies.androidx_compose_ui_tooling + + testImplementation project(':support-test') + testImplementation ComponentsDependencies.androidx_compose_ui_test + testImplementation ComponentsDependencies.androidx_test_core + testImplementation ComponentsDependencies.androidx_test_junit + testImplementation ComponentsDependencies.testing_robolectric + + androidTestImplementation ComponentsDependencies.androidx_test_junit + androidTestImplementation ComponentsDependencies.androidx_compose_ui_test_manifest + androidTestImplementation ComponentsDependencies.androidx_compose_ui_test + androidTestImplementation ComponentsDependencies.testing_mockito +} + +apply from: '../../../android-lint.gradle' +apply from: '../../../publish.gradle' +ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description) diff --git a/mobile/android/android-components/components/compose/engine/proguard-rules.pro b/mobile/android/android-components/components/compose/engine/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/mobile/android/android-components/components/compose/engine/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/mobile/android/android-components/components/compose/engine/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/engine/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e16cda1d34 --- /dev/null +++ b/mobile/android/android-components/components/compose/engine/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ +<!-- 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/. --> +<manifest /> diff --git a/mobile/android/android-components/components/compose/engine/src/main/java/mozilla/components/compose/engine/WebContent.kt b/mobile/android/android-components/components/compose/engine/src/main/java/mozilla/components/compose/engine/WebContent.kt new file mode 100644 index 0000000000..0d2bfb02f1 --- /dev/null +++ b/mobile/android/android-components/components/compose/engine/src/main/java/mozilla/components/compose/engine/WebContent.kt @@ -0,0 +1,62 @@ +/* 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 mozilla.components.compose.engine + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.viewinterop.AndroidView +import mozilla.components.browser.state.action.EngineAction +import mozilla.components.browser.state.helper.Target +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.concept.engine.Engine +import mozilla.components.concept.engine.EngineView + +/** + * Composes an [EngineView] obtained from the given [Engine] and renders the web content of the + * [target] from the [store] on it. + */ +@Composable +fun WebContent( + engine: Engine, + store: BrowserStore, + target: Target, +) { + val selectedTab = target.observeAsComposableStateFrom( + store = store, + observe = { tab -> + // Render if the tab itself changed or when the state of the linked engine session changes + arrayOf( + tab?.id, + tab?.engineState?.engineSession, + tab?.engineState?.crashed, + tab?.content?.firstContentfulPaint, + ) + }, + ) + + AndroidView( + modifier = Modifier.fillMaxSize(), + factory = { context -> engine.createView(context).asView() }, + update = { view -> + val engineView = view as EngineView + + val tab = selectedTab.value + if (tab == null) { + engineView.release() + } else { + val session = tab.engineState.engineSession + if (session == null) { + // This tab does not have an EngineSession that we can render yet. Let's dispatch an + // action to request creating one. Once one was created and linked to this session, this + // method will get invoked again. + store.dispatch(EngineAction.CreateEngineSessionAction(tab.id)) + } else { + engineView.render(session) + } + } + }, + ) +} diff --git a/mobile/android/android-components/components/compose/engine/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/engine/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..cf1c399ea8 --- /dev/null +++ b/mobile/android/android-components/components/compose/engine/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1,2 @@ +mock-maker-inline +// This allows mocking final classes (classes are final by default in Kotlin) diff --git a/mobile/android/android-components/components/compose/engine/src/test/resources/robolectric.properties b/mobile/android/android-components/components/compose/engine/src/test/resources/robolectric.properties new file mode 100644 index 0000000000..932b01b9eb --- /dev/null +++ b/mobile/android/android-components/components/compose/engine/src/test/resources/robolectric.properties @@ -0,0 +1 @@ +sdk=28 diff --git a/mobile/android/android-components/components/compose/tabstray/README.md b/mobile/android/android-components/components/compose/tabstray/README.md new file mode 100644 index 0000000000..6a70022ee0 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/README.md @@ -0,0 +1,19 @@ +# [Android Components](../../../README.md) > Compose > Tabs tray + +A customizable tabs tray using Jetpack Compose. + +## Usage + +### Setting up the dependency + +Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)): + +```Groovy +implementation "org.mozilla.components:compose-tabstray:{latest-version}" +``` + +## License + + 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/ diff --git a/mobile/android/android-components/components/compose/tabstray/build.gradle b/mobile/android/android-components/components/compose/tabstray/build.gradle new file mode 100644 index 0000000000..1b12b0ac53 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/build.gradle @@ -0,0 +1,58 @@ +/* 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/. */ + +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' + +android { + defaultConfig { + minSdkVersion config.minSdkVersion + compileSdk config.compileSdkVersion + targetSdkVersion config.targetSdkVersion + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + buildFeatures { + compose true + } + + composeOptions { + kotlinCompilerExtensionVersion = Versions.compose_compiler + } + + namespace 'mozilla.components.compose.browser.tabstray' +} + +dependencies { + implementation project(":concept-tabstray") + + implementation project(":browser-state") + + implementation project(":ui-icons") + + implementation project(":feature-tabs") + + implementation ComponentsDependencies.androidx_compose_ui + implementation ComponentsDependencies.androidx_compose_ui_tooling_preview + implementation ComponentsDependencies.androidx_compose_foundation + implementation ComponentsDependencies.androidx_compose_material + + debugImplementation ComponentsDependencies.androidx_compose_ui_tooling + + testImplementation project(':support-test') + testImplementation ComponentsDependencies.androidx_compose_ui_test + testImplementation ComponentsDependencies.androidx_test_core + testImplementation ComponentsDependencies.androidx_test_junit + testImplementation ComponentsDependencies.testing_robolectric +} + +apply from: '../../../android-lint.gradle' +apply from: '../../../publish.gradle' +ext.configurePublish(config.componentsGroupId, archivesBaseName, project.ext.description) diff --git a/mobile/android/android-components/components/compose/tabstray/proguard-rules.pro b/mobile/android/android-components/components/compose/tabstray/proguard-rules.pro new file mode 100644 index 0000000000..f1b424510d --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/AndroidManifest.xml b/mobile/android/android-components/components/compose/tabstray/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e16cda1d34 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ +<!-- 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/. --> +<manifest /> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/Tab.kt b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/Tab.kt new file mode 100644 index 0000000000..20801e0609 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/Tab.kt @@ -0,0 +1,97 @@ +/* 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 mozilla.components.compose.tabstray + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.layout.size +import androidx.compose.material.ContentAlpha +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import mozilla.components.browser.state.state.TabSessionState +import mozilla.components.ui.icons.R + +/** + * Renders a single [TabSessionState] as a list item. + * + * @param tab The tab to render. + * @param selected Whether this tab is selected or not. + * @param onClick Gets invoked when the tab gets clicked. + * @param onClose Gets invoked when tab gets closed. + */ +@Composable +fun Tab( + tab: TabSessionState, + selected: Boolean = false, + onClick: (String) -> Unit = {}, + onClose: (String) -> Unit = {}, +) { + Box( + modifier = Modifier + .background(if (selected) Color(0xFFFF45A1FF.toInt()) else Color.Unspecified) + .size(width = Dp.Unspecified, height = 72.dp) + .fillMaxWidth() + .clickable { onClick.invoke(tab.id) } + .padding(8.dp), + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceAround, + ) { + // BrowserThumbnail(tab) + Column( + modifier = Modifier + .weight(1f) + .align(Alignment.CenterVertically) + .padding(8.dp), + ) { + Text( + text = tab.content.title, + fontWeight = FontWeight.Bold, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + color = Color.White, + ) + Text( + text = tab.content.url, + style = MaterialTheme.typography.body2, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + color = Color.White.copy(alpha = ContentAlpha.medium), + ) + } + IconButton( + modifier = Modifier + .align(Alignment.CenterVertically) + .requiredSize(24.dp), + onClick = { onClose.invoke(tab.id) }, + ) { + Icon( + painter = painterResource(R.drawable.mozac_ic_cross_24), + contentDescription = "close", + tint = Color.White, + ) + } + } + } +} diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabCounterButton.kt b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabCounterButton.kt new file mode 100644 index 0000000000..2f73136d7a --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabCounterButton.kt @@ -0,0 +1,79 @@ +/* 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 mozilla.components.compose.tabstray + +import androidx.compose.foundation.Image +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.contentColorFor +import androidx.compose.material.primarySurface +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.sp +import mozilla.components.browser.state.state.TabSessionState +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.compose.browser.tabstray.R +import mozilla.components.lib.state.ext.observeAsComposableState + +private const val MAX_VISIBLE_TABS = 99 +private const val SO_MANY_TABS_OPEN = "∞" + +/** + * A button showing the count of tabs in the [store] using the provided [tabsFilter]. + * + * @param store The store to observe. + * @param onClicked Gets invoked when the user clicks the button. + * @param tabsFilter Used for filtering the list of tabs. + */ +@Composable +fun TabCounterButton( + store: BrowserStore, + onClicked: () -> Unit, + tabsFilter: (TabSessionState) -> Boolean = { true }, +) { + IconButton( + onClick = onClicked, + ) { + val backgroundColor = MaterialTheme.colors.primarySurface + val foregroundColor = contentColorFor(backgroundColor) + val tabs = store.observeAsComposableState { state -> state.tabs.filter(tabsFilter) } + val count = tabs.value?.size ?: 0 + + Image( + painter = painterResource(R.drawable.mozac_tabcounter_background), + contentDescription = createContentDescription(count), + colorFilter = ColorFilter.tint(foregroundColor), + ) + + Text( + createButtonText(count), + fontSize = 12.sp, + color = foregroundColor, + ) + } +} + +private fun createButtonText(count: Int): String { + return if (count > MAX_VISIBLE_TABS) { + SO_MANY_TABS_OPEN + } else { + count.toString() + } +} + +@Composable +private fun createContentDescription(count: Int): String { + return if (count == 1) { + stringResource(R.string.mozac_tab_counter_open_tab_tray_single) + } else { + String.format( + stringResource(R.string.mozac_tab_counter_open_tab_tray_plural), + count.toString(), + ) + } +} diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabList.kt b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabList.kt new file mode 100644 index 0000000000..e862854687 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/java/mozilla/components/compose/tabstray/TabList.kt @@ -0,0 +1,77 @@ +/* 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 mozilla.components.compose.tabstray + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import mozilla.components.browser.state.state.TabSessionState +import mozilla.components.browser.state.store.BrowserStore +import mozilla.components.lib.state.ext.observeAsComposableState + +/** + * Renders a list of tabs from the given [store], using the provided [tabsFilter]. + * + * @param store The store to observe. + * @param modifier The modifier to apply to this layout. + * @param tabsFilter Used to filter the list of tabs from the [store]. + * @param onTabClosed Gets invoked when the user closes a tab. + * @param onTabSelected Gets invoked when the user selects a tab. + */ +@Composable +fun TabList( + store: BrowserStore, + modifier: Modifier = Modifier, + tabsFilter: (TabSessionState) -> Boolean = { true }, + onTabSelected: (TabSessionState) -> Unit = {}, + onTabClosed: (TabSessionState) -> Unit = {}, +) { + val tabs = store.observeAsComposableState { state -> state.tabs.filter(tabsFilter) } + val selectedTabId = store.observeAsComposableState { state -> state.selectedTabId } + TabList( + tabs.value ?: emptyList(), + modifier, + selectedTabId.value, + onTabSelected, + onTabClosed, + ) +} + +/** + * Renders the given list of [tabs]. + * + * @param tabs The list of tabs to render. + * @param selectedTabId the currently selected tab ID. + * @param modifier The modifier to apply to this layout. + * @param onTabClosed Gets invoked when the user closes a tab. + * @param onTabSelected Gets invoked when the user selects a tab. + */ +@Composable +fun TabList( + tabs: List<TabSessionState>, + modifier: Modifier = Modifier, + selectedTabId: String? = null, + onTabSelected: (TabSessionState) -> Unit, + onTabClosed: (TabSessionState) -> Unit, +) { + LazyColumn( + modifier = modifier + .fillMaxWidth() + .background(MaterialTheme.colors.surface), + ) { + items(tabs) { tab -> + Tab( + tab, + selected = selectedTabId == tab.id, + onClick = { onTabSelected(tab) }, + onClose = { onTabClosed(tab) }, + ) + } + } +} diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/drawable/mozac_tabcounter_background.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/drawable/mozac_tabcounter_background.xml new file mode 100644 index 0000000000..489efcb568 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/drawable/mozac_tabcounter_background.xml @@ -0,0 +1,15 @@ +<?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/. --> + +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> +<path + android:pathData="M4.5,4A2.5,2.5 0,0 0,2 6.5v11A2.5,2.5 0,0 0,4.5 20h15a2.5,2.5 0,0 0,2.5 -2.5v-11A2.5,2.5 0,0 0,19.5 4h-15zM20.5,17.7 L19.7,18.5L4.3,18.5l-0.8,-0.8L3.5,6.3l0.8,-0.8h15.4l0.8,0.8v11.4z" + android:strokeWidth="1" + android:fillColor="@color/mozac_ui_tabcounter_default_tint"/> +</vector> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-am/strings.xml new file mode 100644 index 0000000000..5cb872a827 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-am/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ትር ክፈት። ትሮችን ለመቀየር መታ ያድርጉ።</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ትሮች ክፍት። ትሮችን ለመቀየር መታ ያድርጉ።</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ar/strings.xml new file mode 100644 index 0000000000..bbd8b69682 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ar/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">لسان واحد مفتوح. انقر لتبديل الألسنة.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s من الألسنة مفتوح. انقر لتبديل الألسنة.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ast/strings.xml new file mode 100644 index 0000000000..966c990739 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ast/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 llingüeta abierta. Toca pa cambiar de llingüeta.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s llingüetes abiertes. Toca pa cambiar de llingüeta.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-azb/strings.xml new file mode 100644 index 0000000000..acc68b47f3 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-azb/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">آچیق سئکمه. سئکمهلری دگیشدیرمک اوچون توخونون.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s آچیق سئکمه. دگیشدیرمک اوچون توخونون.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-be/strings.xml new file mode 100644 index 0000000000..3a96d5f1ce --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-be/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 адкрытая картка. Націсніце, каб пераключыць карткі.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Адкрытых картак: %1$s. Націсніце, каб пераключыць карткі.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bg/strings.xml new file mode 100644 index 0000000000..14638b0375 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bg/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 отворен раздел. Докоснете, за да превключите разделите.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s отворени раздела. Докоснете, за да превключите разделите.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-br/strings.xml new file mode 100644 index 0000000000..9d8952f911 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-br/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ivinell digor. Pouezit evit cheñch ivinell.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ivinell digor. Pouezit evit cheñch ivinell.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bs/strings.xml new file mode 100644 index 0000000000..7d1b51b3f4 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-bs/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 otvoren tab. Dodirnite za promjenu tabova.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s otvorenih tabova. Dodirnite za promjenu tabova.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ca/strings.xml new file mode 100644 index 0000000000..5dbcca54f0 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ca/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 pestanya oberta. Toqueu per canviar de pestanya.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestanyes obertes. Toqueu per canviar de pestanya.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cak/strings.xml new file mode 100644 index 0000000000..cb7c638e0c --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cak/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ruwi\' jaqon. Tachapa\' richin nak\'ëx ruwi\'.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ruwi\' ejaqon. Tachapa\' richin nak\'ëx ruwi\'.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ceb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ceb/strings.xml new file mode 100644 index 0000000000..26943c382c --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ceb/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ang abli nga tab. i-Tap para mobalhin ug mga tab.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ang abli nga mga tab. i-Tap para mobalhin ug mga tab.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ckb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ckb/strings.xml new file mode 100644 index 0000000000..7152d88845 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ckb/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">١ بازدەر کراوەیە. پەنجەدابگرە بۆ گۆڕینی بازدەرەکان.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s بازدەر کراوەیە. پەنجەدابگرە بۆ گۆڕینی بازدەرەکان.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-co/strings.xml new file mode 100644 index 0000000000..4c1798bd68 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-co/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 unghjetta aperta. Picchichjà per cambià d’unghjetta.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s unghjette aperte. Picchichjà per cambià d’unghjetta.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cs/strings.xml new file mode 100644 index 0000000000..cb7c806931 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cs/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">Jeden otevřený panel. Klepnutím panely přepnete.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s otevřených panelů. Klepnutím přepnete panely.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cy/strings.xml new file mode 100644 index 0000000000..77d02443e7 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-cy/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 tab ar agor. Tapio i newid tabiau.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tab ar agor. Tapio i newid tabiau.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-da/strings.xml new file mode 100644 index 0000000000..ac794bbf47 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-da/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 åbent faneblad. Tryk for at skifte faneblade.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s åbne faneblade. Tryk for at skifte faneblade.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-de/strings.xml new file mode 100644 index 0000000000..704e927f0e --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-de/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 offener Tab. Antippen, um Tabs zu wechseln.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s offene Tabs. Antippen, um Tabs zu wechseln.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-dsb/strings.xml new file mode 100644 index 0000000000..afb4eb2be2 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-dsb/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 wócynjony rejtarik. Pótusniśo, aby rejtariki pśešaltował.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Wócynjone rejtariki: %1$s. Pótusniśo, aby rejtariki pśešaltował.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-el/strings.xml new file mode 100644 index 0000000000..f25b3f5377 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-el/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ανοικτή καρτέλα. Πατήστε για εναλλαγή καρτελών.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ανοικτές καρτέλες. Πατήστε για εναλλαγή καρτελών.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rCA/strings.xml new file mode 100644 index 0000000000..4ca62a8c45 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rCA/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 open tab. Tap to switch tabs.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open tabs. Tap to switch tabs.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 0000000000..4ca62a8c45 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 open tab. Tap to switch tabs.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open tabs. Tap to switch tabs.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eo/strings.xml new file mode 100644 index 0000000000..d013c4a3a5 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eo/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 malfermita langeto. Tuŝetu por ŝanĝi langeton.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s malfermitaj langetoj. Tuŝetu por ŝanĝi langeton.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 0000000000..6344a3e800 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Tocá para cambiar de pestaña.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Tocá para cambiar de pestaña.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rCL/strings.xml new file mode 100644 index 0000000000..1fc73bee57 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rCL/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Toca para cambiar de pestaña.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Toca para cambiar de pestaña.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rES/strings.xml new file mode 100644 index 0000000000..1fc73bee57 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rES/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Toca para cambiar de pestaña.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Toca para cambiar de pestaña.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rMX/strings.xml new file mode 100644 index 0000000000..93340efa67 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es-rMX/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Tocar para cambiar de pestaña.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Tocar para cambiar de pestaña.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es/strings.xml new file mode 100644 index 0000000000..1fc73bee57 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-es/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 pestaña abierta. Toca para cambiar de pestaña.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s pestañas abiertas. Toca para cambiar de pestaña.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-et/strings.xml new file mode 100644 index 0000000000..9bb9d80603 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-et/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 avatud kaart. Kaartide vahetamiseks puuduta.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s avatud kaarti. Kaartide vahetamiseks puuduta.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eu/strings.xml new file mode 100644 index 0000000000..52ef09e49b --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-eu/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">Irekitako fitxa bat. Sakatu fitxaz aldatzeko.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Irekitako %1$s fitxa. Sakatu fitxaz aldatzeko.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fa/strings.xml new file mode 100644 index 0000000000..c28779d31a --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fa/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 زبانه باز. برای تغییر زبانه ها ضربه بزنید.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s زبانههای باز. برای تغییر زبانهها ضربه بزنید.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fi/strings.xml new file mode 100644 index 0000000000..9043061f21 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fi/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 avoin välilehti. Napauta vaihtaaksesi.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s avointa välilehteä. Napauta vaihtaaksesi.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000000..5b0e434e7a --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fr/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 onglet ouvert. Appuyez pour changer d’onglet.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s onglets ouverts. Appuyez pour changer d’onglet.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fur/strings.xml new file mode 100644 index 0000000000..66634fc877 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fur/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 schede vierte. Tocje par cambiâ schede.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s schedis viertis. Tocje par cambiâ schede.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fy-rNL/strings.xml new file mode 100644 index 0000000000..f6662bab43 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-fy-rNL/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 iepen ljepblêd. Tik om tusken ljepblêden te wikseljen.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s iepen ljepblêden. Tik om tusken ljepblêden te wikseljen.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gd/strings.xml new file mode 100644 index 0000000000..c93c8ec7a6 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gd/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">Tha taba fosgailte. Thoir gnogag airson leum a ghearradh gu taba eile.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Tha tabaichean (%1$s) fosgailte. Thoir gnogag airson leum a ghearradh gu taba eile.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gl/strings.xml new file mode 100644 index 0000000000..3148297284 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gl/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 separador aberto. Toque para cambiar de separador.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s separadores abertos. Toque para cambiar de separador.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gn/strings.xml new file mode 100644 index 0000000000..2716e6a454 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-gn/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 tendayke mbojuruja. Eikutu emoambue hag̃ua tendayke.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tendayke ijurujáva. Eikutu emoambue hag̃ua tendayke.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hi-rIN/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hi-rIN/strings.xml new file mode 100644 index 0000000000..5700f3b171 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hi-rIN/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 खुले टैब। टैब स्विच करने के लिए टैप करें।</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s खुले टैब। टैब स्विच करने के लिए टैप करें।</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hr/strings.xml new file mode 100644 index 0000000000..71af2cc3cd --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hr/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 otvorena kartica. Dodirni za prebacivanje kartica.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s otvorene kartice. Dodirni za prebacivanje kartica.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hsb/strings.xml new file mode 100644 index 0000000000..f1a123a29e --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hsb/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 wočinjeny rajtark. Podótkńće so, zo byšće rajtarki přepinał.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Wočinjene rajtarki: %1$s. Podótkńće so, zo byšće rajtarki přepinał.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hu/strings.xml new file mode 100644 index 0000000000..1d101ccdd3 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hu/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 nyitott lap. Koppintson a lapváltáshoz.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s nyitott lap. Koppintson a lapváltáshoz.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000000..4dcf37a304 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-hy-rAM/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 բաց ներդիր: Հպեք՝ ներդիրին անցնելու համար:</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s բաց ներդիրներ: Հպեք՝ ներդիրին անցնելու համար:</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ia/strings.xml new file mode 100644 index 0000000000..978d967aab --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ia/strings.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 scheda aperte. Tocca pro cambiar de scheda. +</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s schedas aperte. Tocca pro cambiar de scheda.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-in/strings.xml new file mode 100644 index 0000000000..bce1963ede --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-in/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 tab terbuka. Ketuk untuk beralih tab.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tab terbuka. Ketuk untuk beralih tab.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-is/strings.xml new file mode 100644 index 0000000000..a66a6df882 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-is/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 opinn flipi. Snertu til að skipta um flipa.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s opnir flipar. Snertu til að skipta um flipa.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-it/strings.xml new file mode 100644 index 0000000000..140462654e --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-it/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">Aperta 1 scheda. Tocca per passare alla scheda.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Aperte %1$s schede. Tocca per passare alle schede.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-iw/strings.xml new file mode 100644 index 0000000000..4f1393a5e8 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-iw/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">לשונית אחת פתוחה. יש להקיש כדי להחליף לשוניות.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s לשוניות פתוחות. יש להקיש כדי להחליף לשוניות.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ja/strings.xml new file mode 100644 index 0000000000..c9d1a62ca7 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ja/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">開いているタブ 1 個。タップしてタブを切り替えます。</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">開いているタブ %1$s 個。タップしてタブを切り替えます。</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ka/strings.xml new file mode 100644 index 0000000000..934c9fea2d --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ka/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 გახსნილი ჩანართი. შეეხეთ ჩანართების გადასართველად.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s გახსნილი ჩანართი. შეეხეთ ჩანართების გადასართველად.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kaa/strings.xml new file mode 100644 index 0000000000..44c0e17a69 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kaa/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 bet ashıq. Basqa betlerge ótiw ushın basıń.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s bet ashıq. Basqa betlerge ótiw ushın basıń.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kab/strings.xml new file mode 100644 index 0000000000..8c487c45bb --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kab/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 yiccer i yeldin. Sit akken ad tettbeddileḍ accaren.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s waccaren yeldin. Sit akken ad tettbeddileḍ gar waccaren.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kk/strings.xml new file mode 100644 index 0000000000..ac04517a9a --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kk/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ашық бет. Беттерді ауыстыру үшін шертіңіз.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ашық бет. Беттерді ауыстыру үшін шертіңіз.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kmr/strings.xml new file mode 100644 index 0000000000..822e18a09a --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-kmr/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 hilpekîna vekirî. Ji bo hilpekînê biguherînî, bitikîne.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s hilpekînên vekirî. Ji bo hilpekînan biguherînî, bitikîne.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ko/strings.xml new file mode 100644 index 0000000000..5f133435b1 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ko/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">열린 탭 1개. 탭을 전환하려면 누르세요.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">열린 탭 %1$s개. 탭을 전환하려면 누르세요.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lo/strings.xml new file mode 100644 index 0000000000..0b4ad9c0bc --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lo/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ແທັບທີ່ເປີດ. ແຕະເພື່ອປ່ຽນແທັບ.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ແທັບທີ່ເປີດ. ແຕະເພື່ອປ່ຽນແທັບ.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lt/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lt/strings.xml new file mode 100644 index 0000000000..e11a4df1f6 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-lt/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 atverta kortelė. Bakstelėkite, norėdami pereiti tarp kortelių.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s atvertos kortelės. Bakstelėkite, norėdami pereiti tarp kortelių.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-mr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-mr/strings.xml new file mode 100644 index 0000000000..c5eb4b33bd --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-mr/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 टॅब उघडी. टॅब स्विच करण्यासाठी टॅप करा.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s टॅब उघड्या. टॅब स्विच करण्यासाठी टॅप करा.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-my/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-my/strings.xml new file mode 100644 index 0000000000..da0d02a362 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-my/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ဖွင်ထားသော တပ်ဘ်. တပ်ဘ်များပြောင်းလဲရန်နှိပ်ပါ။</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">ဖွင့်ထားသော တက်ဗ်များ %1$s ခု။ တက်ဗ်များပြောင်းလဲရန်နှိပ်ပါ။</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nb-rNO/strings.xml new file mode 100644 index 0000000000..ce10fee7ea --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nb-rNO/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 åpen fane. Trykk for å bytte fane.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s åpne faner. Trykk for å bytte fane.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ne-rNP/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ne-rNP/strings.xml new file mode 100644 index 0000000000..297d697276 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ne-rNP/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1ट्याब खोल्नुहोस् । ट्याबहरु बिच स्वीच गर्नको लागि ट्याप गर्नुहोस् ।</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ट्याबहरु खोल्नुहोस्। ट्याबहरु बिच स्वीच गर्नको लागि ट्याप गर्नुहोस्।</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nl/strings.xml new file mode 100644 index 0000000000..02eb5b97e8 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nl/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 open tabblad. Tik om tussen tabbladen te wisselen.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open tabbladen. Tik om tussen tabbladen te wisselen.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nn-rNO/strings.xml new file mode 100644 index 0000000000..a743c17ac4 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-nn-rNO/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 open fane. Trykk for å byte fane.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s opne faner. Trykk for å byte fane.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-oc/strings.xml new file mode 100644 index 0000000000..6e5eb1f335 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-oc/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 onglet dobèrt. Tocatz per i bascular.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s onglets dobèrts. Tocatz per cambiar d’onglet.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 0000000000..b6941d927d --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ਟੈਬ ਖੋਲ੍ਹੋ। ਟੈਬਾਂ ਬਦਲਣ ਲਈ ਛੂਹੋ।</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ਟੈਬਾਂ ਖੋਲ੍ਹੋ। ਟੈਬਾਂ ਬਦਲਣ ਲਈ ਛੂਹੋ।</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rPK/strings.xml new file mode 100644 index 0000000000..fee2e99440 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pa-rPK/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">اک ٹیب کھُلھی اے۔ ہورناں ٹیب جاوݨ لئی اِتھے چھوہو۔</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ٹیباں کھُلھیاں ہن۔ ہورناں ٹیب جاوݨ لئی اِتھے چھوہو۔</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pl/strings.xml new file mode 100644 index 0000000000..95eff57834 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pl/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">Otwarte karty: 1. Stuknij, aby przełączyć karty.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Otwarte karty: %1$s. Stuknij, aby przełączyć karty.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000000..c26434a581 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 aba aberta. Toque para alternar abas.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s abas abertas. Toque para alternar abas.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000..b0481b37f4 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 separador aberto. Toque para mudar de separador.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s separadores abertos. Toque para mudar de separador.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-rm/strings.xml new file mode 100644 index 0000000000..1a085d3aa4 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-rm/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 tab avert. Tutgar per midar tab.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tabs averts. Tutgar per midar tab.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ro/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ro/strings.xml new file mode 100644 index 0000000000..4e5f9a7a12 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ro/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 filă deschisă. Atinge pentru a comuta între file.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s file deschise. Atinge pentru a comuta între file.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000000..084301cc50 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ru/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 открытая вкладка. Нажмите, чтобы переключить вкладки.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Открытых вкладок: %1$s. Нажмите, чтобы переключить вкладки.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sat/strings.xml new file mode 100644 index 0000000000..31dce75121 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sat/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ᱴᱮᱵᱽ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ ᱾ ᱴᱮᱵᱽ ᱵᱚᱫᱚᱞ ᱞᱟᱹᱜᱤᱫ ᱴᱤᱯᱟᱹᱣ ᱢᱮ ᱾</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ᱴᱮᱵᱽ ᱠᱚ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ ᱾ ᱴᱮᱵᱽ ᱵᱚᱫᱚᱞ ᱞᱟᱹᱜᱤᱫ ᱴᱤᱯᱟᱹᱣ ᱢᱮ ᱾</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sc/strings.xml new file mode 100644 index 0000000000..aba35fe993 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sc/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ischeda aberta. Toca pro cuncambiare ischedas.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ischedas abertas. Toca pro cuncambiare ischedas.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-si/strings.xml new file mode 100644 index 0000000000..fa81c6c72e --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-si/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">විවෘත පටිති 1. මාරු වීමට ඔබන්න.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">විවෘත පටිති %1$s. මාරු වීමට ඔබන්න.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sk/strings.xml new file mode 100644 index 0000000000..6d9c07e007 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sk/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">Počet otvorených kariet: 1. Ťuknutím prepnete karty.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Počet otvorených kariet: %1$s. Ťuknutím prepnete karty.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-skr/strings.xml new file mode 100644 index 0000000000..259bf6e843 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-skr/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ٹیب کھولو۔ ٹیبز بدلن کیتے دباؤ۔</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ٹیبز کھولو۔ ٹیبز بدلن کیتے دباؤ۔</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sl/strings.xml new file mode 100644 index 0000000000..da63aabfe3 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sl/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 odprt zavihek. Tapnite za preklop zavihkov.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Odprtih zavihkov: %1$s. Tapnite za preklop zavihkov.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sq/strings.xml new file mode 100644 index 0000000000..ab5ac214b6 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sq/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 skedë e hapur. Prekeni që të ndërroni skeda.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s skeda të hapura. Prekeni që të ndërroni skeda.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sr/strings.xml new file mode 100644 index 0000000000..c2b36f1e84 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sr/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 отворен језичак. Додирни за пребацивање.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s отоврених језичака. Додирни за пребацивање.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-su/strings.xml new file mode 100644 index 0000000000..6ca8fedea8 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-su/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 tab muka. Toél pikeun ngagilir tab.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s tab muka. Toél pikeun ngagilir tab.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sv-rSE/strings.xml new file mode 100644 index 0000000000..4dccc57f82 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-sv-rSE/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 öppen flik. Tryck för att växla mellan flikar.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s öppna flikar. Tryck för att växla mellan flikar.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-szl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-szl/strings.xml new file mode 100644 index 0000000000..d8a8f70ecd --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-szl/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ôtwarto karta. Tyknij, coby przełōnczyć karty.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Ôtwarte karty: %1$s. Tyknij, coby je zmiynić.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ta/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ta/strings.xml new file mode 100644 index 0000000000..dd73074d4e --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ta/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 திறந்த கீற்று. கீற்றுகளிடையே மாற தட்டு.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s திறந்த கீற்றுகள். கீற்றுகளிடையே மாற தட்டு.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tg/strings.xml new file mode 100644 index 0000000000..ec5a7e0129 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tg/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 варақаи кушодашуда. Барои гузариш байни варақаҳо зарба занед.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s варақаи кушодашуда. Барои гузариш байни варақаҳо зарба занед.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-th/strings.xml new file mode 100644 index 0000000000..8dd4edebd2 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-th/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 แท็บที่เปิด แตะเพื่อสลับไปยังแท็บ</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s แท็บที่เปิด แตะเพื่อสลับไปยังแท็บ</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tl/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tl/strings.xml new file mode 100644 index 0000000000..b90ceee0ac --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tl/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 open na tab. i-Tap para mag switch ng tabs.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open na tabs. i-Tap para mag switch ng tabs.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tr/strings.xml new file mode 100644 index 0000000000..6fd9d0a795 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tr/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 açık sekme. Sekme değiştirmek için dokunun.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s açık sekme. Sekme değiştirmek için dokunun.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-trs/strings.xml new file mode 100644 index 0000000000..73ab55b438 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-trs/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 nā\'nïn rakïj ñanj. Gūru\'man ra\'a da\' nādūnāt rakïj ñanj.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s nā\'nïn nej rakïj ñanj. Gūru\'man ra\'a da\' nādūnāt nej rakïj ñanj.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tt/strings.xml new file mode 100644 index 0000000000..cccb0f592c --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-tt/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ачык таб. Табларны алмаштыру өчен басыгыз.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ачык таб. Табларны алмаштыру өчен басыгыз.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ug/strings.xml new file mode 100644 index 0000000000..b06335ccd7 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ug/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 بەتكۈچ ئوچۇق. بەتكۈچنى ئالماشتۇرۇش ئۈچۈن چېكىڭ.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s بەتكۈچ ئوچۇق. بەتكۈچنى ئالماشتۇرۇش ئۈچۈن چېكىڭ.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uk/strings.xml new file mode 100644 index 0000000000..7c4eac5634 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uk/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 відкрита вкладка. Торкніться, щоб перемкнути вкладки.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s відкритих вкладок. Торкніться, щоб перемкнути вкладки.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ur/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ur/strings.xml new file mode 100644 index 0000000000..2aff9ce62a --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-ur/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 کھلا ٹیب۔ ٹیبز بدلنے کے لئے دبائیں۔</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s کھلے ٹیب۔ ٹیب بدلنے کے لئے دبائیں۔</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uz/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uz/strings.xml new file mode 100644 index 0000000000..27d543d25d --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-uz/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 ta ochiq varaq. Boshqa varaqqa oʻtish uchun bosing.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s ta ochiq varaq. Boshqa varaqqa oʻtish uchun bosing.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vec/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vec/strings.xml new file mode 100644 index 0000000000..df02a32682 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vec/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">Verta 1 scheda. Toca par pasare a ƚa scheda.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">Verte %1$s schede. Toca par pasare a ƚe schede.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vi/strings.xml new file mode 100644 index 0000000000..b72a0a985d --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-vi/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 thẻ đang mở. Chạm để chuyển thẻ.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s thẻ đang mở. Chạm để chuyển thẻ.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-yo/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-yo/strings.xml new file mode 100644 index 0000000000..702c4c49ec --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-yo/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 sí táàbù. Fọwọ́ kàn án láti tan táàbù.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s sí táàbù. Fọwọ́ kàn án láti tan táàbù.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000..56655683a4 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">打开了 1 个标签页,点按即可切换。</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">打开了 %1$s 个标签页,点按即可切换。</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000..69ffb4a021 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">開啟了 1 個分頁,點擊即可切換分頁。</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">開啟了 %1$s 個分頁,點擊即可切換分頁。</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/main/res/values/strings.xml b/mobile/android/android-components/components/compose/tabstray/src/main/res/values/strings.xml new file mode 100644 index 0000000000..961847b251 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/main/res/values/strings.xml @@ -0,0 +1,10 @@ +<?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/. --> +<resources> + <!-- Message announced to the user when tab tray is selected with 1 tab --> + <string name="mozac_tab_counter_open_tab_tray_single">1 open tab. Tap to switch tabs.</string> + <!-- Message announced to the user when tab tray is selected with multiple tabs. %1$s is getting replaced with the number of open tabs. --> + <string name="mozac_tab_counter_open_tab_tray_plural">%1$s open tabs. Tap to switch tabs.</string> +</resources> diff --git a/mobile/android/android-components/components/compose/tabstray/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/mobile/android/android-components/components/compose/tabstray/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 0000000000..cf1c399ea8 --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1,2 @@ +mock-maker-inline +// This allows mocking final classes (classes are final by default in Kotlin) diff --git a/mobile/android/android-components/components/compose/tabstray/src/test/resources/robolectric.properties b/mobile/android/android-components/components/compose/tabstray/src/test/resources/robolectric.properties new file mode 100644 index 0000000000..932b01b9eb --- /dev/null +++ b/mobile/android/android-components/components/compose/tabstray/src/test/resources/robolectric.properties @@ -0,0 +1 @@ +sdk=28 |