Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Matthew Finkel
fenix
Commits
333ff8c9
Commit
333ff8c9
authored
Nov 04, 2019
by
Tiger Oakes
Committed by
Emily Kager
Nov 14, 2019
Browse files
Fixes #4528 - Prevent share menu from jumping
Plus a bunch of docs and refactoring
parent
6b9a0d02
Changes
17
Hide whitespace changes
Inline
Side-by-side
app/src/main/java/org/mozilla/fenix/share/AddNewDeviceFragment.kt
View file @
333ff8c9
...
...
@@ -13,6 +13,9 @@ import kotlinx.android.synthetic.main.fragment_add_new_device.*
import
org.mozilla.fenix.R
import
org.mozilla.fenix.settings.SupportUtils
/**
* Fragment to add a new device. Tabs can be shared to devices after they are added.
*/
class
AddNewDeviceFragment
:
Fragment
(
R
.
layout
.
fragment_add_new_device
)
{
override
fun
onResume
()
{
...
...
app/src/main/java/org/mozilla/fenix/share/ShareCloseView.kt
View file @
333ff8c9
...
...
@@ -23,6 +23,7 @@ class ShareCloseView(
override
val
containerView
:
ViewGroup
,
private
val
interactor
:
ShareCloseInteractor
)
:
LayoutContainer
{
val
adapter
=
ShareTabsAdapter
()
init
{
...
...
@@ -36,6 +37,6 @@ class ShareCloseView(
}
fun
setTabs
(
tabs
:
List
<
ShareTab
>)
{
adapter
.
s
etTabs
(
tabs
)
adapter
.
s
ubmitList
(
tabs
)
}
}
app/src/main/java/org/mozilla/fenix/share/ShareController.kt
View file @
333ff8c9
...
...
@@ -26,7 +26,7 @@ import org.mozilla.fenix.components.metrics.Event
import
org.mozilla.fenix.ext.getRootView
import
org.mozilla.fenix.ext.metrics
import
org.mozilla.fenix.ext.nav
import
org.mozilla.fenix.share.listadapters.A
pp
ShareOption
import
org.mozilla.fenix.share.listadapters.A
ndroid
ShareOption
/**
* [ShareFragment] controller.
...
...
@@ -36,7 +36,7 @@ import org.mozilla.fenix.share.listadapters.AppShareOption
interface
ShareController
{
fun
handleReauth
()
fun
handleShareClosed
()
fun
handleShareToApp
(
app
:
A
pp
ShareOption
)
fun
handleShareToApp
(
app
:
A
ndroid
ShareOption
.
App
)
fun
handleAddNewDevice
()
fun
handleShareToDevice
(
device
:
Device
)
fun
handleShareToAllDevices
(
devices
:
List
<
Device
>)
...
...
@@ -72,7 +72,7 @@ class DefaultShareController(
dismiss
()
}
override
fun
handleShareToApp
(
app
:
A
pp
ShareOption
)
{
override
fun
handleShareToApp
(
app
:
A
ndroid
ShareOption
.
App
)
{
val
intent
=
Intent
(
ACTION_SEND
).
apply
{
putExtra
(
EXTRA_TEXT
,
getShareText
())
type
=
"text/plain"
...
...
@@ -116,9 +116,10 @@ class DefaultShareController(
private
fun
shareToDevicesWithRetry
(
shareOperation
:
()
->
Deferred
<
Boolean
>)
{
// Use GlobalScope to allow the continuation of this method even if the share fragment is closed.
GlobalScope
.
launch
(
Dispatchers
.
Main
)
{
when
(
shareOperation
.
invoke
().
await
())
{
true
->
showSuccess
()
false
->
showFailureWithRetryOption
{
shareToDevicesWithRetry
(
shareOperation
)
}
if
(
shareOperation
.
invoke
().
await
())
{
showSuccess
()
}
else
{
showFailureWithRetryOption
{
shareToDevicesWithRetry
(
shareOperation
)
}
}
dismiss
()
}
...
...
app/src/main/java/org/mozilla/fenix/share/ShareFragment.kt
View file @
333ff8c9
...
...
@@ -17,17 +17,19 @@ import android.os.Parcelable
import
android.view.LayoutInflater
import
android.view.View
import
android.view.ViewGroup
import
androidx.annotation.WorkerThread
import
androidx.appcompat.app.AppCompatDialogFragment
import
androidx.core.content.getSystemService
import
androidx.lifecycle.lifecycleScope
import
androidx.navigation.fragment.findNavController
import
androidx.navigation.fragment.navArgs
import
kotlinx.android.parcel.Parcelize
import
kotlinx.android.synthetic.main.fragment_share.view.*
import
kotlinx.coroutines.Deferred
import
kotlinx.coroutines.Dispatchers
import
kotlinx.coroutines.Dispatchers
.IO
import
kotlinx.coroutines.async
import
kotlinx.coroutines.launch
import
mozilla.components.concept.sync.DeviceCapability
import
mozilla.components.concept.sync.DeviceType
import
mozilla.components.feature.sendtab.SendTabUseCases
import
mozilla.components.service.fxa.manager.FxaAccountManager
import
org.mozilla.fenix.R
...
...
@@ -35,7 +37,7 @@ import org.mozilla.fenix.components.FenixSnackbarPresenter
import
org.mozilla.fenix.ext.components
import
org.mozilla.fenix.ext.getRootView
import
org.mozilla.fenix.ext.requireComponents
import
org.mozilla.fenix.share.listadapters.A
pp
ShareOption
import
org.mozilla.fenix.share.listadapters.A
ndroid
ShareOption
import
org.mozilla.fenix.share.listadapters.SyncShareOption
@Suppress
(
"TooManyFunctions"
)
...
...
@@ -44,20 +46,39 @@ class ShareFragment : AppCompatDialogFragment() {
private
lateinit
var
shareCloseView
:
ShareCloseView
private
lateinit
var
shareToAccountDevicesView
:
ShareToAccountDevicesView
private
lateinit
var
shareToAppsView
:
ShareToAppsView
private
lateinit
var
appsListDeferred
:
Deferred
<
List
<
A
pp
ShareOption
>>
private
lateinit
var
appsListDeferred
:
Deferred
<
List
<
A
ndroid
ShareOption
>>
private
lateinit
var
devicesListDeferred
:
Deferred
<
List
<
SyncShareOption
>>
private
var
connectivityManager
:
ConnectivityManager
?
=
null
private
val
networkCallback
=
object
:
ConnectivityManager
.
NetworkCallback
()
{
override
fun
onLost
(
network
:
Network
?)
=
reloadDevices
()
override
fun
onAvailable
(
network
:
Network
?)
=
reloadDevices
()
private
fun
reloadDevices
()
{
context
?.
let
{
context
->
val
fxaAccountManager
=
context
.
components
.
backgroundServices
.
accountManager
lifecycleScope
.
launch
{
fxaAccountManager
.
authenticatedAccount
()
?.
deviceConstellation
()
?.
refreshDevicesAsync
()
?.
await
()
val
devicesShareOptions
=
buildDeviceList
(
fxaAccountManager
)
shareToAccountDevicesView
.
setShareTargets
(
devicesShareOptions
)
}
}
}
}
override
fun
onAttach
(
context
:
Context
)
{
super
.
onAttach
(
context
)
connectivityManager
=
context
.
getSystemService
(
Context
.
CONNECTIVITY_SERVICE
)
as
?
ConnectivityManager
connectivityManager
=
context
.
getSystemService
()
val
networkRequest
=
NetworkRequest
.
Builder
().
build
()
connectivityManager
?.
registerNetworkCallback
(
networkRequest
,
networkCallback
)
// Start preparing the data as soon as we have a valid Context
appsListDeferred
=
lifecycleScope
.
async
(
Dispatchers
.
IO
)
{
appsListDeferred
=
lifecycleScope
.
async
(
IO
)
{
val
shareIntent
=
Intent
(
ACTION_SEND
).
apply
{
type
=
"text/plain"
flags
=
FLAG_ACTIVITY_NEW_TASK
...
...
@@ -66,53 +87,29 @@ class ShareFragment : AppCompatDialogFragment() {
buildAppsList
(
shareAppsActivities
,
context
)
}
devicesListDeferred
=
lifecycleScope
.
async
(
Dispatchers
.
IO
)
{
devicesListDeferred
=
lifecycleScope
.
async
(
IO
)
{
val
fxaAccountManager
=
context
.
components
.
backgroundServices
.
accountManager
buildDeviceList
(
fxaAccountManager
)
}
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setStyle
(
STYLE_NO_TITLE
,
R
.
style
.
ShareDialogStyle
)
}
private
val
networkCallback
=
object
:
ConnectivityManager
.
NetworkCallback
()
{
override
fun
onLost
(
network
:
Network
?)
{
reloadDevices
()
}
override
fun
onAvailable
(
network
:
Network
?)
{
reloadDevices
()
}
}
private
fun
reloadDevices
()
{
context
?.
let
{
val
fxaAccountManager
=
it
.
components
.
backgroundServices
.
accountManager
lifecycleScope
.
launch
{
val
refreshDevicesAsync
=
fxaAccountManager
.
authenticatedAccount
()
?.
deviceConstellation
()
?.
refreshDevicesAsync
()
refreshDevicesAsync
?.
await
()
val
devicesShareOptions
=
buildDeviceList
(
fxaAccountManager
)
shareToAccountDevicesView
.
setSharetargets
(
devicesShareOptions
)
}
}
}
override
fun
onDetach
()
{
connectivityManager
?.
unregisterNetworkCallback
(
networkCallback
)
super
.
onDetach
()
}
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setStyle
(
STYLE_NO_TITLE
,
R
.
style
.
ShareDialogStyle
)
}
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
!!
)
val
args
by
navArgs
<
ShareFragmentArgs
>(
)
check
(!(
args
.
url
==
null
&&
args
.
tabs
.
isNullOrEmpty
()))
{
"URL and tabs cannot both be null."
}
val
tabs
=
args
.
tabs
?.
toList
()
?:
listOf
(
ShareTab
(
args
.
url
!!
,
args
.
title
.
orEmpty
()))
...
...
@@ -153,74 +150,84 @@ class ShareFragment : AppCompatDialogFragment() {
override
fun
onViewCreated
(
view
:
View
,
savedInstanceState
:
Bundle
?)
{
super
.
onViewCreated
(
view
,
savedInstanceState
)
// Start with some invisible views so the share menu height doesn't jump later
shareToAppsView
.
setShareTargets
(
listOf
(
AndroidShareOption
.
Invisible
,
AndroidShareOption
.
Invisible
)
)
lifecycleScope
.
launch
{
val
devicesShareOptions
=
devicesListDeferred
.
await
()
shareToAccountDevicesView
.
setShare
t
argets
(
devicesShareOptions
)
shareToAccountDevicesView
.
setShare
T
argets
(
devicesShareOptions
)
val
appsToShareTo
=
appsListDeferred
.
await
()
shareToAppsView
.
setShareTargets
(
appsToShareTo
)
}
}
@WorkerThread
private
fun
getIntentActivities
(
shareIntent
:
Intent
,
context
:
Context
):
List
<
ResolveInfo
>?
{
return
context
.
packageManager
.
queryIntentActivities
(
shareIntent
,
0
)
}
/**
* Returns a list of apps that can be shared to.
* @param intentActivities List of activities from [getIntentActivities].
*/
@WorkerThread
private
fun
buildAppsList
(
intentActivities
:
List
<
ResolveInfo
>?,
context
:
Context
):
List
<
AppShareOption
>
{
return
intentActivities
?.
map
{
resolveInfo
->
AppShareOption
(
resolveInfo
.
loadLabel
(
context
.
packageManager
).
toString
(),
resolveInfo
.
loadIcon
(
context
.
packageManager
),
resolveInfo
.
activityInfo
.
packageName
,
resolveInfo
.
activityInfo
.
name
)
}
?.
filter
{
it
.
packageName
!=
context
.
packageName
}.
orEmpty
()
):
List
<
AndroidShareOption
>
{
return
intentActivities
.
orEmpty
()
.
filter
{
it
.
activityInfo
.
packageName
!=
context
.
packageName
}
.
map
{
resolveInfo
->
AndroidShareOption
.
App
(
resolveInfo
.
loadLabel
(
context
.
packageManager
).
toString
(),
resolveInfo
.
loadIcon
(
context
.
packageManager
),
resolveInfo
.
activityInfo
.
packageName
,
resolveInfo
.
activityInfo
.
name
)
}
}
@Suppress
(
"ReturnCount"
)
/**
* Builds list of options to display in the top row of the share sheet.
* This will primarily include devices that tabs can be sent to, but also options
* for reconnecting the account or sending to all devices.
*/
private
fun
buildDeviceList
(
accountManager
:
FxaAccountManager
):
List
<
SyncShareOption
>
{
val
list
=
mutableListOf
<
SyncShareOption
>()
val
activeNetwork
=
connectivityManager
?.
activeNetworkInfo
if
(
activeNetwork
?.
isConnected
!=
true
)
{
list
.
add
(
SyncShareOption
.
Offline
)
return
list
}
if
(
accountManager
.
authenticatedAccount
()
==
null
)
{
list
.
add
(
SyncShareOption
.
SignIn
)
return
list
}
if
(
accountManager
.
accountNeedsReauth
())
{
list
.
add
(
SyncShareOption
.
Reconnect
)
return
list
}
accountManager
.
authenticatedAccount
()
?.
deviceConstellation
()
?.
state
()
?.
otherDevices
?.
let
{
devices
->
val
shareableDevices
=
devices
.
filter
{
it
.
capabilities
.
contains
(
DeviceCapability
.
SEND_TAB
)
}
val
account
=
accountManager
.
authenticatedAccount
()
return
when
{
// No network
activeNetwork
?.
isConnected
!=
true
->
listOf
(
SyncShareOption
.
Offline
)
// No account signed in
account
==
null
->
listOf
(
SyncShareOption
.
SignIn
)
// Account needs to be re-authenticated
accountManager
.
accountNeedsReauth
()
->
listOf
(
SyncShareOption
.
Reconnect
)
// Signed in
else
->
{
val
shareableDevices
=
account
.
deviceConstellation
().
state
()
?.
otherDevices
.
orEmpty
()
.
filter
{
it
.
capabilities
.
contains
(
DeviceCapability
.
SEND_TAB
)
}
val
list
=
mutableListOf
<
SyncShareOption
>()
if
(
shareableDevices
.
isEmpty
())
{
// Show add device button if there are no devices
list
.
add
(
SyncShareOption
.
AddNewDevice
)
}
if
(
shareableDevices
.
isEmpty
())
{
list
.
add
(
SyncShareOption
.
AddNewDevice
)
}
shareableDevices
.
mapTo
(
list
)
{
SyncShareOption
.
SingleDevice
(
it
)
}
val
shareOptions
=
shareableDevices
.
map
{
when
(
it
.
deviceType
)
{
DeviceType
.
MOBILE
->
SyncShareOption
.
Mobile
(
it
.
displayName
,
it
)
else
->
SyncShareOption
.
Desktop
(
it
.
displayName
,
it
)
if
(
shareableDevices
.
size
>
1
)
{
// Show send all button if there are multiple devices
list
.
add
(
SyncShareOption
.
SendAll
(
shareableDevices
))
}
}
list
.
addAll
(
shareOptions
)
if
(
shareableDevices
.
size
>
1
)
{
list
.
add
(
SyncShareOption
.
SendAll
(
shareableDevices
))
list
}
}
return
list
}
companion
object
{
...
...
app/src/main/java/org/mozilla/fenix/share/ShareInteractor.kt
View file @
333ff8c9
...
...
@@ -5,7 +5,7 @@
package
org.mozilla.fenix.share
import
mozilla.components.concept.sync.Device
import
org.mozilla.fenix.share.listadapters.A
pp
ShareOption
import
org.mozilla.fenix.share.listadapters.A
ndroid
ShareOption
/**
* Interactor for the share screen.
...
...
@@ -37,7 +37,7 @@ class ShareInteractor(
controller
.
handleShareToAllDevices
(
devices
)
}
override
fun
onShareToApp
(
appToShareTo
:
A
pp
ShareOption
)
{
override
fun
onShareToApp
(
appToShareTo
:
A
ndroid
ShareOption
.
App
)
{
controller
.
handleShareToApp
(
appToShareTo
)
}
}
app/src/main/java/org/mozilla/fenix/share/ShareToAccountDevicesView.kt
View file @
333ff8c9
...
...
@@ -26,18 +26,19 @@ interface ShareToAccountDevicesInteractor {
class
ShareToAccountDevicesView
(
override
val
containerView
:
ViewGroup
,
private
val
interactor
:
ShareToAccountDevicesInteractor
interactor
:
ShareToAccountDevicesInteractor
)
:
LayoutContainer
{
private
val
adapter
=
AccountDevicesShareAdapter
(
interactor
)
init
{
LayoutInflater
.
from
(
containerView
.
context
)
.
inflate
(
R
.
layout
.
share_to_account_devices
,
containerView
,
true
)
devicesList
.
adapter
=
AccountDevicesShareAdapter
(
interactor
)
devicesList
.
adapter
=
adapter
}
fun
setSharetargets
(
targets
:
List
<
SyncShareOption
>)
{
with
(
devicesList
.
adapter
as
AccountDevicesShareAdapter
)
{
updateData
(
targets
)
}
fun
setShareTargets
(
targets
:
List
<
SyncShareOption
>)
{
adapter
.
submitList
(
targets
)
}
}
app/src/main/java/org/mozilla/fenix/share/ShareToAppsView.kt
View file @
333ff8c9
...
...
@@ -10,14 +10,14 @@ import android.view.ViewGroup
import
kotlinx.android.extensions.LayoutContainer
import
kotlinx.android.synthetic.main.share_to_apps.*
import
org.mozilla.fenix.R
import
org.mozilla.fenix.share.listadapters.AndroidShareOption
import
org.mozilla.fenix.share.listadapters.AppShareAdapter
import
org.mozilla.fenix.share.listadapters.AppShareOption
/**
* Callbacks for possible user interactions on the [ShareCloseView]
*/
interface
ShareToAppsInteractor
{
fun
onShareToApp
(
appToShareTo
:
A
pp
ShareOption
)
fun
onShareToApp
(
appToShareTo
:
A
ndroid
ShareOption
.
App
)
}
class
ShareToAppsView
(
...
...
@@ -34,7 +34,7 @@ class ShareToAppsView(
appsList
.
adapter
=
adapter
}
fun
setShareTargets
(
targets
:
List
<
A
pp
ShareOption
>)
{
fun
setShareTargets
(
targets
:
List
<
A
ndroid
ShareOption
>)
{
progressBar
.
visibility
=
View
.
GONE
appsList
.
visibility
=
View
.
VISIBLE
...
...
app/src/main/java/org/mozilla/fenix/share/listadapters/AccountDevicesAdapter.kt
View file @
333ff8c9
...
...
@@ -6,15 +6,19 @@ package org.mozilla.fenix.share.listadapters
import
android.view.LayoutInflater
import
android.view.ViewGroup
import
androidx.recyclerview.widget.RecyclerView
import
androidx.recyclerview.widget.DiffUtil
import
androidx.recyclerview.widget.ListAdapter
import
mozilla.components.concept.sync.Device
import
org.mozilla.fenix.share.ShareToAccountDevicesInteractor
import
org.mozilla.fenix.share.viewholders.AccountDeviceViewHolder
/**
* Adapter for a list of devices that can be shared to.
* May also display buttons to reconnect, add a device, or send to all devices.
*/
class
AccountDevicesShareAdapter
(
private
val
interactor
:
ShareToAccountDevicesInteractor
,
private
val
devices
:
MutableList
<
SyncShareOption
>
=
mutableListOf
()
)
:
RecyclerView
.
Adapter
<
AccountDeviceViewHolder
>()
{
private
val
interactor
:
ShareToAccountDevicesInteractor
)
:
ListAdapter
<
SyncShareOption
,
AccountDeviceViewHolder
>(
DiffCallback
)
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
AccountDeviceViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
)
...
...
@@ -23,25 +27,33 @@ class AccountDevicesShareAdapter(
return
AccountDeviceViewHolder
(
view
,
interactor
)
}
override
fun
getItemCount
():
Int
=
devices
.
size
override
fun
onBindViewHolder
(
holder
:
AccountDeviceViewHolder
,
position
:
Int
)
{
holder
.
bind
(
devices
[
position
]
)
holder
.
bind
(
getItem
(
position
)
)
}
fun
updateData
(
deviceOptions
:
List
<
SyncShareOption
>)
{
this
.
devices
.
clear
()
this
.
devices
.
addAll
(
deviceOptions
)
notifyDataSetChanged
()
private
object
DiffCallback
:
DiffUtil
.
ItemCallback
<
SyncShareOption
>()
{
override
fun
areItemsTheSame
(
oldItem
:
SyncShareOption
,
newItem
:
SyncShareOption
)
=
when
(
oldItem
)
{
is
SyncShareOption
.
SendAll
->
newItem
is
SyncShareOption
.
SendAll
is
SyncShareOption
.
SingleDevice
->
newItem
is
SyncShareOption
.
SingleDevice
&&
oldItem
.
device
.
id
==
newItem
.
device
.
id
else
->
oldItem
===
newItem
}
@Suppress
(
"DiffUtilEquals"
)
override
fun
areContentsTheSame
(
oldItem
:
SyncShareOption
,
newItem
:
SyncShareOption
)
=
oldItem
==
newItem
}
}
/**
* Different options to be displayed by [AccountDevicesShareAdapter].
*/
sealed
class
SyncShareOption
{
object
Reconnect
:
SyncShareOption
()
object
Offline
:
SyncShareOption
()
object
SignIn
:
SyncShareOption
()
object
AddNewDevice
:
SyncShareOption
()
data class
SendAll
(
val
devices
:
List
<
Device
>)
:
SyncShareOption
()
data class
Mobile
(
val
name
:
String
,
val
device
:
Device
)
:
SyncShareOption
()
data class
Desktop
(
val
name
:
String
,
val
device
:
Device
)
:
SyncShareOption
()
data class
SingleDevice
(
val
device
:
Device
)
:
SyncShareOption
()
}
app/src/main/java/org/mozilla/fenix/share/listadapters/AppShareAdapter.kt
View file @
333ff8c9
...
...
@@ -12,9 +12,12 @@ import androidx.recyclerview.widget.ListAdapter
import
org.mozilla.fenix.share.ShareToAppsInteractor
import
org.mozilla.fenix.share.viewholders.AppViewHolder
/**
* Adapter for a list of apps that can be shared to.
*/
class
AppShareAdapter
(
private
val
interactor
:
ShareToAppsInteractor
)
:
ListAdapter
<
A
pp
ShareOption
,
AppViewHolder
>(
DiffCallback
)
{
)
:
ListAdapter
<
A
ndroid
ShareOption
,
AppViewHolder
>(
DiffCallback
)
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
):
AppViewHolder
{
val
view
=
LayoutInflater
.
from
(
parent
.
context
)
...
...
@@ -26,20 +29,38 @@ class AppShareAdapter(
override
fun
onBindViewHolder
(
holder
:
AppViewHolder
,
position
:
Int
)
{
holder
.
bind
(
getItem
(
position
))
}
}
private
object
DiffCallback
:
DiffUtil
.
ItemCallback
<
AppShareOption
>()
{
override
fun
areItemsTheSame
(
oldItem
:
AppShareOption
,
newItem
:
AppShareOption
)
=
oldItem
.
packageName
==
newItem
.
packageName
private
object
DiffCallback
:
DiffUtil
.
ItemCallback
<
AndroidShareOption
>()
{
override
fun
areItemsTheSame
(
oldItem
:
AndroidShareOption
,
newItem
:
AndroidShareOption
)
=
when
(
oldItem
)
{
AndroidShareOption
.
Invisible
->
oldItem
===
newItem
is
AndroidShareOption
.
App
->
newItem
is
AndroidShareOption
.
App
&&
oldItem
.
packageName
==
newItem
.
packageName
}
override
fun
areContentsTheSame
(
oldItem
:
AppShareOption
,
newItem
:
AppShareOption
)
=
oldItem
==
newItem
@Suppress
(
"DiffUtilEquals"
)
override
fun
areContentsTheSame
(
oldItem
:
AndroidShareOption
,
newItem
:
AndroidShareOption
)
=
oldItem
==
newItem
}
}
data class
AppShareOption
(
val
name
:
String
,
val
icon
:
Drawable
,
val
packageName
:
String
,
val
activityName
:
String
)
/**
* Represents an app that can be shared to.
*/
sealed
class
AndroidShareOption
{
object
Invisible
:
AndroidShareOption
()
/**
* Represents an app that can be shared to.
*
* @property name Name of the app.
* @property icon Icon representing the share target.
* @property packageName Package of the app.
* @property activityName Activity that will be shared to.
*/
data class
App
(
val
name
:
String
,
val
icon
:
Drawable
,
val
packageName
:
String
,
val
activityName
:
String
)
:
AndroidShareOption
()
}
app/src/main/java/org/mozilla/fenix/share/listadapters/ShareTabsAdapter.kt
View file @
333ff8c9
...
...
@@ -16,8 +16,11 @@ import org.mozilla.fenix.ext.components
import
org.mozilla.fenix.ext.loadIntoView
import
org.mozilla.fenix.share.ShareTab
/**
* Adapter for a list of tabs to be shared.
*/
class
ShareTabsAdapter
:
ListAdapter
<
ShareTab
,
ShareTabsAdapter
.
ShareTabViewHolder
>(
ShareTabDiffCallback
()
)
{
ListAdapter
<
ShareTab
,
ShareTabsAdapter
.
ShareTabViewHolder
>(
ShareTabDiffCallback
)
{
override
fun
onCreateViewHolder
(
parent
:
ViewGroup
,
viewType
:
Int
)
=
ShareTabViewHolder
(
LayoutInflater
.
from
(
parent
.
context
)
...
...
@@ -27,13 +30,7 @@ class ShareTabsAdapter :
override
fun
onBindViewHolder
(
holder
:
ShareTabViewHolder
,
position
:
Int
)
=
holder
.
bind
(
getItem
(
position
))
fun
setTabs
(
tabs
:
List
<
ShareTab
>)
{
submitList
(
tabs
.
toMutableList
())
}
inner
class
ShareTabViewHolder
(
itemView
:
View
)
:
RecyclerView
.
ViewHolder
(
itemView
)
{
class
ShareTabViewHolder
(
itemView
:
View
)
:
RecyclerView
.
ViewHolder
(
itemView
)
{
fun
bind
(
item
:
ShareTab
)
=
with
(
itemView
)
{
context
.
components
.
core
.
icons
.
loadIntoView
(
itemView
.
share_tab_favicon
,
item
.
url
)
...
...
@@ -42,19 +39,11 @@ class ShareTabsAdapter :
}
}
private
class
ShareTabDiffCallback
:
DiffUtil
.
ItemCallback
<
ShareTab
>()
{
override
fun
areItemsTheSame
(
oldItem
:
ShareTab
,
newItem
:
ShareTab
):
Boolean
{
return
oldItem
.
url
==
newItem
.
url
}
private
object
ShareTabDiffCallback
:
DiffUtil
.
ItemCallback
<
ShareTab
>()
{
override
fun
areItemsTheSame
(
oldItem
:
ShareTab
,
newItem
:
ShareTab
)
=
oldItem
.
url
==
newItem
.
url
override
fun
areContentsTheSame
(
oldItem
:
ShareTab
,
newItem
:
ShareTab
):
Boolean
{