Skip to content

Commit

Permalink
added support for urls
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Dec 20, 2023
1 parent 514cd91 commit ed7f46a
Show file tree
Hide file tree
Showing 15 changed files with 115 additions and 16 deletions.
10 changes: 10 additions & 0 deletions app/android/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:scheme="http" />
<data android:scheme="https" />

<data android:host="bs.to" />
</intent-filter>
</activity>

<meta-data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.arkivanov.essenty.lifecycle.LifecycleOwner
import com.arkivanov.essenty.lifecycle.essentyLifecycle
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.shouldShowRationale
import dev.datlag.burningseries.model.BSUtil
import dev.datlag.burningseries.model.common.safeCast
import dev.datlag.burningseries.shared.App
import dev.datlag.burningseries.shared.SharedRes
Expand Down Expand Up @@ -50,12 +51,14 @@ class MainActivity : AppCompatActivity() {
override val lifecycle: Lifecycle = essentyLifecycle()
}

val shortcutIntent = BSUtil.getIntentDataUrl(intent?.data?.toString())
val root = NavHostComponent(
componentContext = DefaultComponentContext(
lifecycle = lifecycleOwner.lifecycle,
backHandler = backHandler()
),
di = di
di = di,
shortcutIntent = shortcutIntent
)

Kast.setup(this)
Expand Down
13 changes: 13 additions & 0 deletions app/android/src/androidMain/res/xml/shortcuts.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
<capability android:name="actions.intent.GET_THING">
<intent
android:action="android.intent.action.VIEW"
android:targetPackage="dev.datlag.burningseries"
android:targetClass="dev.datlag.burningseries.MainActivity">
<parameter
android:name="thing.name"
android:key="name" />
</intent>
</capability>
</shortcuts>
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.router.stack.push
import dev.datlag.burningseries.model.Shortcut
import dev.datlag.burningseries.shared.LocalDI
import dev.datlag.burningseries.shared.common.backAnimation
import dev.datlag.burningseries.shared.ui.screen.initial.InitialScreenComponent
Expand All @@ -16,14 +17,17 @@ import org.kodein.di.DI

