ShareFragment.kt 5.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
package org.mozilla.fenix.share

/* 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/. */

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
12
import android.os.Parcelable
13
import android.view.ContextThemeWrapper
14
15
16
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
17
import androidx.appcompat.app.AlertDialog
18
import androidx.appcompat.app.AppCompatDialogFragment
19
import kotlinx.android.parcel.Parcelize
20
21
22
23
import kotlinx.android.synthetic.main.fragment_share.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
24
import mozilla.components.concept.sync.DeviceEventOutgoing
25
import mozilla.components.concept.sync.OAuthAccount
26
27
import org.mozilla.fenix.FenixViewModelProvider
import org.mozilla.fenix.R
28
import org.mozilla.fenix.ext.nav
29
30
31
32
33
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.getAutoDisposeObservable
import kotlin.coroutines.CoroutineContext

34
class ShareFragment : AppCompatDialogFragment(), CoroutineScope {
35
36
37
38
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main + job
    private lateinit var job: Job
    private lateinit var component: ShareComponent
39
    private var tabs: Array<ShareTab> = emptyArray()
40
41
42

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
43
        setStyle(STYLE_NO_TITLE, R.style.ShareDialogStyle)
44
45
46
47
48
49
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view = inflater.inflate(R.layout.fragment_share, container, false)
        val args = ShareFragmentArgs.fromBundle(arguments!!)

50
51
52
53
        if (args.url == null && args.tabs.isNullOrEmpty()) {
            throw IllegalStateException("URL and tabs cannot both be null.")
        }

54
        job = Job()
55
56
        tabs = args.tabs ?: arrayOf(ShareTab(args.url!!, args.title ?: ""))

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
        component = ShareComponent(
            view.share_wrapper,
            ActionBusFactory.get(this),
            FenixViewModelProvider.create(
                this,
                ShareUIViewModel::class.java
            ) {
                ShareUIViewModel(ShareState)
            }
        )

        return view
    }

    override fun onResume() {
        super.onResume()
        subscribeToActions()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        job.cancel()
    }

81
    @SuppressWarnings("ComplexMethod")
82
83
84
85
86
87
    private fun subscribeToActions() {
        getAutoDisposeObservable<ShareAction>().subscribe {
            when (it) {
                ShareAction.Close -> {
                    dismiss()
                }
88
89
                ShareAction.SignInClicked -> {
                    val directions = ShareFragmentDirections.actionShareFragmentToTurnOnSyncFragment()
90
                    nav(R.id.shareFragment, directions)
91
                    dismiss()
92
                }
93
                ShareAction.AddNewDeviceClicked -> {
94
95
96
97
98
99
100
101
102
103
                    AlertDialog.Builder(
                        ContextThemeWrapper(
                            context,
                            R.style.DialogStyle
                        )
                    ).apply {
                        setMessage(R.string.sync_connect_device_dialog)
                        setPositiveButton(R.string.sync_confirmation_button) { dialog, _ -> dialog.cancel() }
                        create()
                    }.show()
104
105
106
107
                }
                is ShareAction.ShareDeviceClicked -> {
                    val authAccount = requireComponents.backgroundServices.accountManager.authenticatedAccount()
                    authAccount?.run {
108
                        sendSendTab(this, it.device.id, tabs)
109
                    }
110
                    dismiss()
111
112
113
114
115
                }
                is ShareAction.SendAllClicked -> {
                    val authAccount = requireComponents.backgroundServices.accountManager.authenticatedAccount()
                    authAccount?.run {
                        it.devices.forEach { device ->
116
                            sendSendTab(this, device.id, tabs)
117
118
                        }
                    }
119
                    dismiss()
120
                }
121
                is ShareAction.ShareAppClicked -> {
122
123
124

                    val shareText = tabs.joinToString("\n") { tab -> tab.url }

125
                    val intent = Intent(ACTION_SEND).apply {
126
                        putExtra(EXTRA_TEXT, shareText)
127
128
                        type = "text/plain"
                        flags = FLAG_ACTIVITY_NEW_TASK
129
                        setClassName(it.item.packageName, it.item.activityName)
130
131
                    }
                    startActivity(intent)
132
                    dismiss()
133
134
135
136
                }
            }
        }
    }
137
138
139
140
141
142
143
144
145
146
147

    private fun sendSendTab(account: OAuthAccount, deviceId: String, tabs: Array<ShareTab>) {
        account.run {
            tabs.forEach { tab ->
                deviceConstellation().sendEventToDeviceAsync(
                    deviceId,
                    DeviceEventOutgoing.SendTab(tab.title, tab.url)
                )
            }
        }
    }
148
}
149
150
151

@Parcelize
data class ShareTab(val url: String, val title: String, val sessionId: String? = null) : Parcelable