mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-11-05 18:30:59 +01:00
Use Wholphin-specific dispatchers (#1583)
## Description Switches all usages of `kotlinx.coroutines.Dispatchers` to `WholphinDispatchers`. `WholphinDispatchers` provides an easier and more reliable mechanism to use a test dispatcher in unit tests. For regular app usage, `WholphinDispatchers` just delegates to `Dispatchers`. There are no user facing changes ### Related issues None ### Testing Basic emulator testing & unit tests ## Screenshots N/A ## AI or LLM usage None
This commit is contained in:
parent
ddbec0da73
commit
e17ae3eb8a
68 changed files with 252 additions and 226 deletions
|
|
@ -60,10 +60,10 @@ import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
import com.github.damontecres.wholphin.ui.util.ProvideLocalClock
|
import com.github.damontecres.wholphin.ui.util.ProvideLocalClock
|
||||||
import com.github.damontecres.wholphin.util.DebugLogTree
|
import com.github.damontecres.wholphin.util.DebugLogTree
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
@ -170,7 +170,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
viewModel.serverRepository.currentUserFlow
|
viewModel.serverRepository.currentUserFlow
|
||||||
.onEach { user ->
|
.onEach { user ->
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
if (user?.hasPin == true) {
|
if (user?.hasPin == true) {
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -184,7 +184,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
screensaverService.keepScreenOn
|
screensaverService.keepScreenOn
|
||||||
.onEach { keepScreenOn ->
|
.onEach { keepScreenOn ->
|
||||||
Timber.v("keepScreenOn: %s", keepScreenOn)
|
Timber.v("keepScreenOn: %s", keepScreenOn)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
if (keepScreenOn) {
|
if (keepScreenOn) {
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -383,7 +383,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun changeDisplayMode(modeId: Int) {
|
fun changeDisplayMode(modeId: Int) {
|
||||||
lifecycleScope.launch(Dispatchers.Main + ExceptionHandler(autoToast = true)) {
|
lifecycleScope.launch(WholphinDispatchers.Main + ExceptionHandler(autoToast = true)) {
|
||||||
val attrs = window.attributes
|
val attrs = window.attributes
|
||||||
if (attrs.preferredDisplayModeId != modeId) {
|
if (attrs.preferredDisplayModeId != modeId) {
|
||||||
Timber.d("Switch preferredDisplayModeId to %s", modeId)
|
Timber.d("Switch preferredDisplayModeId to %s", modeId)
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import com.github.damontecres.wholphin.data.model.PlaybackLanguageChoice
|
||||||
import com.github.damontecres.wholphin.data.model.TrackIndex
|
import com.github.damontecres.wholphin.data.model.TrackIndex
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.wholphin.services.StreamChoiceService
|
import com.github.damontecres.wholphin.services.StreamChoiceService
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jellyfin.sdk.model.api.MediaSourceInfo
|
import org.jellyfin.sdk.model.api.MediaSourceInfo
|
||||||
import org.jellyfin.sdk.model.api.MediaStream
|
import org.jellyfin.sdk.model.api.MediaStream
|
||||||
|
|
@ -108,7 +108,7 @@ class ItemPlaybackRepository
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
sourceId: UUID,
|
sourceId: UUID,
|
||||||
): ItemPlayback? =
|
): ItemPlayback? =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
serverRepository.currentUser?.let { user ->
|
serverRepository.currentUser?.let { user ->
|
||||||
val itemPlayback =
|
val itemPlayback =
|
||||||
ItemPlayback(
|
ItemPlayback(
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import com.github.damontecres.wholphin.data.model.JellyfinUser
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
import com.github.damontecres.wholphin.services.hilt.IoDispatcher
|
import com.github.damontecres.wholphin.services.hilt.IoDispatcher
|
||||||
import com.github.damontecres.wholphin.ui.toServerString
|
import com.github.damontecres.wholphin.ui.toServerString
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -109,7 +109,7 @@ class ServerRepository
|
||||||
}.build()
|
}.build()
|
||||||
}
|
}
|
||||||
val currentUser = CurrentUser(updatedServer, updatedUser)
|
val currentUser = CurrentUser(updatedServer, updatedUser)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
_current.value = currentUser
|
_current.value = currentUser
|
||||||
_currentUserDto.value = userDto
|
_currentUserDto.value = userDto
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +222,7 @@ class ServerRepository
|
||||||
|
|
||||||
suspend fun removeUser(user: JellyfinUser) {
|
suspend fun removeUser(user: JellyfinUser) {
|
||||||
if (current.value?.user?.id == user.id) {
|
if (current.value?.user?.id == user.id) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
_current.value = null
|
_current.value = null
|
||||||
}
|
}
|
||||||
userPreferencesDataStore.updateData {
|
userPreferencesDataStore.updateData {
|
||||||
|
|
@ -241,7 +241,7 @@ class ServerRepository
|
||||||
|
|
||||||
suspend fun removeServer(server: JellyfinServer) {
|
suspend fun removeServer(server: JellyfinServer) {
|
||||||
if (current.value?.server?.id == server.id) {
|
if (current.value?.server?.id == server.id) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
_current.value = null
|
_current.value = null
|
||||||
}
|
}
|
||||||
userPreferencesDataStore.updateData {
|
userPreferencesDataStore.updateData {
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.BackdropStyle
|
import com.github.damontecres.wholphin.preferences.BackdropStyle
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.FlowPreview
|
import kotlinx.coroutines.FlowPreview
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -55,7 +55,7 @@ class BackdropService
|
||||||
* Update the backdrop to use the specified item
|
* Update the backdrop to use the specified item
|
||||||
*/
|
*/
|
||||||
suspend fun submit(item: BaseItem) =
|
suspend fun submit(item: BaseItem) =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val imageUrl =
|
val imageUrl =
|
||||||
if (item.type == BaseItemKind.GENRE) {
|
if (item.type == BaseItemKind.GENRE) {
|
||||||
item.imageUrlOverride
|
item.imageUrlOverride
|
||||||
|
|
@ -76,7 +76,7 @@ class BackdropService
|
||||||
suspend fun submit(
|
suspend fun submit(
|
||||||
itemId: String,
|
itemId: String,
|
||||||
imageUrl: String?,
|
imageUrl: String?,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(WholphinDispatchers.IO) {
|
||||||
if (backdropFlow.firstOrNull()?.imageUrl != imageUrl) {
|
if (backdropFlow.firstOrNull()?.imageUrl != imageUrl) {
|
||||||
_backdropFlow.update {
|
_backdropFlow.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
|
|
@ -132,7 +132,7 @@ class BackdropService
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun extractColorsFromBackdrop(imageUrl: String?): ExtractedColors =
|
suspend fun extractColorsFromBackdrop(imageUrl: String?): ExtractedColors =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
if (imageUrl.isNullOrBlank()) {
|
if (imageUrl.isNullOrBlank()) {
|
||||||
return@withContext ExtractedColors.DEFAULT
|
return@withContext ExtractedColors.DEFAULT
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,12 @@ import com.github.damontecres.wholphin.preferences.AppPreference
|
||||||
import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope
|
import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope
|
||||||
import com.github.damontecres.wholphin.ui.collectLatestIn
|
import com.github.damontecres.wholphin.ui.collectLatestIn
|
||||||
import com.github.damontecres.wholphin.util.GetEpisodesRequestHandler
|
import com.github.damontecres.wholphin.util.GetEpisodesRequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.google.common.cache.CacheBuilder
|
import com.google.common.cache.CacheBuilder
|
||||||
import dagger.hilt.android.qualifiers.ActivityContext
|
import dagger.hilt.android.qualifiers.ActivityContext
|
||||||
import dagger.hilt.android.scopes.ActivityScoped
|
import dagger.hilt.android.scopes.ActivityScoped
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
|
|
@ -56,7 +56,7 @@ class DatePlayedService
|
||||||
adjacentTo = item.id,
|
adjacentTo = item.id,
|
||||||
limit = 1,
|
limit = 1,
|
||||||
)
|
)
|
||||||
return scope.async(Dispatchers.IO) {
|
return scope.async(WholphinDispatchers.IO) {
|
||||||
val premiereDate = item.data.premiereDate
|
val premiereDate = item.data.premiereDate
|
||||||
try {
|
try {
|
||||||
val result =
|
val result =
|
||||||
|
|
@ -92,7 +92,7 @@ class DatePlayedService
|
||||||
* the previous episode's last played timestamp, and the episode's premiere date
|
* the previous episode's last played timestamp, and the episode's premiere date
|
||||||
*/
|
*/
|
||||||
suspend fun getLastPlayed(item: BaseItem): LocalDateTime? =
|
suspend fun getLastPlayed(item: BaseItem): LocalDateTime? =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val seriesId = item.data.seriesId
|
val seriesId = item.data.seriesId
|
||||||
return@withContext if (seriesId != null) {
|
return@withContext if (seriesId != null) {
|
||||||
datePlayedCache
|
datePlayedCache
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ package com.github.damontecres.wholphin.services
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.damontecres.wholphin.preferences.AssPlaybackMode
|
import com.github.damontecres.wholphin.preferences.AssPlaybackMode
|
||||||
import com.github.damontecres.wholphin.preferences.PlaybackPreferences
|
import com.github.damontecres.wholphin.preferences.PlaybackPreferences
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.profile.MediaCodecCapabilitiesTest
|
import com.github.damontecres.wholphin.util.profile.MediaCodecCapabilitiesTest
|
||||||
import com.github.damontecres.wholphin.util.profile.createDeviceProfile
|
import com.github.damontecres.wholphin.util.profile.createDeviceProfile
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -37,7 +37,7 @@ class DeviceProfileService
|
||||||
prefs: PlaybackPreferences,
|
prefs: PlaybackPreferences,
|
||||||
serverVersion: ServerVersion?,
|
serverVersion: ServerVersion?,
|
||||||
): DeviceProfile =
|
): DeviceProfile =
|
||||||
withContext(Dispatchers.Default) {
|
withContext(WholphinDispatchers.Default) {
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
val newConfig =
|
val newConfig =
|
||||||
DeviceProfileConfiguration(
|
DeviceProfileConfiguration(
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ package com.github.damontecres.wholphin.services
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||||
import com.github.damontecres.wholphin.util.LocalDateTimeSerializer
|
import com.github.damontecres.wholphin.util.LocalDateTimeSerializer
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.supportItemKinds
|
import com.github.damontecres.wholphin.util.supportItemKinds
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.sync.Semaphore
|
import kotlinx.coroutines.sync.Semaphore
|
||||||
|
|
@ -143,14 +143,14 @@ class LatestNextUpService
|
||||||
resume: List<BaseItem>,
|
resume: List<BaseItem>,
|
||||||
nextUp: List<BaseItem>,
|
nextUp: List<BaseItem>,
|
||||||
): List<BaseItem> =
|
): List<BaseItem> =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
val semaphore = Semaphore(3)
|
val semaphore = Semaphore(3)
|
||||||
val deferred =
|
val deferred =
|
||||||
nextUp
|
nextUp
|
||||||
.filter { it.data.seriesId != null }
|
.filter { it.data.seriesId != null }
|
||||||
.map { item ->
|
.map { item ->
|
||||||
async(Dispatchers.IO) {
|
async(WholphinDispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
semaphore.withPermit {
|
semaphore.withPermit {
|
||||||
datePlayedService.getLastPlayed(item)
|
datePlayedService.getLastPlayed(item)
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@ import androidx.work.workDataOf
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.ui.collectLatestIn
|
import com.github.damontecres.wholphin.ui.collectLatestIn
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.qualifiers.ActivityContext
|
import dagger.hilt.android.qualifiers.ActivityContext
|
||||||
import dagger.hilt.android.scopes.ActivityScoped
|
import dagger.hilt.android.scopes.ActivityScoped
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
|
import org.jellyfin.sdk.model.serializer.toUUIDOrNull
|
||||||
|
|
@ -92,7 +92,7 @@ class LatestNextUpSchedulerService
|
||||||
)
|
)
|
||||||
|
|
||||||
// Exposed for testing
|
// Exposed for testing
|
||||||
internal var dispatcher: CoroutineDispatcher = Dispatchers.IO
|
internal var dispatcher: CoroutineDispatcher = WholphinDispatchers.IO
|
||||||
|
|
||||||
init {
|
init {
|
||||||
serverRepository.current.collectLatestIn(activity.lifecycleScope) { user ->
|
serverRepository.current.collectLatestIn(activity.lifecycleScope) { user ->
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,10 @@ import com.github.damontecres.wholphin.util.BlockingList
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
import com.github.damontecres.wholphin.util.PlaybackItemState
|
import com.github.damontecres.wholphin.util.PlaybackItemState
|
||||||
import com.github.damontecres.wholphin.util.TrackActivityPlaybackListener
|
import com.github.damontecres.wholphin.util.TrackActivityPlaybackListener
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.profile.supportedAudioCodecs
|
import com.github.damontecres.wholphin.util.profile.supportedAudioCodecs
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -177,9 +177,9 @@ class MusicService
|
||||||
items: BlockingList<BaseItem?>,
|
items: BlockingList<BaseItem?>,
|
||||||
startIndex: Int,
|
startIndex: Int,
|
||||||
shuffled: Boolean,
|
shuffled: Boolean,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(WholphinDispatchers.IO) {
|
||||||
Timber.d("setQueue: %s items, startIndex=%s, shuffled=%s", items.size, startIndex, shuffled)
|
Timber.d("setQueue: %s items, startIndex=%s, shuffled=%s", items.size, startIndex, shuffled)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
player.setMediaItems(emptyList())
|
player.setMediaItems(emptyList())
|
||||||
player.shuffleModeEnabled = shuffled
|
player.shuffleModeEnabled = shuffled
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +199,7 @@ class MusicService
|
||||||
items
|
items
|
||||||
.filter { it.type == BaseItemKind.AUDIO }
|
.filter { it.type == BaseItemKind.AUDIO }
|
||||||
.map(::convert)
|
.map(::convert)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
player.setMediaItems(mediaItems)
|
player.setMediaItems(mediaItems)
|
||||||
player.shuffleModeEnabled = shuffled
|
player.shuffleModeEnabled = shuffled
|
||||||
updateQueueSize()
|
updateQueueSize()
|
||||||
|
|
@ -216,7 +216,7 @@ class MusicService
|
||||||
) {
|
) {
|
||||||
if (item.type == BaseItemKind.AUDIO) {
|
if (item.type == BaseItemKind.AUDIO) {
|
||||||
val mediaItem = convert(item)
|
val mediaItem = convert(item)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
player.addMediaItem(index, mediaItem)
|
player.addMediaItem(index, mediaItem)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -293,7 +293,7 @@ class MusicService
|
||||||
*/
|
*/
|
||||||
private suspend fun updateQueueSize() {
|
private suspend fun updateQueueSize() {
|
||||||
// val ids =
|
// val ids =
|
||||||
// withContext(Dispatchers.Default) {
|
// withContext(WholphinDispatchers.Default) {
|
||||||
// (0..<player.mediaItemCount).map { player.getMediaItemAt(it).mediaId.toUUID() }
|
// (0..<player.mediaItemCount).map { player.getMediaItemAt(it).mediaId.toUUID() }
|
||||||
// }
|
// }
|
||||||
val timeline = onMain { player.currentTimeline }
|
val timeline = onMain { player.currentTimeline }
|
||||||
|
|
@ -304,7 +304,7 @@ class MusicService
|
||||||
timeline.getWindow(it, window)
|
timeline.getWindow(it, window)
|
||||||
window.mediaItem.mediaId.toUUID()
|
window.mediaItem.mediaId.toUUID()
|
||||||
}.toSet()
|
}.toSet()
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
queueVersion = it.queueVersion + 1,
|
queueVersion = it.queueVersion + 1,
|
||||||
|
|
@ -321,7 +321,7 @@ class MusicService
|
||||||
suspend fun moveQueue(
|
suspend fun moveQueue(
|
||||||
index: Int,
|
index: Int,
|
||||||
direction: MoveDirection,
|
direction: MoveDirection,
|
||||||
) = withContext(Dispatchers.Main) {
|
) = withContext(WholphinDispatchers.Main) {
|
||||||
player.moveMediaItem(index, if (direction == MoveDirection.UP) index - 1 else index + 1)
|
player.moveMediaItem(index, if (direction == MoveDirection.UP) index - 1 else index + 1)
|
||||||
updateQueueSize()
|
updateQueueSize()
|
||||||
}
|
}
|
||||||
|
|
@ -332,7 +332,7 @@ class MusicService
|
||||||
suspend fun moveQueue(
|
suspend fun moveQueue(
|
||||||
index: Int,
|
index: Int,
|
||||||
newIndex: Int,
|
newIndex: Int,
|
||||||
) = withContext(Dispatchers.Main) {
|
) = withContext(WholphinDispatchers.Main) {
|
||||||
player.moveMediaItem(index, newIndex)
|
player.moveMediaItem(index, newIndex)
|
||||||
updateQueueSize()
|
updateQueueSize()
|
||||||
}
|
}
|
||||||
|
|
@ -385,7 +385,7 @@ class MusicService
|
||||||
.subscribe<PlaystateMessage>()
|
.subscribe<PlaystateMessage>()
|
||||||
.onEach { message ->
|
.onEach { message ->
|
||||||
message.data?.let {
|
message.data?.let {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
when (it.command) {
|
when (it.command) {
|
||||||
PlaystateCommand.STOP -> {
|
PlaystateCommand.STOP -> {
|
||||||
stop()
|
stop()
|
||||||
|
|
|
||||||
|
|
@ -13,11 +13,11 @@ import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.nav.NavDrawerItem
|
import com.github.damontecres.wholphin.ui.nav.NavDrawerItem
|
||||||
import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem
|
import com.github.damontecres.wholphin.ui.nav.ServerNavDrawerItem
|
||||||
import com.github.damontecres.wholphin.ui.showToast
|
import com.github.damontecres.wholphin.ui.showToast
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.supportedCollectionTypes
|
import com.github.damontecres.wholphin.util.supportedCollectionTypes
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -209,7 +209,7 @@ class NavDrawerService
|
||||||
val allItems = builtins + libraries
|
val allItems = builtins + libraries
|
||||||
|
|
||||||
val navDrawerPins =
|
val navDrawerPins =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
serverPreferencesDao.getNavDrawerPinnedItems(user).associateBy { it.itemId }
|
serverPreferencesDao.getNavDrawerPinnedItems(user).associateBy { it.itemId }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import com.github.damontecres.wholphin.preferences.MediaExtensionStatus
|
||||||
import com.github.damontecres.wholphin.preferences.PlaybackPreferences
|
import com.github.damontecres.wholphin.preferences.PlaybackPreferences
|
||||||
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
import com.github.damontecres.wholphin.preferences.PlayerBackend
|
||||||
import com.github.damontecres.wholphin.services.hilt.AuthOkHttpClient
|
import com.github.damontecres.wholphin.services.hilt.AuthOkHttpClient
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.mpv.MpvPlayer
|
import com.github.damontecres.wholphin.util.mpv.MpvPlayer
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import io.github.peerless2012.ass.media.AssHandler
|
import io.github.peerless2012.ass.media.AssHandler
|
||||||
|
|
@ -36,7 +37,6 @@ import io.github.peerless2012.ass.media.factory.AssRenderersFactory
|
||||||
import io.github.peerless2012.ass.media.kt.withAssMkvSupport
|
import io.github.peerless2012.ass.media.kt.withAssMkvSupport
|
||||||
import io.github.peerless2012.ass.media.parser.AssSubtitleParserFactory
|
import io.github.peerless2012.ass.media.parser.AssSubtitleParserFactory
|
||||||
import io.github.peerless2012.ass.media.type.AssRenderType
|
import io.github.peerless2012.ass.media.type.AssRenderType
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
@ -62,7 +62,7 @@ class PlayerFactory
|
||||||
backend: PlayerBackend,
|
backend: PlayerBackend,
|
||||||
prefs: PlaybackPreferences,
|
prefs: PlaybackPreferences,
|
||||||
): PlayerCreation {
|
): PlayerCreation {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
if (currentPlayer?.isReleased == false) {
|
if (currentPlayer?.isReleased == false) {
|
||||||
Timber.w("Player was not released before trying to create a new one!")
|
Timber.w("Player was not released before trying to create a new one!")
|
||||||
currentPlayer?.release()
|
currentPlayer?.release()
|
||||||
|
|
@ -138,7 +138,7 @@ class PlayerFactory
|
||||||
.build()
|
.build()
|
||||||
.apply {
|
.apply {
|
||||||
assHandler?.init(this)
|
assHandler?.init(this)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
setAudioAttributes(
|
setAudioAttributes(
|
||||||
AudioAttributes
|
AudioAttributes
|
||||||
.Builder()
|
.Builder()
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ import android.os.Looper
|
||||||
import android.view.Display
|
import android.view.Display
|
||||||
import com.github.damontecres.wholphin.MainActivity
|
import com.github.damontecres.wholphin.MainActivity
|
||||||
import com.github.damontecres.wholphin.ui.showToast
|
import com.github.damontecres.wholphin.ui.showToast
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
|
|
@ -38,7 +38,7 @@ class RefreshRateService
|
||||||
stream: MediaStream,
|
stream: MediaStream,
|
||||||
switchRefreshRate: Boolean,
|
switchRefreshRate: Boolean,
|
||||||
switchResolution: Boolean,
|
switchResolution: Boolean,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(WholphinDispatchers.IO) {
|
||||||
if (!switchRefreshRate && !switchResolution) {
|
if (!switchRefreshRate && !switchResolution) {
|
||||||
Timber.v("Not switching either refresh rate nor resolution")
|
Timber.v("Not switching either refresh rate nor resolution")
|
||||||
return@withContext
|
return@withContext
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package com.github.damontecres.wholphin.services
|
||||||
import com.github.damontecres.wholphin.data.RememberedTabDao
|
import com.github.damontecres.wholphin.data.RememberedTabDao
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.data.model.RememberedTab
|
import com.github.damontecres.wholphin.data.model.RememberedTab
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
|
|
@ -16,7 +16,7 @@ class RememberedTabService
|
||||||
private val rememberedTabDao: RememberedTabDao,
|
private val rememberedTabDao: RememberedTabDao,
|
||||||
) {
|
) {
|
||||||
suspend fun getRememberedTab(itemId: String): Int? =
|
suspend fun getRememberedTab(itemId: String): Int? =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
serverRepository.currentUser?.rowId?.let { userId ->
|
serverRepository.currentUser?.rowId?.let { userId ->
|
||||||
rememberedTabDao.getRememberedTab(userId, itemId)?.index
|
rememberedTabDao.getRememberedTab(userId, itemId)?.index
|
||||||
}
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ class RememberedTabService
|
||||||
itemId: String,
|
itemId: String,
|
||||||
tabIndex: Int,
|
tabIndex: Int,
|
||||||
): Unit =
|
): Unit =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
serverRepository.currentUser?.rowId?.let { userId ->
|
serverRepository.currentUser?.rowId?.let { userId ->
|
||||||
rememberedTabDao.save(RememberedTab(userId, itemId, tabIndex))
|
rememberedTabDao.save(RememberedTab(userId, itemId, tabIndex))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@ import com.github.damontecres.wholphin.ui.launchDefault
|
||||||
import com.github.damontecres.wholphin.util.ApiRequestPager
|
import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
@ -224,7 +224,7 @@ class ScreensaverService
|
||||||
if (index > pager.lastIndex) index = 0
|
if (index > pager.lastIndex) index = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.flowOn(Dispatchers.Default).cancellable()
|
}.flowOn(WholphinDispatchers.Default).cancellable()
|
||||||
|
|
||||||
private suspend fun createPager(): ApiRequestPager<GetItemsRequest> {
|
private suspend fun createPager(): ApiRequestPager<GetItemsRequest> {
|
||||||
val prefs =
|
val prefs =
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ package com.github.damontecres.wholphin.services
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.damontecres.wholphin.ui.toServerString
|
import com.github.damontecres.wholphin.ui.toServerString
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.mayakapps.kache.InMemoryKache
|
import com.mayakapps.kache.InMemoryKache
|
||||||
import com.mayakapps.kache.ObjectKache
|
import com.mayakapps.kache.ObjectKache
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
|
|
@ -43,7 +43,7 @@ class SuggestionsCache
|
||||||
|
|
||||||
private val memoryCache =
|
private val memoryCache =
|
||||||
InMemoryKache<String, CachedSuggestions>(maxSize = 8) {
|
InMemoryKache<String, CachedSuggestions>(maxSize = 8) {
|
||||||
creationScope = CoroutineScope(Dispatchers.IO)
|
creationScope = CoroutineScope(WholphinDispatchers.IO)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun cacheKey(
|
private fun cacheKey(
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreference
|
import com.github.damontecres.wholphin.preferences.AppPreference
|
||||||
import com.github.damontecres.wholphin.preferences.AppPreferences
|
import com.github.damontecres.wholphin.preferences.AppPreferences
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.coroutineScope
|
import kotlinx.coroutines.coroutineScope
|
||||||
|
|
@ -81,7 +81,7 @@ class SuggestionsWorker
|
||||||
.takeIf { it > 0 }
|
.takeIf { it > 0 }
|
||||||
?: AppPreference.HomePageItems.defaultValue.toInt()
|
?: AppPreference.HomePageItems.defaultValue.toInt()
|
||||||
|
|
||||||
val context = Dispatchers.IO.limitedParallelism(2, "fetchSuggestions")
|
val context = WholphinDispatchers.IO.limitedParallelism(2, "fetchSuggestions")
|
||||||
if (requestedParentId != null && requestedItemKind != null) {
|
if (requestedParentId != null && requestedItemKind != null) {
|
||||||
Timber.d(
|
Timber.d(
|
||||||
"Fetching on-demand suggestions for parent=%s kind=%s",
|
"Fetching on-demand suggestions for parent=%s kind=%s",
|
||||||
|
|
@ -128,7 +128,7 @@ class SuggestionsWorker
|
||||||
supervisorScope {
|
supervisorScope {
|
||||||
supportedViews
|
supportedViews
|
||||||
.map { view ->
|
.map { view ->
|
||||||
async(Dispatchers.IO) {
|
async(WholphinDispatchers.IO) {
|
||||||
runCatching {
|
runCatching {
|
||||||
Timber.v("Fetching suggestions for parent=%s kind=%s", view.id, view.itemKind)
|
Timber.v("Fetching suggestions for parent=%s kind=%s", view.id, view.itemKind)
|
||||||
fetchAndCacheSuggestions(
|
fetchAndCacheSuggestions(
|
||||||
|
|
@ -293,7 +293,7 @@ class SuggestionsWorker
|
||||||
limit = freshLimit,
|
limit = freshLimit,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Default) {
|
withContext(WholphinDispatchers.Default) {
|
||||||
val contextual = contextualDeferred.await()
|
val contextual = contextualDeferred.await()
|
||||||
val random = randomDeferred.await()
|
val random = randomDeferred.await()
|
||||||
val fresh = freshDeferred.await()
|
val fresh = freshDeferred.await()
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@ import com.github.damontecres.wholphin.preferences.ThemeSongVolume
|
||||||
import com.github.damontecres.wholphin.services.hilt.AuthOkHttpClient
|
import com.github.damontecres.wholphin.services.hilt.AuthOkHttpClient
|
||||||
import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope
|
import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.profile.Codec
|
import com.github.damontecres.wholphin.util.profile.Codec
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.cancelAndJoin
|
import kotlinx.coroutines.cancelAndJoin
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -102,7 +102,7 @@ class ThemeSongPlayer
|
||||||
Codec.Audio.FLAC,
|
Codec.Audio.FLAC,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
player.apply {
|
player.apply {
|
||||||
stop()
|
stop()
|
||||||
volume = volumeLevel
|
volume = volumeLevel
|
||||||
|
|
@ -127,7 +127,7 @@ class ThemeSongPlayer
|
||||||
scope.launch {
|
scope.launch {
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
state.value.job?.cancelAndJoin()
|
state.value.job?.cancelAndJoin()
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
Timber.v("Stopping theme song")
|
Timber.v("Stopping theme song")
|
||||||
player.stop()
|
player.stop()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,8 @@ import com.github.damontecres.wholphin.services.hilt.StandardOkHttpClient
|
||||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
import com.github.damontecres.wholphin.ui.showToast
|
import com.github.damontecres.wholphin.ui.showToast
|
||||||
import com.github.damontecres.wholphin.util.Version
|
import com.github.damontecres.wholphin.util.Version
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
@ -131,7 +131,7 @@ class UpdateChecker
|
||||||
suspend fun getRelease(version: Version): Release? {
|
suspend fun getRelease(version: Version): Release? {
|
||||||
val url =
|
val url =
|
||||||
"https://api.github.com/repos/damontecres/Wholphin/releases/tags/v${version.major}.${version.minor}.${version.patch}"
|
"https://api.github.com/repos/damontecres/Wholphin/releases/tags/v${version.major}.${version.minor}.${version.patch}"
|
||||||
return withContext(Dispatchers.IO) {
|
return withContext(WholphinDispatchers.IO) {
|
||||||
val request =
|
val request =
|
||||||
Request
|
Request
|
||||||
.Builder()
|
.Builder()
|
||||||
|
|
@ -146,7 +146,7 @@ class UpdateChecker
|
||||||
* Get the latest released version
|
* Get the latest released version
|
||||||
*/
|
*/
|
||||||
suspend fun getLatestRelease(updateUrl: String): Release? =
|
suspend fun getLatestRelease(updateUrl: String): Release? =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val request =
|
val request =
|
||||||
Request
|
Request
|
||||||
.Builder()
|
.Builder()
|
||||||
|
|
@ -199,7 +199,7 @@ class UpdateChecker
|
||||||
release: Release,
|
release: Release,
|
||||||
callback: DownloadCallback,
|
callback: DownloadCallback,
|
||||||
) {
|
) {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
cleanup()
|
cleanup()
|
||||||
val request =
|
val request =
|
||||||
Request
|
Request
|
||||||
|
|
@ -210,7 +210,7 @@ class UpdateChecker
|
||||||
okHttpClient.newCall(request).execute().use {
|
okHttpClient.newCall(request).execute().use {
|
||||||
if (it.isSuccessful && it.body != null) {
|
if (it.isSuccessful && it.body != null) {
|
||||||
Timber.v("Request successful for ${release.downloadUrl}")
|
Timber.v("Request successful for ${release.downloadUrl}")
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
callback.contentLength(it.body.contentLength())
|
callback.contentLength(it.body.contentLength())
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
|
@ -396,7 +396,7 @@ suspend fun copyTo(
|
||||||
while (bytes >= 0) {
|
while (bytes >= 0) {
|
||||||
out.write(buffer, 0, bytes)
|
out.write(buffer, 0, bytes)
|
||||||
bytesCopied += bytes
|
bytesCopied += bytes
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
callback.bytesDownloaded(bytesCopied)
|
callback.bytesDownloaded(bytesCopied)
|
||||||
}
|
}
|
||||||
bytes = input.read(buffer)
|
bytes = input.read(buffer)
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,9 @@ import com.github.damontecres.wholphin.data.model.JellyfinUser
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrAuthMethod
|
import com.github.damontecres.wholphin.data.model.SeerrAuthMethod
|
||||||
import com.github.damontecres.wholphin.ui.launchDefault
|
import com.github.damontecres.wholphin.ui.launchDefault
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.qualifiers.ActivityContext
|
import dagger.hilt.android.qualifiers.ActivityContext
|
||||||
import dagger.hilt.android.scopes.ActivityScoped
|
import dagger.hilt.android.scopes.ActivityScoped
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.supervisorScope
|
import kotlinx.coroutines.supervisorScope
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -56,7 +56,7 @@ class UserSwitchListener
|
||||||
user.uiLanguage?.let { LocaleListCompat.forLanguageTags(it) }
|
user.uiLanguage?.let { LocaleListCompat.forLanguageTags(it) }
|
||||||
?: LocaleListCompat.getEmptyLocaleList()
|
?: LocaleListCompat.getEmptyLocaleList()
|
||||||
Timber.i("Switching locale to %s", localeList)
|
Timber.i("Switching locale to %s", localeList)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
AppCompatDelegate.setApplicationLocales(localeList)
|
AppCompatDelegate.setApplicationLocales(localeList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.services.SeerrApi
|
import com.github.damontecres.wholphin.services.SeerrApi
|
||||||
import com.github.damontecres.wholphin.util.CoroutineContextApiClientFactory
|
import com.github.damontecres.wholphin.util.CoroutineContextApiClientFactory
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
|
@ -14,7 +15,6 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import org.jellyfin.sdk.Jellyfin
|
import org.jellyfin.sdk.Jellyfin
|
||||||
|
|
@ -42,21 +42,21 @@ annotation class AuthOkHttpClient
|
||||||
annotation class StandardOkHttpClient
|
annotation class StandardOkHttpClient
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [CoroutineScope] with [Dispatchers.IO]
|
* A [CoroutineScope] with [WholphinDispatchers.IO]
|
||||||
*/
|
*/
|
||||||
@Qualifier
|
@Qualifier
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
annotation class IoCoroutineScope
|
annotation class IoCoroutineScope
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [CoroutineScope] with [Dispatchers.Default]
|
* A [CoroutineScope] with [WholphinDispatchers.Default]
|
||||||
*/
|
*/
|
||||||
@Qualifier
|
@Qualifier
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
annotation class DefaultCoroutineScope
|
annotation class DefaultCoroutineScope
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [Dispatchers.IO]
|
* [WholphinDispatchers.IO]
|
||||||
*
|
*
|
||||||
* @see IoCoroutineScope
|
* @see IoCoroutineScope
|
||||||
*/
|
*/
|
||||||
|
|
@ -65,7 +65,7 @@ annotation class DefaultCoroutineScope
|
||||||
annotation class IoDispatcher
|
annotation class IoDispatcher
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [Dispatchers.Default]
|
* [WholphinDispatchers.Default]
|
||||||
*
|
*
|
||||||
* @see DefaultCoroutineScope
|
* @see DefaultCoroutineScope
|
||||||
*/
|
*/
|
||||||
|
|
@ -156,7 +156,7 @@ object AppModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@IoDispatcher
|
@IoDispatcher
|
||||||
fun ioDispatcher(): CoroutineDispatcher = Dispatchers.IO
|
fun ioDispatcher(): CoroutineDispatcher = WholphinDispatchers.IO
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
|
|
@ -168,7 +168,7 @@ object AppModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@DefaultDispatcher
|
@DefaultDispatcher
|
||||||
fun defaultDispatcher(): CoroutineDispatcher = Dispatchers.Default
|
fun defaultDispatcher(): CoroutineDispatcher = WholphinDispatchers.Default
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ object DatabaseModule {
|
||||||
).addMigrations(Migrations.Migrate2to3)
|
).addMigrations(Migrations.Migrate2to3)
|
||||||
// .setQueryCallback({ sqlQuery, args ->
|
// .setQueryCallback({ sqlQuery, args ->
|
||||||
// Timber.v("sqlQuery=$sqlQuery, args=$args")
|
// Timber.v("sqlQuery=$sqlQuery, args=$args")
|
||||||
// }, Dispatchers.IO.asExecutor())
|
// }, WholphinDispatchers.IO.asExecutor())
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,9 @@ import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
import com.github.damontecres.wholphin.ui.data.RowColumn
|
import com.github.damontecres.wholphin.ui.data.RowColumn
|
||||||
import com.github.damontecres.wholphin.ui.data.RowColumnSaver
|
import com.github.damontecres.wholphin.ui.data.RowColumnSaver
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.CoroutineStart
|
import kotlinx.coroutines.CoroutineStart
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
|
@ -359,34 +359,34 @@ suspend fun showToast(
|
||||||
context: Context,
|
context: Context,
|
||||||
text: CharSequence,
|
text: CharSequence,
|
||||||
duration: Int,
|
duration: Int,
|
||||||
) = withContext(Dispatchers.Main) {
|
) = withContext(WholphinDispatchers.Main) {
|
||||||
Toast.makeText(context, text, duration).show()
|
Toast.makeText(context, text, duration).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun showToast(
|
suspend fun showToast(
|
||||||
context: Context,
|
context: Context,
|
||||||
text: CharSequence,
|
text: CharSequence,
|
||||||
) = withContext(Dispatchers.Main) {
|
) = withContext(WholphinDispatchers.Main) {
|
||||||
Toast.makeText(context, text, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, text, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launches a coroutine with [Dispatchers.IO] plus the provided [CoroutineContext] defaulting to using [ExceptionHandler]
|
* Launches a coroutine with [WholphinDispatchers.IO] plus the provided [CoroutineContext] defaulting to using [ExceptionHandler]
|
||||||
*/
|
*/
|
||||||
fun CoroutineScope.launchIO(
|
fun CoroutineScope.launchIO(
|
||||||
context: CoroutineContext = ExceptionHandler(),
|
context: CoroutineContext = ExceptionHandler(),
|
||||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
block: suspend CoroutineScope.() -> Unit,
|
block: suspend CoroutineScope.() -> Unit,
|
||||||
): Job = launch(context = Dispatchers.IO + context, start = start, block = block)
|
): Job = launch(context = WholphinDispatchers.IO + context, start = start, block = block)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launches a coroutine with [Dispatchers.Default] plus the provided [CoroutineContext] defaulting to using [ExceptionHandler]
|
* Launches a coroutine with [WholphinDispatchers.Default] plus the provided [CoroutineContext] defaulting to using [ExceptionHandler]
|
||||||
*/
|
*/
|
||||||
fun CoroutineScope.launchDefault(
|
fun CoroutineScope.launchDefault(
|
||||||
context: CoroutineContext = ExceptionHandler(),
|
context: CoroutineContext = ExceptionHandler(),
|
||||||
start: CoroutineStart = CoroutineStart.DEFAULT,
|
start: CoroutineStart = CoroutineStart.DEFAULT,
|
||||||
block: suspend CoroutineScope.() -> Unit,
|
block: suspend CoroutineScope.() -> Unit,
|
||||||
): Job = launch(context = Dispatchers.Default + context, start = start, block = block)
|
): Job = launch(context = WholphinDispatchers.Default + context, start = start, block = block)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a UUID to the format used server-side (ie without hyphens).
|
* Converts a UUID to the format used server-side (ie without hyphens).
|
||||||
|
|
@ -410,7 +410,7 @@ fun logTab(
|
||||||
ACRA.errorReporter.putCustomData("tabInfo", info)
|
ACRA.errorReporter.putCustomData("tabInfo", info)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun <T> onMain(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block)
|
suspend fun <T> onMain(block: suspend CoroutineScope.() -> T) = withContext(WholphinDispatchers.Main, block)
|
||||||
|
|
||||||
fun Modifier.dimAndBlur(enabled: Boolean) =
|
fun Modifier.dimAndBlur(enabled: Boolean) =
|
||||||
this.ifElse(
|
this.ifElse(
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import coil3.request.crossfade
|
||||||
import com.github.damontecres.wholphin.ui.AspectRatios
|
import com.github.damontecres.wholphin.ui.AspectRatios
|
||||||
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
||||||
import com.github.damontecres.wholphin.ui.components.Genre
|
import com.github.damontecres.wholphin.ui.components.Genre
|
||||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
|
||||||
import com.github.damontecres.wholphin.ui.setup.rememberIdColor
|
import com.github.damontecres.wholphin.ui.setup.rememberIdColor
|
||||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,7 @@ import coil3.request.ImageRequest
|
||||||
import coil3.request.crossfade
|
import coil3.request.crossfade
|
||||||
import com.github.damontecres.wholphin.ui.AspectRatios
|
import com.github.damontecres.wholphin.ui.AspectRatios
|
||||||
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
||||||
import com.github.damontecres.wholphin.ui.components.Genre
|
|
||||||
import com.github.damontecres.wholphin.ui.components.Studio
|
import com.github.damontecres.wholphin.ui.components.Studio
|
||||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
|
||||||
import com.github.damontecres.wholphin.ui.setup.rememberIdColor
|
import com.github.damontecres.wholphin.ui.setup.rememberIdColor
|
||||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,13 @@ import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.GetPersonsHandler
|
import com.github.damontecres.wholphin.util.GetPersonsHandler
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.successValue
|
import com.github.damontecres.wholphin.util.successValue
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.catch
|
import kotlinx.coroutines.flow.catch
|
||||||
|
|
@ -251,7 +251,7 @@ class CollectionFolderViewModel
|
||||||
|
|
||||||
fun saveViewOptions(viewOptions: ViewOptions) {
|
fun saveViewOptions(viewOptions: ViewOptions) {
|
||||||
_state.update { it.copy(viewOptions = viewOptions) }
|
_state.update { it.copy(viewOptions = viewOptions) }
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
saveLibraryDisplayInfo(viewOptions = viewOptions)
|
saveLibraryDisplayInfo(viewOptions = viewOptions)
|
||||||
if (!viewOptions.showBackdrop) {
|
if (!viewOptions.showBackdrop) {
|
||||||
backdropService.clearBackdrop()
|
backdropService.clearBackdrop()
|
||||||
|
|
@ -295,7 +295,7 @@ class CollectionFolderViewModel
|
||||||
recursive: Boolean,
|
recursive: Boolean,
|
||||||
filter: GetItemsFilter,
|
filter: GetItemsFilter,
|
||||||
useSeriesForPrimary: Boolean,
|
useSeriesForPrimary: Boolean,
|
||||||
) = viewModelScope.launch(Dispatchers.IO) {
|
) = viewModelScope.launch(WholphinDispatchers.IO) {
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
items = DataLoadingState.Loading,
|
items = DataLoadingState.Loading,
|
||||||
|
|
@ -437,7 +437,7 @@ class CollectionFolderViewModel
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun positionOfLetter(letter: Char): Int? =
|
suspend fun positionOfLetter(letter: Char): Int? =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val sort = state.value.sortAndDirection
|
val sort = state.value.sortAndDirection
|
||||||
val filter = state.value.filter
|
val filter = state.value.filter
|
||||||
val request =
|
val request =
|
||||||
|
|
@ -461,7 +461,7 @@ class CollectionFolderViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setWatched(itemId, played)
|
favoriteWatchManager.setWatched(itemId, played)
|
||||||
(state.value.items as? DataLoadingState.Success)?.let {
|
(state.value.items as? DataLoadingState.Success)?.let {
|
||||||
(it.data as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
(it.data as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
||||||
|
|
@ -474,7 +474,7 @@ class CollectionFolderViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
(state.value.items as? DataLoadingState.Success)?.let {
|
(state.value.items as? DataLoadingState.Success)?.let {
|
||||||
(it.data as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
(it.data as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
||||||
|
|
|
||||||
|
|
@ -33,13 +33,13 @@ import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
import com.github.damontecres.wholphin.util.GetGenresRequestHandler
|
import com.github.damontecres.wholphin.util.GetGenresRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.mayakapps.kache.InMemoryKache
|
import com.mayakapps.kache.InMemoryKache
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -142,7 +142,7 @@ class GenreViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun positionOfLetter(letter: Char): Int =
|
suspend fun positionOfLetter(letter: Char): Int =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val request =
|
val request =
|
||||||
GetGenresRequest(
|
GetGenresRequest(
|
||||||
parentId = itemId,
|
parentId = itemId,
|
||||||
|
|
@ -197,7 +197,7 @@ suspend fun getGenreImageMap(
|
||||||
val semaphore = Semaphore(4)
|
val semaphore = Semaphore(4)
|
||||||
genres
|
genres
|
||||||
.map { genreId ->
|
.map { genreId ->
|
||||||
scope.async(Dispatchers.IO) {
|
scope.async(WholphinDispatchers.IO) {
|
||||||
semaphore.withPermit {
|
semaphore.withPermit {
|
||||||
val item =
|
val item =
|
||||||
GetItemsRequestHandler
|
GetItemsRequestHandler
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,13 @@ import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.RequestHandler
|
import com.github.damontecres.wholphin.util.RequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
@ -150,7 +150,7 @@ class ItemGridViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setWatched(itemId, played)
|
favoriteWatchManager.setWatched(itemId, played)
|
||||||
(state.value.items as? DataLoadingState.Success)?.let {
|
(state.value.items as? DataLoadingState.Success)?.let {
|
||||||
(it.data as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
(it.data as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
||||||
|
|
@ -163,7 +163,7 @@ class ItemGridViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
(state.value.items as? DataLoadingState.Success)?.let {
|
(state.value.items as? DataLoadingState.Success)?.let {
|
||||||
(it.data as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
(it.data as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
||||||
|
|
|
||||||
|
|
@ -48,13 +48,13 @@ import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
import com.github.damontecres.wholphin.util.RequestHandler
|
import com.github.damontecres.wholphin.util.RequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
|
|
@ -173,7 +173,7 @@ class RecommendedViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchSuggestions() {
|
private fun fetchSuggestions() {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(WholphinDispatchers.IO) {
|
||||||
val limit =
|
val limit =
|
||||||
userPreferencesService
|
userPreferencesService
|
||||||
.getCurrent()
|
.getCurrent()
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,11 @@ import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
import com.github.damontecres.wholphin.util.GetStudiosRequestHandler
|
import com.github.damontecres.wholphin.util.GetStudiosRequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
@ -113,7 +113,7 @@ class StudioViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun positionOfLetter(letter: Char): Int =
|
suspend fun positionOfLetter(letter: Char): Int =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val request =
|
val request =
|
||||||
GetStudiosRequest(
|
GetStudiosRequest(
|
||||||
userId = serverRepository.currentUser?.id,
|
userId = serverRepository.currentUser?.id,
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ import android.speech.RecognizerIntent
|
||||||
import android.speech.SpeechRecognizer
|
import android.speech.SpeechRecognizer
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.android.asCoroutineDispatcher
|
import kotlinx.coroutines.android.asCoroutineDispatcher
|
||||||
|
|
@ -175,7 +175,7 @@ class VoiceInputManager
|
||||||
|
|
||||||
private fun provideMainDispatcher(): CoroutineDispatcher =
|
private fun provideMainDispatcher(): CoroutineDispatcher =
|
||||||
try {
|
try {
|
||||||
Dispatchers.Main.immediate
|
WholphinDispatchers.Main.immediate
|
||||||
} catch (_: IllegalStateException) {
|
} catch (_: IllegalStateException) {
|
||||||
// Fallback for unit tests where Main dispatcher is not installed
|
// Fallback for unit tests where Main dispatcher is not installed
|
||||||
handler.asCoroutineDispatcher()
|
handler.asCoroutineDispatcher()
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ import com.github.damontecres.wholphin.ui.playback.isForwardButton
|
||||||
import com.github.damontecres.wholphin.ui.playback.isPlayKeyUp
|
import com.github.damontecres.wholphin.ui.playback.isPlayKeyUp
|
||||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
@ -217,7 +217,7 @@ fun <T : CardGridItem> CardGrid(
|
||||||
{ letter: Char ->
|
{ letter: Char ->
|
||||||
scope.launch(ExceptionHandler()) {
|
scope.launch(ExceptionHandler()) {
|
||||||
val jumpPosition =
|
val jumpPosition =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
letterPosition.invoke(letter)
|
letterPosition.invoke(letter)
|
||||||
}
|
}
|
||||||
Timber.d("Alphabet jump to $jumpPosition")
|
Timber.d("Alphabet jump to $jumpPosition")
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,12 @@ import com.github.damontecres.wholphin.ui.util.StringStringProvider
|
||||||
import com.github.damontecres.wholphin.util.ApiRequestPager
|
import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
@ -166,7 +166,7 @@ class HomeRowGridViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setWatched(itemId, played)
|
favoriteWatchManager.setWatched(itemId, played)
|
||||||
(state.value.loading as? HomeRowLoadingState.Success)?.let {
|
(state.value.loading as? HomeRowLoadingState.Success)?.let {
|
||||||
(it.items as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
(it.items as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
||||||
|
|
@ -179,7 +179,7 @@ class HomeRowGridViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
(state.value.loading as? HomeRowLoadingState.Success)?.let {
|
(state.value.loading as? HomeRowLoadingState.Success)?.let {
|
||||||
(it.items as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
(it.items as? ApiRequestPager<*>)?.refreshItem(position, itemId)
|
||||||
|
|
|
||||||
|
|
@ -107,12 +107,12 @@ import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -316,14 +316,14 @@ class PlaylistViewModel
|
||||||
fun setWatched(
|
fun setWatched(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setWatched(itemId, played)
|
favoriteWatchManager.setWatched(itemId, played)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setFavorite(
|
fun setFavorite(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,12 @@ import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -210,7 +210,7 @@ class CollectionViewModel
|
||||||
supervisorScope {
|
supervisorScope {
|
||||||
val jobs =
|
val jobs =
|
||||||
typesInCollection.map { type ->
|
typesInCollection.map { type ->
|
||||||
async(Dispatchers.IO) {
|
async(WholphinDispatchers.IO) {
|
||||||
val title = ResStringProvider(formatTypeName(type))
|
val title = ResStringProvider(formatTypeName(type))
|
||||||
val result =
|
val result =
|
||||||
try {
|
try {
|
||||||
|
|
@ -359,7 +359,7 @@ class CollectionViewModel
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun letterPosition(letter: Char): Int =
|
suspend fun letterPosition(letter: Char): Int =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val sort = state.value.sortAndDirection
|
val sort = state.value.sortAndDirection
|
||||||
val filter = state.value.itemFilter
|
val filter = state.value.itemFilter
|
||||||
val request =
|
val request =
|
||||||
|
|
@ -387,7 +387,7 @@ class CollectionViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
position: RowColumn?,
|
position: RowColumn?,
|
||||||
) = viewModelScope.launch(Dispatchers.IO + ExceptionHandler()) {
|
) = viewModelScope.launch(WholphinDispatchers.IO + ExceptionHandler()) {
|
||||||
favoriteWatchManager.setWatched(itemId, played)
|
favoriteWatchManager.setWatched(itemId, played)
|
||||||
if (itemId == state.value.collection?.id) {
|
if (itemId == state.value.collection?.id) {
|
||||||
refreshCollection()
|
refreshCollection()
|
||||||
|
|
@ -400,7 +400,7 @@ class CollectionViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
position: RowColumn?,
|
position: RowColumn?,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
if (itemId == state.value.collection?.id) {
|
if (itemId == state.value.collection?.id) {
|
||||||
refreshCollection()
|
refreshCollection()
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.showToast
|
import com.github.damontecres.wholphin.ui.showToast
|
||||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.successValue
|
import com.github.damontecres.wholphin.util.successValue
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
|
@ -31,7 +32,6 @@ import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -73,7 +73,7 @@ class DiscoverMovieViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchAndSetItem(): Deferred<MovieDetails?> =
|
private fun fetchAndSetItem(): Deferred<MovieDetails?> =
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val movie = seerrService.api.moviesApi.movieMovieIdGet(movieId = item.id)
|
val movie = seerrService.api.moviesApi.movieMovieIdGet(movieId = item.id)
|
||||||
_state.update { it.copy(movie = DataLoadingState.Success(movie)) }
|
_state.update { it.copy(movie = DataLoadingState.Success(movie)) }
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.showToast
|
import com.github.damontecres.wholphin.ui.showToast
|
||||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.successValue
|
import com.github.damontecres.wholphin.util.successValue
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
|
@ -30,7 +31,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -71,7 +71,7 @@ class DiscoverSeriesViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchAndSetItem(): Deferred<TvDetails?> =
|
private fun fetchAndSetItem(): Deferred<TvDetails?> =
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val tv = seerrService.api.tvApi.tvTvIdGet(tvId = item.id)
|
val tv = seerrService.api.tvApi.tvTvIdGet(tvId = item.id)
|
||||||
_state.update { it.copy(tvSeries = DataLoadingState.Success(tv)) }
|
_state.update { it.copy(tvSeries = DataLoadingState.Success(tv)) }
|
||||||
|
|
|
||||||
|
|
@ -23,13 +23,13 @@ import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.showToast
|
import com.github.damontecres.wholphin.ui.showToast
|
||||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -126,7 +126,7 @@ class EpisodeViewModel
|
||||||
fun setWatched(
|
fun setWatched(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setWatched(itemId, played)
|
favoriteWatchManager.setWatched(itemId, played)
|
||||||
fetchAndSetItem()
|
fetchAndSetItem()
|
||||||
}
|
}
|
||||||
|
|
@ -134,7 +134,7 @@ class EpisodeViewModel
|
||||||
fun setFavorite(
|
fun setFavorite(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
fetchAndSetItem()
|
fetchAndSetItem()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,11 +59,11 @@ import com.github.damontecres.wholphin.ui.rememberInt
|
||||||
import com.github.damontecres.wholphin.ui.rememberPosition
|
import com.github.damontecres.wholphin.ui.rememberPosition
|
||||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import eu.wewox.programguide.ProgramGuide
|
import eu.wewox.programguide.ProgramGuide
|
||||||
import eu.wewox.programguide.ProgramGuideDimensions
|
import eu.wewox.programguide.ProgramGuideDimensions
|
||||||
import eu.wewox.programguide.ProgramGuideItem
|
import eu.wewox.programguide.ProgramGuideItem
|
||||||
import eu.wewox.programguide.rememberSaveableProgramGuideState
|
import eu.wewox.programguide.rememberSaveableProgramGuideState
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
@ -319,7 +319,7 @@ fun TvGuideGridContent(
|
||||||
var focusedProgramIndex by rememberInt(0)
|
var focusedProgramIndex by rememberInt(0)
|
||||||
|
|
||||||
LaunchedEffect(onFocus, focusedProgramIndex) {
|
LaunchedEffect(onFocus, focusedProgramIndex) {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(WholphinDispatchers.Default) {
|
||||||
val program = programs.programs.getOrNull(focusedProgramIndex)
|
val program = programs.programs.getOrNull(focusedProgramIndex)
|
||||||
if (program != null) {
|
if (program != null) {
|
||||||
val channelIndex = channels.indexOfFirst { it.id == program.channelId }
|
val channelIndex = channels.indexOfFirst { it.id == program.channelId }
|
||||||
|
|
|
||||||
|
|
@ -86,12 +86,12 @@ import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -242,7 +242,7 @@ class AlbumViewModel
|
||||||
fun setFavorite(
|
fun setFavorite(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
val album =
|
val album =
|
||||||
api.userLibraryApi
|
api.userLibraryApi
|
||||||
|
|
|
||||||
|
|
@ -81,12 +81,12 @@ import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -254,7 +254,7 @@ class ArtistViewModel
|
||||||
fun setFavorite(
|
fun setFavorite(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
val artist =
|
val artist =
|
||||||
api.userLibraryApi
|
api.userLibraryApi
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ import com.github.damontecres.wholphin.ui.playback.ControllerViewState
|
||||||
import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackAction
|
import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackAction
|
||||||
import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackButton
|
import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackButton
|
||||||
import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackButtons
|
import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackButtons
|
||||||
import com.github.damontecres.wholphin.ui.playback.overlay.PlaybackFaButton
|
|
||||||
import com.github.damontecres.wholphin.ui.playback.overlay.buttonSpacing
|
import com.github.damontecres.wholphin.ui.playback.overlay.buttonSpacing
|
||||||
import com.github.damontecres.wholphin.ui.theme.PreviewInteractionSource
|
import com.github.damontecres.wholphin.ui.theme.PreviewInteractionSource
|
||||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,13 @@ import com.github.damontecres.wholphin.ui.launchDefault
|
||||||
import com.github.damontecres.wholphin.ui.main.settings.MoveDirection
|
import com.github.damontecres.wholphin.ui.main.settings.MoveDirection
|
||||||
import com.github.damontecres.wholphin.ui.onMain
|
import com.github.damontecres.wholphin.ui.onMain
|
||||||
import com.github.damontecres.wholphin.ui.playback.ControllerViewState
|
import com.github.damontecres.wholphin.ui.playback.ControllerViewState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.mayakapps.kache.InMemoryKache
|
import com.mayakapps.kache.InMemoryKache
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -95,7 +95,7 @@ class NowPlayingViewModel
|
||||||
|
|
||||||
private val lyricCache =
|
private val lyricCache =
|
||||||
InMemoryKache<UUID, LyricDto>(20) {
|
InMemoryKache<UUID, LyricDto>(20) {
|
||||||
creationScope = CoroutineScope(Dispatchers.IO)
|
creationScope = CoroutineScope(WholphinDispatchers.IO)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.tv.material3.DenseListItem
|
import androidx.tv.material3.DenseListItem
|
||||||
import androidx.tv.material3.Icon
|
import androidx.tv.material3.Icon
|
||||||
import androidx.tv.material3.ListItem
|
|
||||||
import androidx.tv.material3.ListItemDefaults
|
import androidx.tv.material3.ListItemDefaults
|
||||||
import androidx.tv.material3.LocalContentColor
|
import androidx.tv.material3.LocalContentColor
|
||||||
import androidx.tv.material3.Text
|
import androidx.tv.material3.Text
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetEpisodesRequestHandler
|
import com.github.damontecres.wholphin.util.GetEpisodesRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.successValue
|
import com.github.damontecres.wholphin.util.successValue
|
||||||
import com.google.common.cache.CacheBuilder
|
import com.google.common.cache.CacheBuilder
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
|
|
@ -50,7 +51,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
@ -137,7 +137,7 @@ class SeriesViewModel
|
||||||
|
|
||||||
val episodeListDeferred =
|
val episodeListDeferred =
|
||||||
if (seriesPageType == SeriesPageType.OVERVIEW) {
|
if (seriesPageType == SeriesPageType.OVERVIEW) {
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
if (seasonEpisodeIds != null) {
|
if (seasonEpisodeIds != null) {
|
||||||
loadEpisodesInternal(
|
loadEpisodesInternal(
|
||||||
seasonEpisodeIds.seasonId,
|
seasonEpisodeIds.seasonId,
|
||||||
|
|
@ -292,7 +292,7 @@ class SeriesViewModel
|
||||||
series: BaseItem,
|
series: BaseItem,
|
||||||
seasonNum: Int?,
|
seasonNum: Int?,
|
||||||
): Deferred<List<BaseItem?>> =
|
): Deferred<List<BaseItem?>> =
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
Timber.v("getSeasons for %s", series.id)
|
Timber.v("getSeasons for %s", series.id)
|
||||||
val request =
|
val request =
|
||||||
GetItemsRequest(
|
GetItemsRequest(
|
||||||
|
|
@ -405,7 +405,7 @@ class SeriesViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
listIndex: Int?,
|
listIndex: Int?,
|
||||||
) = viewModelScope.launch(Dispatchers.IO + ExceptionHandler()) {
|
) = viewModelScope.launch(WholphinDispatchers.IO + ExceptionHandler()) {
|
||||||
favoriteWatchManager.setWatched(itemId, played)
|
favoriteWatchManager.setWatched(itemId, played)
|
||||||
listIndex?.let {
|
listIndex?.let {
|
||||||
refreshEpisode(itemId, listIndex)
|
refreshEpisode(itemId, listIndex)
|
||||||
|
|
@ -440,7 +440,7 @@ class SeriesViewModel
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
listIndex: Int?,
|
listIndex: Int?,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
if (listIndex != null) {
|
if (listIndex != null) {
|
||||||
refreshEpisode(itemId, listIndex)
|
refreshEpisode(itemId, listIndex)
|
||||||
|
|
@ -452,13 +452,13 @@ class SeriesViewModel
|
||||||
fun setSeasonWatched(
|
fun setSeasonWatched(
|
||||||
seasonId: UUID,
|
seasonId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
) = viewModelScope.launch(Dispatchers.IO + ExceptionHandler()) {
|
) = viewModelScope.launch(WholphinDispatchers.IO + ExceptionHandler()) {
|
||||||
setWatched(seasonId, played, null)
|
setWatched(seasonId, played, null)
|
||||||
updateSeries()
|
updateSeries()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setWatchedSeries(played: Boolean) =
|
fun setWatchedSeries(played: Boolean) =
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setWatched(seriesId, played)
|
favoriteWatchManager.setWatched(seriesId, played)
|
||||||
updateSeries()
|
updateSeries()
|
||||||
}
|
}
|
||||||
|
|
@ -466,7 +466,7 @@ class SeriesViewModel
|
||||||
fun refreshEpisode(
|
fun refreshEpisode(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
listIndex: Int,
|
listIndex: Int,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
val eps = state.value.episodes
|
val eps = state.value.episodes
|
||||||
if (eps is EpisodeList.Success) {
|
if (eps is EpisodeList.Success) {
|
||||||
eps.episodes.refreshItem(listIndex, itemId)
|
eps.episodes.refreshItem(listIndex, itemId)
|
||||||
|
|
@ -481,7 +481,7 @@ class SeriesViewModel
|
||||||
* Play whichever episode is next up for series or else the first episode
|
* Play whichever episode is next up for series or else the first episode
|
||||||
*/
|
*/
|
||||||
fun playNextUp() {
|
fun playNextUp() {
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
val result by api.tvShowsApi.getNextUp(seriesId = seriesId)
|
val result by api.tvShowsApi.getNextUp(seriesId = seriesId)
|
||||||
val nextUp =
|
val nextUp =
|
||||||
result.items.firstOrNull() ?: api.tvShowsApi
|
result.items.firstOrNull() ?: api.tvShowsApi
|
||||||
|
|
@ -491,7 +491,7 @@ class SeriesViewModel
|
||||||
).content.items
|
).content.items
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
if (nextUp != null) {
|
if (nextUp != null) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
navigateTo(Destination.Playback(BaseItem(nextUp)))
|
navigateTo(Destination.Playback(BaseItem(nextUp)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -582,7 +582,7 @@ class SeriesViewModel
|
||||||
val result =
|
val result =
|
||||||
peopleInEpisodeCache
|
peopleInEpisodeCache
|
||||||
.get(item.id) {
|
.get(item.id) {
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
val list =
|
val list =
|
||||||
api.userLibraryApi
|
api.userLibraryApi
|
||||||
.getItem(item.id)
|
.getItem(item.id)
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -77,7 +77,7 @@ class SeerrRequestsViewModel
|
||||||
val requests =
|
val requests =
|
||||||
mediaRequests.mapNotNull { request ->
|
mediaRequests.mapNotNull { request ->
|
||||||
if (request.media?.tmdbId != null) {
|
if (request.media?.tmdbId != null) {
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
semaphore.withPermit {
|
semaphore.withPermit {
|
||||||
val type = SeerrItemType.fromString(request.type)
|
val type = SeerrItemType.fromString(request.type)
|
||||||
when (type) {
|
when (type) {
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,9 @@ import com.github.damontecres.wholphin.ui.util.EmptyStringProvider
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -117,7 +117,7 @@ class HomeViewModel
|
||||||
val deferred =
|
val deferred =
|
||||||
settings.rows
|
settings.rows
|
||||||
.map { row ->
|
.map { row ->
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
semaphore.withPermit {
|
semaphore.withPermit {
|
||||||
Timber.v("Fetching row: %s", row)
|
Timber.v("Fetching row: %s", row)
|
||||||
try {
|
try {
|
||||||
|
|
@ -220,9 +220,9 @@ class HomeViewModel
|
||||||
fun setWatched(
|
fun setWatched(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
played: Boolean,
|
played: Boolean,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setWatched(itemId, played)
|
favoriteWatchManager.setWatched(itemId, played)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
init()
|
init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -230,9 +230,9 @@ class HomeViewModel
|
||||||
fun setFavorite(
|
fun setFavorite(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
favorite: Boolean,
|
favorite: Boolean,
|
||||||
) = viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
) = viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
favoriteWatchManager.setFavorite(itemId, favorite)
|
favoriteWatchManager.setFavorite(itemId, favorite)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
init()
|
init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -103,9 +103,9 @@ import com.github.damontecres.wholphin.ui.rememberPosition
|
||||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.SearchRelevance
|
import com.github.damontecres.wholphin.util.SearchRelevance
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
@ -253,7 +253,7 @@ class SearchViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun searchCombined(query: String) {
|
private fun searchCombined(query: String) {
|
||||||
viewModelScope.launch(ExceptionHandler() + Dispatchers.IO) {
|
viewModelScope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val request =
|
val request =
|
||||||
GetItemsRequest(
|
GetItemsRequest(
|
||||||
|
|
@ -477,7 +477,7 @@ fun SearchPage(
|
||||||
) {
|
) {
|
||||||
if (!searchClicked) return@LaunchedEffect
|
if (!searchClicked) return@LaunchedEffect
|
||||||
|
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
// Want to focus on the first successful row after all of the ones before it are finished searching
|
// Want to focus on the first successful row after all of the ones before it are finished searching
|
||||||
val results =
|
val results =
|
||||||
if (isLibraryTab) {
|
if (isLibraryTab) {
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,10 @@ import com.github.damontecres.wholphin.ui.util.ResStringProvider
|
||||||
import com.github.damontecres.wholphin.ui.util.StringStringProvider
|
import com.github.damontecres.wholphin.ui.util.StringStringProvider
|
||||||
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
import com.github.damontecres.wholphin.util.HomeRowLoadingState
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
|
|
@ -129,7 +129,7 @@ class HomeSettingsViewModel
|
||||||
.let { state ->
|
.let { state ->
|
||||||
state.rows
|
state.rows
|
||||||
.map { row ->
|
.map { row ->
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
semaphore.withPermit {
|
semaphore.withPermit {
|
||||||
try {
|
try {
|
||||||
homeSettingsService.fetchDataForRow(
|
homeSettingsService.fetchDataForRow(
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
import com.github.damontecres.wholphin.util.PlaybackItemState
|
import com.github.damontecres.wholphin.util.PlaybackItemState
|
||||||
import com.github.damontecres.wholphin.util.TrackActivityPlaybackListener
|
import com.github.damontecres.wholphin.util.TrackActivityPlaybackListener
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import com.github.damontecres.wholphin.util.checkForSupport
|
import com.github.damontecres.wholphin.util.checkForSupport
|
||||||
import com.github.damontecres.wholphin.util.mpv.MpvPlayer
|
import com.github.damontecres.wholphin.util.mpv.MpvPlayer
|
||||||
import com.github.damontecres.wholphin.util.mpv.mpvDeviceProfile
|
import com.github.damontecres.wholphin.util.mpv.mpvDeviceProfile
|
||||||
|
|
@ -79,7 +80,6 @@ import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -242,7 +242,7 @@ class PlaybackViewModel
|
||||||
Timber.d("Selected backend: %s", playerBackend)
|
Timber.d("Selected backend: %s", playerBackend)
|
||||||
if (currentPlayer.value?.backend != playerBackend) {
|
if (currentPlayer.value?.backend != playerBackend) {
|
||||||
Timber.i("Switching player backend to %s", playerBackend)
|
Timber.i("Switching player backend to %s", playerBackend)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
disconnectPlayer()
|
disconnectPlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -421,7 +421,7 @@ class PlaybackViewModel
|
||||||
positionMs: Long,
|
positionMs: Long,
|
||||||
forceTranscoding: Boolean = this.forceTranscoding,
|
forceTranscoding: Boolean = this.forceTranscoding,
|
||||||
): Boolean =
|
): Boolean =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val item =
|
val item =
|
||||||
when (playlistItem) {
|
when (playlistItem) {
|
||||||
is PlaylistItem.Intro -> playlistItem.item
|
is PlaylistItem.Intro -> playlistItem.item
|
||||||
|
|
@ -581,7 +581,7 @@ class PlaybackViewModel
|
||||||
trickPlayInfo = trickPlayInfo,
|
trickPlayInfo = trickPlayInfo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
changeStreams(
|
changeStreams(
|
||||||
item,
|
item,
|
||||||
itemPlaybackToUse,
|
itemPlaybackToUse,
|
||||||
|
|
@ -612,7 +612,7 @@ class PlaybackViewModel
|
||||||
userInitiated: Boolean,
|
userInitiated: Boolean,
|
||||||
enableDirectPlay: Boolean = !this.forceTranscoding,
|
enableDirectPlay: Boolean = !this.forceTranscoding,
|
||||||
enableDirectStream: Boolean = !this.forceTranscoding,
|
enableDirectStream: Boolean = !this.forceTranscoding,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(WholphinDispatchers.IO) {
|
||||||
val itemId = item.id
|
val itemId = item.id
|
||||||
|
|
||||||
val currentPlayback = state.value.currentPlayback
|
val currentPlayback = state.value.currentPlayback
|
||||||
|
|
@ -779,7 +779,7 @@ class PlaybackViewModel
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
// TODO, don't need to release & recreate when switching streams
|
// TODO, don't need to release & recreate when switching streams
|
||||||
this@PlaybackViewModel.activityListener?.let {
|
this@PlaybackViewModel.activityListener?.let {
|
||||||
it.release()
|
it.release()
|
||||||
|
|
@ -850,7 +850,7 @@ class PlaybackViewModel
|
||||||
subtitleIndex: Int?,
|
subtitleIndex: Int?,
|
||||||
userInitiated: Boolean,
|
userInitiated: Boolean,
|
||||||
): Boolean =
|
): Boolean =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
// TODO there's probably no reason why we can't add external subtitles?
|
// TODO there's probably no reason why we can't add external subtitles?
|
||||||
Timber.v("changeStreams direct play")
|
Timber.v("changeStreams direct play")
|
||||||
|
|
||||||
|
|
@ -859,7 +859,7 @@ class PlaybackViewModel
|
||||||
|
|
||||||
if (externalSubtitle == null) {
|
if (externalSubtitle == null) {
|
||||||
val result =
|
val result =
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
TrackSelectionUtils.createTrackSelections(
|
TrackSelectionUtils.createTrackSelections(
|
||||||
onMain { player.trackSelectionParameters },
|
onMain { player.trackSelectionParameters },
|
||||||
onMain { player.currentTracks },
|
onMain { player.currentTracks },
|
||||||
|
|
@ -1124,7 +1124,7 @@ class PlaybackViewModel
|
||||||
MediaSegmentType.INTRO -> prefs.skipIntros
|
MediaSegmentType.INTRO -> prefs.skipIntros
|
||||||
MediaSegmentType.UNKNOWN -> SkipSegmentBehavior.IGNORE
|
MediaSegmentType.UNKNOWN -> SkipSegmentBehavior.IGNORE
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
val newSegment =
|
val newSegment =
|
||||||
when (behavior) {
|
when (behavior) {
|
||||||
SkipSegmentBehavior.AUTO_SKIP -> {
|
SkipSegmentBehavior.AUTO_SKIP -> {
|
||||||
|
|
@ -1318,7 +1318,7 @@ class PlaybackViewModel
|
||||||
|
|
||||||
override fun onPlayerError(error: PlaybackException) {
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
Timber.e(error, "Playback error")
|
Timber.e(error, "Playback error")
|
||||||
viewModelScope.launch(Dispatchers.Main + ExceptionHandler()) {
|
viewModelScope.launch(WholphinDispatchers.Main + ExceptionHandler()) {
|
||||||
state.value.currentPlayback?.let {
|
state.value.currentPlayback?.let {
|
||||||
when (it.playMethod) {
|
when (it.playMethod) {
|
||||||
PlayMethod.TRANSCODE -> {
|
PlayMethod.TRANSCODE -> {
|
||||||
|
|
@ -1346,7 +1346,7 @@ class PlaybackViewModel
|
||||||
enableDirectPlay = false,
|
enableDirectPlay = false,
|
||||||
enableDirectStream = false,
|
enableDirectStream = false,
|
||||||
)
|
)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
player.prepare()
|
player.prepare()
|
||||||
player.play()
|
player.play()
|
||||||
}
|
}
|
||||||
|
|
@ -1367,7 +1367,7 @@ class PlaybackViewModel
|
||||||
.subscribe<PlaystateMessage>()
|
.subscribe<PlaystateMessage>()
|
||||||
.onEach { message ->
|
.onEach { message ->
|
||||||
message.data?.let {
|
message.data?.let {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
when (it.command) {
|
when (it.command) {
|
||||||
PlaystateCommand.STOP -> {
|
PlaystateCommand.STOP -> {
|
||||||
release()
|
release()
|
||||||
|
|
@ -1422,7 +1422,7 @@ class PlaybackViewModel
|
||||||
* Atomically update [currentMediaInfo]
|
* Atomically update [currentMediaInfo]
|
||||||
*/
|
*/
|
||||||
internal suspend fun updateCurrentMedia(block: (CurrentMediaInfo) -> CurrentMediaInfo) =
|
internal suspend fun updateCurrentMedia(block: (CurrentMediaInfo) -> CurrentMediaInfo) =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
_state.update {
|
_state.update {
|
||||||
it.copy(currentMediaInfo = block.invoke(it.currentMediaInfo))
|
it.copy(currentMediaInfo = block.invoke(it.currentMediaInfo))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import com.github.damontecres.wholphin.data.model.TrackIndex
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.onMain
|
import com.github.damontecres.wholphin.ui.onMain
|
||||||
import com.github.damontecres.wholphin.ui.showToast
|
import com.github.damontecres.wholphin.ui.showToast
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -183,7 +183,7 @@ fun PlaybackViewModel.downloadAndSwitchSubtitles(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
subtitleSearchState.update { it.copy(status = SubtitleSearchStatus.Inactive) }
|
subtitleSearchState.update { it.copy(status = SubtitleSearchStatus.Inactive) }
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
if (wasPlaying) {
|
if (wasPlaying) {
|
||||||
player.play()
|
player.play()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
import com.github.damontecres.wholphin.util.TrackSupport
|
import com.github.damontecres.wholphin.util.TrackSupport
|
||||||
import com.github.damontecres.wholphin.util.TrackSupportReason
|
import com.github.damontecres.wholphin.util.TrackSupportReason
|
||||||
import com.github.damontecres.wholphin.util.TrackType
|
import com.github.damontecres.wholphin.util.TrackType
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -90,7 +90,7 @@ fun PlaybackDebugOverlay(
|
||||||
)
|
)
|
||||||
|
|
||||||
val memoryUsed by produceState("") {
|
val memoryUsed by produceState("") {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(WholphinDispatchers.Default) {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
val runtime = Runtime.getRuntime()
|
val runtime = Runtime.getRuntime()
|
||||||
val total = runtime.totalMemory()
|
val total = runtime.totalMemory()
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import androidx.compose.ui.window.Dialog
|
||||||
import androidx.compose.ui.window.DialogProperties
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.asFlow
|
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.tv.material3.Text
|
import androidx.tv.material3.Text
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,9 @@ import com.github.damontecres.wholphin.ui.main.settings.MoveDirection
|
||||||
import com.github.damontecres.wholphin.ui.nav.NavDrawerItem
|
import com.github.damontecres.wholphin.ui.nav.NavDrawerItem
|
||||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.firstOrNull
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
|
|
@ -317,7 +317,7 @@ class NavDrawerPreferencesViewModel
|
||||||
return@launchDefault
|
return@launchDefault
|
||||||
}
|
}
|
||||||
val navDrawerPins =
|
val navDrawerPins =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
serverPreferencesDao
|
serverPreferencesDao
|
||||||
.getNavDrawerPinnedItems(user)
|
.getNavDrawerPinnedItems(user)
|
||||||
.associateBy { it.itemId }
|
.associateBy { it.itemId }
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.ui.FontAwesome
|
import com.github.damontecres.wholphin.ui.FontAwesome
|
||||||
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
||||||
import com.github.damontecres.wholphin.ui.components.BasicDialog
|
import com.github.damontecres.wholphin.ui.components.BasicDialog
|
||||||
import com.github.damontecres.wholphin.ui.components.Button
|
|
||||||
import com.github.damontecres.wholphin.ui.components.TextButton
|
import com.github.damontecres.wholphin.ui.components.TextButton
|
||||||
import com.github.damontecres.wholphin.ui.playback.isEnterKey
|
import com.github.damontecres.wholphin.ui.playback.isEnterKey
|
||||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@ import com.github.damontecres.wholphin.services.SetupNavigationManager
|
||||||
import com.github.damontecres.wholphin.ui.launchDefault
|
import com.github.damontecres.wholphin.ui.launchDefault
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Deferred
|
import kotlinx.coroutines.Deferred
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
@ -119,7 +119,7 @@ class SwitchUserViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
fun trySwitchUser(user: JellyfinUser): Deferred<String?> =
|
fun trySwitchUser(user: JellyfinUser): Deferred<String?> =
|
||||||
viewModelScope.async(Dispatchers.IO) {
|
viewModelScope.async(WholphinDispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val current = serverRepository.changeUser(server, user)
|
val current = serverRepository.changeUser(server, user)
|
||||||
setupNavigationManager.navigateTo(SetupDestination.AppContent(current))
|
setupNavigationManager.navigateTo(SetupDestination.AppContent(current))
|
||||||
|
|
@ -234,7 +234,7 @@ class SwitchUserViewModel
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getUsers(): List<JellyfinUserAndImage> =
|
private suspend fun getUsers(): List<JellyfinUserAndImage> =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(WholphinDispatchers.IO) {
|
||||||
val api = jellyfin.createApi(server.url)
|
val api = jellyfin.createApi(server.url)
|
||||||
val knownUsers =
|
val knownUsers =
|
||||||
serverDao
|
serverDao
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,13 @@ import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
import dagger.assisted.AssistedInject
|
import dagger.assisted.AssistedInject
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
@ -377,7 +377,7 @@ class SlideshowViewModel
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
Timber.d("Saved VideoFilter for image %s", it.image.id)
|
Timber.d("Saved VideoFilter for image %s", it.image.id)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
showToast(
|
showToast(
|
||||||
context,
|
context,
|
||||||
"Saved",
|
"Saved",
|
||||||
|
|
@ -406,7 +406,7 @@ class SlideshowViewModel
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
Timber.d("Saved VideoFilter for album %s", slideshowSettings.parentId)
|
Timber.d("Saved VideoFilter for album %s", slideshowSettings.parentId)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
showToast(
|
showToast(
|
||||||
context,
|
context,
|
||||||
"Saved",
|
"Saved",
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import androidx.compose.runtime.compositionLocalOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import com.github.damontecres.wholphin.ui.getTimeFormatter
|
import com.github.damontecres.wholphin.ui.getTimeFormatter
|
||||||
import kotlinx.coroutines.Dispatchers
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -34,7 +34,7 @@ data class Clock(
|
||||||
fun ProvideLocalClock(content: @Composable () -> Unit) {
|
fun ProvideLocalClock(content: @Composable () -> Unit) {
|
||||||
val clock = remember { Clock() }
|
val clock = remember { Clock() }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
withContext(Dispatchers.Default) {
|
withContext(WholphinDispatchers.Default) {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
val now = LocalDateTime.now()
|
val now = LocalDateTime.now()
|
||||||
val time = getTimeFormatter().format(now)
|
val time = getTimeFormatter().format(now)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package com.github.damontecres.wholphin.util
|
package com.github.damontecres.wholphin.util
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.ApiClientFactory
|
import org.jellyfin.sdk.api.client.ApiClientFactory
|
||||||
|
|
@ -21,7 +20,7 @@ import kotlin.coroutines.CoroutineContext
|
||||||
*/
|
*/
|
||||||
class CoroutineContextApiClient(
|
class CoroutineContextApiClient(
|
||||||
private val client: ApiClient,
|
private val client: ApiClient,
|
||||||
private val coroutineContext: CoroutineContext = Dispatchers.IO,
|
private val coroutineContext: CoroutineContext = WholphinDispatchers.IO,
|
||||||
) : ApiClient() {
|
) : ApiClient() {
|
||||||
override val baseUrl: String?
|
override val baseUrl: String?
|
||||||
get() = client.baseUrl
|
get() = client.baseUrl
|
||||||
|
|
@ -65,7 +64,7 @@ class CoroutineContextApiClient(
|
||||||
|
|
||||||
class CoroutineContextApiClientFactory(
|
class CoroutineContextApiClientFactory(
|
||||||
private val factory: OkHttpFactory,
|
private val factory: OkHttpFactory,
|
||||||
private val coroutineContext: CoroutineContext = Dispatchers.IO,
|
private val coroutineContext: CoroutineContext = WholphinDispatchers.IO,
|
||||||
) : ApiClientFactory,
|
) : ApiClientFactory,
|
||||||
SocketConnectionFactory {
|
SocketConnectionFactory {
|
||||||
override fun create(
|
override fun create(
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import androidx.compose.runtime.setValue
|
||||||
import com.github.damontecres.wholphin.ui.DEFAULT_PAGE_SIZE
|
import com.github.damontecres.wholphin.ui.DEFAULT_PAGE_SIZE
|
||||||
import com.google.common.cache.CacheBuilder
|
import com.google.common.cache.CacheBuilder
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
|
@ -85,7 +84,7 @@ abstract class RequestPager<T>(
|
||||||
get() = totalCount
|
get() = totalCount
|
||||||
|
|
||||||
private fun fetchPage(position: Int): Job =
|
private fun fetchPage(position: Int): Job =
|
||||||
scope.launch(ExceptionHandler() + Dispatchers.IO) {
|
scope.launch(ExceptionHandler() + WholphinDispatchers.IO) {
|
||||||
fetchPageBlocking(position, false)
|
fetchPageBlocking(position, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ import com.github.damontecres.wholphin.data.model.ItemPlayback
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.playback.CurrentPlayback
|
import com.github.damontecres.wholphin.ui.playback.CurrentPlayback
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.extensions.playStateApi
|
import org.jellyfin.sdk.api.client.extensions.playStateApi
|
||||||
|
|
@ -34,7 +33,7 @@ class TrackActivityPlaybackListener(
|
||||||
private val player: Player,
|
private val player: Player,
|
||||||
private val getState: () -> PlaybackItemState?,
|
private val getState: () -> PlaybackItemState?,
|
||||||
) : Player.Listener {
|
) : Player.Listener {
|
||||||
private val coroutineScope = CoroutineScope(Dispatchers.Main)
|
private val coroutineScope = CoroutineScope(WholphinDispatchers.Main)
|
||||||
private val task: TimerTask =
|
private val task: TimerTask =
|
||||||
object : TimerTask() {
|
object : TimerTask() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
|
|
@ -57,7 +56,7 @@ class TrackActivityPlaybackListener(
|
||||||
PlaybackStartInfo(
|
PlaybackStartInfo(
|
||||||
canSeek = true,
|
canSeek = true,
|
||||||
itemId = state.itemId,
|
itemId = state.itemId,
|
||||||
isPaused = withContext(Dispatchers.Main) { !player.isPlaying },
|
isPaused = withContext(WholphinDispatchers.Main) { !player.isPlaying },
|
||||||
playMethod = state.playMethod,
|
playMethod = state.playMethod,
|
||||||
repeatMode = RepeatMode.REPEAT_NONE,
|
repeatMode = RepeatMode.REPEAT_NONE,
|
||||||
playbackOrder = PlaybackOrder.DEFAULT,
|
playbackOrder = PlaybackOrder.DEFAULT,
|
||||||
|
|
@ -117,11 +116,11 @@ class TrackActivityPlaybackListener(
|
||||||
launch("saveActivity") {
|
launch("saveActivity") {
|
||||||
getState.invoke()?.let { state ->
|
getState.invoke()?.let { state ->
|
||||||
val calcPosition =
|
val calcPosition =
|
||||||
withContext(Dispatchers.Main) {
|
withContext(WholphinDispatchers.Main) {
|
||||||
(if (position >= 0) position else player.currentPosition)
|
(if (position >= 0) position else player.currentPosition)
|
||||||
}
|
}
|
||||||
if (calcPosition > 0) {
|
if (calcPosition > 0) {
|
||||||
val isPaused = withContext(Dispatchers.Main) { !player.isPlaying }
|
val isPaused = withContext(WholphinDispatchers.Main) { !player.isPlaying }
|
||||||
Timber.v("saveActivity: itemId=${state.itemId}, pos=$calcPosition")
|
Timber.v("saveActivity: itemId=${state.itemId}, pos=$calcPosition")
|
||||||
api.playStateApi.reportPlaybackProgress(
|
api.playStateApi.reportPlaybackProgress(
|
||||||
PlaybackProgressInfo(
|
PlaybackProgressInfo(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.github.damontecres.wholphin.util
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
|
import kotlinx.coroutines.MainCoroutineDispatcher
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Analogous to [kotlinx.coroutines.Dispatchers], but easier to swap for testing
|
||||||
|
*/
|
||||||
|
object WholphinDispatchers {
|
||||||
|
@Suppress("ktlint:standard:property-naming")
|
||||||
|
val Main: MainCoroutineDispatcher get() = kotlinx.coroutines.Dispatchers.Main
|
||||||
|
|
||||||
|
@Suppress("ktlint:standard:property-naming")
|
||||||
|
var IO: CoroutineDispatcher = kotlinx.coroutines.Dispatchers.IO
|
||||||
|
internal set
|
||||||
|
|
||||||
|
@Suppress("ktlint:standard:property-naming")
|
||||||
|
var Default: CoroutineDispatcher = kotlinx.coroutines.Dispatchers.Default
|
||||||
|
internal set
|
||||||
|
}
|
||||||
|
|
@ -8,17 +8,17 @@ import androidx.lifecycle.LifecycleRegistry
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.github.damontecres.wholphin.data.CurrentUser
|
import com.github.damontecres.wholphin.data.CurrentUser
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
|
import com.github.damontecres.wholphin.util.configure
|
||||||
|
import com.github.damontecres.wholphin.util.reset
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
import kotlinx.coroutines.test.advanceUntilIdle
|
import kotlinx.coroutines.test.advanceUntilIdle
|
||||||
import kotlinx.coroutines.test.resetMain
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlinx.coroutines.test.setMain
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
|
@ -36,14 +36,14 @@ class LatestNextUpSchedulerServiceTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
Dispatchers.setMain(testDispatcher)
|
WholphinDispatchers.configure(testDispatcher)
|
||||||
every { mockActivity.lifecycle } returns lifecycleRegistry
|
every { mockActivity.lifecycle } returns lifecycleRegistry
|
||||||
every { mockServerRepository.current } returns currentUser
|
every { mockServerRepository.current } returns currentUser
|
||||||
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun tearDown() = Dispatchers.resetMain()
|
fun tearDown() = WholphinDispatchers.reset()
|
||||||
|
|
||||||
private fun createService() =
|
private fun createService() =
|
||||||
LatestNextUpSchedulerService(
|
LatestNextUpSchedulerService(
|
||||||
|
|
@ -56,7 +56,7 @@ class LatestNextUpSchedulerServiceTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun cancels_latestNextUp_work_when_user_null() =
|
fun cancels_latestNextUp_work_when_user_null() =
|
||||||
runTest {
|
runTest(testDispatcher) {
|
||||||
createService()
|
createService()
|
||||||
|
|
||||||
currentUser.value = null
|
currentUser.value = null
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,15 @@
|
||||||
|
|
||||||
package com.github.damontecres.wholphin.services
|
package com.github.damontecres.wholphin.services
|
||||||
|
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
|
import com.github.damontecres.wholphin.util.configure
|
||||||
|
import com.github.damontecres.wholphin.util.reset
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
import kotlinx.coroutines.test.resetMain
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlinx.coroutines.test.setMain
|
|
||||||
import kotlinx.serialization.UseSerializers
|
import kotlinx.serialization.UseSerializers
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
|
|
@ -56,14 +56,14 @@ class LatestNextUpServiceTests {
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
Dispatchers.setMain(testDispatcher)
|
WholphinDispatchers.configure(testDispatcher)
|
||||||
every { mockApi.tvShowsApi } returns mockTvShowsApi
|
every { mockApi.tvShowsApi } returns mockTvShowsApi
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@After
|
@After
|
||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
Dispatchers.resetMain()
|
WholphinDispatchers.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -8,19 +8,19 @@ import androidx.work.WorkManager
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.data.model.JellyfinUser
|
import com.github.damontecres.wholphin.data.model.JellyfinUser
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
|
import com.github.damontecres.wholphin.util.configure
|
||||||
|
import com.github.damontecres.wholphin.util.reset
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
import kotlinx.coroutines.test.resetMain
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlinx.coroutines.test.setMain
|
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.Response
|
import org.jellyfin.sdk.api.client.Response
|
||||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||||
|
|
@ -48,12 +48,12 @@ class SuggestionServiceTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
Dispatchers.setMain(testDispatcher)
|
WholphinDispatchers.configure(testDispatcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
Dispatchers.resetMain()
|
WholphinDispatchers.reset()
|
||||||
io.mockk.unmockkObject(GetItemsRequestHandler)
|
io.mockk.unmockkObject(GetItemsRequestHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,19 +11,19 @@ import com.github.damontecres.wholphin.data.CurrentUser
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.data.model.JellyfinServer
|
import com.github.damontecres.wholphin.data.model.JellyfinServer
|
||||||
import com.github.damontecres.wholphin.data.model.JellyfinUser
|
import com.github.damontecres.wholphin.data.model.JellyfinUser
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
|
import com.github.damontecres.wholphin.util.configure
|
||||||
|
import com.github.damontecres.wholphin.util.reset
|
||||||
import com.google.common.util.concurrent.ListenableFuture
|
import com.google.common.util.concurrent.ListenableFuture
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.slot
|
import io.mockk.slot
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
import kotlinx.coroutines.test.advanceUntilIdle
|
import kotlinx.coroutines.test.advanceUntilIdle
|
||||||
import kotlinx.coroutines.test.resetMain
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlinx.coroutines.test.setMain
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
|
@ -43,14 +43,14 @@ class SuggestionsSchedulerServiceTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
Dispatchers.setMain(testDispatcher)
|
WholphinDispatchers.configure(testDispatcher)
|
||||||
every { mockActivity.lifecycle } returns lifecycleRegistry
|
every { mockActivity.lifecycle } returns lifecycleRegistry
|
||||||
every { mockServerRepository.current } returns currentUser
|
every { mockServerRepository.current } returns currentUser
|
||||||
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
fun tearDown() = Dispatchers.resetMain()
|
fun tearDown() = WholphinDispatchers.reset()
|
||||||
|
|
||||||
private fun createService() =
|
private fun createService() =
|
||||||
SuggestionsSchedulerService(
|
SuggestionsSchedulerService(
|
||||||
|
|
|
||||||
|
|
@ -27,18 +27,17 @@ import com.github.damontecres.wholphin.ui.setup.SwitchServerContent
|
||||||
import com.github.damontecres.wholphin.ui.setup.SwitchServerViewModel
|
import com.github.damontecres.wholphin.ui.setup.SwitchServerViewModel
|
||||||
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
|
import com.github.damontecres.wholphin.util.configure
|
||||||
|
import com.github.damontecres.wholphin.util.reset
|
||||||
import dagger.hilt.android.testing.HiltAndroidRule
|
import dagger.hilt.android.testing.HiltAndroidRule
|
||||||
import dagger.hilt.android.testing.HiltAndroidTest
|
import dagger.hilt.android.testing.HiltAndroidTest
|
||||||
import dagger.hilt.android.testing.HiltTestApplication
|
import dagger.hilt.android.testing.HiltTestApplication
|
||||||
import io.mockk.coEvery
|
import io.mockk.coEvery
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.mockkStatic
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.test.resetMain
|
|
||||||
import kotlinx.coroutines.test.setMain
|
|
||||||
import org.jellyfin.sdk.Jellyfin
|
import org.jellyfin.sdk.Jellyfin
|
||||||
import org.jellyfin.sdk.api.client.ApiClient
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.api.client.extensions.quickConnectApi
|
import org.jellyfin.sdk.api.client.extensions.quickConnectApi
|
||||||
|
|
@ -105,11 +104,7 @@ class BasicUiTests {
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
Dispatchers.setMain(TestModule.testDispatcher)
|
WholphinDispatchers.configure(TestModule.testDispatcher)
|
||||||
mockkStatic(Dispatchers::class)
|
|
||||||
|
|
||||||
every { Dispatchers.IO } returns TestModule.testDispatcher
|
|
||||||
every { Dispatchers.Default } returns TestModule.testDispatcher
|
|
||||||
|
|
||||||
hiltRule.inject()
|
hiltRule.inject()
|
||||||
screensaverService = mockk(relaxed = true)
|
screensaverService = mockk(relaxed = true)
|
||||||
|
|
@ -130,7 +125,7 @@ class BasicUiTests {
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@After
|
@After
|
||||||
fun tearDown() {
|
fun tearDown() {
|
||||||
Dispatchers.resetMain()
|
WholphinDispatchers.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ import com.github.damontecres.wholphin.services.hilt.IoCoroutineScope
|
||||||
import com.github.damontecres.wholphin.services.hilt.IoDispatcher
|
import com.github.damontecres.wholphin.services.hilt.IoDispatcher
|
||||||
import com.github.damontecres.wholphin.services.hilt.StandardOkHttpClient
|
import com.github.damontecres.wholphin.services.hilt.StandardOkHttpClient
|
||||||
import com.github.damontecres.wholphin.util.CoroutineContextApiClientFactory
|
import com.github.damontecres.wholphin.util.CoroutineContextApiClientFactory
|
||||||
|
import com.github.damontecres.wholphin.util.WholphinDispatchers
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
|
@ -46,7 +47,6 @@ import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.asExecutor
|
import kotlinx.coroutines.asExecutor
|
||||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||||
|
|
@ -225,7 +225,7 @@ object TestDatabaseModule {
|
||||||
.allowMainThreadQueries()
|
.allowMainThreadQueries()
|
||||||
.setQueryCallback({ sqlQuery, args ->
|
.setQueryCallback({ sqlQuery, args ->
|
||||||
Timber.v("sqlQuery=$sqlQuery, args=$args")
|
Timber.v("sqlQuery=$sqlQuery, args=$args")
|
||||||
}, Dispatchers.IO.asExecutor())
|
}, WholphinDispatchers.IO.asExecutor())
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.github.damontecres.wholphin.util
|
||||||
|
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.test.TestDispatcher
|
||||||
|
import kotlinx.coroutines.test.resetMain
|
||||||
|
import kotlinx.coroutines.test.setMain
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
fun WholphinDispatchers.configure(testDispatcher: TestDispatcher) {
|
||||||
|
Dispatchers.setMain(testDispatcher)
|
||||||
|
IO = testDispatcher
|
||||||
|
Default = testDispatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
fun WholphinDispatchers.reset() {
|
||||||
|
Dispatchers.resetMain()
|
||||||
|
IO = Dispatchers.IO
|
||||||
|
Default = Dispatchers.Default
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue