diff --git a/composeApp/src/androidMain/kotlin/dev/datlag/aniflow/MainActivity.kt b/composeApp/src/androidMain/kotlin/dev/datlag/aniflow/MainActivity.kt index 0dd4fc9..b899e96 100644 --- a/composeApp/src/androidMain/kotlin/dev/datlag/aniflow/MainActivity.kt +++ b/composeApp/src/androidMain/kotlin/dev/datlag/aniflow/MainActivity.kt @@ -89,7 +89,7 @@ class MainActivity : AppCompatActivity() { } val accessToken = uri.getFragmentOrQueryParameter("access_token") - if (accessToken.isNullOrBlank()) { + if (accessToken.isNullOrBlank() || !::root.isInitialized) { return } diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumComponent.kt index d91afa3..0c6b8bf 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumComponent.kt @@ -23,6 +23,8 @@ interface MediumComponent : ContentHolderComponent { val initialMedium: Medium val titleLanguage: Flow val charLanguage: Flow + val isLoggedIn: Flow + val loginUri: String val mediumState: Flow val isAdult: Flow diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreen.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreen.kt index 82fced4..a6c12a6 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreen.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreen.kt @@ -86,6 +86,8 @@ fun MediumScreen(component: MediumComponent) { bannerImageFlow = component.bannerImage, coverImage = coverImage, titleFlow = component.title, + isLoggedIn = component.isLoggedIn, + loginUri = component.loginUri, isFavoriteFlow = component.isFavorite, isFavoriteBlockedFlow = component.isFavoriteBlocked, siteUrlFlow = component.siteUrl, @@ -117,11 +119,19 @@ fun MediumScreen(component: MediumComponent) { } if (!notReleased) { + val loggedIn by component.isLoggedIn.collectAsStateWithLifecycle(false) val status by component.listStatus.collectAsStateWithLifecycle(component.initialMedium.entry?.status ?: MediaListStatus.UNKNOWN__) val type by component.type.collectAsStateWithLifecycle(component.initialMedium.type) + val uriHandler = LocalUriHandler.current ExtendedFloatingActionButton( - onClick = { component.edit() }, + onClick = { + if (!loggedIn) { + uriHandler.openUri(component.loginUri) + } else { + component.edit() + } + }, expanded = listState.isScrollingUp() && listState.canScrollForward, icon = { Icon( diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreenComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreenComponent.kt index 020e20e..60e2386 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreenComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/MediumScreenComponent.kt @@ -52,7 +52,10 @@ class MediumScreenComponent( private val aniListClient by di.instance(Constants.AniList.APOLLO_CLIENT) private val appSettings by di.instance() + private val userHelper by di.instance() + override val isLoggedIn: Flow = userHelper.isLoggedIn + override val loginUri: String = userHelper.loginUrl override val titleLanguage: Flow = appSettings.titleLanguage.flowOn(ioDispatcher()) override val charLanguage: Flow = appSettings.charLanguage.flowOn(ioDispatcher()) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/component/CollapsingToolbar.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/component/CollapsingToolbar.kt index 3693506..0f7d85e 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/component/CollapsingToolbar.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/component/CollapsingToolbar.kt @@ -12,6 +12,9 @@ import androidx.compose.material.icons.filled.ArrowBackIosNew import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.FavoriteBorder import androidx.compose.material.icons.filled.Share +import androidx.compose.material.icons.rounded.ArrowBackIosNew +import androidx.compose.material.icons.rounded.Favorite +import androidx.compose.material.icons.rounded.FavoriteBorder import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -56,6 +59,8 @@ fun CollapsingToolbar( bannerImageFlow: Flow, coverImage: Medium.CoverImage, titleFlow: Flow, + isLoggedIn: Flow, + loginUri: String, isFavoriteFlow: Flow, isFavoriteBlockedFlow: Flow, siteUrlFlow: Flow, @@ -106,7 +111,7 @@ fun CollapsingToolbar( } ) { Icon( - imageVector = Icons.Default.ArrowBackIosNew, + imageVector = Icons.Rounded.ArrowBackIosNew, contentDescription = null ) } @@ -177,22 +182,28 @@ fun CollapsingToolbar( enter = fadeIn(), exit = fadeOut() ) { + val loggedIn by isLoggedIn.collectAsStateWithLifecycle(false) val isFavoriteBlocked by isFavoriteBlockedFlow.collectAsStateWithLifecycle(initialMedium.isFavoriteBlocked) val isFavorite by isFavoriteFlow.collectAsStateWithLifecycle(initialMedium.isFavorite) var favoriteChanged by remember(isFavorite) { mutableStateOf(null) } + val uriHandler = LocalUriHandler.current IconButton( onClick = { - favoriteChanged = !(favoriteChanged ?: isFavorite) - onToggleFavorite() + if (!loggedIn) { + uriHandler.openUri(loginUri) + } else { + favoriteChanged = !(favoriteChanged ?: isFavorite) + onToggleFavorite() + } }, - enabled = !isFavoriteBlocked + enabled = !loggedIn || !isFavoriteBlocked ) { Icon( imageVector = if (favoriteChanged ?: isFavorite) { - Icons.Default.Favorite + Icons.Rounded.Favorite } else { - Icons.Default.FavoriteBorder + Icons.Rounded.FavoriteBorder }, contentDescription = null ) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterComponent.kt index 3059b41..c957aec 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterComponent.kt @@ -9,6 +9,8 @@ import kotlinx.coroutines.flow.StateFlow interface CharacterComponent : DialogComponent { val initialChar: Character + val isLoggedIn: Flow + val loginUri: String val state: Flow val charLanguage: Flow diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialog.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialog.kt index 9a94460..f005460 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialog.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialog.kt @@ -11,6 +11,8 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* import androidx.compose.material.icons.rounded.ArrowBackIosNew +import androidx.compose.material.icons.rounded.Favorite +import androidx.compose.material.icons.rounded.FavoriteBorder import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -18,6 +20,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -112,22 +115,28 @@ fun CharacterDialog(component: CharacterComponent) { enter = fadeIn(), exit = fadeOut() ) { + val loggedIn by component.isLoggedIn.collectAsStateWithLifecycle(false) val isFavoriteBlocked by component.isFavoriteBlocked.collectAsStateWithLifecycle(component.initialChar.isFavoriteBlocked) val isFavorite by component.isFavorite.collectAsStateWithLifecycle(component.initialChar.isFavorite) var favoriteChanged by remember(isFavorite) { mutableStateOf(null) } + val uriHandler = LocalUriHandler.current IconButton( onClick = { - favoriteChanged = !(favoriteChanged ?: isFavorite) - component.toggleFavorite() + if (!loggedIn) { + uriHandler.openUri(component.loginUri) + } else { + favoriteChanged = !(favoriteChanged ?: isFavorite) + component.toggleFavorite() + } }, - enabled = !isFavoriteBlocked + enabled = !loggedIn || !isFavoriteBlocked ) { Icon( imageVector = if (favoriteChanged ?: isFavorite) { - Icons.Default.Favorite + Icons.Rounded.Favorite } else { - Icons.Default.FavoriteBorder + Icons.Rounded.FavoriteBorder }, contentDescription = null, ) diff --git a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialogComponent.kt b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialogComponent.kt index 26125fe..76d741b 100644 --- a/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialogComponent.kt +++ b/composeApp/src/commonMain/kotlin/dev/datlag/aniflow/ui/navigation/screen/medium/dialog/character/CharacterDialogComponent.kt @@ -11,6 +11,7 @@ import dev.datlag.aniflow.common.nullableFirebaseInstance import dev.datlag.aniflow.common.onRender import dev.datlag.aniflow.model.safeFirstOrNull import dev.datlag.aniflow.other.Constants +import dev.datlag.aniflow.other.UserHelper import dev.datlag.aniflow.settings.Settings import dev.datlag.aniflow.settings.model.CharLanguage import dev.datlag.aniflow.settings.model.TitleLanguage @@ -28,12 +29,16 @@ class CharacterDialogComponent( private val onDismiss: () -> Unit ) : CharacterComponent, ComponentContext by componentContext { - private val aniListClient by di.instance(Constants.AniList.APOLLO_CLIENT) - private val characterRepository by di.instance() + private val aniListClient by instance(Constants.AniList.APOLLO_CLIENT) + private val characterRepository by instance() - private val appSettings by di.instance() + private val appSettings by instance() override val charLanguage: Flow = appSettings.charLanguage.flowOn(ioDispatcher()) + private val userHelper by instance() + override val isLoggedIn: Flow = userHelper.isLoggedIn + override val loginUri: String = userHelper.loginUrl + override val state = characterRepository.character private val characterSuccessState = state.mapNotNull { it.safeCast()