Commit bfc955cd authored by Mihai Branescu's avatar Mihai Branescu
Browse files

For #11498 - add Sync tabs error view (including sign-in CTA)

parent a1127707
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -6,10 +6,13 @@ package org.mozilla.fenix.sync

import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.navigation.NavController
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import mozilla.components.browser.storage.sync.SyncedDeviceTabs
import org.mozilla.fenix.sync.SyncedTabsViewHolder.DeviceViewHolder
import org.mozilla.fenix.sync.SyncedTabsViewHolder.ErrorViewHolder
import org.mozilla.fenix.sync.SyncedTabsViewHolder.SignInViewHolder
import org.mozilla.fenix.sync.SyncedTabsViewHolder.TabViewHolder
import mozilla.components.browser.storage.sync.Tab as SyncTab
import mozilla.components.concept.sync.Device as SyncDevice
@@ -24,6 +27,8 @@ class SyncedTabsAdapter(
        return when (viewType) {
            DeviceViewHolder.LAYOUT_ID -> DeviceViewHolder(itemView)
            TabViewHolder.LAYOUT_ID -> TabViewHolder(itemView)
            ErrorViewHolder.LAYOUT_ID -> ErrorViewHolder(itemView)
            SignInViewHolder.LAYOUT_ID -> SignInViewHolder(itemView)
            else -> throw IllegalStateException()
        }
    }
@@ -35,6 +40,8 @@ class SyncedTabsAdapter(
    override fun getItemViewType(position: Int) = when (getItem(position)) {
        is AdapterItem.Device -> DeviceViewHolder.LAYOUT_ID
        is AdapterItem.Tab -> TabViewHolder.LAYOUT_ID
        is AdapterItem.Error -> ErrorViewHolder.LAYOUT_ID
        is AdapterItem.SignIn -> SignInViewHolder.LAYOUT_ID
    }

    fun updateData(syncedTabs: List<SyncedDeviceTabs>) {
@@ -55,7 +62,7 @@ class SyncedTabsAdapter(
            when (oldItem) {
                is AdapterItem.Device ->
                    newItem is AdapterItem.Device && oldItem.device.id == newItem.device.id
                is AdapterItem.Tab ->
                is AdapterItem.Tab, AdapterItem.Error, AdapterItem.SignIn ->
                    oldItem == newItem
            }

@@ -67,5 +74,7 @@ class SyncedTabsAdapter(
    sealed class AdapterItem {
        data class Device(val device: SyncDevice) : AdapterItem()
        data class Tab(val tab: SyncTab) : AdapterItem()
        data class SignIn(val navController: NavController) : AdapterItem()
        data class Error(val errorResId: Int) : AdapterItem()
    }
}
+3 −1
Original line number Diff line number Diff line
@@ -6,8 +6,10 @@ package org.mozilla.fenix.sync

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.FrameLayout
import androidx.annotation.StringRes
import androidx.fragment.app.findFragment
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager
import kotlinx.android.synthetic.main.component_sync_tabs.view.*
import kotlinx.coroutines.CoroutineScope
+59 −1
Original line number Diff line number Diff line
@@ -5,11 +5,17 @@
package org.mozilla.fenix.sync

import android.view.View
import android.view.View.GONE
import android.widget.LinearLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.no_content_message_with_action.view.*
import kotlinx.android.synthetic.main.sync_tabs_list_item.view.*
import kotlinx.android.synthetic.main.view_synced_tabs_group.view.*
import mozilla.components.browser.storage.sync.Tab
import mozilla.components.concept.sync.DeviceType
import mozilla.components.support.ktx.android.util.dpToPx
import org.mozilla.fenix.NavGraphDirections
import org.mozilla.fenix.R
import org.mozilla.fenix.sync.SyncedTabsAdapter.AdapterItem

@@ -38,6 +44,44 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item
        }
    }

    class SignInViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) {

        override fun <T : AdapterItem> bind(item: T, interactor: (Tab) -> Unit) {
            val signInItem = item as AdapterItem.SignIn
            setErrorMargins()

            itemView.no_content_header.visibility = GONE
            itemView.no_content_description.text =
                itemView.context.getString(R.string.synced_tabs_sign_in_message)
            itemView.no_content_button.text =
                itemView.context.getString(R.string.synced_tabs_sign_in_button)
            itemView.no_content_button.icon =
                ContextCompat.getDrawable(itemView.context, R.drawable.ic_sign_in)
            itemView.no_content_button.setOnClickListener {
                signInItem.navController.navigate(NavGraphDirections.actionGlobalTurnOnSync())
            }
        }

        companion object {
            const val LAYOUT_ID = R.layout.no_content_message_with_action
        }
    }

    class ErrorViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) {

        override fun <T : AdapterItem> bind(item: T, interactor: (Tab) -> Unit) {
            val errorItem = item as AdapterItem.Error
            setErrorMargins()

            itemView.no_content_header.visibility = GONE
            itemView.no_content_description.text = itemView.context.getString(errorItem.errorResId)
        }

        companion object {
            const val LAYOUT_ID = R.layout.no_content_message
        }
    }

    class DeviceViewHolder(itemView: View) : SyncedTabsViewHolder(itemView) {

        override fun <T : AdapterItem> bind(item: T, interactor: (Tab) -> Unit) {
@@ -45,7 +89,6 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item
        }

        private fun bindHeader(device: AdapterItem.Device) {

            val deviceLogoDrawable = when (device.device.deviceType) {
                DeviceType.DESKTOP -> R.drawable.mozac_ic_device_desktop
                else -> R.drawable.mozac_ic_device_mobile
@@ -59,4 +102,19 @@ sealed class SyncedTabsViewHolder(itemView: View) : RecyclerView.ViewHolder(item
            const val LAYOUT_ID = R.layout.view_synced_tabs_group
        }
    }

    internal fun setErrorMargins() {
        val lp = LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.MATCH_PARENT,
            LinearLayout.LayoutParams.WRAP_CONTENT
        )
        val displayMetrics = itemView.context.resources.displayMetrics
        val margin = ERROR_MARGIN.dpToPx(displayMetrics)
        lp.setMargins(margin, margin, margin, 0)
        itemView.layoutParams = lp
    }

    companion object {
        private const val ERROR_MARGIN = 20
    }
}
+0 −14
Original line number Diff line number Diff line
@@ -20,20 +20,6 @@
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/sync_tabs_status"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:gravity="center"
        android:text="@string/sync_connect_device"
        android:textColor="?secondaryText"
        android:textSize="16sp"
        android:visibility="gone"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent" />

    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        android:id="@+id/synced_tabs_pull_to_refresh"
        android:layout_width="match_parent"
+0 −2
Original line number Diff line number Diff line
@@ -1432,8 +1432,6 @@
    <string name="saved_login_duplicate">A login with that username already exists</string>

    <!-- Synced Tabs -->
    <!-- Text displayed when user is not logged into a Firefox Account -->
    <string name="synced_tabs_connect_to_sync_account">Connect with a Firefox Account.</string>
    <!-- Text displayed to ask user to connect another device as no devices found with account -->
    <string name="synced_tabs_connect_another_device">Connect another device.</string>
    <!-- Text displayed asking user to re-authenticate -->