blob: 8d1253b457cc258cb17a734f366a5a1e17b5d701 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.people
import android.view.View
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager
import javax.inject.Inject
import javax.inject.Singleton
/** Boundary between the View and PeopleHub, as seen by the View. */
interface PeopleHubSectionFooterViewAdapter {
fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary)
}
/** Abstract `View` representation of PeopleHub footer in [NotificationSectionsManager]. */
interface PeopleHubSectionFooterViewBoundary {
/** View used for animating the activity launch caused by clicking a person in the hub. */
val associatedViewForClickAnimation: View
/** [DataListener]s for individual people in the hub. */
val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
/** Sets the visibility of the Hub in the notification shade. */
fun setVisible(isVisible: Boolean)
}
/** Creates a [PeopleHubViewModel] given some additional information required from the `View`. */
interface PeopleHubViewModelFactory {
/**
* Creates a [PeopleHubViewModel] that, when clicked, starts an activity using an animation
* involving the given [view].
*/
fun createWithAssociatedClickView(view: View): PeopleHubViewModel
}
/**
* Wraps a [PeopleHubSectionFooterViewBoundary] in a [DataListener], and connects it to the data
* pipeline.
*
* @param dataSource PeopleHub data pipeline.
*/
@Singleton
class PeopleHubSectionFooterViewAdapterImpl @Inject constructor(
private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubViewModelFactory>
) : PeopleHubSectionFooterViewAdapter {
override fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary) =
dataSource.setListener(PeopleHubDataListenerImpl(viewBoundary))
}
private class PeopleHubDataListenerImpl(
private val viewBoundary: PeopleHubSectionFooterViewBoundary
) : DataListener<PeopleHubViewModelFactory> {
override fun onDataChanged(data: PeopleHubViewModelFactory) {
val viewModel = data.createWithAssociatedClickView(
viewBoundary.associatedViewForClickAnimation
)
viewBoundary.setVisible(viewModel.isVisible)
val padded = viewModel.people + repeated(null)
for ((personAdapter, personModel) in viewBoundary.personViewAdapters.zip(padded)) {
personAdapter.onDataChanged(personModel)
}
}
}
/**
* Converts [PeopleHubModel]s into [PeopleHubViewModelFactory]s.
*
* This class serves as the glue between the View layer (which depends on
* [PeopleHubSectionFooterViewBoundary]) and the Data layer (which produces [PeopleHubModel]s).
*/
@Singleton
class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor(
private val activityStarter: ActivityStarter,
private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubModel>
) : DataSource<PeopleHubViewModelFactory> {
override fun setListener(listener: DataListener<PeopleHubViewModelFactory>) =
dataSource.setListener(PeopleHubModelListenerImpl(activityStarter, listener))
}
private class PeopleHubModelListenerImpl(
private val activityStarter: ActivityStarter,
private val dataListener: DataListener<PeopleHubViewModelFactory>
) : DataListener<PeopleHubModel> {
override fun onDataChanged(data: PeopleHubModel) =
dataListener.onDataChanged(PeopleHubViewModelFactoryImpl(data, activityStarter))
}
private class PeopleHubViewModelFactoryImpl(
private val data: PeopleHubModel,
private val activityStarter: ActivityStarter
) : PeopleHubViewModelFactory {
override fun createWithAssociatedClickView(view: View): PeopleHubViewModel {
val personViewModels = data.people.asSequence().map { personModel ->
val onClick = {
activityStarter.startPendingIntentDismissingKeyguard(
personModel.clickIntent,
null,
view
)
}
PersonViewModel(personModel.name, personModel.avatar, onClick)
}
return PeopleHubViewModel(personViewModels, data.people.isNotEmpty())
}
}
private fun <T> repeated(value: T): Sequence<T> = sequence {
while (true) {
yield(value)
}
}