summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2026-01-22 09:02:54 -0500
committerFreya Murphy <freya@freyacat.org>2026-03-16 09:45:27 -0400
commit6d9f0c1526c51ed1bc8102c135aae56a0bc0e1ef (patch)
tree9c77312e5a873647d3540331413dbe691e6768f2 /modules
parentremove lockscreen (diff)
downloadcaelestia-shell-6d9f0c1526c51ed1bc8102c135aae56a0bc0e1ef.tar.gz
caelestia-shell-6d9f0c1526c51ed1bc8102c135aae56a0bc0e1ef.tar.bz2
caelestia-shell-6d9f0c1526c51ed1bc8102c135aae56a0bc0e1ef.zip
fix rebase
Diffstat (limited to 'modules')
-rw-r--r--modules/areapicker/Picker.qml312
-rw-r--r--modules/background/Background.qml15
-rw-r--r--modules/background/DesktopClock.qml169
-rw-r--r--modules/background/Visualiser.qml151
-rw-r--r--modules/background/Wallpaper.qml108
-rw-r--r--modules/bar/components/workspaces/SpecialWorkspaces.qml363
-rw-r--r--modules/controlcenter/network/NetworkSettings.qml72
-rw-r--r--modules/controlcenter/network/NetworkingPane.qml68
-rw-r--r--modules/controlcenter/network/VpnDetails.qml396
-rw-r--r--modules/controlcenter/network/VpnList.qml686
-rw-r--r--modules/controlcenter/network/VpnSettings.qml232
-rw-r--r--modules/controlcenter/state/VpnState.qml5
-rw-r--r--modules/controlcenter/taskbar/TaskbarPane.qml757
-rw-r--r--modules/launcher/items/SchemeItem.qml104
-rw-r--r--modules/launcher/items/VariantItem.qml80
-rw-r--r--modules/launcher/services/Apps.qml2
-rw-r--r--modules/lock/Center.qml416
-rw-r--r--modules/lock/Fetch.qml177
-rw-r--r--modules/lock/NotifDock.qml145
-rw-r--r--modules/lock/NotifGroup.qml339
-rw-r--r--modules/lock/WeatherInfo.qml176
-rw-r--r--modules/utilities/RecordingDeleteModal.qml207
-rw-r--r--modules/utilities/cards/RecordingList.qml240
23 files changed, 4 insertions, 5216 deletions
diff --git a/modules/areapicker/Picker.qml b/modules/areapicker/Picker.qml
deleted file mode 100644
index f4f4a36..0000000
--- a/modules/areapicker/Picker.qml
+++ /dev/null
@@ -1,312 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import Caelestia
-import Quickshell
-import Quickshell.Io
-import Quickshell.Wayland
-import QtQuick
-import QtQuick.Effects
-
-MouseArea {
- id: root
-
- required property LazyLoader loader
- required property ShellScreen screen
-
- property bool onClient
-
- property real realBorderWidth: onClient ? (Hypr.options["general:border_size"] ?? 1) : 2
- property real realRounding: onClient ? (Hypr.options["decoration:rounding"] ?? 0) : 0
-
- property real ssx
- property real ssy
-
- property real sx: 0
- property real sy: 0
- property real ex: screen.width
- property real ey: screen.height
-
- property real rsx: Math.min(sx, ex)
- property real rsy: Math.min(sy, ey)
- property real sw: Math.abs(sx - ex)
- property real sh: Math.abs(sy - ey)
-
- property list<var> clients: {
- const mon = Hypr.monitorFor(screen);
- if (!mon)
- return [];
-
- const special = mon.lastIpcObject.specialWorkspace;
- const wsId = special.name ? special.id : mon.activeWorkspace.id;
-
- return Hypr.toplevels.values.filter(c => c.workspace?.id === wsId).sort((a, b) => {
- // Pinned first, then fullscreen, then floating, then any other
- const ac = a.lastIpcObject;
- const bc = b.lastIpcObject;
- return (bc.pinned - ac.pinned) || ((bc.fullscreen !== 0) - (ac.fullscreen !== 0)) || (bc.floating - ac.floating);
- });
- }
-
- function checkClientRects(x: real, y: real): void {
- for (const client of clients) {
- if (!client)
- continue;
-
- let {
- at: [cx, cy],
- size: [cw, ch]
- } = client.lastIpcObject;
- cx -= screen.x;
- cy -= screen.y;
- if (cx <= x && cy <= y && cx + cw >= x && cy + ch >= y) {
- onClient = true;
- sx = cx;
- sy = cy;
- ex = cx + cw;
- ey = cy + ch;
- break;
- }
- }
- }
-
- function save(): void {
- const tmpfile = Qt.resolvedUrl(`/tmp/caelestia-picker-${Quickshell.processId}-${Date.now()}.png`);
- CUtils.saveItem(screencopy, tmpfile, Qt.rect(Math.ceil(rsx), Math.ceil(rsy), Math.floor(sw), Math.floor(sh)), path => {
- if (root.loader.clipboardOnly) {
- Quickshell.execDetached(["sh", "-c", "wl-copy --type image/png < " + path]);
- Quickshell.execDetached(["notify-send", "-a", "caelestia-cli", "-i", path, "Screenshot taken", "Screenshot copied to clipboard"]);
- } else {
- Quickshell.execDetached(["swappy", "-f", path]);
- }
- closeAnim.start();
- });
- }
-
- onClientsChanged: checkClientRects(mouseX, mouseY)
-
- anchors.fill: parent
- opacity: 0
- hoverEnabled: true
- cursorShape: Qt.CrossCursor
-
- Component.onCompleted: {
- Hypr.extras.refreshOptions();
-
- // Break binding if frozen
- if (loader.freeze)
- clients = clients;
-
- opacity = 1;
-
- const c = clients[0];
- if (c) {
- const cx = c.lastIpcObject.at[0] - screen.x;
- const cy = c.lastIpcObject.at[1] - screen.y;
- onClient = true;
- sx = cx;
- sy = cy;
- ex = cx + c.lastIpcObject.size[0];
- ey = cy + c.lastIpcObject.size[1];
- } else {
- sx = screen.width / 2 - 100;
- sy = screen.height / 2 - 100;
- ex = screen.width / 2 + 100;
- ey = screen.height / 2 + 100;
- }
- }
-
- onPressed: event => {
- ssx = event.x;
- ssy = event.y;
- }
-
- onReleased: {
- if (closeAnim.running)
- return;
-
- if (root.loader.freeze) {
- save();
- } else {
- overlay.visible = border.visible = false;
- screencopy.visible = false;
- screencopy.active = true;
- }
- }
-
- onPositionChanged: event => {
- const x = event.x;
- const y = event.y;
-
- if (pressed) {
- onClient = false;
- sx = ssx;
- sy = ssy;
- ex = x;
- ey = y;
- } else {
- checkClientRects(x, y);
- }
- }
-
- focus: true
- Keys.onEscapePressed: closeAnim.start()
-
- SequentialAnimation {
- id: closeAnim
-
- PropertyAction {
- target: root.loader
- property: "closing"
- value: true
- }
- ParallelAnimation {
- Anim {
- target: root
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.large
- }
- ExAnim {
- target: root
- properties: "rsx,rsy"
- to: 0
- }
- ExAnim {
- target: root
- property: "sw"
- to: root.screen.width
- }
- ExAnim {
- target: root
- property: "sh"
- to: root.screen.height
- }
- }
- PropertyAction {
- target: root.loader
- property: "activeAsync"
- value: false
- }
- }
-
- Process {
- running: true
- command: ["hyprctl", "cursorpos", "-j"]
- stdout: StdioCollector {
- onStreamFinished: {
- const pos = JSON.parse(text);
- root.checkClientRects(pos.x - root.screen.x, pos.y - root.screen.y);
- }
- }
- }
-
- Loader {
- id: screencopy
-
- anchors.fill: parent
-
- active: root.loader.freeze
-
- sourceComponent: ScreencopyView {
- captureSource: root.screen
-
- onHasContentChanged: {
- if (hasContent && !root.loader.freeze) {
- overlay.visible = border.visible = true;
- root.save();
- }
- }
- }
- }
-
- StyledRect {
- id: overlay
-
- anchors.fill: parent
- color: Colours.palette.m3secondaryContainer
- opacity: 0.3
-
- layer.enabled: true
- layer.effect: MultiEffect {
- maskSource: selectionWrapper
- maskEnabled: true
- maskInverted: true
- maskSpreadAtMin: 1
- maskThresholdMin: 0.5
- }
- }
-
- Item {
- id: selectionWrapper
-
- anchors.fill: parent
- layer.enabled: true
- visible: false
-
- Rectangle {
- id: selectionRect
-
- radius: root.realRounding
- x: root.rsx
- y: root.rsy
- implicitWidth: root.sw
- implicitHeight: root.sh
- }
- }
-
- Rectangle {
- id: border
-
- color: "transparent"
- radius: root.realRounding > 0 ? root.realRounding + root.realBorderWidth : 0
- border.width: root.realBorderWidth
- border.color: Colours.palette.m3primary
-
- x: selectionRect.x - root.realBorderWidth
- y: selectionRect.y - root.realBorderWidth
- implicitWidth: selectionRect.implicitWidth + root.realBorderWidth * 2
- implicitHeight: selectionRect.implicitHeight + root.realBorderWidth * 2
-
- Behavior on border.color {
- CAnim {}
- }
- }
-
- Behavior on opacity {
- Anim {
- duration: Appearance.anim.durations.large
- }
- }
-
- Behavior on rsx {
- enabled: !root.pressed
-
- ExAnim {}
- }
-
- Behavior on rsy {
- enabled: !root.pressed
-
- ExAnim {}
- }
-
- Behavior on sw {
- enabled: !root.pressed
-
- ExAnim {}
- }
-
- Behavior on sh {
- enabled: !root.pressed
-
- ExAnim {}
- }
-
- component ExAnim: Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
-}
diff --git a/modules/background/Background.qml b/modules/background/Background.qml
index 47b5bde..1a91bd9 100644
--- a/modules/background/Background.qml
+++ b/modules/background/Background.qml
@@ -41,20 +41,7 @@ Loader {
asynchronous: true
fillMode: Image.PreserveAspectCrop
- Loader {
- id: wallpaper
-
- anchors.fill: parent
- active: Config.background.wallpaperEnabled
-
- sourceComponent: Wallpaper {}
- }
-
- Visualiser {
- anchors.fill: parent
- screen: win.modelData
- wallpaper: wallpaper
- }
+ source: Paths.wallpaper ?? ""
}
}
}
diff --git a/modules/background/DesktopClock.qml b/modules/background/DesktopClock.qml
deleted file mode 100644
index f9a06a2..0000000
--- a/modules/background/DesktopClock.qml
+++ /dev/null
@@ -1,169 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import QtQuick
-import QtQuick.Layouts
-import QtQuick.Effects
-
-Item {
- id: root
-
- required property Item wallpaper
- required property real absX
- required property real absY
-
- property real scale: Config.background.desktopClock.scale
- readonly property bool bgEnabled: Config.background.desktopClock.background.enabled
- readonly property bool blurEnabled: bgEnabled && Config.background.desktopClock.background.blur && !GameMode.enabled
- readonly property bool invertColors: Config.background.desktopClock.invertColors
- readonly property bool useLightSet: Colours.light ? !invertColors : invertColors
- readonly property color safePrimary: useLightSet ? Colours.palette.m3primaryContainer : Colours.palette.m3primary
- readonly property color safeSecondary: useLightSet ? Colours.palette.m3secondaryContainer : Colours.palette.m3secondary
- readonly property color safeTertiary: useLightSet ? Colours.palette.m3tertiaryContainer : Colours.palette.m3tertiary
-
- implicitWidth: layout.implicitWidth + (Appearance.padding.large * 4 * root.scale)
- implicitHeight: layout.implicitHeight + (Appearance.padding.large * 2 * root.scale)
-
- Item {
- id: clockContainer
-
- anchors.fill: parent
-
- layer.enabled: Config.background.desktopClock.shadow.enabled
- layer.effect: MultiEffect {
- shadowEnabled: true
- shadowColor: Colours.palette.m3shadow
- shadowOpacity: Config.background.desktopClock.shadow.opacity
- shadowBlur: Config.background.desktopClock.shadow.blur
- }
-
- Loader {
- anchors.fill: parent
- active: root.blurEnabled
-
- sourceComponent: MultiEffect {
- source: ShaderEffectSource {
- sourceItem: root.wallpaper
- sourceRect: Qt.rect(root.absX, root.absY, root.width, root.height)
- }
- maskSource: backgroundPlate
- maskEnabled: true
- blurEnabled: true
- blur: 1
- blurMax: 64
- autoPaddingEnabled: false
- }
- }
-
- StyledRect {
- id: backgroundPlate
-
- visible: root.bgEnabled
- anchors.fill: parent
- radius: Appearance.rounding.large * root.scale
- opacity: Config.background.desktopClock.background.opacity
- color: Colours.palette.m3surface
-
- layer.enabled: root.blurEnabled
- }
-
- RowLayout {
- id: layout
-
- anchors.centerIn: parent
- spacing: Appearance.spacing.larger * root.scale
-
- RowLayout {
- spacing: Appearance.spacing.small
-
- StyledText {
- text: Time.hourStr
- font.pointSize: Appearance.font.size.extraLarge * 3 * root.scale
- font.weight: Font.Bold
- color: root.safePrimary
- }
-
- StyledText {
- text: ":"
- font.pointSize: Appearance.font.size.extraLarge * 3 * root.scale
- color: root.safeTertiary
- opacity: 0.8
- Layout.topMargin: -Appearance.padding.large * 1.5 * root.scale
- }
-
- StyledText {
- text: Time.minuteStr
- font.pointSize: Appearance.font.size.extraLarge * 3 * root.scale
- font.weight: Font.Bold
- color: root.safeSecondary
- }
-
- Loader {
- Layout.alignment: Qt.AlignTop
- Layout.topMargin: Appearance.padding.large * 1.4 * root.scale
-
- active: Config.services.useTwelveHourClock
- visible: active
-
- sourceComponent: StyledText {
- text: Time.amPmStr
- font.pointSize: Appearance.font.size.large * root.scale
- color: root.safeSecondary
- }
- }
- }
-
- StyledRect {
- Layout.fillHeight: true
- Layout.preferredWidth: 4 * root.scale
- Layout.topMargin: Appearance.spacing.larger * root.scale
- Layout.bottomMargin: Appearance.spacing.larger * root.scale
- radius: Appearance.rounding.full
- color: root.safePrimary
- opacity: 0.8
- }
-
- ColumnLayout {
- spacing: 0
-
- StyledText {
- text: Time.format("MMMM").toUpperCase()
- font.pointSize: Appearance.font.size.large * root.scale
- font.letterSpacing: 4
- font.weight: Font.Bold
- color: root.safeSecondary
- }
-
- StyledText {
- text: Time.format("dd")
- font.pointSize: Appearance.font.size.extraLarge * root.scale
- font.letterSpacing: 2
- font.weight: Font.Medium
- color: root.safePrimary
- }
-
- StyledText {
- text: Time.format("dddd")
- font.pointSize: Appearance.font.size.larger * root.scale
- font.letterSpacing: 2
- color: root.safeSecondary
- }
- }
- }
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- Behavior on implicitWidth {
- Anim {
- duration: Appearance.anim.durations.small
- }
- }
-}
diff --git a/modules/background/Visualiser.qml b/modules/background/Visualiser.qml
deleted file mode 100644
index 35a086b..0000000
--- a/modules/background/Visualiser.qml
+++ /dev/null
@@ -1,151 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import Caelestia.Services
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Effects
-
-Item {
- id: root
-
- required property ShellScreen screen
- required property Item wallpaper
-
- readonly property bool shouldBeActive: Config.background.visualiser.enabled && (!Config.background.visualiser.autoHide || (Hypr.monitorFor(screen)?.activeWorkspace?.toplevels?.values.every(t => t.lastIpcObject?.floating) ?? true))
- property real offset: shouldBeActive ? 0 : screen.height * 0.2
-
- opacity: shouldBeActive ? 1 : 0
-
- Loader {
- anchors.fill: parent
- active: root.opacity > 0 && Config.background.visualiser.blur
-
- sourceComponent: MultiEffect {
- source: root.wallpaper
- maskSource: wrapper
- maskEnabled: true
- blurEnabled: true
- blur: 1
- blurMax: 32
- autoPaddingEnabled: false
- }
- }
-
- Item {
- id: wrapper
-
- anchors.fill: parent
- layer.enabled: true
-
- Loader {
- anchors.fill: parent
- anchors.topMargin: root.offset
- anchors.bottomMargin: -root.offset
-
- active: root.opacity > 0
-
- sourceComponent: Item {
- ServiceRef {
- service: Audio.cava
- }
-
- Item {
- id: content
-
- anchors.fill: parent
- anchors.margins: Config.border.thickness
- anchors.leftMargin: Visibilities.bars.get(root.screen).exclusiveZone + Appearance.spacing.small * Config.background.visualiser.spacing
-
- Side {
- content: content
- }
- Side {
- content: content
- isRight: true
- }
-
- Behavior on anchors.leftMargin {
- Anim {}
- }
- }
- }
- }
- }
-
- Behavior on offset {
- Anim {}
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- component Side: Repeater {
- id: side
-
- required property Item content
- property bool isRight
-
- model: Config.services.visualiserBars
-
- ClippingRectangle {
- id: bar
-
- required property int modelData
- property real value: Math.max(0, Math.min(1, Audio.cava.values[side.isRight ? modelData : side.count - modelData - 1]))
-
- clip: true
-
- x: modelData * ((side.content.width * 0.4) / Config.services.visualiserBars) + (side.isRight ? side.content.width * 0.6 : 0)
- implicitWidth: (side.content.width * 0.4) / Config.services.visualiserBars - Appearance.spacing.small * Config.background.visualiser.spacing
-
- y: side.content.height - height
- implicitHeight: bar.value * side.content.height * 0.4
-
- color: "transparent"
- topLeftRadius: Appearance.rounding.small * Config.background.visualiser.rounding
- topRightRadius: Appearance.rounding.small * Config.background.visualiser.rounding
-
- Rectangle {
- topLeftRadius: parent.topLeftRadius
- topRightRadius: parent.topRightRadius
-
- gradient: Gradient {
- orientation: Gradient.Vertical
-
- GradientStop {
- position: 0
- color: Qt.alpha(Colours.palette.m3primary, 0.7)
-
- Behavior on color {
- CAnim {}
- }
- }
- GradientStop {
- position: 1
- color: Qt.alpha(Colours.palette.m3inversePrimary, 0.7)
-
- Behavior on color {
- CAnim {}
- }
- }
- }
-
- anchors.left: parent.left
- anchors.right: parent.right
- y: parent.height - height
- implicitHeight: side.content.height * 0.4
- }
-
- Behavior on value {
- Anim {
- duration: Appearance.anim.durations.small
- }
- }
- }
- }
-}
diff --git a/modules/background/Wallpaper.qml b/modules/background/Wallpaper.qml
deleted file mode 100644
index 0ca5ab1..0000000
--- a/modules/background/Wallpaper.qml
+++ /dev/null
@@ -1,108 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.images
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-
-Item {
- id: root
-
- property string source: Paths.wallpaper
- property Image current: one
-
- onSourceChanged: {
- if (!source)
- current = null;
- else if (current === one)
- two.update();
- else
- one.update();
- }
-
- Component.onCompleted: {
- if (source)
- Qt.callLater(() => one.update());
- }
-
- Loader {
- anchors.fill: parent
-
- active: !root.source
-
- sourceComponent: StyledRect {
- color: Colours.palette.m3surfaceContainer
-
- Row {
- anchors.centerIn: parent
- spacing: Appearance.spacing.large
-
- MaterialIcon {
- text: "sentiment_stressed"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.extraLarge * 5
- }
-
- Column {
- anchors.verticalCenter: parent.verticalCenter
- spacing: Appearance.spacing.small
-
- StyledText {
- text: qsTr("Wallpaper missing?")
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.extraLarge * 2
- font.bold: true
- }
- }
- }
- }
- }
-
- Img {
- id: one
- }
-
- Img {
- id: two
- }
-
- component Img: CachingImage {
- id: img
-
- function update(): void {
- if (path === root.source)
- root.current = this;
- else
- path = root.source;
- }
-
- anchors.fill: parent
-
- opacity: 0
- scale: 0.8
-
- onStatusChanged: {
- if (status === Image.Ready)
- root.current = this;
- }
-
- states: State {
- name: "visible"
- when: root.current === img
-
- PropertyChanges {
- img.opacity: 1
- img.scale: 1
- }
- }
-
- transitions: Transition {
- Anim {
- target: img
- properties: "opacity,scale"
- }
- }
- }
-}
diff --git a/modules/bar/components/workspaces/SpecialWorkspaces.qml b/modules/bar/components/workspaces/SpecialWorkspaces.qml
deleted file mode 100644
index cd3572b..0000000
--- a/modules/bar/components/workspaces/SpecialWorkspaces.qml
+++ /dev/null
@@ -1,363 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.effects
-import qs.services
-import qs.utils
-import qs.config
-import Quickshell
-import Quickshell.Hyprland
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property ShellScreen screen
- readonly property HyprlandMonitor monitor: Hypr.monitorFor(screen)
- readonly property string activeSpecial: (Config.bar.workspaces.perMonitorWorkspaces ? monitor : Hypr.focusedMonitor)?.lastIpcObject?.specialWorkspace?.name ?? ""
-
- layer.enabled: true
- layer.effect: OpacityMask {
- maskSource: mask
- }
-
- Item {
- id: mask
-
- anchors.fill: parent
- layer.enabled: true
- visible: false
-
- Rectangle {
- anchors.fill: parent
- radius: Appearance.rounding.full
-
- gradient: Gradient {
- orientation: Gradient.Vertical
-
- GradientStop {
- position: 0
- color: Qt.rgba(0, 0, 0, 0)
- }
- GradientStop {
- position: 0.3
- color: Qt.rgba(0, 0, 0, 1)
- }
- GradientStop {
- position: 0.7
- color: Qt.rgba(0, 0, 0, 1)
- }
- GradientStop {
- position: 1
- color: Qt.rgba(0, 0, 0, 0)
- }
- }
- }
-
- Rectangle {
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
-
- radius: Appearance.rounding.full
- implicitHeight: parent.height / 2
- opacity: view.contentY > 0 ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- Rectangle {
- anchors.bottom: parent.bottom
- anchors.left: parent.left
- anchors.right: parent.right
-
- radius: Appearance.rounding.full
- implicitHeight: parent.height / 2
- opacity: view.contentY < view.contentHeight - parent.height + Appearance.padding.small ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
- }
-
- ListView {
- id: view
-
- anchors.fill: parent
- spacing: Appearance.spacing.normal
- interactive: false
-
- currentIndex: model.values.findIndex(w => w.name === root.activeSpecial)
- onCurrentIndexChanged: currentIndex = Qt.binding(() => model.values.findIndex(w => w.name === root.activeSpecial))
-
- model: ScriptModel {
- values: Hypr.workspaces.values.filter(w => w.name.startsWith("special:") && (!Config.bar.workspaces.perMonitorWorkspaces || w.monitor === root.monitor))
- }
-
- preferredHighlightBegin: 0
- preferredHighlightEnd: height
- highlightRangeMode: ListView.StrictlyEnforceRange
-
- highlightFollowsCurrentItem: false
- highlight: Item {
- y: view.currentItem?.y ?? 0
- implicitHeight: view.currentItem?.size ?? 0
-
- Behavior on y {
- Anim {}
- }
- }
-
- delegate: ColumnLayout {
- id: ws
-
- required property HyprlandWorkspace modelData
- readonly property int size: label.Layout.preferredHeight + (hasWindows ? windows.implicitHeight + Appearance.padding.small : 0)
- property int wsId
- property string icon
- property bool hasWindows
-
- anchors.left: view.contentItem.left
- anchors.right: view.contentItem.right
-
- spacing: 0
-
- Component.onCompleted: {
- wsId = modelData.id;
- icon = Icons.getSpecialWsIcon(modelData.name);
- hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && modelData.lastIpcObject.windows > 0;
- }
-
- // Hacky thing cause modelData gets destroyed before the remove anim finishes
- Connections {
- target: ws.modelData
-
- function onIdChanged(): void {
- if (ws.modelData)
- ws.wsId = ws.modelData.id;
- }
-
- function onNameChanged(): void {
- if (ws.modelData)
- ws.icon = Icons.getSpecialWsIcon(ws.modelData.name);
- }
-
- function onLastIpcObjectChanged(): void {
- if (ws.modelData)
- ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0;
- }
- }
-
- Connections {
- target: Config.bar.workspaces
-
- function onShowWindowsOnSpecialWorkspacesChanged(): void {
- if (ws.modelData)
- ws.hasWindows = Config.bar.workspaces.showWindowsOnSpecialWorkspaces && ws.modelData.lastIpcObject.windows > 0;
- }
- }
-
- Loader {
- id: label
-
- Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
- Layout.preferredHeight: Config.bar.sizes.innerWidth - Appearance.padding.small * 2
-
- sourceComponent: ws.icon.length === 1 ? letterComp : iconComp
-
- Component {
- id: iconComp
-
- MaterialIcon {
- fill: 1
- text: ws.icon
- verticalAlignment: Qt.AlignVCenter
- }
- }
-
- Component {
- id: letterComp
-
- StyledText {
- text: ws.icon
- verticalAlignment: Qt.AlignVCenter
- }
- }
- }
-
- Loader {
- id: windows
-
- Layout.alignment: Qt.AlignHCenter
- Layout.fillHeight: true
- Layout.preferredHeight: implicitHeight
-
- visible: active
- active: ws.hasWindows
-
- sourceComponent: Column {
- spacing: 0
-
- add: Transition {
- Anim {
- properties: "scale"
- from: 0
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-
- move: Transition {
- Anim {
- properties: "scale"
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- Anim {
- properties: "x,y"
- }
- }
-
- Repeater {
- model: ScriptModel {
- values: {
- const windows = Hypr.toplevels.values.filter(c => c.workspace?.id === ws.wsId);
- const maxIcons = Config.bar.workspaces.maxWindowIcons;
- return maxIcons > 0 ? windows.slice(0, maxIcons) : windows;
- }
- }
-
- MaterialIcon {
- required property var modelData
-
- grade: 0
- text: Icons.getAppCategoryIcon(modelData.lastIpcObject.class, "terminal")
- color: Colours.palette.m3onSurfaceVariant
- }
- }
- }
-
- Behavior on Layout.preferredHeight {
- Anim {}
- }
- }
- }
-
- add: Transition {
- Anim {
- properties: "scale"
- from: 0
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- }
-
- remove: Transition {
- Anim {
- property: "scale"
- to: 0.5
- duration: Appearance.anim.durations.small
- }
- Anim {
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.small
- }
- }
-
- move: Transition {
- Anim {
- properties: "scale"
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- Anim {
- properties: "x,y"
- }
- }
-
- displaced: Transition {
- Anim {
- properties: "scale"
- to: 1
- easing.bezierCurve: Appearance.anim.curves.standardDecel
- }
- Anim {
- properties: "x,y"
- }
- }
- }
-
- Loader {
- active: Config.bar.workspaces.activeIndicator
- anchors.fill: parent
-
- sourceComponent: Item {
- StyledClippingRect {
- id: indicator
-
- anchors.left: parent.left
- anchors.right: parent.right
-
- y: (view.currentItem?.y ?? 0) - view.contentY
- implicitHeight: view.currentItem?.size ?? 0
-
- color: Colours.palette.m3tertiary
- radius: Appearance.rounding.full
-
- Colouriser {
- source: view
- sourceColor: Colours.palette.m3onSurface
- colorizationColor: Colours.palette.m3onTertiary
-
- anchors.horizontalCenter: parent.horizontalCenter
-
- x: 0
- y: -indicator.y
- implicitWidth: view.width
- implicitHeight: view.height
- }
-
- Behavior on y {
- Anim {
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- Behavior on implicitHeight {
- Anim {
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
- }
- }
-
- MouseArea {
- property real startY
-
- anchors.fill: view
-
- drag.target: view.contentItem
- drag.axis: Drag.YAxis
- drag.maximumY: 0
- drag.minimumY: Math.min(0, view.height - view.contentHeight - Appearance.padding.small)
-
- onPressed: event => startY = event.y
-
- onClicked: event => {
- if (Math.abs(event.y - startY) > drag.threshold)
- return;
-
- const ws = view.itemAt(event.x, event.y);
- if (ws?.modelData)
- Hypr.dispatch(`togglespecialworkspace ${ws.modelData.name.slice(8)}`);
- else
- Hypr.dispatch("togglespecialworkspace special");
- }
- }
-}
diff --git a/modules/controlcenter/network/NetworkSettings.qml b/modules/controlcenter/network/NetworkSettings.qml
index bda7cb1..69f4e63 100644
--- a/modules/controlcenter/network/NetworkSettings.qml
+++ b/modules/controlcenter/network/NetworkSettings.qml
@@ -63,45 +63,6 @@ ColumnLayout {
SectionHeader {
Layout.topMargin: Appearance.spacing.large
- title: qsTr("VPN")
- description: qsTr("VPN provider settings")
- visible: Config.utilities.vpn.enabled || Config.utilities.vpn.provider.length > 0
- }
-
- SectionContainer {
- visible: Config.utilities.vpn.enabled || Config.utilities.vpn.provider.length > 0
-
- ToggleRow {
- label: qsTr("VPN enabled")
- checked: Config.utilities.vpn.enabled
- toggle.onToggled: {
- Config.utilities.vpn.enabled = checked;
- Config.save();
- }
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Providers")
- value: qsTr("%1").arg(Config.utilities.vpn.provider.length)
- }
-
- TextButton {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- Layout.minimumHeight: Appearance.font.size.normal + Appearance.padding.normal * 2
- text: qsTr("⚙ Manage VPN Providers")
- inactiveColour: Colours.palette.m3secondaryContainer
- inactiveOnColour: Colours.palette.m3onSecondaryContainer
-
- onClicked: {
- vpnSettingsDialog.open();
- }
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
title: qsTr("Current connection")
description: qsTr("Active network connection information")
}
@@ -135,37 +96,4 @@ ColumnLayout {
value: Nmcli.active ? qsTr("%1 MHz").arg(Nmcli.active.frequency) : qsTr("N/A")
}
}
-
- Popup {
- id: vpnSettingsDialog
-
- parent: Overlay.overlay
- anchors.centerIn: parent
- width: Math.min(600, parent.width - Appearance.padding.large * 2)
- height: Math.min(700, parent.height - Appearance.padding.large * 2)
-
- modal: true
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
- background: StyledRect {
- color: Colours.palette.m3surface
- radius: Appearance.rounding.large
- }
-
- StyledFlickable {
- anchors.fill: parent
- anchors.margins: Appearance.padding.large * 1.5
- flickableDirection: Flickable.VerticalFlick
- contentHeight: vpnSettingsContent.height
- clip: true
-
- VpnSettings {
- id: vpnSettingsContent
-
- anchors.left: parent.left
- anchors.right: parent.right
- session: root.session
- }
- }
- }
}
diff --git a/modules/controlcenter/network/NetworkingPane.qml b/modules/controlcenter/network/NetworkingPane.qml
index 26cdbfa..c32fbb7 100644
--- a/modules/controlcenter/network/NetworkingPane.qml
+++ b/modules/controlcenter/network/NetworkingPane.qml
@@ -112,24 +112,6 @@ Item {
}
CollapsibleSection {
- id: vpnListSection
-
- Layout.fillWidth: true
- title: qsTr("VPN")
- expanded: true
-
- Loader {
- Layout.fillWidth: true
- sourceComponent: Component {
- VpnList {
- session: root.session
- showHeader: false
- }
- }
- }
- }
-
- CollapsibleSection {
id: ethernetListSection
Layout.fillWidth: true
@@ -172,17 +154,14 @@ Item {
Item {
id: rightPaneItem
- property var vpnPane: root.session && root.session.vpn ? root.session.vpn.active : null
property var ethernetPane: root.session && root.session.ethernet ? root.session.ethernet.active : null
property var wirelessPane: root.session && root.session.network ? root.session.network.active : null
- property var pane: vpnPane || ethernetPane || wirelessPane
- property string paneId: vpnPane ? ("vpn:" + (vpnPane.name || "")) : (ethernetPane ? ("eth:" + (ethernetPane.interface || "")) : (wirelessPane ? ("wifi:" + (wirelessPane.ssid || wirelessPane.bssid || "")) : "settings"))
+ property var pane: ethernetPane || wirelessPane
+ property string paneId: ethernetPane ? ("eth:" + (ethernetPane.interface || "")) : (wirelessPane ? ("wifi:" + (wirelessPane.ssid || wirelessPane.bssid || "")) : "settings")
property Component targetComponent: settingsComponent
property Component nextComponent: settingsComponent
function getComponentForPane() {
- if (vpnPane)
- return vpnDetailsComponent;
if (ethernetPane)
return ethernetDetailsComponent;
if (wirelessPane)
@@ -196,30 +175,12 @@ Item {
}
Connections {
- target: root.session && root.session.vpn ? root.session.vpn : null
- enabled: target !== null
-
- function onActiveChanged() {
- // Clear others when VPN is selected
- if (root.session && root.session.vpn && root.session.vpn.active) {
- if (root.session.ethernet && root.session.ethernet.active)
- root.session.ethernet.active = null;
- if (root.session.network && root.session.network.active)
- root.session.network.active = null;
- }
- rightPaneItem.nextComponent = rightPaneItem.getComponentForPane();
- }
- }
-
- Connections {
target: root.session && root.session.ethernet ? root.session.ethernet : null
enabled: target !== null
function onActiveChanged() {
// Clear others when ethernet is selected
if (root.session && root.session.ethernet && root.session.ethernet.active) {
- if (root.session.vpn && root.session.vpn.active)
- root.session.vpn.active = null;
if (root.session.network && root.session.network.active)
root.session.network.active = null;
}
@@ -234,8 +195,6 @@ Item {
function onActiveChanged() {
// Clear others when wireless is selected
if (root.session && root.session.network && root.session.network.active) {
- if (root.session.vpn && root.session.vpn.active)
- root.session.vpn.active = null;
if (root.session.ethernet && root.session.ethernet.active)
root.session.ethernet.active = null;
}
@@ -342,29 +301,6 @@ Item {
}
}
- Component {
- id: vpnDetailsComponent
-
- StyledFlickable {
- id: vpnFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: vpnDetailsInner.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: vpnFlickable
- }
-
- VpnDetails {
- id: vpnDetailsInner
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- session: root.session
- }
- }
- }
-
WirelessPasswordDialog {
anchors.fill: parent
session: root.session
diff --git a/modules/controlcenter/network/VpnDetails.qml b/modules/controlcenter/network/VpnDetails.qml
deleted file mode 100644
index 1c71cd7..0000000
--- a/modules/controlcenter/network/VpnDetails.qml
+++ /dev/null
@@ -1,396 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Layouts
-
-DeviceDetails {
- id: root
-
- required property Session session
- readonly property var vpnProvider: root.session.vpn.active
- readonly property bool providerEnabled: {
- if (!vpnProvider || vpnProvider.index === undefined)
- return false;
- const provider = Config.utilities.vpn.provider[vpnProvider.index];
- return provider && typeof provider === "object" && provider.enabled === true;
- }
-
- device: vpnProvider
-
- headerComponent: Component {
- ConnectionHeader {
- icon: "vpn_key"
- title: root.vpnProvider?.displayName ?? qsTr("Unknown")
- }
- }
-
- sections: [
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Connection status")
- description: qsTr("VPN connection settings")
- }
-
- SectionContainer {
- ToggleRow {
- label: qsTr("Enable this provider")
- checked: root.providerEnabled
- toggle.onToggled: {
- if (!root.vpnProvider)
- return;
- const providers = [];
- const index = root.vpnProvider.index;
-
- // Copy providers and update enabled state
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- const p = Config.utilities.vpn.provider[i];
- if (typeof p === "object") {
- const newProvider = {
- name: p.name,
- displayName: p.displayName,
- interface: p.interface
- };
-
- if (checked) {
- // Enable this one, disable others
- newProvider.enabled = (i === index);
- } else {
- // Just disable this one
- newProvider.enabled = (i === index) ? false : (p.enabled !== false);
- }
-
- providers.push(newProvider);
- } else {
- providers.push(p);
- }
- }
-
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- spacing: Appearance.spacing.normal
-
- TextButton {
- Layout.fillWidth: true
- Layout.minimumHeight: Appearance.font.size.normal + Appearance.padding.normal * 2
- visible: root.providerEnabled
- enabled: !VPN.connecting
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
- text: VPN.connected ? qsTr("Disconnect") : qsTr("Connect")
-
- onClicked: {
- VPN.toggle();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Edit Provider")
- inactiveColour: Colours.palette.m3secondaryContainer
- inactiveOnColour: Colours.palette.m3onSecondaryContainer
-
- onClicked: {
- editVpnDialog.editIndex = root.vpnProvider.index;
- editVpnDialog.providerName = root.vpnProvider.name;
- editVpnDialog.displayName = root.vpnProvider.displayName;
- editVpnDialog.interfaceName = root.vpnProvider.interface;
- editVpnDialog.open();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Delete Provider")
- inactiveColour: Colours.palette.m3errorContainer
- inactiveOnColour: Colours.palette.m3onErrorContainer
-
- onClicked: {
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- if (i !== root.vpnProvider.index) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- }
- Config.utilities.vpn.provider = providers;
- Config.save();
- root.session.vpn.active = null;
- }
- }
- }
- }
- }
- },
- Component {
- ColumnLayout {
- spacing: Appearance.spacing.normal
-
- SectionHeader {
- title: qsTr("Provider details")
- description: qsTr("VPN provider information")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.small / 2
-
- PropertyRow {
- label: qsTr("Provider")
- value: root.vpnProvider?.name ?? qsTr("Unknown")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Display name")
- value: root.vpnProvider?.displayName ?? qsTr("Unknown")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Interface")
- value: root.vpnProvider?.interface || qsTr("N/A")
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Status")
- value: {
- if (!root.providerEnabled)
- return qsTr("Disabled");
- if (VPN.connecting)
- return qsTr("Connecting...");
- if (VPN.connected)
- return qsTr("Connected");
- return qsTr("Enabled (Not connected)");
- }
- }
-
- PropertyRow {
- showTopMargin: true
- label: qsTr("Enabled")
- value: root.providerEnabled ? qsTr("Yes") : qsTr("No")
- }
- }
- }
- }
- ]
-
- // Edit VPN Dialog
- Popup {
- id: editVpnDialog
-
- property int editIndex: -1
- property string providerName: ""
- property string displayName: ""
- property string interfaceName: ""
-
- parent: Overlay.overlay
- anchors.centerIn: parent
- width: Math.min(400, parent.width - Appearance.padding.large * 2)
- padding: Appearance.padding.large * 1.5
-
- modal: true
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
- opacity: 0
- scale: 0.7
-
- enter: Transition {
- Anim {
- property: "opacity"
- from: 0
- to: 1
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- Anim {
- property: "scale"
- from: 0.7
- to: 1
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
-
- exit: Transition {
- Anim {
- property: "opacity"
- from: 1
- to: 0
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- Anim {
- property: "scale"
- from: 1
- to: 0.7
- duration: Appearance.anim.durations.expressiveFastSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveFastSpatial
- }
- }
-
- function closeWithAnimation(): void {
- close();
- }
-
- Overlay.modal: Rectangle {
- color: Qt.rgba(0, 0, 0, 0.4 * editVpnDialog.opacity)
- }
-
- background: StyledRect {
- color: Colours.palette.m3surfaceContainerHigh
- radius: Appearance.rounding.large
-
- Elevation {
- anchors.fill: parent
- radius: parent.radius
- level: 3
- z: -1
- }
- }
-
- contentItem: ColumnLayout {
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Edit VPN Provider")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller / 2
-
- StyledText {
- text: qsTr("Display Name")
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3onSurfaceVariant
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: 40
- color: displayNameField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.small
- border.width: 1
- border.color: displayNameField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3)
-
- Behavior on color {
- CAnim {}
- }
- Behavior on border.color {
- CAnim {}
- }
-
- StyledTextField {
- id: displayNameField
- anchors.centerIn: parent
- width: parent.width - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignLeft
- text: editVpnDialog.displayName
- onTextChanged: editVpnDialog.displayName = text
- }
- }
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller / 2
-
- StyledText {
- text: qsTr("Interface (e.g., wg0, torguard)")
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3onSurfaceVariant
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: 40
- color: interfaceNameField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.small
- border.width: 1
- border.color: interfaceNameField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3)
-
- Behavior on color {
- CAnim {}
- }
- Behavior on border.color {
- CAnim {}
- }
-
- StyledTextField {
- id: interfaceNameField
- anchors.centerIn: parent
- width: parent.width - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignLeft
- text: editVpnDialog.interfaceName
- onTextChanged: editVpnDialog.interfaceName = text
- }
- }
- }
-
- RowLayout {
- Layout.topMargin: Appearance.spacing.normal
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Cancel")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
- onClicked: editVpnDialog.closeWithAnimation()
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Save")
- enabled: editVpnDialog.interfaceName.length > 0
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
-
- onClicked: {
- const providers = [];
- const oldProvider = Config.utilities.vpn.provider[editVpnDialog.editIndex];
- const wasEnabled = typeof oldProvider === "object" ? (oldProvider.enabled !== false) : true;
-
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- if (i === editVpnDialog.editIndex) {
- providers.push({
- name: editVpnDialog.providerName,
- displayName: editVpnDialog.displayName || editVpnDialog.interfaceName,
- interface: editVpnDialog.interfaceName,
- enabled: wasEnabled
- });
- } else {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- }
-
- Config.utilities.vpn.provider = providers;
- Config.save();
- editVpnDialog.closeWithAnimation();
- }
- }
- }
- }
- }
-}
diff --git a/modules/controlcenter/network/VpnList.qml b/modules/controlcenter/network/VpnList.qml
deleted file mode 100644
index 81f4a45..0000000
--- a/modules/controlcenter/network/VpnList.qml
+++ /dev/null
@@ -1,686 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property Session session
- property bool showHeader: true
- property int pendingSwitchIndex: -1
-
- spacing: Appearance.spacing.normal
-
- Connections {
- target: VPN
- function onConnectedChanged() {
- if (!VPN.connected && root.pendingSwitchIndex >= 0) {
- const targetIndex = root.pendingSwitchIndex;
- root.pendingSwitchIndex = -1;
-
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- const p = Config.utilities.vpn.provider[i];
- if (typeof p === "object") {
- const newProvider = {
- name: p.name,
- displayName: p.displayName,
- interface: p.interface,
- enabled: (i === targetIndex)
- };
- providers.push(newProvider);
- } else {
- providers.push(p);
- }
- }
- Config.utilities.vpn.provider = providers;
- Config.save();
-
- Qt.callLater(function () {
- VPN.toggle();
- });
- }
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("+ Add VPN Provider")
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
-
- onClicked: {
- vpnDialog.showProviderSelection();
- }
- }
-
- ListView {
- id: listView
-
- Layout.fillWidth: true
- Layout.preferredHeight: contentHeight
-
- interactive: false
- spacing: Appearance.spacing.smaller
-
- model: ScriptModel {
- values: Config.utilities.vpn.provider.map((provider, index) => {
- const isObject = typeof provider === "object";
- const name = isObject ? (provider.name || "custom") : String(provider);
- const displayName = isObject ? (provider.displayName || name) : name;
- const iface = isObject ? (provider.interface || "") : "";
- const enabled = isObject ? (provider.enabled === true) : false;
-
- return {
- index: index,
- name: name,
- displayName: displayName,
- interface: iface,
- provider: provider,
- enabled: enabled
- };
- })
- }
-
- delegate: Component {
- StyledRect {
- required property var modelData
- required property int index
-
- width: ListView.view ? ListView.view.width : undefined
-
- color: Qt.alpha(Colours.tPalette.m3surfaceContainer, (root.session && root.session.vpn && root.session.vpn.active === modelData) ? Colours.tPalette.m3surfaceContainer.a : 0)
- radius: Appearance.rounding.normal
-
- StateLayer {
- function onClicked(): void {
- if (root.session && root.session.vpn) {
- root.session.vpn.active = modelData;
- }
- }
- }
-
- RowLayout {
- id: rowLayout
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: icon.implicitHeight + Appearance.padding.normal * 2
-
- radius: Appearance.rounding.normal
- color: modelData.enabled && VPN.connected ? Colours.palette.m3primaryContainer : Colours.tPalette.m3surfaceContainerHigh
-
- MaterialIcon {
- id: icon
-
- anchors.centerIn: parent
- text: modelData.enabled && VPN.connected ? "vpn_key" : "vpn_key_off"
- font.pointSize: Appearance.font.size.large
- fill: modelData.enabled && VPN.connected ? 1 : 0
- color: modelData.enabled && VPN.connected ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
- }
- }
-
- ColumnLayout {
- Layout.fillWidth: true
-
- spacing: 0
-
- StyledText {
- Layout.fillWidth: true
- elide: Text.ElideRight
- maximumLineCount: 1
-
- text: modelData.displayName || qsTr("Unknown")
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller
-
- StyledText {
- Layout.fillWidth: true
- text: {
- if (modelData.enabled && VPN.connected)
- return qsTr("Connected");
- if (modelData.enabled && VPN.connecting)
- return qsTr("Connecting...");
- if (modelData.enabled)
- return qsTr("Enabled");
- return qsTr("Disabled");
- }
- color: modelData.enabled ? (VPN.connected ? Colours.palette.m3primary : Colours.palette.m3onSurface) : Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- font.weight: modelData.enabled && VPN.connected ? 500 : 400
- elide: Text.ElideRight
- }
- }
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: connectIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.full
- color: Qt.alpha(Colours.palette.m3primaryContainer, VPN.connected && modelData.enabled ? 1 : 0)
-
- StateLayer {
- enabled: !VPN.connecting
- function onClicked(): void {
- const clickedIndex = modelData.index;
-
- if (modelData.enabled) {
- VPN.toggle();
- } else {
- if (VPN.connected) {
- root.pendingSwitchIndex = clickedIndex;
- VPN.toggle();
- } else {
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- const p = Config.utilities.vpn.provider[i];
- if (typeof p === "object") {
- const newProvider = {
- name: p.name,
- displayName: p.displayName,
- interface: p.interface,
- enabled: (i === clickedIndex)
- };
- providers.push(newProvider);
- } else {
- providers.push(p);
- }
- }
- Config.utilities.vpn.provider = providers;
- Config.save();
-
- Qt.callLater(function () {
- VPN.toggle();
- });
- }
- }
- }
- }
-
- MaterialIcon {
- id: connectIcon
-
- anchors.centerIn: parent
- text: VPN.connected && modelData.enabled ? "link_off" : "link"
- color: VPN.connected && modelData.enabled ? Colours.palette.m3onPrimaryContainer : Colours.palette.m3onSurface
- }
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: deleteIcon.implicitHeight + Appearance.padding.smaller * 2
-
- radius: Appearance.rounding.full
- color: "transparent"
-
- StateLayer {
- function onClicked(): void {
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- if (i !== modelData.index) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- }
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
-
- MaterialIcon {
- id: deleteIcon
-
- anchors.centerIn: parent
- text: "delete"
- color: Colours.palette.m3onSurface
- }
- }
- }
-
- implicitHeight: rowLayout.implicitHeight + Appearance.padding.normal * 2
- }
- }
- }
-
- Popup {
- id: vpnDialog
-
- property string currentState: "selection"
- property int editIndex: -1
- property string providerName: ""
- property string displayName: ""
- property string interfaceName: ""
-
- parent: Overlay.overlay
- x: Math.round((parent.width - width) / 2)
- y: Math.round((parent.height - height) / 2)
- implicitWidth: Math.min(400, parent.width - Appearance.padding.large * 2)
- padding: Appearance.padding.large * 1.5
-
- modal: true
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
- opacity: 0
- scale: 0.7
-
- enter: Transition {
- ParallelAnimation {
- Anim {
- property: "opacity"
- from: 0
- to: 1
- duration: Appearance.anim.durations.normal
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- Anim {
- property: "scale"
- from: 0.7
- to: 1
- duration: Appearance.anim.durations.normal
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
-
- exit: Transition {
- ParallelAnimation {
- Anim {
- property: "opacity"
- from: 1
- to: 0
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- Anim {
- property: "scale"
- from: 1
- to: 0.7
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
-
- function showProviderSelection(): void {
- currentState = "selection";
- open();
- }
-
- function closeWithAnimation(): void {
- close();
- }
-
- function showAddForm(providerType: string, defaultDisplayName: string): void {
- editIndex = -1;
- providerName = providerType;
- displayName = defaultDisplayName;
- interfaceName = "";
-
- if (currentState === "selection") {
- transitionToForm.start();
- } else {
- currentState = "form";
- isClosing = false;
- open();
- }
- }
-
- function showEditForm(index: int): void {
- const provider = Config.utilities.vpn.provider[index];
- const isObject = typeof provider === "object";
-
- editIndex = index;
- providerName = isObject ? (provider.name || "custom") : String(provider);
- displayName = isObject ? (provider.displayName || providerName) : providerName;
- interfaceName = isObject ? (provider.interface || "") : "";
-
- currentState = "form";
- open();
- }
-
- Overlay.modal: Rectangle {
- color: Qt.rgba(0, 0, 0, 0.4 * vpnDialog.opacity)
- }
-
- onClosed: {
- currentState = "selection";
- }
-
- SequentialAnimation {
- id: transitionToForm
-
- ParallelAnimation {
- Anim {
- target: selectionContent
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- ScriptAction {
- script: {
- vpnDialog.currentState = "form";
- }
- }
-
- ParallelAnimation {
- Anim {
- target: formContent
- property: "opacity"
- to: 1
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
-
- background: StyledRect {
- color: Colours.palette.m3surfaceContainerHigh
- radius: Appearance.rounding.large
-
- Elevation {
- anchors.fill: parent
- radius: parent.radius
- level: 3
- z: -1
- }
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.normal
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
- }
-
- contentItem: Item {
- implicitHeight: vpnDialog.currentState === "selection" ? selectionContent.implicitHeight : formContent.implicitHeight
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.normal
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- ColumnLayout {
- id: selectionContent
-
- anchors.fill: parent
- spacing: Appearance.spacing.normal
- visible: vpnDialog.currentState === "selection"
- opacity: vpnDialog.currentState === "selection" ? 1 : 0
-
- Behavior on opacity {
- Anim {
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- StyledText {
- text: qsTr("Add VPN Provider")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Choose a provider to add")
- wrapMode: Text.WordWrap
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- TextButton {
- Layout.topMargin: Appearance.spacing.normal
- Layout.fillWidth: true
- text: qsTr("NetBird")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
- onClicked: {
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- providers.push({
- name: "netbird",
- displayName: "NetBird",
- interface: "wt0"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- vpnDialog.closeWithAnimation();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Tailscale")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
- onClicked: {
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- providers.push({
- name: "tailscale",
- displayName: "Tailscale",
- interface: "tailscale0"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- vpnDialog.closeWithAnimation();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Cloudflare WARP")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
- onClicked: {
- const providers = [];
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- providers.push({
- name: "warp",
- displayName: "Cloudflare WARP",
- interface: "CloudflareWARP"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- vpnDialog.closeWithAnimation();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("WireGuard (Custom)")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
- onClicked: {
- vpnDialog.showAddForm("wireguard", "WireGuard");
- }
- }
-
- TextButton {
- Layout.topMargin: Appearance.spacing.normal
- Layout.fillWidth: true
- text: qsTr("Cancel")
- inactiveColour: Colours.palette.m3secondaryContainer
- inactiveOnColour: Colours.palette.m3onSecondaryContainer
- onClicked: vpnDialog.closeWithAnimation()
- }
- }
-
- ColumnLayout {
- id: formContent
-
- anchors.fill: parent
- spacing: Appearance.spacing.normal
- visible: vpnDialog.currentState === "form"
- opacity: vpnDialog.currentState === "form" ? 1 : 0
-
- Behavior on opacity {
- Anim {
- duration: Appearance.anim.durations.small
- easing.bezierCurve: Appearance.anim.curves.emphasized
- }
- }
-
- StyledText {
- text: vpnDialog.editIndex >= 0 ? qsTr("Edit VPN Provider") : qsTr("Add %1 VPN").arg(vpnDialog.displayName)
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller / 2
-
- StyledText {
- text: qsTr("Display Name")
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3onSurfaceVariant
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: 40
- color: displayNameField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.small
- border.width: 1
- border.color: displayNameField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3)
-
- Behavior on color {
- CAnim {}
- }
- Behavior on border.color {
- CAnim {}
- }
-
- StyledTextField {
- id: displayNameField
- anchors.centerIn: parent
- width: parent.width - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignLeft
- text: vpnDialog.displayName
- onTextChanged: vpnDialog.displayName = text
- }
- }
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller / 2
-
- StyledText {
- text: qsTr("Interface (e.g., wg0, torguard)")
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3onSurfaceVariant
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: 40
- color: interfaceNameField.activeFocus ? Colours.layer(Colours.palette.m3surfaceContainer, 3) : Colours.layer(Colours.palette.m3surfaceContainer, 2)
- radius: Appearance.rounding.small
- border.width: 1
- border.color: interfaceNameField.activeFocus ? Colours.palette.m3primary : Qt.alpha(Colours.palette.m3outline, 0.3)
-
- Behavior on color {
- CAnim {}
- }
- Behavior on border.color {
- CAnim {}
- }
-
- StyledTextField {
- id: interfaceNameField
- anchors.centerIn: parent
- width: parent.width - Appearance.padding.normal
- horizontalAlignment: TextInput.AlignLeft
- text: vpnDialog.interfaceName
- onTextChanged: vpnDialog.interfaceName = text
- }
- }
- }
-
- RowLayout {
- Layout.topMargin: Appearance.spacing.normal
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Cancel")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
- onClicked: vpnDialog.closeWithAnimation()
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("Save")
- enabled: vpnDialog.interfaceName.length > 0
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
-
- onClicked: {
- const providers = [];
- const newProvider = {
- name: vpnDialog.providerName,
- displayName: vpnDialog.displayName || vpnDialog.interfaceName,
- interface: vpnDialog.interfaceName
- };
-
- if (vpnDialog.editIndex >= 0) {
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- if (i === vpnDialog.editIndex) {
- providers.push(newProvider);
- } else {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- }
- } else {
- for (let i = 0; i < Config.utilities.vpn.provider.length; i++) {
- providers.push(Config.utilities.vpn.provider[i]);
- }
- providers.push(newProvider);
- }
-
- Config.utilities.vpn.provider = providers;
- Config.save();
- vpnDialog.closeWithAnimation();
- }
- }
- }
- }
- }
- }
-}
diff --git a/modules/controlcenter/network/VpnSettings.qml b/modules/controlcenter/network/VpnSettings.qml
deleted file mode 100644
index 49d801d..0000000
--- a/modules/controlcenter/network/VpnSettings.qml
+++ /dev/null
@@ -1,232 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.components.effects
-import qs.services
-import qs.config
-import Quickshell
-import QtQuick
-import QtQuick.Controls
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property Session session
-
- spacing: Appearance.spacing.normal
-
- SettingsHeader {
- icon: "vpn_key"
- title: qsTr("VPN Settings")
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("General")
- description: qsTr("VPN configuration")
- }
-
- SectionContainer {
- ToggleRow {
- label: qsTr("VPN enabled")
- checked: Config.utilities.vpn.enabled
- toggle.onToggled: {
- Config.utilities.vpn.enabled = checked;
- Config.save();
- }
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("Providers")
- description: qsTr("Manage VPN providers")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.normal
-
- ListView {
- Layout.fillWidth: true
- Layout.preferredHeight: contentHeight
-
- interactive: false
- spacing: Appearance.spacing.smaller
-
- model: ScriptModel {
- values: Config.utilities.vpn.provider.map((provider, index) => {
- const isObject = typeof provider === "object";
- const name = isObject ? (provider.name || "custom") : String(provider);
- const displayName = isObject ? (provider.displayName || name) : name;
- const iface = isObject ? (provider.interface || "") : "";
-
- return {
- index: index,
- name: name,
- displayName: displayName,
- interface: iface,
- provider: provider,
- isActive: index === 0
- };
- })
- }
-
- delegate: Component {
- StyledRect {
- required property var modelData
- required property int index
-
- width: ListView.view ? ListView.view.width : undefined
- color: Colours.tPalette.m3surfaceContainerHigh
- radius: Appearance.rounding.normal
-
- RowLayout {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.normal
- spacing: Appearance.spacing.normal
-
- MaterialIcon {
- text: modelData.isActive ? "vpn_key" : "vpn_key_off"
- font.pointSize: Appearance.font.size.large
- color: modelData.isActive ? Colours.palette.m3primary : Colours.palette.m3outline
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- spacing: 0
-
- StyledText {
- text: modelData.displayName
- font.weight: modelData.isActive ? 500 : 400
- }
-
- StyledText {
- text: qsTr("%1 • %2").arg(modelData.name).arg(modelData.interface || qsTr("No interface"))
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3outline
- }
- }
-
- IconButton {
- icon: modelData.isActive ? "arrow_downward" : "arrow_upward"
- visible: !modelData.isActive || Config.utilities.vpn.provider.length > 1
- onClicked: {
- if (modelData.isActive && index < Config.utilities.vpn.provider.length - 1) {
- // Move down
- const providers = [...Config.utilities.vpn.provider];
- const temp = providers[index];
- providers[index] = providers[index + 1];
- providers[index + 1] = temp;
- Config.utilities.vpn.provider = providers;
- Config.save();
- } else if (!modelData.isActive) {
- // Make active (move to top)
- const providers = [...Config.utilities.vpn.provider];
- const provider = providers.splice(index, 1)[0];
- providers.unshift(provider);
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
- }
-
- IconButton {
- icon: "delete"
- onClicked: {
- const providers = [...Config.utilities.vpn.provider];
- providers.splice(index, 1);
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
- }
-
- implicitHeight: 60
- }
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.spacing.normal
- text: qsTr("+ Add Provider")
- inactiveColour: Colours.palette.m3primaryContainer
- inactiveOnColour: Colours.palette.m3onPrimaryContainer
-
- onClicked: {
- addProviderDialog.open();
- }
- }
- }
-
- SectionHeader {
- Layout.topMargin: Appearance.spacing.large
- title: qsTr("Quick Add")
- description: qsTr("Add common VPN providers")
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.smaller
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("+ Add NetBird")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
-
- onClicked: {
- const providers = [...Config.utilities.vpn.provider];
- providers.push({
- name: "netbird",
- displayName: "NetBird",
- interface: "wt0"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("+ Add Tailscale")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
-
- onClicked: {
- const providers = [...Config.utilities.vpn.provider];
- providers.push({
- name: "tailscale",
- displayName: "Tailscale",
- interface: "tailscale0"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
-
- TextButton {
- Layout.fillWidth: true
- text: qsTr("+ Add Cloudflare WARP")
- inactiveColour: Colours.tPalette.m3surfaceContainerHigh
- inactiveOnColour: Colours.palette.m3onSurface
-
- onClicked: {
- const providers = [...Config.utilities.vpn.provider];
- providers.push({
- name: "warp",
- displayName: "Cloudflare WARP",
- interface: "CloudflareWARP"
- });
- Config.utilities.vpn.provider = providers;
- Config.save();
- }
- }
- }
-}
diff --git a/modules/controlcenter/state/VpnState.qml b/modules/controlcenter/state/VpnState.qml
deleted file mode 100644
index aa911f1..0000000
--- a/modules/controlcenter/state/VpnState.qml
+++ /dev/null
@@ -1,5 +0,0 @@
-import QtQuick
-
-QtObject {
- property var active: null
-}
diff --git a/modules/controlcenter/taskbar/TaskbarPane.qml b/modules/controlcenter/taskbar/TaskbarPane.qml
deleted file mode 100644
index ba65c1e..0000000
--- a/modules/controlcenter/taskbar/TaskbarPane.qml
+++ /dev/null
@@ -1,757 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import ".."
-import "../components"
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-Item {
- id: root
-
- required property Session session
-
- property bool activeWindowCompact: Config.bar.activeWindow.compact ?? false
- property bool activeWindowInverted: Config.bar.activeWindow.inverted ?? false
- property bool clockShowIcon: Config.bar.clock.showIcon ?? true
- property bool persistent: Config.bar.persistent ?? true
- property bool showOnHover: Config.bar.showOnHover ?? true
- property int dragThreshold: Config.bar.dragThreshold ?? 20
- property bool showAudio: Config.bar.status.showAudio ?? true
- property bool showMicrophone: Config.bar.status.showMicrophone ?? true
- property bool showKbLayout: Config.bar.status.showKbLayout ?? false
- property bool showNetwork: Config.bar.status.showNetwork ?? true
- property bool showWifi: Config.bar.status.showWifi ?? true
- property bool showBluetooth: Config.bar.status.showBluetooth ?? true
- property bool showBattery: Config.bar.status.showBattery ?? true
- property bool showLockStatus: Config.bar.status.showLockStatus ?? true
- property bool trayBackground: Config.bar.tray.background ?? false
- property bool trayCompact: Config.bar.tray.compact ?? false
- property bool trayRecolour: Config.bar.tray.recolour ?? false
- property int workspacesShown: Config.bar.workspaces.shown ?? 5
- property bool workspacesActiveIndicator: Config.bar.workspaces.activeIndicator ?? true
- property bool workspacesOccupiedBg: Config.bar.workspaces.occupiedBg ?? false
- property bool workspacesShowWindows: Config.bar.workspaces.showWindows ?? false
- property int workspacesMaxWindowIcons: Config.bar.workspaces.maxWindowIcons ?? 0
- property bool workspacesPerMonitor: Config.bar.workspaces.perMonitorWorkspaces ?? true
- property bool scrollWorkspaces: Config.bar.scrollActions.workspaces ?? true
- property bool scrollVolume: Config.bar.scrollActions.volume ?? true
- property bool scrollBrightness: Config.bar.scrollActions.brightness ?? true
- property bool popoutActiveWindow: Config.bar.popouts.activeWindow ?? true
- property bool popoutTray: Config.bar.popouts.tray ?? true
- property bool popoutStatusIcons: Config.bar.popouts.statusIcons ?? true
- property list<string> monitorNames: Hypr.monitorNames()
- property list<string> excludedScreens: Config.bar.excludedScreens ?? []
-
- anchors.fill: parent
-
- Component.onCompleted: {
- if (Config.bar.entries) {
- entriesModel.clear();
- for (let i = 0; i < Config.bar.entries.length; i++) {
- const entry = Config.bar.entries[i];
- entriesModel.append({
- id: entry.id,
- enabled: entry.enabled !== false
- });
- }
- }
- }
-
- function saveConfig(entryIndex, entryEnabled) {
- Config.bar.activeWindow.compact = root.activeWindowCompact;
- Config.bar.activeWindow.inverted = root.activeWindowInverted;
- Config.bar.clock.showIcon = root.clockShowIcon;
- Config.bar.persistent = root.persistent;
- Config.bar.showOnHover = root.showOnHover;
- Config.bar.dragThreshold = root.dragThreshold;
- Config.bar.status.showAudio = root.showAudio;
- Config.bar.status.showMicrophone = root.showMicrophone;
- Config.bar.status.showKbLayout = root.showKbLayout;
- Config.bar.status.showNetwork = root.showNetwork;
- Config.bar.status.showWifi = root.showWifi;
- Config.bar.status.showBluetooth = root.showBluetooth;
- Config.bar.status.showBattery = root.showBattery;
- Config.bar.status.showLockStatus = root.showLockStatus;
- Config.bar.tray.background = root.trayBackground;
- Config.bar.tray.compact = root.trayCompact;
- Config.bar.tray.recolour = root.trayRecolour;
- Config.bar.workspaces.shown = root.workspacesShown;
- Config.bar.workspaces.activeIndicator = root.workspacesActiveIndicator;
- Config.bar.workspaces.occupiedBg = root.workspacesOccupiedBg;
- Config.bar.workspaces.showWindows = root.workspacesShowWindows;
- Config.bar.workspaces.maxWindowIcons = root.workspacesMaxWindowIcons;
- Config.bar.workspaces.perMonitorWorkspaces = root.workspacesPerMonitor;
- Config.bar.scrollActions.workspaces = root.scrollWorkspaces;
- Config.bar.scrollActions.volume = root.scrollVolume;
- Config.bar.scrollActions.brightness = root.scrollBrightness;
- Config.bar.popouts.activeWindow = root.popoutActiveWindow;
- Config.bar.popouts.tray = root.popoutTray;
- Config.bar.popouts.statusIcons = root.popoutStatusIcons;
- Config.bar.excludedScreens = root.excludedScreens;
-
- const entries = [];
- for (let i = 0; i < entriesModel.count; i++) {
- const entry = entriesModel.get(i);
- let enabled = entry.enabled;
- if (entryIndex !== undefined && i === entryIndex) {
- enabled = entryEnabled;
- }
- entries.push({
- id: entry.id,
- enabled: enabled
- });
- }
- Config.bar.entries = entries;
- Config.save();
- }
-
- ListModel {
- id: entriesModel
- }
-
- ClippingRectangle {
- id: taskbarClippingRect
- anchors.fill: parent
- anchors.margins: Appearance.padding.normal
- anchors.leftMargin: 0
- anchors.rightMargin: Appearance.padding.normal
-
- radius: taskbarBorder.innerRadius
- color: "transparent"
-
- Loader {
- id: taskbarLoader
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large + Appearance.padding.normal
- anchors.leftMargin: Appearance.padding.large
- anchors.rightMargin: Appearance.padding.large
-
- sourceComponent: taskbarContentComponent
- }
- }
-
- InnerBorder {
- id: taskbarBorder
- leftThickness: 0
- rightThickness: Appearance.padding.normal
- }
-
- Component {
- id: taskbarContentComponent
-
- StyledFlickable {
- id: sidebarFlickable
- flickableDirection: Flickable.VerticalFlick
- contentHeight: sidebarLayout.height
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: sidebarFlickable
- }
-
- ColumnLayout {
- id: sidebarLayout
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
-
- spacing: Appearance.spacing.normal
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- StyledText {
- text: qsTr("Taskbar")
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- }
- }
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Status Icons")
- font.pointSize: Appearance.font.size.normal
- }
-
- ConnectedButtonGroup {
- rootItem: root
-
- options: [
- {
- label: qsTr("Speakers"),
- propertyName: "showAudio",
- onToggled: function (checked) {
- root.showAudio = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Microphone"),
- propertyName: "showMicrophone",
- onToggled: function (checked) {
- root.showMicrophone = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Keyboard"),
- propertyName: "showKbLayout",
- onToggled: function (checked) {
- root.showKbLayout = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Network"),
- propertyName: "showNetwork",
- onToggled: function (checked) {
- root.showNetwork = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Wifi"),
- propertyName: "showWifi",
- onToggled: function (checked) {
- root.showWifi = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Bluetooth"),
- propertyName: "showBluetooth",
- onToggled: function (checked) {
- root.showBluetooth = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Battery"),
- propertyName: "showBattery",
- onToggled: function (checked) {
- root.showBattery = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Capslock"),
- propertyName: "showLockStatus",
- onToggled: function (checked) {
- root.showLockStatus = checked;
- root.saveConfig();
- }
- }
- ]
- }
- }
-
- RowLayout {
- id: mainRowLayout
- Layout.fillWidth: true
- spacing: Appearance.spacing.normal
-
- ColumnLayout {
- id: leftColumnLayout
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignTop
- spacing: Appearance.spacing.normal
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Workspaces")
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: workspacesShownRow.implicitHeight + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- RowLayout {
- id: workspacesShownRow
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Shown")
- }
-
- CustomSpinBox {
- min: 1
- max: 20
- value: root.workspacesShown
- onValueModified: value => {
- root.workspacesShown = value;
- root.saveConfig();
- }
- }
- }
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: workspacesActiveIndicatorRow.implicitHeight + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- RowLayout {
- id: workspacesActiveIndicatorRow
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Active indicator")
- }
-
- StyledSwitch {
- checked: root.workspacesActiveIndicator
- onToggled: {
- root.workspacesActiveIndicator = checked;
- root.saveConfig();
- }
- }
- }
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: workspacesOccupiedBgRow.implicitHeight + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- RowLayout {
- id: workspacesOccupiedBgRow
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Occupied background")
- }
-
- StyledSwitch {
- checked: root.workspacesOccupiedBg
- onToggled: {
- root.workspacesOccupiedBg = checked;
- root.saveConfig();
- }
- }
- }
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: workspacesShowWindowsRow.implicitHeight + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- RowLayout {
- id: workspacesShowWindowsRow
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Show windows")
- }
-
- StyledSwitch {
- checked: root.workspacesShowWindows
- onToggled: {
- root.workspacesShowWindows = checked;
- root.saveConfig();
- }
- }
- }
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: workspacesMaxWindowIconsRow.implicitHeight + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- RowLayout {
- id: workspacesMaxWindowIconsRow
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Max window icons")
- }
-
- CustomSpinBox {
- min: 0
- max: 20
- value: root.workspacesMaxWindowIcons
- onValueModified: value => {
- root.workspacesMaxWindowIcons = value;
- root.saveConfig();
- }
- }
- }
- }
-
- StyledRect {
- Layout.fillWidth: true
- implicitHeight: workspacesPerMonitorRow.implicitHeight + Appearance.padding.large * 2
- radius: Appearance.rounding.normal
- color: Colours.layer(Colours.palette.m3surfaceContainer, 2)
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- RowLayout {
- id: workspacesPerMonitorRow
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.margins: Appearance.padding.large
- spacing: Appearance.spacing.normal
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Per monitor workspaces")
- }
-
- StyledSwitch {
- checked: root.workspacesPerMonitor
- onToggled: {
- root.workspacesPerMonitor = checked;
- root.saveConfig();
- }
- }
- }
- }
- }
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Scroll Actions")
- font.pointSize: Appearance.font.size.normal
- }
-
- ConnectedButtonGroup {
- rootItem: root
-
- options: [
- {
- label: qsTr("Workspaces"),
- propertyName: "scrollWorkspaces",
- onToggled: function (checked) {
- root.scrollWorkspaces = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Volume"),
- propertyName: "scrollVolume",
- onToggled: function (checked) {
- root.scrollVolume = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Brightness"),
- propertyName: "scrollBrightness",
- onToggled: function (checked) {
- root.scrollBrightness = checked;
- root.saveConfig();
- }
- }
- ]
- }
- }
- }
-
- ColumnLayout {
- id: middleColumnLayout
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignTop
- spacing: Appearance.spacing.normal
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Clock")
- font.pointSize: Appearance.font.size.normal
- }
-
- SwitchRow {
- label: qsTr("Show clock icon")
- checked: root.clockShowIcon
- onToggled: checked => {
- root.clockShowIcon = checked;
- root.saveConfig();
- }
- }
- }
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Bar Behavior")
- font.pointSize: Appearance.font.size.normal
- }
-
- SwitchRow {
- label: qsTr("Persistent")
- checked: root.persistent
- onToggled: checked => {
- root.persistent = checked;
- root.saveConfig();
- }
- }
-
- SwitchRow {
- label: qsTr("Show on hover")
- checked: root.showOnHover
- onToggled: checked => {
- root.showOnHover = checked;
- root.saveConfig();
- }
- }
-
- SectionContainer {
- contentSpacing: Appearance.spacing.normal
-
- SliderInput {
- Layout.fillWidth: true
-
- label: qsTr("Drag threshold")
- value: root.dragThreshold
- from: 0
- to: 100
- suffix: "px"
- validator: IntValidator {
- bottom: 0
- top: 100
- }
- formatValueFunction: val => Math.round(val).toString()
- parseValueFunction: text => parseInt(text)
-
- onValueModified: newValue => {
- root.dragThreshold = Math.round(newValue);
- root.saveConfig();
- }
- }
- }
- }
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Active window")
- font.pointSize: Appearance.font.size.normal
- }
-
- SwitchRow {
- label: qsTr("Compact")
- checked: root.activeWindowCompact
- onToggled: checked => {
- root.activeWindowCompact = checked;
- root.saveConfig();
- }
- }
-
- SwitchRow {
- label: qsTr("Inverted")
- checked: root.activeWindowInverted
- onToggled: checked => {
- root.activeWindowInverted = checked;
- root.saveConfig();
- }
- }
- }
- }
-
- ColumnLayout {
- id: rightColumnLayout
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignTop
- spacing: Appearance.spacing.normal
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Popouts")
- font.pointSize: Appearance.font.size.normal
- }
-
- SwitchRow {
- label: qsTr("Active window")
- checked: root.popoutActiveWindow
- onToggled: checked => {
- root.popoutActiveWindow = checked;
- root.saveConfig();
- }
- }
-
- SwitchRow {
- label: qsTr("Tray")
- checked: root.popoutTray
- onToggled: checked => {
- root.popoutTray = checked;
- root.saveConfig();
- }
- }
-
- SwitchRow {
- label: qsTr("Status icons")
- checked: root.popoutStatusIcons
- onToggled: checked => {
- root.popoutStatusIcons = checked;
- root.saveConfig();
- }
- }
- }
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Tray Settings")
- font.pointSize: Appearance.font.size.normal
- }
-
- ConnectedButtonGroup {
- rootItem: root
-
- options: [
- {
- label: qsTr("Background"),
- propertyName: "trayBackground",
- onToggled: function (checked) {
- root.trayBackground = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Compact"),
- propertyName: "trayCompact",
- onToggled: function (checked) {
- root.trayCompact = checked;
- root.saveConfig();
- }
- },
- {
- label: qsTr("Recolour"),
- propertyName: "trayRecolour",
- onToggled: function (checked) {
- root.trayRecolour = checked;
- root.saveConfig();
- }
- }
- ]
- }
- }
-
- SectionContainer {
- Layout.fillWidth: true
- alignTop: true
-
- StyledText {
- text: qsTr("Monitors")
- font.pointSize: Appearance.font.size.normal
- }
-
- ConnectedButtonGroup {
- rootItem: root
- // max 3 options per line
- rows: Math.ceil(root.monitorNames.length / 3)
-
- options: root.monitorNames.map(e => ({
- label: qsTr(e),
- propertyName: `monitor${e}`,
- onToggled: function (_) {
- // if the given monitor is in the excluded list, it should be added back
- let addedBack = excludedScreens.includes(e);
- if (addedBack) {
- const index = excludedScreens.indexOf(e);
- if (index !== -1) {
- excludedScreens.splice(index, 1);
- }
- } else {
- if (!excludedScreens.includes(e)) {
- excludedScreens.push(e);
- }
- }
- root.saveConfig();
- },
- state: !Strings.testRegexList(root.excludedScreens, e)
- }))
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/modules/launcher/items/SchemeItem.qml b/modules/launcher/items/SchemeItem.qml
deleted file mode 100644
index 3ff1846..0000000
--- a/modules/launcher/items/SchemeItem.qml
+++ /dev/null
@@ -1,104 +0,0 @@
-import "../services"
-import qs.components
-import qs.services
-import qs.config
-import QtQuick
-
-Item {
- id: root
-
- required property Schemes.Scheme modelData
- required property var list
-
- implicitHeight: Config.launcher.sizes.itemHeight
-
- anchors.left: parent?.left
- anchors.right: parent?.right
-
- StateLayer {
- radius: Appearance.rounding.normal
-
- function onClicked(): void {
- root.modelData?.onClicked(root.list);
- }
- }
-
- Item {
- anchors.fill: parent
- anchors.leftMargin: Appearance.padding.larger
- anchors.rightMargin: Appearance.padding.larger
- anchors.margins: Appearance.padding.smaller
-
- StyledRect {
- id: preview
-
- anchors.verticalCenter: parent.verticalCenter
-
- border.width: 1
- border.color: Qt.alpha(`#${root.modelData?.colours?.outline}`, 0.5)
-
- color: `#${root.modelData?.colours?.surface}`
- radius: Appearance.rounding.full
- implicitWidth: parent.height * 0.8
- implicitHeight: parent.height * 0.8
-
- Item {
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.right: parent.right
-
- implicitWidth: parent.implicitWidth / 2
- clip: true
-
- StyledRect {
- anchors.top: parent.top
- anchors.bottom: parent.bottom
- anchors.right: parent.right
-
- implicitWidth: preview.implicitWidth
- color: `#${root.modelData?.colours?.primary}`
- radius: Appearance.rounding.full
- }
- }
- }
-
- Column {
- anchors.left: preview.right
- anchors.leftMargin: Appearance.spacing.normal
- anchors.verticalCenter: parent.verticalCenter
-
- width: parent.width - preview.width - anchors.leftMargin - (current.active ? current.width + Appearance.spacing.normal : 0)
- spacing: 0
-
- StyledText {
- text: root.modelData?.flavour ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- text: root.modelData?.name ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3outline
-
- elide: Text.ElideRight
- anchors.left: parent.left
- anchors.right: parent.right
- }
- }
-
- Loader {
- id: current
-
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
-
- active: `${root.modelData?.name} ${root.modelData?.flavour}` === Schemes.currentScheme
-
- sourceComponent: MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-}
diff --git a/modules/launcher/items/VariantItem.qml b/modules/launcher/items/VariantItem.qml
deleted file mode 100644
index 5c34fa8..0000000
--- a/modules/launcher/items/VariantItem.qml
+++ /dev/null
@@ -1,80 +0,0 @@
-import "../services"
-import qs.components
-import qs.services
-import qs.config
-import QtQuick
-
-Item {
- id: root
-
- required property M3Variants.Variant modelData
- required property var list
-
- implicitHeight: Config.launcher.sizes.itemHeight
-
- anchors.left: parent?.left
- anchors.right: parent?.right
-
- StateLayer {
- radius: Appearance.rounding.normal
-
- function onClicked(): void {
- root.modelData?.onClicked(root.list);
- }
- }
-
- Item {
- anchors.fill: parent
- anchors.leftMargin: Appearance.padding.larger
- anchors.rightMargin: Appearance.padding.larger
- anchors.margins: Appearance.padding.smaller
-
- MaterialIcon {
- id: icon
-
- text: root.modelData?.icon ?? ""
- font.pointSize: Appearance.font.size.extraLarge
-
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Column {
- anchors.left: icon.right
- anchors.leftMargin: Appearance.spacing.larger
- anchors.verticalCenter: icon.verticalCenter
-
- width: parent.width - icon.width - anchors.leftMargin - (current.active ? current.width + Appearance.spacing.normal : 0)
- spacing: 0
-
- StyledText {
- text: root.modelData?.name ?? ""
- font.pointSize: Appearance.font.size.normal
- }
-
- StyledText {
- text: root.modelData?.description ?? ""
- font.pointSize: Appearance.font.size.small
- color: Colours.palette.m3outline
-
- elide: Text.ElideRight
- anchors.left: parent.left
- anchors.right: parent.right
- }
- }
-
- Loader {
- id: current
-
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
-
- active: root.modelData?.variant === Schemes.currentVariant
-
- sourceComponent: MaterialIcon {
- text: "check"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.large
- }
- }
- }
-}
diff --git a/modules/launcher/services/Apps.qml b/modules/launcher/services/Apps.qml
index 7569a1e..bcd7345 100644
--- a/modules/launcher/services/Apps.qml
+++ b/modules/launcher/services/Apps.qml
@@ -66,7 +66,7 @@ Searcher {
}
list: appDb.apps
- useFuzzy: Config.launcher.useFuzzy.apps
+ useFuzzy: Config.launcher.useFuzzy
AppDb {
id: appDb
diff --git a/modules/lock/Center.qml b/modules/lock/Center.qml
deleted file mode 100644
index eb93275..0000000
--- a/modules/lock/Center.qml
+++ /dev/null
@@ -1,416 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.controls
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property var lock
- readonly property real centerScale: Math.min(1, (lock.screen?.height ?? 1440) / 1440)
- readonly property int centerWidth: Config.lock.sizes.centerWidth * centerScale
-
- Layout.preferredWidth: centerWidth
- Layout.fillWidth: false
- Layout.fillHeight: true
-
- spacing: Appearance.spacing.large * 2
-
- RowLayout {
- Layout.alignment: Qt.AlignHCenter
- spacing: Appearance.spacing.small
-
- StyledText {
- Layout.alignment: Qt.AlignVCenter
- text: Time.hourStr
- color: Colours.palette.m3secondary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * 3 * root.centerScale)
- font.family: Appearance.font.family.clock
- font.bold: true
- }
-
- StyledText {
- Layout.alignment: Qt.AlignVCenter
- text: ":"
- color: Colours.palette.m3primary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * 3 * root.centerScale)
- font.family: Appearance.font.family.clock
- font.bold: true
- }
-
- StyledText {
- Layout.alignment: Qt.AlignVCenter
- text: Time.minuteStr
- color: Colours.palette.m3secondary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * 3 * root.centerScale)
- font.family: Appearance.font.family.clock
- font.bold: true
- }
-
- Loader {
- Layout.leftMargin: Appearance.spacing.small
- Layout.alignment: Qt.AlignVCenter
-
- active: Config.services.useTwelveHourClock
- visible: active
-
- sourceComponent: StyledText {
- text: Time.amPmStr
- color: Colours.palette.m3primary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * 2 * root.centerScale)
- font.family: Appearance.font.family.clock
- font.bold: true
- }
- }
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- Layout.topMargin: -Appearance.padding.large * 2
-
- text: Time.format("dddd, d MMMM yyyy")
- color: Colours.palette.m3tertiary
- font.pointSize: Math.floor(Appearance.font.size.extraLarge * root.centerScale)
- font.family: Appearance.font.family.mono
- font.bold: true
- }
-
- StyledClippingRect {
- Layout.topMargin: Appearance.spacing.large * 2
- Layout.alignment: Qt.AlignHCenter
-
- implicitWidth: root.centerWidth / 2
- implicitHeight: root.centerWidth / 2
-
- color: Colours.tPalette.m3surfaceContainer
- radius: Appearance.rounding.full
-
- MaterialIcon {
- anchors.centerIn: parent
-
- text: "person"
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Math.floor(root.centerWidth / 4)
- visible: pfp.status !== Image.Ready
- }
-
- Image {
- id: pfp
-
- anchors.fill: parent
- source: Paths.face
- }
- }
-
- StyledRect {
- Layout.alignment: Qt.AlignHCenter
-
- implicitWidth: root.centerWidth * 0.8
- implicitHeight: input.implicitHeight + Appearance.padding.small * 2
-
- color: Colours.tPalette.m3surfaceContainer
- radius: Appearance.rounding.full
-
- focus: true
- onActiveFocusChanged: {
- if (!activeFocus)
- forceActiveFocus();
- }
-
- Keys.onPressed: event => {
- if (root.lock.unlocking)
- return;
-
- if (event.key === Qt.Key_Enter || event.key === Qt.Key_Return)
- inputField.placeholder.animate = false;
-
- root.lock.pam.handleKey(event);
- }
-
- StateLayer {
- hoverEnabled: false
- cursorShape: Qt.IBeamCursor
-
- function onClicked(): void {
- parent.forceActiveFocus();
- }
- }
-
- RowLayout {
- id: input
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.small
- spacing: Appearance.spacing.normal
-
- Item {
- implicitWidth: implicitHeight
- implicitHeight: fprintIcon.implicitHeight + Appearance.padding.small * 2
-
- MaterialIcon {
- id: fprintIcon
-
- anchors.centerIn: parent
- animate: true
- text: {
- if (root.lock.pam.fprint.tries >= Config.lock.maxFprintTries)
- return "fingerprint_off";
- if (root.lock.pam.fprint.active)
- return "fingerprint";
- return "lock";
- }
- color: root.lock.pam.fprint.tries >= Config.lock.maxFprintTries ? Colours.palette.m3error : Colours.palette.m3onSurface
- opacity: root.lock.pam.passwd.active ? 0 : 1
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- CircularIndicator {
- anchors.fill: parent
- running: root.lock.pam.passwd.active
- }
- }
-
- InputField {
- id: inputField
-
- pam: root.lock.pam
- }
-
- StyledRect {
- implicitWidth: implicitHeight
- implicitHeight: enterIcon.implicitHeight + Appearance.padding.small * 2
-
- color: root.lock.pam.buffer ? Colours.palette.m3primary : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
- radius: Appearance.rounding.full
-
- StateLayer {
- color: root.lock.pam.buffer ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
-
- function onClicked(): void {
- root.lock.pam.passwd.start();
- }
- }
-
- MaterialIcon {
- id: enterIcon
-
- anchors.centerIn: parent
- text: "arrow_forward"
- color: root.lock.pam.buffer ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
- font.weight: 500
- }
- }
- }
- }
-
- Item {
- Layout.fillWidth: true
- Layout.topMargin: -Appearance.spacing.large
-
- implicitHeight: Math.max(message.implicitHeight, stateMessage.implicitHeight)
-
- Behavior on implicitHeight {
- Anim {}
- }
-
- StyledText {
- id: stateMessage
-
- readonly property string msg: {
- if (Hypr.kbLayout !== Hypr.defaultKbLayout) {
- if (Hypr.capsLock && Hypr.numLock)
- return qsTr("Caps lock and Num lock are ON.\nKeyboard layout: %1").arg(Hypr.kbLayoutFull);
- if (Hypr.capsLock)
- return qsTr("Caps lock is ON. Kb layout: %1").arg(Hypr.kbLayoutFull);
- if (Hypr.numLock)
- return qsTr("Num lock is ON. Kb layout: %1").arg(Hypr.kbLayoutFull);
- return qsTr("Keyboard layout: %1").arg(Hypr.kbLayoutFull);
- }
-
- if (Hypr.capsLock && Hypr.numLock)
- return qsTr("Caps lock and Num lock are ON.");
- if (Hypr.capsLock)
- return qsTr("Caps lock is ON.");
- if (Hypr.numLock)
- return qsTr("Num lock is ON.");
-
- return "";
- }
-
- property bool shouldBeVisible
-
- onMsgChanged: {
- if (msg) {
- if (opacity > 0) {
- animate = true;
- text = msg;
- animate = false;
- } else {
- text = msg;
- }
- shouldBeVisible = true;
- } else {
- shouldBeVisible = false;
- }
- }
-
- anchors.left: parent.left
- anchors.right: parent.right
-
- scale: shouldBeVisible && !message.msg ? 1 : 0.7
- opacity: shouldBeVisible && !message.msg ? 1 : 0
- color: Colours.palette.m3onSurfaceVariant
- animateProp: "opacity"
-
- font.family: Appearance.font.family.mono
- horizontalAlignment: Qt.AlignHCenter
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
- lineHeight: 1.2
-
- Behavior on scale {
- Anim {}
- }
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- StyledText {
- id: message
-
- readonly property Pam pam: root.lock.pam
- readonly property string msg: {
- if (pam.fprintState === "error")
- return qsTr("FP ERROR: %1").arg(pam.fprint.message);
- if (pam.state === "error")
- return qsTr("PW ERROR: %1").arg(pam.passwd.message);
-
- if (pam.lockMessage)
- return pam.lockMessage;
-
- if (pam.state === "max" && pam.fprintState === "max")
- return qsTr("Maximum password and fingerprint attempts reached.");
- if (pam.state === "max") {
- if (pam.fprint.available)
- return qsTr("Maximum password attempts reached. Please use fingerprint.");
- return qsTr("Maximum password attempts reached.");
- }
- if (pam.fprintState === "max")
- return qsTr("Maximum fingerprint attempts reached. Please use password.");
-
- if (pam.state === "fail") {
- if (pam.fprint.available)
- return qsTr("Incorrect password. Please try again or use fingerprint.");
- return qsTr("Incorrect password. Please try again.");
- }
- if (pam.fprintState === "fail")
- return qsTr("Fingerprint not recognized (%1/%2). Please try again or use password.").arg(pam.fprint.tries).arg(Config.lock.maxFprintTries);
-
- return "";
- }
-
- anchors.left: parent.left
- anchors.right: parent.right
-
- scale: 0.7
- opacity: 0
- color: Colours.palette.m3error
-
- font.pointSize: Appearance.font.size.small
- font.family: Appearance.font.family.mono
- horizontalAlignment: Qt.AlignHCenter
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
-
- onMsgChanged: {
- if (msg) {
- if (opacity > 0) {
- animate = true;
- text = msg;
- animate = false;
-
- exitAnim.stop();
- if (scale < 1)
- appearAnim.restart();
- else
- flashAnim.restart();
- } else {
- text = msg;
- exitAnim.stop();
- appearAnim.restart();
- }
- } else {
- appearAnim.stop();
- flashAnim.stop();
- exitAnim.start();
- }
- }
-
- Connections {
- target: root.lock.pam
-
- function onFlashMsg(): void {
- exitAnim.stop();
- if (message.scale < 1)
- appearAnim.restart();
- else
- flashAnim.restart();
- }
- }
-
- Anim {
- id: appearAnim
-
- target: message
- properties: "scale,opacity"
- to: 1
- onFinished: flashAnim.restart()
- }
-
- SequentialAnimation {
- id: flashAnim
-
- loops: 2
-
- FlashAnim {
- to: 0.3
- }
- FlashAnim {
- to: 1
- }
- }
-
- ParallelAnimation {
- id: exitAnim
-
- Anim {
- target: message
- property: "scale"
- to: 0.7
- duration: Appearance.anim.durations.large
- }
- Anim {
- target: message
- property: "opacity"
- to: 0
- duration: Appearance.anim.durations.large
- }
- }
- }
- }
-
- component FlashAnim: NumberAnimation {
- target: message
- property: "opacity"
- duration: Appearance.anim.durations.small
- easing.type: Easing.Linear
- }
-}
diff --git a/modules/lock/Fetch.qml b/modules/lock/Fetch.qml
deleted file mode 100644
index e96b143..0000000
--- a/modules/lock/Fetch.qml
+++ /dev/null
@@ -1,177 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.effects
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell.Services.UPower
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large * 2
- anchors.topMargin: Appearance.padding.large
-
- spacing: Appearance.spacing.small
-
- RowLayout {
- Layout.fillWidth: true
- Layout.fillHeight: false
- spacing: Appearance.spacing.normal
-
- StyledRect {
- implicitWidth: prompt.implicitWidth + Appearance.padding.normal * 2
- implicitHeight: prompt.implicitHeight + Appearance.padding.normal * 2
-
- color: Colours.palette.m3primary
- radius: Appearance.rounding.small
-
- MonoText {
- id: prompt
-
- anchors.centerIn: parent
- text: ">"
- font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
- color: Colours.palette.m3onPrimary
- }
- }
-
- MonoText {
- Layout.fillWidth: true
- text: "caelestiafetch.sh"
- font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
- elide: Text.ElideRight
- }
-
- WrappedLoader {
- Layout.fillHeight: true
- active: !iconLoader.active
-
- sourceComponent: SysInfo.isDefaultLogo ? caelestiaLogo : distroIcon
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- Layout.fillHeight: false
- spacing: height * 0.15
-
- WrappedLoader {
- id: iconLoader
-
- Layout.fillHeight: true
- active: root.width > 320
-
- sourceComponent: SysInfo.isDefaultLogo ? caelestiaLogo : distroIcon
- }
-
- ColumnLayout {
- Layout.fillWidth: true
- Layout.topMargin: Appearance.padding.normal
- Layout.bottomMargin: Appearance.padding.normal
- Layout.leftMargin: iconLoader.active ? 0 : width * 0.1
- spacing: Appearance.spacing.normal
-
- WrappedLoader {
- Layout.fillWidth: true
- active: !batLoader.active && root.height > 200
-
- sourceComponent: FetchText {
- text: `OS : ${SysInfo.osPrettyName || SysInfo.osName}`
- }
- }
-
- WrappedLoader {
- Layout.fillWidth: true
- active: root.height > (batLoader.active ? 200 : 110)
-
- sourceComponent: FetchText {
- text: `WM : ${SysInfo.wm}`
- }
- }
-
- WrappedLoader {
- Layout.fillWidth: true
- active: !batLoader.active || root.height > 110
-
- sourceComponent: FetchText {
- text: `USER: ${SysInfo.user}`
- }
- }
-
- FetchText {
- text: `UP : ${SysInfo.uptime}`
- }
-
- WrappedLoader {
- id: batLoader
-
- Layout.fillWidth: true
- active: UPower.displayDevice.isLaptopBattery
-
- sourceComponent: FetchText {
- text: `BATT: ${[UPowerDeviceState.Charging, UPowerDeviceState.FullyCharged, UPowerDeviceState.PendingCharge].includes(UPower.displayDevice.state) ? "(+) " : ""}${Math.round(UPower.displayDevice.percentage * 100)}%`
- }
- }
- }
- }
-
- WrappedLoader {
- Layout.alignment: Qt.AlignHCenter
- active: root.height > 180
-
- sourceComponent: RowLayout {
- spacing: Appearance.spacing.large
-
- Repeater {
- model: Math.max(0, Math.min(8, root.width / (Appearance.font.size.larger * 2 + Appearance.spacing.large)))
-
- StyledRect {
- required property int index
-
- implicitWidth: implicitHeight
- implicitHeight: Appearance.font.size.larger * 2
- color: Colours.palette[`term${index}`]
- radius: Appearance.rounding.small
- }
- }
- }
- }
-
- Component {
- id: caelestiaLogo
-
- Logo {
- width: height
- }
- }
-
- Component {
- id: distroIcon
-
- ColouredIcon {
- source: SysInfo.osLogo
- implicitSize: height
- colour: Colours.palette.m3primary
- layer.enabled: Config.lock.recolourLogo
- }
- }
-
- component WrappedLoader: Loader {
- visible: active
- }
-
- component FetchText: MonoText {
- Layout.fillWidth: true
- font.pointSize: root.width > 400 ? Appearance.font.size.larger : Appearance.font.size.normal
- elide: Text.ElideRight
- }
-
- component MonoText: StyledText {
- font.family: Appearance.font.family.mono
- }
-}
diff --git a/modules/lock/NotifDock.qml b/modules/lock/NotifDock.qml
deleted file mode 100644
index cce86cd..0000000
--- a/modules/lock/NotifDock.qml
+++ /dev/null
@@ -1,145 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.containers
-import qs.components.effects
-import qs.services
-import qs.config
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property var lock
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large
-
- spacing: Appearance.spacing.smaller
-
- StyledText {
- Layout.fillWidth: true
- text: Notifs.list.length > 0 ? qsTr("%1 notification%2").arg(Notifs.list.length).arg(Notifs.list.length === 1 ? "" : "s") : qsTr("Notifications")
- color: Colours.palette.m3outline
- font.family: Appearance.font.family.mono
- font.weight: 500
- elide: Text.ElideRight
- }
-
- ClippingRectangle {
- id: clipRect
-
- Layout.fillWidth: true
- Layout.fillHeight: true
-
- radius: Appearance.rounding.small
- color: "transparent"
-
- Loader {
- anchors.centerIn: parent
- active: opacity > 0
- opacity: Notifs.list.length > 0 && !Config.lock.hideNotifs ? 0 : 1
-
- sourceComponent: ColumnLayout {
- spacing: Appearance.spacing.large
-
- Image {
- asynchronous: true
- source: Qt.resolvedUrl(`${Quickshell.shellDir}/assets/dino.png`)
- fillMode: Image.PreserveAspectFit
- sourceSize.width: clipRect.width * 0.8
-
- layer.enabled: true
- layer.effect: Colouriser {
- colorizationColor: Colours.palette.m3outlineVariant
- brightness: 1
- }
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: Config.lock.hideNotifs ? qsTr("Unlock for Notifications") : qsTr("No Notifications")
- color: Colours.palette.m3outlineVariant
- font.pointSize: Appearance.font.size.large
- font.family: Appearance.font.family.mono
- font.weight: 500
- }
- }
-
- Behavior on opacity {
- Anim {
- duration: Appearance.anim.durations.extraLarge
- }
- }
- }
-
- StyledListView {
- anchors.fill: parent
- visible: !Config.lock.hideNotifs
- spacing: Appearance.spacing.small
- clip: true
-
- model: ScriptModel {
- values: {
- const list = Notifs.notClosed.map(n => [n.appName, null]);
- return [...new Map(list).keys()];
- }
- }
-
- delegate: NotifGroup {}
-
- add: Transition {
- Anim {
- property: "opacity"
- from: 0
- to: 1
- }
- Anim {
- property: "scale"
- from: 0
- to: 1
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- remove: Transition {
- Anim {
- property: "opacity"
- to: 0
- }
- Anim {
- property: "scale"
- to: 0.6
- }
- }
-
- move: Transition {
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- Anim {
- property: "y"
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- displaced: Transition {
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- Anim {
- property: "y"
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
- }
- }
-}
diff --git a/modules/lock/NotifGroup.qml b/modules/lock/NotifGroup.qml
deleted file mode 100644
index 7fcb108..0000000
--- a/modules/lock/NotifGroup.qml
+++ /dev/null
@@ -1,339 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.effects
-import qs.services
-import qs.config
-import qs.utils
-import Quickshell
-import Quickshell.Widgets
-import Quickshell.Services.Notifications
-import QtQuick
-import QtQuick.Layouts
-
-StyledRect {
- id: root
-
- required property string modelData
-
- readonly property list<var> notifs: Notifs.list.filter(notif => notif.appName === modelData)
- readonly property var props: {
- let img = "";
- let icon = "";
- let hasCritical = false;
- let hasNormal = false;
- for (const n of notifs) {
- if (!img && n.image.length > 0)
- img = n.image;
- if (!icon && n.appIcon.length > 0)
- icon = n.appIcon;
- if (n.urgency === NotificationUrgency.Critical)
- hasCritical = true;
- else if (n.urgency === NotificationUrgency.Normal)
- hasNormal = true;
- }
- return {
- img,
- icon,
- urgency: hasCritical ? "critical" : hasNormal ? "normal" : "low"
- };
- }
- readonly property string image: props.img
- readonly property string appIcon: props.icon
- readonly property string urgency: props.urgency
-
- property bool expanded
-
- anchors.left: parent?.left
- anchors.right: parent?.right
- implicitHeight: content.implicitHeight + Appearance.padding.normal * 2
-
- clip: true
- radius: Appearance.rounding.normal
- color: root.urgency === "critical" ? Colours.palette.m3secondaryContainer : Colours.layer(Colours.palette.m3surfaceContainerHigh, 2)
-
- RowLayout {
- id: content
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.margins: Appearance.padding.normal
-
- spacing: Appearance.spacing.normal
-
- Item {
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- implicitWidth: Config.notifs.sizes.image
- implicitHeight: Config.notifs.sizes.image
-
- Component {
- id: imageComp
-
- Image {
- source: Qt.resolvedUrl(root.image)
- fillMode: Image.PreserveAspectCrop
- sourceSize.width: Config.notifs.sizes.image
- sourceSize.height: Config.notifs.sizes.image
- cache: false
- asynchronous: true
- width: Config.notifs.sizes.image
- height: Config.notifs.sizes.image
- }
- }
-
- Component {
- id: appIconComp
-
- ColouredIcon {
- implicitSize: Math.round(Config.notifs.sizes.image * 0.6)
- source: Quickshell.iconPath(root.appIcon)
- colour: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
- layer.enabled: root.appIcon.endsWith("symbolic")
- }
- }
-
- Component {
- id: materialIconComp
-
- MaterialIcon {
- text: Icons.getNotifIcon(root.notifs[0]?.summary, root.urgency)
- color: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
- font.pointSize: Appearance.font.size.large
- }
- }
-
- ClippingRectangle {
- anchors.fill: parent
- color: root.urgency === "critical" ? Colours.palette.m3error : root.urgency === "low" ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 3) : Colours.palette.m3secondaryContainer
- radius: Appearance.rounding.full
-
- Loader {
- anchors.centerIn: parent
- sourceComponent: root.image ? imageComp : root.appIcon ? appIconComp : materialIconComp
- }
- }
-
- Loader {
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- active: root.appIcon && root.image
-
- sourceComponent: StyledRect {
- implicitWidth: Config.notifs.sizes.badge
- implicitHeight: Config.notifs.sizes.badge
-
- color: root.urgency === "critical" ? Colours.palette.m3error : root.urgency === "low" ? Colours.palette.m3surfaceContainerHighest : Colours.palette.m3secondaryContainer
- radius: Appearance.rounding.full
-
- ColouredIcon {
- anchors.centerIn: parent
- implicitSize: Math.round(Config.notifs.sizes.badge * 0.6)
- source: Quickshell.iconPath(root.appIcon)
- colour: root.urgency === "critical" ? Colours.palette.m3onError : root.urgency === "low" ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
- layer.enabled: root.appIcon.endsWith("symbolic")
- }
- }
- }
- }
-
- ColumnLayout {
- Layout.topMargin: -Appearance.padding.small
- Layout.bottomMargin: -Appearance.padding.small / 2 - (root.expanded ? 0 : spacing)
- Layout.fillWidth: true
- spacing: Math.round(Appearance.spacing.small / 2)
-
- RowLayout {
- Layout.bottomMargin: -parent.spacing
- Layout.fillWidth: true
- spacing: Appearance.spacing.smaller
-
- StyledText {
- Layout.fillWidth: true
- text: root.modelData
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- elide: Text.ElideRight
- }
-
- StyledText {
- animate: true
- text: root.notifs[0]?.timeStr ?? ""
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.small
- }
-
- StyledRect {
- implicitWidth: expandBtn.implicitWidth + Appearance.padding.smaller * 2
- implicitHeight: groupCount.implicitHeight + Appearance.padding.small
-
- color: root.urgency === "critical" ? Colours.palette.m3error : Colours.layer(Colours.palette.m3surfaceContainerHighest, 2)
- radius: Appearance.rounding.full
-
- opacity: root.notifs.length > Config.notifs.groupPreviewNum ? 1 : 0
- Layout.preferredWidth: root.notifs.length > Config.notifs.groupPreviewNum ? implicitWidth : 0
-
- StateLayer {
- color: root.urgency === "critical" ? Colours.palette.m3onError : Colours.palette.m3onSurface
-
- function onClicked(): void {
- root.expanded = !root.expanded;
- }
- }
-
- RowLayout {
- id: expandBtn
-
- anchors.centerIn: parent
- spacing: Appearance.spacing.small / 2
-
- StyledText {
- id: groupCount
-
- Layout.leftMargin: Appearance.padding.small / 2
- animate: true
- text: root.notifs.length
- color: root.urgency === "critical" ? Colours.palette.m3onError : Colours.palette.m3onSurface
- font.pointSize: Appearance.font.size.small
- }
-
- MaterialIcon {
- Layout.rightMargin: -Appearance.padding.small / 2
- animate: true
- text: root.expanded ? "expand_less" : "expand_more"
- color: root.urgency === "critical" ? Colours.palette.m3onError : Colours.palette.m3onSurface
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on Layout.preferredWidth {
- Anim {}
- }
- }
- }
-
- Repeater {
- model: ScriptModel {
- values: root.notifs.slice(0, Config.notifs.groupPreviewNum)
- }
-
- NotifLine {
- id: notif
-
- ParallelAnimation {
- running: true
-
- Anim {
- target: notif
- property: "opacity"
- from: 0
- to: 1
- }
- Anim {
- target: notif
- property: "scale"
- from: 0.7
- to: 1
- }
- Anim {
- target: notif.Layout
- property: "preferredHeight"
- from: 0
- to: notif.implicitHeight
- }
- }
-
- ParallelAnimation {
- running: notif.modelData.closed
- onFinished: notif.modelData.unlock(notif)
-
- Anim {
- target: notif
- property: "opacity"
- to: 0
- }
- Anim {
- target: notif
- property: "scale"
- to: 0.7
- }
- Anim {
- target: notif.Layout
- property: "preferredHeight"
- to: 0
- }
- }
- }
- }
-
- Loader {
- Layout.fillWidth: true
-
- opacity: root.expanded ? 1 : 0
- Layout.preferredHeight: root.expanded ? implicitHeight : 0
- active: opacity > 0
-
- sourceComponent: ColumnLayout {
- Repeater {
- model: ScriptModel {
- values: root.notifs.slice(Config.notifs.groupPreviewNum)
- }
-
- NotifLine {}
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
- }
- }
- }
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
-
- component NotifLine: StyledText {
- id: notifLine
-
- required property Notifs.Notif modelData
-
- Layout.fillWidth: true
- textFormat: Text.MarkdownText
- text: {
- const summary = modelData.summary.replace(/\n/g, " ");
- const body = modelData.body.replace(/\n/g, " ");
- const colour = root.urgency === "critical" ? Colours.palette.m3secondary : Colours.palette.m3outline;
-
- if (metrics.text === metrics.elidedText)
- return `${summary} <span style='color:${colour}'>${body}</span>`;
-
- const t = metrics.elidedText.length - 3;
- if (t < summary.length)
- return `${summary.slice(0, t)}...`;
-
- return `${summary} <span style='color:${colour}'>${body.slice(0, t - summary.length)}...</span>`;
- }
- color: root.urgency === "critical" ? Colours.palette.m3onSecondaryContainer : Colours.palette.m3onSurface
-
- Component.onCompleted: modelData.lock(this)
- Component.onDestruction: modelData.unlock(this)
-
- TextMetrics {
- id: metrics
-
- text: `${notifLine.modelData.summary} ${notifLine.modelData.body}`.replace(/\n/g, " ")
- font.pointSize: notifLine.font.pointSize
- font.family: notifLine.font.family
- elideWidth: notifLine.width
- elide: Text.ElideRight
- }
- }
-}
diff --git a/modules/lock/WeatherInfo.qml b/modules/lock/WeatherInfo.qml
deleted file mode 100644
index d6c25af..0000000
--- a/modules/lock/WeatherInfo.qml
+++ /dev/null
@@ -1,176 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.services
-import qs.config
-import qs.utils
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property int rootHeight
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.margins: Appearance.padding.large * 2
-
- spacing: Appearance.spacing.small
-
- Loader {
- Layout.topMargin: Appearance.padding.large * 2
- Layout.bottomMargin: -Appearance.padding.large
- Layout.alignment: Qt.AlignHCenter
-
- active: root.rootHeight > 610
- visible: active
-
- sourceComponent: StyledText {
- text: qsTr("Weather")
- color: Colours.palette.m3primary
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: Appearance.spacing.large
-
- MaterialIcon {
- animate: true
- text: Weather.icon
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.extraLarge * 2.5
- }
-
- ColumnLayout {
- spacing: Appearance.spacing.small
-
- StyledText {
- Layout.fillWidth: true
-
- animate: true
- text: Weather.description
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.large
- font.weight: 500
- elide: Text.ElideRight
- }
-
- StyledText {
- Layout.fillWidth: true
-
- animate: true
- text: qsTr("Humidity: %1%").arg(Weather.humidity)
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.normal
- elide: Text.ElideRight
- }
- }
-
- Loader {
- Layout.rightMargin: Appearance.padding.smaller
- active: root.width > 400
- visible: active
-
- sourceComponent: ColumnLayout {
- spacing: Appearance.spacing.small
-
- StyledText {
- Layout.fillWidth: true
-
- animate: true
- text: Weather.temp
- color: Colours.palette.m3primary
- horizontalAlignment: Text.AlignRight
- font.pointSize: Appearance.font.size.extraLarge
- font.weight: 500
- elide: Text.ElideLeft
- }
-
- StyledText {
- Layout.fillWidth: true
-
- animate: true
- text: qsTr("Feels like: %1").arg(Weather.feelsLike)
- color: Colours.palette.m3outline
- horizontalAlignment: Text.AlignRight
- font.pointSize: Appearance.font.size.smaller
- elide: Text.ElideLeft
- }
- }
- }
- }
-
- Loader {
- id: forecastLoader
-
- Layout.topMargin: Appearance.spacing.smaller
- Layout.bottomMargin: Appearance.padding.large * 2
- Layout.fillWidth: true
-
- active: root.rootHeight > 820
- visible: active
-
- sourceComponent: RowLayout {
- spacing: Appearance.spacing.large
-
- Repeater {
- model: {
- const forecast = Weather.hourlyForecast;
- const count = root.width < 320 ? 3 : root.width < 400 ? 4 : 5;
- if (!forecast)
- return Array.from({
- length: count
- }, () => null);
-
- return forecast.slice(0, count);
- }
-
- ColumnLayout {
- id: forecastHour
-
- required property var modelData
-
- Layout.fillWidth: true
- spacing: Appearance.spacing.small
-
- StyledText {
- Layout.fillWidth: true
- text: {
- const hour = forecastHour.modelData?.hour ?? 0;
- return hour > 12 ? `${(hour - 12).toString().padStart(2, "0")} PM` : `${hour.toString().padStart(2, "0")} AM`;
- }
- color: Colours.palette.m3outline
- horizontalAlignment: Text.AlignHCenter
- font.pointSize: Appearance.font.size.larger
- }
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: forecastHour.modelData?.icon ?? "cloud_alert"
- font.pointSize: Appearance.font.size.extraLarge * 1.5
- font.weight: 500
- }
-
- StyledText {
- Layout.alignment: Qt.AlignHCenter
- text: Config.services.useFahrenheit ? `${forecastHour.modelData?.tempF ?? 0}°F` : `${forecastHour.modelData?.tempC ?? 0}°C`
- color: Colours.palette.m3secondary
- font.pointSize: Appearance.font.size.larger
- }
- }
- }
- }
- }
-
- Timer {
- running: true
- triggeredOnStart: true
- repeat: true
- interval: 900000 // 15 minutes
- onTriggered: Weather.reload()
- }
-}
diff --git a/modules/utilities/RecordingDeleteModal.qml b/modules/utilities/RecordingDeleteModal.qml
deleted file mode 100644
index 127afe9..0000000
--- a/modules/utilities/RecordingDeleteModal.qml
+++ /dev/null
@@ -1,207 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.controls
-import qs.components.effects
-import qs.services
-import qs.config
-import Caelestia
-import QtQuick
-import QtQuick.Layouts
-import QtQuick.Shapes
-
-Loader {
- id: root
-
- required property var props
-
- anchors.fill: parent
-
- opacity: root.props.recordingConfirmDelete ? 1 : 0
- active: opacity > 0
-
- sourceComponent: MouseArea {
- id: deleteConfirmation
-
- property string path
-
- Component.onCompleted: path = root.props.recordingConfirmDelete
-
- hoverEnabled: true
- onClicked: root.props.recordingConfirmDelete = ""
-
- Item {
- anchors.fill: parent
- anchors.margins: -Appearance.padding.large
- anchors.rightMargin: -Appearance.padding.large - Config.border.thickness
- anchors.bottomMargin: -Appearance.padding.large - Config.border.thickness
- opacity: 0.5
-
- StyledRect {
- anchors.fill: parent
- topLeftRadius: Config.border.rounding
- color: Colours.palette.m3scrim
- }
-
- Shape {
- id: shape
-
- anchors.fill: parent
- preferredRendererType: Shape.CurveRenderer
- asynchronous: true
-
- ShapePath {
- startX: -Config.border.rounding * 2
- startY: shape.height - Config.border.thickness
- strokeWidth: 0
- fillGradient: LinearGradient {
- orientation: LinearGradient.Horizontal
- x1: -Config.border.rounding * 2
-
- GradientStop {
- position: 0
- color: Qt.alpha(Colours.palette.m3scrim, 0)
- }
- GradientStop {
- position: 1
- color: Colours.palette.m3scrim
- }
- }
-
- PathLine {
- relativeX: Config.border.rounding
- relativeY: 0
- }
- PathArc {
- relativeY: -Config.border.rounding
- radiusX: Config.border.rounding
- radiusY: Config.border.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: 0
- relativeY: Config.border.rounding + Config.border.thickness
- }
- PathLine {
- relativeX: -Config.border.rounding * 2
- relativeY: 0
- }
- }
-
- ShapePath {
- startX: shape.width - Config.border.rounding - Config.border.thickness
- strokeWidth: 0
- fillGradient: LinearGradient {
- orientation: LinearGradient.Vertical
- y1: -Config.border.rounding * 2
-
- GradientStop {
- position: 0
- color: Qt.alpha(Colours.palette.m3scrim, 0)
- }
- GradientStop {
- position: 1
- color: Colours.palette.m3scrim
- }
- }
-
- PathArc {
- relativeX: Config.border.rounding
- relativeY: -Config.border.rounding
- radiusX: Config.border.rounding
- radiusY: Config.border.rounding
- direction: PathArc.Counterclockwise
- }
- PathLine {
- relativeX: 0
- relativeY: -Config.border.rounding
- }
- PathLine {
- relativeX: Config.border.thickness
- relativeY: 0
- }
- PathLine {
- relativeX: 0
- }
- }
- }
- }
-
- StyledRect {
- anchors.centerIn: parent
- radius: Appearance.rounding.large
- color: Colours.palette.m3surfaceContainerHigh
-
- scale: 0
- Component.onCompleted: scale = Qt.binding(() => root.props.recordingConfirmDelete ? 1 : 0)
-
- width: Math.min(parent.width - Appearance.padding.large * 2, implicitWidth)
- implicitWidth: deleteConfirmationLayout.implicitWidth + Appearance.padding.large * 3
- implicitHeight: deleteConfirmationLayout.implicitHeight + Appearance.padding.large * 3
-
- MouseArea {
- anchors.fill: parent
- }
-
- Elevation {
- anchors.fill: parent
- radius: parent.radius
- z: -1
- level: 3
- }
-
- ColumnLayout {
- id: deleteConfirmationLayout
-
- anchors.fill: parent
- anchors.margins: Appearance.padding.large * 1.5
- spacing: Appearance.spacing.normal
-
- StyledText {
- text: qsTr("Delete recording?")
- font.pointSize: Appearance.font.size.large
- }
-
- StyledText {
- Layout.fillWidth: true
- text: qsTr("Recording '%1' will be permanently deleted.").arg(deleteConfirmation.path)
- color: Colours.palette.m3onSurfaceVariant
- font.pointSize: Appearance.font.size.small
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
- }
-
- RowLayout {
- Layout.topMargin: Appearance.spacing.normal
- Layout.alignment: Qt.AlignRight
- spacing: Appearance.spacing.normal
-
- TextButton {
- text: qsTr("Cancel")
- type: TextButton.Text
- onClicked: root.props.recordingConfirmDelete = ""
- }
-
- TextButton {
- text: qsTr("Delete")
- type: TextButton.Text
- onClicked: {
- CUtils.deleteFile(Qt.resolvedUrl(root.props.recordingConfirmDelete));
- root.props.recordingConfirmDelete = "";
- }
- }
- }
- }
-
- Behavior on scale {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
-}
diff --git a/modules/utilities/cards/RecordingList.qml b/modules/utilities/cards/RecordingList.qml
deleted file mode 100644
index dbe7a73..0000000
--- a/modules/utilities/cards/RecordingList.qml
+++ /dev/null
@@ -1,240 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import qs.components
-import qs.components.controls
-import qs.components.containers
-import qs.services
-import qs.config
-import qs.utils
-import Caelestia
-import Quickshell
-import Quickshell.Widgets
-import QtQuick
-import QtQuick.Layouts
-
-ColumnLayout {
- id: root
-
- required property var props
- required property var visibilities
-
- spacing: 0
-
- WrapperMouseArea {
- Layout.fillWidth: true
-
- cursorShape: Qt.PointingHandCursor
- onClicked: root.props.recordingListExpanded = !root.props.recordingListExpanded
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- MaterialIcon {
- Layout.alignment: Qt.AlignVCenter
- text: "list"
- font.pointSize: Appearance.font.size.large
- }
-
- StyledText {
- Layout.alignment: Qt.AlignVCenter
- Layout.fillWidth: true
- text: qsTr("Recordings")
- font.pointSize: Appearance.font.size.normal
- }
-
- IconButton {
- icon: root.props.recordingListExpanded ? "unfold_less" : "unfold_more"
- type: IconButton.Text
- label.animate: true
- onClicked: root.props.recordingListExpanded = !root.props.recordingListExpanded
- }
- }
- }
-
- StyledListView {
- id: list
-
- model: FileSystemModel {
- path: Paths.recsdir
- nameFilters: ["recording_*.mp4"]
- sortReverse: true
- }
-
- Layout.fillWidth: true
- Layout.rightMargin: -Appearance.spacing.small
- implicitHeight: (Appearance.font.size.larger + Appearance.padding.small) * (root.props.recordingListExpanded ? 10 : 3)
- clip: true
-
- StyledScrollBar.vertical: StyledScrollBar {
- flickable: list
- }
-
- delegate: RowLayout {
- id: recording
-
- required property FileSystemEntry modelData
- property string baseName
-
- anchors.left: list.contentItem.left
- anchors.right: list.contentItem.right
- anchors.rightMargin: Appearance.spacing.small
- spacing: Appearance.spacing.small / 2
-
- Component.onCompleted: baseName = modelData.baseName
-
- StyledText {
- Layout.fillWidth: true
- Layout.rightMargin: Appearance.spacing.small / 2
- text: {
- const time = recording.baseName;
- const matches = time.match(/^recording_(\d{4})(\d{2})(\d{2})_(\d{2})-(\d{2})-(\d{2})/);
- if (!matches)
- return time;
- const date = new Date(...matches.slice(1));
- date.setMonth(date.getMonth() - 1); // Woe (months start from 0)
- return qsTr("Recording at %1").arg(Qt.formatDateTime(date, Qt.locale()));
- }
- color: Colours.palette.m3onSurfaceVariant
- elide: Text.ElideRight
- }
-
- IconButton {
- icon: "play_arrow"
- type: IconButton.Text
- onClicked: {
- root.visibilities.utilities = false;
- root.visibilities.sidebar = false;
- Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.playback, recording.modelData.path]);
- }
- }
-
- IconButton {
- icon: "folder"
- type: IconButton.Text
- onClicked: {
- root.visibilities.utilities = false;
- root.visibilities.sidebar = false;
- Quickshell.execDetached(["app2unit", "--", ...Config.general.apps.explorer, recording.modelData.path]);
- }
- }
-
- IconButton {
- icon: "delete_forever"
- type: IconButton.Text
- label.color: Colours.palette.m3error
- stateLayer.color: Colours.palette.m3error
- onClicked: root.props.recordingConfirmDelete = recording.modelData.path
- }
- }
-
- add: Transition {
- Anim {
- property: "opacity"
- from: 0
- to: 1
- }
- Anim {
- property: "scale"
- from: 0.5
- to: 1
- }
- }
-
- remove: Transition {
- Anim {
- property: "opacity"
- to: 0
- }
- Anim {
- property: "scale"
- to: 0.5
- }
- }
-
- displaced: Transition {
- Anim {
- properties: "opacity,scale"
- to: 1
- }
- Anim {
- property: "y"
- }
- }
-
- Loader {
- anchors.centerIn: parent
-
- opacity: list.count === 0 ? 1 : 0
- active: opacity > 0
-
- sourceComponent: ColumnLayout {
- spacing: Appearance.spacing.small
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: "scan_delete"
- color: Colours.palette.m3outline
- font.pointSize: Appearance.font.size.extraLarge
-
- opacity: root.props.recordingListExpanded ? 1 : 0
- scale: root.props.recordingListExpanded ? 1 : 0
- Layout.preferredHeight: root.props.recordingListExpanded ? implicitHeight : 0
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {}
- }
-
- Behavior on Layout.preferredHeight {
- Anim {}
- }
- }
-
- RowLayout {
- spacing: Appearance.spacing.smaller
-
- MaterialIcon {
- Layout.alignment: Qt.AlignHCenter
- text: "scan_delete"
- color: Colours.palette.m3outline
-
- opacity: !root.props.recordingListExpanded ? 1 : 0
- scale: !root.props.recordingListExpanded ? 1 : 0
- Layout.preferredWidth: !root.props.recordingListExpanded ? implicitWidth : 0
-
- Behavior on opacity {
- Anim {}
- }
-
- Behavior on scale {
- Anim {}
- }
-
- Behavior on Layout.preferredWidth {
- Anim {}
- }
- }
-
- StyledText {
- text: qsTr("No recordings found")
- color: Colours.palette.m3outline
- }
- }
- }
-
- Behavior on opacity {
- Anim {}
- }
- }
-
- Behavior on implicitHeight {
- Anim {
- duration: Appearance.anim.durations.expressiveDefaultSpatial
- easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
- }
- }
- }
-}