[update] Better UI

This commit is contained in:
acite
2025-09-14 18:26:05 +08:00
parent 9c04d7679c
commit cc540903d3
21 changed files with 661 additions and 98 deletions

View File

@@ -16,6 +16,7 @@ import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@@ -43,6 +44,7 @@ fun ComicGridView(comicId: String, navController: NavHostController, comicGridVi
comicGridViewModel.resolve(comicId.hexToString())
comicGridViewModel.updateProcess(comicId.hexToString()){}
ToggleFullScreen(false)
val colorScheme = MaterialTheme.colorScheme
val context = LocalContext.current
val comic by comicGridViewModel.comic
@@ -53,28 +55,25 @@ fun ComicGridView(comicId: String, navController: NavHostController, comicGridVi
Box(
Modifier
.padding(horizontal = 16.dp).padding(top = 36.dp)
.background(Color.White.copy(alpha = 0.65f), shape = RoundedCornerShape(12.dp))
.background(colorScheme.surfaceContainerHighest, shape = RoundedCornerShape(12.dp))
)
{
Text(
text = comic!!.comic.comic_name,
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = Color.Black,
maxLines = 1,
modifier = Modifier.padding(4.dp)
)
modifier = Modifier.padding(4.dp))
}
Box(
Modifier
.padding(horizontal = 16.dp).padding(top = 4.dp)
.background(Color.White.copy(alpha = 0.65f), shape = RoundedCornerShape(12.dp))
.background(colorScheme.surfaceContainerHighest, shape = RoundedCornerShape(12.dp))
) {
Text(
text = comic!!.comic.author,
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
color = Color.Black,
maxLines = 1,
modifier = Modifier.padding(4.dp)
)
@@ -83,13 +82,12 @@ fun ComicGridView(comicId: String, navController: NavHostController, comicGridVi
Box(
Modifier
.padding(horizontal = 16.dp).padding(top = 4.dp)
.background(Color.White.copy(alpha = 0.65f), shape = RoundedCornerShape(12.dp))
.background(colorScheme.surfaceContainerHighest, shape = RoundedCornerShape(12.dp))
) {
Text(
text = "Tags : ${comic!!.comic.tags.joinToString(", ")}",
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
color = Color.Black,
maxLines = 5,
modifier = Modifier.padding(4.dp)
)
@@ -105,7 +103,7 @@ fun ComicGridView(comicId: String, navController: NavHostController, comicGridVi
Box(
Modifier
.padding(horizontal = 16.dp).padding(top = 6.dp).padding(bottom = 20.dp).heightIn(min = 42.dp)
.background(Color.White.copy(alpha = 0.65f), shape = RoundedCornerShape(12.dp))
.background(colorScheme.surfaceContainerHighest, shape = RoundedCornerShape(12.dp))
.clickable{
comicGridViewModel.updateProcess(comicId.hexToString())
{
@@ -133,7 +131,6 @@ fun ComicGridView(comicId: String, navController: NavHostController, comicGridVi
text = "Last Read Position: ${k.first.name} ${k.second}/${comic!!.getChapterLength(k.first.page)}",
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
color = Color.Black,
maxLines = 1,
modifier = Modifier.padding(4.dp).weight(1f)
)
@@ -142,7 +139,6 @@ fun ComicGridView(comicId: String, navController: NavHostController, comicGridVi
text = "Read from scratch",
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
color = Color.Black,
maxLines = 1,
modifier = Modifier.padding(4.dp).weight(1f)
)

View File

@@ -26,6 +26,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -139,6 +140,7 @@ fun ComicScreen(
comicScreenViewModel.SetupClient()
val included = comicScreenViewModel.included
val state = rememberLazyGridState()
val colorScheme = MaterialTheme.colorScheme
Column {
@@ -154,9 +156,7 @@ fun ComicScreen(
Box(
Modifier
.background(
if (included.contains(i)) Color.Green.copy(alpha = 0.65f) else Color.White.copy(
alpha = 0.65f
),
if (included.contains(i)) Color.Green.copy(alpha = 0.65f) else colorScheme.surfaceContainerHighest,
shape = RoundedCornerShape(4.dp)
)
.height(32.dp).widthIn(max = 72.dp)
@@ -174,8 +174,7 @@ fun ComicScreen(
maxLines = 1,
modifier = Modifier
.padding(2.dp)
.align(Alignment.Center),
color = Color.Black
.align(Alignment.Center)
)
}
}

View File

@@ -26,12 +26,13 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.acitelight.aether.Global
import com.acitelight.aether.Global.updateRelate
import com.acitelight.aether.service.MediaManager
import com.acitelight.aether.service.RecentManager
import com.acitelight.aether.viewModel.HomeScreenViewModel
@Composable
fun HomeScreen(homeScreenViewModel: HomeScreenViewModel = hiltViewModel(), navController: NavController)
fun HomeScreen(homeScreenViewModel: HomeScreenViewModel = androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel<HomeScreenViewModel>(), navController: NavController)
{
if(Global.loggedIn)
homeScreenViewModel.Init()
@@ -42,9 +43,9 @@ fun HomeScreen(homeScreenViewModel: HomeScreenViewModel = hiltViewModel(), navCo
{
Column {
Text(
text = "Recent",
text = "Videos",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(16.dp).align(Alignment.Start)
modifier = Modifier.padding(8.dp).align(Alignment.Start)
)
HorizontalDivider(Modifier.padding(8.dp), 2.dp, DividerDefaults.color)
@@ -56,7 +57,7 @@ fun HomeScreen(homeScreenViewModel: HomeScreenViewModel = hiltViewModel(), navCo
.padding(horizontal = 12.dp),
i,
{
Global.sameClassVideos = RecentManager.recent
updateRelate(RecentManager.recent, i)
val route = "video_player_route/${ "${i.klass}/${i.id}".toHex() }"
navController.navigate(route)
}, homeScreenViewModel.imageLoader!!)

View File

@@ -46,7 +46,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@Composable
fun MeScreen(meScreenViewModel: MeScreenViewModel = hiltViewModel()) {
fun MeScreen(meScreenViewModel: MeScreenViewModel = androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel<MeScreenViewModel>()) {
val context = LocalContext.current
var username by meScreenViewModel.username;
var privateKey by meScreenViewModel.privateKey;
@@ -200,7 +200,7 @@ fun MeScreen(meScreenViewModel: MeScreenViewModel = hiltViewModel()) {
onClick = {
meScreenViewModel.updateServer(url, cert, context)
},
modifier = Modifier.fillMaxWidth(0.5f)
modifier = Modifier.weight(0.5f)
) {
Text("Save")
}
@@ -213,7 +213,7 @@ fun MeScreen(meScreenViewModel: MeScreenViewModel = hiltViewModel()) {
Log.i("Delay Analyze", "Abyss Hello: ${h.string()}")
}
},
modifier = Modifier.fillMaxWidth(0.5f)
modifier = Modifier.weight(0.5f)
) {
Text("Ping")
}

View File

@@ -0,0 +1,150 @@
package com.acitelight.aether.view
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Pause
import androidx.compose.material.icons.filled.Stop
import androidx.compose.material.icons.*
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.PlayArrow
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CardElevation
import androidx.compose.material3.DividerDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProgressIndicatorDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.acitelight.aether.model.DownloadItemState
import com.acitelight.aether.viewModel.TransmissionScreenViewModel
import com.tonyodev.fetch2.Download
import com.tonyodev.fetch2.FetchListener
import com.tonyodev.fetch2.Status
import com.tonyodev.fetch2core.DownloadBlock
@Composable
fun TransmissionScreen(transmissionScreenViewModel: TransmissionScreenViewModel = hiltViewModel<TransmissionScreenViewModel>())
{
val downloads = transmissionScreenViewModel.downloads
Surface(modifier = Modifier.fillMaxWidth()) {
LazyColumn(modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(8.dp)) {
items(downloads, key = { it.id }) { item ->
DownloadCard(
model = item,
onPause = { transmissionScreenViewModel.pause(item.id) },
onResume = { transmissionScreenViewModel.resume(item.id) },
onCancel = { transmissionScreenViewModel.cancel(item.id) },
onDelete = { transmissionScreenViewModel.delete(item.id, true) }
)
}
}
}
}
@Composable
private fun DownloadCard(
model: DownloadItemState,
onPause: () -> Unit,
onResume: () -> Unit,
onCancel: () -> Unit,
onDelete: () -> Unit
) {
Card(
elevation = CardDefaults.cardElevation(4.dp),
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
) {
Column(modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.weight(1f)) {
Text(text = model.fileName, style = MaterialTheme.typography.titleMedium)
Text(text = model.url, style = MaterialTheme.typography.displayMedium, modifier = Modifier.padding(top = 4.dp))
}
// progress percentage
Text(text = "${model.progress}%", modifier = Modifier.padding(start = 8.dp))
}
// progress bar
LinearProgressIndicator(
progress = { model.progress.coerceIn(0, 100) / 100f },
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp, bottom = 8.dp),
color = ProgressIndicatorDefaults.linearColor,
trackColor = ProgressIndicatorDefaults.linearTrackColor,
strokeCap = ProgressIndicatorDefaults.LinearStrokeCap,
)
// action buttons
Row(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
when (model.status) {
Status.DOWNLOADING -> {
Button(onClick = onPause) {
Icon(imageVector = Icons.Default.Pause, contentDescription = "Pause")
Text(text = " Pause", modifier = Modifier.padding(start = 6.dp))
}
Button(onClick = onCancel) {
Icon(imageVector = Icons.Default.Stop, contentDescription = "Cancel")
Text(text = " Cancel", modifier = Modifier.padding(start = 6.dp))
}
}
Status.PAUSED, Status.QUEUED -> {
Button(onClick = onResume) {
Icon(imageVector = Icons.Default.PlayArrow, contentDescription = "Resume")
Text(text = " Resume", modifier = Modifier.padding(start = 6.dp))
}
Button(onClick = onCancel) {
Icon(imageVector = Icons.Default.Stop, contentDescription = "Cancel")
Text(text = " Cancel", modifier = Modifier.padding(start = 6.dp))
}
}
Status.COMPLETED -> {
Button(onClick = onDelete) {
Icon(imageVector = Icons.Default.Delete, contentDescription = "Delete")
Text(text = " Delete", modifier = Modifier.padding(start = 6.dp))
}
}
else -> {
// for FAILED, CANCELLED, REMOVED etc.
Button(onClick = onResume) {
Icon(imageVector = Icons.Default.PlayArrow, contentDescription = "Retry")
Text(text = " Retry", modifier = Modifier.padding(start = 6.dp))
}
Button(onClick = onDelete) {
Icon(imageVector = Icons.Default.Delete, contentDescription = "Delete")
Text(text = " Delete", modifier = Modifier.padding(start = 6.dp))
}
}
}
}
}
}
}

View File

@@ -625,7 +625,7 @@ fun VideoPlayerPortal(videoPlayerViewModel: VideoPlayerViewModel, navController:
{
TabRow (
selectedTabIndex = videoPlayerViewModel.tabIndex,
modifier = Modifier.height(38.dp).fillMaxWidth(0.6f)
modifier = Modifier.height(38.dp)
) {
Tab(
selected = videoPlayerViewModel.tabIndex == 0,
@@ -645,8 +645,6 @@ fun VideoPlayerPortal(videoPlayerViewModel: VideoPlayerViewModel, navController:
LazyColumn(state = listState, modifier = Modifier.fillMaxWidth()) {
item{
HorizontalDivider(Modifier, 2.dp, DividerDefaults.color)
Text(
modifier = Modifier.align(Alignment.Start).padding(horizontal = 12.dp).padding(top = 12.dp),
text = videoPlayerViewModel.video?.video?.name ?: "",

View File

@@ -19,6 +19,7 @@ import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -43,6 +44,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.navigation.NavHostController
import coil3.request.ImageRequest
import com.acitelight.aether.Global
import com.acitelight.aether.Global.updateRelate
import java.nio.charset.Charset
fun String.toHex(): String {
@@ -93,10 +95,10 @@ fun VideoScreen(videoScreenViewModel: VideoScreenViewModel = viewModel(), navCon
fun TopRow(videoScreenViewModel: VideoScreenViewModel)
{
val tabIndex by videoScreenViewModel.tabIndex;
if(videoScreenViewModel.classes.isEmpty()) return
val colorScheme = MaterialTheme.colorScheme
ScrollableTabRow (selectedTabIndex = tabIndex) {
ScrollableTabRow (selectedTabIndex = tabIndex, modifier = Modifier.background(colorScheme.surface)) {
videoScreenViewModel.classes.forEachIndexed { index, title ->
Tab(
selected = tabIndex == index,
@@ -116,7 +118,7 @@ fun VideoCard(video: Video, navController: NavHostController, videoScreenViewMod
.fillMaxWidth()
.wrapContentHeight(),
onClick = {
Global.sameClassVideos = videoScreenViewModel.classesMap[videoScreenViewModel.classes[tabIndex]] ?: mutableStateListOf()
updateRelate(videoScreenViewModel.classesMap[videoScreenViewModel.classes[tabIndex]] ?: mutableStateListOf(), video)
val route = "video_player_route/${ "${video.klass}/${video.id}".toHex() }"
navController.navigate(route)
}
@@ -168,7 +170,7 @@ fun VideoCard(video: Video, navController: NavHostController, videoScreenViewMod
horizontalArrangement = Arrangement.SpaceBetween,
) {
Text("Class", fontSize = 12.sp)
Text("${video.klass}", fontSize = 12.sp)
Text(video.klass, fontSize = 12.sp)
}
}
}