diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 13b9e12..75bad18 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -13,6 +13,7 @@ plugins { alias(libs.plugins.kotlinSerialization) } +val appVersion = "1.0.0" kotlin { /*linuxX64 { binaries { @@ -114,7 +115,7 @@ android { minSdk = libs.versions.android.minSdk.get().toInt() targetSdk = libs.versions.android.targetSdk.get().toInt() versionCode = 1 - versionName = "1.0" + versionName = appVersion } packaging { resources { @@ -143,7 +144,8 @@ compose.desktop { nativeDistributions { targetFormats(TargetFormat.Exe, TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) packageName = "Feufaro" - packageVersion = "1.0.0" + packageVersion = appVersion + jvmArgs("-Dapp.version=$appVersion") modules("java.base", "java.desktop", "jdk.unsupported", "java.naming") windows { diff --git a/composeApp/src/androidMain/kotlin/mg/dot/feufaro/di/AppVersion.kt b/composeApp/src/androidMain/kotlin/mg/dot/feufaro/di/AppVersion.kt new file mode 100644 index 0000000..e74b8b4 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/mg/dot/feufaro/di/AppVersion.kt @@ -0,0 +1,32 @@ +package mg.dot.feufaro.di + +import android.content.pm.PackageManager +import android.os.Build +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext + +@Composable +actual fun rememberAppVersion(): String { + val context = LocalContext.current + + return remember(context) { + try { + val pm = context.packageManager + val packageName = context.packageName + + val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + pm.getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0)) + } else { + @Suppress("DEPRECATION") + pm.getPackageInfo(packageName, 0) + } + + packageInfo.versionName ?: "0.0.0" + } catch (e: Exception) { + println("AppVersion Error: ${e.message}") + e.printStackTrace() + "0.0.0" + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/di/AppVersion.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/di/AppVersion.kt new file mode 100644 index 0000000..3f85889 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/di/AppVersion.kt @@ -0,0 +1,6 @@ +package mg.dot.feufaro.di + +import androidx.compose.runtime.Composable + +@Composable +expect fun rememberAppVersion(): String \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/AboutScreen.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/AboutScreen.kt new file mode 100644 index 0000000..b7023e9 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/AboutScreen.kt @@ -0,0 +1,165 @@ +package mg.dot.feufaro.ui + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.Code +import androidx.compose.material.icons.filled.Email +import androidx.compose.material.icons.filled.Language +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import feufaro.composeapp.generated.resources.Res +import feufaro.composeapp.generated.resources.icon +import mg.dot.feufaro.di.rememberAppVersion +import mg.dot.feufaro.getPlatform +import org.jetbrains.compose.resources.painterResource + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AboutDialog(onDismiss: () -> Unit) { + val platform = getPlatform() + val isAndroid = platform.name.startsWith("Android") + val appVersion = rememberAppVersion() + Dialog( + onDismissRequest = onDismiss, + properties = DialogProperties( + usePlatformDefaultWidth = false + ) + ) { + ElevatedCard( + modifier = Modifier + .fillMaxWidth(if(isAndroid) 0.9f else 0.3f) + .padding(16.dp), + shape = RoundedCornerShape(24.dp), + colors = CardDefaults.elevatedCardColors( + containerColor = MaterialTheme.colorScheme.surface + ), + elevation = CardDefaults.elevatedCardElevation(defaultElevation = 8.dp) + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(24.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.TopEnd) { + IconButton( + onClick = onDismiss, + modifier = Modifier.size(32.dp) + ) { + Icon( + imageVector = Icons.Default.Close, + contentDescription = "Fermer", + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + } + + Surface( + modifier = Modifier.size(100.dp), + shape = CircleShape, + color = MaterialTheme.colorScheme.primary.copy(alpha = 0.5f), + tonalElevation = 4.dp + ) { + Image( + painter = painterResource(Res.drawable.icon), + contentDescription = "Logo Feufaro", + modifier = Modifier + .padding(12.dp) + .clip(CircleShape) + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "Feufaro", + style = MaterialTheme.typography.headlineMedium.copy(fontWeight = FontWeight.Bold), + color = MaterialTheme.colorScheme.primary + ) + + Surface( + color = MaterialTheme.colorScheme.secondaryContainer, + shape = RoundedCornerShape(12.dp), + modifier = Modifier.padding(top = 4.dp, bottom = 16.dp) + ) { + Text( + text = "Version $appVersion", + modifier = Modifier.padding(horizontal = 12.dp, vertical = 4.dp), + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + } + + Text( + text = "L'application pour lire, éditer et analyser vos partitions Solfa. Ecrivez et créez des harmonies, écoutez ses mélodies et organisez votre playlist en toute simplicité.", + style = MaterialTheme.typography.bodyMedium, + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onSurfaceVariant, + lineHeight = 22.sp + ) + + Spacer(modifier = Modifier.height(24.dp)) + HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.5f)) + Spacer(modifier = Modifier.height(16.dp)) + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + InfoIconItem(icon = Icons.Default.Language, label = "Site Web") + InfoIconItem(icon = Icons.Default.Email, label = "Contact") + InfoIconItem(icon = Icons.Default.Code, label = "Licence") + } + + Spacer(modifier = Modifier.height(24.dp)) + + Text( + text = "Fait avec <3", + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.7f) + ) + } + } + } +} + +@Composable +fun InfoIconItem(icon: ImageVector, label: String) { + Column(horizontalAlignment = Alignment.CenterHorizontally) { + IconButton( + onClick = { + + }, + modifier = Modifier + .size(48.dp) + .background(MaterialTheme.colorScheme.surfaceVariant, CircleShape) + ) { + Icon( + imageVector = icon, + contentDescription = label, + tint = MaterialTheme.colorScheme.primary + ) + } + Spacer(modifier = Modifier.height(4.dp)) + Text( + text = label, + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/DrawerUI.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/DrawerUI.kt index 89540d8..da3c775 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/DrawerUI.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/DrawerUI.kt @@ -11,6 +11,7 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.KeyboardArrowLeft import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight @@ -28,18 +29,17 @@ import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.input.pointer.PointerEventType import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.input.VisualTransformation -import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.compose.ui.platform.LocalSoftwareKeyboardController import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.launch @@ -65,6 +65,7 @@ fun MainScreenWithDrawer( ) { val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) var showSettingsDialog by remember { mutableStateOf(false) } + var showAboutDialog by remember { mutableStateOf(false) } val scope = rememberCoroutineScope() val items by sharedScreenModel.drawerItems.collectAsState() @@ -215,6 +216,9 @@ fun MainScreenWithDrawer( }, onSettingsCheck = { showSettingsDialog = true + }, + onAboutCheck = { + showAboutDialog = true } ) }, content = { @@ -262,6 +266,9 @@ fun MainScreenWithDrawer( isAndroid ) } + if (showAboutDialog) { + AboutDialog(onDismiss = { showAboutDialog = false }) + } val favoritePaths by sharedScreenModel.playlistItems.collectAsState() val keyboardController = LocalSoftwareKeyboardController.current diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/Settings.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/Settings.kt index 7ea93f6..a70eae4 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/Settings.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/Settings.kt @@ -76,11 +76,9 @@ fun Settings( val player = sharedScreenModel.mediaPlayer var expandedAudio by remember { mutableStateOf(player?.getCurrentPosition() != 0L) } var expandedGeneral by remember { mutableStateOf(true) } - var expandedPrint by remember { mutableStateOf(false) } fun openExclusive(target: String) { expandedGeneral = (target == "General") - expandedPrint = (target == "Print") expandedAudio = (target == "Audio") } @@ -146,7 +144,11 @@ fun Settings( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - Text("Mode Plein Écran") + Text( + text = "Mode Plein Écran", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurface + ) Switch( checked = isFullScreenEnabled, onCheckedChange = { isChecked -> @@ -165,7 +167,7 @@ fun Settings( ) { Text( text = "Thème Sombre", - style = MaterialTheme.typography.bodyLarge, + style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface ) @@ -205,7 +207,7 @@ fun Settings( ) { Text( text = "Taille de la police", - style = MaterialTheme.typography.bodyLarge, + style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurface ) @@ -341,27 +343,6 @@ fun Settings( } } - SettingsAccordion( - title = "Paramètres Impression", - isExpanded = expandedPrint, - onToggle = { - openExclusive("Print") - } - ) { - Column( - modifier = Modifier.padding(8.dp), - verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - - } - } - } - SettingsAccordion( title = "Paramètres Audio & Nuances", isExpanded = expandedAudio, @@ -402,8 +383,9 @@ fun Settings( } ) Text( - if (isDynamicEnabled) "Désactiver" else "Activer", - fontSize = 15.sp + text = if (isDynamicEnabled) "Désactiver" else "Activer", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurface ) } @@ -696,7 +678,7 @@ fun Settings( ) Text( - text = "Règlage du player", + text = "Règlage du lecteur", style = MaterialTheme.typography.bodyLarge, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.onSurface, @@ -727,9 +709,10 @@ fun Settings( horizontalArrangement = Arrangement.spacedBy(10.dp) ) { if(!isAndroid) { + val countInStat = if (hasCountIn) "Désactiver" else "Activer" Text( - if (hasCountIn) "Désactiver" else "Activer", - fontSize = 15.sp + text = countInStat, + style = MaterialTheme.typography.bodyMedium ) } Switch( diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/SimpleDrawerContent.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/SimpleDrawerContent.kt index 0421814..29e0b13 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/SimpleDrawerContent.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ui/SimpleDrawerContent.kt @@ -3,15 +3,12 @@ package mg.dot.feufaro.ui import SharedScreenModel import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ListAlt @@ -22,10 +19,8 @@ import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.rotate import androidx.compose.ui.draw.scale -import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.text.font.FontWeight @@ -52,7 +47,8 @@ fun SimpleDrawerContent( scope: CoroutineScope, onScannerButtonClick: () -> Unit, onSongSelected: (String) -> Unit, - onSettingsCheck: () -> Unit + onSettingsCheck: () -> Unit, + onAboutCheck: () -> Unit, ) { var searchTxt by remember { mutableStateOf("") } @@ -72,7 +68,6 @@ fun SimpleDrawerContent( val editMode by sharedScreenModel.modeEditor.collectAsState() val chordView by sharedScreenModel.harmonyView.collectAsState() - var state2 by remember { mutableStateOf(false) } ModalDrawerSheet( modifier = Modifier.width(300.dp) ) { @@ -371,6 +366,7 @@ fun SimpleDrawerContent( state = rememberTooltipState() ) { IconButton(onClick = { + onAboutCheck() scope.launch { drawerState.close() } }) { Icon(Icons.Default.Info, contentDescription = null, tint = MaterialTheme.colorScheme.onSecondary) diff --git a/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/di/AppVersion.kt b/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/di/AppVersion.kt new file mode 100644 index 0000000..2b48164 --- /dev/null +++ b/composeApp/src/desktopMain/kotlin/mg/dot/feufaro/di/AppVersion.kt @@ -0,0 +1,10 @@ +package mg.dot.feufaro.di + +import androidx.compose.runtime.Composable + +@Composable +actual fun rememberAppVersion(): String { + return System.getProperty("jpackage.app-version") + ?: System.getProperty("app.version") + ?: "0.0.0" +} \ No newline at end of file