diff --git a/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.android.kt b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.android.kt index 026d2d46..6ddcf11b 100644 --- a/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.android.kt +++ b/app/shared/src/androidMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.android.kt @@ -19,9 +19,10 @@ import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.flow.StateFlow -actual fun LazyGridScope.DeviceContent(release: StateFlow) { +actual fun LazyGridScope.DeviceContent(release: StateFlow, onDeviceReachable: StateFlow) { header { val newRelease by release.collectAsStateWithLifecycle() + val reachable by onDeviceReachable.collectAsStateWithLifecycle() if (newRelease != null) { Row( @@ -58,6 +59,8 @@ actual fun LazyGridScope.DeviceContent(release: StateFlow) { Text(text = stringResource(SharedRes.strings.github)) } } + } else if (!reachable) { + Text(text = stringResource(SharedRes.strings.enable_custom_dns)) } } } \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/custom/state/ErrorState.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/custom/state/ErrorState.kt index 57d1d0bf..a86e982c 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/custom/state/ErrorState.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/custom/state/ErrorState.kt @@ -20,7 +20,7 @@ import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource @Composable -fun ErrorState(text: String, onRetry: () -> Unit) { +fun ErrorState(text: String, customText: (@Composable () -> Unit)? = null, onRetry: () -> Unit) { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterVertically), @@ -43,6 +43,7 @@ fun ErrorState(text: String, onRetry: () -> Unit) { softWrap = true, textAlign = TextAlign.Center ) + customText?.invoke() Button( onClick = { onRetry() @@ -54,4 +55,8 @@ fun ErrorState(text: String, onRetry: () -> Unit) { } @Composable -fun ErrorState(text: StringResource, onRetry: () -> Unit) = ErrorState(text = stringResource(text), onRetry) \ No newline at end of file +fun ErrorState( + text: StringResource, + customText: (@Composable () -> Unit)? = null, + onRetry: () -> Unit +) = ErrorState(text = stringResource(text), customText, onRetry) \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeComponent.kt index 24dd5545..06f17b10 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeComponent.kt @@ -17,6 +17,8 @@ interface HomeComponent : SeriesHolderComponent { val homeState: StateFlow val release: StateFlow + val onDeviceReachable: StateFlow + fun retryLoadingHome(): Any? fun itemClicked(config: HomeConfig) diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreen.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreen.kt index 5ba55805..6b1a89b2 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreen.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreen.kt @@ -15,6 +15,7 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState import dev.datlag.burningseries.model.Home @@ -45,7 +46,20 @@ fun HomeScreen(component: HomeComponent) { LoadingState(SharedRes.strings.loading_home) } is HomeState.Error -> { - ErrorState(SharedRes.strings.error_loading_home) { + val reachable by component.onDeviceReachable.collectAsStateWithLifecycle() + + ErrorState( + text = SharedRes.strings.error_loading_home, + customText = { + if (!reachable) { + Text( + modifier = Modifier.fillMaxWidth(0.85F), + text = stringResource(SharedRes.strings.enable_custom_dns), + textAlign = TextAlign.Center + ) + } + } + ) { component.retryLoadingHome() } } @@ -116,7 +130,7 @@ private fun MainView(home: Home, component: HomeComponent, modifier: Modifier = horizontalArrangement = Arrangement.spacedBy(8.dp), state = state ) { - DeviceContent(component.release) + DeviceContent(component.release, component.onDeviceReachable) header { Row( modifier = Modifier.padding(top = 16.dp).fillMaxWidth(), diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreenComponent.kt index 9fe2cfa6..9ae0c937 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/HomeScreenComponent.kt @@ -10,6 +10,7 @@ import dev.datlag.burningseries.model.Release import dev.datlag.burningseries.model.Series import dev.datlag.burningseries.model.Shortcut import dev.datlag.burningseries.model.common.getDigitsOrNull +import dev.datlag.burningseries.model.common.safeCast import dev.datlag.burningseries.model.state.HomeAction import dev.datlag.burningseries.model.state.HomeState import dev.datlag.burningseries.model.state.ReleaseState @@ -40,6 +41,9 @@ class HomeScreenComponent( private val homeStateMachine: HomeStateMachine by di.instance() override val homeState: StateFlow = homeStateMachine.state.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), HomeState.Loading) + override val onDeviceReachable = homeState.map { + it.safeCast()?.onDeviceReachable ?: (it is HomeState.Loading) + }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), true) private val appVersion: String? by di.instanceOrNull("APP_VERSION") private val releaseStateMachine: ReleaseStateMachine by di.instance() diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.kt index ec281bd8..00b55a6b 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.kt @@ -4,4 +4,4 @@ import androidx.compose.foundation.lazy.grid.LazyGridScope import dev.datlag.burningseries.model.Release import kotlinx.coroutines.flow.StateFlow -expect fun LazyGridScope.DeviceContent(release: StateFlow) \ No newline at end of file +expect fun LazyGridScope.DeviceContent(release: StateFlow, onDeviceReachable: StateFlow) \ No newline at end of file diff --git a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/video/VideoScreenComponent.kt b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/video/VideoScreenComponent.kt index c8800c49..94c7fc47 100644 --- a/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/video/VideoScreenComponent.kt +++ b/app/shared/src/commonMain/kotlin/dev/datlag/burningseries/shared/ui/screen/video/VideoScreenComponent.kt @@ -29,6 +29,7 @@ import kotlinx.coroutines.delay import kotlinx.coroutines.flow.* import org.kodein.di.DI import org.kodein.di.instance +import kotlin.math.max class VideoScreenComponent( componentContext: ComponentContext, @@ -127,7 +128,7 @@ class VideoScreenComponent( val currentEpisode = episode.value database.burningSeriesQueries.updateEpisodeLength( - length = millis, + length = max(millis, 0L), href = currentEpisode.href, number = currentEpisode.number, title = currentEpisode.title, diff --git a/app/shared/src/commonMain/resources/MR/base/strings.xml b/app/shared/src/commonMain/resources/MR/base/strings.xml index 7dea88b0..c08c731e 100644 --- a/app/shared/src/commonMain/resources/MR/base/strings.xml +++ b/app/shared/src/commonMain/resources/MR/base/strings.xml @@ -73,4 +73,5 @@ Muted Unmuted Loading series + You should set a custom DNS to make sure you can access all features. \ No newline at end of file diff --git a/app/shared/src/commonMain/resources/MR/de/strings.xml b/app/shared/src/commonMain/resources/MR/de/strings.xml index 588ac718..63bbf8e1 100644 --- a/app/shared/src/commonMain/resources/MR/de/strings.xml +++ b/app/shared/src/commonMain/resources/MR/de/strings.xml @@ -73,4 +73,5 @@ Stumm Nicht stumm Lade Serie + Du solltest einen DNS-Server einrichten, um alle Funktionen zuverlässig nutzen zu können. \ No newline at end of file diff --git a/app/shared/src/desktopMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.desktop.kt b/app/shared/src/desktopMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.desktop.kt index b8f772f6..4586c9e6 100644 --- a/app/shared/src/desktopMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.desktop.kt +++ b/app/shared/src/desktopMain/kotlin/dev/datlag/burningseries/shared/ui/screen/initial/home/component/DeviceContent.desktop.kt @@ -26,7 +26,7 @@ import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.flow.StateFlow -actual fun LazyGridScope.DeviceContent(release: StateFlow) { +actual fun LazyGridScope.DeviceContent(release: StateFlow, onDeviceReachable: StateFlow) { header { val newRelease by release.collectAsStateWithLifecycle() @@ -123,6 +123,16 @@ actual fun LazyGridScope.DeviceContent(release: StateFlow) { ) } } + is CEFState.INITIALIZED -> { + val reachable by onDeviceReachable.collectAsStateWithLifecycle() + + if (!reachable) { + Text( + modifier = Modifier.padding(top = 16.dp), + text = stringResource(SharedRes.strings.enable_custom_dns) + ) + } + } else -> { } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9bf5b951..a3a91276 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -app = "5.1.0" +app = "5.2.0" aboutlibraries = "10.9.2" accompanist = "0.32.0" activity = "1.8.2" diff --git a/model/src/commonMain/kotlin/dev/datlag/burningseries/model/state/HomeState.kt b/model/src/commonMain/kotlin/dev/datlag/burningseries/model/state/HomeState.kt index 965e86ff..3347dc77 100644 --- a/model/src/commonMain/kotlin/dev/datlag/burningseries/model/state/HomeState.kt +++ b/model/src/commonMain/kotlin/dev/datlag/burningseries/model/state/HomeState.kt @@ -4,7 +4,7 @@ import dev.datlag.burningseries.model.Home sealed interface HomeState { data object Loading : HomeState - data class Success(val home: Home) : HomeState + data class Success(val home: Home, val onDeviceReachable: Boolean) : HomeState data object Error : HomeState } diff --git a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/HomeStateMachine.kt b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/HomeStateMachine.kt index 0f5ae9dc..89ec3d01 100644 --- a/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/HomeStateMachine.kt +++ b/network/src/commonMain/kotlin/dev/datlag/burningseries/network/state/HomeStateMachine.kt @@ -28,14 +28,16 @@ class HomeStateMachine( } onEnter { state -> val result = suspendCatchResult { + var onDeviceReachable: Boolean = true val loadedHome = BurningSeries.getHome(client) ?: run { + onDeviceReachable = false wrapApiKey?.let { json.decodeFromJsonElement(wrapApi.getBurningSeriesHome(it).data) } }!! if (loadedHome.episodes.isNotEmpty() || loadedHome.series.isNotEmpty()) { - HomeState.Success(loadedHome) + HomeState.Success(loadedHome, onDeviceReachable) } else { HomeState.Error }