From f91afe6c468f1b49165bd79cfaa07b3a76cdbd63 Mon Sep 17 00:00:00 2001 From: rifsxd Date: Tue, 3 Jun 2025 00:29:02 +0600 Subject: [PATCH] manager: add module background banners" module devs can add banners for their modules through module.prop config Example: banner=https://something.com/banner.png --- .../rifsxd/ksunext/ui/screen/Customization.kt | 18 +- .../com/rifsxd/ksunext/ui/screen/Module.kt | 980 +++++++++--------- .../ksunext/ui/viewmodel/ModuleViewModel.kt | 6 +- manager/app/src/main/res/values/strings.xml | 2 + 4 files changed, 538 insertions(+), 468 deletions(-) diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Customization.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Customization.kt index 86673472..8cdd7a1d 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Customization.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Customization.kt @@ -96,7 +96,7 @@ fun CustomizationScreen(navigator: DestinationsNavigator) { ) } SwitchItem( - icon = Icons.Filled.ColorLens, + icon = Icons.Filled.Dashboard, title = stringResource(id = R.string.settings_legacyui), summary = stringResource(id = R.string.settings_legacyui_summary), checked = useLagacyUI @@ -105,6 +105,22 @@ fun CustomizationScreen(navigator: DestinationsNavigator) { useLagacyUI = it } + var useBanner by rememberSaveable { + mutableStateOf( + prefs.getBoolean("use_banner", true) + ) + } + SwitchItem( + enabled = !useLagacyUI, + icon = Icons.Filled.ViewCarousel, + title = stringResource(id = R.string.settings_banner), + summary = stringResource(id = R.string.settings_banner_summary), + checked = useBanner + ) { + prefs.edit().putBoolean("use_banner", it).apply() + useBanner = it + } + var enableAmoled by rememberSaveable { mutableStateOf( prefs.getBoolean("enable_amoled", false) diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt index 25dee55a..47037cc5 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/screen/Module.kt @@ -1,5 +1,6 @@ package com.rifsxd.ksunext.ui.screen + import android.app.Activity.RESULT_OK import android.content.Context import android.content.Intent @@ -8,6 +9,8 @@ import android.util.Log import android.widget.Toast import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts +import androidx.compose.foundation.background +import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.LocalIndication import androidx.compose.foundation.interaction.MutableInteractionSource @@ -21,6 +24,7 @@ import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.only @@ -68,6 +72,9 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -93,6 +100,7 @@ import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext +import coil.compose.AsyncImage import com.rifsxd.ksunext.Natives import com.rifsxd.ksunext.R import com.rifsxd.ksunext.ksuApp @@ -677,507 +685,548 @@ fun ModuleItem( ElevatedCard( modifier = Modifier.fillMaxWidth() ) { - val textDecoration = if (!module.remove) null else TextDecoration.LineThrough - val interactionSource = remember { MutableInteractionSource() } - val indication = LocalIndication.current - val viewModel = viewModel() + Box( + modifier = Modifier + .fillMaxWidth() + ) { + val context = LocalContext.current + val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) + val useLagacyUI = prefs.getBoolean("use_legacyui", false) - val context = LocalContext.current - val prefs = context.getSharedPreferences("settings", Context.MODE_PRIVATE) + val useBanner = prefs.getBoolean("use_banner", true) - var developerOptionsEnabled by rememberSaveable { - mutableStateOf( - prefs.getBoolean("enable_developer_options", false) - ) - } - - val useLagacyUI = prefs.getBoolean("use_legacyui", false) - - LaunchedEffect(Unit) { - developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false) - } - - if (useLagacyUI) { - Column( - modifier = Modifier - .padding(22.dp, 18.dp, 22.dp, 12.dp) - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, + if (useBanner && !useLagacyUI && module.banner.isNotEmpty()) { + Box( + modifier = Modifier + .matchParentSize(), + contentAlignment = Alignment.Center ) { - val moduleVersion = stringResource(id = R.string.module_version) - val moduleAuthor = stringResource(id = R.string.module_author) - val moduleId = stringResource(id = R.string.module_id) - val moduleVersionCode = stringResource(id = R.string.module_version_code) - val moduleUpdateJson = stringResource(id = R.string.module_update_json) - val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty) - - Column( - modifier = Modifier.fillMaxWidth(0.8f) - ) { - Text( - text = module.name, - fontSize = MaterialTheme.typography.titleMedium.fontSize, - fontWeight = FontWeight.SemiBold, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.titleMedium.fontFamily, - textDecoration = textDecoration, - ) - - Text( - text = "$moduleVersion: ${module.version}", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - - Text( - text = "$moduleAuthor: ${module.author}", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - - if (developerOptionsEnabled) { - - Text( - text = "$moduleId: ${module.id}", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - - Text( - text = "$moduleVersionCode: ${module.versionCode}", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - - Text( - text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - } - } - - Spacer(modifier = Modifier.weight(1f)) - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End, - ) { - Switch( - enabled = !module.update, - checked = module.enabled, - onCheckedChange = onCheckChanged, - interactionSource = if (!module.hasWebUi) interactionSource else null - ) - } - } - - Spacer(modifier = Modifier.height(12.dp)) - - Text( - text = module.description, - fontSize = MaterialTheme.typography.bodySmall.fontSize, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontWeight = MaterialTheme.typography.bodySmall.fontWeight, - overflow = TextOverflow.Ellipsis, - maxLines = 4, - textDecoration = textDecoration - ) - - Spacer(modifier = Modifier.height(16.dp)) - - HorizontalDivider(thickness = Dp.Hairline) - - Spacer(modifier = Modifier.height(4.dp)) - - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - if (module.hasActionScript) { - FilledTonalButton( - modifier = Modifier.defaultMinSize(52.dp, 32.dp), - enabled = !module.remove && module.enabled, - onClick = { - navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId)) - viewModel.markNeedRefresh() - }, - contentPadding = ButtonDefaults.TextButtonContentPadding - ) { - Icon( - modifier = Modifier.size(20.dp), - imageVector = Icons.Outlined.PlayArrow, - contentDescription = null - ) - if (!module.hasWebUi && updateUrl.isEmpty()) { - Text( - modifier = Modifier.padding(start = 7.dp), - text = stringResource(R.string.action), - fontFamily = MaterialTheme.typography.labelMedium.fontFamily, - fontSize = MaterialTheme.typography.labelMedium.fontSize + AsyncImage( + model = module.banner, + contentDescription = null, + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(), + contentScale = ContentScale.Crop, + alpha = 0.18f + ) + Box( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight() + .background( + Brush.verticalGradient( + colors = listOf( + Color.Black.copy(alpha = 0.0f), + Color.Black.copy(alpha = 0.9f) + ), + startY = 0f, + endY = Float.POSITIVE_INFINITY ) - } - } - - Spacer(modifier = Modifier.weight(0.1f, true)) - } - - if (module.hasWebUi) { - FilledTonalButton( - modifier = Modifier.defaultMinSize(52.dp, 32.dp), - enabled = !module.remove && module.enabled, - onClick = { onClick(module) }, - interactionSource = interactionSource, - contentPadding = ButtonDefaults.TextButtonContentPadding - ) { - Icon( - modifier = Modifier.size(20.dp), - imageVector = Icons.AutoMirrored.Outlined.Wysiwyg, - contentDescription = null ) - if (!module.hasActionScript && updateUrl.isEmpty()) { - Text( - modifier = Modifier.padding(start = 7.dp), - fontFamily = MaterialTheme.typography.labelMedium.fontFamily, - fontSize = MaterialTheme.typography.labelMedium.fontSize, - text = stringResource(R.string.open) - ) - } - } - } - - Spacer(modifier = Modifier.weight(1f, true)) - - if (updateUrl.isNotEmpty()) { - Button( - modifier = Modifier.defaultMinSize(52.dp, 32.dp), - enabled = !module.remove, - onClick = { onUpdate(module) }, - shape = ButtonDefaults.textShape, - contentPadding = ButtonDefaults.TextButtonContentPadding - ) { - Icon( - modifier = Modifier.size(20.dp), - imageVector = Icons.Outlined.Download, - contentDescription = null - ) - if (!module.hasActionScript || !module.hasWebUi) { - Text( - modifier = Modifier.padding(start = 7.dp), - fontFamily = MaterialTheme.typography.labelMedium.fontFamily, - fontSize = MaterialTheme.typography.labelMedium.fontSize, - text = stringResource(R.string.module_update) - ) - } - } - - Spacer(modifier = Modifier.weight(0.1f, true)) - } - - if (module.remove) { - FilledTonalButton( - modifier = Modifier.defaultMinSize(52.dp, 32.dp), - onClick = { onRestore(module) }, - contentPadding = ButtonDefaults.TextButtonContentPadding - ) { - Icon( - modifier = Modifier.size(20.dp), - imageVector = Icons.Outlined.Restore, - contentDescription = null - ) - if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) { - Text( - modifier = Modifier.padding(start = 7.dp), - fontFamily = MaterialTheme.typography.labelMedium.fontFamily, - fontSize = MaterialTheme.typography.labelMedium.fontSize, - text = stringResource(R.string.restore) - ) - } - } - } else { - FilledTonalButton( - modifier = Modifier.defaultMinSize(52.dp, 32.dp), - enabled = true, - onClick = { onUninstall(module) }, - contentPadding = ButtonDefaults.TextButtonContentPadding - ) { - Icon( - modifier = Modifier.size(20.dp), - imageVector = Icons.Outlined.Delete, - contentDescription = null - ) - if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) { - Text( - modifier = Modifier.padding(start = 7.dp), - fontFamily = MaterialTheme.typography.labelMedium.fontFamily, - fontSize = MaterialTheme.typography.labelMedium.fontSize, - text = stringResource(R.string.uninstall) - ) - } - } - } + ) } } - } else { - Column( - modifier = Modifier - .padding(22.dp, 18.dp, 22.dp, 12.dp) - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - val moduleVersion = stringResource(id = R.string.module_version) - val moduleAuthor = stringResource(id = R.string.module_author) - val moduleId = stringResource(id = R.string.module_id) - val moduleVersionCode = stringResource(id = R.string.module_version_code) - val moduleUpdateJson = stringResource(id = R.string.module_update_json) - val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty) + Column { + val textDecoration = if (!module.remove) null else TextDecoration.LineThrough + val interactionSource = remember { MutableInteractionSource() } + val indication = LocalIndication.current + val viewModel = viewModel() + + var developerOptionsEnabled by rememberSaveable { + mutableStateOf( + prefs.getBoolean("enable_developer_options", false) + ) + } + + LaunchedEffect(Unit) { + developerOptionsEnabled = prefs.getBoolean("enable_developer_options", false) + } + + if (useLagacyUI) { Column( - modifier = Modifier.fillMaxWidth(0.8f) + modifier = Modifier + .padding(22.dp, 18.dp, 22.dp, 12.dp) ) { Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(6.dp) + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, ) { - LabelItem( - text = formatSize(module.size), - style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( - containerColor = MaterialTheme.colorScheme.secondaryContainer, - contentColor = MaterialTheme.colorScheme.onSecondaryContainer + val moduleVersion = stringResource(id = R.string.module_version) + val moduleAuthor = stringResource(id = R.string.module_author) + val moduleId = stringResource(id = R.string.module_id) + val moduleVersionCode = stringResource(id = R.string.module_version_code) + val moduleUpdateJson = stringResource(id = R.string.module_update_json) + val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty) + + Column( + modifier = Modifier.fillMaxWidth(0.8f) + ) { + Text( + text = module.name, + fontSize = MaterialTheme.typography.titleMedium.fontSize, + fontWeight = FontWeight.SemiBold, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.titleMedium.fontFamily, + textDecoration = textDecoration, ) - ) - LabelItem( - text = if (module.enabled) stringResource(R.string.enabled) else stringResource(R.string.disabled), - style = if (module.enabled) - com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy() - else - com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( - containerColor = MaterialTheme.colorScheme.errorContainer, - contentColor = MaterialTheme.colorScheme.onErrorContainer + + Text( + text = "$moduleVersion: ${module.version}", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + + Text( + text = "$moduleAuthor: ${module.author}", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + + if (developerOptionsEnabled) { + + Text( + text = "$moduleId: ${module.id}", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration ) - ) + + Text( + text = "$moduleVersionCode: ${module.versionCode}", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + + Text( + text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + } + } + + Spacer(modifier = Modifier.weight(1f)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + ) { + Switch( + enabled = !module.update, + checked = module.enabled, + onCheckedChange = onCheckChanged, + interactionSource = if (!module.hasWebUi) interactionSource else null + ) + } + } + + Spacer(modifier = Modifier.height(12.dp)) + + Text( + text = module.description, + fontSize = MaterialTheme.typography.bodySmall.fontSize, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontWeight = MaterialTheme.typography.bodySmall.fontWeight, + overflow = TextOverflow.Ellipsis, + maxLines = 4, + textDecoration = textDecoration + ) + + Spacer(modifier = Modifier.height(16.dp)) + + HorizontalDivider(thickness = Dp.Hairline) + + Spacer(modifier = Modifier.height(4.dp)) + + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + if (module.hasActionScript) { + FilledTonalButton( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + enabled = !module.remove && module.enabled, + onClick = { + navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId)) + viewModel.markNeedRefresh() + }, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.PlayArrow, + contentDescription = null + ) + if (!module.hasWebUi && updateUrl.isEmpty()) { + Text( + modifier = Modifier.padding(start = 7.dp), + text = stringResource(R.string.action), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize + ) + } + } + + Spacer(modifier = Modifier.weight(0.1f, true)) + } + + if (module.hasWebUi) { + FilledTonalButton( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + enabled = !module.remove && module.enabled, + onClick = { onClick(module) }, + interactionSource = interactionSource, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.AutoMirrored.Outlined.Wysiwyg, + contentDescription = null + ) + if (!module.hasActionScript && updateUrl.isEmpty()) { + Text( + modifier = Modifier.padding(start = 7.dp), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize, + text = stringResource(R.string.open) + ) + } + } + } + + Spacer(modifier = Modifier.weight(1f, true)) + + if (updateUrl.isNotEmpty()) { + Button( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + enabled = !module.remove, + onClick = { onUpdate(module) }, + shape = ButtonDefaults.textShape, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.Download, + contentDescription = null + ) + if (!module.hasActionScript || !module.hasWebUi) { + Text( + modifier = Modifier.padding(start = 7.dp), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize, + text = stringResource(R.string.module_update) + ) + } + } + + Spacer(modifier = Modifier.weight(0.1f, true)) + } + if (module.remove) { - LabelItem( - text = stringResource(R.string.uninstalled), - style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( - containerColor = MaterialTheme.colorScheme.errorContainer, - contentColor = MaterialTheme.colorScheme.onErrorContainer + FilledTonalButton( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + onClick = { onRestore(module) }, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.Restore, + contentDescription = null ) - ) - } - if (updateUrl.isNotEmpty() && !module.remove && !module.update) { - LabelItem( - text = stringResource(R.string.module_update), - style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( - containerColor = MaterialTheme.colorScheme.onTertiary, - contentColor = MaterialTheme.colorScheme.onTertiaryContainer - ) - ) - } - if (!module.remove) { - if (module.update) { - LabelItem( - text = stringResource(R.string.module_updated), - style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( - containerColor = MaterialTheme.colorScheme.tertiaryContainer, - contentColor = MaterialTheme.colorScheme.onTertiaryContainer + if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) { + Text( + modifier = Modifier.padding(start = 7.dp), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize, + text = stringResource(R.string.restore) ) + } + } + } else { + FilledTonalButton( + modifier = Modifier.defaultMinSize(52.dp, 32.dp), + enabled = true, + onClick = { onUninstall(module) }, + contentPadding = ButtonDefaults.TextButtonContentPadding + ) { + Icon( + modifier = Modifier.size(20.dp), + imageVector = Icons.Outlined.Delete, + contentDescription = null ) + if (!module.hasActionScript && !module.hasWebUi && updateUrl.isEmpty()) { + Text( + modifier = Modifier.padding(start = 7.dp), + fontFamily = MaterialTheme.typography.labelMedium.fontFamily, + fontSize = MaterialTheme.typography.labelMedium.fontSize, + text = stringResource(R.string.uninstall) + ) + } } } - if (!module.remove) { - if (module.hasWebUi) { + } + } + } else { + Column( + modifier = Modifier + .padding(22.dp, 18.dp, 22.dp, 12.dp) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + val moduleVersion = stringResource(id = R.string.module_version) + val moduleAuthor = stringResource(id = R.string.module_author) + val moduleId = stringResource(id = R.string.module_id) + val moduleVersionCode = stringResource(id = R.string.module_version_code) + val moduleUpdateJson = stringResource(id = R.string.module_update_json) + val moduleUpdateJsonEmpty = stringResource(id = R.string.module_update_json_empty) + + Column( + modifier = Modifier.fillMaxWidth(0.8f) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(6.dp) + ) { LabelItem( - text = stringResource(R.string.webui), - style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( - containerColor = MaterialTheme.colorScheme.primaryContainer, - contentColor = MaterialTheme.colorScheme.onPrimaryContainer - ) - ) - } - if (module.hasActionScript) { - LabelItem( - text = stringResource(R.string.action), + text = formatSize(module.size), style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( containerColor = MaterialTheme.colorScheme.secondaryContainer, contentColor = MaterialTheme.colorScheme.onSecondaryContainer ) ) - } - } - } - - Spacer(modifier = Modifier.height(8.dp)) - - Text( - text = module.name, - fontSize = MaterialTheme.typography.titleMedium.fontSize, - fontWeight = FontWeight.SemiBold, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.titleMedium.fontFamily, - textDecoration = textDecoration, - ) - - Text( - text = "$moduleVersion: ${module.version}", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - - Text( - text = "$moduleAuthor: ${module.author}", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - - if (developerOptionsEnabled) { - - Text( - text = "$moduleId: ${module.id}", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - - Text( - text = "$moduleVersionCode: ${module.versionCode}", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - - Text( - text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty", - fontSize = MaterialTheme.typography.bodySmall.fontSize, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - textDecoration = textDecoration - ) - } - } - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End, - ) { - var expanded by remember { mutableStateOf(false) } - IconButton(onClick = { expanded = true }) { - Icon( - Icons.Filled.MoreVert, - contentDescription = "Module actions" - ) - } - DropdownMenu( - expanded = expanded, - onDismissRequest = { expanded = false } - ) { - if (updateUrl.isNotEmpty() && !module.remove) { - DropdownMenuItem( - text = { Text(stringResource(R.string.module_update)) }, - onClick = { - expanded = false - onUpdate(module) - } - ) - HorizontalDivider() - } - - if (!module.remove) { - if (module.hasWebUi) { - DropdownMenuItem( - text = { Text(stringResource(R.string.webui)) }, - onClick = { - expanded = false - onClick(module) - } + LabelItem( + text = if (module.enabled) stringResource(R.string.enabled) else stringResource(R.string.disabled), + style = if (module.enabled) + com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy() + else + com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( + containerColor = MaterialTheme.colorScheme.errorContainer, + contentColor = MaterialTheme.colorScheme.onErrorContainer + ) ) - } - if (module.hasActionScript) { - DropdownMenuItem( - text = { Text(stringResource(R.string.action)) }, - onClick = { - expanded = false - navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId)) - viewModel.markNeedRefresh() - } - ) - } - - if (module.hasWebUi || module.hasActionScript ) { - HorizontalDivider() - } - } - - if (!module.remove) { - DropdownMenuItem( - text = { - Text( - if (module.enabled) stringResource(R.string.disable) - else stringResource(R.string.enable) + if (module.remove) { + LabelItem( + text = stringResource(R.string.uninstalled), + style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( + containerColor = MaterialTheme.colorScheme.errorContainer, + contentColor = MaterialTheme.colorScheme.onErrorContainer + ) ) - }, - onClick = { - expanded = false - onCheckChanged(!module.enabled) } + if (updateUrl.isNotEmpty() && !module.remove && !module.update) { + LabelItem( + text = stringResource(R.string.module_update), + style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( + containerColor = MaterialTheme.colorScheme.onTertiary, + contentColor = MaterialTheme.colorScheme.onTertiaryContainer + ) + ) + } + if (!module.remove) { + if (module.update) { + LabelItem( + text = stringResource(R.string.module_updated), + style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( + containerColor = MaterialTheme.colorScheme.tertiaryContainer, + contentColor = MaterialTheme.colorScheme.onTertiaryContainer + ) + ) + } + } + if (!module.remove) { + if (module.hasWebUi) { + LabelItem( + text = stringResource(R.string.webui), + style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( + containerColor = MaterialTheme.colorScheme.primaryContainer, + contentColor = MaterialTheme.colorScheme.onPrimaryContainer + ) + ) + } + if (module.hasActionScript) { + LabelItem( + text = stringResource(R.string.action), + style = com.dergoogler.mmrl.ui.component.LabelItemDefaults.style.copy( + containerColor = MaterialTheme.colorScheme.secondaryContainer, + contentColor = MaterialTheme.colorScheme.onSecondaryContainer + ) + ) + } + } + } + + Spacer(modifier = Modifier.height(8.dp)) + + Text( + text = module.name, + fontSize = MaterialTheme.typography.titleMedium.fontSize, + fontWeight = FontWeight.SemiBold, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.titleMedium.fontFamily, + textDecoration = textDecoration, ) + + Text( + text = "$moduleVersion: ${module.version}", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + + Text( + text = "$moduleAuthor: ${module.author}", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + + if (developerOptionsEnabled) { + + Text( + text = "$moduleId: ${module.id}", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + + Text( + text = "$moduleVersionCode: ${module.versionCode}", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + + Text( + text = if (module.updateJson.isNotEmpty()) "$moduleUpdateJson: ${module.updateJson}" else "$moduleUpdateJson: $moduleUpdateJsonEmpty", + fontSize = MaterialTheme.typography.bodySmall.fontSize, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + textDecoration = textDecoration + ) + } } - if (module.remove) { - DropdownMenuItem( - text = { Text(stringResource(R.string.restore)) }, - onClick = { - expanded = false - onRestore(module) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.End, + ) { + var expanded by remember { mutableStateOf(false) } + IconButton(onClick = { expanded = true }) { + Icon( + Icons.Filled.MoreVert, + contentDescription = "Module actions" + ) + } + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false } + ) { + if (updateUrl.isNotEmpty() && !module.remove) { + DropdownMenuItem( + text = { Text(stringResource(R.string.module_update)) }, + onClick = { + expanded = false + onUpdate(module) + } + ) + HorizontalDivider() } - ) - } else { - DropdownMenuItem( - text = { Text(stringResource(R.string.uninstall)) }, - onClick = { - expanded = false - onUninstall(module) + + if (!module.remove) { + if (module.hasWebUi) { + DropdownMenuItem( + text = { Text(stringResource(R.string.webui)) }, + onClick = { + expanded = false + onClick(module) + } + ) + } + if (module.hasActionScript) { + DropdownMenuItem( + text = { Text(stringResource(R.string.action)) }, + onClick = { + expanded = false + navigator.navigate(ExecuteModuleActionScreenDestination(module.dirId)) + viewModel.markNeedRefresh() + } + ) + } + + if (module.hasWebUi || module.hasActionScript ) { + HorizontalDivider() + } } - ) + + if (!module.remove) { + DropdownMenuItem( + text = { + Text( + if (module.enabled) stringResource(R.string.disable) + else stringResource(R.string.enable) + ) + }, + onClick = { + expanded = false + onCheckChanged(!module.enabled) + } + ) + } + if (module.remove) { + DropdownMenuItem( + text = { Text(stringResource(R.string.restore)) }, + onClick = { + expanded = false + onRestore(module) + } + ) + } else { + DropdownMenuItem( + text = { Text(stringResource(R.string.uninstall)) }, + onClick = { + expanded = false + onUninstall(module) + } + ) + } + } } } + + Spacer(modifier = Modifier.height(12.dp)) + + Text( + text = module.description, + fontSize = MaterialTheme.typography.bodySmall.fontSize, + fontFamily = MaterialTheme.typography.bodySmall.fontFamily, + lineHeight = MaterialTheme.typography.bodySmall.lineHeight, + fontWeight = MaterialTheme.typography.bodySmall.fontWeight, + overflow = TextOverflow.Ellipsis, + maxLines = 4, + textDecoration = textDecoration + ) + + Spacer(modifier = Modifier.height(6.dp)) } } - - Spacer(modifier = Modifier.height(12.dp)) - - Text( - text = module.description, - fontSize = MaterialTheme.typography.bodySmall.fontSize, - fontFamily = MaterialTheme.typography.bodySmall.fontFamily, - lineHeight = MaterialTheme.typography.bodySmall.lineHeight, - fontWeight = MaterialTheme.typography.bodySmall.fontWeight, - overflow = TextOverflow.Ellipsis, - maxLines = 4, - textDecoration = textDecoration - ) - - Spacer(modifier = Modifier.height(6.dp)) } } } @@ -1212,7 +1261,8 @@ fun ModuleItemPreview() { hasWebUi = false, hasActionScript = false, dirId = "dirId", - size = 12345678L + size = 12345678L, + banner = "" ) ModuleItem(EmptyDestinationsNavigator, module, "", {}, {}, {}, {}, {}) } diff --git a/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt b/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt index 4a7aafd8..9b878cd6 100644 --- a/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt +++ b/manager/app/src/main/java/com/rifsxd/ksunext/ui/viewmodel/ModuleViewModel.kt @@ -46,7 +46,8 @@ class ModuleViewModel : ViewModel() { val hasWebUi: Boolean, val hasActionScript: Boolean, val dirId: String, - val size: Long + val size: Long, + val banner: String ) data class ModuleUpdateInfo( @@ -142,7 +143,8 @@ class ModuleViewModel : ViewModel() { obj.optBoolean("web"), obj.optBoolean("action"), dirId, - size + size, + obj.optString("banner") ) }.toList() isNeedRefresh = false diff --git a/manager/app/src/main/res/values/strings.xml b/manager/app/src/main/res/values/strings.xml index 485841d3..2839975e 100644 --- a/manager/app/src/main/res/values/strings.xml +++ b/manager/app/src/main/res/values/strings.xml @@ -213,6 +213,8 @@ Language Use Legacy UI Switch to the previous user interface style. + Enable banners + Show background banners for modules. Use WebUI X Use WebUI X instead of WebUI, which supports more APIs. Inject Eruda into WebUI X