Selaa lähdekoodia

wifi pre-implementation

milan jurkulák 2 vuotta sitten
vanhempi
sitoutus
857de36e97

+ 7 - 6
src/main/kotlin/eu/mjdev/desktop/components/appsmenu/AppsMenu.kt

@@ -167,14 +167,15 @@ fun AppsMenu(
                         )
                         val brush = Brush.horizontalGradient(
                             listOf(
-                                backgroundColor.alpha(1f),
-                                backgroundColor.alpha(1f),
-                                backgroundColor.darker(0.3f),
+                                backgroundColor.darker(0.1f),
+                                backgroundColor.darker(0.1f),
+                                backgroundColor.darker(0.1f),
                                 backgroundColor.alpha(0.9f),
-                                backgroundColor.alpha(0.7f)
+                                backgroundColor.alpha(0.7f),
+                                backgroundColor.alpha(0.3f),
                             ),
-                            startX = 0f,
-                            endX = 0f
+//                            startX = 0f,
+//                            endX = 0f
                         )
                         Box(
                             modifier = Modifier.fillMaxWidth()

+ 19 - 8
src/main/kotlin/eu/mjdev/desktop/components/blur/BlurPanel.kt

@@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.runtime.Composable
 import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.BlurredEdgeTreatment
 import androidx.compose.ui.draw.alpha
 import androidx.compose.ui.draw.blur
 import androidx.compose.ui.graphics.Brush
@@ -35,29 +36,39 @@ fun BlurPanel(
     resourceId: String = "blur4.png",
     contentAlignment: Alignment = Alignment.TopStart,
     propagateMinConstraints: Boolean = false,
-    blurRadius: Dp = 20.dp,
+    blurRadius: Dp = 12.dp,
     alpha: Float = 0.3f,
     content: @Composable BoxScope.() -> Unit = {}
 ) = withDesktopScope {
+    val transparentGradientBrush = Brush.linearGradient(
+        colors = listOf(
+            Color(0x66FFFFFF),
+            Color(0x1AFFFFFF)
+        )
+    )
     BoxWithConstraints(
         modifier = modifier,
         contentAlignment = contentAlignment,
         propagateMinConstraints = propagateMinConstraints
     ) {
         ImageAny(
-            modifier = modifier.fillMaxSize().alpha(alpha).blur(blurRadius),
+            modifier = modifier.fillMaxSize()
+                .alpha(alpha)
+                .background(transparentGradientBrush)
+                .blur(blurRadius, edgeTreatment = BlurredEdgeTreatment.Unbounded),
             src = painterResource("images/$resourceId"),
             contentScale = if (maxHeight > maxWidth) ContentScale.FillHeight else ContentScale.FillWidth
         )
         Box(
-            modifier = Modifier.fillMaxSize().background(
-                Brush.radialGradient(
-                    listOf(
-                        Color.Transparent,
-                        backgroundColor.alpha(alpha + 0.2f)
+            modifier = Modifier.fillMaxSize()
+                .background(
+                    Brush.radialGradient(
+                        listOf(
+                            Color.Transparent,
+                            backgroundColor.alpha(alpha + 0.2f)
+                        )
                     )
                 )
-            )
         )
         content()
     }

+ 8 - 8
src/main/kotlin/eu/mjdev/desktop/components/controlcenter/pages/MainSettingsPage.kt

@@ -21,7 +21,6 @@ import eu.mjdev.desktop.components.user.UserAvatar
 import eu.mjdev.desktop.extensions.ColorUtils.alpha
 import eu.mjdev.desktop.extensions.ColorUtils.darker
 import eu.mjdev.desktop.extensions.Compose.runAsync
-import eu.mjdev.desktop.extensions.Modifier.rectShadow
 import eu.mjdev.desktop.helpers.shape.BarShape
 
 @Suppress("FunctionName")
@@ -50,14 +49,16 @@ fun MainSettingsPage() = ControlCenterPage(
                 )
                 val brush = Brush.horizontalGradient(
                     listOf(
-                        backgroundColor.alpha(1f),
-                        backgroundColor.alpha(1f),
-                        backgroundColor.darker(0.3f),
+                        backgroundColor.darker(0.1f),
+                        backgroundColor.darker(0.1f),
+                        backgroundColor.darker(0.1f),
                         backgroundColor.alpha(0.9f),
-                        backgroundColor.alpha(0.7f)
+                        backgroundColor.alpha(0.7f),
+                        backgroundColor.alpha(0.3f),
+                        backgroundColor.darker(0.1f).alpha(0.5f),
                     ),
-                    startX = 0f,
-                    endX = 0f
+//                    startX = 0f,
+//                    endX = 0f
                 )
                 Box(
                     modifier = Modifier
@@ -127,7 +128,6 @@ fun MainSettingsPage() = ControlCenterPage(
                 PowerBlock(
                     backgroundColor = backgroundColor,
                     shadowColor = borderColor.alpha(0.3f),
-                    iconTintColor = iconsTintColor,
                     onPowerButtonClick = {
                         // todo : dialog
                         runAsync {

+ 66 - 40
src/main/kotlin/eu/mjdev/desktop/components/controlcenter/pages/WifiSettingsPage.kt

@@ -1,27 +1,37 @@
 package eu.mjdev.desktop.components.controlcenter.pages
 
 import androidx.compose.desktop.ui.tooling.preview.Preview
+import androidx.compose.foundation.background
 import androidx.compose.foundation.layout.*
 import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.*
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.Wifi
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.collectAsState
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.text.font.FontWeight
 import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.unit.dp
 import eu.mjdev.desktop.components.controlcenter.base.ControlCenterPage
 import eu.mjdev.desktop.components.text.TextAny
+import eu.mjdev.desktop.data.WifiInfo
+import eu.mjdev.desktop.extensions.ColorUtils.alpha
 import eu.mjdev.desktop.extensions.Compose.launchedEffect
 import eu.mjdev.desktop.extensions.Compose.rememberState
+import eu.mjdev.desktop.extensions.Custom.flowBlock
 import eu.mjdev.desktop.helpers.system.Shell
 import eu.mjdev.desktop.helpers.system.Shell.Companion.CMD_NMCLI
+import eu.mjdev.desktop.provider.DesktopScope.Companion.withDesktopScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.delay
-import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.flowOn
+import eu.mjdev.desktop.components.icon.WifiLevelIcon
 
 // nmcli -t -f ALL dev wifi
 // nmcli device show
@@ -32,11 +42,8 @@ fun WifiSettingsPage() = ControlCenterPage(
     condition = { connectionManager.isWifiAdapterAvailable }
 ) {
     var lastSeen by rememberState(0L)
-    val list by flow<List<List<String>>> {
-        Shell.executeAndReadLines(
-            CMD_NMCLI, "-t", " -f", "ALL", "dev", "wifi"
-        ).map { ws ->
-            println(ws)
+    val list by flowBlock {
+        Shell.executeAndReadLines(CMD_NMCLI, "-t", "-f", "ALL", "dev", "wifi").map { ws ->
             ws.split(":")
         }
     }.flowOn(Dispatchers.IO).collectAsState(emptyList())
@@ -48,7 +55,7 @@ fun WifiSettingsPage() = ControlCenterPage(
         ) {
             list.forEach { wr ->
                 item {
-                    WifiRow(wr)
+                    WifiRow(WifiInfo(wr))
                 }
             }
         }
@@ -59,40 +66,59 @@ fun WifiSettingsPage() = ControlCenterPage(
     }
 }
 
-// 0  : AP[n]
-// 1  : ssid
-// 2  : ? 57692D737472656C
-// 3  : IPV6 or IP
-// 4  : ? Infra
-// 5  : freq type
-// 6  : speed
-// 7  : freq
-// 8  : level in db
-// 9  : level semi-graph
-// 10 : encryption
-// 11 : ?
-// 12 : device
-// 14 : ?
-// 15 : connected [*  || ""]
-// 16 : config point
 @Composable
-fun WifiRow(item: List<String>) = Row(
-    modifier = Modifier.fillMaxWidth(),
-) {
-    TextAny(
-        modifier = Modifier.weight(1f),
-        text = item.getOrNull(1).orEmpty(),
-        color = Color.White,
-        textAlign = TextAlign.Start,
-        textSelectionEnabled = true
-    )
-    TextAny(
-        modifier = Modifier.wrapContentWidth(),
-        text = item.getOrNull(9).orEmpty(),
-        color = Color.White,
-        textAlign = TextAlign.Start,
-        textSelectionEnabled = true
-    )
+fun WifiRow(
+    info: WifiInfo
+) = withDesktopScope {
+    Row(
+        modifier = Modifier
+            .padding(4.dp)
+            .fillMaxWidth()
+            .background(
+                Color.White.copy(alpha = 0.1f),
+                RoundedCornerShape(8.dp)
+            )
+            .padding(8.dp),
+        verticalAlignment = Alignment.CenterVertically
+    ) {
+        TextAny(
+            modifier = Modifier.weight(1f),
+            text = info.ssid,
+            color = textColor,
+            fontWeight = FontWeight.Bold,
+            textAlign = TextAlign.Start,
+            singleLine = true,
+            textSelectionEnabled = false
+        )
+        Row(
+            verticalAlignment = Alignment.CenterVertically
+        ) {
+            TextAny(
+                modifier = Modifier.padding(start = 8.dp).wrapContentWidth(),
+                text = info.encryption,
+                fontWeight = FontWeight.Bold,
+                color = textColor,
+                textAlign = TextAlign.Start,
+                singleLine = true,
+                textSelectionEnabled = false
+            )
+            WifiLevelIcon(
+                modifier = Modifier.padding(start = 8.dp).size(28.dp),
+                color = textColor,
+                level = info.signalLevel.toInt()
+            )
+            RadioButton(
+                modifier = Modifier.padding(start = 8.dp).size(24.dp),
+                selected = true,
+                onClick = {},
+                colors = RadioButtonDefaults.colors(
+                    selectedColor = textColor,
+                    unselectedColor = textColor,
+                    disabledColor = textColor.alpha(0.5f)
+                )
+            )
+        }
+    }
 }
 
 @Preview

+ 1 - 3
src/main/kotlin/eu/mjdev/desktop/components/custom/PowerBlock.kt

@@ -26,12 +26,10 @@ import eu.mjdev.desktop.extensions.Modifier.rectShadow
 import eu.mjdev.desktop.helpers.shape.BarShape
 import eu.mjdev.desktop.provider.DesktopScope.Companion.withDesktopScope
 
-// todo shadow? background?
 @Composable
 fun PowerBlock(
     backgroundColor: Color = Color.Transparent,
     shadowColor: Color = Color.Black.copy(alpha = 0.3f),
-    iconTintColor: Color = Color.Black,
     bottomBoxHeight: Dp = 128.dp,
     iconHeight: Dp = 64.dp,
     onPowerButtonClick: () -> Unit = {}
@@ -87,4 +85,4 @@ fun PowerBlock(
 
 @Preview
 @Composable
-fun PowerBlockPreview() = PowerBlock()
+fun PowerBlockPreview() = PowerBlock()

+ 51 - 0
src/main/kotlin/eu/mjdev/desktop/components/icon/WifiLevelIcon.kt

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package  eu.mjdev.desktop.components.icon
+
+import androidx.compose.desktop.ui.tooling.preview.Preview
+import androidx.compose.foundation.layout.size
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.ColorFilter
+import androidx.compose.ui.unit.DpSize
+import androidx.compose.ui.unit.dp
+import eu.mjdev.desktop.components.image.ImageAny
+import eu.mjdev.desktop.extensions.Compose.rememberComputed
+import eu.mjdev.desktop.icons.Icons
+import eu.mjdev.desktop.icons.wifi.level.*
+
+@Composable
+fun WifiLevelIcon(
+    modifier: Modifier = Modifier,
+    level: Int = 55,
+    color: Color = Color.Black,
+    iconSize: DpSize = DpSize(24.dp, 24.dp)
+) {
+    val levelIcon by rememberComputed(level, iconSize) {
+        when {
+            level > 80 -> Icons.Wifi_Level_5
+            level > 60 -> Icons.Wifi_Level_4
+            level > 40 -> Icons.Wifi_Level_3
+            level > 20 -> Icons.Wifi_Level_2
+            level > 10 -> Icons.Wifi_Level_1
+            else -> Icons.Wifi_Level_0
+        }
+    }
+    ImageAny(
+        modifier = modifier.size(iconSize),
+        src = levelIcon,
+        colorFilter = ColorFilter.tint(color)
+    )
+}
+
+@Preview
+@Composable
+fun WifiLevelIconPreview() = WifiLevelIcon()

+ 1 - 0
src/main/kotlin/eu/mjdev/desktop/components/text/TextAny.kt

@@ -17,6 +17,7 @@ import androidx.compose.ui.text.style.TextOverflow
 import androidx.compose.ui.unit.TextUnit
 import eu.mjdev.desktop.extensions.Compose.textFrom
 
+// todo weight does not work when selectable enabled
 @Suppress("FunctionName")
 @Composable
 fun TextAny(

+ 36 - 0
src/main/kotlin/eu/mjdev/desktop/data/WifiInfo.kt

@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.data
+
+data class WifiInfo(
+    val data: List<String> = emptyList(),
+    val id: String = data.getOrNull(0).orEmpty(),
+    val ssid: String = data.getOrNull(1).orEmpty(),
+    val password: String = data.getOrNull(2).orEmpty(),
+    val a0: String = data.getOrNull(3).orEmpty(),
+    val a1: String = data.getOrNull(4).orEmpty(),
+    val a2: String = data.getOrNull(5).orEmpty(),
+    val a3: String = data.getOrNull(6).orEmpty(),
+    val a4: String = data.getOrNull(7).orEmpty(),
+    val a5: String = data.getOrNull(8).orEmpty(),
+    val infra: String = data.getOrNull(9).orEmpty(),
+    val channel: String = data.getOrNull(10).orEmpty(),
+    val frequency: String = data.getOrNull(11).orEmpty(),
+    val speed: String = data.getOrNull(12).orEmpty(),
+    val bandwidth: String = data.getOrNull(13).orEmpty(),
+    val signalLevel: String = data.getOrNull(14).orEmpty(),
+    val signalGraph: String = data.getOrNull(15).orEmpty(),
+    val encryption: String = data.getOrNull(16).orEmpty(),
+    val reserved1: String = data.getOrNull(17).orEmpty(),
+    val encryptionDetails: String = data.getOrNull(18).orEmpty(),
+    val adapter: String = data.getOrNull(19).orEmpty(),
+    val connected: String = data.getOrNull(20).orEmpty(),
+    val reserved2: String = data.getOrNull(21).orEmpty(),
+    val mntp: String = data.getOrNull(17).orEmpty(),
+)

+ 7 - 1
src/main/kotlin/eu/mjdev/desktop/helpers/internal/KeyEventHandler.kt

@@ -15,6 +15,7 @@ import eu.mjdev.desktop.extensions.Custom.isPrintable
 import java.awt.AWTEvent
 import java.awt.Toolkit
 import java.awt.event.AWTEventListener
+import java.awt.event.KeyEvent.VK_TAB
 import java.awt.event.KeyEvent as AwtKeyEvent
 
 @Suppress("CanBeParameter", "unused", "MemberVisibilityCanBePrivate")
@@ -90,7 +91,12 @@ class KeyEventHandler(
 
         override fun eventDispatched(event: AWTEvent?) {
             (event as? AwtKeyEvent)?.also { kev ->
-                if (!event.isConsumed) onKey(kev)
+                val notConsumed = !kev.isConsumed
+                val isAlt = kev.isAltDown
+                val keyCode = kev.keyCode
+                val isAltTab = (isAlt && keyCode == VK_TAB)
+                if (isAltTab) return
+                if (notConsumed) onKey(kev)
             }
         }
     }

+ 34 - 4
src/main/kotlin/eu/mjdev/desktop/helpers/system/Shell.kt

@@ -96,9 +96,14 @@ class Shell(
 
         fun executeAndRead(
             cmd: String,
-            vararg args: String
+            vararg args: String,
+            onError: (Throwable) -> Unit = { e -> e.printStackTrace() }
         ): String = runCatching {
-            Runtime.getRuntime().exec(arrayOf(cmd) + args).apply { waitFor() }
+            Runtime.getRuntime().exec(arrayOf(cmd) + args).apply {
+                waitFor()
+            }.onError { e ->
+                onError(e)
+            }
         }.onFailure { e ->
             e.printStackTrace()
         }.getOrNull()?.inputReader()?.readText().orEmpty()
@@ -106,10 +111,35 @@ class Shell(
         fun executeAndReadLines(
             cmd: String,
             vararg args: String,
+            onError: (Throwable) -> Unit = { e -> e.printStackTrace() }
         ): List<String> = runCatching {
-            Runtime.getRuntime().exec(arrayOf(cmd) + args).apply { waitFor() }
+            Runtime.getRuntime().exec(arrayOf(cmd) + args).apply {
+                waitFor()
+            }.onError { e ->
+                onError(e)
+            }
         }.onFailure { e ->
-            e.printStackTrace()
+            onError(e)
         }.getOrNull()?.inputReader()?.readLines() ?: emptyList()
+
+        fun Process.onText(
+            onText: (String) -> Unit
+        ): Process {
+            if (inputStream.available() > 0) {
+                onText(inputReader().readText())
+            }
+            return this
+        }
+
+        fun Process.onError(
+            onError: (Throwable) -> Unit
+        ): Process {
+            if (errorStream.available() > 0) {
+                onError(RuntimeException(errorReader().readText()))
+            }
+            return this
+        }
     }
 }
+
+

+ 98 - 0
src/main/kotlin/eu/mjdev/desktop/icons/wifi/WifiSettings.kt

@@ -0,0 +1,98 @@
+package eu.mjdev.desktop.icons.wifi
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import eu.mjdev.desktop.icons.Icons
+
+@Suppress("unused")
+val Icons.WifiSettings: ImageVector by lazy(LazyThreadSafetyMode.NONE) {
+    ImageVector.Builder(
+        name = "WifiSettings",
+        defaultWidth = 24.dp,
+        defaultHeight = 24.dp,
+        viewportWidth = 960f,
+        viewportHeight = 960f
+    ).apply {
+        path(fill = SolidColor(Color(0xFFE8EAED))) {
+            moveTo(339f, 698f)
+            quadToRelative(22f, -22f, 49.5f, -36f)
+            reflectiveQuadToRelative(58.5f, -19f)
+            quadToRelative(-5f, 19f, -8f, 38f)
+            reflectiveQuadToRelative(-3f, 39f)
+            quadToRelative(0f, 24f, 3.5f, 47f)
+            reflectiveQuadToRelative(11.5f, 44f)
+            lineTo(339f, 698f)
+            close()
+            moveTo(254f, 614f)
+            lineTo(170f, 528f)
+            quadToRelative(62f, -62f, 142f, -95f)
+            reflectiveQuadToRelative(168f, -33f)
+            quadToRelative(49f, 0f, 96f, 10.5f)
+            reflectiveQuadToRelative(90f, 30.5f)
+            quadToRelative(-44f, 8f, -81.5f, 29f)
+            reflectiveQuadTo(517f, 522f)
+            quadToRelative(-9f, -1f, -18.5f, -1.5f)
+            reflectiveQuadTo(480f, 520f)
+            quadToRelative(-64f, 0f, -122.5f, 24.5f)
+            reflectiveQuadTo(254f, 614f)
+            close()
+            moveTo(84f, 444f)
+            lineTo(0f, 360f)
+            quadToRelative(95f, -97f, 219.5f, -148.5f)
+            reflectiveQuadTo(480f, 160f)
+            quadToRelative(136f, 0f, 260.5f, 51.5f)
+            reflectiveQuadTo(960f, 360f)
+            lineToRelative(-84f, 84f)
+            quadToRelative(-79f, -79f, -181.5f, -121.5f)
+            reflectiveQuadTo(480f, 280f)
+            quadToRelative(-112f, 0f, -214.5f, 42.5f)
+            reflectiveQuadTo(84f, 444f)
+            close()
+            moveTo(760f, 520f)
+            lineTo(772f, 580f)
+            quadToRelative(12f, 5f, 22.5f, 10.5f)
+            reflectiveQuadTo(816f, 604f)
+            lineToRelative(58f, -18f)
+            lineToRelative(40f, 68f)
+            lineToRelative(-46f, 40f)
+            quadToRelative(2f, 12f, 2f, 26f)
+            reflectiveQuadToRelative(-2f, 26f)
+            lineToRelative(46f, 40f)
+            lineToRelative(-40f, 68f)
+            lineToRelative(-58f, -18f)
+            quadToRelative(-11f, 8f, -21.5f, 13.5f)
+            reflectiveQuadTo(772f, 860f)
+            lineToRelative(-12f, 60f)
+            horizontalLineToRelative(-80f)
+            lineToRelative(-12f, -60f)
+            quadToRelative(-12f, -5f, -22.5f, -10.5f)
+            reflectiveQuadTo(624f, 836f)
+            lineToRelative(-58f, 18f)
+            lineToRelative(-40f, -68f)
+            lineToRelative(46f, -40f)
+            quadToRelative(-2f, -12f, -2f, -26f)
+            reflectiveQuadToRelative(2f, -26f)
+            lineToRelative(-46f, -40f)
+            lineToRelative(40f, -68f)
+            lineToRelative(58f, 18f)
+            quadToRelative(11f, -8f, 21.5f, -13.5f)
+            reflectiveQuadTo(668f, 580f)
+            lineToRelative(12f, -60f)
+            horizontalLineToRelative(80f)
+            close()
+            moveTo(720f, 640f)
+            quadToRelative(-33f, 0f, -56.5f, 23.5f)
+            reflectiveQuadTo(640f, 720f)
+            quadToRelative(0f, 33f, 23.5f, 56.5f)
+            reflectiveQuadTo(720f, 800f)
+            quadToRelative(33f, 0f, 56.5f, -23.5f)
+            reflectiveQuadTo(800f, 720f)
+            quadToRelative(0f, -33f, -23.5f, -56.5f)
+            reflectiveQuadTo(720f, 640f)
+            close()
+        }
+    }.build()
+}

+ 46 - 0
src/main/kotlin/eu/mjdev/desktop/icons/wifi/level/Wifi_Level_0.kt

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.icons.wifi.level
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import eu.mjdev.desktop.icons.Icons
+
+val Icons.Wifi_Level_0: ImageVector by
+        lazy(LazyThreadSafetyMode.NONE) {
+    ImageVector.Builder(
+        name = "Wifi_Level_0",
+        defaultWidth = 24.dp,
+        defaultHeight = 24.dp,
+        viewportWidth = 960f,
+        viewportHeight = 960f
+    ).apply {
+        path(fill = SolidColor(Color(0xFFE8EAED))) {
+            moveTo(480f, 840f)
+            lineTo(0f, 360f)
+            quadToRelative(95f, -97f, 219.5f, -148.5f)
+            reflectiveQuadTo(480f, 160f)
+            quadToRelative(136f, 0f, 260.5f, 51.5f)
+            reflectiveQuadTo(960f, 360f)
+            lineTo(480f, 840f)
+            close()
+            moveTo(480f, 726f)
+            lineTo(844f, 362f)
+            quadToRelative(-79f, -60f, -172f, -91f)
+            reflectiveQuadToRelative(-192f, -31f)
+            quadToRelative(-99f, 0f, -192f, 31f)
+            reflectiveQuadToRelative(-172f, 91f)
+            lineToRelative(364f, 364f)
+            close()
+        }
+    }.build()
+}

+ 50 - 0
src/main/kotlin/eu/mjdev/desktop/icons/wifi/level/Wifi_Level_1.kt

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.icons.wifi.level
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import eu.mjdev.desktop.icons.Icons
+
+val Icons.Wifi_Level_1: ImageVector by
+lazy(LazyThreadSafetyMode.NONE) {
+    ImageVector.Builder(
+        name = "Wifi_Level_1",
+        defaultWidth = 24.dp,
+        defaultHeight = 24.dp,
+        viewportWidth = 960f,
+        viewportHeight = 960f
+    ).apply {
+        path(fill = SolidColor(Color(0xFFE8EAED))) {
+            moveTo(480f, 840f)
+            lineTo(0f, 360f)
+            quadToRelative(96f, -98f, 220f, -149f)
+            reflectiveQuadToRelative(260f, -51f)
+            quadToRelative(137f, 0f, 261f, 51f)
+            reflectiveQuadToRelative(219f, 149f)
+            lineTo(480f, 840f)
+            close()
+            moveTo(361f, 607f)
+            quadToRelative(25f, -18f, 55.5f, -28f)
+            reflectiveQuadToRelative(63.5f, -10f)
+            quadToRelative(33f, 0f, 63.5f, 10f)
+            reflectiveQuadToRelative(55.5f, 28f)
+            lineToRelative(245f, -245f)
+            quadToRelative(-78f, -59f, -170.5f, -90.5f)
+            reflectiveQuadTo(480f, 240f)
+            quadToRelative(-101f, 0f, -193.5f, 31.5f)
+            reflectiveQuadTo(116f, 362f)
+            lineToRelative(245f, 245f)
+            close()
+        }
+    }.build()
+}

+ 50 - 0
src/main/kotlin/eu/mjdev/desktop/icons/wifi/level/Wifi_Level_2.kt

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.icons.wifi.level
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import eu.mjdev.desktop.icons.Icons
+
+val Icons.Wifi_Level_2: ImageVector by
+        lazy(LazyThreadSafetyMode.NONE) {
+    ImageVector.Builder(
+        name = "Wifi_Level_2",
+        defaultWidth = 24.dp,
+        defaultHeight = 24.dp,
+        viewportWidth = 960f,
+        viewportHeight = 960f
+    ).apply {
+        path(fill = SolidColor(Color(0xFFE8EAED))) {
+            moveTo(480f, 840f)
+            lineTo(0f, 360f)
+            quadToRelative(96f, -98f, 220f, -149f)
+            reflectiveQuadToRelative(260f, -51f)
+            quadToRelative(137f, 0f, 261f, 51f)
+            reflectiveQuadToRelative(219f, 149f)
+            lineTo(480f, 840f)
+            close()
+            moveTo(299f, 545f)
+            quadToRelative(38f, -28f, 84f, -43.5f)
+            reflectiveQuadToRelative(97f, -15.5f)
+            quadToRelative(51f, 0f, 97f, 15.5f)
+            reflectiveQuadToRelative(84f, 43.5f)
+            lineToRelative(183f, -183f)
+            quadToRelative(-78f, -59f, -170.5f, -90.5f)
+            reflectiveQuadTo(480f, 240f)
+            quadToRelative(-101f, 0f, -193.5f, 31.5f)
+            reflectiveQuadTo(116f, 362f)
+            lineToRelative(183f, 183f)
+            close()
+        }
+    }.build()
+}

+ 50 - 0
src/main/kotlin/eu/mjdev/desktop/icons/wifi/level/Wifi_Level_3.kt

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.icons.wifi.level
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import eu.mjdev.desktop.icons.Icons
+
+val Icons.Wifi_Level_3: ImageVector by
+        lazy(LazyThreadSafetyMode.NONE) {
+    ImageVector.Builder(
+        name = "Wifi_Level_3",
+        defaultWidth = 24.dp,
+        defaultHeight = 24.dp,
+        viewportWidth = 960f,
+        viewportHeight = 960f
+    ).apply {
+        path(fill = SolidColor(Color(0xFFE8EAED))) {
+            moveTo(480f, 840f)
+            lineTo(0f, 360f)
+            quadToRelative(96f, -98f, 220f, -149f)
+            reflectiveQuadToRelative(260f, -51f)
+            quadToRelative(137f, 0f, 261f, 51f)
+            reflectiveQuadToRelative(219f, 149f)
+            lineTo(480f, 840f)
+            close()
+            moveTo(232f, 478f)
+            quadToRelative(53f, -38f, 116f, -59.5f)
+            reflectiveQuadTo(480f, 397f)
+            quadToRelative(69f, 0f, 132f, 21.5f)
+            reflectiveQuadTo(728f, 478f)
+            lineToRelative(116f, -116f)
+            quadToRelative(-78f, -59f, -170.5f, -90.5f)
+            reflectiveQuadTo(480f, 240f)
+            quadToRelative(-101f, 0f, -193.5f, 31.5f)
+            reflectiveQuadTo(116f, 362f)
+            lineToRelative(116f, 116f)
+            close()
+        }
+    }.build()
+}

+ 50 - 0
src/main/kotlin/eu/mjdev/desktop/icons/wifi/level/Wifi_Level_4.kt

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.icons.wifi.level
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import eu.mjdev.desktop.icons.Icons
+
+val Icons.Wifi_Level_4: ImageVector by
+        lazy(LazyThreadSafetyMode.NONE) {
+    ImageVector.Builder(
+        name = "Wifi_Level_4",
+        defaultWidth = 24.dp,
+        defaultHeight = 24.dp,
+        viewportWidth = 960f,
+        viewportHeight = 960f
+    ).apply {
+        path(fill = SolidColor(Color(0xFFE8EAED))) {
+            moveTo(480f, 840f)
+            lineTo(0f, 360f)
+            quadToRelative(95f, -97f, 219.5f, -148.5f)
+            reflectiveQuadTo(480f, 160f)
+            quadToRelative(137f, 0f, 261f, 51f)
+            reflectiveQuadToRelative(219f, 149f)
+            lineTo(480f, 840f)
+            close()
+            moveTo(174f, 420f)
+            quadToRelative(67f, -48f, 145f, -74f)
+            reflectiveQuadToRelative(161f, -26f)
+            quadToRelative(83f, 0f, 161f, 26f)
+            reflectiveQuadToRelative(145f, 74f)
+            lineToRelative(58f, -58f)
+            quadToRelative(-79f, -60f, -172f, -91f)
+            reflectiveQuadToRelative(-192f, -31f)
+            quadToRelative(-99f, 0f, -192f, 31f)
+            reflectiveQuadToRelative(-172f, 91f)
+            lineToRelative(58f, 58f)
+            close()
+        }
+    }.build()
+}

+ 38 - 0
src/main/kotlin/eu/mjdev/desktop/icons/wifi/level/Wifi_Level_5.kt

@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) Milan Jurkulák 2024.
+ *  Contact:
+ *  e: mimoccc@gmail.com
+ *  e: mj@mjdev.org
+ *  w: https://mjdev.org
+ */
+
+package eu.mjdev.desktop.icons.wifi.level
+
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.SolidColor
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.graphics.vector.path
+import androidx.compose.ui.unit.dp
+import eu.mjdev.desktop.icons.Icons
+
+val Icons.Wifi_Level_5: ImageVector by
+        lazy(LazyThreadSafetyMode.NONE) {
+    ImageVector.Builder(
+        name = "Wifi_Level_5",
+        defaultWidth = 24.dp,
+        defaultHeight = 24.dp,
+        viewportWidth = 960f,
+        viewportHeight = 960f
+    ).apply {
+        path(fill = SolidColor(Color(0xFFE8EAED))) {
+            moveTo(480f, 840f)
+            lineTo(0f, 360f)
+            quadToRelative(95f, -97f, 219.5f, -148.5f)
+            reflectiveQuadTo(480f, 160f)
+            quadToRelative(136f, 0f, 260.5f, 51.5f)
+            reflectiveQuadTo(960f, 360f)
+            lineTo(480f, 840f)
+            close()
+        }
+    }.build()
+}

+ 4 - 2
src/main/kotlin/eu/mjdev/desktop/managers/theme/linux/ThemeManagerLinux.kt

@@ -37,8 +37,10 @@ class ThemeManagerLinux(
     private val gtk4ThemeDir = themeDir["gtk-4.0"]
     private val gtk3CssFile = gtk3ThemeDir["gtk.css"]
     private val gtk4CssFile = gtk4ThemeDir["gtk.css"]
-    private val systemGtk3CssFile = gtk3ThemeDir["gtk.css"]
-    private val systemGtk4CssFile = gtk4ThemeDir["gtk.css"]
+    private val systemGtk3ThemeDir = systemThemeDir["gtk-3.0"]
+    private val systemGtk4ThemeDir = systemThemeDir["gtk-4.0"]
+    private val systemGtk3CssFile = systemGtk3ThemeDir["gtk.css"]
+    private val systemGtk4CssFile = systemGtk4ThemeDir["gtk.css"]
 
     override fun createFromPalette() {
         createDesktopFile()