Initial commit

This commit is contained in:
2025-06-04 23:42:03 +08:00
commit 6e10240402
48 changed files with 2300 additions and 0 deletions

44
frontend/build.gradle.kts Normal file
View File

@@ -0,0 +1,44 @@
plugins {
autowire(libs.plugins.kotlin.jvm)
autowire(libs.plugins.kotlin.ksp)
autowire(libs.plugins.jetbrains.compose)
autowire(libs.plugins.compose.compiler)
}
group = property.project.groupName
version = property.project.app.version
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlin {
jvmToolchain(17)
sourceSets.all { languageSettings { languageVersion = "2.0" } }
compilerOptions {
freeCompilerArgs = listOf(
"-Xno-param-assertions",
"-Xno-call-assertions",
"-Xno-receiver-assertions"
)
}
}
ksp {
arg("lyricist.generateStringsProperty", "true")
}
compose.desktop {
application {
mainClass = "$group.frontend.AppKt"
}
}
dependencies {
implementation(projects.backend)
implementation(compose.desktop.currentOs)
implementation(compose.material3)
implementation(cafe.adriel.lyricist.lyricist)
ksp(cafe.adriel.lyricist.lyricist.processor)
}

View File

@@ -0,0 +1,66 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.window.application
import com.highcapable.adbrowser.frontend.cl.AppState
import com.highcapable.adbrowser.frontend.cl.LocalAppState
import com.highcapable.adbrowser.frontend.locale.ProvidedLocales
import com.highcapable.adbrowser.frontend.ui.window.MainWindow
import com.highcapable.adbrowser.frontend.ui.window.manager.LocalWindowManager
import com.highcapable.adbrowser.frontend.ui.window.manager.rememberWindowManager
import com.highcapable.adbrowser.frontend.ui.window.manager.windowRegistries
fun main() = runApp()
private fun runApp() = application {
val appState = AppState(application = this)
val windowManager = rememberWindowManager()
CompositionLocalProvider(
LocalAppState provides appState,
LocalWindowManager provides windowManager
) {
ProvidedLocales {
RenderWindows()
}
}
}
@Composable
private fun RenderWindows() {
val appState = LocalAppState.current
val windowManager = LocalWindowManager.current
// Keep the main window always open.
MainWindow(appState.application::exitApplication)
// Render all registered windows.
windowRegistries.forEach {
if (windowManager.isOpen(it.window)) it.content {
windowManager.close(it.window)
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.cl
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.window.ApplicationScope
data class AppState(
val application: ApplicationScope
)
val LocalAppState = compositionLocalOf<AppState> {
error("No AppState provided")
}

View File

@@ -0,0 +1,51 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.locale
import androidx.compose.runtime.Composable
import cafe.adriel.lyricist.ProvideStrings
import cafe.adriel.lyricist.rememberStrings
import java.util.*
object Locales {
const val EN = "en"
const val ZH_CN = "zh-CN"
}
@Composable
fun ProvidedLocales(content: @Composable () -> Unit) {
val lyricist = rememberStrings(
defaultLanguageTag = Locales.EN,
currentLanguageTag = getCurrentLanguageTagFromLocalStorage()
)
ProvideStrings(lyricist, content)
}
private fun getCurrentLanguageTagFromLocalStorage(): String {
// This function should retrieve the current language tag from local storage.
// For now, we return the default language tag.
val locale = Locale.getDefault()
val langRegion = "${locale.language}-${locale.country}" // e.g. "zh-CN"
return langRegion
}

View File

@@ -0,0 +1,32 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.locale.strings
import cafe.adriel.lyricist.LyricistStrings
import com.highcapable.adbrowser.frontend.locale.Locales
@LyricistStrings(languageTag = Locales.EN, default = true)
val EnStrings = Strings(
preferences = "Preferences",
logViewer = "Log Viewer"
)

View File

@@ -0,0 +1,28 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.locale.strings
data class Strings(
val preferences: String,
val logViewer: String
)

View File

@@ -0,0 +1,32 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.locale.strings
import cafe.adriel.lyricist.LyricistStrings
import com.highcapable.adbrowser.frontend.locale.Locales
@LyricistStrings(languageTag = Locales.ZH_CN)
val ZhCNStrings = Strings(
preferences = "偏好设置",
logViewer = "日志查看器"
)

View File

@@ -0,0 +1,33 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.theme
import androidx.compose.ui.graphics.Color
val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)

View File

@@ -0,0 +1,67 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.theme
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun AdbrowserTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
content: @Composable () -> Unit
) {
val colorScheme = when {
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}

View File

@@ -0,0 +1,56 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)

View File

@@ -0,0 +1,50 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.window
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.FrameWindowScope
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.rememberWindowState
import cafe.adriel.lyricist.strings
import com.highcapable.adbrowser.frontend.ui.theme.AdbrowserTheme
@Composable
fun LogViewerWindow(onCloseRequest: () -> Unit) {
Window(
onCloseRequest = onCloseRequest,
title = strings.logViewer,
resizable = false,
state = rememberWindowState(width = 450.dp, height = 600.dp)
) {
AdbrowserTheme {
LogViewerScreen()
}
}
}
@Composable
private fun FrameWindowScope.LogViewerScreen() {
// TODO
}

View File

@@ -0,0 +1,80 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.window
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.FrameWindowScope
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.rememberWindowState
import com.highcapable.adbrowser.frontend.ui.theme.AdbrowserTheme
import com.highcapable.adbrowser.frontend.ui.window.manager.LocalWindowManager
import com.highcapable.adbrowser.generated.AdbrowserProperties
@Composable
fun MainWindow(onCloseRequest: () -> Unit) {
Window(
onCloseRequest = onCloseRequest,
title = AdbrowserProperties.PROJECT_NAME,
state = rememberWindowState(width = 800.dp, height = 600.dp)
) {
AdbrowserTheme {
MainScreen()
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun FrameWindowScope.MainScreen() {
Scaffold(topBar = {
// You don't have to use TopAppBar, it's just to show a simple top app bar.
TopAppBar(title = {
Text(AdbrowserProperties.PROJECT_NAME)
})
}) { innerPaddings ->
// Want to use the window manager to manage windows.
val windowManager = LocalWindowManager.current
Column(
modifier = Modifier
.padding(innerPaddings)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text("WIP")
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.window
import androidx.compose.runtime.Composable
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.FrameWindowScope
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.rememberWindowState
import cafe.adriel.lyricist.strings
import com.highcapable.adbrowser.frontend.ui.theme.AdbrowserTheme
@Composable
fun PreferencesWindow(onCloseRequest: () -> Unit) {
Window(
onCloseRequest = onCloseRequest,
title = strings.preferences,
resizable = false,
state = rememberWindowState(width = 450.dp, height = 600.dp)
) {
AdbrowserTheme {
PreferencesScreen()
}
}
}
@Composable
private fun FrameWindowScope.PreferencesScreen() {
// TODO
}

View File

@@ -0,0 +1,28 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.window.manager
enum class AppWindow {
Preferences,
LogViewer
}

View File

@@ -0,0 +1,52 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.window.manager
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.staticCompositionLocalOf
class WindowManager {
private val _openWindows = mutableStateMapOf<AppWindow, Boolean>()
fun isOpen(window: AppWindow): Boolean = _openWindows[window] == true
fun open(window: AppWindow) {
_openWindows[window] = true
}
fun close(window: AppWindow) {
_openWindows[window] = false
}
val openWindows get() = _openWindows
}
@Composable
fun rememberWindowManager() = remember { WindowManager() }
val LocalWindowManager = staticCompositionLocalOf<WindowManager> {
error("No WindowManager provided")
}

View File

@@ -0,0 +1,40 @@
/*
* Adbrowser - A modern cross-platform Android file manager powered by ADB.
* Copyright (C) 2019 HighCapable
* https://github.com/BetterAndroid/Adbrowser
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
* <p>
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is created by fankes on 2025/6/4.
*/
package com.highcapable.adbrowser.frontend.ui.window.manager
import androidx.compose.runtime.Composable
import com.highcapable.adbrowser.frontend.ui.window.LogViewerWindow
import com.highcapable.adbrowser.frontend.ui.window.PreferencesWindow
data class WindowRegistry(
val window: AppWindow,
val content: @Composable (onCloseRequest: () -> Unit) -> Unit
)
/**
* Registered windows in the application.
*/
val windowRegistries = listOf(
WindowRegistry(AppWindow.Preferences) { PreferencesWindow(it) },
WindowRegistry(AppWindow.LogViewer) { LogViewerWindow(it) }
)