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