7 Commits

Author SHA1 Message Date
rootacite
9efbcdfe8a [feat] Optional sort, tags folder 2025-10-29 23:53:14 +08:00
rootacite
c3e0a23ed1 [update] Comic sort policy 2025-10-29 20:14:07 +08:00
acite
7be18dd517 [feat] Playlist remember 2025-10-09 11:33:34 +08:00
acite
a13ddbdd87 [feat] Live framework. 2025-10-06 22:54:08 +08:00
acite
390094b8b0 [fix&optimize] Fix the issue of element teleportation in ComicScreen pages 2025-10-02 12:24:26 +08:00
acite
b360724dca [fix] Chapter progress 2025-10-02 01:34:09 +08:00
acite
db8d5ef4d5 [fix] Cover height meansure 2025-10-02 01:20:13 +08:00
15 changed files with 438 additions and 182 deletions

View File

@@ -56,6 +56,7 @@ import com.acitelight.aether.view.pages.ComicGridView
import com.acitelight.aether.view.pages.ComicPageView
import com.acitelight.aether.view.pages.ComicScreen
import com.acitelight.aether.view.pages.HomeScreen
import com.acitelight.aether.view.pages.LiveScreen
import com.acitelight.aether.view.pages.MeScreen
import com.acitelight.aether.view.pages.TransmissionScreen
import com.acitelight.aether.view.pages.VideoPlayer
@@ -179,12 +180,21 @@ fun AppNavigation() {
TransmissionScreen(navigator = navController)
}
}
composable(Screen.Live.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)) }) {
LiveScreen()
}
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(
@@ -246,6 +256,7 @@ fun BottomNavigationBar(navController: NavController) {
Screen.Video,
Screen.Comic,
Screen.Transmission,
Screen.Live,
Screen.Me
) else listOf(
Screen.Video,
@@ -310,6 +321,8 @@ sealed class Screen(val route: String, val icon: ImageVector, val title: String)
data object Comic : Screen("comic_route", Icons.Filled.Image, "Comic")
data object Transmission : Screen("transmission_route",
Icons.AutoMirrored.Filled.CompareArrows, "Transmission")
data object Live : Screen("live_route",
Icons.Filled.LiveTv, "Live")
data object Me : Screen("me_route", Icons.Filled.AccountCircle, "me")
data object VideoPlayer : Screen("video_player_route/{videoId}", Icons.Filled.PlayArrow, "VideoPlayer")
data object ComicGrid : Screen("comic_grid_route/{comicId}", Icons.Filled.PlayArrow, "ComicGrid")

View File

@@ -46,6 +46,9 @@ class ApiClient @Inject constructor(
fun getBase(): String{
return replaceAbyssProtocol(base)
}
fun getDomain(): String = domain
private var base: String = ""
private var domain: String = ""
private var cert: String = ""
@@ -236,7 +239,7 @@ class ApiClient @Inject constructor(
throw Exception("No reachable URL found")
}
domain = selectedUrl.toHttpUrlOrNull()?.host ?: ""
domain = replaceAbyssProtocol(selectedUrl).toHttpUrlOrNull()?.host ?: ""
cert = crt
base = selectedUrl
withContext(Dispatchers.IO)

View File

@@ -156,7 +156,7 @@ class MediaManager @Inject constructor(
{
try{
val j = apiClient.api!!.getComics()
return j
return j.sorted()
}catch (_: Exception)
{
return listOf()

View File

@@ -64,11 +64,11 @@ fun ComicCard(
.diskCacheKey("${comic.id}/cover")
.build(),
contentDescription = null,
imageLoader = comicScreenViewModel.imageLoader!!,
modifier = Modifier
.fillMaxSize()
.clip(RoundedCornerShape(8.dp)),
contentScale = ContentScale.Crop,
contentScale = ContentScale.Fit,
imageLoader = comicScreenViewModel.imageLoader!!,
)
Box(
@@ -100,22 +100,21 @@ fun ComicCard(
}
Text(
text = comic.comic.comic_name,
fontSize = 14.sp,
lineHeight = 17.sp,
fontWeight = FontWeight.Bold,
maxLines = 2,
modifier = Modifier.padding(4.dp)
)
Box(Modifier.padding(4.dp).fillMaxWidth()){
Text(
text = "Id: ${comic.id}",
fontSize = 12.sp,
lineHeight = 14.sp,
fontWeight = FontWeight.Bold,
maxLines = 2,
modifier = Modifier
.padding(4.dp)
.heightIn(min = 14.dp)
)
Text(
text = "Id: ${comic.id}",
fontSize = 10.sp,
lineHeight = 12.sp,
maxLines = 1,
modifier = Modifier.align(Alignment.CenterStart)
modifier = Modifier.padding(4.dp)
)
}
}
}
}

View File

@@ -31,6 +31,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
@@ -52,6 +53,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
@@ -87,6 +89,18 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
val activity = (context as? Activity)!!
val exoPlayer: ExoPlayer = videoPlayerViewModel.player!!
val name by videoPlayerViewModel.currentName
val id by videoPlayerViewModel.currentId
val listState = rememberLazyListState()
val videos = videoPlayerViewModel.videos
LaunchedEffect(id, videos) {
val targetIndex = videos.indexOfFirst { it.id == id }
if (targetIndex >= 0) {
listState.scrollToItem(targetIndex)
}
}
val audioManager = remember { context.getSystemService(Context.AUDIO_SERVICE) as AudioManager }
val maxVolume = remember { audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) }
var volFactor by remember {
@@ -95,9 +109,6 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
)
}
val name by videoPlayerViewModel.currentName
val id by videoPlayerViewModel.currentId
fun setVolume(value: Int) {
audioManager.setStreamVolume(
AudioManager.STREAM_MUSIC,
@@ -229,7 +240,9 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
}
}
},
modifier = Modifier.fillMaxWidth()
modifier = Modifier
.align(Alignment.Center)
.fillMaxWidth()
)
}
@@ -588,7 +601,7 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) {
colors = CardDefaults.cardColors(containerColor = colorScheme.surface.copy(0.75f))
)
{
LazyColumn(contentPadding = PaddingValues(vertical = 4.dp)) {
LazyColumn(state = listState, contentPadding = PaddingValues(vertical = 4.dp)) {
items(videoPlayerViewModel.videos) { item ->
MiniPlaylistCard(Modifier.padding(4.dp), video = item, imageLoader = videoPlayerViewModel.imageLoader!!,
selected = id == item.id, apiClient = videoPlayerViewModel.apiClient)

View File

@@ -260,7 +260,7 @@ fun VideoPlayerPortal(
playList.add("${i.klass}/${i.id}")
}
val route = "video_player_route/${playList.joinToString(",").toHex()}"
val route = "video_player_route/${(playList.joinToString(",") + "|${i.id}").toHex()}"
navController.navigate(route)
}
HorizontalDivider(

View File

@@ -95,8 +95,9 @@ fun ComicGridView(
}
}
LaunchedEffect(Unit) {
comicGridViewModel.coverHeight = screenHeight * 0.4f
LaunchedEffect(comicGridViewModel) {
comicGridViewModel.coverHeight = screenHeight * 0.3f
if(comicGridViewModel.maxHeight == 0.dp)
comicGridViewModel.maxHeight = screenHeight * 0.8f
}
@@ -251,7 +252,7 @@ fun ComicGridView(
fontSize = 11.sp,
lineHeight = 15.sp,
maxLines = 3,
modifier = Modifier.padding(horizontal = 16.dp).padding(bottom = 4.dp)
modifier = Modifier.padding(horizontal = 16.dp).padding(bottom = 4.dp).align(Alignment.CenterStart)
)
Button(onClick = {
@@ -378,10 +379,10 @@ fun ChapterCard(
{
Text(
text = chapter.name,
fontSize = 14.sp,
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
maxLines = 2,
lineHeight = 16.sp,
lineHeight = 18.sp,
modifier = Modifier
.padding(horizontal = 8.dp).padding(vertical = 4.dp)
.background(Color.Transparent)
@@ -390,7 +391,6 @@ fun ChapterCard(
text = "${comic.getChapterLength(chapter.page)} Pages",
fontSize = 14.sp,
lineHeight = 16.sp,
fontWeight = FontWeight.Bold,
maxLines = 1,
modifier = Modifier
.padding(horizontal = 8.dp)

View File

@@ -5,15 +5,18 @@ import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyRow
@@ -36,7 +39,9 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
@@ -50,6 +55,7 @@ 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.BiliMiniSlider
import com.acitelight.aether.view.components.BookmarkPop
import com.acitelight.aether.viewModel.ComicPageViewModel
import kotlinx.coroutines.launch
@@ -92,7 +98,9 @@ fun ComicPageView(
.fillMaxSize()
.align(Alignment.Center)
.background(Color.Black)
.clickable {
.pointerInput(Unit) {
detectTapGestures(
onTap = {
showPlane = !showPlane
if (showPlane) {
comicPageViewModel.viewModelScope.launch {
@@ -100,6 +108,8 @@ fun ComicPageView(
}
}
}
)
}
) { page ->
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
@@ -123,29 +133,29 @@ fun ComicPageView(
modifier = Modifier
.align(Alignment.TopCenter)
) {
Box()
{
Column(Modifier
.align(Alignment.TopCenter)
.fillMaxWidth())
{
Card(
colors = CardDefaults.cardColors(containerColor = colorScheme.primary),
shape = RoundedCornerShape(12.dp),
modifier = Modifier
.fillMaxWidth()
.padding(top = 18.dp)
.padding(horizontal = 12.dp)
.height(42.dp)
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.Black.copy(alpha = 0.9f),
Color.Transparent,
)
)
))
{
Row(modifier = Modifier.fillMaxSize())
Row(modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp).padding(top = 16.dp))
{
Text(
text = title,
fontSize = 16.sp,
lineHeight = 19.sp,
fontWeight = FontWeight.Bold,
maxLines = 1,
color = Color.White,
modifier = Modifier
.padding(8.dp)
.padding(horizontal = 10.dp)
@@ -155,27 +165,19 @@ fun ComicPageView(
Text(
text = "${pagerState.currentPage + 1}/${pagerState.pageCount}",
fontSize = 18.sp,
fontSize = 16.sp,
lineHeight = 19.sp,
fontWeight = FontWeight.Bold,
maxLines = 1,
color = Color.White,
modifier = Modifier
.padding(8.dp)
.widthIn(min = 60.dp)
.align(Alignment.CenterVertically)
)
}
}
Box(Modifier.fillMaxWidth()) {
Card(
modifier = Modifier
.align(Alignment.CenterStart)
.padding(top = 6.dp)
.padding(horizontal = 12.dp)
.height(42.dp),
colors = CardDefaults.cardColors(containerColor = colorScheme.primary),
shape = RoundedCornerShape(12.dp)
)
Box(Modifier.fillMaxWidth()
.padding(horizontal = 16.dp))
{
Row {
val k = it.getPageChapterIndex(pagerState.currentPage)
@@ -184,6 +186,7 @@ fun ComicPageView(
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
maxLines = 1,
color = Color.White,
modifier = Modifier
.padding(8.dp)
.padding(horizontal = 10.dp)
@@ -195,13 +198,13 @@ fun ComicPageView(
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
maxLines = 1,
color = Color.White,
modifier = Modifier
.padding(8.dp)
.widthIn(min = 60.dp)
.align(Alignment.CenterVertically)
)
}
}
Card(
@@ -210,7 +213,7 @@ fun ComicPageView(
.padding(top = 6.dp)
.padding(horizontal = 12.dp)
.height(42.dp),
colors = CardDefaults.cardColors(containerColor = colorScheme.primary),
colors = CardDefaults.cardColors(containerColor = colorScheme.surface),
shape = RoundedCornerShape(12.dp)
)
{
@@ -226,7 +229,7 @@ fun ComicPageView(
}
}
}
}
Spacer(Modifier.height(64.dp))
}
}
@@ -238,15 +241,24 @@ fun ComicPageView(
.align(Alignment.BottomCenter)
)
{
Box {
val k = it.getPageChapterIndex(pagerState.currentPage)
Column(Modifier
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.Transparent,
Color.Black.copy(alpha = 0.9f),
)
)
)) {
Spacer(Modifier.height(42.dp))
LazyRow(
horizontalArrangement = Arrangement.spacedBy(5.dp),
state = comicPageViewModel.listState!!, modifier = Modifier
.fillMaxWidth()
.padding(bottom = 18.dp)
.padding(bottom = 1.dp)
.padding(horizontal = 12.dp)
.height(180.dp)
.align(Alignment.BottomCenter)
)
{
items(comicPageViewModel.pageList.size)
@@ -262,7 +274,7 @@ fun ComicPageView(
pagerState.requestScrollToPage(page = r)
}
) {
Box(Modifier.padding(1.dp))
Box(Modifier.padding(0.dp))
{
AsyncImage(
model = ImageRequest.Builder(LocalContext.current)
@@ -306,6 +318,20 @@ fun ComicPageView(
}
}
}
BiliMiniSlider(
value = (k.second.toInt()) / it.getChapterLength(k.first.page).toFloat(),
modifier = Modifier
.height(6.dp)
.fillMaxWidth().padding(horizontal = 24.dp)
.fillMaxWidth(),
onValueChange = {
}
)
Spacer(Modifier.height(24.dp))
}
}
}

View File

@@ -1,5 +1,11 @@
package com.acitelight.aether.view.pages
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@@ -27,13 +33,21 @@ 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.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
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
@@ -122,6 +136,7 @@ fun VariableGrid(
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ComicScreen(
navController: NavHostController,
@@ -131,11 +146,18 @@ fun ComicScreen(
val state = rememberLazyStaggeredGridState()
val colorScheme = MaterialTheme.colorScheme
var searchFilter by comicScreenViewModel.searchFilter
var isTagsVisible by remember { mutableStateOf(false) }
var sortType by remember { mutableIntStateOf(0) }
Column {
Row(Modifier
Column(
modifier = Modifier.animateContentSize()
) {
Row(
Modifier
.padding(4.dp)
.align(Alignment.CenterHorizontally)) {
.align(Alignment.CenterHorizontally)
)
{
Text(
text = "Comics",
style = MaterialTheme.typography.headlineMedium,
@@ -149,7 +171,7 @@ fun ComicScreen(
.align(Alignment.CenterVertically)
.height(36.dp)
.widthIn(max = 240.dp)
.background(colorScheme.primary, RoundedCornerShape(8.dp))
.background(colorScheme.surface, RoundedCornerShape(8.dp))
.padding(horizontal = 6.dp)
) {
Icon(
@@ -174,11 +196,76 @@ fun ComicScreen(
}
}
Row {
Text(
text = "Sorted by: ",
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
modifier = Modifier.padding(horizontal = 6.dp).align(Alignment.CenterVertically)
)
RadioButton(
selected = (sortType == 0),
onClick = { sortType = 0 },
modifier = Modifier.align(Alignment.CenterVertically).size(24.dp)
)
Text(
text = "Id",
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
modifier = Modifier.align(Alignment.CenterVertically).padding(3.dp)
)
Spacer(modifier = Modifier.width(12.dp))
RadioButton(
selected = (sortType == 1),
onClick = { sortType = 1 },
modifier = Modifier.align(Alignment.CenterVertically).size(24.dp)
)
Text(
text = "Name",
fontWeight = FontWeight.Bold,
fontSize = 16.sp,
modifier = Modifier.align(Alignment.CenterVertically).padding(3.dp)
)
Spacer(modifier = Modifier.width(12.dp))
Spacer(Modifier.weight(1f))
Card(
shape = RoundedCornerShape(8.dp),
colors = CardDefaults.cardColors(containerColor = colorScheme.surface),
modifier = Modifier
.align(Alignment.CenterVertically)
.padding(horizontal = 4.dp)
.padding(vertical = 4.dp)
.height(32.dp)
.width(64.dp),
onClick = {
isTagsVisible = !isTagsVisible
})
{
Row(Modifier.fillMaxSize())
{
Text(text = "Tags", fontWeight = FontWeight.Bold, fontSize = 16.sp, modifier = Modifier.align(Alignment.CenterVertically).padding(start = 5.dp))
ExposedDropdownMenuDefaults.TrailingIcon(expanded = isTagsVisible, modifier = Modifier.align(Alignment.CenterVertically).padding(end = 5.dp))
}
}
}
HorizontalDivider(Modifier.padding(1.dp), thickness = 1.5.dp)
AnimatedVisibility(
visible = isTagsVisible,
enter = expandVertically(expandFrom = Alignment.Top) + fadeIn(),
exit = shrinkVertically(shrinkTowards = Alignment.Top) + fadeOut()
) {
Column {
VariableGrid(
modifier = Modifier
.heightIn(max = 88.dp)
.heightIn(max = 80.dp)
.padding(4.dp),
rowHeight = 32.dp
rowHeight = 30.dp
)
{
for (i in comicScreenViewModel.tags) {
@@ -189,7 +276,8 @@ fun ComicScreen(
if (included.contains(i)) Color.Green.copy(alpha = 0.65f) else colorScheme.surface,
shape = RoundedCornerShape(4.dp)
)
.height(32.dp).widthIn(max = 72.dp)
.height(32.dp)
.widthIn(max = 72.dp)
.clickable {
if (included.contains(i))
included.remove(i)
@@ -211,6 +299,8 @@ fun ComicScreen(
}
HorizontalDivider(Modifier.padding(1.dp), thickness = 1.5.dp)
}
}
LazyVerticalStaggeredGrid(
columns = StaggeredGridCells.Adaptive(120.dp),
@@ -221,12 +311,23 @@ fun ComicScreen(
modifier = Modifier.fillMaxSize()
) {
items(
items = comicScreenViewModel.comics.filter { searchFilter.isEmpty() || searchFilter in it.comic.comic_name }.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()
}
.sortedByDescending {
when(sortType)
{
0 -> it.id.toInt().toString().padStart(10, '0')
1 -> it.comic.comic_name
else -> it.id
}
},
key = { it.id }
) { comic ->
Box(modifier = Modifier
Box(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
) {

View File

@@ -0,0 +1,13 @@
package com.acitelight.aether.view.pages
import androidx.compose.runtime.Composable
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import com.acitelight.aether.viewModel.LiveScreenViewModel
@Composable
fun LiveScreen(
liveScreenViewModel: LiveScreenViewModel = hiltViewModel<LiveScreenViewModel>()
)
{
}

View File

@@ -15,6 +15,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Key
import androidx.compose.material.icons.filled.Link
import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.Textsms
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.Checkbox
@@ -41,6 +42,7 @@ fun MeScreen(meScreenViewModel: MeScreenViewModel = hiltViewModel<MeScreenViewMo
var privateKey by meScreenViewModel.privateKey
var url by meScreenViewModel.url
var cert by meScreenViewModel.cert
var pak by meScreenViewModel.pak
val uss by meScreenViewModel.uss.collectAsState(initial = false)
@@ -50,7 +52,8 @@ fun MeScreen(meScreenViewModel: MeScreenViewModel = hiltViewModel<MeScreenViewMo
.padding(8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top
) {
)
{
// Card component for a clean, contained UI block
item{
Card(
@@ -196,6 +199,54 @@ fun MeScreen(meScreenViewModel: MeScreenViewModel = hiltViewModel<MeScreenViewMo
}
}
}
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
)
{
Column(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Toolbox",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier
.padding(bottom = 16.dp)
.align(Alignment.Start)
)
Spacer(modifier = Modifier.width(8.dp))
OutlinedTextField(
value = pak,
onValueChange = { pak = it },
label = { Text("Packet") },
leadingIcon = {
Icon(Icons.Default.Textsms, contentDescription = "Packet")
},
singleLine = true,
modifier = Modifier.fillMaxWidth()
)
Spacer(modifier = Modifier.height(8.dp))
Row{
Button(
onClick = {
meScreenViewModel.sendPacket(pak)
},
modifier = Modifier.weight(0.5f).padding(8.dp)
) {
Text("Send")
}
}
}
}
}
}
}

View File

@@ -32,7 +32,7 @@ class ComicGridViewModel @Inject constructor(
) : ViewModel()
{
var coverHeight by mutableStateOf(220.dp)
var maxHeight = 220.dp
var maxHeight = 0.dp
var imageLoader: ImageLoader? = null
var comic = mutableStateOf<Comic?>(null)

View File

@@ -61,7 +61,7 @@ class ComicScreenViewModel @Inject constructor(
val m = mediaManager.queryComicInfoBulk(l)
if(m != null) {
comics.addAll(m.sortedWith(compareBy(naturalOrder()) { it.comic.comic_name }))
comics.addAll(m.sortedBy { it.id.toInt() }.reversed())
tags.addAll(m.flatMap { it.comic.tags }.groupingBy { it }.eachCount()
.entries.sortedByDescending { it.value }
.map { it.key })

View File

@@ -0,0 +1,14 @@
package com.acitelight.aether.viewModel
import androidx.lifecycle.ViewModel
import com.acitelight.aether.service.ApiClient
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class LiveScreenViewModel @Inject constructor(
val apiClient: ApiClient
) : ViewModel(){
}

View File

@@ -18,6 +18,9 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
import javax.inject.Inject
@HiltViewModel
@@ -33,6 +36,7 @@ class MeScreenViewModel @Inject constructor(
val privateKey = mutableStateOf("")
val url = mutableStateOf("")
val cert = mutableStateOf("")
val pak = mutableStateOf("")
val uss = settingsDataStoreManager.useSelfSignedFlow
@@ -108,7 +112,8 @@ class MeScreenViewModel @Inject constructor(
}
}
fun updateAccount(u: String, p: String) {
fun updateAccount(u: String, p: String)
{
viewModelScope.launch {
settingsDataStoreManager.saveUserName(u)
settingsDataStoreManager.savePrivateKey(p)
@@ -142,4 +147,22 @@ class MeScreenViewModel @Inject constructor(
}
}
}
fun sendPacket(p: String)
{
val b = (p + "\r\n").toByteArray(Charsets.UTF_8)
viewModelScope.launch {
withContext(Dispatchers.IO) {
val addr = InetAddress.getByName(apiClient.getDomain())
val socket = DatagramSocket()
val packet = DatagramPacket(
b, b.size, addr, 4096
)
socket.send(packet)
}
}
}
}