v2026.06.03 — Media3 like button + Bluetooth/UPnP picker + system playlist daily rotation #77
+60
@@ -0,0 +1,60 @@
|
|||||||
|
package com.fabledsword.minstrel.player.output
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NowPlaying-scoped projection over [OutputPickerController]. The
|
||||||
|
* controller is the long-lived Hilt singleton (its MediaRouter
|
||||||
|
* callback must not churn with screen lifecycle); this ViewModel is
|
||||||
|
* a thin lens over its [OutputPickerController.routesState] Flow
|
||||||
|
* plus the sheet's visibility state.
|
||||||
|
*
|
||||||
|
* Sheet open/close are forwarded to the controller's discovery
|
||||||
|
* toggle so active MediaRouter discovery only runs while the sheet
|
||||||
|
* is actually visible.
|
||||||
|
*/
|
||||||
|
@HiltViewModel
|
||||||
|
class OutputPickerViewModel @Inject constructor(
|
||||||
|
private val controller: OutputPickerController,
|
||||||
|
) : ViewModel() {
|
||||||
|
|
||||||
|
val routes: StateFlow<RouteSnapshot> = controller.routesState
|
||||||
|
.stateIn(
|
||||||
|
scope = viewModelScope,
|
||||||
|
started = SharingStarted.WhileSubscribed(STOP_TIMEOUT_MS),
|
||||||
|
initialValue = controller.routesState.value,
|
||||||
|
)
|
||||||
|
|
||||||
|
private val sheetVisibleInternal = MutableStateFlow(false)
|
||||||
|
val sheetVisible: StateFlow<Boolean> = sheetVisibleInternal.asStateFlow()
|
||||||
|
|
||||||
|
fun onChipTapped() {
|
||||||
|
sheetVisibleInternal.value = true
|
||||||
|
controller.upgradeDiscovery()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onSheetDismissed() {
|
||||||
|
sheetVisibleInternal.value = false
|
||||||
|
controller.downgradeDiscovery()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onRouteSelected(route: OutputRoute) {
|
||||||
|
controller.select(route)
|
||||||
|
sheetVisibleInternal.value = false
|
||||||
|
controller.downgradeDiscovery()
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
// SharingStarted timeout so quick screen-orientation changes
|
||||||
|
// don't tear down + re-subscribe the controller's Flow.
|
||||||
|
const val STOP_TIMEOUT_MS = 5_000L
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user