Skip to content

Commit

Permalink
Merge pull request #86 from dmzz-yyhyy/word_count_filter
Browse files Browse the repository at this point in the history
添加字数筛选器
  • Loading branch information
dmzz-yyhyy authored Aug 30, 2024
2 parents ecd5ac8 + 7dc68e8 commit e3fabfb
Show file tree
Hide file tree
Showing 14 changed files with 261 additions and 24 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ android {
minSdk = 24
targetSdk = 34
// 版本号为x.y.z则versionCode为x*1000000+y*10000+z*100+debug版本号(开发需要时迭代, 两位数)
versionCode = 4_04_006
versionCode = 4_04_009
versionName = "0.4.4"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
Expand Down Expand Up @@ -77,7 +77,7 @@ android {

dependencies {
// desugaring support
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.1")
// android lib
implementation("androidx.core:core-ktx:1.13.1")
implementation ("androidx.core:core-splashscreen:1.0.1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class BookRepository @Inject constructor(
) {
private val coroutineScope: CoroutineScope = CoroutineScope(Dispatchers.Default)

suspend fun getBookInformation(id: Int): Flow<BookInformation> {
suspend fun getBookInformation(id: Int): Flow<BookInformation> {
val bookInformation: MutableStateFlow<BookInformation> =
MutableStateFlow(localBookDataSource.getBookInformation(id) ?: BookInformation.empty())
coroutineScope.launch {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.filter

enum class FilterTypes(name: String) {
SWITCH("switch"),
SINGLE_CHOICE("single_choice"),
enum class FilterTypes {
SWITCH,
SINGLE_CHOICE,
SLIDER
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ class IsCompletedSwitchFilter(
onChange: () -> Unit
): SwitchFilter("已完结", onChange), LocalFilter{
override fun filter(bookInformation: BookInformation): Boolean =
!this.enable || bookInformation.isComplete
!this.enabled || bookInformation.isComplete
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.filter

import androidx.annotation.IntRange

abstract class SliderFilter(
private val title: String,
val description: String,
defaultValue: Float,
val valueRange: ClosedFloatingPointRange<Float>,
@IntRange(from = 0) val steps: Int = 0,
private val onChange: () -> Unit
) : Filter() {
abstract var enabled: Boolean
abstract val displayValue: String
open val displayTitle = title

var value: Float = defaultValue
set(value) {
onChange()
field = value
}
override fun getType(): FilterTypes = FilterTypes.SLIDER
override fun getTitle(): String = title
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ abstract class SwitchFilter(
private var title: String,
private var onChange: () -> Unit
): Filter() {
var enable = false
var enabled = false
set(value) {
field = value
onChange.invoke()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.filter

import indi.dmzz_yyhyy.lightnovelreader.data.book.BookInformation

class WordCountFilter(onChange: () -> Unit) : SliderFilter(
title = "字数限制",
description = "仅显示字数大于该值的书本,若为0则显示全部书本。",
defaultValue = 0f,
valueRange = 0f..200_0000f,
steps = 9,
onChange = onChange
), LocalFilter {
override var enabled: Boolean
get() = value != 0f
set(value) { if (!value) this.value = 0f }
override val displayValue: String
get() = if (value == 0f) "无限制" else "${(value / 1000).toInt()}K"

override val displayTitle: String
get() = "字数"
override fun filter(bookInformation: BookInformation): Boolean =
!enabled || bookInformation.wordCount >= value
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.ExplorationExpanded
import indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.ExplorationPageDataSource
import indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.filter.IsCompletedSwitchFilter
import indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.filter.SingleChoiceFilter
import indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.filter.WordCountFilter
import indi.dmzz_yyhyy.lightnovelreader.data.web.wenku8.exploration.Wenku8AllExplorationPage
import indi.dmzz_yyhyy.lightnovelreader.data.web.wenku8.exploration.Wenku8HomeExplorationPage
import indi.dmzz_yyhyy.lightnovelreader.data.web.wenku8.exploration.Wenku8TagsExplorationPage
Expand Down Expand Up @@ -285,7 +286,8 @@ object Wenku8Api: WebBookDataSource {
if (this.arg != "") this.arg += "&initial="
this.refresh()
},
PublishingHouseSingleChoiceFilter { this.refresh() }
PublishingHouseSingleChoiceFilter { this.refresh() },
WordCountFilter { this.refresh() }
)
}
)
Expand All @@ -306,7 +308,8 @@ object Wenku8Api: WebBookDataSource {
if (this.arg != "") this.arg += "&initial="
this.refresh()
},
PublishingHouseSingleChoiceFilter { this.refresh() }
PublishingHouseSingleChoiceFilter { this.refresh() },
WordCountFilter { this.refresh() }
)
},
extendedParameters = "&fullflag=1"
Expand Down Expand Up @@ -336,7 +339,8 @@ object Wenku8Api: WebBookDataSource {
if (this.arg != "") this.arg += "&initial="
this.refresh()
},
PublishingHouseSingleChoiceFilter { this.refresh() }
PublishingHouseSingleChoiceFilter { this.refresh() },
WordCountFilter { this.refresh() }
)
},
extendedParameters = "&sort=$id",
Expand Down Expand Up @@ -378,7 +382,8 @@ object Wenku8Api: WebBookDataSource {
this.arg = choicesMap[it.trim()] ?: ""
this.refresh()
},
PublishingHouseSingleChoiceFilter { this.refresh() }
PublishingHouseSingleChoiceFilter { this.refresh() },
WordCountFilter { this.refresh() }
)
},
extendedParameters = "&t=${URLEncoder.encode(tag, "gb2312")}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import indi.dmzz_yyhyy.lightnovelreader.data.web.exploration.filter.SingleChoice
class PublishingHouseSingleChoiceFilter(onChange: (String) -> Unit) : SingleChoiceFilter(
title = "文库",
dialogTitle = "文库筛选",
description = "根据小说文库的筛选。",
description = "根据小说的文库筛选",
choices = listOf("全部轻小说", "电击文库", "富士见文库", "角川文库", "MF文库J", "Fami通文库", "GA文库", "HJ文库", "一迅社", "集英社", "小学馆", "讲谈社", "少女文库", "其他文库", "游戏剧本"),
defaultChoice = "全部轻小说",
onChange = onChange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,45 @@ package indi.dmzz_yyhyy.lightnovelreader.ui

import android.content.Context
import android.widget.Toast
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.FilterChip
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LifecycleEventEffect
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import indi.dmzz_yyhyy.lightnovelreader.R
import indi.dmzz_yyhyy.lightnovelreader.ui.book.BookScreen
import indi.dmzz_yyhyy.lightnovelreader.ui.components.AddBookToBookshelfDialog
import indi.dmzz_yyhyy.lightnovelreader.ui.components.BaseDialog
import indi.dmzz_yyhyy.lightnovelreader.ui.components.SettingsSliderEntry
import indi.dmzz_yyhyy.lightnovelreader.ui.components.SliderDialog
import indi.dmzz_yyhyy.lightnovelreader.ui.components.UpdatesAvailableDialog
import indi.dmzz_yyhyy.lightnovelreader.ui.home.HomeScreen
import kotlin.math.roundToInt

@Composable
fun LightNovelReaderApp(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package indi.dmzz_yyhyy.lightnovelreader.ui.components

import android.annotation.SuppressLint
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Checkbox
Expand All @@ -21,17 +27,28 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Slider
import androidx.compose.material3.SliderDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
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.compose.ui.unit.times
import androidx.core.content.ContextCompat.startActivity
import dev.jeziellago.compose.markdowntext.MarkdownText
import indi.dmzz_yyhyy.lightnovelreader.BuildConfig
Expand Down Expand Up @@ -227,4 +244,69 @@ fun AddBookToBookshelfDialog(
}
}
}
}

@SuppressLint("UseOfNonLambdaOffsetOverload")
@Composable
fun SliderDialog(
onDismissRequest: () -> Unit,
onConfirmation: () -> Unit,
value: Float,
valueRange: ClosedFloatingPointRange<Float>,
steps: Int,
onSlideChange: (Float) -> Unit,
onSliderChangeFinished: () -> Unit,
title: String,
description: String
) {
BaseDialog(
icon = painterResource(R.drawable.filled_settings_24px),
title = title,
description = description,
onDismissRequest = onDismissRequest,
onConfirmation = onConfirmation,
dismissText = stringResource(R.string.cancel),
confirmationText = stringResource(R.string.apply),
) {
val sliderPercentage = (value - valueRange.start) / (valueRange.endInclusive - valueRange.start)
var boxWidth by remember { mutableStateOf(0.dp) }

Box(modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned { layoutCoordinates ->
boxWidth = layoutCoordinates.size.width.dp
}
) {
Box(modifier = Modifier
.offset(x = (sliderPercentage * (boxWidth - 170.dp) / 2.8F))
.padding(vertical = 8.dp)
) {
Box(
modifier = Modifier
.clip(RoundedCornerShape(64.dp))
.background(MaterialTheme.colorScheme.surfaceContainerHighest)
.wrapContentWidth()
.padding(12.dp)
) {
Text(
modifier = Modifier.padding(horizontal = 12.dp),
text = value.toInt().toString(),
textAlign = TextAlign.Center,
fontSize = 16.sp
)
}
}
}
Slider(
modifier = Modifier.fillMaxWidth(),
value = value,
valueRange = valueRange,
steps = steps,
onValueChange = onSlideChange,
onValueChangeFinished = onSliderChangeFinished,
colors = SliderDefaults.colors(
inactiveTrackColor = MaterialTheme.colorScheme.primaryContainer,
),
)
}
}
Loading

0 comments on commit e3fabfb

Please sign in to comment.