[feat] UI optimization 3
This commit is contained in:
@@ -54,6 +54,8 @@ dependencies {
|
||||
implementation(libs.hilt.android)
|
||||
implementation(libs.hilt.navigation.compose)
|
||||
implementation(libs.androidx.compose.material.core)
|
||||
implementation(libs.androidx.constraintlayout)
|
||||
implementation(libs.androidx.compose.animation)
|
||||
ksp(libs.hilt.android.compiler)
|
||||
|
||||
implementation(libs.androidx.room.runtime)
|
||||
|
||||
@@ -10,6 +10,7 @@ object Global {
|
||||
var sameClassVideos: List<Video>? = null
|
||||
private set
|
||||
|
||||
var isFullScreen by mutableStateOf(false)
|
||||
fun updateRelate(v: List<Video>, s: Video)
|
||||
{
|
||||
sameClassVideos = if (v.contains(s)) {
|
||||
|
||||
@@ -4,11 +4,15 @@ import android.app.Activity
|
||||
import android.content.Intent
|
||||
import androidx.compose.material.icons.Icons
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||
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.slideOutVertically
|
||||
import androidx.compose.foundation.background
|
||||
@@ -95,22 +99,17 @@ class MainScreenActivity : ComponentActivity() {
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun ToggleFullScreen(isFullScreen: Boolean)
|
||||
{
|
||||
val view = LocalView.current
|
||||
fun setFullScreen(view: View, isFullScreen: Boolean) {
|
||||
Global.isFullScreen = isFullScreen
|
||||
val window = (view.context as Activity).window
|
||||
val insetsController = WindowCompat.getInsetsController(window, view)
|
||||
|
||||
LaunchedEffect(isFullScreen) {
|
||||
val window = (view.context as Activity).window
|
||||
val insetsController = WindowCompat.getInsetsController(window, view)
|
||||
|
||||
if (isFullScreen) {
|
||||
insetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||
insetsController.systemBarsBehavior =
|
||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
} else {
|
||||
insetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||
}
|
||||
if (isFullScreen) {
|
||||
insetsController.hide(WindowInsetsCompat.Type.systemBars())
|
||||
insetsController.systemBarsBehavior =
|
||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
} else {
|
||||
insetsController.show(WindowInsetsCompat.Type.systemBars())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,40 +135,64 @@ fun AppNavigation() {
|
||||
) {
|
||||
BottomNavigationBar(navController = navController)
|
||||
}
|
||||
if(shouldShowBottomBar)
|
||||
ToggleFullScreen(false)
|
||||
}
|
||||
) { innerPadding ->
|
||||
NavHost(
|
||||
navController = navController,
|
||||
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) {
|
||||
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)) }
|
||||
) {
|
||||
CardPage(title = "Home") {
|
||||
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)
|
||||
}
|
||||
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") {
|
||||
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") {
|
||||
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();
|
||||
}
|
||||
|
||||
composable(
|
||||
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 })
|
||||
) {
|
||||
backStackEntry ->
|
||||
@@ -181,6 +204,10 @@ fun AppNavigation() {
|
||||
|
||||
composable(
|
||||
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 })
|
||||
) {
|
||||
backStackEntry ->
|
||||
@@ -192,6 +219,10 @@ fun AppNavigation() {
|
||||
|
||||
composable(
|
||||
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 })
|
||||
) {
|
||||
backStackEntry ->
|
||||
@@ -199,7 +230,6 @@ fun AppNavigation() {
|
||||
val page = backStackEntry.arguments?.getString("page")
|
||||
if (comicId != null && page != null) {
|
||||
ComicPageView(comicId = comicId, page = page, navController = navController)
|
||||
ToggleFullScreen(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.acitelight.aether.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class BookMark(
|
||||
val name: String,
|
||||
val page: String
|
||||
|
||||
@@ -7,6 +7,19 @@ class Comic(
|
||||
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
|
||||
{
|
||||
return "${api.getBase()}api/image/$id/${comic.list[pageNumber]}"
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.acitelight.aether.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ComicResponse(
|
||||
val comic_name: String,
|
||||
val page_count: Int,
|
||||
val bookmarks: List<BookMark>,
|
||||
val list: List<String>,
|
||||
val tags: List<String>,
|
||||
val author: String
|
||||
val author: String,
|
||||
val cover: String
|
||||
)
|
||||
@@ -219,6 +219,8 @@ class ApiClient @Inject constructor(
|
||||
|
||||
suspend fun apply(context: Context, urls: String, crt: String): String? {
|
||||
try {
|
||||
client = createOkHttp()
|
||||
|
||||
val urlList = urls.split(";").map { it.trim() }
|
||||
|
||||
var selectedUrl: String? = null
|
||||
@@ -231,7 +233,6 @@ class ApiClient @Inject constructor(
|
||||
}
|
||||
|
||||
if (selectedUrl == null) {
|
||||
client = createOkHttp()
|
||||
throw Exception("No reachable URL found")
|
||||
}
|
||||
|
||||
|
||||
@@ -59,9 +59,9 @@ fun ComicCard(
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
AsyncImage(
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
.data(comic.getPage(0, comicScreenViewModel.apiClient))
|
||||
.memoryCacheKey("${comic.id}/${0}")
|
||||
.diskCacheKey("${comic.id}/${0}")
|
||||
.data(comic.getCover(comicScreenViewModel.apiClient))
|
||||
.memoryCacheKey("${comic.id}/cover")
|
||||
.diskCacheKey("${comic.id}/cover")
|
||||
.build(),
|
||||
contentDescription = null,
|
||||
imageLoader = comicScreenViewModel.imageLoader!!,
|
||||
@@ -115,14 +115,6 @@ fun ComicCard(
|
||||
maxLines = 1,
|
||||
modifier = Modifier.align(Alignment.CenterStart)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = comic.comic.author,
|
||||
fontSize = 12.sp,
|
||||
lineHeight = 14.sp,
|
||||
maxLines = 1,
|
||||
modifier = Modifier.align(Alignment.CenterEnd)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
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.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -69,7 +71,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
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.moveBrit
|
||||
import com.acitelight.aether.viewModel.VideoPlayerViewModel
|
||||
@@ -108,7 +110,14 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
|
||||
videoPlayerViewModel.isLandscape = false
|
||||
}
|
||||
|
||||
ToggleFullScreen(true)
|
||||
val view = LocalView.current
|
||||
DisposableEffect(Unit) {
|
||||
setFullScreen(view, true)
|
||||
onDispose {
|
||||
setFullScreen(view, false)
|
||||
}
|
||||
}
|
||||
|
||||
Box(Modifier.fillMaxSize())
|
||||
{
|
||||
Box(
|
||||
|
||||
@@ -48,7 +48,6 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.navigation.NavHostController
|
||||
import com.acitelight.aether.Global
|
||||
import com.acitelight.aether.ToggleFullScreen
|
||||
import com.acitelight.aether.view.pages.formatTime
|
||||
import com.acitelight.aether.view.pages.toHex
|
||||
import com.acitelight.aether.viewModel.VideoPlayerViewModel
|
||||
@@ -110,7 +109,6 @@ fun VideoPlayerPortal(
|
||||
val name by videoPlayerViewModel.currentName
|
||||
val duration by videoPlayerViewModel.currentDuration
|
||||
|
||||
ToggleFullScreen(false)
|
||||
Column(
|
||||
Modifier
|
||||
.nestedScroll(nestedScrollConnection)
|
||||
@@ -120,7 +118,6 @@ fun VideoPlayerPortal(
|
||||
Box {
|
||||
PortalCorePlayer(
|
||||
Modifier
|
||||
.padding(top = 32.dp)
|
||||
.heightIn(max = playerHeight)
|
||||
.onGloballyPositioned { layoutCoordinates ->
|
||||
if (!posed && videoPlayerViewModel.renderedFirst) {
|
||||
|
||||
@@ -2,44 +2,72 @@ package com.acitelight.aether.view.pages
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
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.FlowRow
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
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.material3.Button
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.CardDefaults
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
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.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
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.platform.LocalConfiguration
|
||||
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.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
|
||||
import androidx.navigation.NavHostController
|
||||
import coil3.compose.AsyncImage
|
||||
import coil3.request.ImageRequest
|
||||
import com.acitelight.aether.ToggleFullScreen
|
||||
import com.acitelight.aether.model.BookMark
|
||||
import com.acitelight.aether.model.Comic
|
||||
import com.acitelight.aether.setFullScreen
|
||||
import com.acitelight.aether.view.components.BiliMiniSlider
|
||||
import com.acitelight.aether.viewModel.ComicGridViewModel
|
||||
|
||||
|
||||
@Composable
|
||||
fun ComicGridView(
|
||||
comicId: String,
|
||||
@@ -48,104 +76,206 @@ fun ComicGridView(
|
||||
) {
|
||||
comicGridViewModel.resolve(comicId.hexToString())
|
||||
comicGridViewModel.updateProcess(comicId.hexToString()) {}
|
||||
ToggleFullScreen(false)
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
|
||||
val comic by comicGridViewModel.comic
|
||||
val configuration = LocalConfiguration.current
|
||||
val screenHeight = configuration.screenHeightDp.dp
|
||||
val screenWidth = configuration.screenWidthDp.dp
|
||||
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) {
|
||||
Column {
|
||||
Card(
|
||||
Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(top = 36.dp)
|
||||
.heightIn(min = 42.dp),
|
||||
colors = CardDefaults.cardColors(containerColor = colorScheme.primary),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
)
|
||||
val comic = comic!!
|
||||
val pagerState = rememberPagerState(
|
||||
initialPage = 0,
|
||||
pageCount = { comic.comic.bookmarks.size })
|
||||
|
||||
Column(Modifier
|
||||
.nestedScroll(nestedScrollConnection).fillMaxSize()) {
|
||||
Box(Modifier
|
||||
.fillMaxWidth()
|
||||
.height(comicGridViewModel.coverHeight))
|
||||
{
|
||||
Box(
|
||||
Modifier
|
||||
.heightIn(min = 42.dp)
|
||||
.fillMaxWidth()
|
||||
HorizontalPager(
|
||||
state = pagerState,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
)
|
||||
{
|
||||
Text(
|
||||
text = comic!!.comic.comic_name,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
modifier = Modifier.padding(4.dp).align(Alignment.CenterStart)
|
||||
{ page ->
|
||||
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
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
Box(modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.BottomCenter)
|
||||
.height(50.dp)
|
||||
.background(
|
||||
brush = Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
Color.Transparent,
|
||||
Color.Black.copy(alpha = 0.5f),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
BiliMiniSlider(
|
||||
value = (pagerState.currentPage + 1) / pagerState.pageCount.toFloat(),
|
||||
modifier = Modifier
|
||||
.height(6.dp)
|
||||
.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 = comic!!.comic.author,
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
.align(Alignment.CenterStart)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
state = listState,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f)
|
||||
.fillMaxSize()
|
||||
.padding(top = 6.dp)
|
||||
.clip(RoundedCornerShape(6.dp))
|
||||
)
|
||||
{
|
||||
item()
|
||||
{
|
||||
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)
|
||||
ChapterCard(comic, navController, c, comicGridViewModel)
|
||||
HorizontalDivider(Modifier.padding(horizontal = 26.dp), thickness = 1.5.dp)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Card(
|
||||
Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
@@ -156,12 +286,12 @@ fun ComicGridView(
|
||||
comicGridViewModel.updateProcess(comicId.hexToString())
|
||||
{
|
||||
if (record != null) {
|
||||
val route = "comic_page_route/${comic!!.id.toHex()}/${
|
||||
val route = "comic_page_route/${comic.id.toHex()}/${
|
||||
record!!.position
|
||||
}"
|
||||
navController.navigate(route)
|
||||
} else {
|
||||
val route = "comic_page_route/${comic!!.id.toHex()}/${0}"
|
||||
val route = "comic_page_route/${comic.id.toHex()}/${0}"
|
||||
navController.navigate(route)
|
||||
}
|
||||
}
|
||||
@@ -178,11 +308,11 @@ fun ComicGridView(
|
||||
.padding(horizontal = 8.dp)
|
||||
) {
|
||||
if (record != null) {
|
||||
val k = comic!!.getPageChapterIndex(record!!.position)
|
||||
val k = comic.getPageChapterIndex(record!!.position)
|
||||
|
||||
Text(
|
||||
text = "Last Read Position: ${k.first.name} ${k.second}/${
|
||||
comic!!.getChapterLength(
|
||||
comic.getChapterLength(
|
||||
k.first.page
|
||||
)
|
||||
}",
|
||||
@@ -207,6 +337,8 @@ fun ComicGridView(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,8 +352,10 @@ fun ChapterCard(
|
||||
) {
|
||||
val c = chapter
|
||||
val iv = comic.getPageIndex(c.page)
|
||||
val r = comic.comic.list.subList(iv, iv + comic.getChapterLength(c.page))
|
||||
|
||||
Card(
|
||||
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surface.copy(0.65f)),
|
||||
shape = RoundedCornerShape(6.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -235,57 +369,31 @@ fun ChapterCard(
|
||||
) {
|
||||
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,
|
||||
)
|
||||
}
|
||||
Text(
|
||||
text = chapter.name,
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 2,
|
||||
lineHeight = 16.sp,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp).padding(vertical = 4.dp)
|
||||
.background(Color.Transparent)
|
||||
)
|
||||
Text(
|
||||
text = "${comic.getChapterLength(chapter.page)} Pages",
|
||||
fontSize = 14.sp,
|
||||
lineHeight = 16.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 8.dp)
|
||||
.background(Color.Transparent)
|
||||
)
|
||||
|
||||
Column(modifier = Modifier.padding(horizontal = 12.dp)) {
|
||||
Text(
|
||||
text = chapter.name,
|
||||
fontSize = 18.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 5,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.background(Color.Transparent)
|
||||
)
|
||||
Text(
|
||||
text = "${comic.getChapterLength(chapter.page)} Pages",
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.background(Color.Transparent)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val r = comic.comic.list.subList(iv, iv + comic.getChapterLength(c.page))
|
||||
LazyRow(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(6.dp)
|
||||
.padding(horizontal = 8.dp).padding(vertical = 4.dp)
|
||||
) {
|
||||
items(r)
|
||||
{ r ->
|
||||
@@ -294,8 +402,8 @@ fun ChapterCard(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.height(140.dp)
|
||||
.padding(horizontal = 6.dp),
|
||||
.height(120.dp)
|
||||
.padding(horizontal = 2.dp),
|
||||
onClick = {
|
||||
val route =
|
||||
"comic_page_route/${comic.id.toHex()}/${comic.getPageIndex(r)}"
|
||||
@@ -313,7 +421,7 @@ fun ChapterCard(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.clip(RoundedCornerShape(12.dp)),
|
||||
contentScale = ContentScale.Crop,
|
||||
contentScale = ContentScale.Fit,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
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.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
@@ -47,6 +49,7 @@ import androidx.navigation.NavHostController
|
||||
import coil3.compose.AsyncImage
|
||||
import coil3.request.ImageRequest
|
||||
import com.acitelight.aether.model.BookMark
|
||||
import com.acitelight.aether.setFullScreen
|
||||
import com.acitelight.aether.view.components.BookmarkPop
|
||||
import com.acitelight.aether.viewModel.ComicPageViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -71,6 +74,15 @@ fun ComicPageView(
|
||||
comicPageViewModel.updateProcess(pagerState.currentPage)
|
||||
|
||||
val comic by comicPageViewModel.comic
|
||||
|
||||
val view = LocalView.current
|
||||
DisposableEffect(Unit) {
|
||||
setFullScreen(view, true)
|
||||
onDispose {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
comic?.let {
|
||||
Box()
|
||||
{
|
||||
@@ -233,7 +245,7 @@ fun ComicPageView(
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 18.dp)
|
||||
.padding(horizontal = 12.dp)
|
||||
.height(240.dp)
|
||||
.height(180.dp)
|
||||
.align(Alignment.BottomCenter)
|
||||
)
|
||||
{
|
||||
@@ -241,7 +253,7 @@ fun ComicPageView(
|
||||
{ r ->
|
||||
Card(
|
||||
colors = CardDefaults.cardColors(containerColor = colorScheme.primary.copy(0.8f)),
|
||||
shape = RoundedCornerShape(12.dp),
|
||||
shape = RoundedCornerShape(8.dp),
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.wrapContentHeight()
|
||||
@@ -250,7 +262,7 @@ fun ComicPageView(
|
||||
pagerState.requestScrollToPage(page = r)
|
||||
}
|
||||
) {
|
||||
Box(Modifier.padding(4.dp))
|
||||
Box(Modifier.padding(1.dp))
|
||||
{
|
||||
AsyncImage(
|
||||
model = ImageRequest.Builder(LocalContext.current)
|
||||
@@ -262,7 +274,7 @@ fun ComicPageView(
|
||||
imageLoader = comicPageViewModel.imageLoader!!,
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.clip(RoundedCornerShape(8.dp))
|
||||
.align(Alignment.Center),
|
||||
contentScale = ContentScale.Fit,
|
||||
)
|
||||
@@ -278,18 +290,6 @@ fun ComicPageView(
|
||||
)
|
||||
{
|
||||
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 = "${k.second}/${it.getChapterLength(k.first.page)}",
|
||||
fontSize = 16.sp,
|
||||
|
||||
@@ -6,11 +6,15 @@ 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.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
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.wrapContentHeight
|
||||
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.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
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.Icon
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.Layout
|
||||
import androidx.compose.ui.layout.Placeable
|
||||
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.sp
|
||||
@@ -118,16 +130,50 @@ fun ComicScreen(
|
||||
val included = comicScreenViewModel.included
|
||||
val state = rememberLazyStaggeredGridState()
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
var searchFilter by comicScreenViewModel.searchFilter
|
||||
|
||||
Column {
|
||||
Text(
|
||||
text = "Comic& Images",
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.align(Alignment.Start)
|
||||
)
|
||||
HorizontalDivider(Modifier.padding(1.dp), thickness = 1.5.dp)
|
||||
Row(Modifier
|
||||
.padding(4.dp)
|
||||
.align(Alignment.CenterHorizontally)) {
|
||||
Text(
|
||||
text = "Comics",
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
modifier = Modifier.align(Alignment.CenterVertically)
|
||||
)
|
||||
|
||||
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(
|
||||
modifier = Modifier
|
||||
.heightIn(max = 88.dp)
|
||||
@@ -140,7 +186,7 @@ fun ComicScreen(
|
||||
Box(
|
||||
Modifier
|
||||
.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)
|
||||
)
|
||||
.height(32.dp).widthIn(max = 72.dp)
|
||||
@@ -167,15 +213,15 @@ fun ComicScreen(
|
||||
HorizontalDivider(Modifier.padding(1.dp), thickness = 1.5.dp)
|
||||
|
||||
LazyVerticalStaggeredGrid(
|
||||
columns = StaggeredGridCells.Adaptive(136.dp),
|
||||
contentPadding = PaddingValues(8.dp),
|
||||
verticalItemSpacing = 8.dp,
|
||||
columns = StaggeredGridCells.Adaptive(120.dp),
|
||||
contentPadding = PaddingValues(4.dp),
|
||||
verticalItemSpacing = 6.dp,
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
state = state,
|
||||
modifier = Modifier.fillMaxSize()
|
||||
) {
|
||||
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()
|
||||
},
|
||||
key = { it.id }
|
||||
|
||||
@@ -89,10 +89,13 @@ fun HomeScreen(
|
||||
|
||||
val group =
|
||||
fv.filter { it.klass == i.klass && it.video.group == i.video.group && it.video.group != "null" }
|
||||
for (i in group) {
|
||||
playList.add("${i.klass}/${i.id}")
|
||||
for (ix in group) {
|
||||
playList.add("${ix.klass}/${ix.id}")
|
||||
}
|
||||
|
||||
if(!playList.contains("${i.klass}/${i.id}"))
|
||||
playList.add("${i.klass}/${i.id}")
|
||||
|
||||
val route =
|
||||
"video_player_route/${(playList.joinToString(",") + "|${i.id}").toHex()}"
|
||||
navController.navigate(route)
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.acitelight.aether.viewModel
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
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.viewModelScope
|
||||
import coil3.ImageLoader
|
||||
@@ -27,6 +31,9 @@ class ComicGridViewModel @Inject constructor(
|
||||
val apiClient: ApiClient
|
||||
) : ViewModel()
|
||||
{
|
||||
var coverHeight by mutableStateOf(220.dp)
|
||||
var maxHeight = 220.dp
|
||||
|
||||
var imageLoader: ImageLoader? = null
|
||||
var comic = mutableStateOf<Comic?>(null)
|
||||
val chapterList = mutableStateListOf<BookMark>()
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.acitelight.aether.viewModel
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import coil3.ImageLoader
|
||||
@@ -23,6 +24,7 @@ class ComicScreenViewModel @Inject constructor(
|
||||
|
||||
var imageLoader: ImageLoader? = null;
|
||||
|
||||
val searchFilter = mutableStateOf("")
|
||||
val comics = mutableStateListOf<Comic>()
|
||||
val excluded = mutableStateListOf<String>()
|
||||
val included = mutableStateListOf<String>()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[versions]
|
||||
accompanistNavigationAnimation = "0.37.3"
|
||||
agp = "8.13.0"
|
||||
ariaCompiler = "latest"
|
||||
bcprovJdk15on = "1.70"
|
||||
@@ -10,7 +11,7 @@ datastorePreferences = "1.1.7"
|
||||
exoplayerplus = "0.2.0"
|
||||
fetch2 = "3.4.1"
|
||||
fetch2okhttp = "3.4.1"
|
||||
gson = "2.13.1"
|
||||
gson = "2.13.2"
|
||||
kotlin = "2.2.20"
|
||||
coreKtx = "1.17.0"
|
||||
junit = "4.13.2"
|
||||
@@ -19,28 +20,31 @@ espressoCore = "3.7.0"
|
||||
kotlinxSerializationJson = "1.9.0"
|
||||
lifecycleRuntimeKtx = "2.9.4"
|
||||
activityCompose = "1.11.0"
|
||||
composeBom = "2025.09.00"
|
||||
composeBom = "2025.09.01"
|
||||
media3Common = "1.8.0"
|
||||
media3Exoplayer = "1.8.0"
|
||||
media3ExoplayerFfmpeg = "1.8.0"
|
||||
media3Ui = "1.8.0"
|
||||
navigationCompose = "2.9.4"
|
||||
navigationCompose = "2.9.5"
|
||||
okhttp = "5.1.0"
|
||||
persistentcookiejar = "1.0.1"
|
||||
repo = "Tag"
|
||||
retrofit = "3.0.0"
|
||||
retrofit2KotlinxSerializationConverter = "1.0.0"
|
||||
media3DatasourceOkhttp = "1.8.0"
|
||||
roomCompiler = "2.8.0"
|
||||
roomKtx = "2.8.0"
|
||||
roomRuntime = "2.8.0"
|
||||
roomCompiler = "2.8.1"
|
||||
roomKtx = "2.8.1"
|
||||
roomRuntime = "2.8.1"
|
||||
|
||||
ksp = "2.1.21-2.0.2"
|
||||
hilt = "2.57.1"
|
||||
hilt = "2.57.2"
|
||||
hilt-navigation-compose = "1.3.0"
|
||||
composeMaterialCore = "1.5.1"
|
||||
composeMaterialCore = "1.5.2"
|
||||
constraintlayout = "2.2.1"
|
||||
animation = "1.9.2"
|
||||
|
||||
[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-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" }
|
||||
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-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-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||
androidx-compose-animation = { group = "androidx.compose.animation", name = "animation", version.ref = "animation" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
|
||||
Reference in New Issue
Block a user