diff options
Diffstat (limited to 'mobile/android/android-components/components/ui/widgets/src/main')
102 files changed, 1853 insertions, 0 deletions
diff --git a/mobile/android/android-components/components/ui/widgets/src/main/AndroidManifest.xml b/mobile/android/android-components/components/ui/widgets/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..e16cda1d34 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/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/ui/widgets/src/main/java/mozilla/components/ui/widgets/Extentions.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/Extentions.kt new file mode 100644 index 0000000000..fb17b7eb5a --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/Extentions.kt @@ -0,0 +1,37 @@ +/* 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.ui.widgets + +import android.widget.TextView +import android.view.View.TEXT_ALIGNMENT_CENTER as CENTER + +/** + * A shortcut to align buttons' text to center inside AlertDialog. + */ +fun androidx.appcompat.app.AlertDialog.withCenterAlignedButtons(): androidx.appcompat.app.AlertDialog { + findViewById<TextView>(android.R.id.button1)?.let { it.textAlignment = CENTER } + findViewById<TextView>(android.R.id.button2)?.let { it.textAlignment = CENTER } + findViewById<TextView>(android.R.id.button3)?.let { it.textAlignment = CENTER } + return this +} + +/** + * A shortcut to align buttons' text to center inside AlertDialog. + * + * Important: On Android API levels lower than 24, this method must be called only AFTER the dialog + * has been shown. Calling this method prior to displaying the dialog on those API levels will cause + * partial initialization of the view, leading to a crash. + * + * Usage example: + * dialog.setOnShowListener { + * dialog.withCenterAlignedButtons() + * } + */ +fun android.app.AlertDialog.withCenterAlignedButtons(): android.app.AlertDialog { + findViewById<TextView>(android.R.id.button1)?.let { it.textAlignment = CENTER } + findViewById<TextView>(android.R.id.button2)?.let { it.textAlignment = CENTER } + findViewById<TextView>(android.R.id.button3)?.let { it.textAlignment = CENTER } + return this +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/SnackbarDelegate.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/SnackbarDelegate.kt new file mode 100644 index 0000000000..8e2dd2fad7 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/SnackbarDelegate.kt @@ -0,0 +1,55 @@ +/* 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.ui.widgets + +import android.view.View +import com.google.android.material.snackbar.Snackbar + +/** + * Delegate to display a snackbar. + */ +interface SnackbarDelegate { + /** + * Displays a snackbar. + * + * @param snackBarParentView The view to find a parent from for displaying the Snackbar. + * @param text The text to show. Can be formatted text. + * @param duration How long to display the message. + * @param action String resource to display for the action. + * @param listener callback to be invoked when the action is clicked. + */ + fun show( + snackBarParentView: View, + text: Int, + duration: Int, + action: Int = 0, + listener: ((v: View) -> Unit)? = null, + ) +} + +/** + * Default implementation for [SnackbarDelegate]. Will display a standard default Snackbar. + */ +class DefaultSnackbarDelegate : SnackbarDelegate { + override fun show( + snackBarParentView: View, + text: Int, + duration: Int, + action: Int, + listener: ((v: View) -> Unit)?, + ) { + val snackbar = Snackbar.make( + snackBarParentView, + text, + duration, + ) + + if (action != 0 && listener != null) { + snackbar.setAction(action, listener) + } + + snackbar.show() + } +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/VerticalSwipeRefreshLayout.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/VerticalSwipeRefreshLayout.kt new file mode 100644 index 0000000000..aa8bc10b67 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/VerticalSwipeRefreshLayout.kt @@ -0,0 +1,216 @@ +/* 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.ui.widgets + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import android.view.ViewConfiguration +import androidx.annotation.VisibleForTesting +import androidx.swiperefreshlayout.widget.SwipeRefreshLayout +import kotlin.math.abs + +/** + * [SwipeRefreshLayout] that filters only vertical scrolls for triggering pull to refresh. + * + * Following situations will not trigger pull to refresh: + * - a scroll happening more on the horizontal axis + * - a scale in/out gesture + * - a quick scale gesture + * + * To control responding to scrolls and showing the pull to refresh throbber or not + * use the [View.isEnabled] property. + */ +class VerticalSwipeRefreshLayout @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, +) : SwipeRefreshLayout(context, attrs) { + @VisibleForTesting + internal var isQuickScaleInProgress = false + + @VisibleForTesting + internal var quickScaleEvents = QuickScaleEvents() + private var previousX = 0f + private var previousY = 0f + private val doubleTapTimeout = ViewConfiguration.getDoubleTapTimeout() + private val doubleTapSlop = ViewConfiguration.get(context).scaledDoubleTapSlop + private val doubleTapSlopSquare = doubleTapSlop * doubleTapSlop + + @VisibleForTesting + internal var hadMultiTouch: Boolean = false + + @VisibleForTesting + internal var disallowInterceptTouchEvent = false + + @Suppress("ComplexMethod", "ReturnCount") + override fun onInterceptTouchEvent(event: MotionEvent): Boolean { + // Setting "isEnabled = false" is recommended for users of this ViewGroup + // who who are not interested in the pull to refresh functionality + // Setting this easily avoids executing code unneededsly before the check for "canChildScrollUp". + if (!isEnabled || disallowInterceptTouchEvent) { + return false + } + + if (MotionEvent.ACTION_DOWN == event.action) { + hadMultiTouch = false + } + + // Layman's scale gesture (with two fingers) detector. + // Allows for quick, serial inference as opposed to using ScaleGestureDetector + // which uses callbacks and would be hard to synchronize in the little time we have. + if (event.pointerCount > 1 || hadMultiTouch) { + hadMultiTouch = true + return false + } + + val eventAction = event.action + + // Cleanup if the gesture has been aborted or quick scale just ended/ + if (MotionEvent.ACTION_CANCEL == eventAction || + (MotionEvent.ACTION_UP == eventAction && isQuickScaleInProgress) + ) { + forgetQuickScaleEvents() + return callSuperOnInterceptTouchEvent(event) + } + + // Disable pull to refresh if quick scale is in progress. + maybeAddDoubleTapEvent(event) + if (isQuickScaleInProgress(quickScaleEvents)) { + isQuickScaleInProgress = true + return false + } + + // Disable pull to refresh if the move was more on the X axis. + if (MotionEvent.ACTION_DOWN == eventAction) { + previousX = event.x + previousY = event.y + } else if (MotionEvent.ACTION_MOVE == eventAction) { + val xDistance = abs(event.x - previousX) + val yDistance = abs(event.y - previousY) + previousX = event.x + previousY = event.y + if (xDistance > yDistance) { + return false + } + } + + return callSuperOnInterceptTouchEvent(event) + } + + override fun onStartNestedScroll(child: View, target: View, nestedScrollAxes: Int): Boolean { + // Ignoring nested scrolls from descendants. + // Allowing descendants to trigger nested scrolls would defeat the purpose of this class + // and result in pull to refresh to happen for all movements on the Y axis + // (even as part of scale/quick scale gestures) while also doubling the throbber with the overscroll shadow. + return if (isEnabled) { + return false + } else { + callSuperOnStartNestedScroll(child, target, nestedScrollAxes) + } + } + + @SuppressLint("Recycle") // we do recycle the events in forgetQuickScaleEvents() + @VisibleForTesting + internal fun maybeAddDoubleTapEvent(event: MotionEvent) { + val currentEventAction = event.action + + // A double tap event must follow the order: + // ACTION_DOWN - ACTION_UP - ACTION_DOWN + // all these events happening in an interval defined by a system constant - DOUBLE_TAP_TIMEOUT + + if (MotionEvent.ACTION_DOWN == currentEventAction) { + if (quickScaleEvents.upEvent != null) { + if (event.eventTime - quickScaleEvents.upEvent!!.eventTime > doubleTapTimeout) { + // Too much time passed for the MotionEvents sequence to be considered + // a quick scale gesture. Restart counting. + forgetQuickScaleEvents() + quickScaleEvents.firstDownEvent = MotionEvent.obtain(event) + } else { + quickScaleEvents.secondDownEvent = MotionEvent.obtain(event) + } + } else { + // This may be the first time the user touches the screen or + // the gesture was not finished with ACTION_UP. + forgetQuickScaleEvents() + quickScaleEvents.firstDownEvent = MotionEvent.obtain(event) + } + } + // For the double tap events series we need ACTION_DOWN first + // and then ACTION_UP second. + else if (MotionEvent.ACTION_UP == currentEventAction && quickScaleEvents.firstDownEvent != null) { + quickScaleEvents.upEvent = MotionEvent.obtain(event) + } + } + + override fun requestDisallowInterceptTouchEvent(b: Boolean) { + // We need to disable Pull to Refresh on this layout be we don't want to propagate the + // request to the parent, because they may use the gesture for other purpose, like + // propagating it to ToolbarBehavior + this.disallowInterceptTouchEvent = b + } + + @VisibleForTesting + internal fun forgetQuickScaleEvents() { + quickScaleEvents.firstDownEvent?.recycle() + quickScaleEvents.upEvent?.recycle() + quickScaleEvents.secondDownEvent?.recycle() + quickScaleEvents.firstDownEvent = null + quickScaleEvents.upEvent = null + quickScaleEvents.secondDownEvent = null + + isQuickScaleInProgress = false + } + + @VisibleForTesting + internal fun isQuickScaleInProgress(events: QuickScaleEvents): Boolean { + return if (events.isNotNull()) { + isQuickScaleInProgress(events.firstDownEvent!!, events.upEvent!!, events.secondDownEvent!!) + } else { + false + } + } + + // Method closely following GestureDetectorCompat#isConsideredDoubleTap. + // Allows for serial inference of double taps as opposed to using callbacks. + @VisibleForTesting + internal fun isQuickScaleInProgress( + firstDown: MotionEvent, + firstUp: MotionEvent, + secondDown: MotionEvent, + ): Boolean { + if (secondDown.eventTime - firstUp.eventTime > doubleTapTimeout) { + return false + } + + val deltaX = firstDown.x.toInt() - secondDown.x.toInt() + val deltaY = firstDown.y.toInt() - secondDown.y.toInt() + + return deltaX * deltaX + deltaY * deltaY < doubleTapSlopSquare + } + + @VisibleForTesting + internal fun callSuperOnInterceptTouchEvent(event: MotionEvent) = + super.onInterceptTouchEvent(event) + + @VisibleForTesting + internal fun callSuperOnStartNestedScroll(child: View, target: View, nestedScrollAxes: Int) = + super.onStartNestedScroll(child, target, nestedScrollAxes) + + private fun QuickScaleEvents.isNotNull(): Boolean { + return firstDownEvent != null && upEvent != null && secondDownEvent != null + } + + /** + * Wrapper over the MotionEvents that compose a quickScale gesture. + */ + @VisibleForTesting + internal data class QuickScaleEvents( + var firstDownEvent: MotionEvent? = null, + var upEvent: MotionEvent? = null, + var secondDownEvent: MotionEvent? = null, + ) +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/WidgetSiteItemView.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/WidgetSiteItemView.kt new file mode 100644 index 0000000000..0eca198957 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/WidgetSiteItemView.kt @@ -0,0 +1,106 @@ +/* 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.ui.widgets + +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.FrameLayout +import android.widget.ImageButton +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.appcompat.content.res.AppCompatResources.getDrawable +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.core.view.isVisible + +/** + * Shared UI widget for showing a website in a list of websites, + * such as in bookmarks, history, site exceptions, or collections. + */ +class WidgetSiteItemView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : ConstraintLayout(context, attrs, defStyleAttr) { + + private val labelView: TextView by lazy { findViewById<TextView>(R.id.label) } + private val captionView: TextView by lazy { findViewById<TextView>(R.id.caption) } + private val iconWrapper: FrameLayout by lazy { findViewById<FrameLayout>(R.id.favicon_wrapper) } + private val secondaryButton: ImageButton by lazy { findViewById<ImageButton>(R.id.secondary_button) } + + /** + * ImageView that should display favicons. + */ + val iconView: ImageView by lazy { findViewById<ImageView>(R.id.favicon) } + + init { + LayoutInflater.from(context).inflate(R.layout.mozac_widget_site_item, this, true) + } + + /** + * Sets the text displayed inside of the site item view. + * + * @param label Main label text, such as a site title. + * @param caption Sub caption text, such as a URL. If null, the caption is hidden. + */ + fun setText(label: CharSequence, caption: CharSequence?) { + labelView.text = label + captionView.text = caption + captionView.isVisible = caption != null + } + + /** + * Add a view that will overlay the favicon, such as a checkmark. + */ + fun addIconOverlay(overlay: View) { + iconWrapper.addView(overlay) + } + + /** + * Add a secondary button, such as an overflow menu. + * + * @param icon Drawable to display in the button. + * @param contentDescription Accessible description of the button's purpose. + * @param onClickListener Listener called when the button is clicked. + */ + fun setSecondaryButton( + icon: Drawable?, + contentDescription: CharSequence, + onClickListener: (View) -> Unit, + ) { + secondaryButton.isVisible = true + secondaryButton.setImageDrawable(icon) + secondaryButton.contentDescription = contentDescription + secondaryButton.setOnClickListener(onClickListener) + } + + /** + * Add a secondary button, such as an overflow menu. + * + * @param icon Drawable to display in the button. + * @param contentDescription Accessible description of the button's purpose. + * @param onClickListener Listener called when the button is clicked. + */ + fun setSecondaryButton( + @DrawableRes icon: Int, + @StringRes contentDescription: Int, + onClickListener: (View) -> Unit, + ) = setSecondaryButton( + icon = getDrawable(context, icon), + contentDescription = context.getString(contentDescription), + onClickListener = onClickListener, + ) + + /** + * Removes the secondary button if it was previously set in [setSecondaryButton]. + */ + fun removeSecondaryButton() { + secondaryButton.isVisible = false + } +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/BrowserGestureDetector.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/BrowserGestureDetector.kt new file mode 100644 index 0000000000..b15df65078 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/BrowserGestureDetector.kt @@ -0,0 +1,192 @@ +/* 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.ui.widgets.behavior + +import android.content.Context +import android.view.GestureDetector +import android.view.MotionEvent +import android.view.ScaleGestureDetector +import androidx.annotation.VisibleForTesting +import mozilla.components.concept.base.crash.CrashReporting +import kotlin.math.abs + +/** + * Wraps exceptions that are caught by [BrowserGestureDetector]. + * Instances of this class are submitted via [CrashReporting]. This wrapping helps easily identify + * exceptions related to [BrowserGestureDetector]. + */ +internal class BrowserGestureDetectorException(e: Throwable) : Throwable(e) + +/** + * Custom [MotionEvent] gestures detector with scroll / zoom callbacks. + * + * Favors zoom gestures in detriment of the scroll gestures with: + * - higher sensitivity for multi-finger zoom gestures + * - ignoring scrolls if zoom is in progress + * + * @param applicationContext context used for registering internal gesture listeners. + * @param listener client interested in zoom / scroll events. + */ +internal class BrowserGestureDetector( + applicationContext: Context, + listener: GesturesListener, + private val crashReporting: CrashReporting? = null, +) { + @VisibleForTesting + internal var gestureDetector = GestureDetector( + applicationContext, + CustomScrollDetectorListener { previousEvent: MotionEvent?, currentEvent: MotionEvent, distanceX, distanceY -> + run { + listener.onScroll?.invoke(distanceX, distanceY) + + // We got many crashes because of the initial event - ACTION_DOWN being null. + // Investigations to be continued in android-components/issues/8552. + // In the meantime we'll protect against this with a simple null check. + if (previousEvent != null) { + if (abs(currentEvent.y - previousEvent.y) >= abs(currentEvent.x - previousEvent.x)) { + listener.onVerticalScroll?.invoke(distanceY) + } else { + listener.onHorizontalScroll?.invoke(distanceX) + } + } + } + }, + ) + + @VisibleForTesting + internal var scaleGestureDetector = ScaleGestureDetector( + applicationContext, + CustomScaleDetectorListener( + listener.onScaleBegin ?: {}, + listener.onScale ?: {}, + listener.onScaleEnd ?: {}, + ), + ) + + /** + * Accepts MotionEvents and dispatches zoom / scroll events to the registered listener when appropriate. + * + * Applications should pass a complete and consistent event stream to this method. + * A complete and consistent event stream involves all MotionEvents from the initial ACTION_DOWN + * to the final ACTION_UP or ACTION_CANCEL. + * + * @return if the event was handled by any of the registered detectors + */ + @Suppress("ComplexCondition") + internal fun handleTouchEvent(event: MotionEvent): Boolean { + val eventAction = event.actionMasked + + // A double tap for a quick scale gesture (quick double tap followed by a drag) + // would trigger a ACTION_CANCEL event before the MOVE_EVENT. + // This would prevent the scale detector from properly inferring the movement. + // We'll want to ignore ACTION_CANCEL but process the next stream of events. + if (eventAction != MotionEvent.ACTION_CANCEL) { + scaleGestureDetector.onTouchEvent(event) + } + + // Ignore scrolling if zooming is already in progress. + // Always pass motion begin / end events just to have the detector ready + // to infer scrolls when the scale gesture ended. + return if (!scaleGestureDetector.isInProgress || + eventAction == MotionEvent.ACTION_DOWN || + eventAction == MotionEvent.ACTION_UP || + eventAction == MotionEvent.ACTION_CANCEL + ) { + @Suppress("TooGenericExceptionCaught") + try { + gestureDetector.onTouchEvent(event) + } catch (e: Exception) { + crashReporting?.submitCaughtException(BrowserGestureDetectorException(e)) + false + } + } else { + false + } + } + + /** + * A convenience containing listeners for zoom / scroll events + * + * Provide implementation for the events you are interested in. + * The others will be no-op. + */ + internal class GesturesListener( + /** + * Responds to scroll events for a gesture in progress. + * The distance in x and y is also supplied for convenience. + */ + val onScroll: ((distanceX: Float, distanceY: Float) -> Unit)? = { _, _ -> run {} }, + + /** + * Responds to an in progress scroll occuring more on the vertical axis. + * The scroll distance is also supplied for convenience. + */ + val onVerticalScroll: ((distance: Float) -> Unit)? = {}, + + /** + * Responds to an in progress scroll occurring more on the horizontal axis. + * The scroll distance is also supplied for convenience. + */ + val onHorizontalScroll: ((distance: Float) -> Unit)? = {}, + + /** + * Responds to the the beginning of a new scale gesture. + * Reported by new pointers going down. + */ + val onScaleBegin: ((scaleFactor: Float) -> Unit)? = {}, + + /** + * Responds to scaling events for a gesture in progress. + * The scaling factor is also supplied for convenience. + * This value is represents the difference from the previous scale event to the current event. + */ + val onScale: ((scaleFactor: Float) -> Unit)? = {}, + + /** + * Responds to the end of a scale gesture. + * Reported by existing pointers going up. + */ + val onScaleEnd: ((scaleFactor: Float) -> Unit)? = {}, + ) + + private class CustomScrollDetectorListener( + val onScrolling: ( + previousEvent: MotionEvent?, + currentEvent: MotionEvent, + distanceX: Float, + distanceY: Float, + ) -> Unit, + ) : GestureDetector.SimpleOnGestureListener() { + override fun onScroll( + e1: MotionEvent?, + e2: MotionEvent, + distanceX: Float, + distanceY: Float, + ): Boolean { + onScrolling(e1, e2, distanceX, distanceY) + return true + } + } + + private class CustomScaleDetectorListener( + val onScaleBegin: (scaleFactor: Float) -> Unit = {}, + val onScale: (scaleFactor: Float) -> Unit = {}, + val onScaleEnd: (scaleFactor: Float) -> Unit = {}, + ) : ScaleGestureDetector.SimpleOnScaleGestureListener() { + override fun onScaleBegin(detector: ScaleGestureDetector): Boolean { + onScaleBegin(detector.scaleFactor) + return true + } + + override fun onScale(detector: ScaleGestureDetector): Boolean { + onScale(detector.scaleFactor) + return true + } + + override fun onScaleEnd(detector: ScaleGestureDetector) { + onScaleEnd(detector.scaleFactor) + } + } +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewClippingBehavior.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewClippingBehavior.kt new file mode 100644 index 0000000000..d0f532bfbc --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewClippingBehavior.kt @@ -0,0 +1,90 @@ +/* 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.ui.widgets.behavior + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.annotation.VisibleForTesting +import androidx.coordinatorlayout.widget.CoordinatorLayout +import mozilla.components.concept.engine.EngineView +import mozilla.components.concept.toolbar.ScrollableToolbar +import mozilla.components.support.ktx.android.view.findViewInHierarchy +import kotlin.math.roundToInt + +/** + * A [CoordinatorLayout.Behavior] implementation that allows the [EngineView] to automatically + * size itself in relation to the Y translation of the [ScrollableToolbar]. + * + * This is useful for dynamic [ScrollableToolbar]s ensuring the web content is displayed immediately + * below / above the toolbar even when that is animated. + * + * @param context [Context] used for various Android interactions + * @param attrs XML set attributes configuring this + * @param engineViewParent NestedScrollingChild parent of the [EngineView] + * @param toolbarHeight size of [ScrollableToolbar] when it is placed above the [EngineView] + * @param toolbarPosition whether the [ScrollableToolbar] is placed above or below the [EngineView] + */ +class EngineViewClippingBehavior( + context: Context?, + attrs: AttributeSet?, + engineViewParent: View, + toolbarHeight: Int, + toolbarPosition: ToolbarPosition, +) : CoordinatorLayout.Behavior<View>(context, attrs) { + + @VisibleForTesting + internal val engineView = engineViewParent.findViewInHierarchy { it is EngineView } as EngineView? + + @VisibleForTesting + internal var toolbarChangedAction: (Float) -> Unit? + private val bottomToolbarChangedAction = { newToolbarTranslationY: Float -> + if (!newToolbarTranslationY.isNaN()) { + engineView?.setVerticalClipping(-newToolbarTranslationY.roundToInt()) + } + } + private val topToolbarChangedAction = { newToolbarTranslationY: Float -> + // the top toolbar is translated upwards when collapsing-> all values received are 0 or negative + engineView?.let { + it.setVerticalClipping(newToolbarTranslationY.roundToInt()) + // Need to add the toolbarHeight to effectively place the engineView below the toolbar. + engineViewParent.translationY = newToolbarTranslationY + toolbarHeight + } + } + + init { + toolbarChangedAction = if (toolbarPosition == ToolbarPosition.TOP) { + topToolbarChangedAction + } else { + bottomToolbarChangedAction + } + } + + override fun layoutDependsOn(parent: CoordinatorLayout, child: View, dependency: View): Boolean { + if (dependency is ScrollableToolbar) { + return true + } + + return super.layoutDependsOn(parent, child, dependency) + } + + /** + * Apply vertical clipping to [EngineView]. This requires [EngineViewClippingBehavior] to be set + * in/on the [EngineView] or its parent. Must be a direct descending child of [CoordinatorLayout]. + */ + override fun onDependentViewChanged(parent: CoordinatorLayout, child: View, dependency: View): Boolean { + toolbarChangedAction.invoke(dependency.translationY) + + return true + } +} + +/** + * Where the toolbar is placed on the screen. + */ +enum class ToolbarPosition { + TOP, + BOTTOM, +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehavior.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehavior.kt new file mode 100644 index 0000000000..08da7e5064 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehavior.kt @@ -0,0 +1,237 @@ +/* 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.ui.widgets.behavior + +import android.content.Context +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import androidx.annotation.VisibleForTesting +import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.view.ViewCompat +import mozilla.components.concept.base.crash.CrashReporting +import mozilla.components.concept.engine.EngineView +import mozilla.components.support.ktx.android.view.findViewInHierarchy + +/** + * Where the view is placed on the screen. + */ +enum class ViewPosition { + TOP, + BOTTOM, +} + +/** + * A [CoordinatorLayout.Behavior] implementation to be used when placing [View] at the bottom of the screen. + * + * This is safe to use even if the [View] may be added / removed from a parent layout later + * or if it could have Visibility.GONE set. + * + * This implementation will: + * - Show/Hide the [View] automatically when scrolling vertically. + * - Snap the [View] to be hidden or visible when the user stops scrolling. + */ +class EngineViewScrollingBehavior( + val context: Context?, + attrs: AttributeSet?, + private val viewPosition: ViewPosition, + private val crashReporting: CrashReporting? = null, +) : CoordinatorLayout.Behavior<View>(context, attrs) { + // This implementation is heavily based on this blog article: + // https://android.jlelse.eu/scroll-your-bottom-navigation-view-away-with-10-lines-of-code-346f1ed40e9e + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal var shouldSnapAfterScroll: Boolean = false + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal var startedScroll = false + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal var isScrollEnabled = false + + /** + * Reference to [EngineView] used to check user's [android.view.MotionEvent]s. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal var engineView: EngineView? = null + + /** + * Reference to the actual [View] that we'll animate. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal var dynamicScrollView: View? = null + + /** + * Depending on how user's touch was consumed by EngineView / current website, + * + * we will animate the dynamic navigation bar if: + * - touches were used for zooming / panning operations in the website. + * + * We will do nothing if: + * - the website is not scrollable + * - the website handles the touch events itself through it's own touch event listeners. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal val shouldScroll: Boolean + get() = engineView?.getInputResultDetail()?.let { + (it.canScrollToBottom() || it.canScrollToTop()) && isScrollEnabled + } ?: false + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal var gesturesDetector: BrowserGestureDetector = createGestureDetector() + + @VisibleForTesting + internal var yTranslator: ViewYTranslator = createYTranslationStrategy() + + private fun createYTranslationStrategy() = ViewYTranslator(viewPosition) + + override fun onStartNestedScroll( + coordinatorLayout: CoordinatorLayout, + child: View, + directTargetChild: View, + target: View, + axes: Int, + type: Int, + ): Boolean { + return if (dynamicScrollView != null) { + startNestedScroll(axes, type, child) + } else { + return false // not interested in subsequent scroll events + } + } + + override fun onStopNestedScroll( + coordinatorLayout: CoordinatorLayout, + child: View, + target: View, + type: Int, + ) { + if (dynamicScrollView != null) { + stopNestedScroll(type, child) + } + } + + override fun onInterceptTouchEvent( + parent: CoordinatorLayout, + child: View, + ev: MotionEvent, + ): Boolean { + if (dynamicScrollView != null) { + gesturesDetector.handleTouchEvent(ev) + } + return false // allow events to be passed to below listeners + } + + override fun onLayoutChild( + parent: CoordinatorLayout, + child: View, + layoutDirection: Int, + ): Boolean { + dynamicScrollView = child + engineView = parent.findViewInHierarchy { it is EngineView } as? EngineView + + return super.onLayoutChild(parent, child, layoutDirection) + } + + /** + * Used to expand the [View] + */ + fun forceExpand(view: View) { + yTranslator.expandWithAnimation(view) + } + + /** + * Used to collapse the [View] + */ + fun forceCollapse(view: View) { + yTranslator.collapseWithAnimation(view) + } + + /** + * Allow this view to be animated. + * + * @see disableScrolling + */ + fun enableScrolling() { + isScrollEnabled = true + } + + /** + * Disable scrolling of the view irrespective of the intrinsic checks. + * + * @see enableScrolling + */ + fun disableScrolling() { + isScrollEnabled = false + } + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal fun tryToScrollVertically(distance: Float) { + dynamicScrollView?.let { view -> + if (shouldScroll && startedScroll) { + yTranslator.translate(view, distance) + } else if (engineView?.getInputResultDetail()?.isTouchHandlingUnknown() == false) { + // Force expand the view if the user scrolled up, it is not already expanded and + // an animation to expand it is not already in progress, + // otherwise the user could get stuck in a state where they cannot show the view + // See https://github.com/mozilla-mobile/android-components/issues/7101 + yTranslator.forceExpandIfNotAlready(view, distance) + } + } + } + + /** + * Helper function to ease testing. + * (Re)Initializes the [BrowserGestureDetector] in a new context. + * + * Useful in spied behaviors, to ensure callbacks are of the spy and not of the initially created object + * if the passed in argument is the result of [createGestureDetector]. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal fun initGesturesDetector(detector: BrowserGestureDetector) { + gesturesDetector = detector + } + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + internal fun createGestureDetector() = + BrowserGestureDetector( + context!!, + BrowserGestureDetector.GesturesListener( + onVerticalScroll = ::tryToScrollVertically, + onScaleBegin = { + // Scale shouldn't animate the view but a small y translation is still possible + // because of a previous scroll. Try to be swift about such an in progress animation. + yTranslator.snapImmediately(dynamicScrollView) + }, + ), + crashReporting = crashReporting, + ) + + @VisibleForTesting + internal fun startNestedScroll(axes: Int, type: Int, view: View): Boolean { + return if (shouldScroll && axes == ViewCompat.SCROLL_AXIS_VERTICAL) { + startedScroll = true + shouldSnapAfterScroll = type == ViewCompat.TYPE_TOUCH + yTranslator.cancelInProgressTranslation() + true + } else if (engineView?.getInputResultDetail()?.isTouchUnhandled() == true) { + // Force expand the view if event is unhandled, otherwise user could get stuck in a + // state where they cannot show the view + yTranslator.cancelInProgressTranslation() + yTranslator.expandWithAnimation(view) + false + } else { + false + } + } + + @VisibleForTesting + internal fun stopNestedScroll(type: Int, view: View) { + startedScroll = false + if (shouldSnapAfterScroll || type == ViewCompat.TYPE_NON_TOUCH) { + yTranslator.snapWithAnimation(view) + } + } +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/ViewYTranslationStrategy.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/ViewYTranslationStrategy.kt new file mode 100644 index 0000000000..8311f2d21a --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/ViewYTranslationStrategy.kt @@ -0,0 +1,189 @@ +/* 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.ui.widgets.behavior + +import android.animation.ValueAnimator +import android.view.View +import android.view.animation.DecelerateInterpolator +import androidx.annotation.VisibleForTesting +import kotlin.math.max +import kotlin.math.min + +@VisibleForTesting +internal const val SNAP_ANIMATION_DURATION = 150L + +/** + * Helper class with methods for different behaviors for when translating a [View] on the Y axis. + */ +internal abstract class ViewYTranslationStrategy { + @VisibleForTesting + var animator = ValueAnimator().apply { + interpolator = DecelerateInterpolator() + duration = SNAP_ANIMATION_DURATION + } + + /** + * Snap the [View] to be collapsed or expanded, depending on whatever state is closer + * over a short amount of time. + */ + abstract fun snapWithAnimation(view: View) + + /** + * Snap the [View] to be collapsed or expanded, depending on whatever state is closer immediately. + */ + abstract fun snapImmediately(view: View?) + + /** + * Translate the [View] to it's full visible height. + */ + abstract fun expandWithAnimation(view: View) + + /** + * Force expanding the [View] depending on the [distance] value that should be translated + * cancelling any other translation already in progress. + */ + abstract fun forceExpandWithAnimation(view: View, distance: Float) + + /** + * Translate the [View] to it's full 0 visible height. + */ + abstract fun collapseWithAnimation(view: View) + + /** + * Translate [view] immediately to the specified [distance] amount (positive or negative). + */ + abstract fun translate(view: View, distance: Float) + + /** + * Translate [view] to the indicated [targetTranslationY] vaue over a short amount of time. + */ + open fun animateToTranslationY(view: View, targetTranslationY: Float) = with(animator) { + addUpdateListener { view.translationY = it.animatedValue as Float } + setFloatValues(view.translationY, targetTranslationY) + start() + } + + /** + * Cancel any translation animations currently in progress. + */ + fun cancelInProgressTranslation() = animator.cancel() +} + +/** + * Helper class containing methods for translating a [View] on the Y axis + * between 0 and [View.getHeight] + */ +internal class BottomViewBehaviorStrategy : ViewYTranslationStrategy() { + @VisibleForTesting + internal var wasLastExpanding = false + + override fun snapWithAnimation(view: View) { + if (view.translationY >= (view.height / 2f)) { + collapseWithAnimation(view) + } else { + expandWithAnimation(view) + } + } + + override fun snapImmediately(view: View?) { + if (animator.isStarted) { + animator.end() + } else { + view?.apply { + translationY = if (translationY >= height / 2) { + height.toFloat() + } else { + 0f + } + } + } + } + + override fun expandWithAnimation(view: View) { + animateToTranslationY(view, 0f) + } + + override fun forceExpandWithAnimation(view: View, distance: Float) { + val shouldExpandToolbar = distance < 0 + val isToolbarExpanded = view.translationY == 0f + if (shouldExpandToolbar && !isToolbarExpanded && !wasLastExpanding) { + animator.cancel() + expandWithAnimation(view) + } + } + + override fun collapseWithAnimation(view: View) { + animateToTranslationY(view, view.height.toFloat()) + } + + override fun translate(view: View, distance: Float) { + view.translationY = + max(0f, min(view.height.toFloat(), view.translationY + distance)) + } + + override fun animateToTranslationY(view: View, targetTranslationY: Float) { + wasLastExpanding = targetTranslationY <= view.translationY + super.animateToTranslationY(view, targetTranslationY) + } +} + +/** + * Helper class containing methods for translating a [View] on the Y axis + * between -[View.getHeight] and 0. + */ +internal class TopViewBehaviorStrategy : ViewYTranslationStrategy() { + @VisibleForTesting + internal var wasLastExpanding = false + + override fun snapWithAnimation(view: View) { + if (view.translationY >= -(view.height / 2f)) { + expandWithAnimation(view) + } else { + collapseWithAnimation(view) + } + } + + override fun snapImmediately(view: View?) { + if (animator.isStarted) { + animator.end() + } else { + view?.apply { + translationY = if (translationY >= -height / 2) { + 0f + } else { + -height.toFloat() + } + } + } + } + + override fun expandWithAnimation(view: View) { + animateToTranslationY(view, 0f) + } + + override fun forceExpandWithAnimation(view: View, distance: Float) { + val isExpandingInProgress = animator.isStarted && wasLastExpanding + val shouldExpandToolbar = distance < 0 + val isToolbarExpanded = view.translationY == 0f + if (shouldExpandToolbar && !isToolbarExpanded && !isExpandingInProgress) { + animator.cancel() + expandWithAnimation(view) + } + } + + override fun collapseWithAnimation(view: View) { + animateToTranslationY(view, -view.height.toFloat()) + } + + override fun translate(view: View, distance: Float) { + view.translationY = + min(0f, max(-view.height.toFloat(), view.translationY - distance)) + } + + override fun animateToTranslationY(view: View, targetTranslationY: Float) { + wasLastExpanding = targetTranslationY >= view.translationY + super.animateToTranslationY(view, targetTranslationY) + } +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/ViewYTranslator.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/ViewYTranslator.kt new file mode 100644 index 0000000000..042b810b40 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/ViewYTranslator.kt @@ -0,0 +1,81 @@ +/* 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.ui.widgets.behavior + +import android.view.View +import androidx.annotation.VisibleForTesting + +/** + * Helper class with methods for translating on the Y axis a top / bottom [View]. + * + * @param viewPosition whether the view is displayed immediately at the top of the screen or + * immediately at the bottom. This affects how it will be translated: + * - if place at the bottom it will be Y translated between 0 and [View.getHeight] + * - if place at the top it will be Y translated between -[View.getHeight] and 0 + */ +class ViewYTranslator(viewPosition: ViewPosition) { + @VisibleForTesting + internal var strategy = getTranslationStrategy(viewPosition) + + /** + * Snap the [View] to be collapsed or expanded, depending on whatever state is closer + * over a short amount of time. + */ + internal fun snapWithAnimation(view: View) { + strategy.snapWithAnimation(view) + } + + /** + * Snap the [View] to be collapsed or expanded, depending on whatever state is closer immediately. + */ + fun snapImmediately(view: View?) { + strategy.snapImmediately(view) + } + + /** + * Translate the [View] to it's full visible height over a short amount of time. + */ + internal fun expandWithAnimation(view: View) { + strategy.expandWithAnimation(view) + } + + /** + * Translate the [View] to be hidden from view over a short amount of time. + */ + internal fun collapseWithAnimation(view: View) { + strategy.collapseWithAnimation(view) + } + + /** + * Force expanding the [View] depending on the [distance] value that should be translated + * cancelling any other translation already in progress. + */ + fun forceExpandIfNotAlready(view: View, distance: Float) { + strategy.forceExpandWithAnimation(view, distance) + } + + /** + * Translate [view] immediately to the specified [distance] amount (positive or negative). + */ + fun translate(view: View, distance: Float) { + strategy.translate(view, distance) + } + + /** + * Cancel any translation animations currently in progress. + */ + fun cancelInProgressTranslation() { + strategy.cancelInProgressTranslation() + } + + @VisibleForTesting + internal fun getTranslationStrategy(viewPosition: ViewPosition): ViewYTranslationStrategy { + return if (viewPosition == ViewPosition.TOP) { + TopViewBehaviorStrategy() + } else { + BottomViewBehaviorStrategy() + } + } +} diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/drawable/mozac_widget_favicon_background.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/drawable/mozac_widget_favicon_background.xml new file mode 100644 index 0000000000..93e6f01141 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/drawable/mozac_widget_favicon_background.xml @@ -0,0 +1,17 @@ +<?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/. --> +<shape + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:shape="rectangle"> + <corners android:radius="4dp" /> + <solid + android:color="?mozac_widget_favicon_background_color" + tools:color="@color/photonWhite" /> + <stroke + android:width="1dp" + android:color="?mozac_widget_favicon_border_color" + tools:color="@color/photonLightGrey30" /> +</shape> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/drawable/rounded_button_background.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/drawable/rounded_button_background.xml new file mode 100644 index 0000000000..260a02530d --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/drawable/rounded_button_background.xml @@ -0,0 +1,18 @@ +<?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/. --> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="?android:attr/colorControlHighlight"> + <item android:id="@android:id/mask"> + <shape> + <solid android:color="#000000" /> + <corners android:radius="4dp" /> + </shape> + </item> + <item> + <shape android:shape="rectangle"> + <corners android:radius="4dp" /> + </shape> + </item> +</ripple> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/layout/mozac_widget_site_item.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/layout/mozac_widget_site_item.xml new file mode 100644 index 0000000000..3ddfd7a2c3 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/layout/mozac_widget_site_item.xml @@ -0,0 +1,77 @@ +<?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/. --> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/mozac_widget_site_item_height" + android:background="?android:attr/selectableItemBackground"> + + <FrameLayout + android:id="@+id/favicon_wrapper" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + app:layout_constraintHorizontal_chainStyle="spread_inside" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@id/label"> + <ImageView + android:id="@+id/favicon" + style="@style/Mozac.Widgets.Favicon" + android:importantForAccessibility="no" + tools:src="@android:drawable/ic_secure" /> + </FrameLayout> + + <TextView + android:id="@+id/label" + style="@style/Mozac.Widgets.SiteItem.Label" + android:layout_width="0dp" + tools:textColor="#20123A" + tools:text="Example site" + app:layout_goneMarginEnd="16dp" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toTopOf="@id/caption" + app:layout_constraintStart_toEndOf="@id/favicon_wrapper" + app:layout_constraintEnd_toStartOf="@id/secondary_button" + app:layout_constraintVertical_chainStyle="packed" /> + + <TextView + android:id="@+id/caption" + style="@style/Mozac.Widgets.SiteItem.Caption" + android:layout_width="0dp" + android:layout_marginTop="2dp" + tools:text="https://example.com/" + tools:textColor="@color/photonLightGrey90" + app:layout_constraintEnd_toEndOf="@id/label" + app:layout_constraintStart_toStartOf="@id/label" + app:layout_constraintTop_toBottomOf="@id/label" + app:layout_constraintBottom_toBottomOf="parent" /> + + <ImageButton + android:id="@+id/secondary_button" + android:layout_width="@dimen/mozac_widget_site_item_secondary_button_size" + android:layout_height="@dimen/mozac_widget_site_item_secondary_button_size" + android:padding="@dimen/mozac_widget_site_item_secondary_button_padding" + android:layout_marginStart="12dp" + android:layout_marginEnd="12dp" + android:background="?android:attr/selectableItemBackgroundBorderless" + android:visibility="gone" + tools:visibility="visible" + tools:src="@drawable/mozac_ic_ellipsis_vertical_24" + tools:ignore="ContentDescription" + tools:tint="#20123A" + app:tint="?attr/mozac_primary_text_color" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toEndOf="@id/label" + app:layout_constraintEnd_toEndOf="parent" /> + +</merge> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-am/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-am/strings.xml new file mode 100644 index 0000000000..cdde258cef --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-am/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">ምስል ወደ ቅንጥብ ሰሌዳ ተቀድቷል</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ar/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ar/strings.xml new file mode 100644 index 0000000000..eb2045ed67 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ar/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">نُسخت الصورة إلى الحافظة</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ast/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ast/strings.xml new file mode 100644 index 0000000000..013fbec0b8 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ast/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">La imaxe copióse al cartafueyu</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-azb/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-azb/strings.xml new file mode 100644 index 0000000000..706d647459 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-azb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">عکس کلیپبوردا کوپی اولدو</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-be/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-be/strings.xml new file mode 100644 index 0000000000..7096e05e05 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-be/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Відарыс скапіяваны ў буфер абмену</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-bg/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-bg/strings.xml new file mode 100644 index 0000000000..9c2defef43 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-bg/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Изображението е копирано</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-br/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-br/strings.xml new file mode 100644 index 0000000000..3ae6d8340a --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-br/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Skeudenn eilet er golver</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-bs/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-bs/strings.xml new file mode 100644 index 0000000000..b0e64d0437 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-bs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Slika je kopirana u privremenu memoriju</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ca/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ca/strings.xml new file mode 100644 index 0000000000..75a4596b48 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ca/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">S’ha copiat la imatge al porta-retalls</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-cak/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-cak/strings.xml new file mode 100644 index 0000000000..dee19cb2a1 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-cak/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Xwachib\'ëx ri wachib\'äl pa molwuj</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-co/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-co/strings.xml new file mode 100644 index 0000000000..dc5ae642c1 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-co/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Fiura cupiata in u preme’papei</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-cs/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-cs/strings.xml new file mode 100644 index 0000000000..039f1848dc --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-cs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Obrázek zkopírován do schránky</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-cy/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-cy/strings.xml new file mode 100644 index 0000000000..274e4c8a92 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-cy/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Copïwyd delwedd i’r clipfwrdd</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-da/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-da/strings.xml new file mode 100644 index 0000000000..1e8162dcf1 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-da/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Billede kopieret til udklipsholder</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-de/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-de/strings.xml new file mode 100644 index 0000000000..a6f23ccb4a --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-de/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Grafik in Zwischenablage kopiert</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-dsb/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-dsb/strings.xml new file mode 100644 index 0000000000..5119090d13 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-dsb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Wobraz jo se kopěrował do mjazywótkłada</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-el/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-el/strings.xml new file mode 100644 index 0000000000..57da3ec96d --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-el/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Η εικόνα αντιγράφτηκε στο πρόχειρο</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-en-rCA/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-en-rCA/strings.xml new file mode 100644 index 0000000000..638ee8543e --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-en-rCA/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Image copied to clipboard</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-en-rGB/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-en-rGB/strings.xml new file mode 100644 index 0000000000..638ee8543e --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-en-rGB/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Image copied to clipboard</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-eo/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-eo/strings.xml new file mode 100644 index 0000000000..9cc052f510 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-eo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Bildo kopiita al la tondujo</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rAR/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rAR/strings.xml new file mode 100644 index 0000000000..06f644e903 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rAR/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagen copiada al portapapeles</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rCL/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rCL/strings.xml new file mode 100644 index 0000000000..06f644e903 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rCL/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagen copiada al portapapeles</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rES/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rES/strings.xml new file mode 100644 index 0000000000..06f644e903 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rES/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagen copiada al portapapeles</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rMX/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rMX/strings.xml new file mode 100644 index 0000000000..06f644e903 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es-rMX/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagen copiada al portapapeles</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-es/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es/strings.xml new file mode 100644 index 0000000000..06f644e903 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-es/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagen copiada al portapapeles</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-et/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-et/strings.xml new file mode 100644 index 0000000000..b77f8fe2fc --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-et/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Pilt kopeeriti vahemällu</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-eu/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-eu/strings.xml new file mode 100644 index 0000000000..18039c3b03 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-eu/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Irudia arbelean kopiatu da</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-fa/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fa/strings.xml new file mode 100644 index 0000000000..4d9c243f3c --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fa/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">تصویر به تختهگیره رونوشت شد</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-fi/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fi/strings.xml new file mode 100644 index 0000000000..426de77fe1 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fi/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Kuva kopioitu leikepöydälle</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-fr/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000000..c41cec7a23 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Image copiée dans le presse-papiers</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-fur/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fur/strings.xml new file mode 100644 index 0000000000..5fb71c5b51 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fur/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagjin copiade intes notis</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-fy-rNL/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fy-rNL/strings.xml new file mode 100644 index 0000000000..db7c6fa54d --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-fy-rNL/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Ofbylding nei klamboerd kopiearre</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-gd/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-gd/strings.xml new file mode 100644 index 0000000000..a2c04bd312 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-gd/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Chaidh lethbhreac dhen dealbh a chur air an stòr-bhòrd</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-gl/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-gl/strings.xml new file mode 100644 index 0000000000..3e7252778d --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-gl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Copiouse a imaxe ao portapapeis</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-gn/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-gn/strings.xml new file mode 100644 index 0000000000..af5e3ba7cb --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-gn/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Embohasa ta’ãnga kuatiajokohápe</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-hr/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-hr/strings.xml new file mode 100644 index 0000000000..dbfcb2d809 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-hr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Slika je kopirana u međuspremnik</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-hsb/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-hsb/strings.xml new file mode 100644 index 0000000000..473527a6cd --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-hsb/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Wobraz je so do mjezyskłada kopěrował</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-hu/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-hu/strings.xml new file mode 100644 index 0000000000..0ca081817d --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-hu/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Kép vágólapra másolva</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-hy-rAM/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000000..4567efaed4 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-hy-rAM/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Պատկերը պատճենվել է սեղմատախտակին</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ia/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ia/strings.xml new file mode 100644 index 0000000000..6b8f02500b --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ia/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagine copiate al area de transferentia</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-in/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-in/strings.xml new file mode 100644 index 0000000000..4b6807e51e --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-in/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Gambar disalin ke papan klip</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-is/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-is/strings.xml new file mode 100644 index 0000000000..c2e2bb5714 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-is/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Mynd afrituð á klippispjald</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-it/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-it/strings.xml new file mode 100644 index 0000000000..79c58ec52e --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-it/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Immagine copiata negli appunti</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-iw/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-iw/strings.xml new file mode 100644 index 0000000000..85bf7a942a --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-iw/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">התמונה הועתקה ללוח</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ja/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ja/strings.xml new file mode 100644 index 0000000000..805eacfc87 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ja/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">画像をクリップボードにコピーしました</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ka/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ka/strings.xml new file mode 100644 index 0000000000..8de04f6263 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ka/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">სურათის ასლი აღებულია</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-kaa/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-kaa/strings.xml new file mode 100644 index 0000000000..cb2c90ba5b --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-kaa/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Súwret almasıw buferine kóshirip alındı</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-kab/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-kab/strings.xml new file mode 100644 index 0000000000..093f1d2616 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-kab/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Tugna tettwanɣel ɣef wafus</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-kk/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-kk/strings.xml new file mode 100644 index 0000000000..80b99ef483 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-kk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Сурет алмасу буферіне көшірілді</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-kmr/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-kmr/strings.xml new file mode 100644 index 0000000000..b299c8f6b7 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-kmr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Wêne li panoyê hate kopîkirin</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ko/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ko/strings.xml new file mode 100644 index 0000000000..5d6ebf83e7 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ko/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">클립보드에 이미지 복사됨</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-lo/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-lo/strings.xml new file mode 100644 index 0000000000..ab066dba6f --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-lo/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">ສຳເນົາຮູບໃສ່ຄລິບບອດແລ້ວ</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-nb-rNO/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-nb-rNO/strings.xml new file mode 100644 index 0000000000..bef36125f1 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-nb-rNO/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Bilde kopiert til utklippstavlen</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-nl/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-nl/strings.xml new file mode 100644 index 0000000000..06070807bb --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-nl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Afbeelding naar klembord gekopieerd</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-nn-rNO/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-nn-rNO/strings.xml new file mode 100644 index 0000000000..16c41f8d38 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-nn-rNO/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Bilde kopiert til utklippstavla</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-oc/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-oc/strings.xml new file mode 100644 index 0000000000..131c779121 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-oc/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imatge copiat al quichapapièrs</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-pa-rIN/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pa-rIN/strings.xml new file mode 100644 index 0000000000..03300db934 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pa-rIN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">ਚਿੱਤਰ ਨੂੰ ਕਲਿੱਪਬੋਰਡ ਲਈ ਕਾਪੀ ਕੀਤਾ</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-pa-rPK/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pa-rPK/strings.xml new file mode 100644 index 0000000000..cb4e8c879c --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pa-rPK/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">کاپی کیتی گئی</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-pl/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pl/strings.xml new file mode 100644 index 0000000000..8a79fb5c5e --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Skopiowano obraz do schowka</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-pt-rBR/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000000..223e60bc6a --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagem copiada para área de transferência</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-pt-rPT/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pt-rPT/strings.xml new file mode 100644 index 0000000000..48dc017c65 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-pt-rPT/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imagem copiada para a área de transferência</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-rm/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-rm/strings.xml new file mode 100644 index 0000000000..8b428f02b1 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-rm/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Copià il maletg en l\'archiv provisoric</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ro/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ro/strings.xml new file mode 100644 index 0000000000..be7fc12e65 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ro/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Imaginea a fost copiată în clipboard</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ru/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000000..35ac3be80a --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ru/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Изображение скопировано в буфер обмена</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-sat/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sat/strings.xml new file mode 100644 index 0000000000..d945ea02c5 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sat/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">ᱨᱮᱴᱚᱯᱵᱚᱰ ᱨᱮ ᱪᱤᱛᱟᱹᱨ ᱱᱚᱠᱚᱞ ᱮᱱᱟ</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-sc/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sc/strings.xml new file mode 100644 index 0000000000..6d122f7e8b --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sc/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Immàgine copiada in punta de billete</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-si/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-si/strings.xml new file mode 100644 index 0000000000..95d46d5ddd --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-si/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">රූපය පසුරුපුවරුවට පිටපත් විය</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-sk/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sk/strings.xml new file mode 100644 index 0000000000..02dc6628cb --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Obrázok bol skopírovaný do schránky</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-skr/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-skr/strings.xml new file mode 100644 index 0000000000..da370ffcb7 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-skr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">تصویر کلپ بورڈ تے نقل تھی ڳئی</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-sl/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sl/strings.xml new file mode 100644 index 0000000000..b3a3418289 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sl/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Slika kopirana v odložišče</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-sq/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sq/strings.xml new file mode 100644 index 0000000000..b76b67a352 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sq/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Figura u kopjua në të papastër</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-sr/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sr/strings.xml new file mode 100644 index 0000000000..f0fbe5c485 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Слика је копирана у привремену меморију</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-su/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-su/strings.xml new file mode 100644 index 0000000000..91a37e77b6 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-su/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Gambar ditiron kana papan klip</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-sv-rSE/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sv-rSE/strings.xml new file mode 100644 index 0000000000..51210de628 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-sv-rSE/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Bilden har kopierats till urklipp</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-tg/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-tg/strings.xml new file mode 100644 index 0000000000..b304da28c1 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-tg/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Тасвир ба ҳофизаи муваққатӣ нусха бардошта шуд</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-th/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-th/strings.xml new file mode 100644 index 0000000000..52a77b64dc --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-th/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">คัดลอกภาพไปยังคลิปบอร์ดแล้ว</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-tr/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-tr/strings.xml new file mode 100644 index 0000000000..b0ef721f12 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-tr/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Resim panoya kopyalandı</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-trs/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-trs/strings.xml new file mode 100644 index 0000000000..d905bed3df --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-trs/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Ñadū’hua ngà nanun riña portapapel</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-tt/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-tt/strings.xml new file mode 100644 index 0000000000..ad4402d83c --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-tt/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Рәсем алмашу буферына копияләнде</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-ug/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ug/strings.xml new file mode 100644 index 0000000000..2719590251 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-ug/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">سۈرەت چاپلاش تاختىسىغا كۆچۈرۈلدى</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-uk/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-uk/strings.xml new file mode 100644 index 0000000000..49cffe6ba2 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-uk/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Зображення скопійовано в буфер обміну</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-vi/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-vi/strings.xml new file mode 100644 index 0000000000..8127c7855b --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-vi/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Đã sao chép ảnh vào khay nhớ tạm</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-zh-rCN/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 0000000000..98d08c5c6a --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">图像已复制到剪贴板</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values-zh-rTW/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values-zh-rTW/strings.xml new file mode 100644 index 0000000000..39326e4ac0 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values-zh-rTW/strings.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">已將圖片複製至剪貼簿</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values/attrs.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values/attrs.xml new file mode 100644 index 0000000000..60a3b3a35f --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values/attrs.xml @@ -0,0 +1,19 @@ +<?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> + <attr name="mozac_font_semibold" format="reference" /> + <attr name="mozac_accent" format="reference" /> + <attr name="mozac_contrast_text" format="reference" /> + + <!-- Background color for favicon widget box --> + <attr name="mozac_widget_favicon_background_color" format="reference" /> + <!-- Border color for favicon widget box --> + <attr name="mozac_widget_favicon_border_color" format="reference" /> + + <!-- Label color and icon button tint for site item widget --> + <attr name="mozac_primary_text_color" format="reference" /> + <!-- Caption color for site item widget --> + <attr name="mozac_caption_text_color" format="reference" /> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values/colors.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values/colors.xml new file mode 100644 index 0000000000..105264e605 --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values/colors.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> + <!-- Button Colors --> + <color name="mozac_grey_button_color">#E0E0E6</color> + <color name="mozac_destructive_button_text_color">#C50042</color> + <color name="mozac_grey_button_text_color">#312A65</color> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values/dimens.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values/dimens.xml new file mode 100644 index 0000000000..9f6d4587fd --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values/dimens.xml @@ -0,0 +1,14 @@ +<?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> + <dimen name="mozac_widget_favicon_size">40dp</dimen> + <dimen name="mozac_widget_favicon_padding">8dp</dimen> + + <dimen name="mozac_widget_site_item_height">56dp</dimen> + <dimen name="mozac_widget_site_item_label_text_size">16sp</dimen> + <dimen name="mozac_widget_site_item_caption_text_size">12sp</dimen> + <dimen name="mozac_widget_site_item_secondary_button_size">32dp</dimen> + <dimen name="mozac_widget_site_item_secondary_button_padding">4dp</dimen> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values/strings.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values/strings.xml new file mode 100644 index 0000000000..6a82d7eaef --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/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> + <!-- Text for confirmation "snackbar" shown after copying an image to the clipboard. --> + <string name="snackbar_copy_image_to_clipboard_confirmation">Image copied to clipboard</string> +</resources> diff --git a/mobile/android/android-components/components/ui/widgets/src/main/res/values/styles.xml b/mobile/android/android-components/components/ui/widgets/src/main/res/values/styles.xml new file mode 100644 index 0000000000..515b98e12e --- /dev/null +++ b/mobile/android/android-components/components/ui/widgets/src/main/res/values/styles.xml @@ -0,0 +1,63 @@ +<?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 xmlns:android="http://schemas.android.com/apk/res/android"> + <style name="Mozac.Widgets.TestTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> + <item name="mozac_widget_favicon_background_color">@color/photonWhite</item> + <item name="mozac_widget_favicon_border_color">@color/photonLightGrey30</item> + <item name="mozac_primary_text_color">@color/photonInk90</item> + <item name="mozac_caption_text_color">@color/photonInk50</item> + </style> + + <!-- Button styling --> + <style name="Mozac.Widgets.NeutralButton" parent="Widget.MaterialComponents.Button.TextButton"> + <item name="iconTint">@color/mozac_grey_button_text_color</item> + <item name="iconPadding">8dp</item> + <item name="iconGravity">textStart</item> + <item name="android:textAlignment">center</item> + <item name="android:background">@drawable/rounded_button_background</item> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">48dp</item> + <item name="android:textStyle">bold</item> + <item name="android:textAllCaps">false</item> + <item name="backgroundTint">@color/mozac_grey_button_color</item> + <item name="android:textColor">@color/mozac_grey_button_text_color</item> + <item name="android:letterSpacing">0</item> + <item name="fontFamily">?mozac_font_semibold</item> + </style> + + <style name="Mozac.Widgets.DestructiveButton" parent="Mozac.Widgets.NeutralButton"> + <item name="iconTint">@color/mozac_destructive_button_text_color</item> + <item name="android:textColor">@color/mozac_destructive_button_text_color</item> + </style> + + <style name="Mozac.Widgets.PositiveButton" parent="Mozac.Widgets.NeutralButton"> + <item name="backgroundTint">?mozac_accent</item> + <item name="iconTint">?mozac_contrast_text</item> + <item name="android:textColor">?mozac_contrast_text</item> + </style> + + <!-- Favicon styling --> + <style name="Mozac.Widgets.Favicon" parent=""> + <item name="android:layout_width">@dimen/mozac_widget_favicon_size</item> + <item name="android:layout_height">@dimen/mozac_widget_favicon_size</item> + <item name="android:scaleType">fitCenter</item> + <item name="android:padding">@dimen/mozac_widget_favicon_padding</item> + <item name="android:background">@drawable/mozac_widget_favicon_background</item> + </style> + + <style name="Mozac.Widgets.SiteItem.Label" parent=""> + <item name="android:layout_height">wrap_content</item> + <item name="android:ellipsize">end</item> + <item name="android:singleLine">true</item> + <item name="android:textAlignment">viewStart</item> + <item name="android:textSize">@dimen/mozac_widget_site_item_label_text_size</item> + <item name="android:textColor">?attr/mozac_primary_text_color</item> + </style> + <style name="Mozac.Widgets.SiteItem.Caption" parent="Mozac.Widgets.SiteItem.Label"> + <item name="android:textSize">@dimen/mozac_widget_site_item_caption_text_size</item> + <item name="android:textColor">?attr/mozac_caption_text_color</item> + </style> +</resources> |