diff --git a/app/src/main/java/org/mozilla/fenix/share/AccountDevicesShareView.kt b/app/src/main/java/org/mozilla/fenix/share/AccountDevicesShareView.kt deleted file mode 100644 index d7d37295e..000000000 --- a/app/src/main/java/org/mozilla/fenix/share/AccountDevicesShareView.kt +++ /dev/null @@ -1,150 +0,0 @@ -/* 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.share - -import android.content.Context -import android.graphics.PorterDuff.Mode.SRC_IN -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.core.content.ContextCompat -import androidx.recyclerview.widget.RecyclerView -import io.reactivex.Observer -import kotlinx.android.synthetic.main.account_share_list_item.view.* -import mozilla.components.concept.sync.Device -import mozilla.components.concept.sync.DeviceCapability -import mozilla.components.concept.sync.DeviceType -import org.mozilla.fenix.R -import org.mozilla.fenix.ext.components - -class AccountDevicesShareAdapter( - private val context: Context, - val actionEmitter: Observer -) : RecyclerView.Adapter() { - - private val devices = buildDeviceList() - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AccountDeviceViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(AccountDeviceViewHolder.LAYOUT_ID, parent, false) - return AccountDeviceViewHolder(view, actionEmitter) - } - - override fun getItemCount(): Int = devices.size - - override fun onBindViewHolder(holder: AccountDeviceViewHolder, position: Int) { - holder.bind(devices[position]) - } - - private fun buildDeviceList(): List { - val list = mutableListOf() - val accountManager = context.components.backgroundServices.accountManager - - if (accountManager.authenticatedAccount() == null) { - list.add(SyncShareOption.SignIn) - return list - } - - accountManager.authenticatedAccount()?.deviceConstellation()?.state()?.otherDevices?.let { devices -> - val shareableDevices = devices.filter { it.capabilities.contains(DeviceCapability.SEND_TAB) } - - if (shareableDevices.isEmpty()) { - list.add(SyncShareOption.AddNewDevice) - } - - val shareOptions = shareableDevices.map { - when (it.deviceType) { - DeviceType.MOBILE -> SyncShareOption.Mobile(it.displayName, it) - else -> SyncShareOption.Desktop(it.displayName, it) - } - } - list.addAll(shareOptions) - - if (shareableDevices.size > 1) { - list.add(SyncShareOption.SendAll(shareableDevices)) - } - } - return list - } -} - -class AccountDeviceViewHolder( - itemView: View, - actionEmitter: Observer -) : RecyclerView.ViewHolder(itemView) { - - private val context: Context = itemView.context - private var action: ShareAction? = null - - init { - itemView.setOnClickListener { - action?.let { actionEmitter.onNext(it) } - } - } - - fun bind(option: SyncShareOption) { - val (name, drawableRes, colorRes) = when (option) { - SyncShareOption.SignIn -> { - action = ShareAction.SignInClicked - Triple( - context.getText(R.string.sync_sign_in), - R.drawable.mozac_ic_sync, - R.color.default_share_background - ) - } - SyncShareOption.AddNewDevice -> { - action = ShareAction.AddNewDeviceClicked - Triple( - context.getText(R.string.sync_connect_device), - R.drawable.mozac_ic_new, - R.color.default_share_background - ) - } - is SyncShareOption.SendAll -> { - action = ShareAction.SendAllClicked(option.devices) - Triple( - context.getText(R.string.sync_send_to_all), - R.drawable.mozac_ic_select_all, - R.color.default_share_background - ) - } - is SyncShareOption.Mobile -> { - action = ShareAction.ShareDeviceClicked(option.device) - Triple( - option.name, - R.drawable.mozac_ic_device_mobile, - R.color.device_type_mobile_background - ) - } - is SyncShareOption.Desktop -> { - action = ShareAction.ShareDeviceClicked(option.device) - Triple( - option.name, - R.drawable.mozac_ic_device_desktop, - R.color.device_type_desktop_background - ) - } - } - - itemView.deviceIcon.apply { - setImageResource(drawableRes) - background.setColorFilter(ContextCompat.getColor(context, colorRes), SRC_IN) - drawable.setTint(ContextCompat.getColor(context, R.color.device_foreground)) - } - itemView.deviceName.text = name - } - - companion object { - const val LAYOUT_ID = R.layout.account_share_list_item - } -} - -sealed class SyncShareOption { - object SignIn : SyncShareOption() - object AddNewDevice : SyncShareOption() - data class SendAll(val devices: List) : SyncShareOption() - data class Mobile(val name: String, val device: Device) : SyncShareOption() - data class Desktop(val name: String, val device: Device) : SyncShareOption() -} diff --git a/app/src/main/java/org/mozilla/fenix/share/AppShareView.kt b/app/src/main/java/org/mozilla/fenix/share/AppShareView.kt deleted file mode 100644 index d34ada1e9..000000000 --- a/app/src/main/java/org/mozilla/fenix/share/AppShareView.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* 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.share - -import android.content.Context -import android.content.Intent -import android.content.Intent.ACTION_SEND -import android.content.Intent.FLAG_ACTIVITY_NEW_TASK -import android.graphics.drawable.Drawable -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.reactivex.Observer -import kotlinx.android.synthetic.main.app_share_list_item.view.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.cancel -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import org.mozilla.fenix.R - -class AppShareAdapter( - private val context: Context, - val actionEmitter: Observer, - private val intentType: String = "text/plain" -) : RecyclerView.Adapter() { - - private var scope = CoroutineScope(Dispatchers.IO) - - private var size: Int = 0 - private val shareItems: MutableList = mutableListOf() - - init { - val testIntent = Intent(ACTION_SEND).apply { - type = intentType - flags = FLAG_ACTIVITY_NEW_TASK - } - - scope.launch { - val activities = context.packageManager.queryIntentActivities(testIntent, 0) - - val items = activities.map { resolveInfo -> - ShareItem( - resolveInfo.loadLabel(context.packageManager).toString(), - resolveInfo.loadIcon(context.packageManager), - resolveInfo.activityInfo.packageName, - resolveInfo.activityInfo.name - ) - } - - size = activities.size - shareItems.addAll(items) - - // Notify adapter on the UI thread when the dataset is populated. - withContext(Dispatchers.Main) { - notifyDataSetChanged() - } - } - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppShareItemViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(AppShareItemViewHolder.LAYOUT_ID, parent, false) - return AppShareItemViewHolder(view, actionEmitter) - } - - override fun getItemCount(): Int = size - - override fun onBindViewHolder(holder: AppShareItemViewHolder, position: Int) { - holder.bind(shareItems[position]) - } - - override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { - super.onDetachedFromRecyclerView(recyclerView) - scope.cancel() - } -} - -class AppShareItemViewHolder( - itemView: View, - actionEmitter: Observer -) : RecyclerView.ViewHolder(itemView) { - - private var shareItem: ShareItem? = null - - init { - itemView.setOnClickListener { - shareItem?.let { - actionEmitter.onNext(ShareAction.ShareAppClicked(it)) - } - } - } - - internal fun bind(item: ShareItem) { - shareItem = item - itemView.appName.text = item.name - itemView.appIcon.setImageDrawable(item.icon) - } - - companion object { - const val LAYOUT_ID = R.layout.app_share_list_item - } -} - -data class ShareItem(val name: String, val icon: Drawable, val packageName: String, val activityName: String) diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareCloseView.kt b/app/src/main/java/org/mozilla/fenix/share/ShareCloseView.kt new file mode 100644 index 000000000..b9a511cfc --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/ShareCloseView.kt @@ -0,0 +1,30 @@ +/* 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.share + +import android.view.LayoutInflater +import android.view.ViewGroup +import kotlinx.android.extensions.LayoutContainer +import kotlinx.android.synthetic.main.share_close.* +import org.mozilla.fenix.R + +/** + * Callbacks for possible user interactions on the [ShareCloseView] + */ +interface ShareCloseInteractor { + fun onShareClosed() +} + +class ShareCloseView( + override val containerView: ViewGroup, + private val interactor: ShareCloseInteractor +) : LayoutContainer { + init { + LayoutInflater.from(containerView.context) + .inflate(R.layout.share_close, containerView, true) + + closeButton.setOnClickListener { interactor.onShareClosed() } + } +} diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareComponent.kt b/app/src/main/java/org/mozilla/fenix/share/ShareComponent.kt deleted file mode 100644 index 74e92f856..000000000 --- a/app/src/main/java/org/mozilla/fenix/share/ShareComponent.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* 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.share - -import android.view.ViewGroup -import mozilla.components.concept.sync.Device -import org.mozilla.fenix.mvi.Action -import org.mozilla.fenix.mvi.ActionBusFactory -import org.mozilla.fenix.mvi.Change -import org.mozilla.fenix.mvi.Reducer -import org.mozilla.fenix.mvi.UIComponent -import org.mozilla.fenix.mvi.UIComponentViewModelBase -import org.mozilla.fenix.mvi.UIComponentViewModelProvider -import org.mozilla.fenix.mvi.ViewState - -object ShareState : ViewState - -sealed class ShareChange : Change - -sealed class ShareAction : Action { - object Close : ShareAction() - object SignInClicked : ShareAction() - object AddNewDeviceClicked : ShareAction() - data class ShareDeviceClicked(val device: Device) : ShareAction() - data class SendAllClicked(val devices: List) : ShareAction() - data class ShareAppClicked(val item: ShareItem) : ShareAction() -} - -class ShareComponent( - private val container: ViewGroup, - bus: ActionBusFactory, - viewModelProvider: UIComponentViewModelProvider -) : UIComponent( - bus.getManagedEmitter(ShareAction::class.java), - bus.getSafeManagedObservable(ShareChange::class.java), - viewModelProvider -) { - override fun initView() = ShareUIView(container, actionEmitter, changesObservable) - - init { - bind() - } -} - -class ShareUIViewModel( - initialState: ShareState -) : UIComponentViewModelBase( - initialState, - reducer -) { - companion object { - val reducer: Reducer = { _, _ -> ShareState } - } -} diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt index 1531f87f1..3c51798a5 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt @@ -4,35 +4,25 @@ package org.mozilla.fenix.share -import android.content.Intent -import android.content.Intent.ACTION_SEND -import android.content.Intent.EXTRA_TEXT -import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.os.Bundle import android.os.Parcelable import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatDialogFragment import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_share.view.* -import mozilla.components.concept.sync.DeviceEventOutgoing -import mozilla.components.concept.sync.OAuthAccount -import org.mozilla.fenix.FenixViewModelProvider -import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.R -import org.mozilla.fenix.ext.nav -import org.mozilla.fenix.ext.requireComponents -import org.mozilla.fenix.mvi.ActionBusFactory -import org.mozilla.fenix.mvi.getAutoDisposeObservable class ShareFragment : AppCompatDialogFragment() { interface TabsSharedCallback { fun onTabsShared(tabsSize: Int) } - private lateinit var component: ShareComponent + private lateinit var shareInteractor: ShareInteractor + private lateinit var shareCloseView: ShareCloseView + private lateinit var shareToAccountDevicesView: ShareToAccountDevicesView + private lateinit var shareToAppsView: ShareToAppsView private var tabs: Array = emptyArray() override fun onCreate(savedInstanceState: Bundle?) { @@ -53,92 +43,13 @@ class ShareFragment : AppCompatDialogFragment() { tabs = args.tabs ?: arrayOf(ShareTab(args.url!!, args.title ?: "")) - component = ShareComponent( - view.shareWrapper, - ActionBusFactory.get(this), - FenixViewModelProvider.create( - this, - ShareUIViewModel::class.java - ) { - ShareUIViewModel(ShareState) - } - ) + shareInteractor = ShareInteractor() - return view - } - - override fun onResume() { - super.onResume() - subscribeToActions() - } - - @SuppressWarnings("ComplexMethod") - private fun subscribeToActions() { - getAutoDisposeObservable().subscribe { - when (it) { - ShareAction.Close -> { - dismiss() - } - ShareAction.SignInClicked -> { - val directions = - ShareFragmentDirections.actionShareFragmentToTurnOnSyncFragment() - nav(R.id.shareFragment, directions) - dismiss() - } - ShareAction.AddNewDeviceClicked -> { - context?.let { - AlertDialog.Builder(it).apply { - setMessage(R.string.sync_connect_device_dialog) - setPositiveButton(R.string.sync_confirmation_button) { dialog, _ -> dialog.cancel() } - create() - }.show() - } - } - is ShareAction.ShareDeviceClicked -> { - val authAccount = - requireComponents.backgroundServices.accountManager.authenticatedAccount() - authAccount?.run { - sendSendTab(this, it.device.id, tabs) - } - dismiss() - } - is ShareAction.SendAllClicked -> { - val authAccount = - requireComponents.backgroundServices.accountManager.authenticatedAccount() - authAccount?.run { - it.devices.forEach { device -> - sendSendTab(this, device.id, tabs) - } - } - dismiss() - } - is ShareAction.ShareAppClicked -> { - - val shareText = tabs.joinToString("\n") { tab -> tab.url } + shareCloseView = ShareCloseView(view.closeSharingLayout, shareInteractor) + shareToAccountDevicesView = ShareToAccountDevicesView(view.devicesShareLayout, shareInteractor) + shareToAppsView = ShareToAppsView(view.appsShareLayout, shareInteractor) - val intent = Intent(ACTION_SEND).apply { - putExtra(EXTRA_TEXT, shareText) - type = "text/plain" - flags = FLAG_ACTIVITY_NEW_TASK - setClassName(it.item.packageName, it.item.activityName) - } - startActivity(intent) - dismiss() - } - } - } - } - - private fun sendSendTab(account: OAuthAccount, deviceId: String, tabs: Array) { - account.run { - tabs.forEach { tab -> - deviceConstellation().sendEventToDeviceAsync( - deviceId, - DeviceEventOutgoing.SendTab(tab.title, tab.url) - ) - } - } - (activity as? HomeActivity)?.onTabsShared(tabs.size) + return view } } diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt b/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt new file mode 100644 index 000000000..8eebc74b2 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.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 org.mozilla.fenix.share + +import mozilla.components.concept.sync.Device +import org.mozilla.fenix.share.listadapters.Application + +/** + * Interactor for the share screen. + */ +class ShareInteractor : ShareCloseInteractor, ShareToAccountDevicesInteractor, ShareToAppsInteractor { + override fun onShareClosed() { + TODO("not yet!? implemented") + } + + override fun onSignIn() { + TODO("not yet!? implemented") + } + + override fun onAddNewDevice() { + TODO("not yet!? implemented") + } + + override fun onShareToDevice(device: Device) { + TODO("not yet!? implemented") + } + + override fun onShareToAllDevices(devices: List) { + TODO("not yet!? implemented") + } + + override fun onShareToApp(appToShareTo: Application) { + TODO("not yet!? implemented") + } +} diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareToAccountDevicesView.kt b/app/src/main/java/org/mozilla/fenix/share/ShareToAccountDevicesView.kt new file mode 100644 index 000000000..bdd510958 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/ShareToAccountDevicesView.kt @@ -0,0 +1,31 @@ +/* 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.share + +import android.view.LayoutInflater +import android.view.ViewGroup +import kotlinx.android.extensions.LayoutContainer +import mozilla.components.concept.sync.Device +import org.mozilla.fenix.R + +/** + * Callbacks for possible user interactions on the [ShareToAccountDevicesView] + */ +interface ShareToAccountDevicesInteractor { + fun onSignIn() + fun onAddNewDevice() + fun onShareToDevice(device: Device) + fun onShareToAllDevices(devices: List) +} + +class ShareToAccountDevicesView( + override val containerView: ViewGroup, + private val interactor: ShareToAccountDevicesInteractor +) : LayoutContainer { + init { + LayoutInflater.from(containerView.context) + .inflate(R.layout.share_to_account_devices, containerView, true) + } +} diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareToAppsView.kt b/app/src/main/java/org/mozilla/fenix/share/ShareToAppsView.kt new file mode 100644 index 000000000..39aeb1f58 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/ShareToAppsView.kt @@ -0,0 +1,28 @@ +/* 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.share + +import android.view.LayoutInflater +import android.view.ViewGroup +import kotlinx.android.extensions.LayoutContainer +import org.mozilla.fenix.R +import org.mozilla.fenix.share.listadapters.Application + +/** + * Callbacks for possible user interactions on the [ShareCloseView] + */ +interface ShareToAppsInteractor { + fun onShareToApp(appToShareTo: Application) +} + +class ShareToAppsView( + override val containerView: ViewGroup, + private val interactor: ShareToAppsInteractor +) : LayoutContainer { + init { + LayoutInflater.from(containerView.context) + .inflate(R.layout.share_to_apps, containerView, true) + } +} diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareUIView.kt b/app/src/main/java/org/mozilla/fenix/share/ShareUIView.kt deleted file mode 100644 index 30cf3a79f..000000000 --- a/app/src/main/java/org/mozilla/fenix/share/ShareUIView.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* 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.share - -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import io.reactivex.Observable -import io.reactivex.Observer -import io.reactivex.functions.Consumer -import kotlinx.android.synthetic.main.component_share.* -import org.mozilla.fenix.R -import org.mozilla.fenix.ext.components -import org.mozilla.fenix.mvi.UIView - -class ShareUIView( - container: ViewGroup, - actionEmitter: Observer, - changesObservable: Observable -) : UIView( - container, - actionEmitter, - changesObservable -) { - override val view: View = LayoutInflater.from(container.context) - .inflate(R.layout.component_share, container, true) - - init { - val adapter = AppShareAdapter(view.context, actionEmitter).also { - it.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { - override fun onChanged() { - progressBar.visibility = View.GONE - appsList.visibility = View.VISIBLE - } - }) - } - appsList.adapter = adapter - - if (view.context.components.backgroundServices.accountManager.accountNeedsReauth()) { - sendTabGroup.visibility = View.GONE - accountHeaderText.visibility = View.GONE - } else { - devicesList.adapter = AccountDevicesShareAdapter(view.context, actionEmitter) - } - - container.setOnClickListener { actionEmitter.onNext(ShareAction.Close) } - closeButton.setOnClickListener { actionEmitter.onNext(ShareAction.Close) } - } - - override fun updateView() = Consumer { - ShareState - } -} diff --git a/app/src/main/java/org/mozilla/fenix/share/listadapters/AccountDevicesAdapter.kt b/app/src/main/java/org/mozilla/fenix/share/listadapters/AccountDevicesAdapter.kt new file mode 100644 index 000000000..215f51f07 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/listadapters/AccountDevicesAdapter.kt @@ -0,0 +1,45 @@ +/* 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.share.listadapters + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import mozilla.components.concept.sync.Device +import org.mozilla.fenix.share.ShareToAccountDevicesInteractor +import org.mozilla.fenix.share.viewholders.AccountDeviceViewHolder + +class AccountDevicesShareAdapter( + private val interactor: ShareToAccountDevicesInteractor, + private val devices: MutableList = mutableListOf() +) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AccountDeviceViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(AccountDeviceViewHolder.LAYOUT_ID, parent, false) + + return AccountDeviceViewHolder(view, interactor) + } + + override fun getItemCount(): Int = devices.size + + override fun onBindViewHolder(holder: AccountDeviceViewHolder, position: Int) { + holder.bind(devices[position]) + } + + fun updateData(deviceOptions: List) { + this.devices.clear() + this.devices.addAll(deviceOptions) + notifyDataSetChanged() + } +} + +sealed class SyncShareOption { + object SignIn : SyncShareOption() + object AddNewDevice : SyncShareOption() + data class SendAll(val devices: List) : SyncShareOption() + data class Mobile(val name: String, val device: Device) : SyncShareOption() + data class Desktop(val name: String, val device: Device) : SyncShareOption() +} diff --git a/app/src/main/java/org/mozilla/fenix/share/listadapters/AppShareAdapter.kt b/app/src/main/java/org/mozilla/fenix/share/listadapters/AppShareAdapter.kt new file mode 100644 index 000000000..e2584983c --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/listadapters/AppShareAdapter.kt @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.share.listadapters + +import android.graphics.drawable.Drawable +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import org.mozilla.fenix.share.ShareToAppsInteractor +import org.mozilla.fenix.share.viewholders.AppViewHolder + +class AppShareAdapter( + private val interactor: ShareToAppsInteractor, + private val applications: MutableList = mutableListOf() +) : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(AppViewHolder.LAYOUT_ID, parent, false) + + return AppViewHolder(view, interactor) + } + + override fun getItemCount(): Int = applications.size + + override fun onBindViewHolder(holder: AppViewHolder, position: Int) { + holder.bind(applications[position]) + } + + fun updateData(applications: List) { + this.applications.clear() + this.applications.addAll(applications) + notifyDataSetChanged() + } +} + +data class AppShareOption( + val name: String, + val icon: Drawable, + val packageName: String, + val activityName: String +) diff --git a/app/src/main/java/org/mozilla/fenix/share/viewholders/AccountDeviceViewHolder.kt b/app/src/main/java/org/mozilla/fenix/share/viewholders/AccountDeviceViewHolder.kt new file mode 100644 index 000000000..de61568db --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/viewholders/AccountDeviceViewHolder.kt @@ -0,0 +1,82 @@ +/* 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.share.viewholders + +import android.content.Context +import android.graphics.PorterDuff +import android.view.View +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.account_share_list_item.view.* +import org.mozilla.fenix.R +import org.mozilla.fenix.lib.Do +import org.mozilla.fenix.share.ShareToAccountDevicesInteractor +import org.mozilla.fenix.share.listadapters.SyncShareOption + +class AccountDeviceViewHolder( + itemView: View, + private val interactor: ShareToAccountDevicesInteractor +) : RecyclerView.ViewHolder(itemView) { + + private val context: Context = itemView.context + + fun bind(option: SyncShareOption) { + bindClickListeners(option) + bindView(option) + } + + private fun bindClickListeners(option: SyncShareOption) { + itemView.setOnClickListener { + Do exhaustive when (option) { + SyncShareOption.SignIn -> interactor.onSignIn() + SyncShareOption.AddNewDevice -> interactor.onAddNewDevice() + is SyncShareOption.SendAll -> interactor.onShareToAllDevices(option.devices) + is SyncShareOption.Mobile -> interactor.onShareToDevice(option.device) + is SyncShareOption.Desktop -> interactor.onShareToDevice(option.device) + } + } + } + + private fun bindView(option: SyncShareOption) { + val (name, drawableRes, colorRes) = when (option) { + SyncShareOption.SignIn -> Triple( + context.getText(R.string.sync_sign_in), + R.drawable.mozac_ic_sync, + R.color.default_share_background + ) + SyncShareOption.AddNewDevice -> Triple( + context.getText(R.string.sync_connect_device), + R.drawable.mozac_ic_new, + R.color.default_share_background + ) + is SyncShareOption.SendAll -> Triple( + context.getText(R.string.sync_send_to_all), + R.drawable.mozac_ic_select_all, + R.color.default_share_background + ) + is SyncShareOption.Mobile -> Triple( + option.name, + R.drawable.mozac_ic_device_mobile, + R.color.device_type_mobile_background + ) + is SyncShareOption.Desktop -> Triple( + option.name, + R.drawable.mozac_ic_device_desktop, + R.color.device_type_desktop_background + ) + } + + itemView.deviceIcon.apply { + setImageResource(drawableRes) + background.setColorFilter(ContextCompat.getColor(context, colorRes), PorterDuff.Mode.SRC_IN) + drawable.setTint(ContextCompat.getColor(context, R.color.device_foreground)) + } + itemView.deviceName.text = name + } + + companion object { + const val LAYOUT_ID = R.layout.account_share_list_item + } +} diff --git a/app/src/main/java/org/mozilla/fenix/share/viewholders/AppViewHolder.kt b/app/src/main/java/org/mozilla/fenix/share/viewholders/AppViewHolder.kt new file mode 100644 index 000000000..1e2423182 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/viewholders/AppViewHolder.kt @@ -0,0 +1,38 @@ +/* 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.share.viewholders + +import android.view.View +import androidx.recyclerview.widget.RecyclerView +import kotlinx.android.synthetic.main.app_share_list_item.view.* +import org.mozilla.fenix.R +import org.mozilla.fenix.share.ShareToAppsInteractor +import org.mozilla.fenix.share.listadapters.AppShareOption + +class AppViewHolder( + itemView: View, + interactor: ShareToAppsInteractor +) : RecyclerView.ViewHolder(itemView) { + + private var application: AppShareOption? = null + + init { + itemView.setOnClickListener { + application?.let { application -> + interactor.onShareToApp(application) + } + } + } + + fun bind(item: AppShareOption) { + application = item + itemView.appName.text = item.name + itemView.appIcon.setImageDrawable(item.icon) + } + + companion object { + const val LAYOUT_ID = R.layout.app_share_list_item + } +} diff --git a/app/src/main/res/layout/component_share.xml b/app/src/main/res/layout/component_share.xml deleted file mode 100644 index b9b7448c4..000000000 --- a/app/src/main/res/layout/component_share.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_share.xml b/app/src/main/res/layout/fragment_share.xml index aaf2e58d4..21fa1c3f7 100644 --- a/app/src/main/res/layout/fragment_share.xml +++ b/app/src/main/res/layout/fragment_share.xml @@ -3,12 +3,57 @@ - 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/. --> - + tools:context="org.mozilla.fenix.share.ShareFragment"> + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/share_close.xml b/app/src/main/res/layout/share_close.xml new file mode 100644 index 000000000..e79bcee1a --- /dev/null +++ b/app/src/main/res/layout/share_close.xml @@ -0,0 +1,24 @@ + + + + diff --git a/app/src/main/res/layout/share_to_account_devices.xml b/app/src/main/res/layout/share_to_account_devices.xml new file mode 100644 index 000000000..61cde4059 --- /dev/null +++ b/app/src/main/res/layout/share_to_account_devices.xml @@ -0,0 +1,41 @@ + + + + + + + + + + diff --git a/app/src/main/res/layout/share_to_apps.xml b/app/src/main/res/layout/share_to_apps.xml new file mode 100644 index 000000000..b21e0a446 --- /dev/null +++ b/app/src/main/res/layout/share_to_apps.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + +