Skip to content

Commit

Permalink
added trailer
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed Apr 3, 2024
1 parent 55e8a01 commit 7503003
Show file tree
Hide file tree
Showing 28 changed files with 624 additions and 24 deletions.
8 changes: 8 additions & 0 deletions anilist/src/commonMain/graphql/MediumQuery.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ query MediumQuery($id: Int, $statusVersion: Int, $html: Boolean) {
medium
}
}
},
mediaListEntry {
score(format: POINT_5)
},
trailer {
id,
site,
thumbnail
}
}
}
8 changes: 8 additions & 0 deletions anilist/src/commonMain/graphql/RatingMutation.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
mutation RatingMutation(
$mediaId: Int,
$rating: Int
) {
SaveMediaListEntry(mediaId: $mediaId, scoreRaw: $rating) {
score(format: POINT_5)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,15 @@ class AiringTodayStateMachine(
response.asSuccess {
crashlytics?.log(it)

State.Error(state.snapshot.query, state.snapshot.adultContent)
if (retry <= 3) {
State.Loading(
query,
adultContent,
retry + 1
)
} else {
State.Error(query, adultContent)
}
}
}
}
Expand Down Expand Up @@ -96,7 +104,8 @@ class AiringTodayStateMachine(
sealed interface State {
data class Loading(
internal val query: AiringQuery,
val adultContent: Boolean = false
val adultContent: Boolean = false,
internal val retry: Int = 0
) : State {
constructor(
page: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,11 @@ class MediumStateMachine(
response.asSuccess {
crashlytics?.log(it)

State.Error(query)
if (retry <= 3) {
State.Loading(query, retry + 1)
} else {
State.Error(query)
}
}
}
}
Expand All @@ -70,7 +74,8 @@ class MediumStateMachine(

sealed interface State {
data class Loading(
internal val query: MediumQuery
internal val query: MediumQuery,
internal val retry: Int = 0
) : State {
constructor(id: Int) : this(
MediumQuery(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ class PopularNextSeasonStateMachine(
response.asSuccess {
crashlytics?.log(it)

SeasonState.Error(query)
if (state.snapshot.retry <= 3) {
SeasonState.Loading(state.snapshot.query, state.snapshot.retry + 1)
} else {
SeasonState.Error(query)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ class PopularSeasonStateMachine(
response.asSuccess {
crashlytics?.log(it)

SeasonState.Error(query)
if (retry <= 3) {
SeasonState.Loading(query, retry + 1)
} else {
SeasonState.Error(query)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ class TrendingAnimeStateMachine(
response.asSuccess {
crashlytics?.log(it)

State.Error(query)
if (retry <= 3) {
State.Loading(query, retry + 1)
} else {
State.Error(query)
}
}
}
}
Expand Down Expand Up @@ -70,6 +74,7 @@ class TrendingAnimeStateMachine(
sealed interface State {
data class Loading(
internal val query: TrendingQuery,
internal val retry: Int = 0
) : State {
constructor(
page: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import dev.datlag.aniflow.anilist.common.lastMonth
import dev.datlag.aniflow.anilist.type.MediaFormat
import dev.datlag.aniflow.anilist.type.MediaRankType
import dev.datlag.aniflow.anilist.type.MediaStatus
import dev.datlag.aniflow.anilist.type.MediaTrailer
import kotlinx.datetime.Month
import kotlinx.serialization.Serializable

Expand Down Expand Up @@ -298,7 +299,9 @@ open class Medium(
override val coverImage: CoverImage,
val nextAiringEpisode: MediumQuery.NextAiringEpisode?,
val ranking: Set<Ranking>,
val characters: Set<Character>
val characters: Set<Character>,
val entry: Entry?,
val trailer: Trailer?
) : Medium(
id = id,
idMal = idMal,
Expand Down Expand Up @@ -327,12 +330,74 @@ open class Medium(
coverImage = medium.coverImage,
nextAiringEpisode = mediumQuery.nextAiringEpisode,
ranking = mediumQuery.rankingsFilterNotNull()?.map(::Ranking)?.toSet() ?: emptySet(),
characters = mediumQuery.characters?.nodesFilterNotNull()?.mapNotNull(Character::invoke)?.toSet() ?: emptySet()
characters = mediumQuery.characters?.nodesFilterNotNull()?.mapNotNull(Character::invoke)?.toSet() ?: emptySet(),
entry = mediumQuery.mediaListEntry?.let(::Entry),
trailer = mediumQuery.trailer?.let {
val site = it.site?.ifBlank { null }
val thumbnail = it.thumbnail?.ifBlank { null }

if (site == null || thumbnail == null) {
null
} else {
Trailer(
id = it.id?.ifBlank { null },
site = site,
thumbnail = thumbnail
)
}
}
)

constructor(mediumQuery: MediumQuery.Media) : this(
medium = Medium(mediumQuery),
mediumQuery = mediumQuery
)

data class Entry(
val score: Double?
) {
constructor(entry: MediumQuery.MediaListEntry) : this(
score = entry.score
)
}

data class Trailer(
val id: String?,
val site: String,
val thumbnail: String
) {
val website: String = run {
val prefix = if (site.startsWith("https://", ignoreCase = true) || site.startsWith("http://", ignoreCase = true)) {
""
} else {
"https://"
}
val suffix = if (site.substringAfterLast('.', missingDelimiterValue = "").isBlank()) {
".com"
} else {
""
}
"$prefix$site$suffix"
}

val isYoutube: Boolean = site.contains("youtu.be", ignoreCase = true)
|| site.contains("youtube", ignoreCase = true)

private val youtubeVideoId: String? = run {
val afterVi = thumbnail.substringAfter(
delimiter = "vi/",
missingDelimiterValue = thumbnail.substringAfter(
delimiter = "vi_webp/",
missingDelimiterValue = ""
)
).ifBlank { null } ?: return@run null

afterVi.substringBefore('/', missingDelimiterValue = "").ifBlank { null }
}

val youtubeVideo = (id ?: youtubeVideoId)?.let {
"https://youtube.com/watch?v=$it"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import kotlinx.datetime.Instant

sealed interface SeasonState {
data class Loading(
internal val query: SeasonQuery
internal val query: SeasonQuery,
internal val retry: Int = 0
) : SeasonState {
constructor(
page: Int,
Expand Down
12 changes: 11 additions & 1 deletion composeApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,12 @@ kotlin {

implementation(libs.oidc)

implementation("dev.datlag.sheets-compose-dialogs:rating:2.0.0-SNAPSHOT")

implementation(project(":firebase"))
implementation(project(":anilist"))
implementation(project(":model"))
implementation(project(":settings"))
}

iosMain.dependencies {
Expand Down Expand Up @@ -128,6 +131,10 @@ kotlin {
}
}

dependencies {
coreLibraryDesugaring(libs.desugar)
}

android {
sourceSets["main"].setRoot("src/androidMain/")
sourceSets["main"].res.srcDirs("src/androidMain/res", "src/commonMain/resources")
Expand All @@ -146,15 +153,18 @@ android {
vectorDrawables.useSupportLibrary = true

addManifestPlaceholders(
mapOf("oidcRedirectScheme" to "datlag")
mapOf("oidcRedirectScheme" to "aniflow")
)
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
merges += "values**"
}
}
compileOptions {
isCoreLibraryDesugaringEnabled = true

sourceCompatibility = CompileOptions.sourceCompatibility
targetCompatibility = CompileOptions.targetCompatibility
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package dev.datlag.aniflow

import android.content.Intent
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.platform.UriHandler
import androidx.core.content.ContextCompat
import androidx.core.net.toUri
import androidx.core.view.WindowCompat
import com.arkivanov.decompose.DefaultComponentContext
import com.arkivanov.essenty.backhandler.backHandler
Expand All @@ -14,6 +19,7 @@ import com.arkivanov.essenty.lifecycle.LifecycleOwner
import com.arkivanov.essenty.lifecycle.essentyLifecycle
import dev.datlag.aniflow.other.BurningSeriesResolver
import dev.datlag.aniflow.ui.navigation.RootComponent
import dev.datlag.tooling.compose.openInBrowser
import dev.datlag.tooling.compose.withIOContext
import dev.datlag.tooling.decompose.lifecycle.LocalLifecycleOwner
import dev.datlag.tooling.safeCast
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package dev.datlag.aniflow.module

import android.content.Context
import androidx.credentials.CredentialManager
import androidx.datastore.core.DataStoreFactory
import androidx.datastore.core.okio.OkioStorage
import coil3.ImageLoader
import coil3.request.allowHardware
import dev.datlag.aniflow.Sekret
Expand All @@ -10,12 +12,18 @@ import dev.datlag.aniflow.firebase.initialize
import dev.datlag.aniflow.getPackageName
import dev.datlag.aniflow.other.Constants
import dev.datlag.aniflow.other.StateSaver
import dev.datlag.aniflow.settings.DataStoreUserSettings
import dev.datlag.aniflow.settings.Settings
import dev.datlag.aniflow.settings.UserSettingsSerializer
import io.ktor.client.*
import io.ktor.client.engine.okhttp.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.http.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.serialization.json.Json
import okio.FileSystem
import okio.Path.Companion.toOkioPath
import org.kodein.di.DI
import org.kodein.di.bindSingleton
import org.kodein.di.instance
Expand Down Expand Up @@ -44,6 +52,10 @@ actual object PlatformModule {
json(instance<Json>(), ContentType.Application.Json)
json(instance<Json>(), ContentType.Text.Plain)
}
install(HttpRequestRetry) {
retryOnExceptionOrServerErrors(3)
exponentialDelay()
}
}
}
bindSingleton<CredentialManager> {
Expand All @@ -68,6 +80,21 @@ actual object PlatformModule {
bindSingleton(Constants.Sekret.ANILIST_CLIENT_SECRET) {
Sekret.anilistClientSecret(getPackageName()) ?: ""
}
bindSingleton {
val app: Context = instance()
DataStoreFactory.create(
storage = OkioStorage(
fileSystem = FileSystem.SYSTEM,
serializer = UserSettingsSerializer,
producePath = {
app.filesDir.toOkioPath().resolve("datastore").resolve("user.settings")
}
)
)
}
bindSingleton<Settings.PlatformUserSettings> {
DataStoreUserSettings(instance())
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import dev.datlag.aniflow.LocalDI
import dev.datlag.aniflow.ui.navigation.Component
import dev.datlag.aniflow.ui.theme.SchemeTheme
import dev.datlag.tooling.decompose.lifecycle.LocalLifecycleOwner
import dev.datlag.tooling.decompose.lifecycle.collectAsStateWithLifecycle
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map

/**
* Can be placed in the Component interface again when
Expand Down Expand Up @@ -45,4 +48,13 @@ fun Component.onRenderApplyCommonScheme(key: Any?, content: @Composable () -> Un
SchemeTheme.setCommon(null)
}
}
}

@Composable
fun <T, R> StateFlow<T>.mapCollect(transform: (value: T) -> R): State<R> {
return remember(this) {
this.map(transform)
}.collectAsStateWithLifecycle(
initialValue = transform(this.value)
)
}
Loading

0 comments on commit 7503003

Please sign in to comment.