Skip to content

Commit

Permalink
Merge pull request #19 from MineInAbyss/main-menu
Browse files Browse the repository at this point in the history
Main menu revamp
  • Loading branch information
0ffz authored Apr 5, 2022
2 parents 80ffc09 + 273d70a commit 17ba20e
Show file tree
Hide file tree
Showing 9 changed files with 426 additions and 156 deletions.
9 changes: 7 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ dependencies {
implementation(kotlin("reflect"))
implementation(files("deps/BrowserLauncher2-all-1_3.jar"))
implementation(compose.desktop.currentOs) {
exclude(group = "org.jetbrains.compose.material", module ="material")
exclude(group = "org.jetbrains.compose.material", module = "material")
}
@OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)
implementation(compose.material3)
Expand All @@ -54,7 +54,11 @@ tasks.withType<KotlinCompile> {
kotlinOptions.freeCompilerArgs = listOf("-opt-in=androidx.compose.material3.ExperimentalMaterial3Api")
}

val appName = "MineInAbyss_Launcher"
val appName = "MineInAbyss_Launcher-" + when {
Os.isFamily(Os.FAMILY_MAC) -> "macOS"
Os.isFamily(Os.FAMILY_WINDOWS) -> "windows"
else -> "linux"
}

compose.desktop {
application {
Expand Down Expand Up @@ -120,6 +124,7 @@ tasks {
val executeAppImageBuilder by registering(Exec::class) {
dependsOn(downloadAppImageBuilder)
dependsOn(copyBuildToPackaging)
environment("ARCH", "x86_64")
commandLine(appImageTool, linuxAppDir, "releases/$appName-${project.version}.AppImage")
}

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
group=com.mineinabyss
version=1.0.4
version=1.1.0
idofrontConventions=1.6.10-51
kotlinVersion=1.6.10
2 changes: 1 addition & 1 deletion packaging/appimage/Mine in Abyss.AppDir/AppRun
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/bin/bash

HERE="$(dirname $"$(readlink -f "${0}")")"
EXEC="${HERE}/usr/bin/MineInAbyss_Launcher"
EXEC="${HERE}/usr/bin/MineInAbyss_Launcher-linux"
exec "${EXEC}"
28 changes: 28 additions & 0 deletions src/main/kotlin/com/mineinabyss/launchy/ColorSchemeGenerator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.mineinabyss.launchy

import androidx.compose.material3.ColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Color
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.memberProperties

@Composable
fun rememberMIAColorScheme(): ColorScheme = remember {
darkColorScheme().also { scheme ->
ColorScheme::class.memberProperties.filterIsInstance<KMutableProperty1<ColorScheme, Color>>()
.filter { "error" !in it.name.toLowerCase() }
.map { prop ->
val col = (prop.get(scheme))
val hsbVals = FloatArray(3)
val javaCol = java.awt.Color(col.red, col.green, col.blue, col.alpha)
java.awt.Color.RGBtoHSB(javaCol.red, javaCol.green, javaCol.blue, hsbVals)
val shiftedColor = Color(java.awt.Color.HSBtoRGB(0.02f, hsbVals[1], hsbVals[2]))
prop.set(
scheme,
col.copy(red = shiftedColor.red, blue = shiftedColor.blue, green = shiftedColor.green)
)
}
}
}
141 changes: 27 additions & 114 deletions src/main/kotlin/com/mineinabyss/launchy/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,108 +3,38 @@ package com.mineinabyss.launchy
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.window.WindowDraggableArea
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Close
import androidx.compose.material.icons.rounded.CropSquare
import androidx.compose.material.icons.rounded.Minimize
import androidx.compose.material3.*
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.*
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowPlacement
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import com.mineinabyss.launchy.data.Config
import com.mineinabyss.launchy.data.Dirs
import com.mineinabyss.launchy.data.Versions
import com.mineinabyss.launchy.logic.LaunchyState
import com.mineinabyss.launchy.ui.screens.MainScreen
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.memberProperties
import com.mineinabyss.launchy.ui.screens.Content

//private val LocalConfigProvider = compositionLocalOf<Config> { error("No local config provided") }
//val LocalConfig: Config
// @Composable
// get() = LocalConfigProvider.current
//
//private val LocalVersionsProvider = compositionLocalOf<Versions> { error("No local versions provided") }
//val LocalVersions: Versions
// @Composable
// get() = LocalVersionsProvider.current
private val LaunchyStateProvider = compositionLocalOf<LaunchyState> { error("No local versions provided") }
val LocalLaunchyState: LaunchyState
@Composable
get() = LaunchyStateProvider.current

@Composable
fun WindowScope.AppWindowTitleBar(
app: ApplicationScope,
state: WindowState,
onCloseRequest: () -> Unit,
) = WindowDraggableArea {
Surface(
Modifier.fillMaxWidth().height(40.dp),
tonalElevation = 1.dp
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround,
) {
Spacer(Modifier.width(15.dp))
Row(
Modifier.weight(1f),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
"Mine in Abyss",
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary
)
}
Row {
WindowButton(Icons.Rounded.Minimize) {
state.isMinimized = true
}
WindowButton(Icons.Rounded.CropSquare) {
if (state.placement != WindowPlacement.Maximized)
state.placement = WindowPlacement.Maximized
else state.placement = WindowPlacement.Floating
}
WindowButton(Icons.Rounded.Close) {
onCloseRequest()
app.exitApplication()
}
}
}
}
}

@Composable
fun WindowButton(icon: ImageVector, onClick: () -> Unit) {
Surface(
onClick = onClick,
modifier = Modifier.fillMaxHeight().width(44.dp),
contentColor = MaterialTheme.colorScheme.primary,
) {
Icon(icon, "", Modifier.padding(10.dp))
}

}

fun main() {
application {
val windowState = rememberWindowState(placement = WindowPlacement.Floating)
val icon = painterResource("mia_profile_icon.png")
// val scaffoldState = rememberScaffoldState()
val launchyState by produceState<LaunchyState?>(null) {
val config = Config.read()
val versions = Versions.readLatest(config.downloadUpdates)
value = LaunchyState(config, versions/*, scaffoldState*/)
value = LaunchyState(config, versions)
}
val onClose: () -> Unit = {
exitApplication()
Expand All @@ -117,41 +47,24 @@ fun main() {
onCloseRequest = onClose,
undecorated = true,
) {

val topBarState = remember { TopBarState(onClose, windowState, this) }
val ready = launchyState != null
val scheme = darkColorScheme()
ColorScheme::class.memberProperties.filterIsInstance<KMutableProperty1<ColorScheme, Color>>()
.filter { "error" !in it.name.toLowerCase() }
.map { prop ->
val col = (prop.get(scheme))
val hsbVals = FloatArray(3)
val javaCol = java.awt.Color(col.red, col.green, col.blue, col.alpha)
java.awt.Color.RGBtoHSB(javaCol.red, javaCol.green, javaCol.blue, hsbVals)
val shiftedColor = Color(java.awt.Color.HSBtoRGB(0.02f, hsbVals[1], hsbVals[2]))
prop.set(
scheme,
col.copy(red = shiftedColor.red, blue = shiftedColor.blue, green = shiftedColor.green)
)
}
MaterialTheme(
colorScheme = scheme
) {
Scaffold(
topBar = {
AppWindowTitleBar(this@application, windowState, onClose)
}
) {
AnimatedVisibility(!ready, exit = fadeOut()) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("Getting latest plugin versions...")
val scheme = rememberMIAColorScheme()
MaterialTheme(colorScheme = scheme) {
CompositionLocalProvider(TopBarProvider provides topBarState) {
Scaffold {
AnimatedVisibility(!ready, exit = fadeOut()) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("Getting latest plugin versions...")
}
}
}
AnimatedVisibility(ready, enter = fadeIn()) {
CompositionLocalProvider(
LaunchyStateProvider provides launchyState!!,
) {
Dirs.createDirs()
MainScreen()
AnimatedVisibility(ready, enter = fadeIn()) {
CompositionLocalProvider(
LaunchyStateProvider provides launchyState!!,
) {
Dirs.createDirs()
Content()
}
}
}
}
Expand Down
93 changes: 93 additions & 0 deletions src/main/kotlin/com/mineinabyss/launchy/TopBar.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.mineinabyss.launchy

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.slideIn
import androidx.compose.animation.slideOut
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.window.WindowDraggableArea
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.Close
import androidx.compose.material.icons.rounded.CropSquare
import androidx.compose.material.icons.rounded.Minimize
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp

@Composable
fun WindowButton(icon: ImageVector, onClick: () -> Unit) {
Surface(
onClick = onClick,
modifier = Modifier.fillMaxHeight().width(44.dp),
contentColor = Color.White,
color = Color.Transparent
) {
Icon(icon, "", Modifier.padding(10.dp))
}
}

@Composable
fun AppTopBar(
state: TopBarState,
transparent: Boolean,
showBackButton: Boolean,
onBackButtonClicked: (() -> Unit),
) = state.windowScope.WindowDraggableArea(
// Modifier.combinedClickable(onDoubleClick = { toggleMaximized(state) }, onClick = {})
) {
Box(
Modifier.fillMaxWidth().height(40.dp)
) {
AnimatedVisibility(
!transparent,
enter = slideIn(initialOffset = { IntOffset(0, -40) }),
exit = slideOut(targetOffset = { IntOffset(0, -40) })
) {
Surface(tonalElevation = 1.dp, modifier = Modifier.fillMaxSize()) {}
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceAround,
) {
Spacer(Modifier.width(5.dp))
Row(
Modifier.weight(1f),
verticalAlignment = Alignment.CenterVertically,
) {
AnimatedVisibility(showBackButton/*, enter = fadeIn(animationSpec = tween(300, 300))*/) {
IconButton(onClick = onBackButtonClicked) {
Icon(Icons.Rounded.ArrowBack, contentDescription = "Back button")
}
Spacer(Modifier.width(5.dp))
}
AnimatedVisibility(!transparent) {
Text(
"Mine in Abyss",
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.primary
)
}
}
Row {
WindowButton(Icons.Rounded.Minimize) {
state.windowState.isMinimized = true
}
WindowButton(Icons.Rounded.CropSquare) {
state.toggleMaximized()
}
WindowButton(Icons.Rounded.Close) {
state.onClose()
}
}
}
}
}
26 changes: 26 additions & 0 deletions src/main/kotlin/com/mineinabyss/launchy/TopBarState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.mineinabyss.launchy

import androidx.compose.runtime.Composable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.window.ApplicationScope
import androidx.compose.ui.window.WindowPlacement
import androidx.compose.ui.window.WindowScope
import androidx.compose.ui.window.WindowState
import com.mineinabyss.launchy.logic.LaunchyState

val TopBarProvider = compositionLocalOf<TopBarState> { error("No top bar provided") }
val TopBar: TopBarState
@Composable
get() = TopBarProvider.current

class TopBarState(
val onClose: () -> Unit,
val windowState: WindowState,
val windowScope: WindowScope,
) {
fun toggleMaximized() {
if (windowState.placement != WindowPlacement.Maximized)
windowState.placement = WindowPlacement.Maximized
else windowState.placement = WindowPlacement.Floating
}
}
Loading

0 comments on commit 17ba20e

Please sign in to comment.