Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9f2c305 authored by Michael Mikhail's avatar Michael Mikhail Committed by Android (Google) Code Review
Browse files

Merge "Store current carousel position" into main

parents 9f3a5998 c6f70463
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -24,7 +24,11 @@ import android.media.MediaMetadata
import android.media.session.MediaController
import android.media.session.PlaybackState
import android.util.Log
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.graphics.Color
import com.android.internal.logging.InstanceId
@@ -59,11 +63,22 @@ interface MediaRepository {
    /** Current sorted media sessions. */
    val currentMedia: List<MediaDataModel>

    /** Index of the current visible media session */
    val currentCarouselIndex: Int

    /** Whether media carousel should show first media session. */
    val shouldScrollToFirst: Boolean

    /** Seek to [to], in milliseconds on the media session with the given [sessionKey]. */
    fun seek(sessionKey: InstanceId, to: Long)

    /** Reorders media list when media is not visible to user */
    fun reorderMedia()

    fun storeCarouselIndex(index: Int)

    /** Resets [shouldScrollToFirst] flag. */
    fun resetScrollToFirst()
}

@SysUISingleton
@@ -78,6 +93,10 @@ constructor(

    override val currentMedia: SnapshotStateList<MediaDataModel> = mutableStateListOf()

    override var currentCarouselIndex by mutableIntStateOf(0)

    override var shouldScrollToFirst by mutableStateOf(false)

    private var sortedMedia = TreeMap<MediaSortKeyModel, MediaDataModel>(comparator)

    // To store active controllers and their callbacks
@@ -124,6 +143,15 @@ constructor(
    override fun reorderMedia() {
        currentMedia.clear()
        currentMedia.addAll(sortedMedia.values.toList())
        currentCarouselIndex = 0
    }

    override fun storeCarouselIndex(index: Int) {
        currentCarouselIndex = index
    }

    override fun resetScrollToFirst() {
        shouldScrollToFirst = false
    }

    private fun addToSortedMedia(data: MediaData, updateModel: UpdateArtInfoModel?) {
@@ -175,6 +203,9 @@ constructor(
                    }
                    currentMedia.clear()
                    if (isNewToCurrentMedia && active) {
                        // New media added is at the top of the current media given its priority.
                        // Media carousel should show the first card in the current media list.
                        shouldScrollToFirst = true
                        currentMedia.addAll(sortedMap.values.toList())
                    } else {
                        currentMedia.addAll(currentList)
+24 −0
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@ interface MediaInteractor {
    /** The list of sessions. Needs to be backed by a compose snapshot state. */
    val sessions: List<MediaSessionModel>

    /** Index of the current visible media session */
    val currentCarouselIndex: Int

    /** Whether media carousel should show first media session. */
    val shouldScrollToFirst: Boolean

    /** Seek to [to], in milliseconds on the media session with the given [sessionKey]. */
    fun seek(sessionKey: Any, to: Long)

@@ -74,6 +80,10 @@ interface MediaInteractor {
    fun openMediaSettings()

    fun reorderMedia()

    fun storeCurrentCarouselIndex(index: Int)

    fun resetScrollToFirst()
}

@SysUISingleton
@@ -93,6 +103,12 @@ constructor(
    override val sessions: List<MediaSessionModel>
        get() = repository.currentMedia.map { toMediaSessionModel(it) }

    override val currentCarouselIndex: Int
        get() = repository.currentCarouselIndex

    override val shouldScrollToFirst: Boolean
        get() = repository.shouldScrollToFirst

    override fun seek(sessionKey: Any, to: Long) {
        repository.seek(sessionKey as InstanceId, to)
    }
@@ -109,6 +125,14 @@ constructor(
        repository.reorderMedia()
    }

    override fun storeCurrentCarouselIndex(index: Int) {
        repository.storeCarouselIndex(index)
    }

    override fun resetScrollToFirst() {
        repository.resetScrollToFirst()
    }

    private fun toMediaSessionModel(dataModel: MediaDataModel): MediaSessionModel {
        return object : MediaSessionModel {
            override val key
+12 −1
Original line number Diff line number Diff line
@@ -229,8 +229,12 @@ private fun CardCarouselContent(
    modifier: Modifier = Modifier,
) {
    val pagerState = rememberPagerState { viewModel.cards.size }
    LaunchedEffect(viewModel.currentIndex) {
        if (viewModel.currentIndex != pagerState.currentPage) {
            pagerState.scrollToPage(viewModel.currentIndex)
        }
    }
    LaunchedEffect(pagerState.currentPage) { viewModel.onCardSelected(pagerState.currentPage) }

    var isFalseTouchDetected: Boolean by
        remember(behavior.isCarouselScrollFalseTouch) { mutableStateOf(false) }
    val isSwipingEnabled = behavior.isCarouselScrollingEnabled && !isFalseTouchDetected
@@ -308,6 +312,13 @@ private fun CardCarouselContent(
            )
        }
    }

    LaunchedEffect(viewModel.scrollToFirst) {
        if (viewModel.scrollToFirst && viewModel.cards.isNotEmpty()) {
            pagerState.animateScrollToPage(0)
            viewModel.onScrollToFirstCard()
        }
    }
}

/** Renders the UI of a single media card. */
+12 −0
Original line number Diff line number Diff line
@@ -69,6 +69,12 @@ constructor(
    private var selectedCardIndex: Int by mutableIntStateOf(0)
        private set

    /** The index of the currently visible card across different locations of media carousel */
    val currentIndex: Int by derivedStateOf { interactor.currentCarouselIndex }

    /** Whether media carousel should scroll to the first card in the list after composition */
    val scrollToFirst: Boolean by derivedStateOf { interactor.shouldScrollToFirst }

    /** The current list of cards to show in the UI. */
    val cards: List<MediaCardViewModel> by derivedStateOf {
        interactor.sessions.mapIndexed { sessionIndex, session ->
@@ -307,6 +313,12 @@ constructor(
    fun onCardSelected(cardIndex: Int) {
        check(cardIndex >= 0 && cardIndex < cards.size)
        selectedCardIndex = cardIndex
        interactor.storeCurrentCarouselIndex(selectedCardIndex)
    }

    /** Notifies that the carousel is reordered and first card is now visible on screen. */
    fun onScrollToFirstCard() {
        interactor.resetScrollToFirst()
    }

    override suspend fun onActivated(): Nothing {