From fcee7ce6f926b910686937dbf6079b4eaaa59eb4 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 17 Nov 2025 23:43:25 +0100 Subject: [PATCH] refractor quick toggles data, add volume slider for waffles action center --- .../ii/assets/icons/fluent/chevron-right.svg | 1 + .../assets/icons/fluent/speaker-settings.svg | 1 + .../quickshell/ii/modules/common/Config.qml | 5 +- .../quickToggles/AntiFlashbangToggle.qml | 17 +++ .../models/quickToggles/AudioToggle.qml | 17 +++ .../models/quickToggles/BluetoothToggle.qml | 23 ++++ .../quickToggles/CloudflareWarpToggle.qml | 78 ++++++++++++ .../models/quickToggles/ColorPickerToggle.qml | 29 +++++ .../models/quickToggles/DarkModeToggle.qml | 25 ++++ .../models/quickToggles/EasyEffectsToggle.qml | 30 +++++ .../models/quickToggles/GameModeToggle.qml | 33 +++++ .../quickToggles/IdleInhibitorToggle.qml | 18 +++ .../common/models/quickToggles/MicToggle.qml | 20 ++++ .../quickToggles/MusicRecognitionToggle.qml | 25 ++++ .../models/quickToggles/NetworkToggle.qml | 16 +++ .../models/quickToggles/NightLightToggle.qml | 28 +++++ .../quickToggles/NotificationToggle.qml | 20 ++++ .../quickToggles/OnScreenKeyboardToggle.qml | 19 +++ .../quickToggles/PowerProfilesToggle.qml | 39 ++++++ .../models/quickToggles/QuickToggleModel.qml | 22 ++++ .../models/quickToggles/ScreenSnipToggle.qml | 29 +++++ .../ii/modules/common/widgets/Circle.qml | 9 ++ .../ii/modules/ii/bar/BarContent.qml | 12 +- .../AndroidAntiFlashbangToggle.qml | 20 +--- .../androidStyle/AndroidAudioToggle.qml | 17 +-- .../androidStyle/AndroidBluetoothToggle.qml | 20 +--- .../AndroidCloudflareWarpToggle.qml | 71 +---------- .../androidStyle/AndroidColorPickerToggle.qml | 23 +--- .../androidStyle/AndroidDarkModeToggle.qml | 21 +--- .../androidStyle/AndroidEasyEffectsToggle.qml | 26 +--- .../androidStyle/AndroidGameModeToggle.qml | 28 +---- .../AndroidIdleInhibitorToggle.qml | 14 +-- .../androidStyle/AndroidMicToggle.qml | 19 +-- .../androidStyle/AndroidMusicRecognition.qml | 23 +--- .../androidStyle/AndroidNetworkToggle.qml | 14 +-- .../androidStyle/AndroidNightLightToggle.qml | 27 +---- .../AndroidNotificationToggle.qml | 16 +-- .../AndroidOnScreenKeyboardToggle.qml | 15 +-- .../AndroidPowerProfileToggle.qml | 34 +----- .../androidStyle/AndroidQuickToggleButton.qml | 36 ++++-- .../androidStyle/AndroidScreenSnipToggle.qml | 25 +--- .../ii/verticalBar/VerticalBarContent.qml | 12 +- .../waffle/actionCenter/ActionCenterBody.qml | 113 ++++++++++++++++++ .../actionCenter/ActionCenterContent.qml | 47 +------- .../actionCenter/ActionCenterFooter.qml | 49 ++++++++ .../actionCenter/ActionCenterToggle.qml | 40 +++++++ .../actionCenter/toggles/WNetworkToggle.qml | 16 +++ .../ii/modules/waffle/bar/SystemButton.qml | 18 +-- .../waffle/bar/tasks/TaskAppButton.qml | 1 + .../ii/modules/waffle/looks/Looks.qml | 5 + .../ii/modules/waffle/looks/WIcons.qml | 13 +- .../modules/waffle/looks/WPanelIconButton.qml | 23 ++++ .../ii/modules/waffle/looks/WSlider.qml | 81 +++++++++++++ dots/.config/quickshell/ii/services/Audio.qml | 24 +++- dots/.config/quickshell/ii/shell.qml | 2 +- 55 files changed, 939 insertions(+), 470 deletions(-) create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/chevron-right.svg create mode 100644 dots/.config/quickshell/ii/assets/icons/fluent/speaker-settings.svg create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/AntiFlashbangToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/AudioToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/BluetoothToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/CloudflareWarpToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/ColorPickerToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/DarkModeToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/EasyEffectsToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/GameModeToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/IdleInhibitorToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/MicToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/MusicRecognitionToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/NetworkToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/NightLightToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/NotificationToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/OnScreenKeyboardToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/PowerProfilesToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/QuickToggleModel.qml create mode 100644 dots/.config/quickshell/ii/modules/common/models/quickToggles/ScreenSnipToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/common/widgets/Circle.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterBody.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterFooter.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/actionCenter/toggles/WNetworkToggle.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WPanelIconButton.qml create mode 100644 dots/.config/quickshell/ii/modules/waffle/looks/WSlider.qml diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/chevron-right.svg b/dots/.config/quickshell/ii/assets/icons/fluent/chevron-right.svg new file mode 100644 index 000000000..0ac6a30d5 --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/chevron-right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dots/.config/quickshell/ii/assets/icons/fluent/speaker-settings.svg b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-settings.svg new file mode 100644 index 000000000..072abd842 --- /dev/null +++ b/dots/.config/quickshell/ii/assets/icons/fluent/speaker-settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index ec47c514b..32d377530 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -572,7 +572,7 @@ Singleton { } property JsonObject waffles: JsonObject { - // Animations on Windoes are kinda janky. Set the following to + // Animations on Windoes are kinda janky. Setting the following to // false will make (some) stuff also be like that for accuracy. // Example: the right-click menu of the Start button property bool smootherAnimations: true @@ -580,6 +580,9 @@ Singleton { property bool bottom: true property bool leftAlignApps: false } + property JsonObject actionCenter: JsonObject { + property list toggles: [] + } } } } diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/AntiFlashbangToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/AntiFlashbangToggle.qml new file mode 100644 index 000000000..088434ad7 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/AntiFlashbangToggle.qml @@ -0,0 +1,17 @@ +import QtQuick +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Anti-flashbang") + tooltipText: Translation.tr("Anti-flashbang") + icon: "flash_off" + toggled: Config.options.light.antiFlashbang.enable + + mainAction: () => { + Config.options.light.antiFlashbang.enable = !Config.options.light.antiFlashbang.enable; + } + hasMenu: true +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/AudioToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/AudioToggle.qml new file mode 100644 index 000000000..3f79674da --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/AudioToggle.qml @@ -0,0 +1,17 @@ +import QtQuick +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Audio output") + statusText: toggled ? Translation.tr("Unmuted") : Translation.tr("Muted") + tooltipText: Translation.tr("Audio output | Right-click for volume mixer & device selector") + toggled: !Audio.sink?.audio?.muted + icon: Audio.sink?.audio?.muted ? "volume_off" : "volume_up" + mainAction: () => { + Audio.toggleMute() + } + hasMenu: true +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/BluetoothToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/BluetoothToggle.qml new file mode 100644 index 000000000..11b920cb2 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/BluetoothToggle.qml @@ -0,0 +1,23 @@ +import QtQuick +import Quickshell.Bluetooth +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Bluetooth") + statusText: BluetoothStatus.firstActiveDevice?.name ?? Translation.tr("No device") + tooltipText: Translation.tr("%1 | Right-click to configure").arg( + (BluetoothStatus.firstActiveDevice?.name ?? Translation.tr("Bluetooth")) + + (BluetoothStatus.activeDeviceCount > 1 ? ` +${BluetoothStatus.activeDeviceCount - 1}` : "") + ) + icon: BluetoothStatus.connected ? "bluetooth_connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth_disabled" + + available: BluetoothStatus.available + toggled: BluetoothStatus.enabled + mainAction: () => { + Bluetooth.defaultAdapter.enabled = !Bluetooth.defaultAdapter?.enabled + } + hasMenu: true +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/CloudflareWarpToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/CloudflareWarpToggle.qml new file mode 100644 index 000000000..015010cf7 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/CloudflareWarpToggle.qml @@ -0,0 +1,78 @@ +import QtQuick +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets +import Quickshell +import Quickshell.Io + +QuickToggleModel { + id: root + name: Translation.tr("Cloudflare WARP") + + toggled: false + icon: "cloud_lock" + + mainAction: () => { + if (toggled) { + root.toggled = false + Quickshell.execDetached(["warp-cli", "disconnect"]) + } else { + root.toggled = true + Quickshell.execDetached(["warp-cli", "connect"]) + } + } + + Process { + id: connectProc + command: ["warp-cli", "connect"] + onExited: (exitCode, exitStatus) => { + if (exitCode !== 0) { + Quickshell.execDetached(["notify-send", + Translation.tr("Cloudflare WARP"), + Translation.tr("Connection failed. Please inspect manually with the warp-cli command") + , "-a", "Shell" + ]) + } + } + } + + Process { + id: registrationProc + command: ["warp-cli", "registration", "new"] + onExited: (exitCode, exitStatus) => { + console.log("Warp registration exited with code and status:", exitCode, exitStatus) + if (exitCode === 0) { + connectProc.running = true + } else { + Quickshell.execDetached(["notify-send", + Translation.tr("Cloudflare WARP"), + Translation.tr("Registration failed. Please inspect manually with the warp-cli command"), + "-a", "Shell" + ]) + } + } + } + + Process { + id: fetchActiveState + running: true + command: ["bash", "-c", "warp-cli status"] + stdout: StdioCollector { + id: warpStatusCollector + onStreamFinished: { + if (warpStatusCollector.text.length > 0) { + root.available = true + } + if (warpStatusCollector.text.includes("Unable")) { + registrationProc.running = true + } else if (warpStatusCollector.text.includes("Connected")) { + root.toggled = true + } else if (warpStatusCollector.text.includes("Disconnected")) { + root.toggled = false + } + } + } + } + tooltipText: Translation.tr("Cloudflare WARP (1.1.1.1)") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/ColorPickerToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/ColorPickerToggle.qml new file mode 100644 index 000000000..611e256c5 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/ColorPickerToggle.qml @@ -0,0 +1,29 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Color picker") + hasStatusText: false + toggled: false + icon: "colorize" + + mainAction: () => { + GlobalStates.sidebarRightOpen = false; + delayedActionTimer.start(); + } + Timer { + id: delayedActionTimer + interval: 300 + repeat: false + onTriggered: { + Quickshell.execDetached(["hyprpicker", "-a"]); + } + } + + tooltipText: Translation.tr("Color picker") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/DarkModeToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/DarkModeToggle.qml new file mode 100644 index 000000000..8a98f6f51 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/DarkModeToggle.qml @@ -0,0 +1,25 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Dark Mode") + statusText: Appearance.m3colors.darkmode ? Translation.tr("Dark") : Translation.tr("Light") + + toggled: Appearance.m3colors.darkmode + icon: "contrast" + + mainAction: () => { + if (Appearance.m3colors.darkmode) { + Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "light", "--noswitch"]); + } else { + Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "dark", "--noswitch"]); + } + } + + tooltipText: Translation.tr("Dark Mode") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/EasyEffectsToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/EasyEffectsToggle.qml new file mode 100644 index 000000000..4f76c09cc --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/EasyEffectsToggle.qml @@ -0,0 +1,30 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("EasyEffects") + + available: EasyEffects.available + toggled: EasyEffects.active + icon: "graphic_eq" + + Component.onCompleted: { + EasyEffects.fetchActiveState() + } + + mainAction: () => { + EasyEffects.toggle() + } + + altAction: () => { + Quickshell.execDetached(["bash", "-c", "flatpak run com.github.wwmm.easyeffects || easyeffects"]) + GlobalStates.sidebarRightOpen = false + } + + tooltipText: Translation.tr("EasyEffects | Right-click to configure") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/GameModeToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/GameModeToggle.qml new file mode 100644 index 000000000..d8ba7402b --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/GameModeToggle.qml @@ -0,0 +1,33 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + id: root + name: Translation.tr("Game mode") + toggled: toggled + icon: "gamepad" + + mainAction: () => { + root.toggled = !root.toggled + if (root.toggled) { + Quickshell.execDetached(["bash", "-c", `hyprctl --batch "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"`]) + } else { + Quickshell.execDetached(["hyprctl", "reload"]) + } + } + Process { + id: fetchActiveState + running: true + command: ["bash", "-c", `test "$(hyprctl getoption animations:enabled -j | jq ".int")" -ne 0`] + onExited: (exitCode, exitStatus) => { + root.toggled = exitCode !== 0 // Inverted because enabled = nonzero exit + } + } + tooltipText: Translation.tr("Game mode") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/IdleInhibitorToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/IdleInhibitorToggle.qml new file mode 100644 index 000000000..b6cf252bb --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/IdleInhibitorToggle.qml @@ -0,0 +1,18 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Keep awake") + + toggled: Idle.inhibit + icon: "coffee" + mainAction: () => { + Idle.toggleInhibit() + } + tooltipText: Translation.tr("Keep system awake") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/MicToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/MicToggle.qml new file mode 100644 index 000000000..ced0cb03e --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/MicToggle.qml @@ -0,0 +1,20 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Audio input") + statusText: toggled ? Translation.tr("Enabled") : Translation.tr("Muted") + toggled: !Audio.source?.audio?.muted + icon: Audio.source?.audio?.muted ? "mic_off" : "mic" + mainAction: () => { + Audio.toggleMicMute() + } + hasMenu: true + + tooltipText: Translation.tr("Audio input | Right-click for volume mixer & device selector") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/MusicRecognitionToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/MusicRecognitionToggle.qml new file mode 100644 index 000000000..36f161a7d --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/MusicRecognitionToggle.qml @@ -0,0 +1,25 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + toggled: SongRec.running + property bool sourceIsMonitor: SongRec.monitorSource === SongRec.MonitorSource.Monitor + + name: Translation.tr("Identify Music") + statusText: toggled ? Translation.tr("Listening...") : sourceIsMonitor ? Translation.tr("System sound") : Translation.tr("Microphone") + icon: toggled ? "music_cast" : (sourceIsMonitor ? "music_note" : "frame_person_mic") + + tooltipText: Translation.tr("Recognize music | Right-click to toggle source") + + mainAction: () => { + SongRec.toggleRunning() + } + altAction: () => { + SongRec.toggleMonitorSource() + } +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/NetworkToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/NetworkToggle.qml new file mode 100644 index 000000000..f6f412d01 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/NetworkToggle.qml @@ -0,0 +1,16 @@ +import QtQuick +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Internet") + statusText: Network.networkName + tooltipText: Translation.tr("%1 | Right-click to configure").arg(Network.networkName) + icon: Network.materialSymbol + + toggled: Network.wifiStatus !== "disabled" + mainAction: () => Network.toggleWifi() + hasMenu: true +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/NightLightToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/NightLightToggle.qml new file mode 100644 index 000000000..d53af9740 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/NightLightToggle.qml @@ -0,0 +1,28 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + property bool auto: Config.options.light.night.automatic + + name: Translation.tr("Night Light") + statusText: (auto ? Translation.tr("Auto, ") : "") + (toggled ? Translation.tr("Active") : Translation.tr("Inactive")) + + toggled: Hyprsunset.active + icon: auto ? "night_sight_auto" : "bedtime" + + mainAction: () => { + Hyprsunset.toggle() + } + hasMenu: true + + Component.onCompleted: { + Hyprsunset.fetchState() + } + + tooltipText: Translation.tr("Night Light | Right-click to configure") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/NotificationToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/NotificationToggle.qml new file mode 100644 index 000000000..3c4c87146 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/NotificationToggle.qml @@ -0,0 +1,20 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Notifications") + statusText: toggled ? Translation.tr("Show") : Translation.tr("Silent") + toggled: !Notifications.silent + icon: toggled ? "notifications_active" : "notifications_paused" + + mainAction: () => { + Notifications.silent = !Notifications.silent; + } + + tooltipText: Translation.tr("Show notifications") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/OnScreenKeyboardToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/OnScreenKeyboardToggle.qml new file mode 100644 index 000000000..f98ee5a47 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/OnScreenKeyboardToggle.qml @@ -0,0 +1,19 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Virtual Keyboard") + toggled: GlobalStates.oskOpen + icon: toggled ? "keyboard_hide" : "keyboard" + + mainAction: () => { + GlobalStates.oskOpen = !GlobalStates.oskOpen + } + + tooltipText: Translation.tr("On-screen keyboard") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/PowerProfilesToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/PowerProfilesToggle.qml new file mode 100644 index 000000000..ff4ab19ce --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/PowerProfilesToggle.qml @@ -0,0 +1,39 @@ +import QtQuick +import Quickshell +import Quickshell.Services.UPower +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Power Profile") + toggled: PowerProfiles.profile !== PowerProfile.Balanced + icon: switch(PowerProfiles.profile) { + case PowerProfile.PowerSaver: return "energy_savings_leaf" + case PowerProfile.Balanced: return "settings_slow_motion" + case PowerProfile.Performance: return "local_fire_department" + } + statusText: switch(PowerProfiles.profile) { + case PowerProfile.PowerSaver: return "Power Saver" + case PowerProfile.Balanced: return "Balanced" + case PowerProfile.Performance: return "Performance" + } + + mainAction: () => { + if (PowerProfiles.hasPerformanceProfile) { + switch(PowerProfiles.profile) { + case PowerProfile.PowerSaver: PowerProfiles.profile = PowerProfile.Balanced + break; + case PowerProfile.Balanced: PowerProfiles.profile = PowerProfile.Performance + break; + case PowerProfile.Performance: PowerProfiles.profile = PowerProfile.PowerSaver + break; + } + } else { + PowerProfiles.profile = PowerProfiles.profile == PowerProfile.Balanced ? PowerProfile.PowerSaver : PowerProfile.Balanced + } + } + tooltipText: Translation.tr("Click to cycle through power profiles") +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/QuickToggleModel.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/QuickToggleModel.qml new file mode 100644 index 000000000..176edcb48 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/QuickToggleModel.qml @@ -0,0 +1,22 @@ +import QtQuick + +QtObject { + // Textual info + required property string name + property string statusText + property string tooltipText: "" + property string icon: "close" + + // State + property bool hasStatusText: true + property bool available: true + property bool toggled: false + + // Interactions + required property var mainAction + property bool hasMenu: false + property var altAction: null + + // Allow stuff like Processes to be declared freely + default property list data +} diff --git a/dots/.config/quickshell/ii/modules/common/models/quickToggles/ScreenSnipToggle.qml b/dots/.config/quickshell/ii/modules/common/models/quickToggles/ScreenSnipToggle.qml new file mode 100644 index 000000000..28c53334a --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/models/quickToggles/ScreenSnipToggle.qml @@ -0,0 +1,29 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets + +QuickToggleModel { + name: Translation.tr("Screen snip") + hasStatusText: false + toggled: false + icon: "screenshot_region" + + mainAction: () => { + GlobalStates.sidebarRightOpen = false; + delayedActionTimer.start(); + } + Timer { + id: delayedActionTimer + interval: 300 + repeat: false + onTriggered: { + Quickshell.execDetached(["qs", "-p", Quickshell.shellPath(""), "ipc", "call", "region", "screenshot"]); + } + } + + tooltipText: Translation.tr("Screen snip") +} diff --git a/dots/.config/quickshell/ii/modules/common/widgets/Circle.qml b/dots/.config/quickshell/ii/modules/common/widgets/Circle.qml new file mode 100644 index 000000000..ed137a94d --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/widgets/Circle.qml @@ -0,0 +1,9 @@ +import QtQuick + +Rectangle { + property double diameter + + implicitWidth: diameter + implicitHeight: diameter + radius: diameter / 2 +} diff --git a/dots/.config/quickshell/ii/modules/ii/bar/BarContent.qml b/dots/.config/quickshell/ii/modules/ii/bar/BarContent.qml index 997e0209b..04f13d1aa 100644 --- a/dots/.config/quickshell/ii/modules/ii/bar/BarContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/bar/BarContent.qml @@ -197,16 +197,8 @@ Item { // Bar content region implicitWidth: rightSectionRowLayout.implicitWidth implicitHeight: Appearance.sizes.baseBarHeight - onScrollDown: { - const currentVolume = Audio.value; - const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; - Audio.sink.audio.volume -= step; - } - onScrollUp: { - const currentVolume = Audio.value; - const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; - Audio.sink.audio.volume = Math.min(1, Audio.sink.audio.volume + step); - } + onScrollDown: Audio.decrementVolume(); + onScrollUp: Audio.incrementVolume(); onMovedAway: GlobalStates.osdVolumeOpen = false; onPressed: event => { if (event.button === Qt.LeftButton) { diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidAntiFlashbangToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidAntiFlashbangToggle.qml index 4fc8ee4f5..f07d6c2db 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidAntiFlashbangToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidAntiFlashbangToggle.qml @@ -1,3 +1,4 @@ +import qs.modules.common.models.quickToggles import qs.modules.common import qs.modules.common.widgets import qs.services @@ -6,24 +7,7 @@ import Quickshell AndroidQuickToggleButton { id: root - - property bool auto: Config.options.light.night.automatic - name: Translation.tr("Anti-flashbang") - - toggled: Config.options.light.antiFlashbang.enable - buttonIcon: "flash_off" - - mainAction: () => { - Config.options.light.antiFlashbang.enable = !Config.options.light.antiFlashbang.enable; - } - - altAction: () => { - root.openMenu() - } - - StyledToolTip { - text: Translation.tr("Anti-flashbang") - } + toggleModel: AntiFlashbangToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidAudioToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidAudioToggle.qml index 52f7459a7..4a0ee5b34 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidAudioToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidAudioToggle.qml @@ -1,5 +1,6 @@ import qs import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick @@ -8,19 +9,5 @@ import Quickshell AndroidQuickToggleButton { id: root - name: Translation.tr("Audio output") - statusText: toggled ? Translation.tr("Unmuted") : Translation.tr("Muted") - toggled: !Audio.sink?.audio?.muted - buttonIcon: Audio.sink?.audio?.muted ? "volume_off" : "volume_up" - mainAction: () => { - Audio.sink.audio.muted = !Audio.sink.audio.muted - } - - altAction: () => { - root.openMenu() - } - - StyledToolTip { - text: Translation.tr("Audio output | Right-click for volume mixer & device selector") - } + toggleModel: AudioToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml index d592de63b..c0ab7d5c0 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidBluetoothToggle.qml @@ -1,5 +1,6 @@ import qs.services import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.functions import qs.modules.common.widgets import QtQuick @@ -9,22 +10,5 @@ import Quickshell.Bluetooth AndroidQuickToggleButton { id: root - name: Translation.tr("Bluetooth") - statusText: BluetoothStatus.firstActiveDevice?.name ?? Translation.tr("No device") - - available: BluetoothStatus.available - toggled: BluetoothStatus.enabled - buttonIcon: BluetoothStatus.connected ? "bluetooth_connected" : BluetoothStatus.enabled ? "bluetooth" : "bluetooth_disabled" - mainAction: () => { - Bluetooth.defaultAdapter.enabled = !Bluetooth.defaultAdapter?.enabled - } - altAction: () => { - root.openMenu() - } - StyledToolTip { - text: Translation.tr("%1 | Right-click to configure").arg( - (BluetoothStatus.firstActiveDevice?.name ?? Translation.tr("Bluetooth")) - + (BluetoothStatus.activeDeviceCount > 1 ? ` +${BluetoothStatus.activeDeviceCount - 1}` : "") - ) - } + toggleModel: BluetoothToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidCloudflareWarpToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidCloudflareWarpToggle.qml index 5b65e673d..9385133bb 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidCloudflareWarpToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidCloudflareWarpToggle.qml @@ -1,4 +1,5 @@ import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick @@ -8,73 +9,5 @@ import Quickshell.Io AndroidQuickToggleButton { id: root - name: Translation.tr("Cloudflare WARP") - - toggled: false - buttonIcon: "cloud_lock" - - mainAction: () => { - if (toggled) { - root.toggled = false - Quickshell.execDetached(["warp-cli", "disconnect"]) - } else { - root.toggled = true - Quickshell.execDetached(["warp-cli", "connect"]) - } - } - - Process { - id: connectProc - command: ["warp-cli", "connect"] - onExited: (exitCode, exitStatus) => { - if (exitCode !== 0) { - Quickshell.execDetached(["notify-send", - Translation.tr("Cloudflare WARP"), - Translation.tr("Connection failed. Please inspect manually with the warp-cli command") - , "-a", "Shell" - ]) - } - } - } - - Process { - id: registrationProc - command: ["warp-cli", "registration", "new"] - onExited: (exitCode, exitStatus) => { - console.log("Warp registration exited with code and status:", exitCode, exitStatus) - if (exitCode === 0) { - connectProc.running = true - } else { - Quickshell.execDetached(["notify-send", - Translation.tr("Cloudflare WARP"), - Translation.tr("Registration failed. Please inspect manually with the warp-cli command"), - "-a", "Shell" - ]) - } - } - } - - Process { - id: fetchActiveState - running: true - command: ["bash", "-c", "warp-cli status"] - stdout: StdioCollector { - id: warpStatusCollector - onStreamFinished: { - if (warpStatusCollector.text.length > 0) { - root.visible = true - } - if (warpStatusCollector.text.includes("Unable")) { - registrationProc.running = true - } else if (warpStatusCollector.text.includes("Connected")) { - root.toggled = true - } else if (warpStatusCollector.text.includes("Disconnected")) { - root.toggled = false - } - } - } - } - StyledToolTip { - text: Translation.tr("Cloudflare WARP (1.1.1.1)") - } + toggleModel: CloudflareWarpToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidColorPickerToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidColorPickerToggle.qml index 8fdc59205..9319398bd 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidColorPickerToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidColorPickerToggle.qml @@ -1,5 +1,6 @@ import qs import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick @@ -8,25 +9,5 @@ import Quickshell AndroidQuickToggleButton { id: root - name: Translation.tr("Color picker") - statusText: "" - toggled: false - buttonIcon: "colorize" - - mainAction: () => { - GlobalStates.sidebarRightOpen = false; - delayedActionTimer.start() - } - Timer { - id: delayedActionTimer - interval: 300 - repeat: false - onTriggered: { - Quickshell.execDetached(["hyprpicker", "-a"]) - } - } - - StyledToolTip { - text: Translation.tr("Color picker") - } + toggleModel: ColorPickerToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidDarkModeToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidDarkModeToggle.qml index 11be0dae6..4defe6bdd 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidDarkModeToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidDarkModeToggle.qml @@ -1,27 +1,10 @@ import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick import Quickshell AndroidQuickToggleButton { - id: root - - name: Translation.tr("Dark Mode") - statusText: Appearance.m3colors.darkmode ? Translation.tr("Dark") : Translation.tr("Light") - - toggled: Appearance.m3colors.darkmode - buttonIcon: "contrast" - - mainAction: () => { - if (Appearance.m3colors.darkmode) { - Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "light", "--noswitch"]); - } else { - Quickshell.execDetached([Directories.wallpaperSwitchScriptPath, "--mode", "dark", "--noswitch"]); - } - } - - StyledToolTip { - text: Translation.tr("Dark Mode") - } + toggleModel: DarkModeToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml index 0ce6b7ab4..157d9236f 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidEasyEffectsToggle.qml @@ -1,33 +1,11 @@ import qs +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick import Quickshell AndroidQuickToggleButton { - id: root - - name: Translation.tr("EasyEffects") - - available: EasyEffects.available - toggled: EasyEffects.active - buttonIcon: "graphic_eq" - - Component.onCompleted: { - EasyEffects.fetchActiveState() - } - - mainAction: () => { - EasyEffects.toggle() - } - - altAction: () => { - Quickshell.execDetached(["bash", "-c", "flatpak run com.github.wwmm.easyeffects || easyeffects"]) - GlobalStates.sidebarRightOpen = false - } - - StyledToolTip { - text: Translation.tr("EasyEffects | Right-click to configure") - } + toggleModel: EasyEffectsToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidGameModeToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidGameModeToggle.qml index ae63622fe..ec3225e02 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidGameModeToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidGameModeToggle.qml @@ -1,4 +1,5 @@ import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick @@ -6,30 +7,5 @@ import Quickshell import Quickshell.Io AndroidQuickToggleButton { - id: root - - name: Translation.tr("Game mode") - statusText: "" - toggled: toggled - buttonIcon: "gamepad" - - mainAction: () => { - root.toggled = !root.toggled - if (root.toggled) { - Quickshell.execDetached(["bash", "-c", `hyprctl --batch "keyword animations:enabled 0; keyword decoration:shadow:enabled 0; keyword decoration:blur:enabled 0; keyword general:gaps_in 0; keyword general:gaps_out 0; keyword general:border_size 1; keyword decoration:rounding 0; keyword general:allow_tearing 1"`]) - } else { - Quickshell.execDetached(["hyprctl", "reload"]) - } - } - Process { - id: fetchActiveState - running: true - command: ["bash", "-c", `test "$(hyprctl getoption animations:enabled -j | jq ".int")" -ne 0`] - onExited: (exitCode, exitStatus) => { - root.toggled = exitCode !== 0 // Inverted because enabled = nonzero exit - } - } - StyledToolTip { - text: Translation.tr("Game mode") - } + toggleModel: GameModeToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidIdleInhibitorToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidIdleInhibitorToggle.qml index 2daf1f914..a42d6807c 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidIdleInhibitorToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidIdleInhibitorToggle.qml @@ -1,21 +1,11 @@ import qs.services import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.functions import qs.modules.common.widgets import QtQuick AndroidQuickToggleButton { - id: root - - name: Translation.tr("Keep awake") - - toggled: Idle.inhibit - buttonIcon: "coffee" - mainAction: () => { - Idle.toggleInhibit() - } - StyledToolTip { - text: Translation.tr("Keep system awake") - } + toggleModel: IdleInhibitorToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidMicToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidMicToggle.qml index 7ffeea7f7..55f36a3a4 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidMicToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidMicToggle.qml @@ -1,26 +1,11 @@ import qs import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick import Quickshell AndroidQuickToggleButton { - id: root - - name: Translation.tr("Audio input") - statusText: toggled ? Translation.tr("Enabled") : Translation.tr("Muted") - toggled: !Audio.source?.audio?.muted - buttonIcon: Audio.source?.audio?.muted ? "mic_off" : "mic" - mainAction: () => { - Audio.source.audio.muted = !Audio.source.audio.muted - } - - altAction: () => { - root.openMenu() - } - - StyledToolTip { - text: Translation.tr("Audio input | Right-click for volume mixer & device selector") - } + toggleModel: MicToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidMusicRecognition.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidMusicRecognition.qml index 23e2cda92..41139b048 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidMusicRecognition.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidMusicRecognition.qml @@ -1,5 +1,6 @@ import qs import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import QtQuick import Quickshell @@ -8,25 +9,5 @@ import qs.services AndroidQuickToggleButton { - id: root - - toggled: SongRec.running - property bool sourceIsMonitor: SongRec.monitorSource === SongRec.MonitorSource.Monitor - - name: Translation.tr("Identify Music") - statusText: toggled ? Translation.tr("Listening...") : sourceIsMonitor ? Translation.tr("System sound") : Translation.tr("Microphone") - buttonIcon: toggled ? "music_cast" : (sourceIsMonitor ? "music_note" : "frame_person_mic") - - StyledToolTip { - text: Translation.tr("Recognize music | Right-click to toggle source") - } - - mainAction: () => { - SongRec.toggleRunning() - } - - altAction: () => { - SongRec.toggleMonitorSource() - } - + toggleModel: MusicRecognitionToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNetworkToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNetworkToggle.qml index eaf24e141..d5b594ef1 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNetworkToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNetworkToggle.qml @@ -1,5 +1,6 @@ import qs.services import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.functions import qs.modules.common.widgets import QtQuick @@ -7,17 +8,6 @@ import QtQuick AndroidQuickToggleButton { id: root - name: Translation.tr("Internet") - statusText: Network.networkName - - toggled: Network.wifiStatus !== "disabled" - buttonIcon: Network.materialSymbol - mainAction: () => Network.toggleWifi() - altAction: () => { - root.openMenu() - } - StyledToolTip { - text: Translation.tr("%1 | Right-click to configure").arg(Network.networkName) - } + toggleModel: NetworkToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNightLightToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNightLightToggle.qml index 133b0ffcd..5681734e8 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNightLightToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNightLightToggle.qml @@ -1,34 +1,11 @@ import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick import Quickshell AndroidQuickToggleButton { - id: root - - property bool auto: Config.options.light.night.automatic - - name: Translation.tr("Night Light") - statusText: (auto ? Translation.tr("Auto, ") : "") + (toggled ? Translation.tr("Active") : Translation.tr("Inactive")) - - toggled: Hyprsunset.active - buttonIcon: auto ? "night_sight_auto" : "bedtime" - - mainAction: () => { - Hyprsunset.toggle() - } - - altAction: () => { - root.openMenu() - } - - Component.onCompleted: { - Hyprsunset.fetchState() - } - - StyledToolTip { - text: Translation.tr("Night Light | Right-click to configure") - } + toggleModel: NightLightToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNotificationToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNotificationToggle.qml index eda39d716..544baa43a 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNotificationToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidNotificationToggle.qml @@ -1,23 +1,11 @@ import qs import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick import Quickshell AndroidQuickToggleButton { - id: root - - name: Translation.tr("Notifications") - statusText: toggled ? Translation.tr("Show") : Translation.tr("Silent") - toggled: !Notifications.silent - buttonIcon: toggled ? "notifications_active" : "notifications_paused" - - mainAction: () => { - Notifications.silent = !Notifications.silent; - } - - StyledToolTip { - text: Translation.tr("Show notifications") - } + toggleModel: NotificationToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidOnScreenKeyboardToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidOnScreenKeyboardToggle.qml index 779917802..3c97977ea 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidOnScreenKeyboardToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidOnScreenKeyboardToggle.qml @@ -1,22 +1,11 @@ import qs import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick import Quickshell AndroidQuickToggleButton { - id: root - - name: Translation.tr("Virtual Keyboard") - toggled: GlobalStates.oskOpen - buttonIcon: toggled ? "keyboard_hide" : "keyboard" - - mainAction: () => { - GlobalStates.oskOpen = !GlobalStates.oskOpen - } - - StyledToolTip { - text: Translation.tr("On-screen keyboard") - } + toggleModel: OnScreenKeyboardToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidPowerProfileToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidPowerProfileToggle.qml index 381113308..0ac826cdd 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidPowerProfileToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidPowerProfileToggle.qml @@ -1,5 +1,6 @@ import qs import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick @@ -7,36 +8,5 @@ import Quickshell import Quickshell.Services.UPower AndroidQuickToggleButton { - id: root - - name: Translation.tr("Power Profile") - toggled: PowerProfiles.profile !== PowerProfile.Balanced - buttonIcon: switch(PowerProfiles.profile) { - case PowerProfile.PowerSaver: return "energy_savings_leaf" - case PowerProfile.Balanced: return "settings_slow_motion" - case PowerProfile.Performance: return "local_fire_department" - } - statusText: switch(PowerProfiles.profile) { - case PowerProfile.PowerSaver: return "Power Saver" - case PowerProfile.Balanced: return "Balanced" - case PowerProfile.Performance: return "Performance" - } - - mainAction: () => { - if (PowerProfiles.hasPerformanceProfile) { - switch(PowerProfiles.profile) { - case PowerProfile.PowerSaver: PowerProfiles.profile = PowerProfile.Balanced - break; - case PowerProfile.Balanced: PowerProfiles.profile = PowerProfile.Performance - break; - case PowerProfile.Performance: PowerProfiles.profile = PowerProfile.PowerSaver - break; - } - } else { - PowerProfiles.profile = PowerProfiles.profile == PowerProfile.Balanced ? PowerProfile.PowerSaver : PowerProfile.Balanced - } - } - StyledToolTip { - text: Translation.tr("Click to cycle through power profiles") - } + toggleModel: PowerProfilesToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml index 31ad2f262..ebaac6930 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidQuickToggleButton.qml @@ -2,29 +2,42 @@ import QtQuick import QtQuick.Layouts import qs.services import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.functions import qs.modules.common.widgets GroupButton { id: root + // Info to be passed to by repeater required property int buttonIndex required property var buttonData required property bool expandedSize - required property string buttonIcon - required property string name - required property var mainAction - property string statusText: toggled ? Translation.tr("Active") : Translation.tr("Inactive") - property bool available: true - required property real baseCellWidth required property real baseCellHeight required property real cellSpacing required property int cellSize + + // Signals + signal openMenu() + + // Declared in specific toggles + property QuickToggleModel toggleModel + property string name: toggleModel?.name ?? "" + property string statusText: (toggleModel?.hasStatusText) ? (toggleModel?.statusText || (toggled ? Translation.tr("Active") : Translation.tr("Inactive"))) : "" + property string tooltipText: toggleModel?.tooltipText ?? "" + property string buttonIcon: toggleModel?.icon ?? "close" + property bool available: toggleModel?.available ?? true + toggled: toggleModel?.toggled ?? false + property var mainAction: toggleModel?.mainAction ?? null + altAction: toggleModel?.hasMenu ? (() => root.openMenu()) : (toggleModel?.altAction ?? null) + + // Edit mode state + property bool editMode: false + + // Sizing shenanigans baseWidth: root.baseCellWidth * cellSize + cellSpacing * (cellSize - 1) baseHeight: root.baseCellHeight - - property bool editMode: false enableImplicitWidthAnimation: !editMode && root.mouseArea.containsMouse enableImplicitHeightAnimation: !editMode && root.mouseArea.containsMouse Behavior on baseWidth { @@ -41,8 +54,6 @@ GroupButton { animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) } - signal openMenu() - enabled: available || editMode padding: 6 horizontalPadding: padding @@ -226,4 +237,9 @@ GroupButton { event.accepted = true; } } + + StyledToolTip { + extraVisibleCondition: root.tooltipText !== "" + text: root.tooltipText + } } diff --git a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidScreenSnipToggle.qml b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidScreenSnipToggle.qml index 875022249..703a6ef83 100644 --- a/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidScreenSnipToggle.qml +++ b/dots/.config/quickshell/ii/modules/ii/sidebarRight/quickToggles/androidStyle/AndroidScreenSnipToggle.qml @@ -1,5 +1,6 @@ import qs import qs.modules.common +import qs.modules.common.models.quickToggles import qs.modules.common.widgets import qs.services import QtQuick @@ -7,27 +8,5 @@ import Quickshell import Quickshell.Hyprland AndroidQuickToggleButton { - id: root - - name: Translation.tr("Screen snip") - statusText: "" - toggled: false - buttonIcon: "screenshot_region" - - mainAction: () => { - GlobalStates.sidebarRightOpen = false; - delayedActionTimer.start() - } - Timer { - id: delayedActionTimer - interval: 300 - repeat: false - onTriggered: { - Quickshell.execDetached(["qs", "-p", Quickshell.shellPath(""), "ipc", "call", "region", "screenshot"]); - } - } - - StyledToolTip { - text: Translation.tr("Screen snip") - } + toggleModel: ScreenSnipToggle {} } diff --git a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalBarContent.qml b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalBarContent.qml index d3326188e..82ebb4b68 100644 --- a/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalBarContent.qml +++ b/dots/.config/quickshell/ii/modules/ii/verticalBar/VerticalBarContent.qml @@ -171,16 +171,8 @@ Item { // Bar content region implicitWidth: Appearance.sizes.baseVerticalBarWidth implicitHeight: bottomSectionColumnLayout.implicitHeight - onScrollDown: { - const currentVolume = Audio.value; - const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; - Audio.sink.audio.volume -= step; - } - onScrollUp: { - const currentVolume = Audio.value; - const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; - Audio.sink.audio.volume = Math.min(1, Audio.sink.audio.volume + step); - } + onScrollDown: Audio.decrementVolume(); + onScrollUp: Audio.incrementVolume(); onMovedAway: GlobalStates.osdVolumeOpen = false; onPressed: event => { if (event.button === Qt.LeftButton) { diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterBody.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterBody.qml new file mode 100644 index 000000000..6f5a8e031 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterBody.qml @@ -0,0 +1,113 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +Rectangle { + id: root + + property int currentPage: 0 + property alias columns: grid.columns + property alias rows: grid.rows + readonly property int itemsPerPage: columns * rows + property list toggles: Config.options.waffles.actionCenter.toggles + property list togglesInCurrentPage: toggles.slice(currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage) + + Layout.fillHeight: true + Layout.fillWidth: true + color: Looks.colors.bgPanelBody + + implicitWidth: 360 + implicitHeight: contentLayout.implicitHeight + + ColumnLayout { + id: contentLayout + anchors.fill: parent + spacing: 0 + + Item { + id: togglesContainer + property real padding: 22 + Layout.fillWidth: true + Layout.bottomMargin: -12 + implicitHeight: grid.implicitHeight + padding * 2 + + GridLayout { + id: grid + anchors { + fill: parent + margins: parent.padding + } + + columns: 3 + rows: 2 + rowSpacing: 12 + columnSpacing: 12 + uniformCellHeights: true + uniformCellWidths: true + + Repeater { + model: ScriptModel { + values: root.togglesInCurrentPage + } + delegate: ActionCenterToggle { + required property var modelData + name: modelData + } + } + } + + // TODO: pages indicator on the right + } + + Rectangle { + implicitHeight: 1 + Layout.fillWidth: true + color: Looks.colors.bg1Border + } + + RowLayout { + Layout.margins: 12 + Layout.topMargin: 18 + Layout.bottomMargin: 14 + spacing: 4 + + WPanelIconButton { + iconName: WIcons.volumeIcon + onClicked: { + Audio.sink.audio.muted = !Audio.sink.audio.muted; + } + } + WSlider { + Layout.fillWidth: true + value: Audio.sink.audio.volume + onMoved: { + Audio.sink.audio.volume = value; + } + } + WPanelIconButton { + contentItem: Item { + anchors.centerIn: parent + Row { + anchors.centerIn: parent + spacing: -1 + FluentIcon { + anchors.verticalCenter: parent.verticalCenter + implicitSize: 18 + icon: "settings" + } + FluentIcon { + anchors.verticalCenter: parent.verticalCenter + implicitSize: 12 + icon: "chevron-right" + } + } + } + } + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml index 6d2e528db..e33fca0bf 100644 --- a/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterContent.qml @@ -14,15 +14,9 @@ WBarAttachedPanelContent { anchors.centerIn: parent spacing: 0 - Rectangle { - Layout.fillHeight: true - Layout.fillWidth: true + ActionCenterBody { topLeftRadius: root.border.radius - root.border.border.width topRightRadius: topLeftRadius - color: Looks.colors.bgPanelBody - - implicitWidth: 360 - implicitHeight: 380 } Rectangle { @@ -32,46 +26,9 @@ WBarAttachedPanelContent { implicitHeight: 1 } - Rectangle { - Layout.fillHeight: false - Layout.fillWidth: true + ActionCenterFooter { bottomLeftRadius: root.border.radius - root.border.border.width bottomRightRadius: bottomLeftRadius - color: Looks.colors.bgPanelFooter - - implicitWidth: 360 - implicitHeight: 47 - - // Battery button - WPanelFooterButton { - anchors.verticalCenter: parent.verticalCenter - anchors.left: parent.left - anchors.leftMargin: 12 - - contentItem: Row { - spacing: 4 - - FluentIcon { - anchors.verticalCenter: parent.verticalCenter - icon: WIcons.batteryIcon - } - WText { - anchors.verticalCenter: parent.verticalCenter - text: `${Math.round(Battery.percentage * 100) || 0}%` - } - } - } - - // Settings button - WPanelFooterButton { - anchors.verticalCenter: parent.verticalCenter - anchors.right: parent.right - anchors.rightMargin: 12 - - contentItem: FluentIcon { - icon: "settings" - } - } } } } diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterFooter.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterFooter.qml new file mode 100644 index 000000000..46d2517b8 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterFooter.qml @@ -0,0 +1,49 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +Rectangle { + Layout.fillHeight: false + Layout.fillWidth: true + color: Looks.colors.bgPanelFooter + + implicitWidth: 360 + implicitHeight: 47 + + // Battery button + WPanelFooterButton { + visible: Battery.available + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + anchors.leftMargin: 12 + + contentItem: Row { + spacing: 4 + + FluentIcon { + anchors.verticalCenter: parent.verticalCenter + icon: WIcons.batteryIcon + } + WText { + anchors.verticalCenter: parent.verticalCenter + text: `${Math.round(Battery.percentage * 100) || 0}%` + } + } + } + + // Settings button + WPanelFooterButton { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 12 + + contentItem: FluentIcon { + icon: "settings" + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterToggle.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterToggle.qml new file mode 100644 index 000000000..cb88b86a4 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/ActionCenterToggle.qml @@ -0,0 +1,40 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks + +// It should be perfectly fine to use just a Column here, but somehow +// using ColumnLayout prevents weird opening anim stutter +ColumnLayout { + id: root + + property alias name: toggleNameText.text + + Rectangle { + Layout.fillWidth: true + implicitWidth: 96 + implicitHeight: 48 + color: "transparent" + border.width: 1 + border.color: Looks.colors.bg0Border // ??? + radius: Looks.radius.medium + } + + Item { + implicitHeight: 36 + Layout.fillWidth: true + WText { + id: toggleNameText + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + right: parent.right + } + horizontalAlignment: Text.AlignHCenter + elide: Text.ElideRight + text: "Toggle" + } + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/actionCenter/toggles/WNetworkToggle.qml b/dots/.config/quickshell/ii/modules/waffle/actionCenter/toggles/WNetworkToggle.qml new file mode 100644 index 000000000..aa0ec5cad --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/actionCenter/toggles/WNetworkToggle.qml @@ -0,0 +1,16 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.waffle.looks +import qs.modules.waffle.actionCenter + +ActionCenterToggle { + id: root + + name: Network.ethernet ? Translation.tr("Network") : Network.networkName + + +} diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml index 2ce1cd862..956d25ce7 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/SystemButton.qml @@ -3,6 +3,7 @@ import QtQuick.Layouts import qs import qs.services import qs.modules.common +import qs.modules.common.widgets import qs.modules.waffle.looks BarButton { @@ -38,22 +39,15 @@ BarButton { id: volumeHoverArea iconItem: FluentIcon { anchors.verticalCenter: parent.verticalCenter - icon: { - const muted = Audio.sink?.audio.muted ?? false; - const volume = Audio.sink?.audio.volume ?? 0; - if (muted) - return volume > 0 ? "speaker-off" : "speaker-none"; - if (volume == 0) - return "speaker-none"; - if (volume < 0.5) - return "speaker-1"; - return "speaker"; - } + icon: WIcons.volumeIcon } + onScrollDown: Audio.decrementVolume(); + onScrollUp: Audio.incrementVolume(); } IconHoverArea { id: batteryHoverArea + visible: Battery?.available ?? false iconItem: FluentIcon { anchors.verticalCenter: parent.verticalCenter icon: WIcons.batteryIcon @@ -62,7 +56,7 @@ BarButton { } } - component IconHoverArea: MouseArea { + component IconHoverArea: FocusedScrollMouseArea { id: hoverArea required property var iconItem anchors { diff --git a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml index a5915e83e..9f3610fb3 100644 --- a/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml +++ b/dots/.config/quickshell/ii/modules/waffle/bar/tasks/TaskAppButton.qml @@ -85,6 +85,7 @@ AppButton { BarMenu { id: contextMenu + noSmoothClosing: false // On the real thing this is always smooth model: [ ...((root.desktopEntry?.actions.length > 0) ? root.desktopEntry.actions.map(action =>({ diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml index a01628d4a..70d452fa7 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/Looks.qml @@ -35,6 +35,8 @@ Singleton { property color bg2Border: root.dark ? "#464646" : "#EEEEEE" property color fg: root.dark ? "#FFFFFF" : "#000000" property color fg1: root.dark ? "#D1D1D1" : "#626262" + property color controlBg: root.dark ? "#9B9B9B" : "#868686" + property color controlFg: root.dark ? "#454545" : "#FFFFFF" property color danger: "#C42B1C" property color dangerActive: "#B62D1F" property color warning: "#FF9900" @@ -71,6 +73,9 @@ Singleton { transition: QtObject { id: transition + + property int velocity: 850 + property QtObject easing: QtObject { property QtObject bezierCurve: QtObject { readonly property list easeInOut: [0.42,0.00,0.58,1.00,1,1] diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml index 813b0a1ce..21e471489 100644 --- a/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WIcons.qml @@ -27,5 +27,16 @@ Singleton { if (Battery.percentage >= 0.9) return "battery-full"; return `battery-${Math.ceil(Battery.percentage * 10)}`; } - + + property string volumeIcon: { + const muted = Audio.sink?.audio.muted ?? false; + const volume = Audio.sink?.audio.volume ?? 0; + if (muted) + return volume > 0 ? "speaker-off" : "speaker-none"; + if (volume == 0) + return "speaker-none"; + if (volume < 0.5) + return "speaker-1"; + return "speaker"; + } } diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WPanelIconButton.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WPanelIconButton.qml new file mode 100644 index 000000000..edaad11a6 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WPanelIconButton.qml @@ -0,0 +1,23 @@ +import QtQuick +import Quickshell +import qs +import qs.services +import qs.modules.common +import qs.modules.waffle.looks +import qs.modules.waffle.bar + +WButton { + id: root + + property alias iconName: iconContent.icon + inset: 0 + implicitWidth: 40 + implicitHeight: 40 + + contentItem: FluentIcon { + id: iconContent + anchors.centerIn: parent + implicitSize: 18 + icon: root.iconName + } +} diff --git a/dots/.config/quickshell/ii/modules/waffle/looks/WSlider.qml b/dots/.config/quickshell/ii/modules/waffle/looks/WSlider.qml new file mode 100644 index 000000000..16921004c --- /dev/null +++ b/dots/.config/quickshell/ii/modules/waffle/looks/WSlider.qml @@ -0,0 +1,81 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell.Widgets +import qs.modules.common +import qs.modules.common.widgets + +Slider { + id: root + + property real trackWidth: 4 + // leftPadding: handle.width / 2 + // rightPadding: handle.width / 2 + leftPadding: 0 + rightPadding: 0 + + implicitHeight: handle.implicitHeight + + Behavior on value { // This makes the adjusted value (like volume) shift smoothly + SmoothedAnimation { + velocity: Looks.transition.velocity + } + } + + background: Item { + id: background + anchors.fill: parent + + Rectangle { + id: trackHighlight + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + } + topLeftRadius: root.trackWidth / 2 + bottomLeftRadius: root.trackWidth / 2 + color: Looks.colors.accent + implicitHeight: root.trackWidth + width: background.width * root.visualPosition + } + + Rectangle { + id: trackTrough + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + topLeftRadius: root.trackWidth / 2 + bottomLeftRadius: root.trackWidth / 2 + color: Looks.colors.controlBg + implicitHeight: root.trackWidth + width: background.width * (1 - root.visualPosition) + } + } + + handle: Circle { + id: handle + anchors.verticalCenter: parent.verticalCenter + x: (diameter / 2) + root.visualPosition * (root.width - diameter) - (diameter / 2) + diameter: 20 + color: Looks.colors.controlFg + + MouseArea { + id: handleMouseArea + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.NoButton + } + + Circle { + anchors.centerIn: parent + diameter: root.pressed ? 10 : handleMouseArea.containsMouse ? 14 : 12 + color: Looks.colors.accent + + Behavior on diameter { + animation: Looks.transition.enter.createObject(this) + } + } + } +} diff --git a/dots/.config/quickshell/ii/services/Audio.qml b/dots/.config/quickshell/ii/services/Audio.qml index 5fca1a51a..633890cd0 100644 --- a/dots/.config/quickshell/ii/services/Audio.qml +++ b/dots/.config/quickshell/ii/services/Audio.qml @@ -16,9 +16,31 @@ Singleton { property PwNode source: Pipewire.defaultAudioSource readonly property real hardMaxValue: 2.00 // People keep joking about setting volume to 5172% so... property string audioTheme: Config.options.sounds.theme - + property real value: sink?.audio.volume ?? 0 + signal sinkProtectionTriggered(string reason); + function toggleMute() { + Audio.sink.audio.muted = !Audio.sink.audio.muted + } + + function toggleMicMute() { + Audio.source.audio.muted = !Audio.source.audio.muted + } + + function incrementVolume() { + const currentVolume = Audio.value; + const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; + Audio.sink.audio.volume = Math.min(1, Audio.sink.audio.volume + step); + } + + function decrementVolume() { + const currentVolume = Audio.value; + const step = currentVolume < 0.1 ? 0.01 : 0.02 || 0.2; + Audio.sink.audio.volume -= step; + } + + PwObjectTracker { objects: [sink, source] } diff --git a/dots/.config/quickshell/ii/shell.qml b/dots/.config/quickshell/ii/shell.qml index 766728cf5..cbe7394c5 100644 --- a/dots/.config/quickshell/ii/shell.qml +++ b/dots/.config/quickshell/ii/shell.qml @@ -90,7 +90,7 @@ ShellRoot { property list families: ["ii", "waffle"] property var panelFamilies: ({ "ii": ["iiBar", "iiBackground", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiScreenCorners", "iiSessionScreen", "iiSidebarLeft", "iiSidebarRight", "iiVerticalBar", "iiWallpaperSelector"], - "waffle": ["wBar", "wBackground", "wActionCenter", "iiCheatsheet", "iiDock", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiSessionScreen", "iiSidebarRight", "iiWallpaperSelector"], + "waffle": ["wBar", "wBackground", "wActionCenter", "iiCheatsheet", "iiLock", "iiMediaControls", "iiNotificationPopup", "iiOnScreenDisplay", "iiOnScreenKeyboard", "iiOverlay", "iiOverview", "iiPolkit", "iiRegionSelector", "iiReloadPopup", "iiSessionScreen", "iiSidebarRight", "iiWallpaperSelector"], }) function cyclePanelFamily() { const currentIndex = families.indexOf(Config.options.panelFamily)