Compare commits
	
		
			5 Commits
		
	
	
		
			b360724dca
			...
			main
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 9efbcdfe8a | ||
|   | c3e0a23ed1 | ||
|   | 7be18dd517 | ||
|   | a13ddbdd87 | ||
|   | 390094b8b0 | 
| @@ -56,6 +56,7 @@ import com.acitelight.aether.view.pages.ComicGridView | |||||||
| import com.acitelight.aether.view.pages.ComicPageView | import com.acitelight.aether.view.pages.ComicPageView | ||||||
| import com.acitelight.aether.view.pages.ComicScreen | import com.acitelight.aether.view.pages.ComicScreen | ||||||
| import com.acitelight.aether.view.pages.HomeScreen | 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.MeScreen | ||||||
| import com.acitelight.aether.view.pages.TransmissionScreen | import com.acitelight.aether.view.pages.TransmissionScreen | ||||||
| import com.acitelight.aether.view.pages.VideoPlayer | import com.acitelight.aether.view.pages.VideoPlayer | ||||||
| @@ -179,12 +180,21 @@ fun AppNavigation() { | |||||||
|                     TransmissionScreen(navigator = navController) |                     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, |             composable(Screen.Me.route, | ||||||
|                 enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) }, |                 enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) }, | ||||||
|                 exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) }, |                 exitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.Start, animationSpec = tween(200)) }, | ||||||
|                 popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }, |                 popEnterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }, | ||||||
|                 popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }) { |                 popExitTransition = { slideOutOfContainer(AnimatedContentTransitionScope.SlideDirection.End, animationSpec = tween(200)) }) { | ||||||
|                 MeScreen(); |                 MeScreen() | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             composable( |             composable( | ||||||
| @@ -246,6 +256,7 @@ fun BottomNavigationBar(navController: NavController) { | |||||||
|         Screen.Video, |         Screen.Video, | ||||||
|         Screen.Comic, |         Screen.Comic, | ||||||
|         Screen.Transmission, |         Screen.Transmission, | ||||||
|  |         Screen.Live, | ||||||
|         Screen.Me |         Screen.Me | ||||||
|     ) else  listOf( |     ) else  listOf( | ||||||
|         Screen.Video, |         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 Comic : Screen("comic_route", Icons.Filled.Image, "Comic") | ||||||
|     data object Transmission : Screen("transmission_route", |     data object Transmission : Screen("transmission_route", | ||||||
|         Icons.AutoMirrored.Filled.CompareArrows, "Transmission") |         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 Me : Screen("me_route", Icons.Filled.AccountCircle, "me") | ||||||
|     data object VideoPlayer : Screen("video_player_route/{videoId}", Icons.Filled.PlayArrow, "VideoPlayer") |     data object VideoPlayer : Screen("video_player_route/{videoId}", Icons.Filled.PlayArrow, "VideoPlayer") | ||||||
|     data object ComicGrid : Screen("comic_grid_route/{comicId}", Icons.Filled.PlayArrow, "ComicGrid") |     data object ComicGrid : Screen("comic_grid_route/{comicId}", Icons.Filled.PlayArrow, "ComicGrid") | ||||||
|   | |||||||
| @@ -46,6 +46,9 @@ class ApiClient @Inject constructor( | |||||||
|     fun getBase(): String{ |     fun getBase(): String{ | ||||||
|         return replaceAbyssProtocol(base) |         return replaceAbyssProtocol(base) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     fun getDomain(): String = domain | ||||||
|  |  | ||||||
|     private var base: String = "" |     private var base: String = "" | ||||||
|     private var domain: String = "" |     private var domain: String = "" | ||||||
|     private var cert: String = "" |     private var cert: String = "" | ||||||
| @@ -236,7 +239,7 @@ class ApiClient @Inject constructor( | |||||||
|                 throw Exception("No reachable URL found") |                 throw Exception("No reachable URL found") | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             domain = selectedUrl.toHttpUrlOrNull()?.host ?: "" |             domain = replaceAbyssProtocol(selectedUrl).toHttpUrlOrNull()?.host ?: "" | ||||||
|             cert = crt |             cert = crt | ||||||
|             base = selectedUrl |             base = selectedUrl | ||||||
|             withContext(Dispatchers.IO) |             withContext(Dispatchers.IO) | ||||||
|   | |||||||
| @@ -156,7 +156,7 @@ class MediaManager @Inject constructor( | |||||||
|     { |     { | ||||||
|         try{ |         try{ | ||||||
|             val j = apiClient.api!!.getComics() |             val j = apiClient.api!!.getComics() | ||||||
|             return j |             return j.sorted() | ||||||
|         }catch (_: Exception) |         }catch (_: Exception) | ||||||
|         { |         { | ||||||
|             return listOf() |             return listOf() | ||||||
|   | |||||||
| @@ -64,11 +64,11 @@ fun ComicCard( | |||||||
|                         .diskCacheKey("${comic.id}/cover") |                         .diskCacheKey("${comic.id}/cover") | ||||||
|                         .build(), |                         .build(), | ||||||
|                     contentDescription = null, |                     contentDescription = null, | ||||||
|                     imageLoader = comicScreenViewModel.imageLoader!!, |  | ||||||
|                     modifier = Modifier |                     modifier = Modifier | ||||||
|                         .fillMaxSize() |                         .fillMaxSize() | ||||||
|                         .clip(RoundedCornerShape(8.dp)), |                         .clip(RoundedCornerShape(8.dp)), | ||||||
|                     contentScale = ContentScale.Crop, |                     contentScale = ContentScale.Fit, | ||||||
|  |                     imageLoader = comicScreenViewModel.imageLoader!!, | ||||||
|                 ) |                 ) | ||||||
|  |  | ||||||
|                 Box( |                 Box( | ||||||
| @@ -100,22 +100,21 @@ fun ComicCard( | |||||||
|             } |             } | ||||||
|             Text( |             Text( | ||||||
|                 text = comic.comic.comic_name, |                 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, |                 fontSize = 12.sp, | ||||||
|                 lineHeight = 14.sp, |                 lineHeight = 14.sp, | ||||||
|                     maxLines = 1, |                 fontWeight = FontWeight.Bold, | ||||||
|                     modifier = Modifier.align(Alignment.CenterStart) |                 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.padding(4.dp) | ||||||
|             ) |             ) | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -31,6 +31,7 @@ import androidx.compose.foundation.layout.size | |||||||
| import androidx.compose.foundation.layout.width | import androidx.compose.foundation.layout.width | ||||||
| import androidx.compose.foundation.lazy.LazyColumn | import androidx.compose.foundation.lazy.LazyColumn | ||||||
| import androidx.compose.foundation.lazy.items | import androidx.compose.foundation.lazy.items | ||||||
|  | import androidx.compose.foundation.lazy.rememberLazyListState | ||||||
| import androidx.compose.foundation.shape.RoundedCornerShape | import androidx.compose.foundation.shape.RoundedCornerShape | ||||||
| import androidx.compose.material.icons.Icons | import androidx.compose.material.icons.Icons | ||||||
| import androidx.compose.material.icons.automirrored.filled.ArrowBack | 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.material3.Text | ||||||
| import androidx.compose.runtime.Composable | import androidx.compose.runtime.Composable | ||||||
| import androidx.compose.runtime.DisposableEffect | import androidx.compose.runtime.DisposableEffect | ||||||
|  | import androidx.compose.runtime.LaunchedEffect | ||||||
| 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 | ||||||
| @@ -87,6 +89,18 @@ fun VideoPlayerLandscape(videoPlayerViewModel: VideoPlayerViewModel) { | |||||||
|     val activity = (context as? Activity)!! |     val activity = (context as? Activity)!! | ||||||
|     val exoPlayer: ExoPlayer = videoPlayerViewModel.player!! |     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 audioManager = remember { context.getSystemService(Context.AUDIO_SERVICE) as AudioManager } | ||||||
|     val maxVolume = remember { audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) } |     val maxVolume = remember { audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) } | ||||||
|     var volFactor by remember { |     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) { |     fun setVolume(value: Int) { | ||||||
|         audioManager.setStreamVolume( |         audioManager.setStreamVolume( | ||||||
|             AudioManager.STREAM_MUSIC, |             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)) |                     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 -> |                         items(videoPlayerViewModel.videos) { item -> | ||||||
|                             MiniPlaylistCard(Modifier.padding(4.dp), video = item, imageLoader = videoPlayerViewModel.imageLoader!!, |                             MiniPlaylistCard(Modifier.padding(4.dp), video = item, imageLoader = videoPlayerViewModel.imageLoader!!, | ||||||
|                                 selected = id == item.id, apiClient = videoPlayerViewModel.apiClient) |                                 selected = id == item.id, apiClient = videoPlayerViewModel.apiClient) | ||||||
|   | |||||||
| @@ -260,7 +260,7 @@ fun VideoPlayerPortal( | |||||||
|                             playList.add("${i.klass}/${i.id}") |                             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) |                         navController.navigate(route) | ||||||
|                     } |                     } | ||||||
|                     HorizontalDivider( |                     HorizontalDivider( | ||||||
|   | |||||||
| @@ -96,7 +96,7 @@ fun ComicGridView( | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     LaunchedEffect(comicGridViewModel) { |     LaunchedEffect(comicGridViewModel) { | ||||||
|         comicGridViewModel.coverHeight = screenHeight * 0.4f |         comicGridViewModel.coverHeight = screenHeight * 0.3f | ||||||
|         if(comicGridViewModel.maxHeight == 0.dp) |         if(comicGridViewModel.maxHeight == 0.dp) | ||||||
|             comicGridViewModel.maxHeight = screenHeight * 0.8f |             comicGridViewModel.maxHeight = screenHeight * 0.8f | ||||||
|     } |     } | ||||||
| @@ -252,7 +252,7 @@ fun ComicGridView( | |||||||
|                             fontSize = 11.sp, |                             fontSize = 11.sp, | ||||||
|                             lineHeight = 15.sp, |                             lineHeight = 15.sp, | ||||||
|                             maxLines = 3, |                             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 = { |                         Button(onClick = { | ||||||
| @@ -379,10 +379,10 @@ fun ChapterCard( | |||||||
|         { |         { | ||||||
|             Text( |             Text( | ||||||
|                 text = chapter.name, |                 text = chapter.name, | ||||||
|                 fontSize = 14.sp, |                 fontSize = 16.sp, | ||||||
|                 fontWeight = FontWeight.Bold, |                 fontWeight = FontWeight.Bold, | ||||||
|                 maxLines = 2, |                 maxLines = 2, | ||||||
|                 lineHeight = 16.sp, |                 lineHeight = 18.sp, | ||||||
|                 modifier = Modifier |                 modifier = Modifier | ||||||
|                     .padding(horizontal = 8.dp).padding(vertical = 4.dp) |                     .padding(horizontal = 8.dp).padding(vertical = 4.dp) | ||||||
|                     .background(Color.Transparent) |                     .background(Color.Transparent) | ||||||
| @@ -391,7 +391,6 @@ fun ChapterCard( | |||||||
|                 text = "${comic.getChapterLength(chapter.page)} Pages", |                 text = "${comic.getChapterLength(chapter.page)} Pages", | ||||||
|                 fontSize = 14.sp, |                 fontSize = 14.sp, | ||||||
|                 lineHeight = 16.sp, |                 lineHeight = 16.sp, | ||||||
|                 fontWeight = FontWeight.Bold, |  | ||||||
|                 maxLines = 1, |                 maxLines = 1, | ||||||
|                 modifier = Modifier |                 modifier = Modifier | ||||||
|                     .padding(horizontal = 8.dp) |                     .padding(horizontal = 8.dp) | ||||||
|   | |||||||
| @@ -243,7 +243,15 @@ fun ComicPageView( | |||||||
|             { |             { | ||||||
|                 val k = it.getPageChapterIndex(pagerState.currentPage) |                 val k = it.getPageChapterIndex(pagerState.currentPage) | ||||||
|                 Column(Modifier |                 Column(Modifier | ||||||
|                     .padding(bottom = 24.dp)) { |                     .background( | ||||||
|  |                         brush = Brush.verticalGradient( | ||||||
|  |                             colors = listOf( | ||||||
|  |                                 Color.Transparent, | ||||||
|  |                                 Color.Black.copy(alpha = 0.9f), | ||||||
|  |                             ) | ||||||
|  |                         ) | ||||||
|  |                     )) { | ||||||
|  |                     Spacer(Modifier.height(42.dp)) | ||||||
|                     LazyRow( |                     LazyRow( | ||||||
|                         horizontalArrangement = Arrangement.spacedBy(5.dp), |                         horizontalArrangement = Arrangement.spacedBy(5.dp), | ||||||
|                         state = comicPageViewModel.listState!!, modifier = Modifier |                         state = comicPageViewModel.listState!!, modifier = Modifier | ||||||
| @@ -266,7 +274,7 @@ fun ComicPageView( | |||||||
|                                     pagerState.requestScrollToPage(page = r) |                                     pagerState.requestScrollToPage(page = r) | ||||||
|                                 } |                                 } | ||||||
|                             ) { |                             ) { | ||||||
|                                 Box(Modifier.padding(1.dp)) |                                 Box(Modifier.padding(0.dp)) | ||||||
|                                 { |                                 { | ||||||
|                                     AsyncImage( |                                     AsyncImage( | ||||||
|                                         model = ImageRequest.Builder(LocalContext.current) |                                         model = ImageRequest.Builder(LocalContext.current) | ||||||
| @@ -321,6 +329,9 @@ fun ComicPageView( | |||||||
|  |  | ||||||
|                         } |                         } | ||||||
|                     ) |                     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                     Spacer(Modifier.height(24.dp)) | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -1,5 +1,11 @@ | |||||||
| package com.acitelight.aether.view.pages | 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.background | ||||||
| import androidx.compose.foundation.clickable | import androidx.compose.foundation.clickable | ||||||
| import androidx.compose.foundation.layout.Arrangement | import androidx.compose.foundation.layout.Arrangement | ||||||
| @@ -27,13 +33,21 @@ 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.Icons | ||||||
| import androidx.compose.material.icons.filled.Search | 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.HorizontalDivider | ||||||
| import androidx.compose.material3.Icon | import androidx.compose.material3.Icon | ||||||
| import androidx.compose.material3.LocalTextStyle | import androidx.compose.material3.LocalTextStyle | ||||||
| import androidx.compose.material3.MaterialTheme | import androidx.compose.material3.MaterialTheme | ||||||
|  | import androidx.compose.material3.RadioButton | ||||||
| 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.getValue | ||||||
|  | import androidx.compose.runtime.mutableIntStateOf | ||||||
|  | import androidx.compose.runtime.mutableStateOf | ||||||
|  | import androidx.compose.runtime.remember | ||||||
| import androidx.compose.runtime.setValue | 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 | ||||||
| @@ -122,6 +136,7 @@ fun VariableGrid( | |||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @OptIn(ExperimentalMaterial3Api::class) | ||||||
| @Composable | @Composable | ||||||
| fun ComicScreen( | fun ComicScreen( | ||||||
|     navController: NavHostController, |     navController: NavHostController, | ||||||
| @@ -131,11 +146,18 @@ fun ComicScreen( | |||||||
|     val state = rememberLazyStaggeredGridState() |     val state = rememberLazyStaggeredGridState() | ||||||
|     val colorScheme = MaterialTheme.colorScheme |     val colorScheme = MaterialTheme.colorScheme | ||||||
|     var searchFilter by comicScreenViewModel.searchFilter |     var searchFilter by comicScreenViewModel.searchFilter | ||||||
|  |     var isTagsVisible by remember { mutableStateOf(false) } | ||||||
|  |     var sortType by remember { mutableIntStateOf(0) } | ||||||
|  |  | ||||||
|     Column { |     Column( | ||||||
|         Row(Modifier |         modifier = Modifier.animateContentSize() | ||||||
|  |     ) { | ||||||
|  |         Row( | ||||||
|  |             Modifier | ||||||
|                 .padding(4.dp) |                 .padding(4.dp) | ||||||
|             .align(Alignment.CenterHorizontally)) { |                 .align(Alignment.CenterHorizontally) | ||||||
|  |         ) | ||||||
|  |         { | ||||||
|             Text( |             Text( | ||||||
|                 text = "Comics", |                 text = "Comics", | ||||||
|                 style = MaterialTheme.typography.headlineMedium, |                 style = MaterialTheme.typography.headlineMedium, | ||||||
| @@ -149,7 +171,7 @@ fun ComicScreen( | |||||||
|                     .align(Alignment.CenterVertically) |                     .align(Alignment.CenterVertically) | ||||||
|                     .height(36.dp) |                     .height(36.dp) | ||||||
|                     .widthIn(max = 240.dp) |                     .widthIn(max = 240.dp) | ||||||
|                     .background(colorScheme.primary, RoundedCornerShape(8.dp)) |                     .background(colorScheme.surface, RoundedCornerShape(8.dp)) | ||||||
|                     .padding(horizontal = 6.dp) |                     .padding(horizontal = 6.dp) | ||||||
|             ) { |             ) { | ||||||
|                 Icon( |                 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( |                 VariableGrid( | ||||||
|                     modifier = Modifier |                     modifier = Modifier | ||||||
|                 .heightIn(max = 88.dp) |                         .heightIn(max = 80.dp) | ||||||
|                         .padding(4.dp), |                         .padding(4.dp), | ||||||
|             rowHeight = 32.dp |                     rowHeight = 30.dp | ||||||
|                 ) |                 ) | ||||||
|                 { |                 { | ||||||
|                     for (i in comicScreenViewModel.tags) { |                     for (i in comicScreenViewModel.tags) { | ||||||
| @@ -189,7 +276,8 @@ fun ComicScreen( | |||||||
|                                     if (included.contains(i)) Color.Green.copy(alpha = 0.65f) else colorScheme.surface, |                                     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) | ||||||
|                                 .clickable { |                                 .clickable { | ||||||
|                                     if (included.contains(i)) |                                     if (included.contains(i)) | ||||||
|                                         included.remove(i) |                                         included.remove(i) | ||||||
| @@ -211,6 +299,8 @@ 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(120.dp), |             columns = StaggeredGridCells.Adaptive(120.dp), | ||||||
| @@ -221,12 +311,23 @@ fun ComicScreen( | |||||||
|             modifier = Modifier.fillMaxSize() |             modifier = Modifier.fillMaxSize() | ||||||
|         ) { |         ) { | ||||||
|             items( |             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() |                         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 } |                 key = { it.id } | ||||||
|             ) { comic -> |             ) { comic -> | ||||||
|                 Box(modifier = Modifier |                 Box( | ||||||
|  |                     modifier = Modifier | ||||||
|                         .fillMaxWidth() |                         .fillMaxWidth() | ||||||
|                         .wrapContentHeight() |                         .wrapContentHeight() | ||||||
|                 ) { |                 ) { | ||||||
|   | |||||||
| @@ -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>() | ||||||
|  | ) | ||||||
|  | { | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -15,6 +15,7 @@ import androidx.compose.material.icons.Icons | |||||||
| import androidx.compose.material.icons.filled.Key | import androidx.compose.material.icons.filled.Key | ||||||
| import androidx.compose.material.icons.filled.Link | import androidx.compose.material.icons.filled.Link | ||||||
| import androidx.compose.material.icons.filled.Person | import androidx.compose.material.icons.filled.Person | ||||||
|  | import androidx.compose.material.icons.filled.Textsms | ||||||
| import androidx.compose.material3.Button | import androidx.compose.material3.Button | ||||||
| import androidx.compose.material3.Card | import androidx.compose.material3.Card | ||||||
| import androidx.compose.material3.Checkbox | import androidx.compose.material3.Checkbox | ||||||
| @@ -41,6 +42,7 @@ fun MeScreen(meScreenViewModel: MeScreenViewModel = hiltViewModel<MeScreenViewMo | |||||||
|     var privateKey by meScreenViewModel.privateKey |     var privateKey by meScreenViewModel.privateKey | ||||||
|     var url by meScreenViewModel.url |     var url by meScreenViewModel.url | ||||||
|     var cert by meScreenViewModel.cert |     var cert by meScreenViewModel.cert | ||||||
|  |     var pak by meScreenViewModel.pak | ||||||
|  |  | ||||||
|     val uss by meScreenViewModel.uss.collectAsState(initial = false) |     val uss by meScreenViewModel.uss.collectAsState(initial = false) | ||||||
|  |  | ||||||
| @@ -50,7 +52,8 @@ fun MeScreen(meScreenViewModel: MeScreenViewModel = hiltViewModel<MeScreenViewMo | |||||||
|             .padding(8.dp), |             .padding(8.dp), | ||||||
|         horizontalAlignment = Alignment.CenterHorizontally, |         horizontalAlignment = Alignment.CenterHorizontally, | ||||||
|         verticalArrangement = Arrangement.Top |         verticalArrangement = Arrangement.Top | ||||||
|     ) { |     ) | ||||||
|  |     { | ||||||
|         // Card component for a clean, contained UI block |         // Card component for a clean, contained UI block | ||||||
|         item{ |         item{ | ||||||
|             Card( |             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") | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -61,7 +61,7 @@ class ComicScreenViewModel @Inject constructor( | |||||||
|             val m = mediaManager.queryComicInfoBulk(l) |             val m = mediaManager.queryComicInfoBulk(l) | ||||||
|  |  | ||||||
|             if(m != null) { |             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() |                 tags.addAll(m.flatMap { it.comic.tags }.groupingBy { it }.eachCount() | ||||||
|                     .entries.sortedByDescending { it.value } |                     .entries.sortedByDescending { it.value } | ||||||
|                     .map { it.key }) |                     .map { it.key }) | ||||||
|   | |||||||
| @@ -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(){ | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -18,6 +18,9 @@ import kotlinx.coroutines.Dispatchers | |||||||
| import kotlinx.coroutines.flow.first | import kotlinx.coroutines.flow.first | ||||||
| import kotlinx.coroutines.launch | import kotlinx.coroutines.launch | ||||||
| import kotlinx.coroutines.withContext | import kotlinx.coroutines.withContext | ||||||
|  | import java.net.DatagramPacket | ||||||
|  | import java.net.DatagramSocket | ||||||
|  | import java.net.InetAddress | ||||||
| import javax.inject.Inject | import javax.inject.Inject | ||||||
|  |  | ||||||
| @HiltViewModel | @HiltViewModel | ||||||
| @@ -33,6 +36,7 @@ class MeScreenViewModel @Inject constructor( | |||||||
|     val privateKey = mutableStateOf("") |     val privateKey = mutableStateOf("") | ||||||
|     val url = mutableStateOf("") |     val url = mutableStateOf("") | ||||||
|     val cert = mutableStateOf("") |     val cert = mutableStateOf("") | ||||||
|  |     val pak = mutableStateOf("") | ||||||
|  |  | ||||||
|     val uss = settingsDataStoreManager.useSelfSignedFlow |     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 { |         viewModelScope.launch { | ||||||
|             settingsDataStoreManager.saveUserName(u) |             settingsDataStoreManager.saveUserName(u) | ||||||
|             settingsDataStoreManager.savePrivateKey(p) |             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) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user