For #7092: Add initial Migration UI
parent
29d9ba472c
commit
b89afe7b7c
|
@ -429,10 +429,7 @@ dependencies {
|
||||||
implementation Deps.mozilla_support_utils
|
implementation Deps.mozilla_support_utils
|
||||||
implementation Deps.mozilla_support_locale
|
implementation Deps.mozilla_support_locale
|
||||||
|
|
||||||
// We only care about support-migration in builds that will be overwriting Fennec.
|
implementation Deps.mozilla_support_migration
|
||||||
fennecProductionImplementation Deps.mozilla_support_migration
|
|
||||||
fennecBetaImplementation Deps.mozilla_support_migration
|
|
||||||
fennecNightlyImplementation Deps.mozilla_support_migration
|
|
||||||
|
|
||||||
implementation Deps.mozilla_ui_colors
|
implementation Deps.mozilla_ui_colors
|
||||||
implementation Deps.mozilla_ui_icons
|
implementation Deps.mozilla_ui_icons
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
History
|
||||||
|
Bookmarks
|
||||||
|
Logins
|
||||||
|
Open Tabs
|
||||||
|
Settings
|
|
@ -52,7 +52,8 @@ class IntentReceiverActivity : Activity() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val intentProcessors = components.intentProcessors.externalAppIntentProcessors +
|
val intentProcessors = listOf(components.intentProcessors.migrationIntentProcessor) +
|
||||||
|
components.intentProcessors.externalAppIntentProcessors +
|
||||||
modeDependentProcessors +
|
modeDependentProcessors +
|
||||||
NewTabShortcutIntentProcessor()
|
NewTabShortcutIntentProcessor()
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.fenix.components
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
|
||||||
|
import mozilla.components.support.migration.state.MigrationStore
|
||||||
import org.mozilla.fenix.test.Mockable
|
import org.mozilla.fenix.test.Mockable
|
||||||
import org.mozilla.fenix.utils.ClipboardHandler
|
import org.mozilla.fenix.utils.ClipboardHandler
|
||||||
|
|
||||||
|
@ -44,10 +45,12 @@ class Components(private val context: Context) {
|
||||||
useCases.sessionUseCases,
|
useCases.sessionUseCases,
|
||||||
useCases.searchUseCases,
|
useCases.searchUseCases,
|
||||||
core.client,
|
core.client,
|
||||||
core.customTabsStore
|
core.customTabsStore,
|
||||||
|
migrationStore
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val analytics by lazy { Analytics(context) }
|
val analytics by lazy { Analytics(context) }
|
||||||
val publicSuffixList by lazy { PublicSuffixList(context) }
|
val publicSuffixList by lazy { PublicSuffixList(context) }
|
||||||
val clipboardHandler by lazy { ClipboardHandler(context) }
|
val clipboardHandler by lazy { ClipboardHandler(context) }
|
||||||
|
val migrationStore by lazy { MigrationStore() }
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,11 @@ package org.mozilla.fenix.components
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import mozilla.components.feature.intent.processing.IntentProcessor
|
import mozilla.components.feature.intent.processing.IntentProcessor
|
||||||
import org.mozilla.fenix.HomeActivity
|
import org.mozilla.fenix.HomeActivity
|
||||||
|
import org.mozilla.fenix.MigrationProgressActivity
|
||||||
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
|
import org.mozilla.fenix.customtabs.ExternalAppBrowserActivity
|
||||||
|
|
||||||
enum class IntentProcessorType {
|
enum class IntentProcessorType {
|
||||||
EXTERNAL_APP, NEW_TAB, OTHER;
|
EXTERNAL_APP, NEW_TAB, MIGRATION, OTHER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The destination activity based on this intent
|
* The destination activity based on this intent
|
||||||
|
@ -19,6 +20,7 @@ enum class IntentProcessorType {
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
EXTERNAL_APP -> ExternalAppBrowserActivity::class.java.name
|
EXTERNAL_APP -> ExternalAppBrowserActivity::class.java.name
|
||||||
NEW_TAB, OTHER -> HomeActivity::class.java.name
|
NEW_TAB, OTHER -> HomeActivity::class.java.name
|
||||||
|
MIGRATION -> MigrationProgressActivity::class.java.name
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +29,7 @@ enum class IntentProcessorType {
|
||||||
fun shouldOpenToBrowser(intent: Intent): Boolean = when (this) {
|
fun shouldOpenToBrowser(intent: Intent): Boolean = when (this) {
|
||||||
EXTERNAL_APP -> true
|
EXTERNAL_APP -> true
|
||||||
NEW_TAB -> intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0
|
NEW_TAB -> intent.flags and Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY == 0
|
||||||
OTHER -> false
|
MIGRATION, OTHER -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ enum class IntentProcessorType {
|
||||||
* Classifies the [IntentProcessorType] based on the [IntentProcessor] that handled the [Intent].
|
* Classifies the [IntentProcessorType] based on the [IntentProcessor] that handled the [Intent].
|
||||||
*/
|
*/
|
||||||
fun IntentProcessors.getType(processor: IntentProcessor?) = when {
|
fun IntentProcessors.getType(processor: IntentProcessor?) = when {
|
||||||
|
migrationIntentProcessor == processor -> IntentProcessorType.MIGRATION
|
||||||
externalAppIntentProcessors.contains(processor) ||
|
externalAppIntentProcessors.contains(processor) ||
|
||||||
customTabIntentProcessor == processor ||
|
customTabIntentProcessor == processor ||
|
||||||
privateCustomTabIntentProcessor == processor -> IntentProcessorType.EXTERNAL_APP
|
privateCustomTabIntentProcessor == processor -> IntentProcessorType.EXTERNAL_APP
|
||||||
|
|
|
@ -15,6 +15,8 @@ import mozilla.components.feature.pwa.intent.WebAppIntentProcessor
|
||||||
import mozilla.components.feature.pwa.intent.TrustedWebActivityIntentProcessor
|
import mozilla.components.feature.pwa.intent.TrustedWebActivityIntentProcessor
|
||||||
import mozilla.components.feature.search.SearchUseCases
|
import mozilla.components.feature.search.SearchUseCases
|
||||||
import mozilla.components.feature.session.SessionUseCases
|
import mozilla.components.feature.session.SessionUseCases
|
||||||
|
import mozilla.components.support.migration.MigrationIntentProcessor
|
||||||
|
import mozilla.components.support.migration.state.MigrationStore
|
||||||
import org.mozilla.fenix.BuildConfig
|
import org.mozilla.fenix.BuildConfig
|
||||||
import org.mozilla.fenix.home.intent.FennecBookmarkShortcutsIntentProcessor
|
import org.mozilla.fenix.home.intent.FennecBookmarkShortcutsIntentProcessor
|
||||||
import org.mozilla.fenix.test.Mockable
|
import org.mozilla.fenix.test.Mockable
|
||||||
|
@ -29,7 +31,8 @@ class IntentProcessors(
|
||||||
private val sessionUseCases: SessionUseCases,
|
private val sessionUseCases: SessionUseCases,
|
||||||
private val searchUseCases: SearchUseCases,
|
private val searchUseCases: SearchUseCases,
|
||||||
private val httpClient: Client,
|
private val httpClient: Client,
|
||||||
private val customTabsStore: CustomTabsServiceStore
|
private val customTabsStore: CustomTabsServiceStore,
|
||||||
|
private val migrationStore: MigrationStore
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Provides intent processing functionality for ACTION_VIEW and ACTION_SEND intents.
|
* Provides intent processing functionality for ACTION_VIEW and ACTION_SEND intents.
|
||||||
|
@ -67,4 +70,8 @@ class IntentProcessors(
|
||||||
FennecBookmarkShortcutsIntentProcessor(sessionManager, sessionUseCases.loadUrl)
|
FennecBookmarkShortcutsIntentProcessor(sessionManager, sessionUseCases.loadUrl)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val migrationIntentProcessor by lazy {
|
||||||
|
MigrationIntentProcessor(migrationStore)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,77 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingTop="55dp"
|
||||||
|
android:paddingEnd="20dp"
|
||||||
|
android:paddingBottom="67dp">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/migration_firefox_logo"
|
||||||
|
android:layout_width="67dp"
|
||||||
|
android:layout_height="67dp"
|
||||||
|
android:contentDescription="@string/firefox_logo_description"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/ic_firefox" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/migration_welcome_title"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:maxLines="2"
|
||||||
|
android:text="@string/migration_title"
|
||||||
|
android:textAppearance="@style/HeaderTextStyle"
|
||||||
|
android:fontFamily="sans-serif-medium"
|
||||||
|
android:textColor="@color/button_text_color"
|
||||||
|
android:textSize="20sp"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/migration_description"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/migration_firefox_logo"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="Welcome to the all-new Firefox Preview" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
|
android:id="@+id/migration_description"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="24dp"
|
||||||
|
android:text="@string/migration_description"
|
||||||
|
android:textAppearance="@style/Header16TextStyle"
|
||||||
|
android:textColor="@color/text_scale_example_text_color"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/migration_firefox_logo" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/migration_status_list"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/migration_button"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/migration_description"
|
||||||
|
tools:itemCount="5"
|
||||||
|
tools:listitem="@layout/migration_list_item" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/migration_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:enabled="false"
|
||||||
|
android:minWidth="200dp"
|
||||||
|
android:text="@string/migration_updating_app_button_text"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
tools:text="Updating Firefox…" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/migration_status_image"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="@string/migration_icon_description"
|
||||||
|
android:tint="@color/collection_icon_color_violet"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/mozac_ic_check"
|
||||||
|
tools:tint="@color/above_dark_theme" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/migration_item_name"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="24dp"
|
||||||
|
android:layout_marginEnd="32dp"
|
||||||
|
android:fontFamily="sans-serif-medium"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@+id/migration_status_image"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="@sample/migration_items" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1117,4 +1117,17 @@
|
||||||
<string name="search_edit_custom_engine_success_message">Saved %s</string>
|
<string name="search_edit_custom_engine_success_message">Saved %s</string>
|
||||||
<!-- Text shown when a user successfully deletes a custom search engine -->
|
<!-- Text shown when a user successfully deletes a custom search engine -->
|
||||||
<string name="search_delete_search_engine_success_message">Deleted %s</string>
|
<string name="search_delete_search_engine_success_message">Deleted %s</string>
|
||||||
|
|
||||||
|
<!-- Description text for the Firefox brand logo -->
|
||||||
|
<string name="firefox_logo_description">Firefox logo</string>
|
||||||
|
<!-- Title text shown for the migration screen to the new browser -->
|
||||||
|
<string name="migration_title">Welcome to an all-new Firefox</string>
|
||||||
|
<!-- Description text followed by a list of things migrating (e.g. Bookmarks, History) -->
|
||||||
|
<string name="migration_description">A completely redesigned browser awaits, with improved performance and features to help you do more online.\n\nPlease wait while we update Firefox with your</string>
|
||||||
|
<!-- Text on the disabled button while in progress -->
|
||||||
|
<string name="migration_updating_app_button_text">Updating %s…</string>
|
||||||
|
<!-- Text on the enabled button -->
|
||||||
|
<string name="migration_update_app_button">Start %s</string>
|
||||||
|
<!-- Accessibility description text for completed migration item (e.g. Bookmarks, History) -->
|
||||||
|
<string name="migration_icon_description">Migration status: %s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -13,6 +13,11 @@
|
||||||
android:name="org.mozilla.fenix.MigratingFenixApplication"
|
android:name="org.mozilla.fenix.MigratingFenixApplication"
|
||||||
tools:replace="android:name">
|
tools:replace="android:name">
|
||||||
<service android:name="org.mozilla.fenix.MigrationService" />
|
<service android:name="org.mozilla.fenix.MigrationService" />
|
||||||
|
|
||||||
|
<activity
|
||||||
|
android:name="org.mozilla.fenix.MigrationProgressActivity"
|
||||||
|
android:exported="false">
|
||||||
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package org.mozilla.fenix
|
package org.mozilla.fenix
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import mozilla.components.support.migration.FennecMigrator
|
import mozilla.components.support.migration.FennecMigrator
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
import mozilla.components.support.migration.state.MigrationStore
|
||||||
|
@ -47,6 +48,10 @@ class MigratingFenixApplication : FenixApplication() {
|
||||||
// The rest of the migrations can happen now.
|
// The rest of the migrations can happen now.
|
||||||
migrationPushSubscriber.start()
|
migrationPushSubscriber.start()
|
||||||
migrator.startMigrationIfNeeded(migrationStore, MigrationService::class.java)
|
migrator.startMigrationIfNeeded(migrationStore, MigrationService::class.java)
|
||||||
|
|
||||||
|
// Start migration UI
|
||||||
|
val intent = Intent(this, MigrationProgressActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun migrateBlocking() {
|
private fun migrateBlocking() {
|
||||||
|
|
|
@ -0,0 +1,148 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import kotlinx.android.synthetic.main.activity_migration.*
|
||||||
|
import kotlinx.android.synthetic.main.migration_list_item.view.*
|
||||||
|
import mozilla.components.support.migration.AbstractMigrationProgressActivity
|
||||||
|
import mozilla.components.support.migration.Migration
|
||||||
|
import mozilla.components.support.migration.Migration.Bookmarks
|
||||||
|
import mozilla.components.support.migration.Migration.History
|
||||||
|
import mozilla.components.support.migration.Migration.Logins
|
||||||
|
import mozilla.components.support.migration.Migration.Settings
|
||||||
|
import mozilla.components.support.migration.MigrationResults
|
||||||
|
import mozilla.components.support.migration.state.MigrationProgress
|
||||||
|
import mozilla.components.support.migration.state.MigrationStore
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
|
|
||||||
|
class MigrationProgressActivity : AbstractMigrationProgressActivity() {
|
||||||
|
private val statusAdapter = MigrationStatusAdapter()
|
||||||
|
override val store: MigrationStore by lazy { components.migrationStore }
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
setContentView(R.layout.activity_migration)
|
||||||
|
init()
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
migration_status_list.apply {
|
||||||
|
layoutManager = LinearLayoutManager(this@MigrationProgressActivity)
|
||||||
|
adapter = statusAdapter
|
||||||
|
}
|
||||||
|
|
||||||
|
migration_button.apply {
|
||||||
|
setOnClickListener {
|
||||||
|
finish()
|
||||||
|
overridePendingTransition(0, 0)
|
||||||
|
|
||||||
|
// If we received a user-initiated intent, throw this back to the intent receiver.
|
||||||
|
if (intent.hasExtra(HomeActivity.OPEN_TO_BROWSER)) {
|
||||||
|
intent.setClassName(applicationContext, IntentReceiverActivity::class.java.name)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text = getString(
|
||||||
|
R.string.migration_updating_app_button_text,
|
||||||
|
getString(R.string.app_name)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||||
|
super.onWindowFocusChanged(hasFocus)
|
||||||
|
if (hasFocus) {
|
||||||
|
// Enables sticky immersive mode.
|
||||||
|
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||||
|
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||||
|
or View.SYSTEM_UI_FLAG_FULLSCREEN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMigrationCompleted() {
|
||||||
|
// Enable clicking the finish button
|
||||||
|
migration_button.apply {
|
||||||
|
isEnabled = true
|
||||||
|
text = getString(R.string.migration_update_app_button, getString(R.string.app_name))
|
||||||
|
setBackgroundColor(ContextCompat.getColor(context, R.color.button_text_color))
|
||||||
|
setTextColor(ContextCompat.getColor(context, R.color.white_color))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMigrationStateChanged(progress: MigrationProgress, results: MigrationResults) {
|
||||||
|
statusAdapter.submitList(results.toItemList())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These are the only items we want to show migrating in the UI.
|
||||||
|
internal val whiteList = mapOf(
|
||||||
|
Bookmarks to R.string.preferences_sync_bookmarks,
|
||||||
|
History to R.string.preferences_sync_history,
|
||||||
|
Logins to R.string.preferences_sync_logins,
|
||||||
|
Settings to R.string.settings_title
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun MigrationResults.toItemList() = filterKeys {
|
||||||
|
whiteList.keys.contains(it)
|
||||||
|
}.map { (type, status) ->
|
||||||
|
MigrationItem(
|
||||||
|
type,
|
||||||
|
status.success
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal data class MigrationItem(val migration: Migration, val status: Boolean)
|
||||||
|
|
||||||
|
internal class MigrationStatusAdapter :
|
||||||
|
ListAdapter<MigrationItem, MigrationStatusAdapter.ViewHolder>(DiffCallback) {
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val view = LayoutInflater.from(parent.context).inflate(viewType, parent, false)
|
||||||
|
|
||||||
|
return ViewHolder(view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(getItem(position))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int): Int = R.layout.migration_list_item
|
||||||
|
|
||||||
|
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
||||||
|
private val context = view.context
|
||||||
|
private val title = view.migration_item_name
|
||||||
|
private val status = view.migration_status_image
|
||||||
|
|
||||||
|
fun bind(item: MigrationItem) {
|
||||||
|
// Get the resource ID for the item.
|
||||||
|
val migrationText = whiteList[item.migration]?.run {
|
||||||
|
context.getString(this)
|
||||||
|
} ?: ""
|
||||||
|
title.text = migrationText
|
||||||
|
status.visibility = if (item.status) View.VISIBLE else View.INVISIBLE
|
||||||
|
status.contentDescription =
|
||||||
|
context.getString(R.string.migration_icon_description, migrationText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DiffCallback : DiffUtil.ItemCallback<MigrationItem>() {
|
||||||
|
|
||||||
|
override fun areItemsTheSame(oldItem: MigrationItem, newItem: MigrationItem) =
|
||||||
|
oldItem.migration.javaClass.simpleName == newItem.migration.javaClass.simpleName
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: MigrationItem, newItem: MigrationItem) =
|
||||||
|
oldItem.migration.javaClass.simpleName == newItem.migration.javaClass.simpleName &&
|
||||||
|
oldItem.status == newItem.status
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,11 +6,12 @@ package org.mozilla.fenix
|
||||||
|
|
||||||
import mozilla.components.support.migration.AbstractMigrationService
|
import mozilla.components.support.migration.AbstractMigrationService
|
||||||
import mozilla.components.support.migration.state.MigrationStore
|
import mozilla.components.support.migration.state.MigrationStore
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Background service for running the migration from legacy Firefox for Android (Fennec).
|
* Background service for running the migration from legacy Firefox for Android (Fennec).
|
||||||
*/
|
*/
|
||||||
class MigrationService : AbstractMigrationService() {
|
class MigrationService : AbstractMigrationService() {
|
||||||
override val migrator by lazy { getMigratorFromApplication() }
|
override val migrator by lazy { getMigratorFromApplication() }
|
||||||
override val store: MigrationStore by lazy { getMigrationStoreFromApplication() }
|
override val store: MigrationStore by lazy { components.migrationStore }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue