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