Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 5 additions & 11 deletions app/src/main/java/com/capyreader/app/preferences/AppPreferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,10 @@ class AppPreferences(context: Context) {
val fontFamily: Preference<FontOption>
get() = preferenceStore.getEnum("article_font_family", FontOption.default)

val topSwipeGesture: Preference<ArticleVerticalSwipe>
get() = preferenceStore.getEnum(
"article_top_swipe_gesture",
ArticleVerticalSwipe.topSwipeDefault
)

val bottomSwipeGesture: Preference<ArticleVerticalSwipe>
get() = preferenceStore.getEnum(
"article_bottom_swipe_gesture",
ArticleVerticalSwipe.bottomSwipeDefault
val enableSwipeNavigation: Preference<Boolean>
get() = preferenceStore.getBoolean(
"enable_swipe_navigation",
true
)

val imageVisibility: Preference<ReaderImageVisibility>
Expand All @@ -120,7 +114,7 @@ class AppPreferences(context: Context) {
get() = preferenceStore.getBoolean("article_enable_paging_tap_gesture", false)

val enableHorizontaPagination: Preference<Boolean>
get() = preferenceStore.getBoolean("article_enable_horizontal_pagination", true)
get() = preferenceStore.getBoolean("article_enable_horizontal_pagination", false)

val improveTalkback: Preference<Boolean>
get() = preferenceStore.getBoolean("article_improve_talkback", false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@ import com.capyreader.app.R
enum class ArticleVerticalSwipe {
DISABLED,
PREVIOUS_ARTICLE,
NEXT_ARTICLE,
LOAD_FULL_CONTENT,
OPEN_ARTICLE_IN_BROWSER;
NEXT_ARTICLE;

val translationKey: Int
get() = when (this) {
DISABLED -> R.string.article_vertical_swipe_disabled
PREVIOUS_ARTICLE -> R.string.article_vertical_swipe_previous_article
NEXT_ARTICLE -> R.string.article_vertical_swipe_next_article
LOAD_FULL_CONTENT -> R.string.article_vertical_swipe_full_content
OPEN_ARTICLE_IN_BROWSER -> R.string.article_vertical_open_article_in_browser
}

val enabled: Boolean
Expand All @@ -27,19 +23,16 @@ enum class ArticleVerticalSwipe {
companion object {
val topOptions = listOf(
DISABLED,
LOAD_FULL_CONTENT,
PREVIOUS_ARTICLE,
)

val bottomOptions = listOf(
DISABLED,
OPEN_ARTICLE_IN_BROWSER,
NEXT_ARTICLE,
LOAD_FULL_CONTENT,
)

val topSwipeDefault = LOAD_FULL_CONTENT
val topSwipeDefault = PREVIOUS_ARTICLE

val bottomSwipeDefault = OPEN_ARTICLE_IN_BROWSER
val bottomSwipeDefault = NEXT_ARTICLE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import kotlin.math.roundToInt
fun ArticleReader(
article: Article,
onSelectMedia: (media: Media) -> Unit,
modifier: Modifier = Modifier,
) {
val (shareLink, setShareLink) = rememberSaveableShareLink()
val linkOpener = LocalLinkOpener.current
Expand All @@ -53,15 +54,18 @@ fun ArticleReader(

if (improveTalkback) {
Column(
Modifier.fillMaxSize()
modifier = modifier.fillMaxSize()
) {
WebView(
modifier = Modifier.fillMaxSize(),
state = webViewState,
)
}
} else {
ScrollableWebView(webViewState)
ScrollableWebView(
webViewState = webViewState,
modifier = modifier
)
}

LaunchedEffect(article.id, article.content) {
Expand All @@ -87,7 +91,10 @@ fun ArticleReader(
}

@Composable
fun ScrollableWebView(webViewState: WebViewState) {
fun ScrollableWebView(
webViewState: WebViewState,
modifier: Modifier = Modifier,
) {
var maxHeight by remember { mutableFloatStateOf(0f) }
val scrollState = rememberSaveable(saver = ScrollState.Saver) {
ScrollState(initial = 0)
Expand All @@ -101,7 +108,7 @@ fun ScrollableWebView(webViewState: WebViewState) {
) {
ColumnScrollbar(state = scrollState) {
Column(
modifier = Modifier
modifier = modifier
.fillMaxSize()
.verticalScroll(scrollState)
.onGloballyPositioned { coordinates ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.capyreader.app.ui.articles.detail

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.IntOffset

enum class ArticleDirection {
UPWARD,
DOWNWARD,
NONE
}

@Composable
fun ArticleTransition(
article: ArticleTransitionState,
content: @Composable (ArticleTransitionState) -> Unit,
) {
AnimatedContent(
targetState = article,
transitionSpec = {
val direction = when {
initialState.nextArticleId == targetState.articleId -> ArticleDirection.UPWARD
initialState.previousArticleId == targetState.articleId -> ArticleDirection.DOWNWARD
else -> ArticleDirection.NONE
}

val directionMultiplier = when (direction) {
ArticleDirection.UPWARD -> 1
ArticleDirection.DOWNWARD -> -1
ArticleDirection.NONE -> 0
}

val exitDuration = 100
val enterDuration = exitDuration * 2

(slideInVertically(
initialOffsetY = { (it * 0.2f * directionMultiplier).toInt() },
animationSpec = spring(
dampingRatio = 0.9f,
stiffness = Spring.StiffnessLow,
),
) + fadeIn(
animationSpec = tween(enterDuration, delayMillis = exitDuration / 2),
initialAlpha = 0.3f,
)) togetherWith (slideOutVertically(
targetOffsetY = { -(it * 0.2f * directionMultiplier).toInt() },
animationSpec = tween(exitDuration)
) + fadeOut(
animationSpec = tween(exitDuration)
))
},
label = "article_transition"
) { state ->
content(state)
}
}

data class ArticleTransitionState(
val articleId: String,
val previousArticleId: String?,
val nextArticleId: String?,
)
Loading