Copione merged onto master
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
commit
80a56ec2d4
20
README.md
20
README.md
|
@ -123,10 +123,7 @@ If you want to run **performance tests/benchmarks** in automation or locally:
|
||||||
|
|
||||||
For additional context on these recommendations, see [the perf build variant analysis](https://docs.google.com/document/d/1aW-m0HYncTDDiRz_2x6EjcYkjBpL9SHhhYix13Vil30/edit#).
|
For additional context on these recommendations, see [the perf build variant analysis](https://docs.google.com/document/d/1aW-m0HYncTDDiRz_2x6EjcYkjBpL9SHhhYix13Vil30/edit#).
|
||||||
|
|
||||||
Before you can install any release variants including `forPerformanceTest`, **you will need to sign them.** To do this automatically in local development, you can add the following to `<proj-root>/local.properties`:
|
Before you can install any release variants including `forPerformanceTest`, **you will need to sign them:** see [Automatically signing release builds](#automatically-sign-release-builds) for details.
|
||||||
```sh
|
|
||||||
autosignReleaseWithDebugKey
|
|
||||||
```
|
|
||||||
|
|
||||||
## Pre-push hooks
|
## Pre-push hooks
|
||||||
To reduce review turn-around time, we'd like all pushes to run tests locally. We'd
|
To reduce review turn-around time, we'd like all pushes to run tests locally. We'd
|
||||||
|
@ -164,8 +161,19 @@ Steps to downgrade Java Version on Mac with Brew:
|
||||||
7. Verify java-version by running ```java -version```
|
7. Verify java-version by running ```java -version```
|
||||||
|
|
||||||
## local.properties helpers
|
## local.properties helpers
|
||||||
There are multiple helper flags available via `local.properties` that will help speed up local development workflow
|
You can speed up local development by setting a few helper flags available in `local.properties`. Some flags will make it easy to
|
||||||
when working across multiple layers of the dependency stack - specifically, with android-components, geckoview or application-services.
|
work across multiple layers of the dependency stack - specifically, with android-components, geckoview or application-services.
|
||||||
|
|
||||||
|
### Automatically sign release builds
|
||||||
|
To sign your release builds with your debug key automatically, add the following to `<proj-root>/local.properties`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
autosignReleaseWithDebugKey
|
||||||
|
```
|
||||||
|
|
||||||
|
With this line, release build variants will automatically be signed with your debug key (like debug builds), allowing them to be built and installed directly through Android Studio or the command line.
|
||||||
|
|
||||||
|
This is helpful when you're building release variants frequently, for example to test feature flags and or do performance analyses.
|
||||||
|
|
||||||
### Auto-publication workflow for android-components and application-services
|
### Auto-publication workflow for android-components and application-services
|
||||||
If you're making changes to these projects and want to test them in Fenix, auto-publication workflow is the fastest, most reliable
|
If you're making changes to these projects and want to test them in Fenix, auto-publication workflow is the fastest, most reliable
|
||||||
|
|
|
@ -45,6 +45,8 @@ import mozilla.components.feature.search.SearchAdapter
|
||||||
import mozilla.components.service.fxa.sync.SyncReason
|
import mozilla.components.service.fxa.sync.SyncReason
|
||||||
import mozilla.components.support.base.feature.UserInteractionHandler
|
import mozilla.components.support.base.feature.UserInteractionHandler
|
||||||
import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
|
import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
|
||||||
|
import mozilla.components.support.ktx.android.content.call
|
||||||
|
import mozilla.components.support.ktx.android.content.email
|
||||||
import mozilla.components.support.ktx.android.content.share
|
import mozilla.components.support.ktx.android.content.share
|
||||||
import mozilla.components.support.ktx.kotlin.isUrl
|
import mozilla.components.support.ktx.kotlin.isUrl
|
||||||
import mozilla.components.support.ktx.kotlin.toNormalizedUrl
|
import mozilla.components.support.ktx.kotlin.toNormalizedUrl
|
||||||
|
@ -294,10 +296,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
||||||
EngineView::class.java.name -> components.core.engine.createView(context, attrs).apply {
|
EngineView::class.java.name -> components.core.engine.createView(context, attrs).apply {
|
||||||
selectionActionDelegate = DefaultSelectionActionDelegate(
|
selectionActionDelegate = DefaultSelectionActionDelegate(
|
||||||
getSearchAdapter(components.core.store),
|
getSearchAdapter(components.core.store),
|
||||||
resources = context.resources
|
resources = context.resources,
|
||||||
) {
|
shareTextClicked = { share(it) },
|
||||||
share(it)
|
emailTextClicked = { email(it) },
|
||||||
}
|
callTextClicked = { call(it) },
|
||||||
|
actionSorter = ::actionSorter
|
||||||
|
)
|
||||||
}.asView()
|
}.asView()
|
||||||
TabsTray::class.java.name -> {
|
TabsTray::class.java.name -> {
|
||||||
val layout = LinearLayoutManager(context).apply {
|
val layout = LinearLayoutManager(context).apply {
|
||||||
|
@ -313,6 +317,22 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
||||||
else -> super.onCreateView(parent, name, context, attrs)
|
else -> super.onCreateView(parent, name, context, attrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
// Defining the positions as constants doesn't seem super useful here.
|
||||||
|
private fun actionSorter(actions: Array<String>): Array<String> {
|
||||||
|
val order = hashMapOf<String, Int>()
|
||||||
|
|
||||||
|
order["org.mozilla.geckoview.COPY"] = 0
|
||||||
|
order["CUSTOM_CONTEXT_MENU_SEARCH"] = 1
|
||||||
|
order["org.mozilla.geckoview.SELECT_ALL"] = 2
|
||||||
|
order["CUSTOM_CONTEXT_MENU_SHARE"] = 3
|
||||||
|
|
||||||
|
return actions.sortedBy { actionName ->
|
||||||
|
// Sort the actions in our preferred order, putting "other" actions unsorted at the end
|
||||||
|
order[actionName] ?: actions.size
|
||||||
|
}.toTypedArray()
|
||||||
|
}
|
||||||
|
|
||||||
final override fun onBackPressed() {
|
final override fun onBackPressed() {
|
||||||
supportFragmentManager.primaryNavigationFragment?.childFragmentManager?.fragments?.forEach {
|
supportFragmentManager.primaryNavigationFragment?.childFragmentManager?.fragments?.forEach {
|
||||||
if (it is UserInteractionHandler && it.onBackPressed()) {
|
if (it is UserInteractionHandler && it.onBackPressed()) {
|
||||||
|
@ -502,6 +522,7 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
||||||
engine: SearchEngine?,
|
engine: SearchEngine?,
|
||||||
forceSearch: Boolean
|
forceSearch: Boolean
|
||||||
) {
|
) {
|
||||||
|
val startTime = components.core.engine.profiler?.getProfilerTime()
|
||||||
val mode = browsingModeManager.mode
|
val mode = browsingModeManager.mode
|
||||||
|
|
||||||
val loadUrlUseCase = if (newTab) {
|
val loadUrlUseCase = if (newTab) {
|
||||||
|
@ -529,6 +550,12 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
|
||||||
} else {
|
} else {
|
||||||
searchUseCase.invoke(searchTermOrURL)
|
searchUseCase.invoke(searchTermOrURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (components.core.engine.profiler?.isProfilerActive() == true) {
|
||||||
|
// Wrapping the `addMarker` method with `isProfilerActive` even though it's no-op when
|
||||||
|
// profiler is not active. That way, `text` argument will not create a string builder all the time.
|
||||||
|
components.core.engine.profiler?.addMarker("HomeActivity.load", startTime, "newTab: $newTab")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
|
|
|
@ -275,9 +275,4 @@ class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
|
||||||
) + ContextMenuCandidate.createOpenInExternalAppCandidate(requireContext(),
|
) + ContextMenuCandidate.createOpenInExternalAppCandidate(requireContext(),
|
||||||
contextMenuCandidateAppLinksUseCases)
|
contextMenuCandidateAppLinksUseCases)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val SHARED_TRANSITION_MS = 200L
|
|
||||||
private const val TAB_ITEM_TRANSITION_NAME = "tab_item"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ class SyncedTabsLayout @JvmOverloads constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(error: SyncedTabsView.ErrorType) {
|
override fun onError(error: SyncedTabsView.ErrorType) {
|
||||||
|
// We may still be displaying a "loading" spinner, hide it.
|
||||||
|
stopLoading()
|
||||||
|
|
||||||
val stringResId = when (error) {
|
val stringResId = when (error) {
|
||||||
SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE -> R.string.synced_tabs_connect_another_device
|
SyncedTabsView.ErrorType.MULTIPLE_DEVICES_UNAVAILABLE -> R.string.synced_tabs_connect_another_device
|
||||||
SyncedTabsView.ErrorType.SYNC_ENGINE_UNAVAILABLE -> R.string.synced_tabs_enable_tab_syncing
|
SyncedTabsView.ErrorType.SYNC_ENGINE_UNAVAILABLE -> R.string.synced_tabs_enable_tab_syncing
|
||||||
|
|
|
@ -38,9 +38,11 @@ class DefaultTabTrayController(
|
||||||
private val registerCollectionStorageObserver: () -> Unit
|
private val registerCollectionStorageObserver: () -> Unit
|
||||||
) : TabTrayController {
|
) : TabTrayController {
|
||||||
override fun onNewTabTapped(private: Boolean) {
|
override fun onNewTabTapped(private: Boolean) {
|
||||||
|
val startTime = activity.components.core.engine.profiler?.getProfilerTime()
|
||||||
activity.browsingModeManager.mode = BrowsingMode.fromBoolean(private)
|
activity.browsingModeManager.mode = BrowsingMode.fromBoolean(private)
|
||||||
navController.navigate(TabTrayDialogFragmentDirections.actionGlobalHome(focusOnAddressBar = true))
|
navController.navigate(TabTrayDialogFragmentDirections.actionGlobalHome(focusOnAddressBar = true))
|
||||||
dismissTabTray()
|
dismissTabTray()
|
||||||
|
activity.components.core.engine.profiler?.addMarker("DefaultTabTrayController.onNewTabTapped", startTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTabTrayDismissed() {
|
override fun onTabTrayDismissed() {
|
||||||
|
|
|
@ -4,14 +4,86 @@
|
||||||
|
|
||||||
package org.mozilla.fenix.tabtray
|
package org.mozilla.fenix.tabtray
|
||||||
|
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import androidx.appcompat.content.res.AppCompatResources
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import mozilla.components.browser.tabstray.TabTouchCallback
|
import mozilla.components.browser.tabstray.TabTouchCallback
|
||||||
import mozilla.components.concept.tabstray.TabsTray
|
import mozilla.components.concept.tabstray.TabsTray
|
||||||
import mozilla.components.support.base.observer.Observable
|
import mozilla.components.support.base.observer.Observable
|
||||||
|
import mozilla.components.support.ktx.android.content.getColorFromAttr
|
||||||
|
import mozilla.components.support.ktx.android.content.getDrawableWithTint
|
||||||
|
import mozilla.components.support.ktx.android.util.dpToPx
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.home.sessioncontrol.SwipeToDeleteCallback
|
||||||
|
|
||||||
class TabsTouchHelper(observable: Observable<TabsTray.Observer>) :
|
class TabsTouchHelper(observable: Observable<TabsTray.Observer>) :
|
||||||
ItemTouchHelper(object : TabTouchCallback(observable) {
|
ItemTouchHelper(object : TabTouchCallback(observable) {
|
||||||
override fun alphaForItemSwipe(dX: Float, distanceToAlphaMin: Int): Float {
|
override fun onChildDraw(
|
||||||
return 1f - 2f * Math.abs(dX) / distanceToAlphaMin
|
c: Canvas,
|
||||||
|
recyclerView: RecyclerView,
|
||||||
|
viewHolder: RecyclerView.ViewHolder,
|
||||||
|
dX: Float,
|
||||||
|
dY: Float,
|
||||||
|
actionState: Int,
|
||||||
|
isCurrentlyActive: Boolean
|
||||||
|
) {
|
||||||
|
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive)
|
||||||
|
val icon = recyclerView.context.getDrawableWithTint(
|
||||||
|
R.drawable.ic_delete,
|
||||||
|
recyclerView.context.getColorFromAttr(R.attr.destructive)
|
||||||
|
)!!
|
||||||
|
val background = AppCompatResources.getDrawable(
|
||||||
|
recyclerView.context,
|
||||||
|
R.drawable.tab_tray_background
|
||||||
|
)!!
|
||||||
|
val itemView = viewHolder.itemView
|
||||||
|
val iconLeft: Int
|
||||||
|
val iconRight: Int
|
||||||
|
val margin =
|
||||||
|
SwipeToDeleteCallback.MARGIN.dpToPx(recyclerView.context.resources.displayMetrics)
|
||||||
|
val iconWidth = icon.intrinsicWidth
|
||||||
|
val iconHeight = icon.intrinsicHeight
|
||||||
|
val cellHeight = itemView.bottom - itemView.top
|
||||||
|
val iconTop = itemView.top + (cellHeight - iconHeight) / 2
|
||||||
|
val iconBottom = iconTop + iconHeight
|
||||||
|
|
||||||
|
when {
|
||||||
|
dX > 0 -> { // Swiping to the right
|
||||||
|
iconLeft = itemView.left + margin
|
||||||
|
iconRight = itemView.left + margin + iconWidth
|
||||||
|
background.setBounds(
|
||||||
|
itemView.left, itemView.top,
|
||||||
|
(itemView.left + dX).toInt() + SwipeToDeleteCallback.BACKGROUND_CORNER_OFFSET,
|
||||||
|
itemView.bottom
|
||||||
|
)
|
||||||
|
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
|
||||||
|
draw(background, icon, c)
|
||||||
|
}
|
||||||
|
dX < 0 -> { // Swiping to the left
|
||||||
|
iconLeft = itemView.right - margin - iconWidth
|
||||||
|
iconRight = itemView.right - margin
|
||||||
|
background.setBounds(
|
||||||
|
(itemView.right + dX).toInt() - SwipeToDeleteCallback.BACKGROUND_CORNER_OFFSET,
|
||||||
|
itemView.top, itemView.right, itemView.bottom
|
||||||
|
)
|
||||||
|
icon.setBounds(iconLeft, iconTop, iconRight, iconBottom)
|
||||||
|
draw(background, icon, c)
|
||||||
|
}
|
||||||
|
else -> { // View not swiped
|
||||||
|
background.setBounds(0, 0, 0, 0)
|
||||||
|
icon.setBounds(0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun draw(
|
||||||
|
background: Drawable,
|
||||||
|
icon: Drawable,
|
||||||
|
c: Canvas
|
||||||
|
) {
|
||||||
|
background.draw(c)
|
||||||
|
icon.draw(c)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -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/. -->
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="@color/swipe_delete_background_normal_theme" />
|
||||||
|
</shape>
|
|
@ -54,14 +54,15 @@
|
||||||
<attr name="syncedTabsSeparator" format="reference"/>
|
<attr name="syncedTabsSeparator" format="reference"/>
|
||||||
|
|
||||||
<!-- Tab tray -->
|
<!-- Tab tray -->
|
||||||
<attr name="tabTrayItemBackground" format="reference" />
|
|
||||||
<attr name="tabTrayItemSelectedBackground" format="reference" />
|
|
||||||
<attr name="tabTrayToolbarBackground" format="reference" />
|
|
||||||
<attr name="tabTrayItemMediaBackground" format="reference" />
|
<attr name="tabTrayItemMediaBackground" format="reference" />
|
||||||
<attr name="tabTrayHeadingIcon" format="reference" />
|
<attr name="tabTrayHeadingIcon" format="reference" />
|
||||||
<attr name="tabTrayHeadingIconInactive" format="reference" />
|
<attr name="tabTrayHeadingIconInactive" format="reference" />
|
||||||
<attr name="tabTrayThumbnailItemBackground" format="reference" />
|
<attr name="tabTrayThumbnailItemBackground" format="reference" />
|
||||||
<attr name="tabTrayThumbnailIcon" format="reference" />
|
<attr name="tabTrayThumbnailIcon" format="reference" />
|
||||||
|
<!-- Note - these are currently unused, but they are for if/when we add private UI to tabs tray -->
|
||||||
|
<attr name="tabTrayItemBackground" format="reference" />
|
||||||
|
<attr name="tabTrayItemSelectedBackground" format="reference" />
|
||||||
|
<attr name="tabTrayToolbarBackground" format="reference" />
|
||||||
|
|
||||||
<declare-styleable name="TrackingProtectionCategory">
|
<declare-styleable name="TrackingProtectionCategory">
|
||||||
<attr name="categoryItemTitle" format="reference" />
|
<attr name="categoryItemTitle" format="reference" />
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
<color name="tab_tray_item_text_light_theme">@color/ink_80</color>
|
<color name="tab_tray_item_text_light_theme">@color/ink_80</color>
|
||||||
<color name="tab_tray_item_url_light_theme">@color/dark_grey_05</color>
|
<color name="tab_tray_item_url_light_theme">@color/dark_grey_05</color>
|
||||||
<color name="tab_tray_item_background_light_theme">@color/light_grey_10</color>
|
<color name="tab_tray_item_background_light_theme">@color/light_grey_10</color>
|
||||||
<color name="tab_tray_item_selected_background_light_theme">@color/violet_70_12a</color>
|
<color name="tab_tray_item_selected_background_light_theme">#E5DFF4</color>
|
||||||
<color name="tab_tray_toolbar_background_light_theme">@color/light_grey_10</color>
|
<color name="tab_tray_toolbar_background_light_theme">@color/light_grey_10</color>
|
||||||
<color name="tab_tray_item_divider_light_theme">@color/light_grey_30</color>
|
<color name="tab_tray_item_divider_light_theme">@color/light_grey_30</color>
|
||||||
<color name="tab_tray_item_media_stroke">#ffffff</color>
|
<color name="tab_tray_item_media_stroke">#ffffff</color>
|
||||||
|
@ -136,7 +136,7 @@
|
||||||
<color name="tab_tray_item_text_dark_theme">@color/light_grey_05</color>
|
<color name="tab_tray_item_text_dark_theme">@color/light_grey_05</color>
|
||||||
<color name="tab_tray_item_url_dark_theme">@color/light_grey_60</color>
|
<color name="tab_tray_item_url_dark_theme">@color/light_grey_60</color>
|
||||||
<color name="tab_tray_item_background_dark_theme">@color/dark_grey_80</color>
|
<color name="tab_tray_item_background_dark_theme">@color/dark_grey_80</color>
|
||||||
<color name="tab_tray_item_selected_background_dark_theme">@color/violet_50_32a</color>
|
<color name="tab_tray_item_selected_background_dark_theme">#412E69</color>
|
||||||
<color name="tab_tray_toolbar_background_dark_theme">@color/dark_grey_50</color>
|
<color name="tab_tray_toolbar_background_dark_theme">@color/dark_grey_50</color>
|
||||||
<color name="tab_tray_item_divider_dark_theme">@color/dark_grey_10</color>
|
<color name="tab_tray_item_divider_dark_theme">@color/dark_grey_10</color>
|
||||||
<color name="tab_tray_item_media_background_dark_theme">#9059FF</color>
|
<color name="tab_tray_item_media_background_dark_theme">#9059FF</color>
|
||||||
|
@ -190,7 +190,7 @@
|
||||||
<color name="tab_tray_item_text_private_theme">@color/light_grey_05</color>
|
<color name="tab_tray_item_text_private_theme">@color/light_grey_05</color>
|
||||||
<color name="tab_tray_item_url_private_theme">@color/light_grey_60</color>
|
<color name="tab_tray_item_url_private_theme">@color/light_grey_60</color>
|
||||||
<color name="tab_tray_item_background_private_theme">@color/ink_90</color>
|
<color name="tab_tray_item_background_private_theme">@color/ink_90</color>
|
||||||
<color name="tab_tray_item_selected_background_private_theme">@color/violet_50_32a</color>
|
<color name="tab_tray_item_selected_background_private_theme">#422875</color>
|
||||||
<color name="tab_tray_toolbar_background_private_theme">@color/ink_50</color>
|
<color name="tab_tray_toolbar_background_private_theme">@color/ink_50</color>
|
||||||
<color name="tab_tray_item_divider_private_theme">@color/dark_grey_10</color>
|
<color name="tab_tray_item_divider_private_theme">@color/dark_grey_10</color>
|
||||||
<color name="tab_tray_item_media_background_private_theme">#9059FF</color>
|
<color name="tab_tray_item_media_background_private_theme">#9059FF</color>
|
||||||
|
|
|
@ -61,6 +61,7 @@ class DefaultTabTrayControllerTest {
|
||||||
|
|
||||||
every { activity.components.core.sessionManager } returns sessionManager
|
every { activity.components.core.sessionManager } returns sessionManager
|
||||||
every { activity.components.core.tabCollectionStorage } returns tabCollectionStorage
|
every { activity.components.core.tabCollectionStorage } returns tabCollectionStorage
|
||||||
|
every { activity.components.core.engine.profiler } returns mockk(relaxed = true)
|
||||||
every { sessionManager.sessionsOfType(private = true) } returns listOf(session).asSequence()
|
every { sessionManager.sessionsOfType(private = true) } returns listOf(session).asSequence()
|
||||||
every { sessionManager.sessionsOfType(private = false) } returns listOf(nonPrivateSession).asSequence()
|
every { sessionManager.sessionsOfType(private = false) } returns listOf(nonPrivateSession).asSequence()
|
||||||
every { sessionManager.createSessionSnapshot(any()) } returns SessionManager.Snapshot.Item(
|
every { sessionManager.createSessionSnapshot(any()) } returns SessionManager.Snapshot.Item(
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
sdk=28
|
|
@ -3,5 +3,5 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
object AndroidComponents {
|
object AndroidComponents {
|
||||||
const val VERSION = "50.0.20200709130100"
|
const val VERSION = "50.0.20200710130140"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue