notifs/toasts: refactoring

This commit is contained in:
ATMDA 2025-11-12 16:42:45 -05:00
parent 893a91a95a
commit 223159f5b7
4 changed files with 84 additions and 204 deletions

View file

@ -0,0 +1,72 @@
import qs.components
import qs.components.effects
import qs.services
import qs.config
import qs.utils
import Quickshell
import Quickshell.Services.Notifications
import QtQuick
StyledRect {
id: root
required property Notifs.Notif modelData
required property bool hasImage
required property bool hasAppIcon
required property bool isCritical
required property bool isLow
radius: Appearance.rounding.full
color: {
if (root.isCritical) return Colours.palette.m3error;
if (root.isLow) return Colours.layer(Colours.palette.m3surfaceContainerHighest, 2);
return Colours.palette.m3secondaryContainer;
}
implicitWidth: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
implicitHeight: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
Loader {
id: icon
active: root.hasAppIcon
asynchronous: false
visible: active
anchors.centerIn: parent
width: Math.round(parent.width * 0.6)
height: Math.round(parent.width * 0.6)
sourceComponent: ColouredIcon {
anchors.fill: parent
source: Quickshell.iconPath(root.modelData.appIcon)
colour: {
if (root.isCritical) return Colours.palette.m3onError;
if (root.isLow) return Colours.palette.m3onSurface;
return Colours.palette.m3onSecondaryContainer;
}
layer.enabled: root.modelData.appIcon.endsWith("symbolic")
}
}
Loader {
active: !root.hasAppIcon
asynchronous: false
visible: active
anchors.centerIn: parent
anchors.horizontalCenterOffset: -Appearance.font.size.large * 0.02
anchors.verticalCenterOffset: Appearance.font.size.large * 0.02
sourceComponent: MaterialIcon {
text: Icons.getNotifIcon(root.modelData.summary, root.modelData.urgency)
color: {
if (root.isCritical) return Colours.palette.m3onError;
if (root.isLow) return Colours.palette.m3onSurface;
return Colours.palette.m3onSecondaryContainer;
}
font.pointSize: Appearance.font.size.large
}
}
}

View file

@ -155,59 +155,12 @@ StyledRect {
anchors.right: root.hasImage ? image.right : undefined
anchors.bottom: root.hasImage ? image.bottom : undefined
sourceComponent: StyledRect {
radius: Appearance.rounding.full
color: {
if (root.isCritical) return Colours.palette.m3error;
if (root.isLow) return Colours.layer(Colours.palette.m3surfaceContainerHighest, 2);
return Colours.palette.m3secondaryContainer;
}
implicitWidth: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
implicitHeight: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
Loader {
id: icon
active: root.hasAppIcon
asynchronous: false
visible: active
anchors.centerIn: parent
width: Math.round(parent.width * 0.6)
height: Math.round(parent.width * 0.6)
sourceComponent: ColouredIcon {
anchors.fill: parent
source: Quickshell.iconPath(root.modelData.appIcon)
colour: {
if (root.isCritical) return Colours.palette.m3onError;
if (root.isLow) return Colours.palette.m3onSurface;
return Colours.palette.m3onSecondaryContainer;
}
layer.enabled: root.modelData.appIcon.endsWith("symbolic")
}
}
Loader {
active: !root.hasAppIcon
asynchronous: false
visible: active
anchors.centerIn: parent
anchors.horizontalCenterOffset: -Appearance.font.size.large * 0.02
anchors.verticalCenterOffset: Appearance.font.size.large * 0.02
sourceComponent: MaterialIcon {
text: Icons.getNotifIcon(root.modelData.summary, root.modelData.urgency)
color: {
if (root.isCritical) return Colours.palette.m3onError;
if (root.isLow) return Colours.palette.m3onSurface;
return Colours.palette.m3onSecondaryContainer;
}
font.pointSize: Appearance.font.size.large
}
}
sourceComponent: AppIconBadge {
modelData: root.modelData
hasImage: root.hasImage
hasAppIcon: root.hasAppIcon
isCritical: root.isCritical
isLow: root.isLow
}
}

View file

@ -81,44 +81,12 @@ StyledRect {
anchors.right: root.hasImage ? parent.right : undefined
anchors.bottom: root.hasImage ? parent.bottom : undefined
sourceComponent: StyledRect {
radius: Appearance.rounding.full
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3error : root.modelData.urgency === NotificationUrgency.Low ? Colours.layer(Colours.palette.m3surfaceContainerHighest, 2) : Colours.palette.m3secondaryContainer
implicitWidth: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
implicitHeight: root.hasImage ? Config.notifs.sizes.badge : Config.notifs.sizes.image
Loader {
id: appIcon
active: root.hasAppIcon
asynchronous: true
anchors.centerIn: parent
width: Math.round(parent.width * 0.6)
height: Math.round(parent.width * 0.6)
sourceComponent: ColouredIcon {
anchors.fill: parent
source: Quickshell.iconPath(root.modelData.appIcon)
colour: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
layer.enabled: root.modelData.appIcon.endsWith("symbolic")
}
}
Loader {
active: !root.hasAppIcon
asynchronous: true
anchors.centerIn: parent
anchors.horizontalCenterOffset: -Appearance.font.size.large * 0.02
anchors.verticalCenterOffset: Appearance.font.size.large * 0.02
sourceComponent: MaterialIcon {
text: Icons.getNotifIcon(root.modelData.summary, root.modelData.urgency)
color: root.modelData.urgency === NotificationUrgency.Critical ? Colours.palette.m3onError : root.modelData.urgency === NotificationUrgency.Low ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
font.pointSize: Appearance.font.size.large
}
}
sourceComponent: AppIconBadge {
modelData: root.modelData
hasImage: root.hasImage
hasAppIcon: root.hasAppIcon
isCritical: root.modelData.urgency === NotificationUrgency.Critical
isLow: root.modelData.urgency === NotificationUrgency.Low
}
}
}

View file

@ -1,113 +0,0 @@
# Refactoring Plan: Control Center Panes
## Overview
After analyzing the last 30 commits, I've identified significant code duplication and opportunities for modularization in the control center panels. This plan focuses on extracting common patterns into reusable components.
## Key Refactoring Opportunities
### 1. Details Component Consolidation
**Files affected:** `modules/controlcenter/network/Details.qml`, `modules/controlcenter/ethernet/EthernetDetails.qml`
**Issue:** Both files share identical structure:
- Header with icon and title
- Connection status section
- Properties section
- Connection information section (IP, subnet, gateway, DNS)
**Solution:** Create `components/ConnectionDetails.qml` that accepts:
- Device/network object
- Icon name
- Title property path
- Details source (wirelessDeviceDetails vs ethernetDeviceDetails)
**Impact:** Reduces ~200 lines of duplication.
### 2. ToggleButton Component Extraction
**Files affected:** `modules/controlcenter/network/NetworkList.qml`, `modules/controlcenter/ethernet/EthernetList.qml`
**Issue:** Both files define identical `ToggleButton` component (lines 228-301 in NetworkList, 170-243 in EthernetList).
**Solution:** Move to `components/controls/ToggleButton.qml` and import in both files.
**Impact:** Eliminates ~70 lines of duplication.
### 3. Switch/SpinBox Row Components
**Files affected:** `modules/controlcenter/appearance/AppearancePane.qml`, `modules/controlcenter/taskbar/TaskbarPane.qml`
**Issue:** Repeated patterns for:
- Switch rows (label + StyledSwitch)
- SpinBox rows (label + CustomSpinBox)
- Same layout, spacing, and styling
**Solution:** Create:
- `components/controls/SwitchRow.qml` - label + switch with config save callback
- `components/controls/SpinBoxRow.qml` - label + spinbox with config save callback
**Impact:** Reduces ~30-40 lines per row instance (20+ instances total).
### 4. Font List Delegate Consolidation
**Files affected:** `modules/controlcenter/appearance/AppearancePane.qml`
**Issue:** Three nearly identical font list implementations (Material, Mono, Sans) with only the property binding differing.
**Solution:** Create `components/FontList.qml` that accepts:
- Current font property
- Save callback function
- Title text
**Impact:** Reduces ~150 lines of duplication.
### 5. List Item Selection Pattern
**Files affected:** Multiple list delegates across panes
**Issue:** Repeated pattern for selected item highlighting:
- Color with alpha based on selection
- Border width/color based on selection
- StateLayer click handler
**Solution:** Create `components/SelectableListItem.qml` wrapper that handles selection styling.
**Impact:** Reduces ~10-15 lines per list delegate.
## Implementation Order
1. **ConnectionDetails consolidation** (medium impact)
2. **FontList consolidation** (low-medium impact)
3. **SelectableListItem pattern** (nice-to-have, lower priority)
## Files to Create
- `components/controls/SelectableListItem.qml`
- `components/ConnectionDetails.qml`
- `components/FontList.qml`
## Completed Items
- ✅ `components/controls/CollapsibleSection.qml` - DONE
- ✅ `components/controls/SwitchRow.qml` - DONE
- ✅ `components/controls/SpinBoxRow.qml` - DONE
- ✅ `components/controls/ToggleButton.qml` - DONE
## Estimated Impact
- **Lines removed:** ~400-500 lines of duplicated code (from remaining items)
- **Maintainability:** Significantly improved - changes to common patterns only need to be made once
- **Readability:** Panes become more declarative and easier to understand
- **Testability:** Reusable components can be tested independently
## Completed Refactoring
- **Lines removed so far:** ~1300+ lines of duplicated code
- **Components created:** CollapsibleSection, SwitchRow, SpinBoxRow, ToggleButton