From 5ddf5c240d37d2321936590402d10a63b6fc89ae Mon Sep 17 00:00:00 2001 From: Jas Singh Date: Sat, 29 Jun 2024 03:36:57 -0700 Subject: [PATCH] (WIP) Code orginazation/refactoring and beging nework refactoring... --- modules/menus/audio/InputDevices.js | 58 +++ modules/menus/audio/PlaybackDevices.js | 58 +++ modules/menus/audio/SelectedInput.js | 66 +++ modules/menus/audio/SelectedPlayback.js | 67 +++ modules/menus/audio/index.js | 291 +------------ modules/menus/audio/utils.js | 27 ++ modules/menus/network/Ethernet.js | 67 +++ modules/menus/network/Wifi/APStaging.js | 39 ++ modules/menus/network/Wifi/WirelessAPs.js | 61 +++ modules/menus/network/Wifi/index.js | 45 ++ modules/menus/network/index.bkup.js | 483 +++++++++++++++++++++ modules/menus/network/index.js | 486 +--------------------- modules/menus/notifications/index.js | 93 +++-- scss/menus/menu.scss | 23 +- scss/menus/network.scss | 107 ++--- scss/menus/notifications.scss | 9 + style.css | 111 ++--- style.css.map | 2 +- 18 files changed, 1109 insertions(+), 984 deletions(-) create mode 100644 modules/menus/audio/InputDevices.js create mode 100644 modules/menus/audio/PlaybackDevices.js create mode 100644 modules/menus/audio/SelectedInput.js create mode 100644 modules/menus/audio/SelectedPlayback.js create mode 100644 modules/menus/audio/utils.js create mode 100644 modules/menus/network/Ethernet.js create mode 100644 modules/menus/network/Wifi/APStaging.js create mode 100644 modules/menus/network/Wifi/WirelessAPs.js create mode 100644 modules/menus/network/Wifi/index.js create mode 100644 modules/menus/network/index.bkup.js diff --git a/modules/menus/audio/InputDevices.js b/modules/menus/audio/InputDevices.js new file mode 100644 index 0000000..99c3856 --- /dev/null +++ b/modules/menus/audio/InputDevices.js @@ -0,0 +1,58 @@ +const audio = await Service.import("audio"); + +const renderInputDevices = (inputDevices) => { + if (!inputDevices.length) { + return [ + Widget.Box({ + class_name: `menu-unfound-button input`, + child: Widget.Box({ + children: [ + Widget.Label({ + class_name: "menu-button-name input", + label: "No input devices found...", + }), + ], + }), + }), + ]; + } + return inputDevices.map((device) => { + return Widget.Button({ + on_primary_click: () => (audio.microphone = device), + class_name: `menu-button audio input ${device}`, + child: Widget.Box({ + children: [ + Widget.Box({ + hpack: "start", + children: [ + Widget.Label({ + class_name: audio.microphone + .bind("description") + .as((v) => + device.description === v + ? "menu-button-icon active input" + : "menu-button-icon input", + ), + label: "", + }), + Widget.Label({ + truncate: "end", + wrap: true, + class_name: audio.microphone + .bind("description") + .as((v) => + device.description === v + ? "menu-button-name active input" + : "menu-button-name input", + ), + label: device.description, + }), + ], + }), + ], + }), + }); + }); +}; + +export { renderInputDevices }; diff --git a/modules/menus/audio/PlaybackDevices.js b/modules/menus/audio/PlaybackDevices.js new file mode 100644 index 0000000..efe232e --- /dev/null +++ b/modules/menus/audio/PlaybackDevices.js @@ -0,0 +1,58 @@ +const audio = await Service.import("audio"); + +const renderPlaybacks = (playbackDevices) => { + return playbackDevices.map((device) => { + if (device.description === "Dummy Output") { + return Widget.Box({ + class_name: "menu-unfound-button playback", + child: Widget.Box({ + children: [ + Widget.Label({ + class_name: "menu-button-name playback", + label: "No playback devices found...", + }), + ], + }), + }); + } + return Widget.Button({ + class_name: `menu-button audio playback ${device}`, + on_primary_click: () => (audio.speaker = device), + child: Widget.Box({ + children: [ + Widget.Box({ + hpack: "start", + children: [ + Widget.Label({ + truncate: "end", + wrap: true, + class_name: audio.speaker + .bind("description") + .as((v) => + device.description === v + ? "menu-button-icon active playback" + : "menu-button-icon playback", + ), + label: "", + }), + Widget.Label({ + class_name: audio.speaker + .bind("description") + .as((v) => + device.description === v + ? "menu-button-name active playback" + : "menu-button-name playback", + ), + truncate: "end", + wrap: true, + label: device.description, + }), + ], + }), + ], + }), + }); + }); +}; + +export { renderPlaybacks }; diff --git a/modules/menus/audio/SelectedInput.js b/modules/menus/audio/SelectedInput.js new file mode 100644 index 0000000..45579c9 --- /dev/null +++ b/modules/menus/audio/SelectedInput.js @@ -0,0 +1,66 @@ +const audio = await Service.import("audio"); +import { getIcon } from './utils.js'; + +const renderActiveInput = () => { + return [ + Widget.Box({ + class_name: "menu-slider-container input", + children: [ + Widget.Button({ + vexpand: false, + vpack: "end", + setup: (self) => { + self.hook(audio, () => { + const mic = audio.microphone; + const className = `menu-active-button input ${mic.is_muted ? "muted" : ""}`; + return (self.class_name = className); + }); + }, + on_primary_click: () => + (audio.microphone.is_muted = !audio.microphone.is_muted), + child: Widget.Icon({ + class_name: "menu-active-icon input", + setup: (self) => { + self.hook(audio, () => { + self.icon = getIcon( + audio.microphone.volume, + audio.microphone.is_muted, + )["mic"]; + }); + }, + }), + }), + Widget.Box({ + vertical: true, + children: [ + Widget.Label({ + class_name: "menu-active input", + hpack: "start", + truncate: "end", + wrap: true, + label: audio.bind("microphone").as((v) => v.description || ""), + }), + Widget.Slider({ + value: audio.microphone.bind("volume").as((v) => v), + class_name: "menu-active-slider menu-slider inputs", + draw_value: false, + hexpand: true, + min: 0, + max: 1, + onChange: ({ value }) => (audio.microphone.volume = value), + }), + ], + }), + Widget.Label({ + class_name: "menu-active-percentage input", + vpack: "end", + label: audio.microphone + .bind("volume") + .as((v) => `${Math.floor(v * 100)}%`), + }), + ], + }), + ]; +}; + +export { renderActiveInput }; diff --git a/modules/menus/audio/SelectedPlayback.js b/modules/menus/audio/SelectedPlayback.js new file mode 100644 index 0000000..e410f9c --- /dev/null +++ b/modules/menus/audio/SelectedPlayback.js @@ -0,0 +1,67 @@ +const audio = await Service.import("audio"); +import { getIcon } from "./utils.js"; + +const renderActivePlayback = () => { + return [ + Widget.Box({ + class_name: "menu-slider-container playback", + children: [ + Widget.Button({ + vexpand: false, + vpack: "end", + setup: (self) => { + self.hook(audio, () => { + const spkr = audio.speaker; + const className = `menu-active-button playback ${spkr.is_muted ? "muted" : ""}`; + return (self.class_name = className); + }); + }, + on_primary_click: () => + (audio.speaker.is_muted = !audio.speaker.is_muted), + child: Widget.Icon({ + class_name: "menu-active-icon playback", + setup: (self) => { + self.hook(audio, () => { + self.icon = getIcon( + audio.speaker.volume, + audio.speaker.is_muted, + )["spkr"]; + }); + }, + }), + }), + Widget.Box({ + vertical: true, + children: [ + Widget.Label({ + class_name: "menu-active playback", + hpack: "start", + truncate: "end", + expand: true, + wrap: true, + label: audio.bind("speaker").as((v) => v.description || ""), + }), + Widget.Slider({ + value: audio["speaker"].bind("volume"), + class_name: "menu-active-slider menu-slider playback", + draw_value: false, + hexpand: true, + min: 0, + max: 1, + onChange: ({ value }) => (audio.speaker.volume = value), + }), + ], + }), + Widget.Label({ + vpack: "end", + class_name: "menu-active-percentage playback", + label: audio.speaker + .bind("volume") + .as((v) => `${Math.floor(v * 100)}%`), + }), + ], + }), + ]; +}; + +export { renderActivePlayback }; diff --git a/modules/menus/audio/index.js b/modules/menus/audio/index.js index ca7d972..cdb0a06 100644 --- a/modules/menus/audio/index.js +++ b/modules/menus/audio/index.js @@ -1,294 +1,11 @@ const audio = await Service.import("audio"); import DropdownMenu from "../DropdownMenu.js"; +import { renderInputDevices } from "./InputDevices.js"; +import { renderPlaybacks } from "./PlaybackDevices.js"; +import { renderActiveInput } from "./SelectedInput.js"; +import { renderActivePlayback } from "./SelectedPlayback.js"; export default () => { - const renderPlaybacks = (playbackDevices) => { - return playbackDevices.map((device) => { - if (device.description === "Dummy Output") { - return Widget.Box({ - class_name: "menu-unfound-button playback", - child: Widget.Box({ - children: [ - Widget.Label({ - class_name: "menu-button-name playback", - label: "No playback devices found...", - }), - ], - }), - }); - } - return Widget.Button({ - class_name: `menu-button audio playback ${device}`, - on_primary_click: () => (audio.speaker = device), - child: Widget.Box({ - children: [ - Widget.Box({ - hpack: "start", - children: [ - Widget.Label({ - truncate: "end", - wrap: true, - class_name: audio.speaker - .bind("description") - .as((v) => - device.description === v - ? "menu-button-icon active playback" - : "menu-button-icon playback", - ), - label: "", - }), - Widget.Label({ - class_name: audio.speaker - .bind("description") - .as((v) => - device.description === v - ? "menu-button-name active playback" - : "menu-button-name playback", - ), - truncate: "end", - wrap: true, - label: device.description, - }), - ], - }), - Widget.Box({ - hpack: "end", - expand: true, - children: [ - Widget.Label({ - class_name: "menu-button-isactive audio playback", - label: audio.speaker - .bind("description") - .as((v) => (device.description === v ? " " : "")), - }), - ], - }), - ], - }), - }); - }); - }; - - const getIcon = (audioVol, isMuted) => { - const speakerIcons = { - 101: "audio-volume-overamplified-symbolic", - 66: "audio-volume-high-symbolic", - 34: "audio-volume-medium-symbolic", - 1: "audio-volume-low-symbolic", - 0: "audio-volume-muted-symbolic", - }; - - const inputIcons = { - 66: "microphone-sensitivity-high-symbolic", - 34: "microphone-sensitivity-medium-symbolic", - 1: "microphone-sensitivity-low-symbolic", - 0: "microphone-disabled-symbolic", - }; - - const icon = isMuted - ? 0 - : [101, 66, 34, 1, 0].find((threshold) => threshold <= audioVol * 100); - - return { - spkr: speakerIcons[icon], - mic: inputIcons[icon], - }; - }; - - const renderInputDevices = (inputDevices) => { - if (!inputDevices.length) { - return [ - Widget.Box({ - class_name: `menu-unfound-button input`, - child: Widget.Box({ - children: [ - Widget.Label({ - class_name: "menu-button-name input", - label: "No input devices found...", - }), - ], - }), - }), - ]; - } - return inputDevices.map((device) => { - return Widget.Button({ - on_primary_click: () => (audio.microphone = device), - class_name: `menu-button audio input ${device}`, - child: Widget.Box({ - children: [ - Widget.Box({ - hpack: "start", - children: [ - Widget.Label({ - class_name: audio.microphone - .bind("description") - .as((v) => - device.description === v - ? "menu-button-icon active input" - : "menu-button-icon input", - ), - label: "", - }), - Widget.Label({ - truncate: "end", - wrap: true, - class_name: audio.microphone - .bind("description") - .as((v) => - device.description === v - ? "menu-button-name active input" - : "menu-button-name input", - ), - label: device.description, - }), - ], - }), - Widget.Box({ - hpack: "end", - expand: true, - children: [ - Widget.Label({ - class_name: "menu-button-isactive audio input", - truncate: "end", - wrap: true, - label: audio.microphone - .bind("description") - .as((v) => (device.description === v ? " " : "")), - }), - ], - }), - ], - }), - }); - }); - }; - - const renderActivePlayback = () => { - return [ - Widget.Box({ - class_name: "menu-slider-container playback", - children: [ - Widget.Button({ - vexpand: false, - vpack: "end", - setup: (self) => { - self.hook(audio, () => { - const spkr = audio.speaker; - const className = `menu-active-button playback ${spkr.is_muted ? "muted" : ""}`; - return (self.class_name = className); - }); - }, - on_primary_click: () => - (audio.speaker.is_muted = !audio.speaker.is_muted), - child: Widget.Icon({ - class_name: "menu-active-icon playback", - setup: (self) => { - self.hook(audio, () => { - self.icon = getIcon( - audio.speaker.volume, - audio.speaker.is_muted, - )["spkr"]; - }); - }, - }), - }), - Widget.Box({ - vertical: true, - children: [ - Widget.Label({ - class_name: "menu-active playback", - hpack: "start", - truncate: "end", - expand: true, - wrap: true, - label: audio.bind("speaker").as((v) => v.description || ""), - }), - Widget.Slider({ - value: audio["speaker"].bind("volume"), - class_name: "menu-active-slider menu-slider playback", - draw_value: false, - hexpand: true, - min: 0, - max: 1, - onChange: ({ value }) => (audio.speaker.volume = value), - }), - ], - }), - Widget.Label({ - vpack: "end", - class_name: "menu-active-percentage playback", - label: audio.speaker - .bind("volume") - .as((v) => `${Math.floor(v * 100)}%`), - }), - ], - }), - ]; - }; - - const renderActiveInput = () => { - return [ - Widget.Box({ - class_name: "menu-slider-container input", - children: [ - Widget.Button({ - vexpand: false, - vpack: "end", - setup: (self) => { - self.hook(audio, () => { - const mic = audio.microphone; - const className = `menu-active-button input ${mic.is_muted ? "muted" : ""}`; - return (self.class_name = className); - }); - }, - on_primary_click: () => - (audio.microphone.is_muted = !audio.microphone.is_muted), - child: Widget.Icon({ - class_name: "menu-active-icon input", - setup: (self) => { - self.hook(audio, () => { - self.icon = getIcon( - audio.microphone.volume, - audio.microphone.is_muted, - )["mic"]; - }); - }, - }), - }), - Widget.Box({ - vertical: true, - children: [ - Widget.Label({ - class_name: "menu-active input", - hpack: "start", - truncate: "end", - wrap: true, - label: audio.bind("microphone").as((v) => v.description || ""), - }), - Widget.Slider({ - value: audio.microphone.bind("volume").as((v) => v), - class_name: "menu-active-slider menu-slider inputs", - draw_value: false, - hexpand: true, - min: 0, - max: 1, - onChange: ({ value }) => (audio.microphone.volume = value), - }), - ], - }), - Widget.Label({ - class_name: "menu-active-percentage input", - vpack: "end", - label: audio.microphone - .bind("volume") - .as((v) => `${Math.floor(v * 100)}%`), - }), - ], - }), - ]; - }; - return DropdownMenu({ name: "audiomenu", transition: "crossfade", diff --git a/modules/menus/audio/utils.js b/modules/menus/audio/utils.js new file mode 100644 index 0000000..2aa71a7 --- /dev/null +++ b/modules/menus/audio/utils.js @@ -0,0 +1,27 @@ +const getIcon = (audioVol, isMuted) => { + const speakerIcons = { + 101: "audio-volume-overamplified-symbolic", + 66: "audio-volume-high-symbolic", + 34: "audio-volume-medium-symbolic", + 1: "audio-volume-low-symbolic", + 0: "audio-volume-muted-symbolic", + }; + + const inputIcons = { + 66: "microphone-sensitivity-high-symbolic", + 34: "microphone-sensitivity-medium-symbolic", + 1: "microphone-sensitivity-low-symbolic", + 0: "microphone-disabled-symbolic", + }; + + const icon = isMuted + ? 0 + : [101, 66, 34, 1, 0].find((threshold) => threshold <= audioVol * 100); + + return { + spkr: speakerIcons[icon], + mic: inputIcons[icon], + }; +}; + +export { getIcon }; diff --git a/modules/menus/network/Ethernet.js b/modules/menus/network/Ethernet.js new file mode 100644 index 0000000..a7fe47f --- /dev/null +++ b/modules/menus/network/Ethernet.js @@ -0,0 +1,67 @@ +const network = await Service.import("network"); + +const Ethernet = () => { + return Widget.Box({ + class_name: "menu-section-container ethernet", + vertical: true, + children: [ + Widget.Box({ + class_name: "menu-label-container", + hpack: "fill", + child: Widget.Label({ + class_name: "menu-label", + hexpand: true, + hpack: "center", + label: "Ethernet", + }), + }), + Widget.Box({ + class_name: "menu-items-section", + vertical: true, + children: [ + Widget.Box({ + class_name: "menu-content", + vertical: true, + child: network.bind("wired").as((wired) => { + return Widget.Box({ + class_name: "network-element-item", + child: Widget.Box({ + hpack: "start", + children: [ + Widget.Icon({ + class_name: "network-ethernet-icon", + tooltip_text: wired.internet, + icon: `${wired["icon_name"]}`, + }), + Widget.Box({ + class_name: "connection-container", + vertical: true, + children: [ + Widget.Label({ + class_name: "active-connection", + hpack: "start", + truncate: "end", + wrap: true, + label: `Ethernet Connection ${typeof wired.speed === "number" ? `(${wired.speed / 1000} Gbps)` : ""}`, + }), + Widget.Label({ + hpack: "start", + class_name: "connection-status dim", + label: + wired.internet.charAt(0).toUpperCase() + + wired.internet.slice(1), + }), + ], + }), + ], + }), + }); + }), + }), + ], + }), + ], + }); +}; + +export { Ethernet }; diff --git a/modules/menus/network/Wifi/APStaging.js b/modules/menus/network/Wifi/APStaging.js new file mode 100644 index 0000000..5ad9f72 --- /dev/null +++ b/modules/menus/network/Wifi/APStaging.js @@ -0,0 +1,39 @@ +const renderWapStaging = (self, stagedDevice) => { + self.hook(stagedDevice, ({ value }) => { + return (self.child = Widget.Button({ + class_name: "network-element-item", + child: Widget.Box({ + hpack: "start", + children: [ + Widget.Icon({ + class_name: "network-ethernet-icon", + icon: `${stagedDevice["iconName"]}`, + }), + Widget.Box({ + class_name: "connection-container", + vertical: true, + children: [ + Widget.Label({ + class_name: "active-connection", + hpack: "start", + truncate: "end", + wrap: true, + label: stagedDevice.ssid, + }), + Widget.Revealer({ + revealChild: stagedDevice.active, + child: Widget.Label({ + hpack: "start", + class_name: "connection-status dim", + label: "Connected", + }), + }), + ], + }), + ], + }), + })); + }); +}; + +export { renderWapStaging }; diff --git a/modules/menus/network/Wifi/WirelessAPs.js b/modules/menus/network/Wifi/WirelessAPs.js new file mode 100644 index 0000000..7203e8a --- /dev/null +++ b/modules/menus/network/Wifi/WirelessAPs.js @@ -0,0 +1,61 @@ +const renderWAPs = (self, network) => { + self.hook(network, () => { + const WAPs = network.wifi.access_points; + + console.log("WAPs"); + console.log(JSON.stringify(WAPs, null, 2)); + + const filteredWAPs = WAPs.filter((ap) => ap.ssid !== "Unknown").sort( + (a, b) => { + return b.strength - a.strength; + }, + ); + + if (filteredWAPs.length <= 0) { + return (self.child = Widget.Label({ + class_name: "waps-not-found dim", + expand: true, + hpack: "center", + vpack: "center", + label: "No Wi-Fi Networks Found", + })); + } + return (self.children = filteredWAPs.map((ap) => { + return Widget.Button({ + class_name: "network-element-item", + child: Widget.Box({ + hpack: "start", + children: [ + Widget.Icon({ + class_name: "network-ethernet-icon", + icon: `${ap["iconName"]}`, + }), + Widget.Box({ + class_name: "connection-container", + vertical: true, + children: [ + Widget.Label({ + class_name: "active-connection", + hpack: "start", + truncate: "end", + wrap: true, + label: ap.ssid, + }), + Widget.Revealer({ + revealChild: ap.active, + child: Widget.Label({ + hpack: "start", + class_name: "connection-status dim", + label: "Connected", + }), + }), + ], + }), + ], + }), + }); + })); + }); +}; + +export { renderWAPs }; diff --git a/modules/menus/network/Wifi/index.js b/modules/menus/network/Wifi/index.js new file mode 100644 index 0000000..017a100 --- /dev/null +++ b/modules/menus/network/Wifi/index.js @@ -0,0 +1,45 @@ +const network = await Service.import("network"); +import { renderWAPs } from "./WirelessAPs.js"; +import { renderWapStaging } from "./APStaging.js"; + +const Staging = Variable("none"); + +const Wifi = () => { + return Widget.Box({ + class_name: "menu-section-container wifi", + vertical: true, + children: [ + Widget.Box({ + class_name: "menu-label-container", + hpack: "fill", + child: Widget.Label({ + class_name: "menu-label", + hexpand: true, + hpack: "center", + label: "Wi-Fi", + }), + }), + Widget.Box({ + class_name: "menu-items-section", + vertical: true, + children: [ + Widget.Box({ + class_name: "wap-staging", + setup: (self) => { + renderWapStaging(self, Staging); + }, + }), + Widget.Box({ + class_name: "available-waps", + vertical: true, + setup: (self) => { + renderWAPs(self, network); + }, + }), + ], + }), + ], + }); +}; + +export { Wifi }; diff --git a/modules/menus/network/index.bkup.js b/modules/menus/network/index.bkup.js new file mode 100644 index 0000000..c8ba1e9 --- /dev/null +++ b/modules/menus/network/index.bkup.js @@ -0,0 +1,483 @@ +const network = await Service.import("network"); +import DropdownMenu from "../DropdownMenu.js"; + +export default () => { + const pendingAuth = Variable(""); + + return DropdownMenu({ + name: "networkmenu", + transition: "crossfade", + child: Widget.Box({ + class_name: "menu-items", + child: Widget.Box({ + vertical: true, + hexpand: true, + class_name: "menu-items-container network", + children: [ + Widget.Box({ + class_name: "menu-label-container network", + child: Widget.Label({ + class_name: "menu-label network", + hpack: "start", + label: "Connected Network", + }), + }), + Widget.Box({ + class_name: "menu-item-box network", + vertical: true, + children: Utils.merge( + [ + network.bind("wired"), + network.bind("wifi"), + network.bind("primary"), + pendingAuth.bind("value"), + ], + (wired, wifi, primary) => { + let sortedNetworks = []; + + if (wifi.access_points.length > 0) { + sortedNetworks = wifi.access_points + .filter((ap) => ap.ssid !== "Unknown") + .sort((a, b) => { + return b.strength - a.strength; + }); + } + + const localIfConnected = () => { + if (primary === "wired") { + return [ + Widget.Box({ + class_name: `network-element-item-ethernet ${sortedNetworks.length > 0 ? "multi" : ""}`, + child: Widget.Box({ + hpack: "start", + vertical: true, + children: [ + Widget.Box({ + children: [ + Widget.Box({ + class_name: "network-element-items-container", + children: [ + Widget.Button({ + class_name: "menu-button-icon network", + child: Widget.Icon({ + tooltip_text: wired.internet, + icon: `${wired["icon_name"]}`, + }), + }), + Widget.Label({ + class_name: "menu-button-name network", + truncate: "end", + wrap: true, + label: `Ethernet (${wired.speed / 1000} Gbps)`, + }), + ], + }), + ], + }), + Widget.Box({ + class_name: + "menu-button-name-container status dim", + children: [ + Widget.Label({ + class_name: + "menu-button-name status network dim", + label: + wired.internet.charAt(0).toUpperCase() + + wired.internet.slice(1), + }), + ], + }), + ], + }), + }), + ]; + } + return []; + }; + + const wifiIfConnected = () => { + const getIdBySsid = (ssid, nmcliOutput) => { + const lines = nmcliOutput.trim().split("\n"); + for (const line of lines) { + const columns = line.trim().split(/\s{2,}/); + if (columns[0].includes(ssid)) { + return columns[1]; + } + } + return null; + }; + + if (wifi.ssid !== "") { + return [ + Widget.Box({ + class_name: `network-element-item-ethernet`, + children: [ + Widget.Box({ + hpack: "start", + vertical: true, + children: [ + Widget.Box({ + children: [ + Widget.Box({ + class_name: + "network-element-items-container", + children: [ + Widget.Button({ + class_name: "menu-button-icon network", + child: Widget.Icon({ + tooltip_text: wifi.state, + icon: `${wifi["icon_name"]}`, + }), + }), + Widget.Label({ + class_name: "menu-button-name network", + truncate: "end", + wrap: true, + label: wifi.ssid, + }), + ], + }), + ], + }), + Widget.Box({ + class_name: + "menu-button-name-container status dim", + children: [ + Widget.Label({ + class_name: + "menu-button-name status network dim", + label: + wifi.internet.charAt(0).toUpperCase() + + wifi.internet.slice(1), + }), + ], + }), + ], + }), + Widget.Box({ + hexpand: true, + hpack: "end", + children: [ + Widget.Button({ + class_name: + "menu-icon-button network disconnect", + on_primary_click: () => { + Utils.execAsync( + "nmcli connection show --active", + ).then((res) => { + const connectionId = getIdBySsid( + wifi.ssid, + res, + ); + + Utils.execAsync( + `nmcli connection down ${connectionId} "${wifi.ssid}"`, + ).catch((err) => + console.error( + `Error while disconnecting from wifi "${wifi.ssid}": ${err}`, + ), + ); + }); + }, + child: Widget.Label(""), + }), + Widget.Box({ + hexpand: true, + child: Widget.Button({ + class_name: "menu-icon-button network forget", + on_primary_click: () => { + Utils.execAsync( + "nmcli connection show --active", + ).then((res) => { + const connectionId = getIdBySsid( + wifi.ssid, + res, + ); + + Utils.execAsync( + `nmcli connection delete ${connectionId} "${wifi.ssid}"`, + ).catch((err) => + console.error( + `Error while forgetting "${wifi.ssid}": ${err}`, + ), + ); + }); + }, + child: Widget.Label("󰆴"), + }), + }), + ], + }), + ], + }), + ]; + } + return []; + }; + + return [...localIfConnected(), ...wifiIfConnected()]; + }, + ), + }), + Widget.Box({ + children: [ + Widget.Box({ + hpack: "start", + class_name: "menu-label-container network", + child: Widget.Label({ + class_name: "menu-label network", + hpack: "start", + label: "Available Networks", + }), + }), + Widget.Box({ + hexpand: true, + hpack: "end", + child: Widget.Button({ + class_name: "menu-icon-button refresh network", + on_primary_click: () => { + network.wifi.scan(); + }, + child: Widget.Icon("view-refresh-symbolic"), + }), + }), + ], + }), + Widget.Box({ + class_name: "menu-item-box network", + vertical: true, + children: [ + Widget.Box({ + vertical: true, + setup: (self) => { + self.hook(pendingAuth, () => { + const accPoint = network.wifi.access_points.find( + (ap) => ap.bssid === pendingAuth.value, + ); + if ( + pendingAuth.value !== "" && + accPoint !== undefined && + network.wifi.ssid !== pendingAuth.value + ) { + return (self.child = Widget.Box({ + vertical: true, + children: [ + Widget.Button({ + class_name: "network-element-item", + child: Widget.Box({ + children: [ + Widget.Box({ + hpack: "start", + vertical: true, + children: [ + Widget.Box({ + class_name: + "network-element-items-container", + children: [ + Widget.Button({ + class_name: + "menu-button-icon network", + child: Widget.Icon({ + tooltip_text: + accPoint.ssid === + network.wifi.ssid + ? network.wifi.state + : null, + icon: `${accPoint["iconName"]}`, + }), + }), + Widget.Label({ + class_name: + "menu-button-name network", + truncate: "end", + wrap: true, + label: accPoint.ssid, + }), + ], + }), + ], + }), + ], + }), + }), + + Widget.Revealer({ + transition: "slide_down", + reveal_child: pendingAuth + .bind("value") + .as((v) => (v === accPoint.bssid ? true : false)), + class_name: "network-password-input-container", + child: Widget.Box({ + hexpand: true, + children: [ + Widget.Box({ + child: Widget.Entry({ + hpack: "start", + class_name: "network-password-input", + placeholder_text: "enter password", + visibility: false, + onAccept: (selfInp) => { + Utils.execAsync( + `nmcli dev wifi connect ${accPoint.bssid} password ${selfInp.text}`, + ) + .catch((err) => { + pendingAuth.value = ""; + console.error( + `Failed to connect to wifi: ${accPoint.ssid}... ${err}`, + ); + }) + .then(() => (pendingAuth.value = "")); + selfInp.text = ""; + }, + }), + }), + Widget.Box({ + class_name: + "network-password-input-close-container", + hexpand: true, + child: Widget.Button({ + class_name: "network-password-input-close", + on_primary_click: () => + (pendingAuth.value = ""), + child: Widget.Label("󰅜 "), + }), + }), + ], + }), + }), + ], + })); + } else { + self.children = []; + } + }); + }, + }), + Widget.Box({ + vertical: true, + setup: (self) => { + self.hook(network, () => { + let sortedNetworks = []; + + self.hook(pendingAuth, () => { + if (network.wifi.access_points.length > 0) { + sortedNetworks = network.wifi.access_points + .filter((ap) => { + return ( + ap.ssid !== "Unknown" && + ap.bssid !== pendingAuth.value && + !ap.active && + network.wifi.ssid !== ap.ssid + ); + }) + .sort((a, b) => { + return b.strength - a.strength; + }); + } + + if (sortedNetworks.length <= 0) { + return (self.children = [ + Widget.Label({ + class_name: "not-found-label dim", + expand: true, + hpack: "center", + vpack: "center", + label: "No Wifi Networks Found", + }), + ]); + } + + return (self.children = sortedNetworks.map((accPoint) => { + return Widget.Box({ + vertical: true, + children: [ + Widget.Button({ + on_primary_click: () => { + Utils.execAsync( + `nmcli device wifi connect ${accPoint.bssid}`, + ).catch((err) => { + if ( + err + .toLowerCase() + .includes( + "secrets were required, but not provided", + ) + ) { + pendingAuth.value = accPoint.bssid; + } + }); + }, + class_name: "network-element-item", + child: Widget.Box({ + children: [ + Widget.Box({ + hpack: "start", + vertical: true, + children: [ + Widget.Box({ + class_name: + "network-element-items-container", + children: [ + Widget.Button({ + class_name: + "menu-button-icon network", + child: Widget.Icon({ + tooltip_text: + accPoint.ssid === + network.wifi.ssid + ? network.wifi.state + : null, + icon: `${accPoint["iconName"]}`, + }), + }), + Widget.Label({ + class_name: + "menu-button-name network", + truncate: "end", + wrap: true, + label: accPoint.ssid, + }), + ], + }), + ], + }), + ], + }), + }), + Widget.Revealer({ + transition: "slide_down", + reveal_child: pendingAuth + .bind("value") + .as((v) => + v === accPoint.bssid ? true : false, + ), + class_name: "network-password-input-container", + child: Widget.Box({ + hexpand: true, + children: [ + Widget.Entry({ + hexpand: true, + class_name: "network-password-input", + placeholder_text: "enter password", + visibility: false, + onAccept: (selfInp) => { + selfInp.text = ""; + }, + }), + ], + }), + }), + ], + }); + })); + }); + }); + }, + }), + ], + }), + ], + }), + }), + }); +}; diff --git a/modules/menus/network/index.js b/modules/menus/network/index.js index bd45620..0f16b0a 100644 --- a/modules/menus/network/index.js +++ b/modules/menus/network/index.js @@ -1,9 +1,9 @@ const network = await Service.import("network"); import DropdownMenu from "../DropdownMenu.js"; +import { Ethernet } from "./Ethernet.js"; +import { Wifi } from "./Wifi/index.js"; export default () => { - const pendingAuth = Variable(""); - return DropdownMenu({ name: "networkmenu", transition: "crossfade", @@ -13,487 +13,7 @@ export default () => { vertical: true, hexpand: true, class_name: "menu-items-container network", - children: [ - Widget.Box({ - class_name: "menu-dropdown-label-container", - hpack: "start", - children: [ - Widget.Label({ - class_name: "menu-dropdown-label network", - label: "Networks", - }), - ], - }), - Widget.Box({ - class_name: "menu-label-container network", - child: Widget.Label({ - class_name: "menu-label network", - hpack: "start", - label: "Connected Network", - }), - }), - Widget.Box({ - class_name: "menu-item-box network", - vertical: true, - setup: (self) => { - self.hook(network, () => { - self.hook(pendingAuth, () => { - let sortedNetworks = []; - - if (network.wifi.access_points.length > 0) { - sortedNetworks = network.wifi.access_points - .filter((ap) => ap.ssid !== "Unknown") - .sort((a, b) => { - return b.strength - a.strength; - }); - } - - const localIfConnected = () => { - if (network.primary === "wired") { - return [ - Widget.Box({ - class_name: `network-element-item-ethernet ${sortedNetworks.length > 0 ? "multi" : ""}`, - child: Widget.Box({ - hpack: "start", - vertical: true, - children: [ - Widget.Box({ - children: [ - Widget.Box({ - class_name: - "network-element-items-container", - children: [ - Widget.Button({ - class_name: "menu-button-icon network", - child: Widget.Icon({ - tooltip_text: network.wired.internet, - icon: `${network.wired["icon_name"]}`, - }), - }), - Widget.Label({ - class_name: "menu-button-name network", - truncate: "end", - wrap: true, - label: `Ethernet (${network.wired.speed / 1000} Gbps)`, - }), - ], - }), - ], - }), - Widget.Box({ - class_name: - "menu-button-name-container status dim", - children: [ - Widget.Label({ - class_name: - "menu-button-name status network dim", - label: - network.wired.internet - .charAt(0) - .toUpperCase() + - network.wired.internet.slice(1), - }), - ], - }), - ], - }), - }), - ]; - } - return []; - }; - - const wifiIfConnected = () => { - const getIdBySsid = (ssid, nmcliOutput) => { - const lines = nmcliOutput.trim().split("\n"); - for (const line of lines) { - const columns = line.trim().split(/\s{2,}/); - if (columns[0].includes(ssid)) { - return columns[1]; - } - } - return null; - }; - - if (network.wifi.ssid !== "") { - return [ - Widget.Box({ - class_name: `network-element-item-ethernet`, - children: [ - Widget.Box({ - hpack: "start", - vertical: true, - children: [ - Widget.Box({ - children: [ - Widget.Box({ - class_name: - "network-element-items-container", - children: [ - Widget.Button({ - class_name: - "menu-button-icon network", - child: Widget.Icon({ - tooltip_text: network.wifi.state, - icon: `${network.wifi["icon_name"]}`, - }), - }), - Widget.Label({ - class_name: - "menu-button-name network", - truncate: "end", - wrap: true, - label: network.wifi.ssid, - }), - ], - }), - ], - }), - Widget.Box({ - class_name: - "menu-button-name-container status dim", - children: [ - Widget.Label({ - class_name: - "menu-button-name status network dim", - label: - network.wifi.internet - .charAt(0) - .toUpperCase() + - network.wifi.internet.slice(1), - }), - ], - }), - ], - }), - Widget.Box({ - hexpand: true, - hpack: "end", - children: [ - Widget.Button({ - class_name: - "menu-icon-button network disconnect", - on_primary_click: () => { - Utils.execAsync( - "nmcli connection show --active", - ).then((res) => { - const connectionId = getIdBySsid( - network.wifi.ssid, - res, - ); - - Utils.execAsync( - `nmcli connection down ${connectionId} "${network.wifi.ssid}"`, - ).catch((err) => - console.error( - `Error while disconnecting from wifi "${network.wifi.ssid}": ${err}`, - ), - ); - }); - }, - child: Widget.Label(""), - }), - Widget.Box({ - hexpand: true, - child: Widget.Button({ - class_name: - "menu-icon-button network forget", - on_primary_click: () => { - Utils.execAsync( - "nmcli connection show --active", - ).then((res) => { - const connectionId = getIdBySsid( - network.wifi.ssid, - res, - ); - - Utils.execAsync( - `nmcli connection delete ${connectionId} "${network.wifi.ssid}"`, - ).catch((err) => - console.error( - `Error while forgetting "${network.wifi.ssid}": ${err}`, - ), - ); - }); - }, - child: Widget.Label("󰆴"), - }), - }), - ], - }), - ], - }), - ]; - } - return []; - }; - - return (self.children = [ - ...localIfConnected(), - ...wifiIfConnected(), - ]); - }); - }); - }, - }), - Widget.Box({ - children: [ - Widget.Box({ - hpack: "start", - class_name: "menu-label-container network", - child: Widget.Label({ - class_name: "menu-label network", - hpack: "start", - label: "Available Networks", - }), - }), - Widget.Box({ - hexpand: true, - hpack: "end", - child: Widget.Button({ - class_name: "menu-icon-button refresh network", - on_primary_click: () => { - network.wifi.scan(); - }, - child: Widget.Icon("view-refresh-symbolic"), - }), - }), - ], - }), - Widget.Box({ - class_name: "menu-item-box network", - vertical: true, - children: [ - Widget.Box({ - vertical: true, - setup: (self) => { - self.hook(pendingAuth, () => { - const accPoint = network.wifi.access_points.find( - (ap) => ap.bssid === pendingAuth.value, - ); - if ( - pendingAuth.value !== "" && - accPoint !== undefined && - network.wifi.ssid !== pendingAuth.value - ) { - return (self.child = Widget.Box({ - vertical: true, - children: [ - Widget.Button({ - class_name: "network-element-item", - child: Widget.Box({ - children: [ - Widget.Box({ - hpack: "start", - vertical: true, - children: [ - Widget.Box({ - class_name: - "network-element-items-container", - children: [ - Widget.Button({ - class_name: - "menu-button-icon network", - child: Widget.Icon({ - tooltip_text: - accPoint.ssid === - network.wifi.ssid - ? network.wifi.state - : null, - icon: `${accPoint["iconName"]}`, - }), - }), - Widget.Label({ - class_name: - "menu-button-name network", - truncate: "end", - wrap: true, - label: accPoint.ssid, - }), - ], - }), - ], - }), - ], - }), - }), - - Widget.Revealer({ - transition: "slide_down", - reveal_child: pendingAuth - .bind("value") - .as((v) => (v === accPoint.bssid ? true : false)), - class_name: "network-password-input-container", - child: Widget.Box({ - hexpand: true, - children: [ - Widget.Box({ - child: Widget.Entry({ - hpack: "start", - class_name: "network-password-input", - placeholder_text: "enter password", - visibility: false, - onAccept: (selfInp) => { - Utils.execAsync( - `nmcli dev wifi connect ${accPoint.bssid} password ${selfInp.text}`, - ) - .catch((err) => { - pendingAuth.value = ""; - console.error( - `Failed to connect to wifi: ${accPoint.ssid}... ${err}`, - ); - }) - .then(() => (pendingAuth.value = "")); - selfInp.text = ""; - }, - }), - }), - Widget.Box({ - class_name: - "network-password-input-close-container", - hexpand: true, - child: Widget.Button({ - class_name: "network-password-input-close", - on_primary_click: () => - (pendingAuth.value = ""), - child: Widget.Label("󰅜 "), - }), - }), - ], - }), - }), - ], - })); - } else { - self.children = []; - } - }); - }, - }), - Widget.Box({ - vertical: true, - setup: (self) => { - self.hook(network, () => { - let sortedNetworks = []; - - self.hook(pendingAuth, () => { - if (network.wifi.access_points.length > 0) { - sortedNetworks = network.wifi.access_points - .filter((ap) => { - return ( - ap.ssid !== "Unknown" && - ap.bssid !== pendingAuth.value && - !ap.active && - network.wifi.ssid !== ap.ssid - ); - }) - .sort((a, b) => { - return b.strength - a.strength; - }); - } - - if (sortedNetworks.length <= 0) { - return self.children = [ - Widget.Label({ - class_name: "not-found-label dim", - expand: true, - hpack: "center", - vpack: "center", - label: "No Wifi Networks Found" - }) - ] - } - - return (self.children = sortedNetworks.map((accPoint) => { - return Widget.Box({ - vertical: true, - children: [ - Widget.Button({ - on_primary_click: () => { - Utils.execAsync( - `nmcli device wifi connect ${accPoint.bssid}`, - ).catch((err) => { - if ( - err - .toLowerCase() - .includes( - "secrets were required, but not provided", - ) - ) { - pendingAuth.value = accPoint.bssid; - } - }); - }, - class_name: "network-element-item", - child: Widget.Box({ - children: [ - Widget.Box({ - hpack: "start", - vertical: true, - children: [ - Widget.Box({ - class_name: - "network-element-items-container", - children: [ - Widget.Button({ - class_name: - "menu-button-icon network", - child: Widget.Icon({ - tooltip_text: - accPoint.ssid === - network.wifi.ssid - ? network.wifi.state - : null, - icon: `${accPoint["iconName"]}`, - }), - }), - Widget.Label({ - class_name: - "menu-button-name network", - truncate: "end", - wrap: true, - label: accPoint.ssid, - }), - ], - }), - ], - }), - ], - }), - }), - Widget.Revealer({ - transition: "slide_down", - reveal_child: pendingAuth - .bind("value") - .as((v) => - v === accPoint.bssid ? true : false, - ), - class_name: "network-password-input-container", - child: Widget.Box({ - hexpand: true, - children: [ - Widget.Entry({ - hexpand: true, - class_name: "network-password-input", - placeholder_text: "enter password", - visibility: false, - onAccept: (selfInp) => { - selfInp.text = ""; - }, - }), - ], - }), - }), - ], - }); - })); - }); - }); - }, - }), - ], - }), - ], + children: [Ethernet(), Wifi()], }), }), }); diff --git a/modules/menus/notifications/index.js b/modules/menus/notifications/index.js index 1a83df2..b9f7da5 100644 --- a/modules/menus/notifications/index.js +++ b/modules/menus/notifications/index.js @@ -196,70 +196,77 @@ export default () => { return (self.children = sortedNotifications.map((notif) => { return Widget.Box({ - class_name: "notification-card menu", - vpack: "center", - hexpand: true, + class_name: "notification-card-content-container", children: [ - ...imageContainer(notif), Widget.Box({ + class_name: "notification-card menu", vpack: "center", - vertical: true, hexpand: true, - class_name: `notification-card-content ${notif.image === undefined ? "noimg" : " menu"}`, children: [ + ...imageContainer(notif), Widget.Box({ - vertical: false, + vpack: "center", + vertical: true, hexpand: true, + class_name: `notification-card-content ${notif.image === undefined ? "noimg" : " menu"}`, children: [ Widget.Box({ - class_name: "notification-card-header menu", + vertical: false, hexpand: true, - vpack: "start", children: [ - Widget.Label({ + Widget.Box({ class_name: - "notification-card-header-label menu", - hpack: "start", + "notification-card-header menu", hexpand: true, - vexpand: true, - max_width_chars: - notif.image === undefined ? 27 : 20, - truncate: "end", - wrap: true, - label: notif["summary"], + vpack: "start", + children: [ + Widget.Label({ + class_name: + "notification-card-header-label menu", + hpack: "start", + hexpand: true, + vexpand: true, + max_width_chars: + notif.image === undefined ? 27 : 20, + truncate: "end", + wrap: true, + label: notif["summary"], + }), + ], + }), + Widget.Box({ + class_name: + "notification-card-header menu", + hexpand: true, + hpack: "end", + children: [NotificationIcon(notif)], }), ], }), Widget.Box({ - class_name: "notification-card-header menu", + vpack: "start", hexpand: true, - hpack: "end", - children: [NotificationIcon(notif)], + class_name: "notification-card-body menu", + children: [ + Widget.Label({ + hexpand: true, + use_markup: true, + xalign: 0, + justification: "left", + truncate: "end", + lines: 2, + max_width_chars: + notif.image === undefined ? 35 : 28, + wrap: true, + class_name: + "notification-card-body-label menu", + label: notif["body"], + }), + ], }), + ...actionsContainer(notif), ], }), - Widget.Box({ - vpack: "start", - hexpand: true, - class_name: "notification-card-body menu", - children: [ - Widget.Label({ - hexpand: true, - use_markup: true, - xalign: 0, - justification: "left", - truncate: "end", - lines: 2, - max_width_chars: - notif.image === undefined ? 35 : 28, - wrap: true, - class_name: - "notification-card-body-label menu", - label: notif["body"], - }), - ], - }), - ...actionsContainer(notif), ], }), Widget.Button({ diff --git a/scss/menus/menu.scss b/scss/menus/menu.scss index 2344828..f5321e2 100644 --- a/scss/menus/menu.scss +++ b/scss/menus/menu.scss @@ -103,6 +103,8 @@ tooltip label { } .menu-section-container { + margin: 1.35em 0em; + .menu-label { color: $text; font-size: 1.1em; @@ -118,16 +120,18 @@ tooltip label { min-height: 2em; } - margin: 1.35em 0em; - - &.volume { + &:first-child { margin-bottom: 0em; } - &.input { + &:last-child { margin-top: 0em; } + &:nth-child(2) { + margin-top: 1.35em; + } + .menu-items-section { background: $base; border-radius: 0.4em; @@ -135,13 +139,6 @@ tooltip label { border-top-right-radius: 0em; padding: 0.9em; margin: 0em 1.35em; - - &.selected { - margin-bottom: 0em; - } - &.input { - margin-top: 0em; - } } } @@ -232,6 +229,10 @@ tooltip label { font-weight: bold; color: $overlay0; margin-right: .5rem; + + &.active { + color: $maroon; + } } .menu-item-box { diff --git a/scss/menus/network.scss b/scss/menus/network.scss index 3d787c2..4663162 100644 --- a/scss/menus/network.scss +++ b/scss/menus/network.scss @@ -1,91 +1,38 @@ @import "../colors"; -.menu-dropdown-label.network { - color: $mauve; -} - -.network-element-item-ethernet.multi { - margin-bottom: 0.5rem; -} - -.menu-button-name.status.network { - margin-left: 2.5rem; -} - -.menu-label.network { - color: $mauve; -} - -.network-element-items-container * { - font-size: 0.95em; -} - -.network-element-item { - &:not(:last-child) { - margin-bottom: 0.4em; +.menu-items-container.network { + .menu-items-section { + padding-bottom: 1.5em; } - - &:hover { - color: $mauve; - } -} - -.menu-button-icon.network { - color: $overlay2; -} - -.network-password-input { - border-radius: 0.4rem; - background: $crust; - padding: 0.4rem; - margin-left: 2.5rem; - margin-bottom: 0.5rem; - font-size: 0.85em; -} - -.menu-icon-button.refresh.network { - margin-bottom: 1rem; - - &:hover { - color: $mauve; - } -} - -.network-password-input-close { - margin-left: 0.75rem; - margin-bottom: 0.6rem; - - &:hover { - color: $sky; - } - - label { - font-size: 1.45em; - } -} - -.menu-icon-button.network.disconnect { - margin-bottom: 1.4rem; - margin-right: 0.5rem; - - &:hover { + .menu-label { color: $mauve; } - label { - font-size: 1.2rem; - } -} - -.menu-icon-button.network.forget { - margin-bottom: 1.4rem; - margin-right: 0.5rem; - - &:hover { + .network-ethernet-icon { + font-size: 1.3em; color: $mauve; } - label { - font-size: 1.35em; + .connection-container { + margin-left: 1em; + } + .connection-status { + font-size: 0.9em; + } + .menu-section-container.wifi { + .menu-items-section { + min-height: 5em; + } + } + + .network-element-item { + + &:not(:last-child) { + margin-bottom: 0.5em; + } + + &:hover { + color: $mauve; + } } } diff --git a/scss/menus/notifications.scss b/scss/menus/notifications.scss index 7fef961..069ae27 100644 --- a/scss/menus/notifications.scss +++ b/scss/menus/notifications.scss @@ -32,6 +32,15 @@ margin: 0em; } +.notification-card-content-container { + &:first-child { + margin-top: 0.5em; + } + &:not(:last-child) { + margin-bottom: 1em; + } +} + .menu-label-container.notifications { margin: 0em; padding: 0em; diff --git a/style.css b/style.css index e5cb777..1dcfa37 100644 --- a/style.css +++ b/style.css @@ -523,12 +523,15 @@ tooltip label { margin: 0em 1.35em; min-height: 2em; } -.menu-section-container.volume { +.menu-section-container:first-child { margin-bottom: 0em; } -.menu-section-container.input { +.menu-section-container:last-child { margin-top: 0em; } +.menu-section-container:nth-child(2) { + margin-top: 1.35em; +} .menu-section-container .menu-items-section { background: #1e1e2e; border-radius: 0.4em; @@ -537,12 +540,6 @@ tooltip label { padding: 0.9em; margin: 0em 1.35em; } -.menu-section-container .menu-items-section.selected { - margin-bottom: 0em; -} -.menu-section-container .menu-items-section.input { - margin-top: 0em; -} .menu-active { font-size: 0.9em; @@ -628,6 +625,9 @@ tooltip label { color: #6c7086; margin-right: 0.5rem; } +.menu-button-icon.active { + color: #eba0ac; +} .menu-item-box { margin-bottom: 0.5rem; @@ -826,86 +826,32 @@ window#powermenu .powermenu.box { color: #eba0ac; } -.menu-dropdown-label.network { +.menu-items-container.network .menu-items-section { + padding-bottom: 1.5em; +} +.menu-items-container.network .menu-label { color: #cba6f7; } - -.network-element-item-ethernet.multi { - margin-bottom: 0.5rem; -} - -.menu-button-name.status.network { - margin-left: 2.5rem; -} - -.menu-label.network { +.menu-items-container.network .network-ethernet-icon { + font-size: 1.3em; color: #cba6f7; } - -.network-element-items-container * { - font-size: 0.95em; +.menu-items-container.network .connection-container { + margin-left: 1em; } - -.network-element-item:not(:last-child) { - margin-bottom: 0.4em; +.menu-items-container.network .connection-status { + font-size: 0.9em; } -.network-element-item:hover { +.menu-items-container.network .menu-section-container.wifi .menu-items-section { + min-height: 5em; +} +.menu-items-container.network .network-element-item:not(:last-child) { + margin-bottom: 0.5em; +} +.menu-items-container.network .network-element-item:hover { color: #cba6f7; } -.menu-button-icon.network { - color: #9399b2; -} - -.network-password-input { - border-radius: 0.4rem; - background: #11111b; - padding: 0.4rem; - margin-left: 2.5rem; - margin-bottom: 0.5rem; - font-size: 0.85em; -} - -.menu-icon-button.refresh.network { - margin-bottom: 1rem; -} -.menu-icon-button.refresh.network:hover { - color: #cba6f7; -} - -.network-password-input-close { - margin-left: 0.75rem; - margin-bottom: 0.6rem; -} -.network-password-input-close:hover { - color: #89dceb; -} -.network-password-input-close label { - font-size: 1.45em; -} - -.menu-icon-button.network.disconnect { - margin-bottom: 1.4rem; - margin-right: 0.5rem; -} -.menu-icon-button.network.disconnect:hover { - color: #cba6f7; -} -.menu-icon-button.network.disconnect label { - font-size: 1.2rem; -} - -.menu-icon-button.network.forget { - margin-bottom: 1.4rem; - margin-right: 0.5rem; -} -.menu-icon-button.network.forget:hover { - color: #cba6f7; -} -.menu-icon-button.network.forget label { - font-size: 1.35em; -} - .menu-dropdown-label.bluetooth { color: #89dceb; } @@ -1093,6 +1039,13 @@ image { margin: 0em; } +.notification-card-content-container:first-child { + margin-top: 0.5em; +} +.notification-card-content-container:not(:last-child) { + margin-bottom: 1em; +} + .menu-label-container.notifications { margin: 0em; padding: 0em; diff --git a/style.css.map b/style.css.map index 6692a27..8ec5dc1 100644 --- a/style.css.map +++ b/style.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["scss/main.scss","scss/common/common.scss","scss/colors.scss","scss/common/widget-button.scss","scss/bar/menu.scss","scss/bar/audio.scss","scss/bar/media.scss","scss/bar/network.scss","scss/bar/bluetooth.scss","scss/bar/clock.scss","scss/bar/workspace.scss","scss/bar/window_title.scss","scss/bar/systray.scss","scss/bar/notifications.scss","scss/bar/power.scss","scss/bar/bar.scss","scss/menus/menu.scss","scss/menus/power.scss","scss/common/floating-widget.scss","scss/menus/audiomenu.scss","scss/menus/network.scss","scss/menus/bluetooth.scss","scss/menus/media.scss","scss/menus/notifications.scss","scss/menus/calendar.scss","scss/notifications/popups.scss"],"names":[],"mappings":"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","file":"style.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["scss/main.scss","scss/common/common.scss","scss/colors.scss","scss/common/widget-button.scss","scss/bar/menu.scss","scss/bar/audio.scss","scss/bar/media.scss","scss/bar/network.scss","scss/bar/bluetooth.scss","scss/bar/clock.scss","scss/bar/workspace.scss","scss/bar/window_title.scss","scss/bar/systray.scss","scss/bar/notifications.scss","scss/bar/power.scss","scss/bar/bar.scss","scss/menus/menu.scss","scss/menus/power.scss","scss/common/floating-widget.scss","scss/menus/audiomenu.scss","scss/menus/network.scss","scss/menus/bluetooth.scss","scss/menus/media.scss","scss/menus/notifications.scss","scss/menus/calendar.scss","scss/notifications/popups.scss"],"names":[],"mappings":"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","file":"style.css"} \ No newline at end of file