diff --git a/CLAUDE.md b/CLAUDE.md
index 6c3889f6..75576f49 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -191,9 +191,9 @@ shell.qml # Main entry point (minimal orchestration)
Singleton {
id: root
-
+
property type value: defaultValue
-
+
function performAction() { /* implementation */ }
}
```
@@ -251,23 +251,23 @@ shell.qml # Main entry point (minimal orchestration)
// For regular components
Item {
id: root
-
+
property type name: value
-
+
signal customSignal(type param)
-
+
onSignal: { /* handler */ }
-
+
Component { /* children */ }
}
-
+
// For services (singletons)
Singleton {
id: root
-
+
property bool featureAvailable: false
property type currentValue: defaultValue
-
+
function performAction(param) { /* implementation */ }
}
```
@@ -305,7 +305,7 @@ shell.qml # Main entry point (minimal orchestration)
```qml
// In services - detect capabilities
property bool brightnessAvailable: false
-
+
// In modules - adapt UI accordingly
DankSlider {
visible: DisplayService.brightnessAvailable
@@ -335,7 +335,7 @@ shell.qml # Main entry point (minimal orchestration)
console.log("Info message") // General info
console.warn("Warning message") // Warnings
console.error("Error message") // Errors
-
+
// Include context in service operations
onExited: (exitCode) => {
if (exitCode !== 0) {
diff --git a/Common/I18n.qml b/Common/I18n.qml
index 4a0543fe..286438da 100644
--- a/Common/I18n.qml
+++ b/Common/I18n.qml
@@ -16,7 +16,7 @@ Singleton {
return [fullUnderscore, fullHyphen, _lang].filter(c => c && c !== "en");
}
-
+
readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports")
property string currentLocale: "en"
diff --git a/Common/SettingsData.qml b/Common/SettingsData.qml
index 82a00f16..c2adee98 100644
--- a/Common/SettingsData.qml
+++ b/Common/SettingsData.qml
@@ -1180,7 +1180,7 @@ Singleton {
showWorkspaceIndex = enabled
saveSettings()
}
-
+
function setWorkspaceScrolling(enabled) {
workspaceScrolling = enabled
saveSettings()
diff --git a/Common/Theme.qml b/Common/Theme.qml
index c7aab51b..5cfb9c2a 100644
--- a/Common/Theme.qml
+++ b/Common/Theme.qml
@@ -61,7 +61,7 @@ Singleton {
}
readonly property string rawWallpaperPath: {
if (typeof SessionData === "undefined") return ""
-
+
if (SessionData.perMonitorWallpaper) {
// Use first monitor's wallpaper for dynamic theming
var screens = Quickshell.screens
diff --git a/Modals/Clipboard/ClipboardContent.qml b/Modals/Clipboard/ClipboardContent.qml
index 23a09bfa..835400ac 100644
--- a/Modals/Clipboard/ClipboardContent.qml
+++ b/Modals/Clipboard/ClipboardContent.qml
@@ -84,7 +84,7 @@ Item {
id: clipboardListView
anchors.fill: parent
model: filteredModel
-
+
currentIndex: clipboardContent.modal ? clipboardContent.modal.selectedIndex : 0
spacing: Theme.spacingXS
interactive: true
@@ -94,7 +94,7 @@ Item {
boundsMovement: Flickable.FollowBoundsBehavior
pressDelay: 0
flickableDirection: Flickable.VerticalFlick
-
+
function ensureVisible(index) {
if (index < 0 || index >= count) {
return
@@ -108,13 +108,13 @@ Item {
contentY = itemBottom - height
}
}
-
+
onCurrentIndexChanged: {
if (clipboardContent.modal && clipboardContent.modal.keyboardNavigationActive && currentIndex >= 0) {
ensureVisible(currentIndex)
}
}
-
+
StyledText {
text: I18n.tr("No clipboard entries found")
anchors.centerIn: parent
@@ -122,11 +122,11 @@ Item {
color: Theme.surfaceVariantText
visible: filteredModel.count === 0
}
-
+
delegate: ClipboardEntry {
required property int index
required property var model
-
+
width: clipboardListView.width
height: ClipboardConstants.itemHeight
entryData: model.entry
diff --git a/Modals/FileBrowser/FileBrowserModal.qml b/Modals/FileBrowser/FileBrowserModal.qml
index 8977b579..d5e8df88 100644
--- a/Modals/FileBrowser/FileBrowserModal.qml
+++ b/Modals/FileBrowser/FileBrowserModal.qml
@@ -111,18 +111,18 @@ DankModal {
if (!normalizedPath.startsWith("file://")) {
normalizedPath = "file://" + filePath
}
-
+
// Check if file exists by looking through the folder model
var exists = false
var fileName = filePath.split('/').pop()
-
+
for (var i = 0; i < folderModel.count; i++) {
if (folderModel.get(i, "fileName") === fileName && !folderModel.get(i, "fileIsDir")) {
exists = true
break
}
}
-
+
if (exists) {
pendingFilePath = normalizedPath
showOverwriteConfirmation = true
@@ -139,7 +139,7 @@ DankModal {
Component.onCompleted: {
currentPath = getLastPath()
}
-
+
property var steamPaths: [
StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/.steam/steam/steamapps/workshop/content/431960",
StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/.local/share/Steam/steamapps/workshop/content/431960",
@@ -147,17 +147,17 @@ DankModal {
StandardPaths.writableLocation(StandardPaths.HomeLocation) + "/snap/steam/common/.local/share/Steam/steamapps/workshop/content/431960"
]
property int currentPathIndex: 0
-
+
function discoverWallpaperEngine() {
currentPathIndex = 0
checkNextPath()
}
-
+
function checkNextPath() {
if (currentPathIndex >= steamPaths.length) {
return
}
-
+
const wePath = steamPaths[currentPathIndex]
const cleanPath = wePath.replace(/^file:\/\//, '')
weDiscoveryProcess.command = ["test", "-d", cleanPath]
@@ -451,13 +451,13 @@ DankModal {
executeKeyboardSelection(targetIndex)
}
}
-
+
Process {
id: weDiscoveryProcess
-
+
property string wePath: ""
running: false
-
+
onExited: exitCode => {
if (exitCode === 0) {
fileBrowserModal.weAvailable = true
@@ -532,7 +532,7 @@ DankModal {
}
}
}
-
+
DankActionButton {
circular: false
iconName: "info"
@@ -875,26 +875,26 @@ DankModal {
id: overwriteDialog
anchors.fill: parent
visible: showOverwriteConfirmation
-
+
Keys.onEscapePressed: {
showOverwriteConfirmation = false
pendingFilePath = ""
}
-
+
Keys.onReturnPressed: {
showOverwriteConfirmation = false
fileSelected(pendingFilePath)
pendingFilePath = ""
Qt.callLater(() => fileBrowserModal.close())
}
-
+
focus: showOverwriteConfirmation
-
+
Rectangle {
anchors.fill: parent
color: Theme.shadowStrong
opacity: 0.8
-
+
MouseArea {
anchors.fill: parent
onClicked: {
@@ -903,7 +903,7 @@ DankModal {
}
}
}
-
+
StyledRect {
anchors.centerIn: parent
width: 400
@@ -912,12 +912,12 @@ DankModal {
radius: Theme.cornerRadius
border.color: Theme.outlineMedium
border.width: 1
-
+
Column {
anchors.centerIn: parent
width: parent.width - Theme.spacingL * 2
spacing: Theme.spacingM
-
+
StyledText {
text: I18n.tr("File Already Exists")
font.pixelSize: Theme.fontSizeLarge
@@ -925,7 +925,7 @@ DankModal {
color: Theme.surfaceText
anchors.horizontalCenter: parent.horizontalCenter
}
-
+
StyledText {
text: I18n.tr("A file with this name already exists. Do you want to overwrite it?")
font.pixelSize: Theme.fontSizeMedium
@@ -934,11 +934,11 @@ DankModal {
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
-
+
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingM
-
+
StyledRect {
width: 80
height: 36
@@ -946,7 +946,7 @@ DankModal {
color: cancelArea.containsMouse ? Theme.surfaceVariantHover : Theme.surfaceVariant
border.color: Theme.outline
border.width: 1
-
+
StyledText {
anchors.centerIn: parent
text: I18n.tr("Cancel")
@@ -954,7 +954,7 @@ DankModal {
color: Theme.surfaceText
font.weight: Font.Medium
}
-
+
MouseArea {
id: cancelArea
anchors.fill: parent
@@ -966,13 +966,13 @@ DankModal {
}
}
}
-
+
StyledRect {
width: 90
height: 36
radius: Theme.cornerRadius
color: overwriteArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
-
+
StyledText {
anchors.centerIn: parent
text: I18n.tr("Overwrite")
@@ -980,7 +980,7 @@ DankModal {
color: Theme.background
font.weight: Font.Medium
}
-
+
MouseArea {
id: overwriteArea
anchors.fill: parent
diff --git a/Modals/NotificationModal.qml b/Modals/NotificationModal.qml
index 4225163c..aab7f316 100644
--- a/Modals/NotificationModal.qml
+++ b/Modals/NotificationModal.qml
@@ -20,7 +20,7 @@ DankModal {
if (modalKeyboardController && notificationListRef) {
modalKeyboardController.listView = notificationListRef
modalKeyboardController.rebuildFlatNavigation()
-
+
Qt.callLater(() => {
modalKeyboardController.keyboardNavigationActive = true
modalKeyboardController.selectedFlatIndex = 0
diff --git a/Modules/AppDrawer/AppLauncher.qml b/Modules/AppDrawer/AppLauncher.qml
index f6af5eed..b5c5f0a2 100644
--- a/Modules/AppDrawer/AppLauncher.qml
+++ b/Modules/AppDrawer/AppLauncher.qml
@@ -285,12 +285,12 @@ Item {
}
const triggers = PluginService.getAllPluginTriggers()
-
+
for (const trigger in triggers) {
if (query.startsWith(trigger)) {
const pluginId = triggers[trigger]
const plugin = PluginService.getLauncherPlugin(pluginId)
-
+
if (plugin) {
const remainingQuery = query.substring(trigger.length).trim()
const result = {
@@ -304,7 +304,7 @@ Item {
}
}
}
-
+
return { triggered: false, pluginCategory: "", query: "" }
}
diff --git a/Modules/ControlCenter/Details/AudioInputDetail.qml b/Modules/ControlCenter/Details/AudioInputDetail.qml
index 27132e8e..c0643f8b 100644
--- a/Modules/ControlCenter/Details/AudioInputDetail.qml
+++ b/Modules/ControlCenter/Details/AudioInputDetail.qml
@@ -17,7 +17,7 @@ Rectangle {
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
-
+
Row {
id: headerRow
anchors.left: parent.left
@@ -27,7 +27,7 @@ Rectangle {
anchors.rightMargin: Theme.spacingM
anchors.topMargin: Theme.spacingS
height: 40
-
+
StyledText {
id: headerText
text: I18n.tr("Input Devices")
@@ -37,7 +37,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
}
}
-
+
Row {
id: volumeSlider
anchors.left: parent.left
@@ -105,7 +105,7 @@ Rectangle {
}
}
}
-
+
DankFlickable {
id: audioContent
anchors.top: hasInputVolumeSliderInCC ? headerRow.bottom : volumeSlider.bottom
@@ -116,34 +116,34 @@ Rectangle {
anchors.topMargin: hasInputVolumeSliderInCC ? Theme.spacingM : Theme.spacingS
contentHeight: audioColumn.height
clip: true
-
+
Column {
id: audioColumn
width: parent.width
spacing: Theme.spacingS
-
+
Repeater {
model: Pipewire.nodes.values.filter(node => {
return node.audio && !node.isSink && !node.isStream
})
-
+
delegate: Rectangle {
required property var modelData
required property int index
-
+
width: parent.width
height: 50
radius: Theme.cornerRadius
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
border.color: modelData === AudioService.source ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 0
-
+
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
spacing: Theme.spacingS
-
+
DankIcon {
name: {
if (modelData.name.includes("bluez"))
@@ -157,11 +157,11 @@ Rectangle {
color: modelData === AudioService.source ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
-
+
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - Theme.iconSize - Theme.spacingM
-
+
StyledText {
text: AudioService.displayName(modelData)
font.pixelSize: Theme.fontSizeMedium
@@ -171,7 +171,7 @@ Rectangle {
width: parent.width
wrapMode: Text.NoWrap
}
-
+
StyledText {
text: modelData === AudioService.source ? "Active" : "Available"
font.pixelSize: Theme.fontSizeSmall
@@ -182,7 +182,7 @@ Rectangle {
}
}
}
-
+
MouseArea {
id: deviceMouseArea
anchors.fill: parent
diff --git a/Modules/ControlCenter/Details/AudioOutputDetail.qml b/Modules/ControlCenter/Details/AudioOutputDetail.qml
index 7352286d..e8be63ba 100644
--- a/Modules/ControlCenter/Details/AudioOutputDetail.qml
+++ b/Modules/ControlCenter/Details/AudioOutputDetail.qml
@@ -17,7 +17,7 @@ Rectangle {
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
-
+
Row {
id: headerRow
anchors.left: parent.left
@@ -27,7 +27,7 @@ Rectangle {
anchors.rightMargin: Theme.spacingM
anchors.topMargin: Theme.spacingS
height: 40
-
+
StyledText {
id: headerText
text: I18n.tr("Audio Devices")
@@ -121,34 +121,34 @@ Rectangle {
anchors.topMargin: volumeSlider.visible ? Theme.spacingS : Theme.spacingM
contentHeight: audioColumn.height
clip: true
-
+
Column {
id: audioColumn
width: parent.width
spacing: Theme.spacingS
-
+
Repeater {
model: Pipewire.nodes.values.filter(node => {
return node.audio && node.isSink && !node.isStream
})
-
+
delegate: Rectangle {
required property var modelData
required property int index
-
+
width: parent.width
height: 50
radius: Theme.cornerRadius
color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 0
-
+
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
spacing: Theme.spacingS
-
+
DankIcon {
name: {
if (modelData.name.includes("bluez"))
@@ -164,11 +164,11 @@ Rectangle {
color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
-
+
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.parent.width - parent.parent.anchors.leftMargin - parent.spacing - Theme.iconSize - Theme.spacingM
-
+
StyledText {
text: AudioService.displayName(modelData)
font.pixelSize: Theme.fontSizeMedium
@@ -178,7 +178,7 @@ Rectangle {
width: parent.width
wrapMode: Text.NoWrap
}
-
+
StyledText {
text: modelData === AudioService.sink ? "Active" : "Available"
font.pixelSize: Theme.fontSizeSmall
@@ -189,7 +189,7 @@ Rectangle {
}
}
}
-
+
MouseArea {
id: deviceMouseArea
anchors.fill: parent
diff --git a/Modules/ControlCenter/Details/BluetoothCodecSelector.qml b/Modules/ControlCenter/Details/BluetoothCodecSelector.qml
index 7256e2e5..0226065b 100644
--- a/Modules/ControlCenter/Details/BluetoothCodecSelector.qml
+++ b/Modules/ControlCenter/Details/BluetoothCodecSelector.qml
@@ -83,12 +83,12 @@ Item {
hoverEnabled: true
preventStealing: true
propagateComposedEvents: false
-
+
onClicked: root.hide()
onWheel: (wheel) => { wheel.accepted = true }
onPositionChanged: (mouse) => { mouse.accepted = true }
}
-
+
Rectangle {
id: modalBackground
anchors.fill: parent
diff --git a/Modules/ControlCenter/Details/BluetoothDetail.qml b/Modules/ControlCenter/Details/BluetoothDetail.qml
index be53b568..403a79bd 100644
--- a/Modules/ControlCenter/Details/BluetoothDetail.qml
+++ b/Modules/ControlCenter/Details/BluetoothDetail.qml
@@ -12,11 +12,11 @@ Rectangle {
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
border.width: 0
-
+
property var bluetoothCodecModalRef: null
-
+
signal showCodecSelector(var device)
-
+
function updateDeviceCodecDisplay(deviceAddress, codecName) {
for (let i = 0; i < pairedRepeater.count; i++) {
let item = pairedRepeater.itemAt(i)
@@ -26,7 +26,7 @@ Rectangle {
}
}
}
-
+
Row {
id: headerRow
anchors.left: parent.left
@@ -36,7 +36,7 @@ Rectangle {
anchors.rightMargin: Theme.spacingM
anchors.topMargin: Theme.spacingS
height: 40
-
+
StyledText {
id: headerText
text: I18n.tr("Bluetooth Settings")
@@ -45,12 +45,12 @@ Rectangle {
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
-
+
Item {
width: Math.max(0, parent.width - headerText.implicitWidth - scanButton.width - Theme.spacingM)
height: parent.height
}
-
+
Rectangle {
id: scanButton
width: 100
@@ -64,18 +64,18 @@ Rectangle {
border.color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 0
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
-
+
Row {
anchors.centerIn: parent
spacing: Theme.spacingXS
-
+
DankIcon {
name: BluetoothService.adapter && BluetoothService.adapter.discovering ? "stop" : "bluetooth_searching"
size: 18
color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
-
+
StyledText {
text: BluetoothService.adapter && BluetoothService.adapter.discovering ? "Scanning" : "Scan"
color: BluetoothService.adapter && BluetoothService.adapter.enabled ? Theme.primary : Theme.surfaceVariantText
@@ -84,7 +84,7 @@ Rectangle {
anchors.verticalCenter: parent.verticalCenter
}
}
-
+
MouseArea {
id: scanMouseArea
anchors.fill: parent
@@ -98,7 +98,7 @@ Rectangle {
}
}
}
-
+
DankFlickable {
id: bluetoothContent
anchors.top: headerRow.bottom
@@ -110,19 +110,19 @@ Rectangle {
visible: BluetoothService.adapter && BluetoothService.adapter.enabled
contentHeight: bluetoothColumn.height
clip: true
-
+
Column {
id: bluetoothColumn
width: parent.width
spacing: Theme.spacingS
-
-
+
+
Repeater {
id: pairedRepeater
model: {
if (!BluetoothService.adapter || !BluetoothService.adapter.devices)
return []
-
+
let devices = [...BluetoothService.adapter.devices.values.filter(dev => dev && (dev.paired || dev.trusted))]
devices.sort((a, b) => {
if (a.connected && !b.connected) return -1
@@ -131,17 +131,17 @@ Rectangle {
})
return devices
}
-
+
delegate: Rectangle {
required property var modelData
required property int index
-
+
property string currentCodec: BluetoothService.deviceCodecs[modelData.address] || ""
-
+
width: parent.width
height: 50
radius: Theme.cornerRadius
-
+
Component.onCompleted: {
if (modelData.connected && BluetoothService.isAudioDevice(modelData)) {
BluetoothService.refreshDeviceCodec(modelData)
@@ -162,13 +162,13 @@ Rectangle {
return Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
border.width: 0
-
+
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
spacing: Theme.spacingS
-
+
DankIcon {
name: BluetoothService.getDeviceIcon(modelData)
size: Theme.iconSize - 4
@@ -181,11 +181,11 @@ Rectangle {
}
anchors.verticalCenter: parent.verticalCenter
}
-
+
Column {
anchors.verticalCenter: parent.verticalCenter
width: 200
-
+
StyledText {
text: modelData.name || modelData.deviceName || "Unknown Device"
font.pixelSize: Theme.fontSizeMedium
@@ -194,10 +194,10 @@ Rectangle {
elide: Text.ElideRight
width: parent.width
}
-
+
Row {
spacing: Theme.spacingXS
-
+
StyledText {
text: {
if (modelData.state === BluetoothDeviceState.Connecting)
@@ -218,12 +218,12 @@ Rectangle {
return Theme.surfaceVariantText
}
}
-
+
StyledText {
text: {
if (modelData.batteryAvailable && modelData.battery > 0)
return "• " + Math.round(modelData.battery * 100) + "%"
-
+
var btBattery = BatteryService.bluetoothDevices.find(dev => {
return dev.name === (modelData.name || modelData.deviceName) ||
dev.name.toLowerCase().includes((modelData.name || modelData.deviceName).toLowerCase()) ||
@@ -235,7 +235,7 @@ Rectangle {
color: Theme.surfaceVariantText
visible: text.length > 0
}
-
+
StyledText {
text: modelData.signalStrength !== undefined && modelData.signalStrength > 0 ? "• " + modelData.signalStrength + "%" : ""
font.pixelSize: Theme.fontSizeSmall
@@ -245,7 +245,7 @@ Rectangle {
}
}
}
-
+
DankActionButton {
id: pairedOptionsButton
anchors.right: parent.right
@@ -262,7 +262,7 @@ Rectangle {
}
}
}
-
+
MouseArea {
id: deviceMouseArea
anchors.fill: parent
@@ -279,26 +279,26 @@ Rectangle {
}
}
}
-
+
Rectangle {
width: parent.width
height: 1
color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
visible: pairedRepeater.count > 0 && availableRepeater.count > 0
}
-
-
+
+
Item {
width: parent.width
height: 80
visible: BluetoothService.adapter && BluetoothService.adapter.discovering && availableRepeater.count === 0
-
+
DankIcon {
anchors.centerIn: parent
name: "sync"
size: 24
color: Qt.rgba(Theme.surfaceText.r || 0.8, Theme.surfaceText.g || 0.8, Theme.surfaceText.b || 0.8, 0.4)
-
+
RotationAnimation on rotation {
running: parent.visible && BluetoothService.adapter && BluetoothService.adapter.discovering && availableRepeater.count === 0
loops: Animation.Infinite
@@ -308,27 +308,27 @@ Rectangle {
}
}
}
-
+
Repeater {
id: availableRepeater
model: {
if (!BluetoothService.adapter || !BluetoothService.adapter.discovering || !Bluetooth.devices)
return []
-
+
var filtered = Bluetooth.devices.values.filter(dev => {
return dev && !dev.paired && !dev.pairing && !dev.blocked &&
(dev.signalStrength === undefined || dev.signalStrength > 0)
})
return BluetoothService.sortDevices(filtered)
}
-
+
delegate: Rectangle {
required property var modelData
required property int index
-
+
property bool canConnect: BluetoothService.canConnect(modelData)
property bool isBusy: BluetoothService.isDeviceBusy(modelData)
-
+
width: parent.width
height: 50
radius: Theme.cornerRadius
@@ -336,24 +336,24 @@ Rectangle {
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 0
opacity: canConnect ? 1 : 0.6
-
+
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
spacing: Theme.spacingS
-
+
DankIcon {
name: BluetoothService.getDeviceIcon(modelData)
size: Theme.iconSize - 4
color: Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
-
+
Column {
anchors.verticalCenter: parent.verticalCenter
width: 200
-
+
StyledText {
text: modelData.name || modelData.deviceName || "Unknown Device"
font.pixelSize: Theme.fontSizeMedium
@@ -361,10 +361,10 @@ Rectangle {
elide: Text.ElideRight
width: parent.width
}
-
+
Row {
spacing: Theme.spacingXS
-
+
StyledText {
text: {
if (modelData.pairing) return "Pairing..."
@@ -374,7 +374,7 @@ Rectangle {
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
-
+
StyledText {
text: modelData.signalStrength !== undefined && modelData.signalStrength > 0 ? "• " + modelData.signalStrength + "%" : ""
font.pixelSize: Theme.fontSizeSmall
@@ -384,7 +384,7 @@ Rectangle {
}
}
}
-
+
StyledText {
anchors.right: parent.right
anchors.rightMargin: Theme.spacingM
@@ -398,7 +398,7 @@ Rectangle {
color: canConnect ? Theme.primary : Theme.surfaceVariantText
font.weight: Font.Medium
}
-
+
MouseArea {
id: availableMouseArea
anchors.fill: parent
@@ -411,15 +411,15 @@ Rectangle {
}
}
}
-
+
}
}
-
+
Item {
width: parent.width
height: 60
visible: !BluetoothService.adapter
-
+
StyledText {
anchors.centerIn: parent
text: I18n.tr("No Bluetooth adapter found")
@@ -429,25 +429,25 @@ Rectangle {
}
}
}
-
+
Menu {
id: bluetoothContextMenu
width: 150
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
-
+
property var currentDevice: null
-
+
background: Rectangle {
color: Theme.popupBackground()
radius: Theme.cornerRadius
border.width: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
-
+
MenuItem {
text: bluetoothContextMenu.currentDevice && bluetoothContextMenu.currentDevice.connected ? "Disconnect" : "Connect"
height: 32
-
+
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
@@ -455,12 +455,12 @@ Rectangle {
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
-
+
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
-
+
onTriggered: {
if (bluetoothContextMenu.currentDevice) {
if (bluetoothContextMenu.currentDevice.connected) {
@@ -471,12 +471,12 @@ Rectangle {
}
}
}
-
+
MenuItem {
text: I18n.tr("Audio Codec")
height: bluetoothContextMenu.currentDevice && BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice) && bluetoothContextMenu.currentDevice.connected ? 32 : 0
visible: bluetoothContextMenu.currentDevice && BluetoothService.isAudioDevice(bluetoothContextMenu.currentDevice) && bluetoothContextMenu.currentDevice.connected
-
+
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
@@ -484,23 +484,23 @@ Rectangle {
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
-
+
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
-
+
onTriggered: {
if (bluetoothContextMenu.currentDevice) {
showCodecSelector(bluetoothContextMenu.currentDevice)
}
}
}
-
+
MenuItem {
text: I18n.tr("Forget Device")
height: 32
-
+
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
@@ -508,12 +508,12 @@ Rectangle {
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
-
+
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
-
+
onTriggered: {
if (bluetoothContextMenu.currentDevice) {
bluetoothContextMenu.currentDevice.forget()
@@ -521,5 +521,5 @@ Rectangle {
}
}
}
-
+
}
\ No newline at end of file
diff --git a/Modules/ControlCenter/Details/NetworkDetail.qml b/Modules/ControlCenter/Details/NetworkDetail.qml
index 6ca84ea8..3e2188b7 100644
--- a/Modules/ControlCenter/Details/NetworkDetail.qml
+++ b/Modules/ControlCenter/Details/NetworkDetail.qml
@@ -28,7 +28,7 @@ Rectangle {
Component.onDestruction: {
NetworkService.removeRef()
}
-
+
property int currentPreferenceIndex: {
if (DMSService.apiVersion < 5) {
return 1
@@ -88,7 +88,7 @@ Rectangle {
}
}
}
-
+
Item {
id: wifiToggleContent
anchors.top: headerRow.bottom
@@ -127,7 +127,7 @@ Rectangle {
}
}
}
-
+
Item {
id: wifiOffContent
anchors.top: headerRow.bottom
@@ -137,19 +137,19 @@ Rectangle {
anchors.topMargin: Theme.spacingM
visible: currentPreferenceIndex === 1 && !NetworkService.wifiEnabled && !NetworkService.wifiToggling
height: visible ? 120 : 0
-
+
Column {
anchors.centerIn: parent
spacing: Theme.spacingL
width: parent.width
-
+
DankIcon {
anchors.horizontalCenter: parent.horizontalCenter
name: "wifi_off"
size: 48
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
}
-
+
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: I18n.tr("WiFi is off")
@@ -158,7 +158,7 @@ Rectangle {
font.weight: Font.Medium
horizontalAlignment: Text.AlignHCenter
}
-
+
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
width: 120
@@ -167,7 +167,7 @@ Rectangle {
color: enableWifiButton.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08)
border.width: 0
border.color: Theme.primary
-
+
StyledText {
anchors.centerIn: parent
text: I18n.tr("Enable WiFi")
@@ -175,7 +175,7 @@ Rectangle {
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
}
-
+
MouseArea {
id: enableWifiButton
anchors.fill: parent
@@ -257,7 +257,7 @@ Rectangle {
}
}
}
-
+
DankActionButton {
id: wiredOptionsButton
anchors.right: parent.right
@@ -295,7 +295,7 @@ Rectangle {
}
}
}
-
+
Menu {
id: wiredNetworkContextMenu
width: 150
@@ -376,7 +376,7 @@ Rectangle {
id: wifiColumn
width: parent.width
spacing: Theme.spacingS
-
+
Item {
width: parent.width
height: 200
@@ -397,7 +397,7 @@ Rectangle {
}
}
}
-
+
Repeater {
model: sortedNetworks
@@ -415,20 +415,20 @@ Rectangle {
delegate: Rectangle {
required property var modelData
required property int index
-
+
width: parent.width
height: 50
radius: Theme.cornerRadius
color: networkMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : Theme.surfaceContainerHighest
border.color: modelData.ssid === NetworkService.currentWifiSSID ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 0
-
+
Row {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.spacingM
spacing: Theme.spacingS
-
+
DankIcon {
name: {
let strength = modelData.signal || 0
@@ -440,11 +440,11 @@ Rectangle {
color: modelData.ssid === NetworkService.currentWifiSSID ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
-
+
Column {
anchors.verticalCenter: parent.verticalCenter
width: 200
-
+
StyledText {
text: modelData.ssid || "Unknown Network"
font.pixelSize: Theme.fontSizeMedium
@@ -462,14 +462,14 @@ Rectangle {
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
-
+
StyledText {
text: modelData.saved ? "Saved" : ""
font.pixelSize: Theme.fontSizeSmall
color: Theme.primary
visible: text.length > 0
}
-
+
StyledText {
text: (modelData.saved ? "• " : "") + modelData.signal + "%"
font.pixelSize: Theme.fontSizeSmall
@@ -478,7 +478,7 @@ Rectangle {
}
}
}
-
+
DankActionButton {
id: optionsButton
anchors.right: parent.right
@@ -499,7 +499,7 @@ Rectangle {
}
}
}
-
+
MouseArea {
id: networkMouseArea
anchors.fill: parent
@@ -517,34 +517,34 @@ Rectangle {
event.accepted = true
}
}
-
+
}
}
}
}
-
+
Menu {
id: networkContextMenu
width: 150
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
-
+
property string currentSSID: ""
property bool currentSecured: false
property bool currentConnected: false
property bool currentSaved: false
property int currentSignal: 0
-
+
background: Rectangle {
color: Theme.popupBackground()
radius: Theme.cornerRadius
border.width: 0
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
}
-
+
MenuItem {
text: networkContextMenu.currentConnected ? "Disconnect" : "Connect"
height: 32
-
+
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
@@ -552,12 +552,12 @@ Rectangle {
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
-
+
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
-
+
onTriggered: {
if (networkContextMenu.currentConnected) {
NetworkService.disconnectWifi()
@@ -570,11 +570,11 @@ Rectangle {
}
}
}
-
+
MenuItem {
text: I18n.tr("Network Info")
height: 32
-
+
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
@@ -582,23 +582,23 @@ Rectangle {
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
-
+
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
-
+
onTriggered: {
let networkData = NetworkService.getNetworkInfo(networkContextMenu.currentSSID)
networkInfoModal.showNetworkInfo(networkContextMenu.currentSSID, networkData)
}
}
-
+
MenuItem {
text: I18n.tr("Forget Network")
height: networkContextMenu.currentSaved || networkContextMenu.currentConnected ? 32 : 0
visible: networkContextMenu.currentSaved || networkContextMenu.currentConnected
-
+
contentItem: StyledText {
text: parent.text
font.pixelSize: Theme.fontSizeSmall
@@ -606,18 +606,18 @@ Rectangle {
leftPadding: Theme.spacingS
verticalAlignment: Text.AlignVCenter
}
-
+
background: Rectangle {
color: parent.hovered ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.08) : "transparent"
radius: Theme.cornerRadius / 2
}
-
+
onTriggered: {
NetworkService.forgetWifiNetwork(networkContextMenu.currentSSID)
}
}
}
-
+
WifiPasswordModal {
id: wifiPasswordModal
}
@@ -625,7 +625,7 @@ Rectangle {
NetworkInfoModal {
id: networkInfoModal
}
-
+
NetworkWiredInfoModal {
id: networkWiredInfoModal
}
diff --git a/Modules/ControlCenter/Widgets/CompactSlider.qml b/Modules/ControlCenter/Widgets/CompactSlider.qml
index 7a039725..889c8c5d 100644
--- a/Modules/ControlCenter/Widgets/CompactSlider.qml
+++ b/Modules/ControlCenter/Widgets/CompactSlider.qml
@@ -14,7 +14,7 @@ Rectangle {
property real maximumValue: 1.0
property real minimumValue: 0.0
property bool enabled: true
-
+
signal sliderValueChanged(real value)
width: parent ? parent.width : 200
diff --git a/Modules/DankBar/Widgets/LauncherButton.qml b/Modules/DankBar/Widgets/LauncherButton.qml
index 28643ac5..f5e05269 100644
--- a/Modules/DankBar/Widgets/LauncherButton.qml
+++ b/Modules/DankBar/Widgets/LauncherButton.qml
@@ -38,7 +38,7 @@ Item {
}
return
}
-
+
root.clicked();
if (popupTarget && popupTarget.setTriggerPosition) {
const globalPos = mapToGlobal(0, 0);
diff --git a/Modules/DankBar/Widgets/RunningApps.qml b/Modules/DankBar/Widgets/RunningApps.qml
index 6d1645b2..a3426b74 100644
--- a/Modules/DankBar/Widgets/RunningApps.qml
+++ b/Modules/DankBar/Widgets/RunningApps.qml
@@ -82,20 +82,20 @@ Rectangle {
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
-
+
property real scrollAccumulator: 0
property real touchpadThreshold: 500
-
+
onWheel: (wheel) => {
const deltaY = wheel.angleDelta.y;
const isMouseWheel = Math.abs(deltaY) >= 120
&& (Math.abs(deltaY) % 120) === 0;
-
+
const windows = root.sortedToplevels;
if (windows.length < 2) {
return;
}
-
+
if (isMouseWheel) {
// Direct mouse wheel action
let currentIndex = -1;
@@ -128,7 +128,7 @@ Rectangle {
} else {
// Touchpad - accumulate small deltas
scrollAccumulator += deltaY;
-
+
if (Math.abs(scrollAccumulator) >= touchpadThreshold) {
let currentIndex = -1;
for (let i = 0; i < windows.length; i++) {
@@ -157,11 +157,11 @@ Rectangle {
if (nextWindow) {
nextWindow.activate();
}
-
+
scrollAccumulator = 0;
}
}
-
+
wheel.accepted = true;
}
}
@@ -640,51 +640,51 @@ Rectangle {
sourceComponent: DankTooltip {}
}
-
+
Loader {
id: windowContextMenuLoader
active: false
sourceComponent: PanelWindow {
id: contextMenuWindow
-
+
property var currentWindow: null
property bool isVisible: false
property point anchorPos: Qt.point(0, 0)
-
+
function showAt(x, y) {
screen = root.parentScreen;
anchorPos = Qt.point(x, y);
isVisible = true;
visible = true;
}
-
+
function close() {
isVisible = false;
visible = false;
windowContextMenuLoader.active = false;
}
-
+
implicitWidth: 100
implicitHeight: 40
visible: false
color: "transparent"
-
+
WlrLayershell.layer: WlrLayershell.Overlay
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
-
+
anchors {
top: true
left: true
right: true
bottom: true
}
-
+
MouseArea {
anchors.fill: parent
onClicked: contextMenuWindow.close();
}
-
+
Rectangle {
x: {
const left = 10;
@@ -699,13 +699,13 @@ Rectangle {
radius: Theme.cornerRadius
border.width: 1
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
-
+
Rectangle {
anchors.fill: parent
radius: parent.radius
color: closeMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
}
-
+
StyledText {
anchors.centerIn: parent
text: I18n.tr("Close")
@@ -713,7 +713,7 @@ Rectangle {
color: Theme.surfaceText
font.weight: Font.Normal
}
-
+
MouseArea {
id: closeMouseArea
anchors.fill: parent
diff --git a/Modules/DankBar/Widgets/WorkspaceSwitcher.qml b/Modules/DankBar/Widgets/WorkspaceSwitcher.qml
index a1f55f09..5afc27c3 100644
--- a/Modules/DankBar/Widgets/WorkspaceSwitcher.qml
+++ b/Modules/DankBar/Widgets/WorkspaceSwitcher.qml
@@ -290,7 +290,7 @@ Rectangle {
nextWindow.activate();
}
}
-
+
} else {
scrollAccumulator += deltaY
@@ -331,7 +331,7 @@ Rectangle {
nextWindow.activate();
}
}
-
+
scrollAccumulator = 0
}
}
diff --git a/Modules/DankDash/DankDashPopout.qml b/Modules/DankDash/DankDashPopout.qml
index 8e417bd1..f65f2c9d 100644
--- a/Modules/DankDash/DankDashPopout.qml
+++ b/Modules/DankDash/DankDashPopout.qml
@@ -134,11 +134,11 @@ DankPopout {
{ icon: "dashboard", text: I18n.tr("Overview") },
{ icon: "music_note", text: I18n.tr("Media") }
]
-
+
if (SettingsData.weatherEnabled) {
tabs.push({ icon: "wb_sunny", text: I18n.tr("Weather") })
}
-
+
tabs.push({ icon: "settings", text: I18n.tr("Settings"), isAction: true })
return tabs
}
diff --git a/Modules/DankDash/MediaPlayerTab.qml b/Modules/DankDash/MediaPlayerTab.qml
index 4fbd8555..3f2ea2e2 100644
--- a/Modules/DankDash/MediaPlayerTab.qml
+++ b/Modules/DankDash/MediaPlayerTab.qml
@@ -128,9 +128,9 @@ Item {
function getAudioDeviceIcon(device) {
if (!device || !device.name) return "speaker"
-
+
const name = device.name.toLowerCase()
-
+
if (name.includes("bluez") || name.includes("bluetooth"))
return "headset"
if (name.includes("hdmi"))
@@ -139,10 +139,10 @@ Item {
return "headset"
if (name.includes("analog") || name.includes("built-in"))
return "speaker"
-
+
return "speaker"
}
-
+
function getVolumeIcon(sink) {
if (!sink || !sink.audio) return "volume_off"
@@ -262,8 +262,8 @@ Item {
maybeFinishSwitch()
}
}
-
-
+
+
property bool isSeeking: false
@@ -325,7 +325,7 @@ Item {
return mouse.x < item.x || mouse.x > item.x + item.width ||
mouse.y < item.y || mouse.y > item.y + item.height
}
-
+
if (playerSelectorButton.playersExpanded && clickOutside(playerSelectorDropdown)) {
playerSelectorButton.playersExpanded = false
}
@@ -400,11 +400,11 @@ Item {
easing.bezierCurve: Anims.standard
}
}
-
+
Column {
anchors.fill: parent
anchors.margins: Theme.spacingM
-
+
StyledText {
text: I18n.tr("Audio Output Devices (") + audioDevicesDropdown.availableDevices.length + ")"
font.pixelSize: Theme.fontSizeMedium
@@ -414,49 +414,49 @@ Item {
horizontalAlignment: Text.AlignHCenter
bottomPadding: Theme.spacingM
}
-
+
DankFlickable {
width: parent.width
height: parent.height - 40
contentHeight: deviceColumn.height
clip: true
-
+
Column {
id: deviceColumn
width: parent.width
spacing: Theme.spacingS
-
+
Repeater {
model: audioDevicesDropdown.availableDevices
delegate: Rectangle {
required property var modelData
required property int index
-
+
width: parent.width
height: 48
radius: Theme.cornerRadius
color: deviceMouseAreaLeft.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.surfaceContainerHigh
border.color: modelData === AudioService.sink ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
border.width: modelData === AudioService.sink ? 2 : 1
-
+
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
width: parent.width - Theme.spacingM * 2
-
+
DankIcon {
name: getAudioDeviceIcon(modelData)
size: 20
color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText
anchors.verticalCenter: parent.verticalCenter
}
-
+
Column {
anchors.verticalCenter: parent.verticalCenter
width: parent.width - 20 - Theme.spacingM * 2
-
+
StyledText {
text: AudioService.displayName(modelData)
font.pixelSize: Theme.fontSizeMedium
@@ -466,7 +466,7 @@ Item {
width: parent.width
wrapMode: Text.NoWrap
}
-
+
StyledText {
text: modelData === AudioService.sink ? "Active" : "Available"
font.pixelSize: Theme.fontSizeSmall
@@ -477,7 +477,7 @@ Item {
}
}
}
-
+
MouseArea {
id: deviceMouseAreaLeft
anchors.fill: parent
@@ -490,7 +490,7 @@ Item {
audioDevicesButton.devicesExpanded = false
}
}
-
+
Behavior on border.color { ColorAnimation { duration: Anims.durShort } }
}
}
@@ -793,7 +793,7 @@ Item {
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
-
+
StyledText {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
@@ -812,7 +812,7 @@ Item {
Item {
width: parent.width
height: 50
-
+
Row {
anchors.centerIn: parent
spacing: Theme.spacingM
diff --git a/Modules/DankDash/Overview/CalendarOverviewCard.qml b/Modules/DankDash/Overview/CalendarOverviewCard.qml
index e3cde612..42da505d 100644
--- a/Modules/DankDash/Overview/CalendarOverviewCard.qml
+++ b/Modules/DankDash/Overview/CalendarOverviewCard.qml
@@ -92,12 +92,12 @@ Rectangle {
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
-
+
Item {
width: parent.width
height: 40
visible: showEventDetails
-
+
Rectangle {
width: 32
height: 32
@@ -122,7 +122,7 @@ Rectangle {
onClicked: root.showEventDetails = false
}
}
-
+
StyledText {
anchors.left: parent.left
anchors.right: parent.right
@@ -149,7 +149,7 @@ Rectangle {
width: parent.width
height: 28
visible: !showEventDetails
-
+
Rectangle {
width: 28
height: 28
@@ -215,7 +215,7 @@ Rectangle {
}
}
}
-
+
Row {
width: parent.width
height: 18
@@ -248,14 +248,14 @@ Rectangle {
}
}
}
-
+
Grid {
id: calendarGrid
visible: !showEventDetails
-
+
property date displayDate: systemClock.date
property date selectedDate: systemClock.date
-
+
readonly property date firstDay: {
const firstOfMonth = new Date(displayDate.getFullYear(), displayDate.getMonth(), 1)
return startOfWeek(firstOfMonth)
@@ -341,7 +341,7 @@ Rectangle {
visible: showEventDetails
clip: true
spacing: Theme.spacingXS
-
+
delegate: Rectangle {
width: parent ? parent.width : 0
height: eventContent.implicitHeight + Theme.spacingS
@@ -377,7 +377,7 @@ Rectangle {
Column {
id: eventContent
-
+
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
@@ -419,7 +419,7 @@ Rectangle {
MouseArea {
id: eventMouseArea
-
+
anchors.fill: parent
hoverEnabled: true
cursorShape: modelData.url ? Qt.PointingHandCursor : Qt.ArrowCursor
diff --git a/Modules/DankDash/Overview/Card.qml b/Modules/DankDash/Overview/Card.qml
index 1a1fc852..105f4c7b 100644
--- a/Modules/DankDash/Overview/Card.qml
+++ b/Modules/DankDash/Overview/Card.qml
@@ -4,9 +4,9 @@ import qs.Common
Rectangle {
id: card
-
+
property int pad: Theme.spacingM
-
+
radius: Theme.cornerRadius
color: Theme.surfaceContainerHigh
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
diff --git a/Modules/DankDash/Overview/ClockCard.qml b/Modules/DankDash/Overview/ClockCard.qml
index 9c1abbdf..e1a041ba 100644
--- a/Modules/DankDash/Overview/ClockCard.qml
+++ b/Modules/DankDash/Overview/ClockCard.qml
@@ -35,7 +35,7 @@ Card {
width: 28
horizontalAlignment: Text.AlignHCenter
}
-
+
StyledText {
text: {
if (SettingsData.use24HourClock) {
@@ -53,7 +53,7 @@ Card {
horizontalAlignment: Text.AlignHCenter
}
}
-
+
Row {
spacing: 0
anchors.horizontalCenter: parent.horizontalCenter
@@ -66,7 +66,7 @@ Card {
width: 28
horizontalAlignment: Text.AlignHCenter
}
-
+
StyledText {
text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(1)
font.pixelSize: 48
@@ -102,7 +102,7 @@ Card {
}
}
-
+
StyledText {
text: systemClock?.date?.toLocaleDateString(Qt.locale(), "MMM dd")
font.pixelSize: Theme.fontSizeSmall
diff --git a/Modules/DankDash/Overview/UserInfoCard.qml b/Modules/DankDash/Overview/UserInfoCard.qml
index 59f3b6e6..d8ad193d 100644
--- a/Modules/DankDash/Overview/UserInfoCard.qml
+++ b/Modules/DankDash/Overview/UserInfoCard.qml
@@ -92,7 +92,7 @@ Card {
}
// Just using truncated is always true initially idk
property bool shouldUseShort: longTextWidth > availableWidth
-
+
text: shouldUseShort ? UserInfoService.shortUptime : UserInfoService.uptime || "up 1h 23m"
font.pixelSize: Theme.fontSizeSmall
color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
diff --git a/Modules/DankDash/Overview/WeatherOverviewCard.qml b/Modules/DankDash/Overview/WeatherOverviewCard.qml
index f644725b..6695e3c8 100644
--- a/Modules/DankDash/Overview/WeatherOverviewCard.qml
+++ b/Modules/DankDash/Overview/WeatherOverviewCard.qml
@@ -47,18 +47,18 @@ Card {
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingL
visible: WeatherService.weather.available && WeatherService.weather.temp !== 0
-
+
DankIcon {
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
size: 48
color: Theme.primary
anchors.verticalCenter: parent.verticalCenter
}
-
+
Column {
spacing: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
-
+
StyledText {
text: {
const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
@@ -71,7 +71,7 @@ Card {
color: Theme.surfaceText
font.weight: Font.Light
}
-
+
StyledText {
text: WeatherService.getWeatherCondition(WeatherService.weather.wCode)
font.pixelSize: Theme.fontSizeSmall
diff --git a/Modules/DankDash/WeatherTab.qml b/Modules/DankDash/WeatherTab.qml
index 4e8459ae..d7fa1c20 100644
--- a/Modules/DankDash/WeatherTab.qml
+++ b/Modules/DankDash/WeatherTab.qml
@@ -132,7 +132,7 @@ Item {
anchors.left: tempText.right
anchors.leftMargin: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
-
+
MouseArea {
anchors.fill: parent
hoverEnabled: true
@@ -540,7 +540,7 @@ Item {
width: (parent.width - Theme.spacingXS * 6) / 7
height: parent.height
radius: Theme.cornerRadius
-
+
property var dayDate: {
const date = new Date()
date.setDate(date.getDate() + index)
diff --git a/Modules/Notepad/NotepadTextEditor.qml b/Modules/Notepad/NotepadTextEditor.qml
index da0db0f1..c0c2d94e 100644
--- a/Modules/Notepad/NotepadTextEditor.qml
+++ b/Modules/Notepad/NotepadTextEditor.qml
@@ -75,14 +75,14 @@ Column {
property string lastTextForLineModel: ""
property var lineModel: []
-
+
function updateLineModel() {
if (!SettingsData.notepadShowLineNumbers) {
lineModel = []
lastTextForLineModel = ""
return
}
-
+
if (textArea.text !== lastTextForLineModel || lineModel.length === 0) {
lastTextForLineModel = textArea.text
lineModel = textArea.text.split('\n')
@@ -129,10 +129,10 @@ Column {
function highlightCurrentMatch() {
if (currentMatchIndex >= 0 && currentMatchIndex < searchMatches.length) {
const match = searchMatches[currentMatchIndex]
-
+
textArea.cursorPosition = match.start
textArea.moveCursorSelection(match.end, TextEdit.SelectCharacters)
-
+
const flickable = textArea.parent
if (flickable && flickable.contentY !== undefined) {
const lineHeight = textArea.font.pixelSize * 1.5
@@ -219,11 +219,11 @@ Column {
verticalAlignment: TextInput.AlignVCenter
selectByMouse: true
clip: true
-
+
Component.onCompleted: {
text = root.searchQuery
}
-
+
Connections {
target: root
function onSearchQueryChanged() {
@@ -232,7 +232,7 @@ Column {
}
}
}
-
+
onTextChanged: {
if (root.searchQuery !== text) {
root.searchQuery = text
@@ -260,7 +260,7 @@ Column {
event.accepted = true
}
}
-
+
// Placeholder text
StyledText {
Layout.fillWidth: true
diff --git a/Modules/Settings/AboutTab.qml b/Modules/Settings/AboutTab.qml
index 1195fa08..d5cdae14 100644
--- a/Modules/Settings/AboutTab.qml
+++ b/Modules/Settings/AboutTab.qml
@@ -366,7 +366,7 @@ Item {
Row {
spacing: 4
-
+
StyledText {
text: `niri`
font.pixelSize: Theme.fontSizeMedium
@@ -383,14 +383,14 @@ Item {
propagateComposedEvents: true
}
}
-
+
StyledText {
text: "&"
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter
}
-
+
StyledText {
text: `hyprland`
font.pixelSize: Theme.fontSizeMedium
@@ -418,7 +418,7 @@ Item {
Row {
spacing: 4
-
+
StyledText {
text: `DankMaterialShell`
font.pixelSize: Theme.fontSizeMedium
@@ -435,7 +435,7 @@ Item {
propagateComposedEvents: true
}
}
-
+
StyledText {
text: I18n.tr("- Support Us With a Star ⭐")
font.pixelSize: Theme.fontSizeMedium
@@ -453,7 +453,7 @@ Item {
Row {
spacing: 4
-
+
StyledText {
text: `dgop`
font.pixelSize: Theme.fontSizeMedium
@@ -470,7 +470,7 @@ Item {
propagateComposedEvents: true
}
}
-
+
StyledText {
text: I18n.tr("- Stateless System Monitoring")
font.pixelSize: Theme.fontSizeMedium
@@ -488,7 +488,7 @@ Item {
Row {
spacing: 4
-
+
StyledText {
text: `danklinux.com`
font.pixelSize: Theme.fontSizeMedium
diff --git a/Modules/Settings/DankBarTab.qml b/Modules/Settings/DankBarTab.qml
index 2c3067fa..f0b97009 100644
--- a/Modules/Settings/DankBarTab.qml
+++ b/Modules/Settings/DankBarTab.qml
@@ -371,7 +371,7 @@ Item {
widgets = SettingsData.dankBarCenterWidgets.slice()
else if (sectionId === "right")
widgets = SettingsData.dankBarRightWidgets.slice()
-
+
if (widgetIndex >= 0 && widgetIndex < widgets.length) {
var widget = widgets[widgetIndex]
var widgetId = typeof widget === "string" ? widget : widget.id
@@ -401,7 +401,7 @@ Item {
}
}
}
-
+
if (sectionId === "left")
SettingsData.setDankBarLeftWidgets(widgets)
else if (sectionId === "center")
diff --git a/Modules/Settings/WidgetsTabSection.qml b/Modules/Settings/WidgetsTabSection.qml
index 5a06ddbe..a8a4a9b5 100644
--- a/Modules/Settings/WidgetsTabSection.qml
+++ b/Modules/Settings/WidgetsTabSection.qml
@@ -734,11 +734,11 @@ Column {
modal: true
focus: true
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
+
onOpened: {
console.log("Control Center context menu opened")
}
-
+
onClosed: {
console.log("Control Center context menu closed")
}
diff --git a/PLUGINS/LauncherExample/LauncherExampleLauncher.qml b/PLUGINS/LauncherExample/LauncherExampleLauncher.qml
index e44e5718..67964d2c 100644
--- a/PLUGINS/LauncherExample/LauncherExampleLauncher.qml
+++ b/PLUGINS/LauncherExample/LauncherExampleLauncher.qml
@@ -14,7 +14,7 @@ Item {
Component.onCompleted: {
console.log("LauncherExample: Plugin loaded")
-
+
// Load custom trigger from settings
if (pluginService) {
trigger = pluginService.loadPluginData("launcherExample", "trigger", "#")
@@ -119,7 +119,7 @@ Item {
function runScript(command) {
console.log("LauncherExample: Would run script:", command)
showToast("Script executed: " + command)
-
+
// In a real plugin, you might create a Process component here
// For demo purposes, we just show what would happen
}
diff --git a/Services/AppSearchService.qml b/Services/AppSearchService.qml
index 5ca9ea84..29de51c3 100644
--- a/Services/AppSearchService.qml
+++ b/Services/AppSearchService.qml
@@ -11,7 +11,7 @@ Singleton {
id: root
property var applications: DesktopEntries.applications.values.filter(app => !app.noDisplay && !app.runInTerminal)
-
+
function searchApplications(query) {
@@ -266,7 +266,7 @@ Singleton {
function getPluginCategoryIcon(category) {
if (typeof PluginService === "undefined") return null
-
+
const launchers = PluginService.getLauncherPlugins()
for (const pluginId in launchers) {
const plugin = launchers[pluginId]
@@ -296,7 +296,7 @@ Singleton {
function getPluginItems(category, query) {
if (typeof PluginService === "undefined") return []
-
+
const launchers = PluginService.getLauncherPlugins()
for (const pluginId in launchers) {
const plugin = launchers[pluginId]
@@ -338,42 +338,42 @@ Singleton {
function executePluginItem(item, pluginId) {
if (typeof PluginService === "undefined") return false
-
+
const component = PluginService.pluginLauncherComponents[pluginId]
if (!component) return false
-
+
try {
const instance = component.createObject(root, {
"pluginService": PluginService
})
-
+
if (instance && typeof instance.executeItem === "function") {
instance.executeItem(item)
instance.destroy()
return true
}
-
+
if (instance) {
instance.destroy()
}
} catch (e) {
console.warn("AppSearchService: Error executing item from plugin", pluginId, ":", e)
}
-
+
return false
}
function searchPluginItems(query) {
if (typeof PluginService === "undefined") return []
-
+
let allItems = []
const launchers = PluginService.getLauncherPlugins()
-
+
for (const pluginId in launchers) {
const items = getPluginItemsForPlugin(pluginId, query)
allItems = allItems.concat(items)
}
-
+
return allItems
}
}
diff --git a/Services/LegacyNetworkService.qml b/Services/LegacyNetworkService.qml
index db5087c0..eba2b549 100644
--- a/Services/LegacyNetworkService.qml
+++ b/Services/LegacyNetworkService.qml
@@ -21,7 +21,7 @@ Singleton {
property string ethernetConnectionUuid: ""
property var wiredConnections: []
-
+
property string wifiIP: ""
property string wifiInterface: ""
property bool wifiConnected: false
@@ -75,7 +75,7 @@ Singleton {
property string networkInfoSSID: ""
property string networkInfoDetails: ""
property bool networkInfoLoading: false
-
+
property string networkWiredInfoUUID: ""
property string networkWiredInfoDetails: ""
property bool networkWiredInfoLoading: false
@@ -158,12 +158,12 @@ Singleton {
}
return
}
-
+
if (line.includes("StateChanged") ||
line.includes("PrimaryConnectionChanged") ||
line.includes("WirelessEnabled") ||
(line.includes("ActiveConnection") && line.includes("State"))) {
-
+
if (now - nmStateMonitor.lastRefreshTime > nmStateMonitor.minRefreshInterval) {
nmStateMonitor.lastRefreshTime = now
refreshNetworkState()
diff --git a/Services/NetworkManagerService.qml b/Services/NetworkManagerService.qml
index 786e5bea..6cb6d995 100644
--- a/Services/NetworkManagerService.qml
+++ b/Services/NetworkManagerService.qml
@@ -71,7 +71,7 @@ Singleton {
property string networkInfoSSID: ""
property string networkInfoDetails: ""
property bool networkInfoLoading: false
-
+
property string networkWiredInfoUUID: ""
property string networkWiredInfoDetails: ""
property bool networkWiredInfoLoading: false
@@ -227,7 +227,7 @@ Singleton {
connectionChanged()
}
-
+
function connectToSpecificWiredConfig(uuid) {
if (!networkAvailable || isConnecting) return
@@ -446,7 +446,7 @@ Singleton {
autoScan = false
autoRefreshEnabled = false
}
-
+
function fetchWiredNetworkInfo(uuid) {
if (!networkAvailable) return
@@ -475,18 +475,18 @@ Singleton {
details += "Driver: " + info.driver + "\\n"
details += "MAC Addr: " + info.hwAddr + "\\n"
details += "Speed: " + info.speed + " Mb/s\\n\\n"
-
+
details += "IPv4 informations:\\n"
-
+
for (const ip4 of info.IPv4s.ips) {
details += " IPv4 address: " + ip4 + "\\n"
}
details += " Gateway: " + info.IPv4s.gateway + "\\n"
details += " DNS: " + info.IPv4s.dns + "\\n"
-
+
if (info.IPv6s.ips) {
details += "\\nIPv6 informations:\\n"
-
+
for (const ip6 of info.IPv6s.ips) {
details += " IPv6 address: " + ip6 + "\\n"
}
diff --git a/Services/NetworkService.qml b/Services/NetworkService.qml
index c9a6d3a4..35fb492c 100644
--- a/Services/NetworkService.qml
+++ b/Services/NetworkService.qml
@@ -59,7 +59,7 @@ Singleton {
property string networkInfoSSID: activeService?.networkInfoSSID ?? ""
property string networkInfoDetails: activeService?.networkInfoDetails ?? ""
property bool networkInfoLoading: activeService?.networkInfoLoading ?? false
-
+
property string networkWiredInfoUUID: activeService?.networkWiredInfoUUID ?? ""
property string networkWiredInfoDetails: activeService?.networkWiredInfoDetails ?? ""
property bool networkWiredInfoLoading: activeService?.networkWiredInfoLoading ?? false
@@ -252,7 +252,7 @@ Singleton {
activeService.refreshNetworkState()
}
}
-
+
function connectToSpecificWiredConfig(uuid) {
if (activeService && activeService.connectToSpecificWiredConfig) {
activeService.connectToSpecificWiredConfig(uuid)
diff --git a/Services/PluginService.qml b/Services/PluginService.qml
index 596bf145..58206c5f 100644
--- a/Services/PluginService.qml
+++ b/Services/PluginService.qml
@@ -538,7 +538,7 @@ Singleton {
// Launcher plugin helper functions
function getLauncherPlugins() {
const launchers = {}
-
+
// Check plugins that have launcher components
for (const pluginId in pluginLauncherComponents) {
const plugin = availablePlugins[pluginId]
diff --git a/Services/WallpaperCyclingService.qml b/Services/WallpaperCyclingService.qml
index 7a49ef7c..35eb81e0 100644
--- a/Services/WallpaperCyclingService.qml
+++ b/Services/WallpaperCyclingService.qml
@@ -302,7 +302,7 @@ Singleton {
function cyclePrevForMonitor(screenName) {
if (!screenName) return
-
+
var currentWallpaper = SessionData.getMonitorWallpaper(screenName)
if (currentWallpaper) {
cycleToPrevWallpaper(screenName, currentWallpaper)
@@ -370,10 +370,10 @@ Singleton {
Process {
id: cyclingProcess
-
+
property string targetScreenName: ""
property string currentWallpaper: ""
-
+
running: false
stdout: StdioCollector {
@@ -404,10 +404,10 @@ Singleton {
Process {
id: prevCyclingProcess
-
+
property string targetScreenName: ""
property string currentWallpaper: ""
-
+
running: false
stdout: StdioCollector {
diff --git a/Services/WeatherService.qml b/Services/WeatherService.qml
index 46b77a18..4f53ac0d 100644
--- a/Services/WeatherService.qml
+++ b/Services/WeatherService.qml
@@ -75,7 +75,7 @@ Singleton {
"96": "thunderstorm",
"99": "thunderstorm"
})
-
+
property var nightWeatherIcons: ({
"0": "clear_night",
"1": "clear_night",
@@ -114,7 +114,7 @@ Singleton {
const iconMap = isDay ? weatherIcons : nightWeatherIcons
return iconMap[String(code)] || "cloud"
}
-
+
function getWeatherCondition(code) {
const conditions = {
"0": "Clear",
@@ -148,10 +148,10 @@ Singleton {
}
return conditions[String(code)] || "Unknown"
}
-
+
function formatTime(isoString) {
if (!isoString) return "--"
-
+
try {
const date = new Date(isoString)
const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP"
@@ -160,15 +160,15 @@ Singleton {
return "--"
}
}
-
+
function formatForecastDay(isoString, index) {
if (!isoString) return "--"
-
+
try {
const date = new Date(isoString)
if (index === 0) return I18n.tr("Today")
if (index === 1) return I18n.tr("Tomorrow")
-
+
const locale = Qt.locale()
return locale.dayName(date.getDay(), Locale.ShortFormat)
} catch (e) {
@@ -180,7 +180,7 @@ Singleton {
if (!location) {
return null
}
-
+
const params = [
"latitude=" + location.latitude,
"longitude=" + location.longitude,
@@ -189,14 +189,14 @@ Singleton {
"timezone=auto",
"forecast_days=7"
]
-
+
if (SettingsData.useFahrenheit) {
params.push("temperature_unit=fahrenheit")
}
-
+
return "https://api.open-meteo.com/v1/forecast?" + params.join('&')
}
-
+
function getGeocodingUrl(query) {
return "https://geocoding-api.open-meteo.com/v1/search?name=" + encodeURIComponent(query) + "&count=1&language=en&format=json"
}
@@ -229,25 +229,25 @@ Singleton {
}
}
}
-
+
const cityName = SettingsData.weatherLocation
if (cityName) {
getLocationFromCity(cityName)
}
}
}
-
+
function getLocationFromCoords(lat, lon) {
const url = "https://nominatim.openstreetmap.org/reverse?lat=" + lat + "&lon=" + lon + "&format=json&addressdetails=1&accept-language=en"
reverseGeocodeFetcher.command = lowPriorityCmd.concat(curlBaseCmd).concat(["-H", "User-Agent: DankMaterialShell Weather Widget", url])
reverseGeocodeFetcher.running = true
}
-
+
function getLocationFromCity(city) {
cityGeocodeFetcher.command = lowPriorityCmd.concat(curlBaseCmd).concat([getGeocodingUrl(city)])
cityGeocodeFetcher.running = true
}
-
+
function getLocationFromIP() {
ipLocationFetcher.running = true
}
@@ -287,7 +287,7 @@ Singleton {
root.lastFetchTime = 0 // Reset throttle
fetchWeather()
}
-
+
function nextInterval() {
const jitter = Math.floor(Math.random() * 15000) - 7500
return Math.max(60000, root.updateInterval + jitter)
@@ -324,7 +324,7 @@ Singleton {
id: ipLocationFetcher
command: lowPriorityCmd.concat(curlBaseCmd).concat(["http://ipinfo.io/json"])
running: false
-
+
stdout: StdioCollector {
onStreamFinished: {
const raw = text.trim()
@@ -337,23 +337,23 @@ Singleton {
const data = JSON.parse(raw)
const coords = data.loc
const city = data.city
-
+
if (!coords || !city) {
throw new Error("Missing location data")
}
-
+
const coordsParts = coords.split(",")
if (coordsParts.length !== 2) {
throw new Error("Invalid coordinates format")
}
-
+
const lat = parseFloat(coordsParts[0])
const lon = parseFloat(coordsParts[1])
-
+
if (isNaN(lat) || isNaN(lon)) {
throw new Error("Invalid coordinate values")
}
-
+
root.location = {
city: city,
latitude: lat,
@@ -365,18 +365,18 @@ Singleton {
}
}
}
-
+
onExited: exitCode => {
if (exitCode !== 0) {
root.handleWeatherFailure()
}
}
}
-
+
Process {
id: reverseGeocodeFetcher
running: false
-
+
stdout: StdioCollector {
onStreamFinished: {
const raw = text.trim()
@@ -388,32 +388,32 @@ Singleton {
try {
const data = JSON.parse(raw)
const address = data.address || {}
-
+
root.location = {
city: address.hamlet || address.city || address.town || address.village || "Unknown",
country: address.country || "Unknown",
latitude: parseFloat(data.lat),
longitude: parseFloat(data.lon)
}
-
+
fetchWeather()
} catch (e) {
root.handleWeatherFailure()
}
}
}
-
+
onExited: exitCode => {
if (exitCode !== 0) {
root.handleWeatherFailure()
}
}
}
-
+
Process {
id: cityGeocodeFetcher
running: false
-
+
stdout: StdioCollector {
onStreamFinished: {
const raw = text.trim()
@@ -425,27 +425,27 @@ Singleton {
try {
const data = JSON.parse(raw)
const results = data.results
-
+
if (!results || results.length === 0) {
throw new Error("No results found")
}
-
+
const result = results[0]
-
+
root.location = {
city: result.name,
country: result.country,
latitude: result.latitude,
longitude: result.longitude
}
-
+
fetchWeather()
} catch (e) {
root.handleWeatherFailure()
}
}
}
-
+
onExited: exitCode => {
if (exitCode !== 0) {
root.handleWeatherFailure()
@@ -467,7 +467,7 @@ Singleton {
try {
const data = JSON.parse(raw)
-
+
if (!data.current || !data.daily) {
throw new Error("Required weather data fields missing")
}
@@ -475,12 +475,12 @@ Singleton {
const current = data.current
const daily = data.daily
const currentUnits = data.current_units || {}
-
+
const tempC = current.temperature_2m || 0
const tempF = SettingsData.useFahrenheit ? tempC : (tempC * 9/5 + 32)
const feelsLikeC = current.apparent_temperature || tempC
const feelsLikeF = SettingsData.useFahrenheit ? feelsLikeC : (feelsLikeC * 9/5 + 32)
-
+
const forecast = []
if (daily.time && daily.time.length > 0) {
for (let i = 0; i < Math.min(daily.time.length, 7); i++) {
@@ -488,7 +488,7 @@ Singleton {
const tempMaxC = daily.temperature_2m_max?.[i] || 0
const tempMinF = SettingsData.useFahrenheit ? tempMinC : (tempMinC * 9/5 + 32)
const tempMaxF = SettingsData.useFahrenheit ? tempMaxC : (tempMaxC * 9/5 + 32)
-
+
forecast.push({
"day": formatForecastDay(daily.time[i], i),
"wCode": daily.weather_code?.[i] || 0,
@@ -502,7 +502,7 @@ Singleton {
})
}
}
-
+
root.weather = {
"available": true,
"loading": false,
@@ -577,7 +577,7 @@ Singleton {
}
Component.onCompleted: {
-
+
SettingsData.weatherCoordinatesChanged.connect(() => {
root.location = null
root.weather = {
@@ -635,7 +635,7 @@ Singleton {
root.lastFetchTime = 0
root.forceRefresh()
})
-
+
SettingsData.useFahrenheitChanged.connect(() => {
root.lastFetchTime = 0
root.forceRefresh()
diff --git a/Widgets/DankAlbumArt.qml b/Widgets/DankAlbumArt.qml
index 30fcc576..9a29caa2 100644
--- a/Widgets/DankAlbumArt.qml
+++ b/Widgets/DankAlbumArt.qml
@@ -42,91 +42,91 @@ Item {
preferredRendererType: Shape.CurveRenderer
z: 0
layer.enabled: false
-
+
readonly property real centerX: width / 2
readonly property real centerY: height / 2
readonly property real baseRadius: Math.min(width, height) * 0.41 * root.animationScale
readonly property int segments: 28
-
+
property var audioLevels: {
if (!CavaService.cavaAvailable || CavaService.values.length === 0) {
return [0.5, 0.3, 0.7, 0.4, 0.6, 0.5, 0.8, 0.2, 0.9, 0.6]
}
return CavaService.values
}
-
+
property var smoothedLevels: [0.5, 0.3, 0.7, 0.4, 0.6, 0.5, 0.8, 0.2, 0.9, 0.6]
property var cubics: []
onAudioLevelsChanged: updatePath()
-
+
FrameAnimation {
running: morphingBlob.visible
onTriggered: morphingBlob.updatePath()
}
-
+
Component {
id: cubicSegment
PathCubic {}
}
-
+
Component.onCompleted: {
shapePath.pathElements.push(Qt.createQmlObject(
'import QtQuick; import QtQuick.Shapes; PathMove {}', shapePath
))
-
+
for (let i = 0; i < segments; i++) {
const seg = cubicSegment.createObject(shapePath)
shapePath.pathElements.push(seg)
cubics.push(seg)
}
-
+
updatePath()
}
-
+
function expSmooth(prev, next, alpha) {
return prev + alpha * (next - prev)
}
-
+
function updatePath() {
if (cubics.length === 0) return
-
+
for (let i = 0; i < Math.min(smoothedLevels.length, audioLevels.length); i++) {
smoothedLevels[i] = expSmooth(smoothedLevels[i], audioLevels[i], 0.35)
}
-
+
const points = []
for (let i = 0; i < segments; i++) {
const angle = (i / segments) * 2 * Math.PI
const audioIndex = i % Math.min(smoothedLevels.length, 10)
-
+
const rawLevel = smoothedLevels[audioIndex] || 0
const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0), 100) / 100) * 100
const normalizedLevel = scaledLevel / 100
const audioLevel = Math.max(0.15, normalizedLevel) * 0.5
-
+
const radius = baseRadius * (1.0 + audioLevel)
const x = centerX + Math.cos(angle) * radius
const y = centerY + Math.sin(angle) * radius
points.push({x: x, y: y})
}
-
+
const startMove = shapePath.pathElements[0]
startMove.x = points[0].x
startMove.y = points[0].y
-
+
const tension = 0.5
for (let i = 0; i < segments; i++) {
const p0 = points[(i - 1 + segments) % segments]
const p1 = points[i]
const p2 = points[(i + 1) % segments]
const p3 = points[(i + 2) % segments]
-
+
const c1x = p1.x + (p2.x - p0.x) * tension / 3
const c1y = p1.y + (p2.y - p0.y) * tension / 3
const c2x = p2.x - (p3.x - p1.x) * tension / 3
const c2y = p2.y - (p3.y - p1.y) * tension / 3
-
+
const seg = cubics[i]
seg.control1X = c1x
seg.control1Y = c1y
@@ -136,7 +136,7 @@ Item {
seg.y = p2.y
}
}
-
+
ShapePath {
id: shapePath
fillColor: Theme.primary
diff --git a/Widgets/DankTabBar.qml b/Widgets/DankTabBar.qml
index 07510352..b065a31e 100644
--- a/Widgets/DankTabBar.qml
+++ b/Widgets/DankTabBar.qml
@@ -98,10 +98,10 @@ Item {
bottomRightRadius: 0
color: Theme.primary
visible: false
-
+
property bool animationEnabled: false
property bool initialSetupComplete: false
-
+
Behavior on x {
enabled: indicator.animationEnabled
NumberAnimation {
@@ -109,7 +109,7 @@ Item {
easing.type: Theme.standardEasing
}
}
-
+
Behavior on width {
enabled: indicator.animationEnabled
NumberAnimation {
@@ -130,21 +130,21 @@ Item {
if (tabRepeater.count === 0 || currentIndex < 0 || currentIndex >= tabRepeater.count) {
return
}
-
+
const item = tabRepeater.itemAt(currentIndex)
if (!item || item.isAction) {
return
}
-
+
const tabPos = item.mapToItem(tabBar, 0, 0)
const tabCenterX = tabPos.x + item.width / 2
const indicatorWidth = 60
-
+
if (tabPos.x < 10 && currentIndex > 0) {
Qt.callLater(() => updateIndicator(enableAnimation))
return
}
-
+
indicator.animationEnabled = enableAnimation
indicator.width = indicatorWidth
indicator.x = tabCenterX - indicatorWidth / 2