From 56abff12a7d53f18ef72304dc2a6bb2c7a4cccec Mon Sep 17 00:00:00 2001
From: NightFish <101402767+dmzz-yyhyy@users.noreply.github.com>
Date: Mon, 16 Sep 2024 22:30:00 +0800
Subject: [PATCH 1/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BF=BB=E9=A1=B5?=
=?UTF-8?q?=E6=A8=A1=E5=BC=8F=20#101?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/inspectionProfiles/Project_Default.xml | 31 ++++
.../data/userdata/UserDataPath.kt | 1 +
.../ui/book/content/ContentScreen.kt | 17 +-
.../ui/book/content/ContentScreenUiState.kt | 2 +
.../ui/book/content/ContentViewModel.kt | 9 +
.../ui/book/content/TextComponent.kt | 159 +++++++++++-------
6 files changed, 155 insertions(+), 64 deletions(-)
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index b08a1e1..e2e293f 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -30,6 +30,37 @@
+
+
+
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
index 565da0e..d8f7a5b 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
@@ -20,6 +20,7 @@ sealed class UserDataPath(
data object IsUsingFlipPage : UserDataPath("isUsingFlipPage", Reader)
data object IsUsingClickFlipPage : UserDataPath("isUsingClickFlipPage", Reader)
data object IsUsingVolumeKeyFlip : UserDataPath("isUsingVolumeKeyFlip", Reader)
+ data object IsUsingFlipAnime : UserDataPath("isUsingFlipAnime", Reader)
}
data object ReadingBooks : UserDataPath("reading_books")
data object Search: UserDataPath("search") {
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
index 1d211f4..693a225 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
@@ -215,6 +215,7 @@ fun ContentScreen(
isUsingFlipPage = viewModel.uiState.isUsingFlipPage,
isUsingClickFlip = viewModel.uiState.isUsingClickFlipPage,
isUsingVolumeKeyFlip = viewModel.uiState.isUsingVolumeKeyFlip,
+ isUsingFlipAnime = viewModel.uiState.isUsingFlipAnime,
onChapterReadingProgressChange = viewModel::changeChapterReadingProgress,
changeIsImmersive = { isImmersive = !isImmersive }
)
@@ -244,7 +245,9 @@ fun ContentScreen(
isUsingClickFlip = viewModel.uiState.isUsingClickFlipPage,
onIsUsingClickFlipChange = viewModel::changeIsUsingClickFlipPage,
isUsingVolumeKeyFlip = viewModel.uiState.isUsingVolumeKeyFlip,
- onIsUsingVolumeKeyFlipChange = viewModel::changeIsUsingVolumeKeyFlip
+ onIsUsingVolumeKeyFlipChange = viewModel::changeIsUsingVolumeKeyFlip,
+ isUsingFlipAnime = viewModel.uiState.isUsingFlipAnime,
+ onIsUsingFlipAnimeChange = viewModel::changeIsUsingFlipAnime
)
}
AnimatedVisibility(visible = showChapterSelectorBottomSheet) {
@@ -404,7 +407,9 @@ fun SettingsBottomSheet(
isUsingClickFlip: Boolean,
onIsUsingClickFlipChange: (Boolean) -> Unit,
isUsingVolumeKeyFlip: Boolean,
- onIsUsingVolumeKeyFlipChange: (Boolean) -> Unit
+ onIsUsingVolumeKeyFlipChange: (Boolean) -> Unit,
+ isUsingFlipAnime: Boolean,
+ onIsUsingFlipAnimeChange: (Boolean) -> Unit
) {
ModalBottomSheet(
onDismissRequest = onDismissRequest,
@@ -461,6 +466,14 @@ fun SettingsBottomSheet(
onCheckedChange = onIsUsingClickFlipChange,
)
}
+ AnimatedVisibility(isUsingFlipPage) {
+ SettingsSwitchEntry(
+ title = "启用动画",
+ description = "开启点击翻页或音量键翻页时的动画,如果关闭可以允许你快速的翻页。",
+ checked = isUsingFlipAnime,
+ onCheckedChange = onIsUsingFlipAnimeChange,
+ )
+ }
}
}
}
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
index e70418c..53fcfc6 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
@@ -21,6 +21,7 @@ interface ContentScreenUiState {
val isUsingFlipPage: Boolean
val isUsingClickFlipPage: Boolean
val isUsingVolumeKeyFlip: Boolean
+ val isUsingFlipAnime: Boolean
}
class MutableContentScreenUiState: ContentScreenUiState {
@@ -35,4 +36,5 @@ class MutableContentScreenUiState: ContentScreenUiState {
override var isUsingFlipPage by mutableStateOf(false)
override var isUsingClickFlipPage by mutableStateOf(false)
override var isUsingVolumeKeyFlip by mutableStateOf(false)
+ override var isUsingFlipAnime by mutableStateOf(false)
}
\ No newline at end of file
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
index b2c276f..bfcc77e 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
@@ -25,6 +25,7 @@ class ContentViewModel @Inject constructor(
private val isUsingFlipPageUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingFlipPage.path)
private val isUsingClickFlipPageUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingClickFlipPage.path)
private val isUsingVolumeKeyFlipUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingVolumeKeyFlip.path)
+ private val isUsingFlipAnimeUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingFlipAnime.path)
private val readingBookListUserData = userDataRepository.intListUserData(UserDataPath.ReadingBooks.path)
val uiState: ContentScreenUiState = _uiState
@@ -56,6 +57,7 @@ class ContentViewModel @Inject constructor(
_uiState.isUsingFlipPage = isUsingFlipPageUserData.getOrDefault(_uiState.isUsingFlipPage)
_uiState.isUsingClickFlipPage = isUsingClickFlipPageUserData.getOrDefault(_uiState.isUsingClickFlipPage)
_uiState.isUsingVolumeKeyFlip = isUsingVolumeKeyFlipUserData.getOrDefault(_uiState.isUsingVolumeKeyFlip)
+ _uiState.isUsingFlipAnime = isUsingFlipAnimeUserData.getOrDefault(_uiState.isUsingFlipAnime)
}
}
@@ -198,6 +200,13 @@ class ContentViewModel @Inject constructor(
}
}
+ fun changeIsUsingFlipAnime(isUsingFlipAnime: Boolean) {
+ _uiState.isUsingFlipAnime = isUsingFlipAnime
+ viewModelScope.launch(Dispatchers.IO) {
+ isUsingFlipAnimeUserData.set(isUsingFlipAnime)
+ }
+ }
+
fun addToReadingBook(bookId: Int) {
viewModelScope.launch(Dispatchers.IO) {
readingBookListUserData.update {
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
index 917b4b3..7fa2423 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
@@ -11,7 +11,10 @@ import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
+import androidx.compose.foundation.layout.calculateEndPadding
+import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.displayCutout
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
@@ -36,6 +39,7 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
+import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.TextMeasurer
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
@@ -64,9 +68,24 @@ fun ContentText(
isUsingFlipPage: Boolean,
isUsingClickFlip: Boolean,
isUsingVolumeKeyFlip: Boolean,
+ isUsingFlipAnime: Boolean,
onChapterReadingProgressChange: (Float) -> Unit,
changeIsImmersive: () -> Unit,
+ paddingValues: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 12.dp),
+ autoAvoid: Boolean = true
) {
+ val autoAvoidPaddingValues = with(LocalDensity.current) {
+ PaddingValues(
+ top = paddingValues.calculateTopPadding() +
+ WindowInsets.displayCutout.getTop(LocalDensity.current).toDp(),
+ bottom = paddingValues.calculateBottomPadding() +
+ WindowInsets.displayCutout.getBottom(LocalDensity.current).toDp(),
+ start = paddingValues.calculateStartPadding(LayoutDirection.Ltr) +
+ WindowInsets.displayCutout.getLeft(LocalDensity.current, LayoutDirection.Ltr).toDp(),
+ end = paddingValues.calculateEndPadding(LayoutDirection.Ltr) +
+ WindowInsets.displayCutout.getRight(LocalDensity.current, LayoutDirection.Ltr).toDp(),
+ )
+ }
if (!isUsingFlipPage)
ScrollContentTextComponent(
modifier = Modifier
@@ -92,8 +111,11 @@ fun ContentText(
readingProgress = readingProgress,
isUsingClickFlip = isUsingClickFlip,
isUsingVolumeKeyFlip = isUsingVolumeKeyFlip,
+ isUsingFlipAnime = isUsingFlipAnime,
onChapterReadingProgressChange = onChapterReadingProgressChange,
- changeIsImmersive = changeIsImmersive
+ changeIsImmersive = changeIsImmersive,
+ paddingValues =
+ if (autoAvoid) autoAvoidPaddingValues else paddingValues
)
}
@@ -131,6 +153,7 @@ fun ScrollContentTextComponent(
items(
content
.split("[image]")
+ .filter { it.isNotBlank() }
) {
BasicContentComponent(
text = it,
@@ -150,8 +173,10 @@ fun SimpleFlipPageTextComponent(
readingProgress: Float,
isUsingClickFlip: Boolean,
isUsingVolumeKeyFlip: Boolean,
+ isUsingFlipAnime: Boolean,
onChapterReadingProgressChange: (Float) -> Unit,
changeIsImmersive: () -> Unit,
+ paddingValues: PaddingValues = PaddingValues(8.dp)
) {
val textMeasurer = rememberTextMeasurer()
val scope = rememberCoroutineScope()
@@ -220,7 +245,10 @@ fun SimpleFlipPageTextComponent(
override fun onReceive(context: Context?, intent: Intent?) {
if (isUsingVolumeKeyFlip && pageState.pageCount != 0)
scope.launch {
- pageState.animateScrollToPage(pageState.currentPage - 1)
+ if (isUsingFlipAnime)
+ pageState.animateScrollToPage(pageState.currentPage - 1)
+ else
+ pageState.scrollToPage(pageState.currentPage - 1)
}
}
}
@@ -228,7 +256,10 @@ fun SimpleFlipPageTextComponent(
override fun onReceive(context: Context?, intent: Intent?) {
if (isUsingVolumeKeyFlip && pageState.pageCount - 1 != pageState.currentPage)
scope.launch {
- pageState.animateScrollToPage(pageState.currentPage + 1)
+ if (isUsingFlipAnime)
+ pageState.animateScrollToPage(pageState.currentPage + 1)
+ else
+ pageState.scrollToPage(pageState.currentPage + 1)
}
}
}
@@ -243,20 +274,18 @@ fun SimpleFlipPageTextComponent(
constraints = Constraints(
maxWidth = displayMetrics
.widthPixels
- .minus(WindowInsets.displayCutout.getRight(LocalDensity.current, LayoutDirection.Ltr))
- .minus(WindowInsets.displayCutout.getLeft(LocalDensity.current, LayoutDirection.Ltr))
.minus(
with(LocalDensity.current) {
- 36.dp.toPx()
+ (paddingValues.calculateStartPadding(LayoutDirection.Ltr) + paddingValues.calculateEndPadding(LayoutDirection.Ltr))
+ .toPx()
}.toInt()
),
maxHeight = displayMetrics
.heightPixels
- .minus(WindowInsets.displayCutout.getTop(LocalDensity.current))
- .minus(WindowInsets.displayCutout.getBottom(LocalDensity.current))
.minus(
with(LocalDensity.current) {
- 48.dp.toPx()
+ (paddingValues.calculateTopPadding() + paddingValues.calculateBottomPadding() + 10.dp)
+ .toPx()
}.toInt()
),
)
@@ -265,13 +294,14 @@ fun SimpleFlipPageTextComponent(
HorizontalPager(
state = pageState,
modifier = modifier
+ .padding(paddingValues)
.draggable(
enabled = isUsingClickFlip,
interactionSource = remember { MutableInteractionSource() },
orientation = Orientation.Vertical,
state = rememberDraggableState {},
onDragStopped = {
- if (it.absoluteValue > 100) changeIsImmersive.invoke()
+ if (it.absoluteValue > 60) changeIsImmersive.invoke()
}
)
.pointerInput(isUsingClickFlip) {
@@ -280,12 +310,18 @@ fun SimpleFlipPageTextComponent(
if (isUsingClickFlip) {
if (it.x <= current.resources.displayMetrics.widthPixels / 2 && pageState.currentPage != 0) {
scope.launch {
- pageState.animateScrollToPage(pageState.currentPage - 1)
+ if (isUsingFlipAnime)
+ pageState.animateScrollToPage(pageState.currentPage - 1)
+ else
+ pageState.scrollToPage(pageState.currentPage - 1)
}
} else
if (pageState.currentPage + 1 < pageState.pageCount)
scope.launch {
- pageState.animateScrollToPage(pageState.currentPage + 1)
+ if (isUsingFlipAnime)
+ pageState.animateScrollToPage(pageState.currentPage + 1)
+ else
+ pageState.scrollToPage(pageState.currentPage + 1)
}
}
else {
@@ -294,17 +330,16 @@ fun SimpleFlipPageTextComponent(
}
)
},
- ) {
- BasicContentComponent(
- modifier = modifier.fillMaxSize(),
- text = slippedTextList[it],
- fontSize = fontSize,
- fontLineHeight = fontLineHeight,
- )
+ ) {
+ BasicContentComponent(
+ modifier = modifier.fillMaxSize(),
+ text = slippedTextList[it],
+ fontSize = fontSize,
+ fontLineHeight = fontLineHeight,
+ )
}
}
-@Suppress("HttpUrlsUsage")
@Composable
fun BasicContentComponent(
modifier: Modifier = Modifier,
@@ -312,7 +347,7 @@ fun BasicContentComponent(
fontSize: TextUnit,
fontLineHeight: TextUnit,
) {
- if (text.startsWith("http://") || text.startsWith("https://"))
+ if (text.startsWith("http://") || text.startsWith("https://")) {
AsyncImage(
modifier = modifier.fillMaxWidth(),
model = ImageRequest.Builder(LocalContext.current)
@@ -321,9 +356,9 @@ fun BasicContentComponent(
.build(),
contentDescription = null
)
+ }
else Text(
- modifier = modifier
- .padding(18.dp, 8.dp),
+ modifier = modifier.fillMaxSize(),
text = text,
textAlign = TextAlign.Start,
style = MaterialTheme.typography.bodyMedium,
@@ -339,44 +374,44 @@ fun slipText(
text: String,
style: TextStyle,
): List {
- val result = mutableListOf()
- textMeasurer
- .measure(
- text = text,
- style = style,
- constraints = constraints
- )
- .let { textLayoutResult ->
- val textEndIndex = text.length
- var lastTextIndex = 0
- var lastOffset = 0F
- var index = 1
- while (textEndIndex != lastTextIndex) {
- textLayoutResult
- .getOffsetForPosition(Offset(constraints.maxWidth.toFloat(), constraints.maxHeight.toFloat() - 5 + lastOffset))
- .let { offset ->
- textLayoutResult.getLineForOffset(offset).let {
- if (textLayoutResult.getLineBottom(it) > constraints.maxHeight.toFloat() + lastOffset) {
- lastOffset = textLayoutResult.getLineBottom(it - 1)
- textLayoutResult.getOffsetForPosition(
- Offset(
- constraints.maxWidth.toFloat(),
- textLayoutResult.getLineTop(it) - 2
- )
- )
- }
- else {
- lastOffset += constraints.maxHeight
- offset
- }
- }
- }
- .let {
- result.add(text.substring(lastTextIndex, it))
- lastTextIndex = it
- index++
- }
- }
+ val resultList: MutableList = mutableListOf()
+ text.split("[image]").filter { it.isNotEmpty() }.forEach {sigleText ->
+ if (sigleText.startsWith("http://") || sigleText.startsWith("https://"))
+ resultList.add(sigleText)
+ else {
+ textMeasurer
+ .measure(
+ text = sigleText,
+ style = style,
+ constraints = constraints
+ )
+ .getSlipString(text, constraints)
+ .let(resultList::addAll)
}
- return result
+ }
+ return resultList
+}
+
+fun TextLayoutResult.getSlipString(text: String, constraints: Constraints): List {
+ val result: MutableList = mutableListOf()
+ var lastLine = 0
+ fun getNotOverflowText(startLine: Int): String {
+ fun getNotOverflowLine(): Int {
+ val startHeight = getLineTop(startLine)
+ fun isLineOverflow(line: Int): Boolean = getLineBottom(line) > startHeight + constraints.maxHeight
+ var checkLine = getLineForOffset(getOffsetForPosition(Offset(constraints.maxWidth.toFloat(), startHeight + constraints.maxHeight)))
+ while (isLineOverflow(checkLine))
+ checkLine--
+ return checkLine
+ }
+ val startTextOffset = getLineStart(startLine)
+ lastLine = getNotOverflowLine()
+ val endTextOffset = getLineEnd(lastLine)
+ lastLine++
+ return text.slice(startTextOffset..
Date: Tue, 17 Sep 2024 02:33:39 +0800
Subject: [PATCH 2/8] =?UTF-8?q?=E5=86=85=E5=AE=B9=E9=A1=B5=E9=9D=A2?=
=?UTF-8?q?=E8=A7=86=E8=A7=89=E4=BC=98=E5=8C=96=20#103?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../data/userdata/UserDataPath.kt | 8 +
.../lightnovelreader/ui/book/BookScreen.kt | 6 -
.../ui/book/content/ContentScreen.kt | 406 ++++++++++++++----
.../ui/book/content/ContentScreenUiState.kt | 16 +
.../ui/book/content/ContentViewModel.kt | 85 ++++
.../ui/book/content/TextComponent.kt | 68 +--
.../ui/components/SettingsEntry.kt | 9 +-
.../res/drawable/battery_full_alt_24px.xml | 10 +
.../res/drawable/battery_horiz_000_24px.xml | 10 +
.../res/drawable/battery_horiz_050_24px.xml | 10 +
.../res/drawable/battery_horiz_075_24px.xml | 10 +
.../main/res/drawable/battery_low_24px.xml | 10 +
.../res/drawable/battery_very_low_24px.xml | 10 +
13 files changed, 543 insertions(+), 115 deletions(-)
create mode 100644 app/src/main/res/drawable/battery_full_alt_24px.xml
create mode 100644 app/src/main/res/drawable/battery_horiz_000_24px.xml
create mode 100644 app/src/main/res/drawable/battery_horiz_050_24px.xml
create mode 100644 app/src/main/res/drawable/battery_horiz_075_24px.xml
create mode 100644 app/src/main/res/drawable/battery_low_24px.xml
create mode 100644 app/src/main/res/drawable/battery_very_low_24px.xml
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
index d8f7a5b..56cb409 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
@@ -21,6 +21,14 @@ sealed class UserDataPath(
data object IsUsingClickFlipPage : UserDataPath("isUsingClickFlipPage", Reader)
data object IsUsingVolumeKeyFlip : UserDataPath("isUsingVolumeKeyFlip", Reader)
data object IsUsingFlipAnime : UserDataPath("isUsingFlipAnime", Reader)
+ data object EnableBatteryIndicator : UserDataPath("enableBatteryIndicator", Reader)
+ data object EnableTimeIndicator : UserDataPath("enableTimeIndicator", Reader)
+ data object EnableReadingChapterProgressIndicator : UserDataPath("enableReadingChapterProgressIndicator", Reader)
+ data object AutoPadding : UserDataPath("autoPadding", Reader)
+ data object TopPadding : UserDataPath("topPadding", Reader)
+ data object BottomPadding : UserDataPath("bottomPadding", Reader)
+ data object LeftPadding : UserDataPath("leftPadding", Reader)
+ data object RightPadding : UserDataPath("rightPadding", Reader)
}
data object ReadingBooks : UserDataPath("reading_books")
data object Search: UserDataPath("search") {
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/BookScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/BookScreen.kt
index f8d9362..4bc148c 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/BookScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/BookScreen.kt
@@ -32,7 +32,6 @@ fun BookScreen(
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val navController = rememberNavController()
var topBar : @Composable (TopAppBarScrollBehavior) -> Unit by remember { mutableStateOf(@Composable {}) }
- var bottomBar : @Composable () -> Unit by remember { mutableStateOf(@Composable {}) }
var lastIncomingChapterId by remember { mutableStateOf(-1) }
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
@@ -41,7 +40,6 @@ fun BookScreen(
topBar(scrollBehavior)
}
},
- bottomBar = bottomBar
) { paddingValues ->
NavHost(
modifier = Modifier.padding(paddingValues),
@@ -67,7 +65,6 @@ fun BookScreen(
cacheBook = cacheBook,
requestAddBookToBookshelf = requestAddBookToBookshelf,
)
- bottomBar = {}
}
composable(
route = Screen.Book.Content.route,
@@ -81,9 +78,6 @@ fun BookScreen(
topBar = { newTopBar ->
topBar = newTopBar
},
- bottomBar = { newBottomBar ->
- bottomBar = newBottomBar
- },
bookId = bookId,
chapterId = bundle.getInt("chapterId")
)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
index 693a225..33cd4fd 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
@@ -1,6 +1,8 @@
package indi.dmzz_yyhyy.lightnovelreader.ui.book.content
import android.app.Activity
+import android.content.Context.BATTERY_SERVICE
+import android.os.BatteryManager
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.compose.animation.AnimatedContent
@@ -16,11 +18,14 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
@@ -71,6 +76,7 @@ import indi.dmzz_yyhyy.lightnovelreader.ui.components.FilledCard
import indi.dmzz_yyhyy.lightnovelreader.ui.components.Loading
import indi.dmzz_yyhyy.lightnovelreader.ui.components.SettingsSliderEntry
import indi.dmzz_yyhyy.lightnovelreader.ui.components.SettingsSwitchEntry
+import java.time.LocalDateTime
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -80,14 +86,13 @@ import kotlinx.coroutines.launch
fun ContentScreen(
onClickBackButton: () -> Unit,
topBar: (@Composable (TopAppBarScrollBehavior) -> Unit) -> Unit,
- bottomBar: (@Composable () -> Unit) -> Unit,
bookId: Int,
chapterId: Int,
viewModel: ContentViewModel = hiltViewModel()
) {
val activity = LocalContext.current as Activity
val coroutineScope = rememberCoroutineScope()
- val settingsBottomSheetState = rememberModalBottomSheetState()
+ val settingsBottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
val chapterSelectorBottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
var isRunning by remember { mutableStateOf(false) }
var isImmersive by remember { mutableStateOf(false) }
@@ -129,27 +134,6 @@ fun ContentScreen(
}
}
- bottomBar {
- AnimatedVisibility(
- visible = !isImmersive,
- enter = expandVertically(),
- exit = shrinkVertically()
- ) {
- BottomBar(
- chapterContent = viewModel.uiState.chapterContent,
- readingChapterProgress = viewModel.uiState.readingProgress,
- onClickLastChapter = {
- viewModel.lastChapter()
- },
- onClickNextChapter = {
- viewModel.nextChapter()
- },
- onClickSettings = { showSettingsBottomSheet = true },
- onClickChapterSelector = { showChapterSelectorBottomSheet = true },
- )
- }
- }
-
LaunchedEffect(bookId) {
viewModel.addToReadingBook(bookId)
}
@@ -206,21 +190,88 @@ fun ContentScreen(
enter = fadeIn() + scaleIn(initialScale = 0.7f),
exit = fadeOut() + scaleOut(targetScale = 0.7f)
) {
- AnimatedContent(viewModel.uiState.chapterContent.content, label = "ContentAnimate") {text ->
- ContentText(
- content = text,
- fontSize = viewModel.uiState.fontSize.sp,
- fontLineHeight = viewModel.uiState.fontLineHeight.sp,
- readingProgress = readingChapterProgress,
- isUsingFlipPage = viewModel.uiState.isUsingFlipPage,
- isUsingClickFlip = viewModel.uiState.isUsingClickFlipPage,
- isUsingVolumeKeyFlip = viewModel.uiState.isUsingVolumeKeyFlip,
- isUsingFlipAnime = viewModel.uiState.isUsingFlipAnime,
- onChapterReadingProgressChange = viewModel::changeChapterReadingProgress,
- changeIsImmersive = { isImmersive = !isImmersive }
- )
+ val isEnableIndicator = viewModel.uiState.enableBatteryIndicator || viewModel.uiState.enableTimeIndicator || viewModel.uiState.enableReadingChapterProgressIndicator
+ Box(Modifier.fillMaxSize()) {
+ AnimatedContent(
+ viewModel.uiState.chapterContent.content,
+ label = "ContentAnimate"
+ ) { text ->
+ ContentText(
+ content = text,
+ fontSize = viewModel.uiState.fontSize.sp,
+ fontLineHeight = viewModel.uiState.fontLineHeight.sp,
+ readingProgress = readingChapterProgress,
+ isUsingFlipPage = viewModel.uiState.isUsingFlipPage,
+ isUsingClickFlip = viewModel.uiState.isUsingClickFlipPage,
+ isUsingVolumeKeyFlip = viewModel.uiState.isUsingVolumeKeyFlip,
+ isUsingFlipAnime = viewModel.uiState.isUsingFlipAnime,
+ onChapterReadingProgressChange = viewModel::changeChapterReadingProgress,
+ changeIsImmersive = { isImmersive = !isImmersive },
+ paddingValues =
+ if (viewModel.uiState.autoPadding)
+ PaddingValues(
+ top = 12.dp,
+ bottom = if (isEnableIndicator) 46.dp else 12.dp,
+ start = 16.dp,
+ end = 16.dp
+ )
+ else PaddingValues(
+ top = viewModel.uiState.topPadding.dp,
+ bottom = if (isEnableIndicator) (viewModel.uiState.bottomPadding + 38).dp else viewModel.uiState.bottomPadding.dp,
+ start = viewModel.uiState.leftPadding.dp,
+ end = viewModel.uiState.rightPadding.dp
+ ),
+ autoPadding = viewModel.uiState.autoPadding
+ )
+ }
+ AnimatedVisibility (
+ modifier = Modifier.align(Alignment.BottomCenter),
+ visible = isEnableIndicator,
+ enter = expandVertically(),
+ exit = shrinkVertically()
+ ) {
+ Indicator(
+ Modifier
+ .padding(
+ if (viewModel.uiState.autoPadding)
+ PaddingValues(
+ bottom = 8.dp,
+ start = 16.dp,
+ end = 16.dp
+ )
+ else PaddingValues(
+ bottom = viewModel.uiState.bottomPadding.dp,
+ start = viewModel.uiState.leftPadding.dp,
+ end = viewModel.uiState.rightPadding.dp
+ )
+ ),
+ enableBatteryIndicator = viewModel.uiState.enableBatteryIndicator,
+ enableTimeIndicator = viewModel.uiState.enableTimeIndicator,
+ enableReadingChapterProgressIndicator = viewModel.uiState.enableReadingChapterProgressIndicator,
+ readingChapterProgress = viewModel.uiState.readingProgress
+ )
+ }
}
}
+ AnimatedVisibility(
+ modifier = Modifier.align(Alignment.BottomCenter),
+ visible = !isImmersive,
+ enter = expandVertically(),
+ exit = shrinkVertically()
+ ) {
+ BottomBar(
+ chapterContent = viewModel.uiState.chapterContent,
+ readingChapterProgress = viewModel.uiState.readingProgress,
+ onClickLastChapter = {
+ viewModel.lastChapter()
+ },
+ onClickNextChapter = {
+ viewModel.nextChapter()
+ },
+ onClickSettings = { showSettingsBottomSheet = true },
+ onClickChapterSelector = { showChapterSelectorBottomSheet = true },
+ )
+ }
AnimatedVisibility(visible = showSettingsBottomSheet) {
SettingsBottomSheet(
state = settingsBottomSheetState,
@@ -247,7 +298,27 @@ fun ContentScreen(
isUsingVolumeKeyFlip = viewModel.uiState.isUsingVolumeKeyFlip,
onIsUsingVolumeKeyFlipChange = viewModel::changeIsUsingVolumeKeyFlip,
isUsingFlipAnime = viewModel.uiState.isUsingFlipAnime,
- onIsUsingFlipAnimeChange = viewModel::changeIsUsingFlipAnime
+ onIsUsingFlipAnimeChange = viewModel::changeIsUsingFlipAnime,
+ enableBatteryIndicator = viewModel.uiState.enableBatteryIndicator,
+ onEnableBatteryIndicatorChange = viewModel::changeEnableBatteryIndicator,
+ enableTimeIndicator = viewModel.uiState.enableTimeIndicator,
+ onEnableTimeIndicatorChange = viewModel::changeEnableTimeIndicator,
+ enableReadingChapterProgressIndicator = viewModel.uiState.enableReadingChapterProgressIndicator,
+ onEnableReadingChapterProgressIndicatorChange = viewModel::changeEnableReadingChapterProgressIndicator,
+ autoPadding = viewModel.uiState.autoPadding,
+ onAutoPaddingChange = viewModel::changeAutoPadding,
+ topPadding = viewModel.uiState.topPadding,
+ onTopPaddingChange = viewModel::changeTopPadding,
+ onTopPaddingChangeFinished = viewModel::saveTopPadding,
+ bottomPadding = viewModel.uiState.bottomPadding,
+ onBottomPaddingChange = viewModel::changeBottomPadding,
+ onBottomPaddingChangeFinished = viewModel::saveBottomPadding,
+ leftPadding = viewModel.uiState.leftPadding,
+ onLeftPaddingChange = viewModel::changeLeftPadding,
+ onLeftPaddingChangeFinished = viewModel::saveLeftPadding,
+ rightPadding = viewModel.uiState.rightPadding,
+ onRightPaddingChange = viewModel::changeRightPadding,
+ onRightPaddingChangeFinished = viewModel::saveRightPadding,
)
}
AnimatedVisibility(visible = showChapterSelectorBottomSheet) {
@@ -409,7 +480,27 @@ fun SettingsBottomSheet(
isUsingVolumeKeyFlip: Boolean,
onIsUsingVolumeKeyFlipChange: (Boolean) -> Unit,
isUsingFlipAnime: Boolean,
- onIsUsingFlipAnimeChange: (Boolean) -> Unit
+ onIsUsingFlipAnimeChange: (Boolean) -> Unit,
+ autoPadding: Boolean,
+ onAutoPaddingChange: (Boolean) -> Unit,
+ enableBatteryIndicator: Boolean,
+ onEnableBatteryIndicatorChange: (Boolean) -> Unit,
+ enableTimeIndicator: Boolean,
+ onEnableTimeIndicatorChange: (Boolean) -> Unit,
+ enableReadingChapterProgressIndicator: Boolean,
+ onEnableReadingChapterProgressIndicatorChange: (Boolean) -> Unit,
+ topPadding: Float,
+ onTopPaddingChange: (Float) -> Unit,
+ onTopPaddingChangeFinished: () -> Unit,
+ bottomPadding: Float,
+ onBottomPaddingChange: (Float) -> Unit,
+ onBottomPaddingChangeFinished: () -> Unit,
+ leftPadding: Float,
+ onLeftPaddingChange: (Float) -> Unit,
+ onLeftPaddingChangeFinished: () -> Unit,
+ rightPadding: Float,
+ onRightPaddingChange: (Float) -> Unit,
+ onRightPaddingChangeFinished: () -> Unit,
) {
ModalBottomSheet(
onDismissRequest = onDismissRequest,
@@ -418,62 +509,163 @@ fun SettingsBottomSheet(
Box(
modifier = Modifier.padding(16.dp, 0.dp, 16.dp, 22.dp)
) {
- Column(
+ LazyColumn (
modifier = Modifier.clip(RoundedCornerShape(16.dp)),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
- SettingsSliderEntry(
- description = "阅读器字体大小",
- unit = "sp",
- value = fontSize,
- valueRange = 8f..64f,
- onSlideChange = onFontSizeSliderChange,
- onSliderChangeFinished = onFontSizeSliderChangeFinished
- )
- SettingsSliderEntry(
- description = "阅读器行距大小",
- unit = "sp",
- valueRange = 0f..32f,
- value = fontLineHeight,
- onSlideChange = onFontLineHeightSliderChange,
- onSliderChangeFinished = onFontLineHeightSliderChangeFinished
- )
- SettingsSwitchEntry(
- title = "屏幕常亮",
- description = "在阅读页时,总是保持屏幕开启。这将导致耗电量增加",
- checked = isKeepScreenOn,
- onCheckedChange = onKeepScreenOnChange,
- )
- SettingsSwitchEntry(
- title = "翻页模式",
- description = "切换滚动模式为翻页模式",
- checked = isUsingFlipPage,
- onCheckedChange = onIsUsingFlipPageChange,
- )
- AnimatedVisibility(isUsingFlipPage) {
+ item {
+ SettingsSliderEntry(
+ description = "阅读器字体大小",
+ unit = "sp",
+ value = fontSize,
+ valueRange = 8f..64f,
+ onSlideChange = onFontSizeSliderChange,
+ onSliderChangeFinished = onFontSizeSliderChangeFinished
+ )
+ }
+ item {
+ SettingsSliderEntry(
+ description = "阅读器行距大小",
+ unit = "sp",
+ valueRange = 0f..32f,
+ value = fontLineHeight,
+ onSlideChange = onFontLineHeightSliderChange,
+ onSliderChangeFinished = onFontLineHeightSliderChangeFinished
+ )
+ }
+ item {
SettingsSwitchEntry(
- title = "音量键控制",
- description = "使用音量+键切换至上一页,使用音量-键切换至下一页。",
- checked = isUsingVolumeKeyFlip,
- onCheckedChange = onIsUsingVolumeKeyFlipChange,
+ title = "屏幕常亮",
+ description = "在阅读页时,总是保持屏幕开启。这将导致耗电量增加",
+ checked = isKeepScreenOn,
+ onCheckedChange = onKeepScreenOnChange,
)
}
- AnimatedVisibility(isUsingFlipPage) {
+ item {
SettingsSwitchEntry(
- title = "点击翻页",
- description = "使用点击控制翻页,并将呼出菜单变为上下滑动。",
- checked = isUsingClickFlip,
- onCheckedChange = onIsUsingClickFlipChange,
+ title = "翻页模式",
+ description = "切换滚动模式为翻页模式",
+ checked = isUsingFlipPage,
+ onCheckedChange = onIsUsingFlipPageChange,
)
}
- AnimatedVisibility(isUsingFlipPage) {
+ if(isUsingFlipPage) {
+ item {
+ SettingsSwitchEntry(
+ modifier = Modifier.animateItem(),
+ title = "音量键控制",
+ description = "使用音量+键切换至上一页,使用音量-键切换至下一页。",
+ checked = isUsingVolumeKeyFlip,
+ onCheckedChange = onIsUsingVolumeKeyFlipChange,
+ )
+ }
+ }
+ if(isUsingFlipPage) {
+ item {
+ SettingsSwitchEntry(
+ modifier = Modifier.animateItem(),
+ title = "点击翻页",
+ description = "使用点击控制翻页,并将呼出菜单变为上下滑动。",
+ checked = isUsingClickFlip,
+ onCheckedChange = onIsUsingClickFlipChange,
+ )
+ }
+ }
+ if(isUsingFlipPage) {
+ item {
+ SettingsSwitchEntry(
+ modifier = Modifier.animateItem(),
+ title = "启用动画",
+ description = "开启点击翻页或音量键翻页时的动画,如果关闭可以允许你快速的翻页。",
+ checked = isUsingFlipAnime,
+ onCheckedChange = onIsUsingFlipAnimeChange,
+ )
+ }
+ }
+ item {
+ SettingsSwitchEntry(
+ title = "自动获取边距",
+ description = "自动识别手机屏幕的边距,并进行显示适配,如关闭需要手动进行设置。",
+ checked = autoPadding,
+ onCheckedChange = onAutoPaddingChange,
+ )
+ }
+ item {
SettingsSwitchEntry(
- title = "启用动画",
- description = "开启点击翻页或音量键翻页时的动画,如果关闭可以允许你快速的翻页。",
- checked = isUsingFlipAnime,
- onCheckedChange = onIsUsingFlipAnimeChange,
+ title = "电量指示器",
+ description = "在页面左下角显示当前电量。",
+ checked = enableBatteryIndicator,
+ onCheckedChange = onEnableBatteryIndicatorChange,
)
}
+ item {
+ SettingsSwitchEntry(
+ title = "时间指示器",
+ description = "在页面左下角显示当前时间。",
+ checked = enableTimeIndicator,
+ onCheckedChange = onEnableTimeIndicatorChange,
+ )
+ }
+ item {
+ SettingsSwitchEntry(
+ title = "进度指示器",
+ description = "在页面右下角显示当前阅读进度。",
+ checked = enableReadingChapterProgressIndicator,
+ onCheckedChange = onEnableReadingChapterProgressIndicatorChange,
+ )
+ }
+ if(!autoPadding) {
+ item {
+ SettingsSliderEntry(
+ modifier = Modifier.animateItem(),
+ description = "上边距",
+ unit = "dp",
+ value = topPadding,
+ valueRange = 0f..128f,
+ onSlideChange = onTopPaddingChange,
+ onSliderChangeFinished = onTopPaddingChangeFinished
+ )
+ }
+ }
+ if(!autoPadding) {
+ item {
+ SettingsSliderEntry(
+ modifier = Modifier.animateItem(),
+ description = "下边距",
+ unit = "dp",
+ value = bottomPadding,
+ valueRange = 0f..128f,
+ onSlideChange = onBottomPaddingChange,
+ onSliderChangeFinished = onBottomPaddingChangeFinished
+ )
+ }
+ }
+ if(!autoPadding) {
+ item {
+ SettingsSliderEntry(
+ modifier = Modifier.animateItem(),
+ description = "左边距",
+ unit = "dp",
+ value = leftPadding,
+ valueRange = 0f..128f,
+ onSlideChange = onLeftPaddingChange,
+ onSliderChangeFinished = onLeftPaddingChangeFinished
+ )
+ }
+ }
+ if(!autoPadding) {
+ item {
+ SettingsSliderEntry(
+ modifier = Modifier.animateItem(),
+ description = "右边距",
+ unit = "dp",
+ value = rightPadding,
+ valueRange = 0f..128f,
+ onSlideChange = onRightPaddingChange,
+ onSliderChangeFinished = onRightPaddingChangeFinished
+ )
+ }
+ }
}
}
}
@@ -619,4 +811,54 @@ fun ChapterSelectorBottomSheet(
}
}
}
+}
+
+@Composable
+fun Indicator(
+ modifier: Modifier = Modifier,
+ enableBatteryIndicator: Boolean,
+ enableTimeIndicator: Boolean,
+ enableReadingChapterProgressIndicator: Boolean,
+ readingChapterProgress: Float
+) {
+ val batteryManager = LocalContext.current.getSystemService(BATTERY_SERVICE) as BatteryManager
+ val batLevel: Int = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
+ Row(
+ modifier = modifier.fillMaxWidth().height(46.dp),
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
+ verticalAlignment = Alignment.CenterVertically
+ ) {
+ if (enableBatteryIndicator)
+ Icon(
+ modifier = Modifier.size(20.dp),
+ painter =
+ when {
+ (batLevel == 0) -> painterResource(R.drawable.battery_horiz_000_24px)
+ (batLevel in 1..10) -> painterResource(R.drawable.battery_very_low_24px)
+ (batLevel in 11..35) -> painterResource(R.drawable.battery_low_24px)
+ (batLevel in 36..65) -> painterResource(R.drawable.battery_horiz_050_24px)
+ (batLevel in 66..90) -> painterResource(R.drawable.battery_horiz_075_24px)
+ (batLevel in 91..100) -> painterResource(R.drawable.battery_full_alt_24px)
+ else -> painterResource(R.drawable.battery_horiz_000_24px)
+ },
+ contentDescription = null
+ )
+ if (enableTimeIndicator)
+ AnimatedText(
+ text = "${LocalDateTime.now().hour} : " + LocalDateTime.now().minute.let { if (it < 10) "0$it" else it.toString()},
+ style = MaterialTheme.typography.labelLarge.copy(
+ fontWeight = FontWeight.W500
+ ),
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ Box(Modifier.weight(1f))
+ if (enableReadingChapterProgressIndicator)
+ AnimatedText(
+ text = "${(readingChapterProgress * 100).toInt()}%",
+ style = MaterialTheme.typography.labelLarge.copy(
+ fontWeight = FontWeight.W500
+ ),
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
+ }
}
\ No newline at end of file
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
index 53fcfc6..91409ab 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
@@ -22,6 +22,14 @@ interface ContentScreenUiState {
val isUsingClickFlipPage: Boolean
val isUsingVolumeKeyFlip: Boolean
val isUsingFlipAnime: Boolean
+ val enableBatteryIndicator: Boolean
+ val enableTimeIndicator: Boolean
+ val enableReadingChapterProgressIndicator: Boolean
+ val autoPadding: Boolean
+ val topPadding: Float
+ val bottomPadding: Float
+ val leftPadding: Float
+ val rightPadding: Float
}
class MutableContentScreenUiState: ContentScreenUiState {
@@ -37,4 +45,12 @@ class MutableContentScreenUiState: ContentScreenUiState {
override var isUsingClickFlipPage by mutableStateOf(false)
override var isUsingVolumeKeyFlip by mutableStateOf(false)
override var isUsingFlipAnime by mutableStateOf(false)
+ override var enableBatteryIndicator by mutableStateOf(true)
+ override var enableTimeIndicator by mutableStateOf(true)
+ override var enableReadingChapterProgressIndicator by mutableStateOf(true)
+ override var autoPadding by mutableStateOf(false)
+ override var topPadding by mutableStateOf(12f)
+ override var bottomPadding by mutableStateOf(12f)
+ override var leftPadding by mutableStateOf(16f)
+ override var rightPadding by mutableStateOf(16f)
}
\ No newline at end of file
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
index bfcc77e..82f9b45 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
@@ -26,9 +26,18 @@ class ContentViewModel @Inject constructor(
private val isUsingClickFlipPageUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingClickFlipPage.path)
private val isUsingVolumeKeyFlipUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingVolumeKeyFlip.path)
private val isUsingFlipAnimeUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingFlipAnime.path)
+ private val enableBatteryIndicatorUserData = userDataRepository.booleanUserData(UserDataPath.Reader.EnableBatteryIndicator.path)
+ private val enableTimeIndicatorUserData = userDataRepository.booleanUserData(UserDataPath.Reader.EnableTimeIndicator.path)
+ private val enableReadingChapterProgressIndicatorUserData = userDataRepository.booleanUserData(UserDataPath.Reader.EnableReadingChapterProgressIndicator.path)
+ private val autoPaddingUserData = userDataRepository.booleanUserData(UserDataPath.Reader.AutoPadding.path)
+ private val topPaddingUserData = userDataRepository.floatUserData(UserDataPath.Reader.TopPadding.path)
+ private val bottomPaddingUserData = userDataRepository.floatUserData(UserDataPath.Reader.BottomPadding.path)
+ private val leftPaddingUserData = userDataRepository.floatUserData(UserDataPath.Reader.LeftPadding.path)
+ private val rightPaddingUserData = userDataRepository.floatUserData(UserDataPath.Reader.RightPadding.path)
private val readingBookListUserData = userDataRepository.intListUserData(UserDataPath.ReadingBooks.path)
val uiState: ContentScreenUiState = _uiState
+ @Suppress("DuplicatedCode")
fun init(bookId: Int, chapterId: Int) {
if (bookId != _bookId) {
viewModelScope.launch {
@@ -58,6 +67,14 @@ class ContentViewModel @Inject constructor(
_uiState.isUsingClickFlipPage = isUsingClickFlipPageUserData.getOrDefault(_uiState.isUsingClickFlipPage)
_uiState.isUsingVolumeKeyFlip = isUsingVolumeKeyFlipUserData.getOrDefault(_uiState.isUsingVolumeKeyFlip)
_uiState.isUsingFlipAnime = isUsingFlipAnimeUserData.getOrDefault(_uiState.isUsingFlipAnime)
+ _uiState.enableBatteryIndicator = enableBatteryIndicatorUserData.getOrDefault(_uiState.enableBatteryIndicator)
+ _uiState.enableTimeIndicator = enableTimeIndicatorUserData.getOrDefault(_uiState.enableTimeIndicator)
+ _uiState.enableReadingChapterProgressIndicator = enableReadingChapterProgressIndicatorUserData.getOrDefault(_uiState.enableReadingChapterProgressIndicator)
+ _uiState.autoPadding = autoPaddingUserData.getOrDefault(_uiState.autoPadding)
+ _uiState.topPadding = topPaddingUserData.getOrDefault(_uiState.topPadding)
+ _uiState.bottomPadding = bottomPaddingUserData.getOrDefault(_uiState.bottomPadding)
+ _uiState.leftPadding = leftPaddingUserData.getOrDefault(_uiState.leftPadding)
+ _uiState.rightPadding = rightPaddingUserData.getOrDefault(_uiState.rightPadding)
}
}
@@ -207,6 +224,74 @@ class ContentViewModel @Inject constructor(
}
}
+ fun changeEnableBatteryIndicator(enableBatteryIndicator: Boolean) {
+ _uiState.enableBatteryIndicator = enableBatteryIndicator
+ viewModelScope.launch(Dispatchers.IO) {
+ enableBatteryIndicatorUserData.set(enableBatteryIndicator)
+ }
+ }
+
+ fun changeEnableTimeIndicator(enableTimeIndicator: Boolean) {
+ _uiState.enableTimeIndicator = enableTimeIndicator
+ viewModelScope.launch(Dispatchers.IO) {
+ enableTimeIndicatorUserData.set(enableTimeIndicator)
+ }
+ }
+
+ fun changeEnableReadingChapterProgressIndicator(enableReadingChapterProgressIndicator: Boolean) {
+ _uiState.enableReadingChapterProgressIndicator = enableReadingChapterProgressIndicator
+ viewModelScope.launch(Dispatchers.IO) {
+ enableReadingChapterProgressIndicatorUserData.set(enableReadingChapterProgressIndicator)
+ }
+ }
+
+ fun changeAutoPadding(autoPadding: Boolean) {
+ _uiState.autoPadding = autoPadding
+ viewModelScope.launch(Dispatchers.IO) {
+ autoPaddingUserData.set(autoPadding)
+ }
+ }
+
+ fun changeTopPadding(padding: Float) {
+ _uiState.topPadding = padding
+ }
+
+ fun saveTopPadding() {
+ viewModelScope.launch(Dispatchers.IO) {
+ topPaddingUserData.set(_uiState.topPadding)
+ }
+ }
+
+ fun changeBottomPadding(padding: Float) {
+ _uiState.bottomPadding = padding
+ }
+
+ fun saveBottomPadding() {
+ viewModelScope.launch(Dispatchers.IO) {
+ bottomPaddingUserData.set(_uiState.bottomPadding)
+ }
+ }
+
+ fun changeLeftPadding(padding: Float) {
+ _uiState.leftPadding = padding
+ }
+
+ fun saveLeftPadding() {
+ viewModelScope.launch(Dispatchers.IO) {
+ leftPaddingUserData.set(_uiState.leftPadding)
+ }
+ }
+
+ fun changeRightPadding(padding: Float) {
+ _uiState.rightPadding = padding
+ }
+
+ fun saveRightPadding() {
+ viewModelScope.launch(Dispatchers.IO) {
+ rightPaddingUserData.set(_uiState.rightPadding)
+ }
+ }
+
fun addToReadingBook(bookId: Int) {
viewModelScope.launch(Dispatchers.IO) {
readingBookListUserData.update {
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
index 7fa2423..566f99f 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
@@ -11,6 +11,7 @@ import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.calculateEndPadding
@@ -24,6 +25,8 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
+import androidx.compose.foundation.text.selection.SelectionContainer
+import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -34,9 +37,11 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.TextLayoutResult
@@ -71,8 +76,8 @@ fun ContentText(
isUsingFlipAnime: Boolean,
onChapterReadingProgressChange: (Float) -> Unit,
changeIsImmersive: () -> Unit,
- paddingValues: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 12.dp),
- autoAvoid: Boolean = true
+ paddingValues: PaddingValues,
+ autoPadding: Boolean = true
) {
val autoAvoidPaddingValues = with(LocalDensity.current) {
PaddingValues(
@@ -91,6 +96,7 @@ fun ContentText(
modifier = Modifier
.animateContentSize()
.fillMaxSize()
+ .padding(paddingValues)
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
@@ -115,7 +121,7 @@ fun ContentText(
onChapterReadingProgressChange = onChapterReadingProgressChange,
changeIsImmersive = changeIsImmersive,
paddingValues =
- if (autoAvoid) autoAvoidPaddingValues else paddingValues
+ if (autoPadding) autoAvoidPaddingValues else paddingValues
)
}
@@ -156,6 +162,7 @@ fun ScrollContentTextComponent(
.filter { it.isNotBlank() }
) {
BasicContentComponent(
+ modifier = Modifier.fillMaxWidth(),
text = it,
fontSize = fontSize,
fontLineHeight = fontLineHeight,
@@ -176,7 +183,7 @@ fun SimpleFlipPageTextComponent(
isUsingFlipAnime: Boolean,
onChapterReadingProgressChange: (Float) -> Unit,
changeIsImmersive: () -> Unit,
- paddingValues: PaddingValues = PaddingValues(8.dp)
+ paddingValues: PaddingValues
) {
val textMeasurer = rememberTextMeasurer()
val scope = rememberCoroutineScope()
@@ -239,7 +246,7 @@ fun SimpleFlipPageTextComponent(
onChapterReadingProgressChange(pageState.currentPage.toFloat() / (pageState.pageCount - 1))
else onChapterReadingProgressChange(1F)
}
- DisposableEffect(isUsingVolumeKeyFlip) {
+ DisposableEffect(isUsingVolumeKeyFlip, isUsingFlipAnime) {
val localBroadcastManager = LocalBroadcastManager.getInstance(current)
val keycodeVolumeUpReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
@@ -304,7 +311,7 @@ fun SimpleFlipPageTextComponent(
if (it.absoluteValue > 60) changeIsImmersive.invoke()
}
)
- .pointerInput(isUsingClickFlip) {
+ .pointerInput(isUsingClickFlip, isUsingFlipAnime) {
detectTapGestures(
onTap = {
if (isUsingClickFlip) {
@@ -348,24 +355,37 @@ fun BasicContentComponent(
fontLineHeight: TextUnit,
) {
if (text.startsWith("http://") || text.startsWith("https://")) {
- AsyncImage(
- modifier = modifier.fillMaxWidth(),
- model = ImageRequest.Builder(LocalContext.current)
- .data(text)
- .crossfade(true)
- .build(),
- contentDescription = null
- )
- }
- else Text(
- modifier = modifier.fillMaxSize(),
- text = text,
- textAlign = TextAlign.Start,
- style = MaterialTheme.typography.bodyMedium,
- fontWeight = FontWeight.W400,
- fontSize = fontSize,
- lineHeight = (fontSize.value + fontLineHeight.value).sp
- )
+ Box(modifier
+ .fillMaxWidth()
+ ) {
+ CircularProgressIndicator(
+ color = MaterialTheme.colorScheme.primary,
+ modifier = Modifier.align(Alignment.Center).padding(16.dp)
+ )
+ AsyncImage(
+ modifier = Modifier
+ .fillMaxSize()
+ .align(Alignment.Center),
+ model = ImageRequest.Builder(LocalContext.current)
+ .data(text)
+ .crossfade(true)
+ .build(),
+ contentScale = ContentScale.FillWidth,
+ contentDescription = null
+ )
+ }
+ } else
+ SelectionContainer {
+ Text(
+ modifier = modifier.fillMaxSize(),
+ text = text,
+ textAlign = TextAlign.Start,
+ style = MaterialTheme.typography.bodyMedium,
+ fontWeight = FontWeight.W400,
+ fontSize = fontSize,
+ lineHeight = (fontSize.value + fontLineHeight.value).sp
+ )
+ }
}
fun slipText(
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/components/SettingsEntry.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/components/SettingsEntry.kt
index f01b03f..5dca7d4 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/components/SettingsEntry.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/components/SettingsEntry.kt
@@ -30,13 +30,14 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat.startActivity
import indi.dmzz_yyhyy.lightnovelreader.ui.home.settings.data.MenuOptions
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
import java.text.DecimalFormat
import kotlin.math.roundToInt
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
@Composable
fun SettingsSwitchEntry(
+ modifier: Modifier = Modifier,
title: String,
description: String,
checked: Boolean,
@@ -44,7 +45,7 @@ fun SettingsSwitchEntry(
disabled: Boolean = false
) {
FilledCard(
- modifier = Modifier
+ modifier = modifier
.fillMaxWidth(),
shape = RoundedCornerShape(6.dp)
) {
@@ -89,6 +90,7 @@ fun SettingsSwitchEntry(
@Composable
fun SettingsSliderEntry(
+ modifier: Modifier = Modifier,
description: String,
unit: String,
value: Float,
@@ -97,6 +99,7 @@ fun SettingsSliderEntry(
onSliderChangeFinished: () -> Unit
) {
FilledCard(
+ modifier = modifier,
shape = RoundedCornerShape(6.dp)
) {
Column(Modifier.padding(18.dp, 10.dp, 20.dp, 12.dp)) {
diff --git a/app/src/main/res/drawable/battery_full_alt_24px.xml b/app/src/main/res/drawable/battery_full_alt_24px.xml
new file mode 100644
index 0000000..af60055
--- /dev/null
+++ b/app/src/main/res/drawable/battery_full_alt_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/battery_horiz_000_24px.xml b/app/src/main/res/drawable/battery_horiz_000_24px.xml
new file mode 100644
index 0000000..4eeaa5c
--- /dev/null
+++ b/app/src/main/res/drawable/battery_horiz_000_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/battery_horiz_050_24px.xml b/app/src/main/res/drawable/battery_horiz_050_24px.xml
new file mode 100644
index 0000000..5f7be06
--- /dev/null
+++ b/app/src/main/res/drawable/battery_horiz_050_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/battery_horiz_075_24px.xml b/app/src/main/res/drawable/battery_horiz_075_24px.xml
new file mode 100644
index 0000000..4828223
--- /dev/null
+++ b/app/src/main/res/drawable/battery_horiz_075_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/battery_low_24px.xml b/app/src/main/res/drawable/battery_low_24px.xml
new file mode 100644
index 0000000..34ca7dd
--- /dev/null
+++ b/app/src/main/res/drawable/battery_low_24px.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable/battery_very_low_24px.xml b/app/src/main/res/drawable/battery_very_low_24px.xml
new file mode 100644
index 0000000..898bf44
--- /dev/null
+++ b/app/src/main/res/drawable/battery_very_low_24px.xml
@@ -0,0 +1,10 @@
+
+
+
From 42a491bbe5f2bda06412fb3d080eb5d3ea9f0beb Mon Sep 17 00:00:00 2001
From: NightFish <101402767+dmzz-yyhyy@users.noreply.github.com>
Date: Tue, 17 Sep 2024 02:38:30 +0800
Subject: [PATCH 3/8] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=B0=E5=BB=BA?=
=?UTF-8?q?=E4=B9=A6=E6=9E=B6=E6=97=B6=E7=9A=84"=E5=88=A0=E9=99=A4?=
=?UTF-8?q?=E4=B9=A6=E6=9E=B6"=E9=80=89=E9=A1=B9=20#105?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../bookshelf/edit/EditBookshelfScreen.kt | 32 +++++++++----------
1 file changed, 15 insertions(+), 17 deletions(-)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt
index cb4f025..6a5ddd1 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt
@@ -3,12 +3,9 @@ package indi.dmzz_yyhyy.lightnovelreader.ui.home.bookshelf.edit
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
-import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
@@ -128,20 +125,21 @@ fun EditBookshelfScreen(
value = bookshelf.systemUpdateReminder,
onValueChange = onSystemUpdateReminderChange
)
- ListItem(
- modifier = Modifier.clickable {
- dialogVisible = true
- },
- leadingContent = {
- Icon(
- modifier = Modifier.padding(horizontal = 10.dp),
- painter = painterResource(R.drawable.delete_forever_24px),
- contentDescription = "Localized description",
- )
- },
- headlineContent = { Text(text = "删除此书架", fontSize = 16.sp, modifier = Modifier.padding(bottom = 2.dp)) },
- supportingContent = { Text(text = "将此书架永久移除", fontSize = 14.sp, lineHeight = 15.sp) },
- )
+ if (bookshelfId >= 0)
+ ListItem(
+ modifier = Modifier.clickable {
+ dialogVisible = true
+ },
+ leadingContent = {
+ Icon(
+ modifier = Modifier.padding(horizontal = 10.dp),
+ painter = painterResource(R.drawable.delete_forever_24px),
+ contentDescription = "Localized description",
+ )
+ },
+ headlineContent = { Text(text = "删除此书架", fontSize = 16.sp, modifier = Modifier.padding(bottom = 2.dp)) },
+ supportingContent = { Text(text = "将此书架永久移除", fontSize = 14.sp, lineHeight = 15.sp) },
+ )
}
}
From 133aff4b29144092e502c5c143a74c62487f94b5 Mon Sep 17 00:00:00 2001
From: NightFish <101402767+dmzz-yyhyy@users.noreply.github.com>
Date: Tue, 17 Sep 2024 02:54:39 +0800
Subject: [PATCH 4/8] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=90=9C=E7=B4=A2?=
=?UTF-8?q?=E9=A1=B5=E4=B8=8E=E6=8E=A2=E7=B4=A2=E9=A1=B5=E5=8A=A0=E8=BD=BD?=
=?UTF-8?q?=E9=80=BB=E8=BE=91=20#106?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ui/home/exploration/Exploration.kt | 5 ++++-
.../exploration/expanded/ExpandedPageScreen.kt | 2 +-
.../exploration/expanded/ExpandedPageViewModel.kt | 7 +++++++
.../ui/home/settings/SettingsScreen.kt | 14 ++++++--------
4 files changed, 18 insertions(+), 10 deletions(-)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/Exploration.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/Exploration.kt
index 56e7b80..af48489 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/Exploration.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/Exploration.kt
@@ -143,7 +143,10 @@ fun Exploration(
init = { expandedPageViewModel.init(it) },
loadMore = expandedPageViewModel::loadMore,
requestAddBookToBookshelf = requestAddBookToBookshelf,
- onClickBack = navController::popBackStack,
+ onClickBack = {
+ expandedPageViewModel.clear()
+ navController.popBackStack()
+ },
onClickBook = onClickBook
)
}
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageScreen.kt
index f2cf618..d60526c 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageScreen.kt
@@ -47,7 +47,7 @@ fun ExpandedPageScreen(
onClickBack: () -> Unit,
onClickBook: (Int) -> Unit,
) {
- LaunchedEffect(expandedPageDataSourceId) { init(expandedPageDataSourceId) }
+ LifecycleEventEffect(Lifecycle.Event.ON_START) { init.invoke(expandedPageDataSourceId) }
topBar { enterAlwaysScrollBehavior, _ ->
TopBar(
scrollBehavior = enterAlwaysScrollBehavior,
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageViewModel.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageViewModel.kt
index 7687c91..df899b0 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageViewModel.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageViewModel.kt
@@ -19,10 +19,13 @@ class ExpandedPageViewModel @Inject constructor(
private var expandedPageDataSource: ExplorationExpandedPageDataSource? = null
private var explorationExpandedPageBookListCollectJob: Job? = null
private var loadMoreJob: Job? = null
+ private var lastExpandedPageDataSourceId: String = ""
private val _uiState = MutableExpandedPageUiState()
val uiState: ExpandedPageUiState = _uiState
fun init(expandedPageDataSourceId: String) {
+ if (expandedPageDataSourceId == lastExpandedPageDataSourceId) return
+ lastExpandedPageDataSourceId = expandedPageDataSourceId
loadMoreJob?.cancel()
explorationExpandedPageBookListCollectJob?.cancel()
expandedPageDataSource = explorationRepository.getExplorationExpandedPageDataSource(expandedPageDataSourceId)
@@ -51,4 +54,8 @@ class ExpandedPageViewModel @Inject constructor(
expandedPageDataSource?.loadMore()
}
}
+
+ fun clear() {
+ lastExpandedPageDataSourceId = ""
+ }
}
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/SettingsScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/SettingsScreen.kt
index 2bd8400..97f22bd 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/SettingsScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/SettingsScreen.kt
@@ -23,8 +23,8 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -68,12 +68,10 @@ fun SettingsScreen(
LifecycleEventEffect(Lifecycle.Event.ON_CREATE) {
viewModel.loadSettings()
}
- LifecycleEventEffect(Lifecycle.Event.ON_START) {
- topBar { enterAlwaysScrollBehavior, _ ->
- TopBar(
- scrollBehavior = enterAlwaysScrollBehavior,
- )
- }
+ topBar { enterAlwaysScrollBehavior, _ ->
+ TopBar(
+ scrollBehavior = enterAlwaysScrollBehavior,
+ )
}
Column(Modifier.verticalScroll(rememberScrollState())) {
SettingsCard(
@@ -120,7 +118,7 @@ fun SettingsScreen(
private fun TopBar(
scrollBehavior: TopAppBarScrollBehavior
) {
- MediumTopAppBar(
+ TopAppBar(
title = {
Text(
text = stringResource(R.string.nav_settings),
From b2d5266ff56f06a6d0bee8774645dc8e6ca73cbf Mon Sep 17 00:00:00 2001
From: NightFish <101402767+dmzz-yyhyy@users.noreply.github.com>
Date: Tue, 17 Sep 2024 13:32:23 +0800
Subject: [PATCH 5/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=98=85=E8=AF=BB?=
=?UTF-8?q?=E8=BF=9B=E5=BA=A6=E6=81=A2=E5=A4=8D=20#102?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ui/book/content/ContentScreen.kt | 8 +-
.../ui/book/content/ContentScreenUiState.kt | 5 +-
.../ui/book/content/ContentViewModel.kt | 2 +-
.../ui/book/content/TextComponent.kt | 82 +++++++++----------
4 files changed, 45 insertions(+), 52 deletions(-)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
index 33cd4fd..c6c6362 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
@@ -96,7 +96,6 @@ fun ContentScreen(
val chapterSelectorBottomSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
var isRunning by remember { mutableStateOf(false) }
var isImmersive by remember { mutableStateOf(false) }
- var readingChapterProgress by remember { mutableStateOf(0.0f) }
var showSettingsBottomSheet by remember { mutableStateOf(false) }
var showChapterSelectorBottomSheet by remember { mutableStateOf(false) }
var totalReadingTime by remember { mutableStateOf(0) }
@@ -141,11 +140,6 @@ fun ContentScreen(
viewModel.init(bookId, chapterId)
totalReadingTime = 0
}
- LaunchedEffect(viewModel.uiState.chapterContent.id) {
- readingChapterProgress =
- if (viewModel.uiState.chapterContent.id == viewModel.uiState.userReadingData.lastReadChapterId) viewModel.uiState.userReadingData.lastReadChapterProgress
- else 0F
- }
LifecycleResumeEffect(Unit) {
isRunning = true
onPauseOrDispose {
@@ -200,7 +194,7 @@ fun ContentScreen(
content = text,
fontSize = viewModel.uiState.fontSize.sp,
fontLineHeight = viewModel.uiState.fontLineHeight.sp,
- readingProgress = readingChapterProgress,
+ readingProgress = viewModel.uiState.readingProgress,
isUsingFlipPage = viewModel.uiState.isUsingFlipPage,
isUsingClickFlip = viewModel.uiState.isUsingClickFlipPage,
isUsingVolumeKeyFlip = viewModel.uiState.isUsingVolumeKeyFlip,
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
index 91409ab..2386121 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
@@ -13,7 +13,9 @@ interface ContentScreenUiState {
val isLoading: Boolean
val chapterContent: ChapterContent
val userReadingData: UserReadingData
- val readingProgress: Float
+ val readingProgress: Float get() =
+ if (userReadingData.lastReadChapterId == chapterContent.id) userReadingData.lastReadChapterProgress
+ else 0f
val bookVolumes: BookVolumes
val fontSize: Float
val fontLineHeight: Float
@@ -36,7 +38,6 @@ class MutableContentScreenUiState: ContentScreenUiState {
override var isLoading by mutableStateOf(true)
override var chapterContent by mutableStateOf(ChapterContent.empty())
override var userReadingData by mutableStateOf(UserReadingData.empty())
- override var readingProgress by mutableStateOf(0f)
override var bookVolumes by mutableStateOf(BookVolumes.empty())
override var fontSize by mutableStateOf(14f)
override var fontLineHeight by mutableStateOf(0f)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
index 82f9b45..c55da48 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
@@ -140,7 +140,6 @@ class ContentViewModel @Inject constructor(
fun changeChapterReadingProgress(progress: Float) {
if (progress.isNaN()) return
- _uiState.readingProgress = progress
viewModelScope.launch(Dispatchers.IO) {
bookRepository.updateUserReadingData(_bookId) { userReadingData ->
val readCompletedChapterIds =
@@ -150,6 +149,7 @@ class ContentViewModel @Inject constructor(
userReadingData.readCompletedChapterIds
userReadingData.copy(
lastReadTime = LocalDateTime.now(),
+ lastReadChapterId = _uiState.chapterContent.id,
lastReadChapterProgress = progress,
readingProgress = readCompletedChapterIds.size / _uiState.bookVolumes.volumes.sumOf { it.chapters.size }.toFloat(),
readCompletedChapterIds = readCompletedChapterIds
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
index 566f99f..12361e6 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
@@ -77,7 +77,7 @@ fun ContentText(
onChapterReadingProgressChange: (Float) -> Unit,
changeIsImmersive: () -> Unit,
paddingValues: PaddingValues,
- autoPadding: Boolean = true
+ autoPadding: Boolean
) {
val autoAvoidPaddingValues = with(LocalDensity.current) {
PaddingValues(
@@ -123,6 +123,7 @@ fun ContentText(
paddingValues =
if (autoPadding) autoAvoidPaddingValues else paddingValues
)
+ println("autoPadding: $autoPadding values: $autoAvoidPaddingValues simple: $paddingValues")
}
@Composable
@@ -136,7 +137,10 @@ fun ScrollContentTextComponent(
) {
val coroutineScope = rememberCoroutineScope()
val contentLazyColumnState = rememberLazyListState()
+ var contentKey by remember { mutableStateOf(0) }
LaunchedEffect(readingProgress) {
+ if (contentKey == content.hashCode()) return@LaunchedEffect
+ contentKey = content.hashCode()
coroutineScope.launch {
contentLazyColumnState.scrollToItem(
0,
@@ -188,7 +192,10 @@ fun SimpleFlipPageTextComponent(
val textMeasurer = rememberTextMeasurer()
val scope = rememberCoroutineScope()
val current = LocalContext.current
+ val localDensity = LocalDensity.current
+ var contentKey by remember { mutableStateOf(0) }
var slipTextJob by remember { mutableStateOf(null) }
+ var resumedReadingProgressJob by remember { mutableStateOf(null) }
var constraints by remember { mutableStateOf(null) }
var textStyle by remember { mutableStateOf(null) }
var slippedTextList by remember { mutableStateOf(emptyList()) }
@@ -196,51 +203,42 @@ fun SimpleFlipPageTextComponent(
var readingPageFistCharOffset by remember { mutableStateOf(0) }
var resumedReadingProgress by remember { mutableStateOf(false) }
LaunchedEffect(content, textStyle, fontLineHeight, fontSize, constraints?.maxHeight, constraints?.maxWidth) {
- if (constraints != null && textStyle != null) {
- slipTextJob?.cancel()
- slipTextJob = scope.launch(Dispatchers.IO) {
- readingPageFistCharOffset = slippedTextList
- .subList(0, pageState.currentPage)
- .sumOf { it.length }
- .plus(1)
- slippedTextList = slipText(
- textMeasurer = textMeasurer,
- constraints = constraints!!,
- text = content,
- style = textStyle!!.copy(
- fontSize = fontSize,
- fontWeight = FontWeight.W400,
- lineHeight = (fontLineHeight.value + fontSize.value).sp
- )
+ val key = content.hashCode() + fontLineHeight.value.hashCode() + fontSize.value.hashCode() + constraints?.maxHeight.hashCode() + constraints?.maxWidth.hashCode()
+ println(key)
+ println(contentKey)
+ println(with(localDensity) {
+ (paddingValues.calculateTopPadding() + paddingValues.calculateBottomPadding() + 10.dp)
+ .toPx()
+ }.toInt())
+ println("${paddingValues.calculateTopPadding()} ${paddingValues.calculateBottomPadding()}")
+ println("${content.hashCode()} ${fontLineHeight.value}.sp ${fontSize.value}.sp ${constraints?.maxHeight}.xp ${constraints?.maxWidth}.xp")
+ if (constraints == null || textStyle == null || key == contentKey) return@LaunchedEffect
+ contentKey = key
+ slipTextJob?.cancel()
+ slipTextJob = scope.launch(Dispatchers.IO) {
+ readingPageFistCharOffset = slippedTextList
+ .subList(0, pageState.currentPage)
+ .sumOf { it.length }
+ .plus(1)
+ slippedTextList = slipText(
+ textMeasurer = textMeasurer,
+ constraints = constraints!!,
+ text = content,
+ style = textStyle!!.copy(
+ fontSize = fontSize,
+ fontWeight = FontWeight.W400,
+ lineHeight = (fontLineHeight.value + fontSize.value).sp
)
- pageState = PagerState { slippedTextList.size }
- scope.launch {
- slippedTextList
- .let {
- var totalOffset = 0
- it.forEachIndexed { index, s ->
- totalOffset += s.length
- if (totalOffset >= readingPageFistCharOffset)
- return@let index
- }
- return@let 0
- }
- .let {
- if (it != 0) {
- pageState.scrollToPage(it)
- }
- }
- if (!resumedReadingProgress) {
- pageState.scrollToPage((readingProgress * pageState.pageCount).toInt())
- resumedReadingProgress = true
- }
- }
+ )
+ pageState = PagerState { slippedTextList.size }
+ resumedReadingProgressJob?.cancel()
+ resumedReadingProgressJob = scope.launch {
+ pageState.scrollToPage((readingProgress * pageState.pageCount).toInt())
+ resumedReadingProgress = true
+ println("resumed the page to ${(readingProgress * pageState.pageCount).toInt()}")
}
}
}
- LaunchedEffect(readingProgress) {
- resumedReadingProgress = false
- }
LaunchedEffect(pageState.currentPage, pageState.pageCount) {
if (pageState.pageCount != 1)
onChapterReadingProgressChange(pageState.currentPage.toFloat() / (pageState.pageCount - 1))
From 48d53c276821e8fdd2f1f2efa91e2bc84be7a8b3 Mon Sep 17 00:00:00 2001
From: NightFish <101402767+dmzz-yyhyy@users.noreply.github.com>
Date: Tue, 17 Sep 2024 13:56:30 +0800
Subject: [PATCH 6/8] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=88=87=E6=8D=A2?=
=?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=A6=82=E7=8E=87=E9=97=AA=E9=80=80=E4=B8=8E?=
=?UTF-8?q?=E9=98=85=E8=AF=BB=E4=B8=AD=E9=A1=B5=E9=9D=A2=E6=97=A0=E6=B3=95?=
=?UTF-8?q?=E6=BB=9A=E5=8A=A8=E9=97=AE=E9=A2=98=20#97?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../lightnovelreader/ui/home/HomeScreen.kt | 14 ++------------
.../ui/home/bookshelf/BookShelfScreen.kt | 3 +--
.../home/bookshelf/edit/EditBookshelfScreen.kt | 8 +++++---
.../home/bookshelf/home/BookshelfHomeScreen.kt | 9 +++++----
.../ui/home/exploration/Exploration.kt | 5 ++---
.../exploration/expanded/ExpandedPageScreen.kt | 11 ++++++++---
.../exploration/home/ExplorationHomeScreen.kt | 18 +++++++++++++-----
.../search/ExplorationSearchScreen.kt | 5 ++---
.../ui/home/reading/ReadingScreen.kt | 12 +++++++++---
.../ui/home/settings/SettingsScreen.kt | 13 +++++++------
10 files changed, 54 insertions(+), 44 deletions(-)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/HomeScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/HomeScreen.kt
index fecbd88..0627be5 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/HomeScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/HomeScreen.kt
@@ -15,8 +15,6 @@ import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
-import androidx.compose.material3.TopAppBarDefaults
-import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@@ -24,7 +22,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.navigation.NavDestination.Companion.hierarchy
@@ -51,20 +48,13 @@ fun HomeScreen(
checkUpdate: () -> Unit,
requestAddBookToBookshelf: (Int) -> Unit,
) {
- val enterAlwaysScrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
- val pinnedScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val navController = rememberNavController()
- var topBar : @Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit by remember { mutableStateOf( @Composable { _, _ -> }) }
+ var topBar : @Composable () -> Unit by remember { mutableStateOf( @Composable {}) }
var dialog : @Composable () -> Unit by remember { mutableStateOf(@Composable {}) }
var selectedItem by remember { mutableIntStateOf(0) }
Scaffold(
- modifier = Modifier
- .nestedScroll(enterAlwaysScrollBehavior.nestedScrollConnection)
- .nestedScroll(pinnedScrollBehavior.nestedScrollConnection),
topBar = {
- AnimatedContent(topBar, label = "TopBarAnimated") { topBar ->
- topBar(enterAlwaysScrollBehavior, pinnedScrollBehavior)
- }
+ AnimatedContent(topBar, label = "TopBarAnimated") { it.invoke() }
},
bottomBar = {
val entry by navController.currentBackStackEntryAsState()
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/BookShelfScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/BookShelfScreen.kt
index 16e1f24..18071fd 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/BookShelfScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/BookShelfScreen.kt
@@ -1,7 +1,6 @@
package indi.dmzz_yyhyy.lightnovelreader.ui.home.bookshelf
import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.compose.NavHost
@@ -24,7 +23,7 @@ val BookshelfScreenInfo = NavItem (
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BookShelfScreen(
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
dialog: (@Composable () -> Unit) -> Unit,
onClickBook: (Int) -> Unit,
bookshelfHomeViewModel: BookshelfHomeViewModel = hiltViewModel(),
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt
index 6a5ddd1..db6a970 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/edit/EditBookshelfScreen.kt
@@ -22,6 +22,7 @@ import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -42,7 +43,7 @@ import indi.dmzz_yyhyy.lightnovelreader.data.bookshelf.Bookshelf
fun EditBookshelfScreen(
title: String,
bookshelfId: Int,
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
dialog: (@Composable () -> Unit) -> Unit,
bookshelf: Bookshelf,
inti: (Int) -> Unit,
@@ -53,13 +54,14 @@ fun EditBookshelfScreen(
onAutoCacheChange: (Boolean) -> Unit,
onSystemUpdateReminderChange: (Boolean) -> Unit,
) {
+ val pinnedScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
var dialogVisible by remember { mutableStateOf(false) }
- topBar { enterAlwaysScrollBehavior, _ ->
+ topBar {
TopBar(
title = title,
- scrollBehavior = enterAlwaysScrollBehavior,
+ scrollBehavior = pinnedScrollBehavior,
onClickBack = onClickBack,
onClickSave = onClickSave
)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeScreen.kt
index 54ea052..ca9ce4a 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/bookshelf/home/BookshelfHomeScreen.kt
@@ -36,7 +36,6 @@ import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.Tab
-import androidx.compose.material3.TabRow
import androidx.compose.material3.TabRowDefaults.SecondaryIndicator
import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
import androidx.compose.material3.Text
@@ -54,6 +53,7 @@ import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
+import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.SpanStyle
@@ -76,7 +76,7 @@ import indi.dmzz_yyhyy.lightnovelreader.ui.components.EmptyPage
@Composable
fun BookshelfHomeScreen(
init: () -> Unit,
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
changePage: (Int) -> Unit,
changeBookSelectState: (Int) -> Unit,
uiState: BookshelfHomeUiState,
@@ -89,13 +89,14 @@ fun BookshelfHomeScreen(
onClickPin: () -> Unit,
onClickRemove: () -> Unit
) {
+ val enterAlwaysScrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
var updatedBooksExpended by remember { mutableStateOf(true) }
var pinnedBooksExpended by remember { mutableStateOf(true) }
var allBooksExpended by remember { mutableStateOf(true) }
val animatedBackgroundColor by animateColorAsState(
if (!uiState.selectMode) MaterialTheme.colorScheme.surface else MaterialTheme.colorScheme.surfaceContainer
)
- topBar { enterAlwaysScrollBehavior, _ ->
+ topBar {
TopBar(
scrollBehavior = enterAlwaysScrollBehavior,
backgroundColor = animatedBackgroundColor,
@@ -176,7 +177,7 @@ fun BookshelfHomeScreen(
)
}
LazyColumn(
- modifier = Modifier.fillMaxWidth(),
+ modifier = Modifier.fillMaxWidth().nestedScroll(enterAlwaysScrollBehavior.nestedScrollConnection),
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/Exploration.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/Exploration.kt
index af48489..e5b4d01 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/Exploration.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/Exploration.kt
@@ -20,7 +20,6 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
-import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
@@ -58,7 +57,7 @@ val ExplorationScreenInfo = NavItem (
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Exploration(
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
dialog: (@Composable () -> Unit) -> Unit,
requestAddBookToBookshelf: (Int) -> Unit,
onClickBook: (Int) -> Unit,
@@ -76,7 +75,7 @@ fun Exploration(
enter = fadeIn(),
exit = fadeOut()
) {
- topBar { _, _ ->
+ topBar {
TopAppBar(
title = {
Text(
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageScreen.kt
index d60526c..203f3ae 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/expanded/ExpandedPageScreen.kt
@@ -18,10 +18,12 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -37,7 +39,7 @@ import indi.dmzz_yyhyy.lightnovelreader.ui.home.exploration.ExplorationBookCard
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExpandedPageScreen(
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
dialog: (@Composable () -> Unit) -> Unit,
expandedPageDataSourceId: String,
uiState: ExpandedPageUiState,
@@ -47,8 +49,9 @@ fun ExpandedPageScreen(
onClickBack: () -> Unit,
onClickBook: (Int) -> Unit,
) {
+ val enterAlwaysScrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
LifecycleEventEffect(Lifecycle.Event.ON_START) { init.invoke(expandedPageDataSourceId) }
- topBar { enterAlwaysScrollBehavior, _ ->
+ topBar {
TopBar(
scrollBehavior = enterAlwaysScrollBehavior,
title = uiState.pageTitle,
@@ -63,7 +66,9 @@ fun ExpandedPageScreen(
Loading()
}
LazyColumn(
- modifier = Modifier.fillMaxSize(),
+ modifier = Modifier
+ .fillMaxSize()
+ .nestedScroll(enterAlwaysScrollBehavior.nestedScrollConnection),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
item {
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/home/ExplorationHomeScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/home/ExplorationHomeScreen.kt
index 7bc25b9..c1c9da1 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/home/ExplorationHomeScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/home/ExplorationHomeScreen.kt
@@ -27,10 +27,13 @@ import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
+import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -47,7 +50,7 @@ import indi.dmzz_yyhyy.lightnovelreader.ui.components.Loading
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExplorationHomeScreen(
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
onClickExpand: (String) -> Unit,
onClickBook: (Int) -> Unit,
uiState: ExplorationHomeUiState,
@@ -55,7 +58,8 @@ fun ExplorationHomeScreen(
changePage: (Int) -> Unit,
onClickSearch: () -> Unit
) {
- topBar { enterAlwaysScrollBehavior, _ ->
+ val enterAlwaysScrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
+ topBar {
TopBar(
scrollBehavior = enterAlwaysScrollBehavior,
onClickSearch = onClickSearch
@@ -94,7 +98,8 @@ fun ExplorationHomeScreen(
ExplorationPage(
explorationPageBooksRawList = it,
onClickExpand = onClickExpand,
- onClickBook = onClickBook
+ onClickBook = onClickBook,
+ nestedScrollConnection = enterAlwaysScrollBehavior.nestedScrollConnection
)
}
}
@@ -142,9 +147,12 @@ fun TopBar(
fun ExplorationPage(
explorationPageBooksRawList: List,
onClickExpand: (String) -> Unit,
- onClickBook: (Int) -> Unit
+ onClickBook: (Int) -> Unit,
+ nestedScrollConnection: NestedScrollConnection
) {
- LazyColumn {
+ LazyColumn(
+ modifier = Modifier.nestedScroll(nestedScrollConnection)
+ ) {
items(explorationPageBooksRawList) { explorationBooksRow ->
Column(
modifier = Modifier.animateItem()
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/search/ExplorationSearchScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/search/ExplorationSearchScreen.kt
index ccc5c7f..b8589d7 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/search/ExplorationSearchScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/exploration/search/ExplorationSearchScreen.kt
@@ -27,7 +27,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
-import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -59,7 +58,7 @@ import indi.dmzz_yyhyy.lightnovelreader.ui.home.exploration.ExplorationBookCard
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ExplorationSearchScreen(
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
requestAddBookToBookshelf: (Int) -> Unit,
onCLickBack: () -> Unit,
init: () -> Unit,
@@ -77,7 +76,7 @@ fun ExplorationSearchScreen(
LifecycleEventEffect(Lifecycle.Event.ON_START) {
init.invoke()
}
- topBar { _, _ ->
+ topBar {
Box(Modifier.fillMaxWidth().semantics { isTraversalGroup = true }) {
Box(Modifier.align(Alignment.TopEnd).height(56.dp)) {
DropdownMenu(
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/reading/ReadingScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/reading/ReadingScreen.kt
index 9f4e4da..aa36fa8 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/reading/ReadingScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/reading/ReadingScreen.kt
@@ -30,10 +30,12 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@@ -62,20 +64,24 @@ fun ReadingScreen(
onClickBook: (Int) -> Unit,
onClickContinueReading: (Int, Int) -> Unit,
onClickJumpToExploration: () -> Unit,
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
viewModel: ReadingViewModel = hiltViewModel()
) {
+ val pinnedScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
val readingBooks = viewModel.uiState.recentReadingBooks.reversed()
LifecycleEventEffect(Lifecycle.Event.ON_CREATE) {
viewModel.update()
}
LifecycleEventEffect(Lifecycle.Event.ON_START) {
- topBar { _, pinnedScrollBehavior ->
+ topBar {
TopBar(pinnedScrollBehavior)
}
}
LazyColumn(
- modifier = Modifier.fillMaxSize().padding(start = 16.dp, end = 16.dp),
+ modifier = Modifier
+ .fillMaxSize()
+ .padding(start = 16.dp, end = 16.dp)
+ .nestedScroll(pinnedScrollBehavior.nestedScrollConnection),
verticalArrangement = Arrangement.spacedBy(8.dp)) {
item {
Text(
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/SettingsScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/SettingsScreen.kt
index 97f22bd..8373f04 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/SettingsScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/home/settings/SettingsScreen.kt
@@ -25,6 +25,7 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
+import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -34,6 +35,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
@@ -60,20 +62,19 @@ val SettingsScreenInfo = NavItem (
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(
- topBar: (@Composable (TopAppBarScrollBehavior, TopAppBarScrollBehavior) -> Unit) -> Unit,
+ topBar: (@Composable () -> Unit) -> Unit,
checkUpdate: () -> Unit,
viewModel: SettingsViewModel = hiltViewModel()
) {
val state = viewModel.settingsState
+ val pinnedScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
LifecycleEventEffect(Lifecycle.Event.ON_CREATE) {
viewModel.loadSettings()
}
- topBar { enterAlwaysScrollBehavior, _ ->
- TopBar(
- scrollBehavior = enterAlwaysScrollBehavior,
- )
+ topBar {
+ TopBar(pinnedScrollBehavior,)
}
- Column(Modifier.verticalScroll(rememberScrollState())) {
+ Column(Modifier.verticalScroll(rememberScrollState()).nestedScroll(pinnedScrollBehavior.nestedScrollConnection)) {
SettingsCard(
title = stringResource(R.string.app_settings),
icon = ImageVector.vectorResource(R.drawable.outline_settings_24px),
From 51e381397c980f44b64e7cae6f86821b2ae80fef Mon Sep 17 00:00:00 2001
From: NightFish <101402767+dmzz-yyhyy@users.noreply.github.com>
Date: Tue, 17 Sep 2024 14:51:34 +0800
Subject: [PATCH 7/8] =?UTF-8?q?=E4=B8=BA=E7=BF=BB=E9=A1=B5=E6=A8=A1?=
=?UTF-8?q?=E5=BC=8F=E6=B7=BB=E5=8A=A0=E5=BF=AB=E9=80=9F=E5=88=87=E6=8D=A2?=
=?UTF-8?q?=E7=AB=A0=E8=8A=82=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../data/userdata/UserDataPath.kt | 2 +
.../ui/book/content/ContentScreen.kt | 47 +++++++++-
.../ui/book/content/ContentScreenUiState.kt | 4 +
.../ui/book/content/ContentViewModel.kt | 18 ++++
.../ui/book/content/TextComponent.kt | 88 +++++++++----------
5 files changed, 111 insertions(+), 48 deletions(-)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
index 56cb409..a4d0158 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/data/userdata/UserDataPath.kt
@@ -21,8 +21,10 @@ sealed class UserDataPath(
data object IsUsingClickFlipPage : UserDataPath("isUsingClickFlipPage", Reader)
data object IsUsingVolumeKeyFlip : UserDataPath("isUsingVolumeKeyFlip", Reader)
data object IsUsingFlipAnime : UserDataPath("isUsingFlipAnime", Reader)
+ data object FastChapterChange : UserDataPath("fastChapterChange", Reader)
data object EnableBatteryIndicator : UserDataPath("enableBatteryIndicator", Reader)
data object EnableTimeIndicator : UserDataPath("enableTimeIndicator", Reader)
+ data object EnableChapterTitleIndicator : UserDataPath("enableChapterTitleIndicator", Reader)
data object EnableReadingChapterProgressIndicator : UserDataPath("enableReadingChapterProgressIndicator", Reader)
data object AutoPadding : UserDataPath("autoPadding", Reader)
data object TopPadding : UserDataPath("topPadding", Reader)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
index c6c6362..b22ed3a 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreen.kt
@@ -61,6 +61,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
+import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat
@@ -192,6 +193,8 @@ fun ContentScreen(
) { text ->
ContentText(
content = text,
+ onClickLastChapter = viewModel::lastChapter,
+ onClickNextChapter = viewModel::nextChapter,
fontSize = viewModel.uiState.fontSize.sp,
fontLineHeight = viewModel.uiState.fontLineHeight.sp,
readingProgress = viewModel.uiState.readingProgress,
@@ -215,7 +218,8 @@ fun ContentScreen(
start = viewModel.uiState.leftPadding.dp,
end = viewModel.uiState.rightPadding.dp
),
- autoPadding = viewModel.uiState.autoPadding
+ autoPadding = viewModel.uiState.autoPadding,
+ fastChapterChange = viewModel.uiState.fastChapterChange
)
}
AnimatedVisibility (
@@ -241,6 +245,8 @@ fun ContentScreen(
),
enableBatteryIndicator = viewModel.uiState.enableBatteryIndicator,
enableTimeIndicator = viewModel.uiState.enableTimeIndicator,
+ enableChapterTitle = viewModel.uiState.enableChapterTitleIndicator,
+ chapterTitle = viewModel.uiState.chapterContent.title,
enableReadingChapterProgressIndicator = viewModel.uiState.enableReadingChapterProgressIndicator,
readingChapterProgress = viewModel.uiState.readingProgress
)
@@ -293,12 +299,16 @@ fun ContentScreen(
onIsUsingVolumeKeyFlipChange = viewModel::changeIsUsingVolumeKeyFlip,
isUsingFlipAnime = viewModel.uiState.isUsingFlipAnime,
onIsUsingFlipAnimeChange = viewModel::changeIsUsingFlipAnime,
+ fastChapterChange = viewModel.uiState.fastChapterChange,
+ onFastChapterChangeChange = viewModel::changeFastChapterChange,
enableBatteryIndicator = viewModel.uiState.enableBatteryIndicator,
onEnableBatteryIndicatorChange = viewModel::changeEnableBatteryIndicator,
enableTimeIndicator = viewModel.uiState.enableTimeIndicator,
onEnableTimeIndicatorChange = viewModel::changeEnableTimeIndicator,
enableReadingChapterProgressIndicator = viewModel.uiState.enableReadingChapterProgressIndicator,
onEnableReadingChapterProgressIndicatorChange = viewModel::changeEnableReadingChapterProgressIndicator,
+ enableChapterTitleIndicator = viewModel.uiState.enableChapterTitleIndicator,
+ onEnableChapterTitleIndicatorChange = viewModel::changeEnableChapterTitleIndicator,
autoPadding = viewModel.uiState.autoPadding,
onAutoPaddingChange = viewModel::changeAutoPadding,
topPadding = viewModel.uiState.topPadding,
@@ -475,12 +485,16 @@ fun SettingsBottomSheet(
onIsUsingVolumeKeyFlipChange: (Boolean) -> Unit,
isUsingFlipAnime: Boolean,
onIsUsingFlipAnimeChange: (Boolean) -> Unit,
+ fastChapterChange: Boolean,
+ onFastChapterChangeChange: (Boolean) -> Unit,
autoPadding: Boolean,
onAutoPaddingChange: (Boolean) -> Unit,
enableBatteryIndicator: Boolean,
onEnableBatteryIndicatorChange: (Boolean) -> Unit,
enableTimeIndicator: Boolean,
onEnableTimeIndicatorChange: (Boolean) -> Unit,
+ enableChapterTitleIndicator: Boolean,
+ onEnableChapterTitleIndicatorChange: (Boolean) -> Unit,
enableReadingChapterProgressIndicator: Boolean,
onEnableReadingChapterProgressIndicatorChange: (Boolean) -> Unit,
topPadding: Float,
@@ -576,6 +590,17 @@ fun SettingsBottomSheet(
)
}
}
+ if(isUsingFlipPage) {
+ item {
+ SettingsSwitchEntry(
+ modifier = Modifier.animateItem(),
+ title = "快速切换章节",
+ description = "开启后,当你在每章尾页或首页翻页时,会自动切换到上一章或下一章。",
+ checked = fastChapterChange,
+ onCheckedChange = onFastChapterChangeChange,
+ )
+ }
+ }
item {
SettingsSwitchEntry(
title = "自动获取边距",
@@ -600,6 +625,14 @@ fun SettingsBottomSheet(
onCheckedChange = onEnableTimeIndicatorChange,
)
}
+ item {
+ SettingsSwitchEntry(
+ title = "名称指示器",
+ description = "在页面右下角显示当前阅读章节名称。",
+ checked = enableChapterTitleIndicator,
+ onCheckedChange = onEnableChapterTitleIndicatorChange,
+ )
+ }
item {
SettingsSwitchEntry(
title = "进度指示器",
@@ -812,6 +845,8 @@ fun Indicator(
modifier: Modifier = Modifier,
enableBatteryIndicator: Boolean,
enableTimeIndicator: Boolean,
+ enableChapterTitle: Boolean,
+ chapterTitle: String,
enableReadingChapterProgressIndicator: Boolean,
readingChapterProgress: Float
) {
@@ -846,9 +881,19 @@ fun Indicator(
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Box(Modifier.weight(1f))
+ if (enableChapterTitle)
+ AnimatedText(
+ text = chapterTitle,
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.labelLarge.copy(
+ fontWeight = FontWeight.W500
+ ),
+ color = MaterialTheme.colorScheme.onSurfaceVariant
+ )
if (enableReadingChapterProgressIndicator)
AnimatedText(
text = "${(readingChapterProgress * 100).toInt()}%",
+ textAlign = TextAlign.Center,
style = MaterialTheme.typography.labelLarge.copy(
fontWeight = FontWeight.W500
),
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
index 2386121..e53cdfa 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentScreenUiState.kt
@@ -24,9 +24,11 @@ interface ContentScreenUiState {
val isUsingClickFlipPage: Boolean
val isUsingVolumeKeyFlip: Boolean
val isUsingFlipAnime: Boolean
+ val fastChapterChange: Boolean
val enableBatteryIndicator: Boolean
val enableTimeIndicator: Boolean
val enableReadingChapterProgressIndicator: Boolean
+ val enableChapterTitleIndicator: Boolean
val autoPadding: Boolean
val topPadding: Float
val bottomPadding: Float
@@ -46,9 +48,11 @@ class MutableContentScreenUiState: ContentScreenUiState {
override var isUsingClickFlipPage by mutableStateOf(false)
override var isUsingVolumeKeyFlip by mutableStateOf(false)
override var isUsingFlipAnime by mutableStateOf(false)
+ override var fastChapterChange by mutableStateOf(false)
override var enableBatteryIndicator by mutableStateOf(true)
override var enableTimeIndicator by mutableStateOf(true)
override var enableReadingChapterProgressIndicator by mutableStateOf(true)
+ override var enableChapterTitleIndicator by mutableStateOf(true)
override var autoPadding by mutableStateOf(false)
override var topPadding by mutableStateOf(12f)
override var bottomPadding by mutableStateOf(12f)
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
index c55da48..0b2f69f 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/ContentViewModel.kt
@@ -26,8 +26,10 @@ class ContentViewModel @Inject constructor(
private val isUsingClickFlipPageUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingClickFlipPage.path)
private val isUsingVolumeKeyFlipUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingVolumeKeyFlip.path)
private val isUsingFlipAnimeUserData = userDataRepository.booleanUserData(UserDataPath.Reader.IsUsingFlipAnime.path)
+ private val fastChapterChangeUserData = userDataRepository.booleanUserData(UserDataPath.Reader.FastChapterChange.path)
private val enableBatteryIndicatorUserData = userDataRepository.booleanUserData(UserDataPath.Reader.EnableBatteryIndicator.path)
private val enableTimeIndicatorUserData = userDataRepository.booleanUserData(UserDataPath.Reader.EnableTimeIndicator.path)
+ private val enableChapterTitleIndicatorUserData = userDataRepository.booleanUserData(UserDataPath.Reader.EnableChapterTitleIndicator.path)
private val enableReadingChapterProgressIndicatorUserData = userDataRepository.booleanUserData(UserDataPath.Reader.EnableReadingChapterProgressIndicator.path)
private val autoPaddingUserData = userDataRepository.booleanUserData(UserDataPath.Reader.AutoPadding.path)
private val topPaddingUserData = userDataRepository.floatUserData(UserDataPath.Reader.TopPadding.path)
@@ -67,8 +69,10 @@ class ContentViewModel @Inject constructor(
_uiState.isUsingClickFlipPage = isUsingClickFlipPageUserData.getOrDefault(_uiState.isUsingClickFlipPage)
_uiState.isUsingVolumeKeyFlip = isUsingVolumeKeyFlipUserData.getOrDefault(_uiState.isUsingVolumeKeyFlip)
_uiState.isUsingFlipAnime = isUsingFlipAnimeUserData.getOrDefault(_uiState.isUsingFlipAnime)
+ _uiState.fastChapterChange = fastChapterChangeUserData.getOrDefault(_uiState.fastChapterChange)
_uiState.enableBatteryIndicator = enableBatteryIndicatorUserData.getOrDefault(_uiState.enableBatteryIndicator)
_uiState.enableTimeIndicator = enableTimeIndicatorUserData.getOrDefault(_uiState.enableTimeIndicator)
+ _uiState.enableChapterTitleIndicator = enableChapterTitleIndicatorUserData.getOrDefault(_uiState.enableChapterTitleIndicator)
_uiState.enableReadingChapterProgressIndicator = enableReadingChapterProgressIndicatorUserData.getOrDefault(_uiState.enableReadingChapterProgressIndicator)
_uiState.autoPadding = autoPaddingUserData.getOrDefault(_uiState.autoPadding)
_uiState.topPadding = topPaddingUserData.getOrDefault(_uiState.topPadding)
@@ -224,6 +228,13 @@ class ContentViewModel @Inject constructor(
}
}
+ fun changeFastChapterChange(fastChapterChange: Boolean) {
+ _uiState.fastChapterChange = fastChapterChange
+ viewModelScope.launch(Dispatchers.IO) {
+ fastChapterChangeUserData.set(fastChapterChange)
+ }
+ }
+
fun changeEnableBatteryIndicator(enableBatteryIndicator: Boolean) {
_uiState.enableBatteryIndicator = enableBatteryIndicator
viewModelScope.launch(Dispatchers.IO) {
@@ -238,6 +249,13 @@ class ContentViewModel @Inject constructor(
}
}
+ fun changeEnableChapterTitleIndicator(enableChapterTitleIndicator: Boolean) {
+ _uiState.enableChapterTitleIndicator = enableChapterTitleIndicator
+ viewModelScope.launch(Dispatchers.IO) {
+ enableChapterTitleIndicatorUserData.set(enableChapterTitleIndicator)
+ }
+ }
+
fun changeEnableReadingChapterProgressIndicator(enableReadingChapterProgressIndicator: Boolean) {
_uiState.enableReadingChapterProgressIndicator = enableReadingChapterProgressIndicator
viewModelScope.launch(Dispatchers.IO) {
diff --git a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
index 12361e6..60e08d1 100644
--- a/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
+++ b/app/src/main/kotlin/indi/dmzz_yyhyy/lightnovelreader/ui/book/content/TextComponent.kt
@@ -67,6 +67,8 @@ import kotlinx.coroutines.launch
@Composable
fun ContentText(
content: String,
+ onClickLastChapter: () -> Unit,
+ onClickNextChapter: () -> Unit,
fontSize: TextUnit,
fontLineHeight: TextUnit,
readingProgress: Float,
@@ -74,6 +76,7 @@ fun ContentText(
isUsingClickFlip: Boolean,
isUsingVolumeKeyFlip: Boolean,
isUsingFlipAnime: Boolean,
+ fastChapterChange: Boolean,
onChapterReadingProgressChange: (Float) -> Unit,
changeIsImmersive: () -> Unit,
paddingValues: PaddingValues,
@@ -112,18 +115,20 @@ fun ContentText(
SimpleFlipPageTextComponent(
modifier = Modifier.fillMaxSize(),
content = content,
+ onClickLastChapter = onClickLastChapter,
+ onClickNextChapter = onClickNextChapter,
fontSize = fontSize,
fontLineHeight = fontLineHeight,
readingProgress = readingProgress,
isUsingClickFlip = isUsingClickFlip,
isUsingVolumeKeyFlip = isUsingVolumeKeyFlip,
isUsingFlipAnime = isUsingFlipAnime,
+ fastChapterChange = fastChapterChange,
onChapterReadingProgressChange = onChapterReadingProgressChange,
changeIsImmersive = changeIsImmersive,
paddingValues =
if (autoPadding) autoAvoidPaddingValues else paddingValues
)
- println("autoPadding: $autoPadding values: $autoAvoidPaddingValues simple: $paddingValues")
}
@Composable
@@ -179,12 +184,15 @@ fun ScrollContentTextComponent(
fun SimpleFlipPageTextComponent(
modifier: Modifier,
content: String,
+ onClickLastChapter: () -> Unit,
+ onClickNextChapter: () -> Unit,
fontSize: TextUnit,
fontLineHeight: TextUnit,
readingProgress: Float,
isUsingClickFlip: Boolean,
isUsingVolumeKeyFlip: Boolean,
isUsingFlipAnime: Boolean,
+ fastChapterChange: Boolean,
onChapterReadingProgressChange: (Float) -> Unit,
changeIsImmersive: () -> Unit,
paddingValues: PaddingValues
@@ -192,7 +200,6 @@ fun SimpleFlipPageTextComponent(
val textMeasurer = rememberTextMeasurer()
val scope = rememberCoroutineScope()
val current = LocalContext.current
- val localDensity = LocalDensity.current
var contentKey by remember { mutableStateOf(0) }
var slipTextJob by remember { mutableStateOf(null) }
var resumedReadingProgressJob by remember { mutableStateOf(null) }
@@ -202,16 +209,30 @@ fun SimpleFlipPageTextComponent(
var pageState by remember { mutableStateOf(PagerState { 0 }) }
var readingPageFistCharOffset by remember { mutableStateOf(0) }
var resumedReadingProgress by remember { mutableStateOf(false) }
+ fun lastPage() {
+ if (pageState.currentPage != 0)
+ scope.launch {
+ if (isUsingFlipAnime)
+ pageState.animateScrollToPage(pageState.currentPage - 1)
+ else
+ pageState.scrollToPage(pageState.currentPage - 1)
+ }
+ else if (fastChapterChange) onClickLastChapter.invoke()
+ }
+
+ fun nextPage() {
+ if (pageState.currentPage + 1 < pageState.pageCount)
+ scope.launch {
+ if (isUsingFlipAnime)
+ pageState.animateScrollToPage(pageState.currentPage + 1)
+ else
+ pageState.scrollToPage(pageState.currentPage + 1)
+ }
+ else if (fastChapterChange) onClickNextChapter.invoke()
+ }
+
LaunchedEffect(content, textStyle, fontLineHeight, fontSize, constraints?.maxHeight, constraints?.maxWidth) {
val key = content.hashCode() + fontLineHeight.value.hashCode() + fontSize.value.hashCode() + constraints?.maxHeight.hashCode() + constraints?.maxWidth.hashCode()
- println(key)
- println(contentKey)
- println(with(localDensity) {
- (paddingValues.calculateTopPadding() + paddingValues.calculateBottomPadding() + 10.dp)
- .toPx()
- }.toInt())
- println("${paddingValues.calculateTopPadding()} ${paddingValues.calculateBottomPadding()}")
- println("${content.hashCode()} ${fontLineHeight.value}.sp ${fontSize.value}.sp ${constraints?.maxHeight}.xp ${constraints?.maxWidth}.xp")
if (constraints == null || textStyle == null || key == contentKey) return@LaunchedEffect
contentKey = key
slipTextJob?.cancel()
@@ -235,7 +256,6 @@ fun SimpleFlipPageTextComponent(
resumedReadingProgressJob = scope.launch {
pageState.scrollToPage((readingProgress * pageState.pageCount).toInt())
resumedReadingProgress = true
- println("resumed the page to ${(readingProgress * pageState.pageCount).toInt()}")
}
}
}
@@ -244,28 +264,18 @@ fun SimpleFlipPageTextComponent(
onChapterReadingProgressChange(pageState.currentPage.toFloat() / (pageState.pageCount - 1))
else onChapterReadingProgressChange(1F)
}
- DisposableEffect(isUsingVolumeKeyFlip, isUsingFlipAnime) {
+ DisposableEffect(isUsingVolumeKeyFlip, isUsingFlipAnime, fastChapterChange) {
val localBroadcastManager = LocalBroadcastManager.getInstance(current)
val keycodeVolumeUpReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
- if (isUsingVolumeKeyFlip && pageState.pageCount != 0)
- scope.launch {
- if (isUsingFlipAnime)
- pageState.animateScrollToPage(pageState.currentPage - 1)
- else
- pageState.scrollToPage(pageState.currentPage - 1)
- }
+ if (isUsingVolumeKeyFlip)
+ lastPage()
}
}
val keycodeVolumeDownReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
- if (isUsingVolumeKeyFlip && pageState.pageCount - 1 != pageState.currentPage)
- scope.launch {
- if (isUsingFlipAnime)
- pageState.animateScrollToPage(pageState.currentPage + 1)
- else
- pageState.scrollToPage(pageState.currentPage + 1)
- }
+ if (isUsingVolumeKeyFlip)
+ nextPage()
}
}
localBroadcastManager.registerReceiver(keycodeVolumeUpReceiver, IntentFilter(AppEvent.KEYCODE_VOLUME_UP))
@@ -309,29 +319,13 @@ fun SimpleFlipPageTextComponent(
if (it.absoluteValue > 60) changeIsImmersive.invoke()
}
)
- .pointerInput(isUsingClickFlip, isUsingFlipAnime) {
+ .pointerInput(isUsingClickFlip, isUsingFlipAnime, fastChapterChange) {
detectTapGestures(
onTap = {
- if (isUsingClickFlip) {
- if (it.x <= current.resources.displayMetrics.widthPixels / 2 && pageState.currentPage != 0) {
- scope.launch {
- if (isUsingFlipAnime)
- pageState.animateScrollToPage(pageState.currentPage - 1)
- else
- pageState.scrollToPage(pageState.currentPage - 1)
- }
- } else
- if (pageState.currentPage + 1 < pageState.pageCount)
- scope.launch {
- if (isUsingFlipAnime)
- pageState.animateScrollToPage(pageState.currentPage + 1)
- else
- pageState.scrollToPage(pageState.currentPage + 1)
- }
- }
- else {
- changeIsImmersive.invoke()
- }
+ if (isUsingClickFlip)
+ if (it.x <= current.resources.displayMetrics.widthPixels / 2) lastPage()
+ else nextPage()
+ else changeIsImmersive.invoke()
}
)
},
From 159b7522d836c8c4b385f24ce97f5e10b9053613 Mon Sep 17 00:00:00 2001
From: NightFish <101402767+dmzz-yyhyy@users.noreply.github.com>
Date: Tue, 17 Sep 2024 15:02:56 +0800
Subject: [PATCH 8/8] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=89=88=E6=9C=AC?=
=?UTF-8?q?=E5=8F=B7=20=E5=8D=87=E7=BA=A7ci=E5=86=85upload-artifact?=
=?UTF-8?q?=E8=87=B3v3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.github/workflows/marge.yml | 2 +-
.github/workflows/pr.yml | 2 +-
app/build.gradle.kts | 22 +++++++++++-----------
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/marge.yml b/.github/workflows/marge.yml
index 91ee48d..0a3dfad 100644
--- a/.github/workflows/marge.yml
+++ b/.github/workflows/marge.yml
@@ -41,7 +41,7 @@ jobs:
keyPassword: ${{ secrets.KEY_PASSWORD }}
env:
BUILD_TOOLS_VERSION: "34.0.0"
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
name: LightNovelReader-${{steps.android_version.outputs.VERSION_NAME}}-${{steps.android_version.outputs.VERSION_CODE}}-release
path: ${{steps.sign_app.outputs.signedReleaseFile}}
\ No newline at end of file
diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 4d3f9b2..5fff919 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -40,7 +40,7 @@ jobs:
keyPassword: ${{ secrets.KEY_PASSWORD }}
env:
BUILD_TOOLS_VERSION: "34.0.0"
- - uses: actions/upload-artifact@v2
+ - uses: actions/upload-artifact@v3
with:
name: LightNovelReader-${{steps.android_version.outputs.VERSION_CODE}}-debug
path: ${{steps.sign_app.outputs.signedReleaseFile}}
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index c98e39c..168a05c 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -20,7 +20,7 @@ android {
minSdk = 24
targetSdk = 34
// 版本号为x.y.z则versionCode为x*1000000+y*10000+z*100+debug版本号(开发需要时迭代, 两位数)
- versionCode = 4_04_023
+ versionCode = 4_04_024
versionName = "0.4.4"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
@@ -77,24 +77,24 @@ android {
dependencies {
// desugaring support
- coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.1")
+ coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.2")
// android lib
implementation("androidx.core:core-ktx:1.13.1")
implementation ("androidx.core:core-splashscreen:1.0.1")
- implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.4")
- implementation("androidx.lifecycle:lifecycle-runtime-compose-android:2.8.4")
- implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.4")
+ implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.5")
+ implementation("androidx.lifecycle:lifecycle-runtime-compose-android:2.8.5")
+ implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5")
// compose
- implementation("androidx.activity:activity-compose:1.9.1")
- implementation("androidx.compose.animation:animation-graphics-android:1.6.8")
- implementation(platform("androidx.compose:compose-bom:2024.08.00"))
+ implementation("androidx.activity:activity-compose:1.9.2")
+ implementation("androidx.compose.animation:animation-graphics-android:1.7.1")
+ implementation(platform("androidx.compose:compose-bom:2024.09.01"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
- implementation("androidx.compose.material3:material3:1.3.0-rc01")
+ implementation("androidx.compose.material3:material3:1.3.0")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
- androidTestImplementation(platform("androidx.compose:compose-bom:2024.08.00"))
+ androidTestImplementation(platform("androidx.compose:compose-bom:2024.09.01"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
// junit
testImplementation("junit:junit:4.13.2")
@@ -111,7 +111,7 @@ dependencies {
implementation("androidx.hilt:hilt-work:$androidXHilt")
implementation("androidx.hilt:hilt-navigation-compose:$androidXHilt")
// navigation
- val navVersion = "2.7.7"
+ val navVersion = "2.8.0"
implementation("androidx.navigation:navigation-fragment-ktx:$navVersion")
implementation("androidx.navigation:navigation-ui-ktx:$navVersion")
implementation("androidx.navigation:navigation-dynamic-features-fragment:$navVersion")