fixup! Implement desktop builds
This commit is contained in:
parent
7bbbb022e3
commit
6286016da2
7 changed files with 227 additions and 0 deletions
2
desktop/.gitignore
vendored
Normal file
2
desktop/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/build
|
||||||
|
/release
|
21
desktop/.run/desktop.run.xml
Normal file
21
desktop/.run/desktop.run.xml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="desktop" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName"/>
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$"/>
|
||||||
|
<option name="externalSystemIdString" value="GRADLE"/>
|
||||||
|
<option name="scriptParameters" value=""/>
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list/>
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="run"/>
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" value=""/>
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<GradleScriptDebugEnabled>true</GradleScriptDebugEnabled>
|
||||||
|
<method v="2"/>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
69
desktop/build.gradle.kts
Normal file
69
desktop/build.gradle.kts
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("org.jetbrains.compose")
|
||||||
|
java
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.wbrawner.pihelper"
|
||||||
|
version = "1.0-SNAPSHOT"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
|
||||||
|
google()
|
||||||
|
}
|
||||||
|
|
||||||
|
val osName = System.getProperty("os.name")
|
||||||
|
val targetOs = when {
|
||||||
|
osName == "Mac OS X" -> "macos"
|
||||||
|
osName.startsWith("Win") -> "windows"
|
||||||
|
osName.startsWith("Linux") -> "linux"
|
||||||
|
else -> error("Unsupported OS: $osName")
|
||||||
|
}
|
||||||
|
|
||||||
|
val targetArch = when (val osArch = System.getProperty("os.arch")) {
|
||||||
|
"x86_64", "amd64" -> "x64"
|
||||||
|
"aarch64" -> "arm64"
|
||||||
|
else -> error("Unsupported arch: $osArch")
|
||||||
|
}
|
||||||
|
|
||||||
|
val skikoVersion = "0.7.77" // or any more recent version
|
||||||
|
val target = "${targetOs}-${targetArch}"
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Note, if you develop a library, you should use compose.desktop.common.
|
||||||
|
// compose.desktop.currentOs should be used in launcher-sourceSet
|
||||||
|
// (in a separate module for demo project and in testMain).
|
||||||
|
// With compose.desktop.common you will also lose @Preview functionality
|
||||||
|
implementation(project(":shared"))
|
||||||
|
implementation(compose.desktop.currentOs)
|
||||||
|
// implementation("org.jetbrains.skiko:skiko-awt-runtime-$target:$skikoVersion")
|
||||||
|
implementation(libs.kotlinx.coroutines.jvm)
|
||||||
|
implementation("ch.qos.logback:logback-classic:1.4.5")
|
||||||
|
}
|
||||||
|
|
||||||
|
compose.desktop {
|
||||||
|
application {
|
||||||
|
mainClass = "MainKt"
|
||||||
|
|
||||||
|
nativeDistributions {
|
||||||
|
includeAllModules = true
|
||||||
|
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
|
||||||
|
packageName = "Pi-helper"
|
||||||
|
packageVersion = "1.0.0"
|
||||||
|
|
||||||
|
macOS {
|
||||||
|
iconFile.set(project.file("src/main/resources/icon.icns"))
|
||||||
|
}
|
||||||
|
windows {
|
||||||
|
iconFile.set(project.file("icon.ico"))
|
||||||
|
}
|
||||||
|
linux {
|
||||||
|
iconFile.set(project.file("icon.png"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
135
desktop/src/main/kotlin/Main.kt
Normal file
135
desktop/src/main/kotlin/Main.kt
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
|
import androidx.compose.desktop.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.window.Tray
|
||||||
|
import androidx.compose.ui.window.Window
|
||||||
|
import androidx.compose.ui.window.application
|
||||||
|
import androidx.compose.ui.window.rememberTrayState
|
||||||
|
import com.wbrawner.pihelper.shared.*
|
||||||
|
import com.wbrawner.pihelper.shared.State
|
||||||
|
import com.wbrawner.pihelper.shared.ui.AddScreen
|
||||||
|
import com.wbrawner.pihelper.shared.ui.AuthScreen
|
||||||
|
import com.wbrawner.pihelper.shared.ui.InfoScreen
|
||||||
|
import com.wbrawner.pihelper.shared.ui.MainScreen
|
||||||
|
import com.wbrawner.pihelper.shared.ui.theme.PihelperTheme
|
||||||
|
import java.net.InetAddress
|
||||||
|
|
||||||
|
val store = Store(PiholeAPIService.create())
|
||||||
|
|
||||||
|
@OptIn(ExperimentalAnimationApi::class)
|
||||||
|
@Composable
|
||||||
|
@Preview
|
||||||
|
fun App(state: State) {
|
||||||
|
val error by store.effects.collectAsState(Effect.Empty)
|
||||||
|
|
||||||
|
PihelperTheme {
|
||||||
|
when (state.route) {
|
||||||
|
Route.CONNECT -> AddScreen(
|
||||||
|
scanNetwork = {
|
||||||
|
store.dispatch(Action.Scan(InetAddress.getLocalHost().hostAddress))
|
||||||
|
},
|
||||||
|
connectToPihole = { store.dispatch(Action.Connect(it)) },
|
||||||
|
loading = state.loading,
|
||||||
|
error = error as? Effect.Error
|
||||||
|
)
|
||||||
|
|
||||||
|
Route.AUTH -> AuthScreen(store)
|
||||||
|
Route.HOME -> MainScreen(store)
|
||||||
|
Route.ABOUT -> InfoScreen(store)
|
||||||
|
else -> {
|
||||||
|
Text("Not yet implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() = application {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
System.loadLibrary("app/Pi-helper.app/Contents/app/libskiko-macos-arm64.dylib")
|
||||||
|
println("loaded skiko")
|
||||||
|
System.setProperty("apple.awt.enableTemplateImages", "true")
|
||||||
|
}
|
||||||
|
val state by store.state.collectAsState()
|
||||||
|
val trayState = rememberTrayState()
|
||||||
|
var isOpen by remember { mutableStateOf(state.apiKey.isNullOrBlank()) }
|
||||||
|
val statusText = when (val status = state.status) {
|
||||||
|
is Status.Enabled -> "Enabled"
|
||||||
|
is Status.Disabled -> status.timeRemaining?.let { "Disabled (${it})" } ?: "Disabled"
|
||||||
|
else -> "Not connected"
|
||||||
|
}
|
||||||
|
Tray(
|
||||||
|
state = trayState,
|
||||||
|
tooltip = statusText,
|
||||||
|
icon = painterResource("IconTemplate.png"),
|
||||||
|
menu = {
|
||||||
|
Item(
|
||||||
|
text = statusText,
|
||||||
|
enabled = false,
|
||||||
|
onClick = {}
|
||||||
|
)
|
||||||
|
if (state.status is Status.Disabled) {
|
||||||
|
Item(
|
||||||
|
"Enable",
|
||||||
|
onClick = {
|
||||||
|
store.dispatch(Action.Enable)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else if (state.status is Status.Enabled) {
|
||||||
|
Item(
|
||||||
|
"Disable for 10 seconds",
|
||||||
|
onClick = {
|
||||||
|
store.dispatch(Action.Disable(duration = 10))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Item(
|
||||||
|
"Disable for 30 seconds",
|
||||||
|
onClick = {
|
||||||
|
store.dispatch(Action.Disable(duration = 30))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Item(
|
||||||
|
"Disable for 1 minute",
|
||||||
|
onClick = {
|
||||||
|
store.dispatch(Action.Disable(duration = 30))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Item(
|
||||||
|
"Disable for 5 minutes",
|
||||||
|
onClick = {
|
||||||
|
store.dispatch(Action.Disable(duration = 30))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Item(
|
||||||
|
"Disable permanently",
|
||||||
|
onClick = {
|
||||||
|
store.dispatch(Action.Disable())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Item(
|
||||||
|
text = if (isOpen) "Hide window" else "Show window",
|
||||||
|
onClick = {
|
||||||
|
isOpen = !isOpen
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Item(
|
||||||
|
"Exit",
|
||||||
|
onClick = {
|
||||||
|
isOpen = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (isOpen) {
|
||||||
|
Window(
|
||||||
|
title = "Pi-helper",
|
||||||
|
onCloseRequest = {
|
||||||
|
isOpen = false
|
||||||
|
}) {
|
||||||
|
App(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
BIN
desktop/src/main/resources/IconTemplate.png
Normal file
BIN
desktop/src/main/resources/IconTemplate.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
BIN
desktop/src/main/resources/icon.icns
Normal file
BIN
desktop/src/main/resources/icon.icns
Normal file
Binary file not shown.
BIN
desktop/src/main/resources/icon.png
Normal file
BIN
desktop/src/main/resources/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Loading…
Reference in a new issue