class NavHostComponent(
componentContext: ComponentContext,
override val di: DI
override val di: DI,
shortcutIntent: Shortcut.Intent = Shortcut.Intent.NONE
) : Component, ComponentContext by componentContext {

private val navigation = StackNavigation<ScreenConfig>()
private val stack = childStack(
source = navigation,
serializer = ScreenConfig.serializer(),
initialConfiguration = ScreenConfig.Home,
initialConfiguration = ScreenConfig.Home(
shortcutIntent = shortcutIntent
),
childFactory = ::createScreenComponent
)

Expand All @@ -35,6 +39,7 @@ class NavHostComponent(
is ScreenConfig.Home -> InitialScreenComponent(
componentContext = componentContext,
di = di,
shortcutIntent = screenConfig.shortcutIntent,
watchVideo = { schemeKey, series, episode, stream ->
navigation.push(
ScreenConfig.Video(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
package dev.datlag.burningseries.shared.ui.navigation

import dev.datlag.burningseries.model.Series
import dev.datlag.burningseries.model.Shortcut
import dev.datlag.skeo.Stream
import kotlinx.serialization.Serializable

@Serializable
sealed class ScreenConfig {

@Serializable
data object Home : ScreenConfig()
data class Home(
val shortcutIntent: Shortcut.Intent
) : ScreenConfig()

@Serializable
data class Video(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.arkivanov.decompose.ExperimentalDecomposeApi
import com.arkivanov.decompose.router.pages.*
import com.arkivanov.decompose.value.Value
import dev.datlag.burningseries.model.Series
import dev.datlag.burningseries.model.Shortcut
import dev.datlag.burningseries.shared.LocalDI
import dev.datlag.burningseries.shared.SharedRes
import dev.datlag.burningseries.shared.ui.navigation.Component
Expand All @@ -24,6 +25,7 @@ import org.kodein.di.DI
class InitialScreenComponent(
componentContext: ComponentContext,
override val di: DI,
shortcutIntent: Shortcut.Intent,
private val watchVideo: (String, Series, Series.Episode, Collection<Stream>) -> Unit
) : InitialComponent, ComponentContext by componentContext {

Expand Down Expand Up @@ -52,11 +54,15 @@ class InitialScreenComponent(
initialPages = {
Pages(
items = listOf(
View.Home,
View.Home(shortcutIntent),
View.Favorite,
View.Search
),
selectedIndex = 0
selectedIndex = when (shortcutIntent) {
is Shortcut.Intent.SEARCH -> 2
is Shortcut.Intent.Series -> 0
else -> 0
}
)
}
) { config, context ->
Expand Down Expand Up @@ -84,6 +90,7 @@ class InitialScreenComponent(
is View.Home -> HomeScreenComponent(
componentContext = componentContext,
di = di,
shortcutIntent = view.shortcutIntent,
watchVideo = { schemeKey, series, episode, stream ->
watchVideo(schemeKey, series, episode, stream)
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package dev.datlag.burningseries.shared.ui.screen.initial

import dev.datlag.burningseries.model.Shortcut
import kotlinx.serialization.Serializable

@Serializable
sealed class View {

@Serializable
data object Home : View()
data class Home(
val shortcutIntent: Shortcut.Intent
) : View()

@Serializable
data object Favorite : View()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ sealed class HomeConfig {

@Serializable
data class Series(
val title: String,
val title: String?,
val href: String,
val coverHref: String?,
) : HomeConfig() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.arkivanov.decompose.router.slot.*
import com.arkivanov.decompose.value.Value
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.state.HomeAction
import dev.datlag.burningseries.model.state.HomeState
Expand All @@ -30,6 +31,7 @@ import org.kodein.di.instanceOrNull
class HomeScreenComponent(
componentContext: ComponentContext,
override val di: DI,
private val shortcutIntent: Shortcut.Intent,
private val watchVideo: (String, Series, Series.Episode, Collection<Stream>) -> Unit,
private val scrollEnabled: (Boolean) -> Unit
) : HomeComponent, ComponentContext by componentContext {
Expand Down Expand Up @@ -57,7 +59,13 @@ class HomeScreenComponent(
override val child: Value<ChildSlot<*, Component>> = childSlot(
source = navigation,
serializer = HomeConfig.serializer(),
handleBackButton = false
handleBackButton = false,
initialConfiguration = {
when (shortcutIntent) {
is Shortcut.Intent.Series -> HomeConfig.Series(null, shortcutIntent.href, null)
else -> null
}
}
) { config, context ->
when (config) {
is HomeConfig.Series -> SeriesScreenComponent(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ private fun CompactScreen(component: SeriesComponent) {
Cover(
key = coverHref,
data = coverHref?.let { BSUtil.getBurningSeriesLink(it) },
contentDescription = title,
contentDescription = title.ifBlank {
stringResource(SharedRes.strings.loading_intent_series)
},
modifier = Modifier
.fillMaxWidth()
.defaultMinSize(minHeight = 320.dp)
Expand All @@ -104,7 +106,9 @@ private fun CompactScreen(component: SeriesComponent) {
}
)
Text(
text = title,
text = title.ifBlank {
stringResource(SharedRes.strings.loading_intent_series)
},
modifier = Modifier.road(Alignment.TopStart, Alignment.BottomStart).padding(16.dp).background(
color = Color.Black.copy(alpha = run {
val alpha = state.toolbarState.progress
Expand Down Expand Up @@ -148,7 +152,9 @@ private fun CompactScreen(component: SeriesComponent) {
}

Text(
text = title,
text = title.ifBlank {
stringResource(SharedRes.strings.loading_intent_series)
},
color = LocalContentColor.current.copy(alpha = run {
val alpha = reversedProgress
if (alpha < 0.7F) {
Expand Down Expand Up @@ -314,7 +320,9 @@ private fun DefaultScreen(component: SeriesComponent) {
TopAppBar(
title = {
Text(
text = title,
text = title.ifBlank {
stringResource(SharedRes.strings.loading_intent_series)
},
maxLines = 2,
overflow = TextOverflow.Ellipsis,
softWrap = true
Expand Down Expand Up @@ -372,7 +380,9 @@ private fun DefaultScreen(component: SeriesComponent) {
Cover(
key = coverHref,
data = coverHref?.let { BSUtil.getBurningSeriesLink(it) },
contentDescription = title,
contentDescription = title.ifBlank {
stringResource(SharedRes.strings.loading_intent_series)
},
modifier = Modifier
.width(200.dp)
.clip(MaterialTheme.shapes.medium)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import org.kodein.di.instance
class SeriesScreenComponent(
componentContext: ComponentContext,
override val di: DI,
private val initialTitle: String,
private val initialTitle: String?,
private val initialHref: String,
private val initialCoverHref: String?,
private val onGoBack: () -> Unit,
Expand All @@ -73,7 +73,7 @@ class SeriesScreenComponent(
private val successState = seriesState.mapNotNull { it.safeCast<SeriesState.Success>() }.flowOn(ioDispatcher())
private val currentSeries = successState.map { it.series }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), null)
private val onDeviceReachable = successState.map { it.onDeviceReachable }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.Eagerly, true)
override val title: StateFlow<String> = currentSeries.mapNotNull { it?.bestTitle }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), initialTitle)
override val title: StateFlow<String> = currentSeries.mapNotNull { it?.bestTitle }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), initialTitle ?: String())
override val href: StateFlow<String> = currentSeries.mapNotNull { it?.href }.flowOn(ioDispatcher()).stateIn(ioScope(), SharingStarted.WhileSubscribed(), BSUtil.fixSeriesHref(initialHref))
override val commonHref: StateFlow<String> = href.map {
val commonized = BSUtil.commonSeriesHref(it)
Expand Down
1 change: 1 addition & 0 deletions app/shared/src/commonMain/resources/MR/base/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,5 @@
<string name="sekret_unavailable_text">Some features do not work currently.\nYou should restart the app and check if this issue persists.</string>
<string name="muted">Muted</string>
<string name="unmuted">Unmuted</string>
<string name="loading_intent_series">Loading series</string>
</resources>
1 change: 1 addition & 0 deletions app/shared/src/commonMain/resources/MR/de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,5 @@
<string name="sekret_unavailable_text">Einige Funktionen sind momentan nicht verfügbar.\nDu solltest die App neu starten und prüfen, ob das Problem bestehen bleibt.</string>
<string name="muted">Stumm</string>
<string name="unmuted">Nicht stumm</string>
<string name="loading_intent_series">Lade Serie</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ data object BSUtil {

val episodeNumberRegex = "[|({]\\s*Ep([.]|isode)?\\s*(\\d+)\\s*[|)}]".toRegex(RegexOption.IGNORE_CASE)

fun getIntentDataUrl(data: String?): Shortcut.Intent {
return when {
data.isNullOrBlank() -> Shortcut.Intent.NONE
data.contains(SEARCH, true) -> Shortcut.Intent.SEARCH
else -> {
val normalized = normalizeHref(data)
if (!normalized.equals(data, true)) {
Shortcut.Intent.Series(normalized)
} else {
Shortcut.Intent.NONE
}
}
}
}

fun getBurningSeriesLink(href: String, http: Boolean = false, host: String = HOST_BS_TO): String {
return if (!href.matches("^\\w+?://.*".toRegex())) {
if (!href.startsWith("/")) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dev.datlag.burningseries.model

import kotlinx.serialization.Serializable

@Serializable
sealed interface Shortcut {

@Serializable
sealed interface Intent : Shortcut {

@Serializable
data object SEARCH : Intent

@Serializable
data class Series(val href: String) : Intent

@Serializable
data object NONE : Intent
}
}

0 comments on commit ed7f46a

Please sign in to comment.