[feat] UI optimization 3

This commit is contained in:
acite
2025-10-01 19:47:00 +08:00
parent 7c99ea394b
commit 603c2c38aa
17 changed files with 439 additions and 215 deletions

View File

@@ -54,6 +54,8 @@ dependencies {
implementation(libs.hilt.android) implementation(libs.hilt.android)
implementation(libs.hilt.navigation.compose) implementation(libs.hilt.navigation.compose)
implementation(libs.androidx.compose.material.core) implementation(libs.androidx.compose.material.core)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.compose.animation)
ksp(libs.hilt.android.compiler) ksp(libs.hilt.android.compiler)
implementation(libs.androidx.room.runtime) implementation(libs.androidx.room.runtime)

View File

@@ -10,6 +10,7 @@ object Global {
var sameClassVideos: List<Video>? = null var sameClassVideos: List<Video>? = null
private set private set
var isFullScreen by mutableStateOf(false)
fun updateRelate(v: List<Video>, s: Video) fun updateRelate(v: List<Video>, s: Video)
{ {
sameClassVideos = if (v.contains(s)) { sameClassVideos = if (v.contains(s)) {

View File

@@ -4,11 +4,15 @@ import android.app.Activity
import android.content.Intent import android.content.Intent
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import android.os.Bundle import android.os.Bundle
import android.view.View
import android.view.WindowManager import android.view.WindowManager
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.tween
import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -95,12 +99,8 @@ class MainScreenActivity : ComponentActivity() {
} }
@Composable fun setFullScreen(view: View, isFullScreen: Boolean) {
fun ToggleFullScreen(isFullScreen: Boolean) Global.isFullScreen = isFullScreen
{
val view = LocalView.current
LaunchedEffect(isFullScreen) {
val window = (view.context as Activity).window val window = (view.context as Activity).window
val insetsController = WindowCompat.getInsetsController(window, view) val insetsController = WindowCompat.getInsetsController(window, view)
@@ -112,7 +112,6 @@ fun ToggleFullScreen(isFullScreen: Boolean)
insetsController.show(WindowInsetsCompat.Type.systemBars()) insetsController.show(WindowInsetsCompat.Type.systemBars())
} }
} }
}
@Composable @Composable
fun AppNavigation() { fun AppNavigation() {
@@ -136,40 +135,64 @@ fun AppNavigation() {
) { ) {
BottomNavigationBar(navController = navController) BottomNavigationBar(navController = navController)
} }
if(shouldShowBottomBar)
ToggleFullScreen(false)
} }
) { innerPadding -> ) { innerPadding ->
NavHost( NavHost(
navController = navController, navController = navController,
startDestination = Screen.Me.route, startDestination = Screen.Me.route,
modifier = if(shouldShowBottomBar)Modifier.padding(innerPadding) else Modifier.padding(0.dp) modifier = if(!Global.isFullScreen) Modifier.padding(innerPadding) else Modifier.padding(0.dp)
) {
composable(
Screen.Home.route,
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }
) { ) {
composable(Screen.Home.route) {
CardPage(title = "Home") { CardPage(title = "Home") {
HomeScreen(navController = navController) HomeScreen(navController = navController)
} }
} }
composable(Screen.Video.route) { composable(Screen.Video.route,
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }) {
VideoScreen(navController = navController) VideoScreen(navController = navController)
} }
composable(Screen.Comic.route) { composable(Screen.Comic.route,
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }) {
CardPage(title = "Comic") { CardPage(title = "Comic") {
ComicScreen(navController = navController) ComicScreen(navController = navController)
} }
} }
composable(Screen.Transmission.route) { composable(Screen.Transmission.route,
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }) {
CardPage(title = "Tasks") { CardPage(title = "Tasks") {
TransmissionScreen(navigator = navController) TransmissionScreen(navigator = navController)
} }
} }
composable(Screen.Me.route) { composable(Screen.Me.route,
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }) {
MeScreen(); MeScreen();
} }
composable( composable(
route = Screen.VideoPlayer.route, route = Screen.VideoPlayer.route,
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
arguments = listOf(navArgument("videoId") { type = NavType.StringType }) arguments = listOf(navArgument("videoId") { type = NavType.StringType })
) { ) {
backStackEntry -> backStackEntry ->
@@ -181,6 +204,10 @@ fun AppNavigation() {
composable( composable(
route = Screen.ComicGrid.route, route = Screen.ComicGrid.route,
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
arguments = listOf(navArgument("comicId") { type = NavType.StringType }) arguments = listOf(navArgument("comicId") { type = NavType.StringType })
) { ) {
backStackEntry -> backStackEntry ->
@@ -192,6 +219,10 @@ fun AppNavigation() {
composable( composable(
route = Screen.ComicPage.route, route = Screen.ComicPage.route,
enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) },
popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) },
arguments = listOf(navArgument("comicId") { type = NavType.StringType }, navArgument("page") { type = NavType.StringType }) arguments = listOf(navArgument("comicId") { type = NavType.StringType }, navArgument("page") { type = NavType.StringType })
) { ) {
backStackEntry -> backStackEntry ->
@@ -199,7 +230,6 @@ fun AppNavigation() {
val page = backStackEntry.arguments?.getString("page") val page = backStackEntry.arguments?.getString("page")
if (comicId != null && page != null) { if (comicId != null && page != null) {
ComicPageView(comicId = comicId, page = page, navController = navController) ComicPageView(comicId = comicId, page = page, navController = navController)
ToggleFullScreen(true)
} }
} }
} }

View File

@@ -1,5 +1,8 @@
package com.acitelight.aether.model package com.acitelight.aether.model
import kotlinx.serialization.Serializable
@Serializable
data class BookMark( data class BookMark(
val name: String, val name: String,
val page: String val page: String

View File

@@ -7,6 +7,19 @@ class Comic(
val id: String val id: String
) )
{ {
fun getCover(api: ApiClient): String
{
if(id == "101")
print("")
if(comic.cover != "")
{
return "${api.getBase()}api/image/$id/${comic.cover}"
}
return "${api.getBase()}api/image/$id/${comic.list[0]}"
}
fun getPage(pageNumber: Int, api: ApiClient): String fun getPage(pageNumber: Int, api: ApiClient): String
{ {
return "${api.getBase()}api/image/$id/${comic.list[pageNumber]}" return "${api.getBase()}api/image/$id/${comic.list[pageNumber]}"

View File

@@ -1,10 +1,14 @@
package com.acitelight.aether.model package com.acitelight.aether.model
import kotlinx.serialization.Serializable
@Serializable
data class ComicResponse( data class ComicResponse(
val comic_name: String, val comic_name: String,
val page_count: Int, val page_count: Int,
val bookmarks: List<BookMark>, val bookmarks: List<BookMark>,
val list: List<String>, val list: List<String>,
val tags: List<String>, val tags: List<String>,
val author: String val author: String,
val cover: String
) )

View File

@@ -219,6 +219,8 @@ class ApiClient @Inject constructor(
suspend fun apply(context: Context, urls: String, crt: String): String? { suspend fun apply(context: Context, urls: String, crt: String): String? {
try { try {
client = createOkHttp()
val urlList = urls.split(";").map { it.trim() } val urlList = urls.split(";").map { it.trim() }
var selectedUrl: String? = null var selectedUrl: String? = null
@@ -231,7 +233,6 @@ class ApiClient @Inject constructor(
} }
if (selectedUrl == null) { if (selectedUrl == null) {
client = createOkHttp()
throw Exception("No reachable URL found") throw Exception("No reachable URL found")
} }

View File

@@ -59,9 +59,9 @@ fun ComicCard(
Box(modifier = Modifier.fillMaxSize()) { Box(modifier = Modifier.fillMaxSize()) {
AsyncImage( AsyncImage(
model = ImageRequest.Builder(LocalContext.current) model = ImageRequest.Builder(LocalContext.current)
.data(comic.getPage(0, comicScreenViewModel.apiClient)) .data(comic.getCover(comicScreenViewModel.apiClient))
.memoryCacheKey("${comic.id}/${0}") .memoryCacheKey("${comic.id}/cover")
.diskCacheKey("${comic.id}/${0}") .diskCacheKey("${comic.id}/cover")
.build(), .build(),
contentDescription = null, contentDescription = null,
imageLoader = comicScreenViewModel.imageLoader!!, imageLoader = comicScreenViewModel.imageLoader!!,
@@ -115,14 +115,6 @@ fun ComicCard(
maxLines = 1, maxLines = 1,
modifier = Modifier.align(Alignment.CenterStart) modifier = Modifier.align(Alignment.CenterStart)
) )
Text(
text = comic.comic.author,
fontSize = 12.sp,
lineHeight = 14.sp,
maxLines = 1,
modifier = Modifier.align(Alignment.CenterEnd)
)
} }
} }
} }

View File

@@ -51,6 +51,7 @@ import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -61,6 +62,7 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
@@ -69,7 +71,7 @@ import androidx.lifecycle.viewModelScope
import androidx.media3.common.util.UnstableApi import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.ExoPlayer import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView import androidx.media3.ui.PlayerView
import com.acitelight.aether.ToggleFullScreen import com.acitelight.aether.setFullScreen
import com.acitelight.aether.view.pages.formatTime import com.acitelight.aether.view.pages.formatTime
import com.acitelight.aether.view.pages.moveBrit import com.acitelight.aether.view.pages.moveBrit
import com.acitelight.aether.viewModel.VideoPlayerViewModel import com.acitelight.aether.viewModel.VideoPlayerViewModel
@@ -108,7 +110,14 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
videoPlayerViewModel.isLandscape = false videoPlayerViewModel.isLandscape = false
} }
ToggleFullScreen(true) val view = LocalView.current
DisposableEffect(Unit) {
setFullScreen(view, true)
onDispose {
setFullScreen(view, false)
}
}
Box(Modifier.fillMaxSize()) Box(Modifier.fillMaxSize())
{ {
Box( Box(

View File

@@ -48,7 +48,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import com.acitelight.aether.Global import com.acitelight.aether.Global
import com.acitelight.aether.ToggleFullScreen
import com.acitelight.aether.view.pages.formatTime import com.acitelight.aether.view.pages.formatTime
import com.acitelight.aether.view.pages.toHex import com.acitelight.aether.view.pages.toHex
import com.acitelight.aether.viewModel.VideoPlayerViewModel import com.acitelight.aether.viewModel.VideoPlayerViewModel
@@ -110,7 +109,6 @@ fun VideoPlayerPortal(
val name by videoPlayerViewModel.currentName val name by videoPlayerViewModel.currentName
val duration by videoPlayerViewModel.currentDuration val duration by videoPlayerViewModel.currentDuration
ToggleFullScreen(false)
Column( Column(
Modifier Modifier
.nestedScroll(nestedScrollConnection) .nestedScroll(nestedScrollConnection)
@@ -120,7 +118,6 @@ fun VideoPlayerPortal(
Box { Box {
PortalCorePlayer( PortalCorePlayer(
Modifier Modifier
.padding(top = 32.dp)
.heightIn(max = playerHeight) .heightIn(max = playerHeight)
.onGloballyPositioned { layoutCoordinates -> .onGloballyPositioned { layoutCoordinates ->
if (!posed && videoPlayerViewModel.renderedFirst) { if (!posed && videoPlayerViewModel.renderedFirst) {

View File

@@ -2,44 +2,72 @@ package com.acitelight.aether.view.pages
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.staggeredgrid.LazyHorizontalStaggeredGrid
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue 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.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import coil3.request.ImageRequest import coil3.request.ImageRequest
import com.acitelight.aether.ToggleFullScreen
import com.acitelight.aether.model.BookMark import com.acitelight.aether.model.BookMark
import com.acitelight.aether.model.Comic import com.acitelight.aether.model.Comic
import com.acitelight.aether.setFullScreen
import com.acitelight.aether.view.components.BiliMiniSlider
import com.acitelight.aether.viewModel.ComicGridViewModel import com.acitelight.aether.viewModel.ComicGridViewModel
@Composable @Composable
fun ComicGridView( fun ComicGridView(
comicId: String, comicId: String,
@@ -48,104 +76,206 @@ fun ComicGridView(
) { ) {
comicGridViewModel.resolve(comicId.hexToString()) comicGridViewModel.resolve(comicId.hexToString())
comicGridViewModel.updateProcess(comicId.hexToString()) {} comicGridViewModel.updateProcess(comicId.hexToString()) {}
ToggleFullScreen(false) val configuration = LocalConfiguration.current
val colorScheme = MaterialTheme.colorScheme val screenHeight = configuration.screenHeightDp.dp
val screenWidth = configuration.screenWidthDp.dp
val comic by comicGridViewModel.comic
val record by comicGridViewModel.record val record by comicGridViewModel.record
val comic by comicGridViewModel.comic
val view = LocalView.current
DisposableEffect(Unit) {
setFullScreen(view, true)
onDispose {
val nextRoute = navController.currentBackStackEntry?.destination?.route
if (nextRoute?.startsWith("comic_page_route") != true) {
setFullScreen(view, false)
}
}
}
val dens = LocalDensity.current
val listState = rememberLazyListState()
val nestedScrollConnection = remember {
object : NestedScrollConnection {
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
val deltaY = available.y // px
val deltaDp = with(dens) { deltaY.toDp() }
val r = if (deltaY < 0 && comicGridViewModel.coverHeight > 0.dp) {
val newHeight = (comicGridViewModel.coverHeight + deltaDp).coerceIn(0.dp, comicGridViewModel.maxHeight)
val consumedDp = newHeight - comicGridViewModel.coverHeight
comicGridViewModel.coverHeight = newHeight
val consumedPx = with(dens) { consumedDp.toPx() }
Offset(0f, consumedPx)
} else if (
deltaY > 0
&& comicGridViewModel.coverHeight < comicGridViewModel.maxHeight
&& listState.firstVisibleItemIndex == 0 && listState.firstVisibleItemScrollOffset == 0
) {
val newHeight = (comicGridViewModel.coverHeight + deltaDp).coerceIn(0.dp, comicGridViewModel.maxHeight)
val consumedDp = newHeight - comicGridViewModel.coverHeight
comicGridViewModel.coverHeight = newHeight
val consumedPx = with(dens) { consumedDp.toPx() }
Offset(0f, consumedPx)
} else {
Offset.Zero
}
return r
}
}
}
if (comic != null) { if (comic != null) {
Column { val comic = comic!!
Card( val pagerState = rememberPagerState(
Modifier initialPage = 0,
.padding(horizontal = 16.dp) pageCount = { comic.comic.bookmarks.size })
.padding(top = 36.dp)
.heightIn(min = 42.dp), Column(Modifier
colors = CardDefaults.cardColors(containerColor = colorScheme.primary), .nestedScroll(nestedScrollConnection).fillMaxSize()) {
shape = RoundedCornerShape(12.dp) Box(Modifier
)
{
Box(
Modifier
.heightIn(min = 42.dp)
.fillMaxWidth() .fillMaxWidth()
) .height(comicGridViewModel.coverHeight))
{ {
Text( HorizontalPager(
text = comic!!.comic.comic_name, state = pagerState,
fontSize = 18.sp, modifier = Modifier.fillMaxSize()
fontWeight = FontWeight.Bold, )
maxLines = 1, { page ->
modifier = Modifier.padding(4.dp).align(Alignment.CenterStart) AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(comic.getPage(comic.comic.bookmarks[page].page, comicGridViewModel.apiClient))
.memoryCacheKey("${comic.id}/${comic.comic.bookmarks[page].page}")
.diskCacheKey("${comic.id}/${comic.comic.bookmarks[page].page}")
.build(),
contentDescription = null,
imageLoader = comicGridViewModel.imageLoader!!,
modifier = Modifier
.fillMaxSize(),
contentScale = ContentScale.FillWidth,
onSuccess = { success ->
val drawable = success.result.image
val width = drawable.width
val height = drawable.height
val aspectRatio = width.toFloat() / height.toFloat()
comicGridViewModel.maxHeight = screenWidth / aspectRatio
if(comicGridViewModel.coverHeight > comicGridViewModel.maxHeight)
comicGridViewModel.coverHeight = comicGridViewModel.maxHeight
},
) )
}
} }
Card( Box(modifier = Modifier
Modifier
.padding(horizontal = 16.dp)
.padding(top = 4.dp)
.heightIn(min = 42.dp),
colors = CardDefaults.cardColors(containerColor = colorScheme.primary),
shape = RoundedCornerShape(12.dp)
) {
Box(
Modifier
.heightIn(min = 42.dp)
.fillMaxWidth() .fillMaxWidth()
.align(Alignment.BottomCenter)
.height(50.dp)
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.Transparent,
Color.Black.copy(alpha = 0.5f),
) )
{ )
Text( )
text = comic!!.comic.author, )
fontSize = 16.sp,
fontWeight = FontWeight.Bold, BiliMiniSlider(
maxLines = 1, value = (pagerState.currentPage + 1) / pagerState.pageCount.toFloat(),
modifier = Modifier modifier = Modifier
.padding(4.dp) .height(6.dp)
.align(Alignment.CenterStart) .width(100.dp)
) .align(Alignment.BottomCenter)
.fillMaxWidth(),
onValueChange = {
} }
)
} }
Card(
Modifier
.padding(horizontal = 16.dp)
.padding(top = 4.dp)
.heightIn(min = 42.dp),
colors = CardDefaults.cardColors(containerColor = colorScheme.primary),
shape = RoundedCornerShape(12.dp)
) {
Box(
Modifier
.heightIn(min = 42.dp)
.fillMaxWidth()
)
{
Text(
text = "Tags : ${comic!!.comic.tags.joinToString(", ")}",
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
maxLines = 5,
modifier = Modifier
.padding(4.dp)
.align(Alignment.CenterStart)
)
}
}
LazyColumn( LazyColumn(
state = listState,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxSize()
.weight(1f)
.padding(top = 6.dp) .padding(top = 6.dp)
.clip(RoundedCornerShape(6.dp)) .clip(RoundedCornerShape(6.dp))
) )
{ {
items(comicGridViewModel.chapterList) item()
{ c -> {
ChapterCard(comic!!, navController, c, comicGridViewModel) Text(
text = comic.comic.comic_name,
fontSize = 18.sp,
lineHeight = 22.sp,
fontWeight = FontWeight.Bold,
maxLines = 1,
modifier = Modifier.padding(horizontal = 16.dp).padding(top = 16.dp).padding(bottom = 4.dp)
)
FlowRow(
modifier = Modifier.padding(horizontal = 16.dp).padding(bottom = 4.dp)
)
{
comic.comic.tags.take(15).forEach()
{
ic ->
Card(
Modifier.padding(1.dp),
shape = RoundedCornerShape(8.dp)
) {
Text(
text = ic,
fontSize = 10.sp,
lineHeight = 12.sp,
fontWeight = FontWeight.Bold,
maxLines = 2,
modifier = Modifier
.padding(4.dp)
)
}
} }
} }
Box(Modifier.fillMaxWidth())
{
Text(
text = "Author: ${comic.comic.author} \n${comic.comic.list.size} Pages",
fontSize = 11.sp,
lineHeight = 15.sp,
maxLines = 3,
modifier = Modifier.padding(horizontal = 16.dp).padding(bottom = 4.dp)
)
Button(onClick = {
comicGridViewModel.updateProcess(comicId.hexToString())
{
if (record != null) {
val route = "comic_page_route/${comic.id.toHex()}/${
record!!.position
}"
navController.navigate(route)
} else {
val route = "comic_page_route/${comic.id.toHex()}/${0}"
navController.navigate(route)
}
}
}, modifier = Modifier.align(Alignment.CenterEnd))
{
Text(text = "Continue", fontSize = 16.sp)
}
}
HorizontalDivider(Modifier.padding(horizontal = 12.dp).padding(bottom = 4.dp), thickness = 1.5.dp)
}
items(comicGridViewModel.chapterList)
{ c ->
ChapterCard(comic, navController, c, comicGridViewModel)
HorizontalDivider(Modifier.padding(horizontal = 26.dp), thickness = 1.5.dp)
}
}
/*
Card( Card(
Modifier Modifier
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
@@ -156,12 +286,12 @@ fun ComicGridView(
comicGridViewModel.updateProcess(comicId.hexToString()) comicGridViewModel.updateProcess(comicId.hexToString())
{ {
if (record != null) { if (record != null) {
val route = "comic_page_route/${comic!!.id.toHex()}/${ val route = "comic_page_route/${comic.id.toHex()}/${
record!!.position record!!.position
}" }"
navController.navigate(route) navController.navigate(route)
} else { } else {
val route = "comic_page_route/${comic!!.id.toHex()}/${0}" val route = "comic_page_route/${comic.id.toHex()}/${0}"
navController.navigate(route) navController.navigate(route)
} }
} }
@@ -178,11 +308,11 @@ fun ComicGridView(
.padding(horizontal = 8.dp) .padding(horizontal = 8.dp)
) { ) {
if (record != null) { if (record != null) {
val k = comic!!.getPageChapterIndex(record!!.position) val k = comic.getPageChapterIndex(record!!.position)
Text( Text(
text = "Last Read Position: ${k.first.name} ${k.second}/${ text = "Last Read Position: ${k.first.name} ${k.second}/${
comic!!.getChapterLength( comic.getChapterLength(
k.first.page k.first.page
) )
}", }",
@@ -207,6 +337,8 @@ fun ComicGridView(
} }
} }
} }
*/
} }
} }
} }
@@ -220,8 +352,10 @@ fun ChapterCard(
) { ) {
val c = chapter val c = chapter
val iv = comic.getPageIndex(c.page) val iv = comic.getPageIndex(c.page)
val r = comic.comic.list.subList(iv, iv + comic.getChapterLength(c.page))
Card( Card(
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface.copy(0.65f)),
shape = RoundedCornerShape(6.dp), shape = RoundedCornerShape(6.dp),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -235,57 +369,31 @@ fun ChapterCard(
) { ) {
Column(Modifier.fillMaxWidth()) Column(Modifier.fillMaxWidth())
{ {
Row(Modifier.padding(6.dp))
{
Box(
Modifier
.heightIn(max = 170.dp)
.clip(RoundedCornerShape(8.dp))
.background(Color(0x44FFFFFF))
)
{
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
.data(comic.getPage(c.page, comicGridViewModel.apiClient))
.memoryCacheKey("${comic.id}/${c.page}")
.diskCacheKey("${comic.id}/${c.page}")
.build(),
contentDescription = null,
imageLoader = comicGridViewModel.imageLoader!!,
modifier = Modifier
.padding(8.dp)
.widthIn(max = 170.dp),
contentScale = ContentScale.Fit,
)
}
Column(modifier = Modifier.padding(horizontal = 12.dp)) {
Text( Text(
text = chapter.name, text = chapter.name,
fontSize = 18.sp, fontSize = 14.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
maxLines = 5, maxLines = 2,
lineHeight = 16.sp,
modifier = Modifier modifier = Modifier
.padding(8.dp) .padding(horizontal = 8.dp).padding(vertical = 4.dp)
.background(Color.Transparent) .background(Color.Transparent)
) )
Text( Text(
text = "${comic.getChapterLength(chapter.page)} Pages", text = "${comic.getChapterLength(chapter.page)} Pages",
fontSize = 14.sp, fontSize = 14.sp,
lineHeight = 16.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
maxLines = 1, maxLines = 1,
modifier = Modifier modifier = Modifier
.padding(8.dp) .padding(horizontal = 8.dp)
.background(Color.Transparent) .background(Color.Transparent)
) )
}
}
val r = comic.comic.list.subList(iv, iv + comic.getChapterLength(c.page))
LazyRow( LazyRow(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(6.dp) .padding(horizontal = 8.dp).padding(vertical = 4.dp)
) { ) {
items(r) items(r)
{ r -> { r ->
@@ -294,8 +402,8 @@ fun ChapterCard(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.wrapContentHeight() .wrapContentHeight()
.height(140.dp) .height(120.dp)
.padding(horizontal = 6.dp), .padding(horizontal = 2.dp),
onClick = { onClick = {
val route = val route =
"comic_page_route/${comic.id.toHex()}/${comic.getPageIndex(r)}" "comic_page_route/${comic.id.toHex()}/${comic.getPageIndex(r)}"
@@ -313,7 +421,7 @@ fun ChapterCard(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.clip(RoundedCornerShape(12.dp)), .clip(RoundedCornerShape(12.dp)),
contentScale = ContentScale.Crop, contentScale = ContentScale.Fit,
) )
} }
} }

View File

@@ -28,6 +28,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -38,6 +39,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
@@ -47,6 +49,7 @@ import androidx.navigation.NavHostController
import coil3.compose.AsyncImage import coil3.compose.AsyncImage
import coil3.request.ImageRequest import coil3.request.ImageRequest
import com.acitelight.aether.model.BookMark import com.acitelight.aether.model.BookMark
import com.acitelight.aether.setFullScreen
import com.acitelight.aether.view.components.BookmarkPop import com.acitelight.aether.view.components.BookmarkPop
import com.acitelight.aether.viewModel.ComicPageViewModel import com.acitelight.aether.viewModel.ComicPageViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -71,6 +74,15 @@ fun ComicPageView(
comicPageViewModel.updateProcess(pagerState.currentPage) comicPageViewModel.updateProcess(pagerState.currentPage)
val comic by comicPageViewModel.comic val comic by comicPageViewModel.comic
val view = LocalView.current
DisposableEffect(Unit) {
setFullScreen(view, true)
onDispose {
}
}
comic?.let { comic?.let {
Box() Box()
{ {
@@ -233,7 +245,7 @@ fun ComicPageView(
.fillMaxWidth() .fillMaxWidth()
.padding(bottom = 18.dp) .padding(bottom = 18.dp)
.padding(horizontal = 12.dp) .padding(horizontal = 12.dp)
.height(240.dp) .height(180.dp)
.align(Alignment.BottomCenter) .align(Alignment.BottomCenter)
) )
{ {
@@ -241,7 +253,7 @@ fun ComicPageView(
{ r -> { r ->
Card( Card(
colors = CardDefaults.cardColors(containerColor = colorScheme.primary.copy(0.8f)), colors = CardDefaults.cardColors(containerColor = colorScheme.primary.copy(0.8f)),
shape = RoundedCornerShape(12.dp), shape = RoundedCornerShape(8.dp),
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.wrapContentHeight() .wrapContentHeight()
@@ -250,7 +262,7 @@ fun ComicPageView(
pagerState.requestScrollToPage(page = r) pagerState.requestScrollToPage(page = r)
} }
) { ) {
Box(Modifier.padding(4.dp)) Box(Modifier.padding(1.dp))
{ {
AsyncImage( AsyncImage(
model = ImageRequest.Builder(LocalContext.current) model = ImageRequest.Builder(LocalContext.current)
@@ -262,7 +274,7 @@ fun ComicPageView(
imageLoader = comicPageViewModel.imageLoader!!, imageLoader = comicPageViewModel.imageLoader!!,
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.clip(RoundedCornerShape(12.dp)) .clip(RoundedCornerShape(8.dp))
.align(Alignment.Center), .align(Alignment.Center),
contentScale = ContentScale.Fit, contentScale = ContentScale.Fit,
) )
@@ -278,18 +290,6 @@ fun ComicPageView(
) )
{ {
Row { Row {
Text(
text = k.first.name,
fontSize = 14.sp,
fontWeight = FontWeight.Bold,
color = Color.White,
maxLines = 1,
modifier = Modifier
.padding(2.dp)
.widthIn(max = 200.dp)
.align(Alignment.CenterVertically)
)
Text( Text(
text = "${k.second}/${it.getChapterLength(k.first.page)}", text = "${k.second}/${it.getChapterLength(k.first.page)}",
fontSize = 16.sp, fontSize = 16.sp,

View File

@@ -6,11 +6,15 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid
@@ -19,17 +23,25 @@ import androidx.compose.foundation.lazy.staggeredgrid.items
import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState import androidx.compose.foundation.lazy.staggeredgrid.rememberLazyStaggeredGridState
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Search
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.Placeable import androidx.compose.ui.layout.Placeable
import androidx.compose.ui.text.font.FontWeight 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.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
@@ -118,16 +130,50 @@ fun ComicScreen(
val included = comicScreenViewModel.included val included = comicScreenViewModel.included
val state = rememberLazyStaggeredGridState() val state = rememberLazyStaggeredGridState()
val colorScheme = MaterialTheme.colorScheme val colorScheme = MaterialTheme.colorScheme
var searchFilter by comicScreenViewModel.searchFilter
Column { Column {
Row(Modifier
.padding(4.dp)
.align(Alignment.CenterHorizontally)) {
Text( Text(
text = "Comic& Images", text = "Comics",
style = MaterialTheme.typography.headlineMedium, style = MaterialTheme.typography.headlineMedium,
modifier = Modifier modifier = Modifier.align(Alignment.CenterVertically)
.padding(8.dp)
.align(Alignment.Start)
) )
HorizontalDivider(Modifier.padding(1.dp), thickness = 1.5.dp)
Spacer(Modifier.weight(1f))
Row(
modifier = Modifier
.align(Alignment.CenterVertically)
.height(36.dp)
.widthIn(max = 240.dp)
.background(colorScheme.primary, RoundedCornerShape(8.dp))
.padding(horizontal = 6.dp)
) {
Icon(
modifier = Modifier
.size(30.dp)
.align(Alignment.CenterVertically),
imageVector = Icons.Default.Search,
contentDescription = "Catalogue"
)
Spacer(Modifier.width(4.dp))
BasicTextField(
value = searchFilter,
onValueChange = { searchFilter = it },
textStyle = LocalTextStyle.current.copy(
fontSize = 18.sp,
color = Color.White,
textAlign = TextAlign.Start
),
singleLine = true,
modifier = Modifier.align(Alignment.CenterVertically)
)
}
}
VariableGrid( VariableGrid(
modifier = Modifier modifier = Modifier
.heightIn(max = 88.dp) .heightIn(max = 88.dp)
@@ -140,7 +186,7 @@ fun ComicScreen(
Box( Box(
Modifier Modifier
.background( .background(
if (included.contains(i)) Color.Green.copy(alpha = 0.65f) else colorScheme.primary, if (included.contains(i)) Color.Green.copy(alpha = 0.65f) else colorScheme.surface,
shape = RoundedCornerShape(4.dp) shape = RoundedCornerShape(4.dp)
) )
.height(32.dp).widthIn(max = 72.dp) .height(32.dp).widthIn(max = 72.dp)
@@ -167,15 +213,15 @@ fun ComicScreen(
HorizontalDivider(Modifier.padding(1.dp), thickness = 1.5.dp) HorizontalDivider(Modifier.padding(1.dp), thickness = 1.5.dp)
LazyVerticalStaggeredGrid( LazyVerticalStaggeredGrid(
columns = StaggeredGridCells.Adaptive(136.dp), columns = StaggeredGridCells.Adaptive(120.dp),
contentPadding = PaddingValues(8.dp), contentPadding = PaddingValues(4.dp),
verticalItemSpacing = 8.dp, verticalItemSpacing = 6.dp,
horizontalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp),
state = state, state = state,
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { ) {
items( items(
items = comicScreenViewModel.comics.filter { x -> items = comicScreenViewModel.comics.filter { searchFilter.isEmpty() || searchFilter in it.comic.comic_name }.filter { x ->
included.all { y -> y in x.comic.tags } || included.isEmpty() included.all { y -> y in x.comic.tags } || included.isEmpty()
}, },
key = { it.id } key = { it.id }

View File

@@ -89,10 +89,13 @@ fun HomeScreen(
val group = val group =
fv.filter { it.klass == i.klass && it.video.group == i.video.group && it.video.group != "null" } fv.filter { it.klass == i.klass && it.video.group == i.video.group && it.video.group != "null" }
for (i in group) { for (ix in group) {
playList.add("${i.klass}/${i.id}") playList.add("${ix.klass}/${ix.id}")
} }
if(!playList.contains("${i.klass}/${i.id}"))
playList.add("${i.klass}/${i.id}")
val route = val route =
"video_player_route/${(playList.joinToString(",") + "|${i.id}").toHex()}" "video_player_route/${(playList.joinToString(",") + "|${i.id}").toHex()}"
navController.navigate(route) navController.navigate(route)

View File

@@ -1,8 +1,12 @@
package com.acitelight.aether.viewModel package com.acitelight.aether.viewModel
import android.content.Context import android.content.Context
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import coil3.ImageLoader import coil3.ImageLoader
@@ -27,6 +31,9 @@ class ComicGridViewModel @Inject constructor(
val apiClient: ApiClient val apiClient: ApiClient
) : ViewModel() ) : ViewModel()
{ {
var coverHeight by mutableStateOf(220.dp)
var maxHeight = 220.dp
var imageLoader: ImageLoader? = null var imageLoader: ImageLoader? = null
var comic = mutableStateOf<Comic?>(null) var comic = mutableStateOf<Comic?>(null)
val chapterList = mutableStateListOf<BookMark>() val chapterList = mutableStateListOf<BookMark>()

View File

@@ -2,6 +2,7 @@ package com.acitelight.aether.viewModel
import android.content.Context import android.content.Context
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import coil3.ImageLoader import coil3.ImageLoader
@@ -23,6 +24,7 @@ class ComicScreenViewModel @Inject constructor(
var imageLoader: ImageLoader? = null; var imageLoader: ImageLoader? = null;
val searchFilter = mutableStateOf("")
val comics = mutableStateListOf<Comic>() val comics = mutableStateListOf<Comic>()
val excluded = mutableStateListOf<String>() val excluded = mutableStateListOf<String>()
val included = mutableStateListOf<String>() val included = mutableStateListOf<String>()

View File

@@ -1,4 +1,5 @@
[versions] [versions]
accompanistNavigationAnimation = "0.37.3"
agp = "8.13.0" agp = "8.13.0"
ariaCompiler = "latest" ariaCompiler = "latest"
bcprovJdk15on = "1.70" bcprovJdk15on = "1.70"
@@ -10,7 +11,7 @@ datastorePreferences = "1.1.7"
exoplayerplus = "0.2.0" exoplayerplus = "0.2.0"
fetch2 = "3.4.1" fetch2 = "3.4.1"
fetch2okhttp = "3.4.1" fetch2okhttp = "3.4.1"
gson = "2.13.1" gson = "2.13.2"
kotlin = "2.2.20" kotlin = "2.2.20"
coreKtx = "1.17.0" coreKtx = "1.17.0"
junit = "4.13.2" junit = "4.13.2"
@@ -19,28 +20,31 @@ espressoCore = "3.7.0"
kotlinxSerializationJson = "1.9.0" kotlinxSerializationJson = "1.9.0"
lifecycleRuntimeKtx = "2.9.4" lifecycleRuntimeKtx = "2.9.4"
activityCompose = "1.11.0" activityCompose = "1.11.0"
composeBom = "2025.09.00" composeBom = "2025.09.01"
media3Common = "1.8.0" media3Common = "1.8.0"
media3Exoplayer = "1.8.0" media3Exoplayer = "1.8.0"
media3ExoplayerFfmpeg = "1.8.0" media3ExoplayerFfmpeg = "1.8.0"
media3Ui = "1.8.0" media3Ui = "1.8.0"
navigationCompose = "2.9.4" navigationCompose = "2.9.5"
okhttp = "5.1.0" okhttp = "5.1.0"
persistentcookiejar = "1.0.1" persistentcookiejar = "1.0.1"
repo = "Tag" repo = "Tag"
retrofit = "3.0.0" retrofit = "3.0.0"
retrofit2KotlinxSerializationConverter = "1.0.0" retrofit2KotlinxSerializationConverter = "1.0.0"
media3DatasourceOkhttp = "1.8.0" media3DatasourceOkhttp = "1.8.0"
roomCompiler = "2.8.0" roomCompiler = "2.8.1"
roomKtx = "2.8.0" roomKtx = "2.8.1"
roomRuntime = "2.8.0" roomRuntime = "2.8.1"
ksp = "2.1.21-2.0.2" ksp = "2.1.21-2.0.2"
hilt = "2.57.1" hilt = "2.57.2"
hilt-navigation-compose = "1.3.0" hilt-navigation-compose = "1.3.0"
composeMaterialCore = "1.5.1" composeMaterialCore = "1.5.2"
constraintlayout = "2.2.1"
animation = "1.9.2"
[libraries] [libraries]
accompanist-navigation-animation = { module = "com.google.accompanist:accompanist-navigation-animation", version.ref = "accompanistNavigationAnimation" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" } androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" } androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" }
@@ -83,6 +87,8 @@ hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref
hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" } hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hilt-navigation-compose" } hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hilt-navigation-compose" }
androidx-compose-material-core = { group = "androidx.wear.compose", name = "compose-material-core", version.ref = "composeMaterialCore" } androidx-compose-material-core = { group = "androidx.wear.compose", name = "compose-material-core", version.ref = "composeMaterialCore" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
androidx-compose-animation = { group = "androidx.compose.animation", name = "animation", version.ref = "animation" }
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "agp" } android-application = { id = "com.android.application", version.ref = "agp" }