diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareController.kt b/app/src/main/java/org/mozilla/fenix/share/ShareController.kt new file mode 100644 index 000000000..c3686d119 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/share/ShareController.kt @@ -0,0 +1,104 @@ +/* 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.Intent +import android.content.Intent.ACTION_SEND +import android.content.Intent.EXTRA_TEXT +import android.content.Intent.FLAG_ACTIVITY_NEW_TASK +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.Fragment +import androidx.navigation.NavController +import mozilla.components.concept.sync.Device +import mozilla.components.concept.sync.DeviceEventOutgoing +import mozilla.components.concept.sync.OAuthAccount +import org.mozilla.fenix.R +import org.mozilla.fenix.ext.nav +import org.mozilla.fenix.share.listadapters.AppShareOption + +/** + * [ShareFragment] controller. + * + * Delegated by View Interactors, handles container business logic and operates changes on it. + */ +interface ShareController { + fun handleShareClosed() + fun handleShareToApp(app: AppShareOption) + fun handleAddNewDevice() + fun handleShareToDevice(device: Device) + fun handleShareToAllDevices(devices: List) + fun handleSignIn() +} + +/** + * Default behavior of [ShareController]. Other implementations are possible. + * + * @param fragment the [ShareFragment] instance this controller handles business logic for. + * @param tabs the list of [ShareTab]s that can be shared. + * @param account the [OAuthAccount] to which tabs can be shared. + * @param navController - [NavController] used for navigation. + * @param dismiss - callback signalling sharing can be closed. + */ +class DefaultShareController( + private val fragment: Fragment, + private val tabs: List, + private val account: OAuthAccount?, + private val navController: NavController, + private val dismiss: () -> Unit +) : ShareController { + override fun handleShareClosed() { + dismiss() + } + + override fun handleShareToApp(app: AppShareOption) { + val shareText = tabs.joinToString("\n") { tab -> tab.url } + + val intent = Intent(ACTION_SEND).apply { + putExtra(EXTRA_TEXT, shareText) + type = "text/plain" + flags = FLAG_ACTIVITY_NEW_TASK + setClassName(app.packageName, app.activityName) + } + fragment.startActivity(intent) + dismiss() + } + + override fun handleAddNewDevice() { + AlertDialog.Builder(fragment.requireContext()).apply { + setMessage(R.string.sync_connect_device_dialog) + setPositiveButton(R.string.sync_confirmation_button) { dialog, _ -> dialog.cancel() } + create() + }.show() + } + + override fun handleShareToDevice(device: Device) { + sendTab(device.id) + (fragment.activity as ShareFragment.TabsSharedCallback).onTabsShared(tabs.size) + dismiss() + } + + override fun handleShareToAllDevices(devices: List) { + devices.forEach { device -> sendTab(device.id) } + (fragment.activity as ShareFragment.TabsSharedCallback).onTabsShared(tabs.size) + dismiss() + } + + override fun handleSignIn() { + val directions = ShareFragmentDirections.actionShareFragmentToTurnOnSyncFragment() + navController.nav(R.id.shareFragment, directions) + dismiss() + } + + private fun sendTab(deviceId: String) { + account?.run { + tabs.forEach { tab -> + deviceConstellation().sendEventToDeviceAsync( + deviceId, + DeviceEventOutgoing.SendTab(tab.title, tab.url) + ) + } + } + } +} 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 c679bbba6..ce3efbfcc 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt @@ -16,6 +16,7 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatDialogFragment import androidx.lifecycle.lifecycleScope +import androidx.navigation.fragment.findNavController import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_share.view.* import kotlinx.coroutines.Deferred @@ -27,6 +28,7 @@ import mozilla.components.concept.sync.DeviceType import mozilla.components.service.fxa.manager.FxaAccountManager import org.mozilla.fenix.R import org.mozilla.fenix.ext.components +import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.share.listadapters.AppShareOption import org.mozilla.fenix.share.listadapters.SyncShareOption @@ -79,8 +81,17 @@ class ShareFragment : AppCompatDialogFragment() { } val tabs = args.tabs?.toList() ?: listOf(ShareTab(args.url!!, args.title ?: "")) + val account = requireComponents.backgroundServices.accountManager.authenticatedAccount() - shareInteractor = ShareInteractor() + shareInteractor = ShareInteractor( + DefaultShareController( + fragment = this, + tabs = tabs, + navController = findNavController(), + account = account, + dismiss = ::dismiss + ) + ) if (isSharingToDevicesAvailable(requireContext().applicationContext)) { shareToAccountDevicesView = ShareToAccountDevicesView(view.devicesShareLayout, shareInteractor) diff --git a/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt b/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt index d80e3a3b6..902508bb6 100644 --- a/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt +++ b/app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt @@ -10,28 +10,30 @@ import org.mozilla.fenix.share.listadapters.AppShareOption /** * Interactor for the share screen. */ -class ShareInteractor : ShareCloseInteractor, ShareToAccountDevicesInteractor, ShareToAppsInteractor { +class ShareInteractor( + private val controller: ShareController +) : ShareCloseInteractor, ShareToAccountDevicesInteractor, ShareToAppsInteractor { override fun onShareClosed() { - TODO("not yet!? implemented") + controller.handleShareClosed() } override fun onSignIn() { - TODO("not yet!? implemented") + controller.handleSignIn() } override fun onAddNewDevice() { - TODO("not yet!? implemented") + controller.handleAddNewDevice() } override fun onShareToDevice(device: Device) { - TODO("not yet!? implemented") + controller.handleShareToDevice(device) } override fun onShareToAllDevices(devices: List) { - TODO("not yet!? implemented") + controller.handleShareToAllDevices(devices) } override fun onShareToApp(appToShareTo: AppShareOption) { - TODO("not yet!? implemented") + controller.handleShareToApp(appToShareTo) } }