Initial commit
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.window.Window
|
||||
import androidx.compose.ui.window.application
|
||||
import androidx.compose.ui.window.rememberWindowState
|
||||
import data.AliasRepository
|
||||
import data.BufferKey
|
||||
import data.ServerRepository
|
||||
import data.WindowPrefsRepository
|
||||
import irc.ConnectionManager
|
||||
import ui.ChannelWindow
|
||||
import ui.MainScreen
|
||||
import java.io.File
|
||||
|
||||
// Material 3's darkColorScheme() defaults to a purple accent; this keeps everything
|
||||
// (OutlinedTextField borders, Button/TextButton labels, etc.) neutral black-and-white
|
||||
// to match the rest of the app's deliberately plain look, same as the Android version.
|
||||
private val neutralDarkScheme = darkColorScheme(
|
||||
primary = Color.White,
|
||||
onPrimary = Color.Black,
|
||||
secondary = Color.White,
|
||||
onSecondary = Color.Black,
|
||||
background = Color.Black,
|
||||
onBackground = Color.White,
|
||||
surface = Color.Black,
|
||||
onSurface = Color.White,
|
||||
outline = Color.White
|
||||
)
|
||||
|
||||
// All persistence lives under the user's home directory - the desktop analogue of
|
||||
// Android's app-private filesDir, since a desktop app has no sandboxed storage of its own.
|
||||
private val appRoot = File(System.getProperty("user.home"), ".wirc")
|
||||
|
||||
fun main() = application {
|
||||
if (!appRoot.exists()) appRoot.mkdirs()
|
||||
ConnectionManager.init(appRoot)
|
||||
// Loaded once here (not per-window) so the alias map is truly global - every
|
||||
// ChannelWindow's command router reads from this same AliasRepository singleton.
|
||||
AliasRepository.init()
|
||||
|
||||
val repo = remember { ServerRepository(appRoot) }
|
||||
val prefsRepo = remember { WindowPrefsRepository(appRoot) }
|
||||
|
||||
var openBuffers by remember { mutableStateOf(setOf<BufferKey>()) }
|
||||
|
||||
// Full shutdown: same steps /quit (bare, no args) already runs from a channel window -
|
||||
// disconnect every server, then end the process. Shared here so the "Exit wIRC" button
|
||||
// and every channel window's /quit reuse the exact same logic instead of duplicating it.
|
||||
val shutdownApp: () -> Unit = {
|
||||
ConnectionManager.disconnectAll()
|
||||
exitApplication()
|
||||
}
|
||||
|
||||
// Desktop OSes don't kill backgrounded network connections for battery reasons the
|
||||
// way Android does, so there's no foreground-service equivalent needed here -
|
||||
// ConnectionManager's sockets just live for as long as this process runs, and this
|
||||
// listener (which the Android foreground service used to own) can live directly at
|
||||
// the application level instead.
|
||||
LaunchedEffect(Unit) {
|
||||
ConnectionManager.newQueryBuffers.collect { key ->
|
||||
openBuffers = openBuffers + key
|
||||
}
|
||||
}
|
||||
|
||||
// There's no persistent tray/notification surface on this build, so closing the main
|
||||
// server-list window quits the whole app (and every channel window with it) - the
|
||||
// same "closing the primary window ends the session" convention most desktop chat
|
||||
// apps without a tray icon follow.
|
||||
Window(
|
||||
onCloseRequest = ::exitApplication,
|
||||
title = "wIRC - Main",
|
||||
icon = painterResource("icon.png"),
|
||||
state = rememberWindowState()
|
||||
) {
|
||||
MaterialTheme(colorScheme = neutralDarkScheme) {
|
||||
Surface {
|
||||
MainScreen(
|
||||
repo = repo,
|
||||
colorScheme = neutralDarkScheme,
|
||||
onOpenChannel = { serverId, channelName ->
|
||||
openBuffers = openBuffers + BufferKey(serverId, channelName)
|
||||
},
|
||||
onExitApp = shutdownApp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
openBuffers.forEach { bufferKey ->
|
||||
key(bufferKey) {
|
||||
ChannelWindow(
|
||||
bufferKey = bufferKey,
|
||||
prefsRepo = prefsRepo,
|
||||
colorScheme = neutralDarkScheme,
|
||||
onOpenBuffer = { newKey -> openBuffers = openBuffers + newKey },
|
||||
onCloseSelf = { openBuffers = openBuffers - bufferKey },
|
||||
onQuitApp = {
|
||||
exitApplication()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user