summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/DankDashPopout.qml425
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/MediaDropdownOverlay.qml513
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/MediaPlayerTab.qml785
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/CalendarOverviewCard.qml539
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/Card.qml24
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/ClockCard.qml113
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/MediaOverviewCard.qml211
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/SystemMonitorCard.qml178
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/UserInfoCard.qml110
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/WeatherOverviewCard.qml94
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/OverviewTab.qml75
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WallpaperTab.qml590
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WeatherForecastCard.qml206
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WeatherTab.qml1124
14 files changed, 0 insertions, 4987 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/DankDashPopout.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/DankDashPopout.qml
deleted file mode 100644
index 34b324c..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/DankDashPopout.qml
+++ /dev/null
@@ -1,425 +0,0 @@
-import QtQuick
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-DankPopout {
- id: root
-
- layerNamespace: "dms:dash"
-
- property bool dashVisible: false
- property var triggerScreen: null
- property int currentTabIndex: 0
-
- popupWidth: SettingsData.showWeekNumber ? 736 : 700
- popupHeight: contentLoader.item ? contentLoader.item.implicitHeight : 500
- triggerWidth: 80
- screen: triggerScreen
- shouldBeVisible: dashVisible
-
- property bool __focusArmed: false
- property bool __contentReady: false
-
- property var __mediaTabRef: null
-
- property int __dropdownType: 0
- property point __dropdownAnchor: Qt.point(0, 0)
- property bool __dropdownRightEdge: false
- property var __dropdownPlayer: null
- property var __dropdownPlayers: []
-
- function __showVolumeDropdown(pos, rightEdge, player, players) {
- __dropdownAnchor = pos;
- __dropdownRightEdge = rightEdge;
- __dropdownPlayer = player;
- __dropdownPlayers = players;
- __dropdownType = 1;
- }
-
- function __showAudioDevicesDropdown(pos, rightEdge) {
- __dropdownAnchor = pos;
- __dropdownRightEdge = rightEdge;
- __dropdownType = 2;
- }
-
- function __showPlayersDropdown(pos, rightEdge, player, players) {
- __dropdownAnchor = pos;
- __dropdownRightEdge = rightEdge;
- __dropdownPlayer = player;
- __dropdownPlayers = players;
- __dropdownType = 3;
- }
-
- function __hideDropdowns() {
- __volumeCloseTimer.stop();
- __dropdownType = 0;
- __mediaTabRef?.resetDropdownStates();
- }
-
- function __startCloseTimer() {
- __volumeCloseTimer.restart();
- }
-
- function __stopCloseTimer() {
- __volumeCloseTimer.stop();
- }
-
- Timer {
- id: __volumeCloseTimer
- interval: 400
- onTriggered: {
- if (__dropdownType === 1) {
- __hideDropdowns();
- }
- }
- }
-
- overlayContent: Component {
- MediaDropdownOverlay {
- dropdownType: root.__dropdownType
- anchorPos: root.__dropdownAnchor
- isRightEdge: root.__dropdownRightEdge
- activePlayer: root.__dropdownPlayer
- allPlayers: root.__dropdownPlayers
- onCloseRequested: root.__hideDropdowns()
- onPanelEntered: root.__stopCloseTimer()
- onPanelExited: root.__startCloseTimer()
- onVolumeChanged: volume => {
- const player = root.__dropdownPlayer;
- const isChrome = player?.identity?.toLowerCase().includes("chrome") || player?.identity?.toLowerCase().includes("chromium");
- const usePlayerVolume = player && player.volumeSupported && !isChrome;
- if (usePlayerVolume) {
- player.volume = volume;
- } else if (AudioService.sink?.audio) {
- AudioService.sink.audio.volume = volume;
- }
- }
- onPlayerSelected: player => {
- const currentPlayer = MprisController.activePlayer;
- if (currentPlayer && currentPlayer !== player && currentPlayer.canPause) {
- currentPlayer.pause();
- }
- MprisController.setActivePlayer(player);
- root.__hideDropdowns();
- }
- onDeviceSelected: device => {
- root.__hideDropdowns();
- }
- }
- }
-
- function __tryFocusOnce() {
- if (!__focusArmed)
- return;
- const win = root.window;
- if (!win || !win.visible)
- return;
- if (!contentLoader.item)
- return;
- if (win.requestActivate)
- win.requestActivate();
- contentLoader.item.forceActiveFocus(Qt.TabFocusReason);
-
- if (contentLoader.item.activeFocus)
- __focusArmed = false;
- }
-
- onDashVisibleChanged: {
- if (dashVisible) {
- __focusArmed = true;
- __contentReady = !!contentLoader.item;
- open();
- __tryFocusOnce();
- } else {
- __focusArmed = false;
- __contentReady = false;
- __hideDropdowns();
- close();
- }
- }
-
- Connections {
- target: contentLoader
- function onLoaded() {
- __contentReady = true;
- if (__focusArmed)
- __tryFocusOnce();
- }
- }
-
- Connections {
- target: root.window ? root.window : null
- enabled: !!root.window
- function onVisibleChanged() {
- if (__focusArmed)
- __tryFocusOnce();
- }
- }
-
- onBackgroundClicked: {
- dashVisible = false;
- }
-
- content: Component {
- Rectangle {
- id: mainContainer
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- implicitWidth: Math.max(700, pages.implicitWidth + (Theme.spacingM * 2))
- implicitHeight: contentColumn.height + Theme.spacingM * 2
- color: "transparent"
- focus: true
-
- Component.onCompleted: {
- if (root.shouldBeVisible) {
- mainContainer.forceActiveFocus();
- }
- }
-
- Connections {
- target: root
- function onShouldBeVisibleChanged() {
- if (root.shouldBeVisible) {
- Qt.callLater(function () {
- mainContainer.forceActiveFocus();
- });
- }
- }
- }
-
- Keys.onPressed: function (event) {
- if (event.key === Qt.Key_Escape) {
- root.dashVisible = false;
- event.accepted = true;
- return;
- }
-
- if (event.key === Qt.Key_Tab && !(event.modifiers & Qt.ShiftModifier)) {
- let nextIndex = root.currentTabIndex + 1;
- while (nextIndex < tabBar.model.length && tabBar.model[nextIndex] && tabBar.model[nextIndex].isAction) {
- nextIndex++;
- }
- if (nextIndex >= tabBar.model.length) {
- nextIndex = 0;
- }
- root.currentTabIndex = nextIndex;
- event.accepted = true;
- return;
- }
-
- if (event.key === Qt.Key_Backtab || (event.key === Qt.Key_Tab && (event.modifiers & Qt.ShiftModifier))) {
- let prevIndex = root.currentTabIndex - 1;
- while (prevIndex >= 0 && tabBar.model[prevIndex] && tabBar.model[prevIndex].isAction) {
- prevIndex--;
- }
- if (prevIndex < 0) {
- prevIndex = tabBar.model.length - 1;
- while (prevIndex >= 0 && tabBar.model[prevIndex] && tabBar.model[prevIndex].isAction) {
- prevIndex--;
- }
- }
- if (prevIndex >= 0) {
- root.currentTabIndex = prevIndex;
- }
- event.accepted = true;
- return;
- }
-
- if (root.currentTabIndex === 2 && wallpaperLoader.item?.handleKeyEvent) {
- if (wallpaperLoader.item.handleKeyEvent(event)) {
- event.accepted = true;
- return;
- }
- }
- }
-
- Column {
- id: contentColumn
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.margins: Theme.spacingM
- spacing: Theme.spacingS
-
- DankTabBar {
- id: tabBar
-
- width: parent.width
- height: 48
- currentIndex: root.currentTabIndex
- spacing: Theme.spacingS
- equalWidthTabs: true
- enableArrowNavigation: false
- focus: false
- activeFocusOnTab: false
- nextFocusTarget: {
- const item = pages.currentItem;
- if (!item)
- return null;
- if (item.focusTarget)
- return item.focusTarget;
- return item;
- }
-
- model: {
- let tabs = [
- {
- "icon": "dashboard",
- "text": I18n.tr("Overview")
- },
- {
- "icon": "music_note",
- "text": I18n.tr("Media")
- },
- {
- "icon": "wallpaper",
- "text": I18n.tr("Wallpapers")
- }
- ];
-
- if (SettingsData.weatherEnabled) {
- tabs.push({
- "icon": "wb_sunny",
- "text": I18n.tr("Weather")
- });
- }
-
- tabs.push({
- "icon": "settings",
- "text": I18n.tr("Settings"),
- "isAction": true
- });
- return tabs;
- }
-
- onTabClicked: function (index) {
- root.currentTabIndex = index;
- }
-
- onActionTriggered: function (index) {
- let settingsIndex = SettingsData.weatherEnabled ? 4 : 3;
- if (index === settingsIndex) {
- dashVisible = false;
- PopoutService.focusOrToggleSettings();
- }
- }
- }
-
- Item {
- width: parent.width
- height: Theme.spacingXS
- }
-
- Item {
- id: pages
- width: parent.width
- height: implicitHeight
- implicitWidth: currentItem && currentItem.implicitWidth > 0 ? currentItem.implicitWidth : (700 - Theme.spacingM * 2)
- implicitHeight: {
- if (root.currentTabIndex === 0)
- return overviewLoader.item?.implicitHeight ?? 410;
- if (root.currentTabIndex === 1)
- return mediaLoader.item?.implicitHeight ?? 410;
- if (root.currentTabIndex === 2)
- return wallpaperLoader.item?.implicitHeight ?? 410;
- if (SettingsData.weatherEnabled && root.currentTabIndex === 3)
- return weatherLoader.item?.implicitHeight ?? 410;
- return 410;
- }
-
- readonly property var currentItem: {
- if (root.currentTabIndex === 0)
- return overviewLoader.item;
- if (root.currentTabIndex === 1)
- return mediaLoader.item;
- if (root.currentTabIndex === 2)
- return wallpaperLoader.item;
- if (root.currentTabIndex === 3)
- return weatherLoader.item;
- return null;
- }
-
- Loader {
- id: overviewLoader
- anchors.fill: parent
- active: root.currentTabIndex === 0
- visible: active
- sourceComponent: Component {
- OverviewTab {
- onCloseDash: root.dashVisible = false
- onSwitchToWeatherTab: {
- if (SettingsData.weatherEnabled) {
- root.currentTabIndex = 3;
- }
- }
- onSwitchToMediaTab: {
- root.currentTabIndex = 1;
- }
- }
- }
- }
-
- Loader {
- id: mediaLoader
- anchors.fill: parent
- active: root.currentTabIndex === 1
- visible: active
- sourceComponent: Component {
- MediaPlayerTab {
- targetScreen: root.screen
- popoutX: root.alignedX
- popoutY: root.alignedY
- popoutWidth: root.alignedWidth
- popoutHeight: root.alignedHeight
- contentOffsetY: Theme.spacingM + 48 + Theme.spacingS + Theme.spacingXS
- section: root.triggerSection
- barPosition: root.effectiveBarPosition
- Component.onCompleted: root.__mediaTabRef = this
- onShowVolumeDropdown: (pos, screen, rightEdge, player, players) => {
- root.__showVolumeDropdown(pos, rightEdge, player, players);
- }
- onShowAudioDevicesDropdown: (pos, screen, rightEdge) => {
- root.__showAudioDevicesDropdown(pos, rightEdge);
- }
- onShowPlayersDropdown: (pos, screen, rightEdge, player, players) => {
- root.__showPlayersDropdown(pos, rightEdge, player, players);
- }
- onHideDropdowns: root.__hideDropdowns()
- onVolumeButtonExited: root.__startCloseTimer()
- }
- }
- }
-
- Loader {
- id: wallpaperLoader
- anchors.fill: parent
- active: root.currentTabIndex === 2
- visible: active
- sourceComponent: Component {
- WallpaperTab {
- active: true
- tabBarItem: tabBar
- keyForwardTarget: mainContainer
- targetScreen: root.screen
- parentPopout: root
- }
- }
- }
-
- Loader {
- id: weatherLoader
- anchors.fill: parent
- active: SettingsData.weatherEnabled && root.currentTabIndex === 3
- visible: active
- sourceComponent: Component {
- WeatherTab {}
- }
- }
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/MediaDropdownOverlay.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/MediaDropdownOverlay.qml
deleted file mode 100644
index 35dfe97..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/MediaDropdownOverlay.qml
+++ /dev/null
@@ -1,513 +0,0 @@
-import QtQuick
-import QtQuick.Effects
-import Quickshell.Services.Pipewire
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Item {
- id: root
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- property int dropdownType: 0
- property var activePlayer: null
- property var allPlayers: []
- property point anchorPos: Qt.point(0, 0)
- property bool isRightEdge: false
-
- property bool __isChromeBrowser: {
- if (!activePlayer?.identity)
- return false;
- const id = activePlayer.identity.toLowerCase();
- return id.includes("chrome") || id.includes("chromium");
- }
- property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser
- property real currentVolume: usePlayerVolume ? activePlayer.volume : (AudioService.sink?.audio?.volume ?? 0)
- property bool volumeAvailable: (activePlayer && activePlayer.volumeSupported && !__isChromeBrowser) || (AudioService.sink && AudioService.sink.audio)
- property var availableDevices: {
- const hidden = SessionData.hiddenOutputDeviceNames ?? [];
- return Pipewire.nodes.values.filter(node => {
- if (!node.audio || !node.isSink || node.isStream)
- return false;
- return !hidden.includes(node.name);
- });
- }
-
- signal closeRequested
- signal deviceSelected(var device)
- signal playerSelected(var player)
- signal volumeChanged(real volume)
- signal panelEntered
- signal panelExited
-
- property int __volumeHoverCount: 0
-
- function volumeAreaEntered() {
- __volumeHoverCount++;
- panelEntered();
- }
-
- function volumeAreaExited() {
- __volumeHoverCount--;
- Qt.callLater(() => {
- if (__volumeHoverCount <= 0)
- panelExited();
- });
- }
-
- Rectangle {
- id: volumePanel
- visible: dropdownType === 1 && volumeAvailable
- width: 60
- height: 180
- x: isRightEdge ? anchorPos.x : anchorPos.x - width
- y: anchorPos.y - height / 2
- radius: Theme.cornerRadius * 2
- color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.95)
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
- border.width: 1
-
- opacity: dropdownType === 1 ? 1 : 0
- scale: dropdownType === 1 ? 1 : 0.96
- transformOrigin: isRightEdge ? Item.Left : Item.Right
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.expressiveDurations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Theme.expressiveCurves.expressiveDefaultSpatial
- }
- }
-
- Behavior on scale {
- NumberAnimation {
- duration: Theme.expressiveDurations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Theme.expressiveCurves.expressiveDefaultSpatial
- }
- }
-
- ElevationShadow {
- id: volumeShadowLayer
- anchors.fill: parent
- z: -1
- level: Theme.elevationLevel2
- fallbackOffset: 4
- targetRadius: volumePanel.radius
- targetColor: volumePanel.color
- borderColor: volumePanel.border.color
- borderWidth: volumePanel.border.width
- shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
- shadowEnabled: Theme.elevationEnabled
- }
-
- MouseArea {
- anchors.fill: parent
- anchors.margins: -12
- hoverEnabled: true
- onEntered: volumeAreaEntered()
- onExited: volumeAreaExited()
- }
-
- Item {
- anchors.fill: parent
- anchors.margins: Theme.spacingS
-
- Item {
- id: volumeSlider
- width: parent.width * 0.5
- height: parent.height - Theme.spacingXL * 2
- anchors.top: parent.top
- anchors.topMargin: Theme.spacingS
- anchors.horizontalCenter: parent.horizontalCenter
-
- Rectangle {
- width: parent.width
- height: parent.height
- anchors.centerIn: parent
- color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- radius: Theme.cornerRadius
- }
-
- Rectangle {
- width: parent.width
- height: volumeAvailable ? (Math.min(1.0, currentVolume) * parent.height) : 0
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- color: Theme.primary
- bottomLeftRadius: Theme.cornerRadius
- bottomRightRadius: Theme.cornerRadius
- }
-
- Rectangle {
- width: parent.width + 8
- height: 8
- radius: Theme.cornerRadius
- y: {
- const ratio = volumeAvailable ? Math.min(1.0, currentVolume) : 0;
- const travel = parent.height - height;
- return Math.max(0, Math.min(travel, travel * (1 - ratio)));
- }
- anchors.horizontalCenter: parent.horizontalCenter
- color: Theme.primary
- border.width: 3
- border.color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1.0)
- }
-
- MouseArea {
- anchors.fill: parent
- anchors.margins: -12
- enabled: volumeAvailable
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- preventStealing: true
-
- onEntered: volumeAreaEntered()
- onExited: volumeAreaExited()
- onPressed: mouse => updateVolume(mouse)
- onPositionChanged: mouse => {
- if (pressed)
- updateVolume(mouse);
- }
- onClicked: mouse => updateVolume(mouse)
-
- function updateVolume(mouse) {
- if (!volumeAvailable)
- return;
- const ratio = 1.0 - (mouse.y / height);
- const volume = Math.max(0, Math.min(1, ratio));
- root.volumeChanged(volume);
- }
- }
- }
-
- StyledText {
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottomMargin: Theme.spacingL
- text: volumeAvailable ? Math.round(currentVolume * 100) + "%" : "0%"
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- font.weight: Font.Medium
- }
- }
- }
-
- Rectangle {
- id: audioDevicesPanel
- visible: dropdownType === 2
- width: 280
- height: Math.max(200, Math.min(280, availableDevices.length * 50 + 100))
- x: isRightEdge ? anchorPos.x : anchorPos.x - width
- y: anchorPos.y - height / 2
- radius: Theme.cornerRadius * 2
- color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.98)
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.6)
- border.width: 2
-
- opacity: dropdownType === 2 ? 1 : 0
- scale: dropdownType === 2 ? 1 : 0.96
- transformOrigin: isRightEdge ? Item.Left : Item.Right
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.expressiveDurations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Theme.expressiveCurves.expressiveDefaultSpatial
- }
- }
-
- Behavior on scale {
- NumberAnimation {
- duration: Theme.expressiveDurations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Theme.expressiveCurves.expressiveDefaultSpatial
- }
- }
-
- ElevationShadow {
- id: audioDevicesShadowLayer
- anchors.fill: parent
- z: -1
- level: Theme.elevationLevel2
- fallbackOffset: 4
- targetRadius: audioDevicesPanel.radius
- targetColor: audioDevicesPanel.color
- borderColor: audioDevicesPanel.border.color
- borderWidth: audioDevicesPanel.border.width
- shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
- shadowEnabled: Theme.elevationEnabled
- }
-
- Column {
- anchors.fill: parent
- anchors.margins: Theme.spacingM
-
- StyledText {
- text: I18n.tr("Audio Output Devices (") + availableDevices.length + ")"
- font.pixelSize: Theme.fontSizeMedium
- font.weight: Font.Medium
- color: Theme.surfaceText
- width: parent.width
- 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: availableDevices
- delegate: Rectangle {
- required property var modelData
- required property int index
-
- width: parent.width
- height: 48
- radius: Theme.cornerRadius
- color: deviceMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- 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
-
- function getAudioDeviceIcon(device) {
- if (!device?.name)
- return "speaker";
- const name = device.name.toLowerCase();
- if (name.includes("bluez") || name.includes("bluetooth"))
- return "headset";
- if (name.includes("hdmi"))
- return "tv";
- if (name.includes("usb"))
- return "headset";
- return "speaker";
- }
- }
-
- Column {
- anchors.verticalCenter: parent.verticalCenter
- width: parent.width - 20 - Theme.spacingM * 2
-
- StyledText {
- text: AudioService.displayName(modelData)
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.surfaceText
- font.weight: modelData === AudioService.sink ? Font.Medium : Font.Normal
- elide: Text.ElideRight
- wrapMode: Text.NoWrap
- width: parent.width
- }
-
- StyledText {
- text: modelData === AudioService.sink ? "Active" : "Available"
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceVariantText
- elide: Text.ElideRight
- width: parent.width
- }
- }
- }
-
- MouseArea {
- id: deviceMouseArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (modelData) {
- Pipewire.preferredDefaultAudioSink = modelData;
- root.deviceSelected(modelData);
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- Rectangle {
- id: playersPanel
- visible: dropdownType === 3
- width: 240
- height: Math.max(180, Math.min(240, (allPlayers?.length || 0) * 50 + 80))
- x: isRightEdge ? anchorPos.x : anchorPos.x - width
- y: anchorPos.y - height / 2
- radius: Theme.cornerRadius * 2
- color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.98)
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.6)
- border.width: 2
-
- opacity: dropdownType === 3 ? 1 : 0
- scale: dropdownType === 3 ? 1 : 0.96
- transformOrigin: isRightEdge ? Item.Left : Item.Right
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.expressiveDurations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Theme.expressiveCurves.expressiveDefaultSpatial
- }
- }
-
- Behavior on scale {
- NumberAnimation {
- duration: Theme.expressiveDurations.expressiveDefaultSpatial
- easing.type: Easing.BezierSpline
- easing.bezierCurve: Theme.expressiveCurves.expressiveDefaultSpatial
- }
- }
-
- ElevationShadow {
- id: playersShadowLayer
- anchors.fill: parent
- z: -1
- level: Theme.elevationLevel2
- fallbackOffset: 4
- targetRadius: playersPanel.radius
- targetColor: playersPanel.color
- borderColor: playersPanel.border.color
- borderWidth: playersPanel.border.width
- shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
- shadowEnabled: Theme.elevationEnabled
- }
-
- Column {
- anchors.fill: parent
- anchors.margins: Theme.spacingM
-
- StyledText {
- text: I18n.tr("Media Players (") + (allPlayers?.length || 0) + ")"
- font.pixelSize: Theme.fontSizeMedium
- font.weight: Font.Medium
- color: Theme.surfaceText
- width: parent.width
- horizontalAlignment: Text.AlignHCenter
- bottomPadding: Theme.spacingM
- }
-
- DankFlickable {
- width: parent.width
- height: parent.height - 40
- contentHeight: playerColumn.height
- clip: true
-
- Column {
- id: playerColumn
- width: parent.width
- spacing: Theme.spacingS
-
- Repeater {
- model: allPlayers || []
- delegate: Rectangle {
- required property var modelData
- required property int index
-
- width: parent.width
- height: 48
- radius: Theme.cornerRadius
- color: playerMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- border.color: modelData === activePlayer ? Theme.primary : Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
- border.width: modelData === activePlayer ? 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: "music_note"
- size: 20
- color: modelData === activePlayer ? Theme.primary : Theme.surfaceText
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Column {
- anchors.verticalCenter: parent.verticalCenter
- width: parent.width - 20 - Theme.spacingM * 2
-
- StyledText {
- text: {
- if (!modelData)
- return "Unknown Player";
- const identity = modelData.identity || "Unknown Player";
- const trackTitle = modelData.trackTitle || "";
- return trackTitle.length > 0 ? identity + " - " + trackTitle : identity;
- }
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.surfaceText
- font.weight: modelData === activePlayer ? Font.Medium : Font.Normal
- elide: Text.ElideRight
- wrapMode: Text.NoWrap
- width: parent.width
- }
-
- StyledText {
- text: {
- if (!modelData)
- return "";
- const artist = modelData.trackArtist || "";
- const isActive = modelData === activePlayer;
- if (artist.length > 0)
- return artist + (isActive ? " (Active)" : "");
- return isActive ? "Active" : "Available";
- }
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceVariantText
- elide: Text.ElideRight
- wrapMode: Text.NoWrap
- width: parent.width
- }
- }
- }
-
- MouseArea {
- id: playerMouseArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (modelData?.identity) {
- root.playerSelected(modelData);
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- MouseArea {
- anchors.fill: parent
- z: -1
- enabled: dropdownType !== 0
- onClicked: closeRequested()
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/MediaPlayerTab.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/MediaPlayerTab.qml
deleted file mode 100644
index c6d7bfc..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/MediaPlayerTab.qml
+++ /dev/null
@@ -1,785 +0,0 @@
-import QtQuick
-import QtQuick.Effects
-import QtQuick.Layouts
-import Quickshell.Services.Mpris
-import Quickshell.Io
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Item {
- id: root
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- property MprisPlayer activePlayer: MprisController.activePlayer
- property var allPlayers: MprisController.availablePlayers
- property var targetScreen: null
- property real popoutX: 0
- property real popoutY: 0
- property real popoutWidth: 0
- property real popoutHeight: 0
- property real contentOffsetY: 0
- property string section: ""
- property int barPosition: SettingsData.Position.Top
-
- signal showVolumeDropdown(point pos, var screen, bool rightEdge, var player, var players)
- signal showAudioDevicesDropdown(point pos, var screen, bool rightEdge)
- signal showPlayersDropdown(point pos, var screen, bool rightEdge, var player, var players)
- signal hideDropdowns
- signal volumeButtonExited
-
- property bool volumeExpanded: false
- property bool devicesExpanded: false
- property bool playersExpanded: false
-
- function resetDropdownStates() {
- volumeExpanded = false;
- devicesExpanded = false;
- playersExpanded = false;
- }
-
- DankTooltipV2 {
- id: sharedTooltip
- }
-
- readonly property bool isRightEdge: {
- if (barPosition === SettingsData.Position.Right)
- return true;
- if (barPosition === SettingsData.Position.Left)
- return false;
- return section === "right";
- }
- readonly property bool __isChromeBrowser: {
- if (!activePlayer?.identity)
- return false;
- const id = activePlayer.identity.toLowerCase();
- return id.includes("chrome") || id.includes("chromium");
- }
- readonly property bool volumeAvailable: (activePlayer && activePlayer.volumeSupported && !__isChromeBrowser) || (AudioService.sink && AudioService.sink.audio)
- readonly property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser
- readonly property real currentVolume: usePlayerVolume ? activePlayer.volume : (AudioService.sink?.audio?.volume ?? 0)
-
- property bool isSwitching: false
-
- // Derived "no players" state: always correct, no timers.
- readonly property int _playerCount: allPlayers ? allPlayers.length : 0
- readonly property bool _noneAvailable: _playerCount === 0
- readonly property bool _trulyIdle: activePlayer && activePlayer.playbackState === MprisPlaybackState.Stopped && !activePlayer.trackTitle && !activePlayer.trackArtist
- readonly property bool showNoPlayerNow: (!_switchHold) && (_noneAvailable || _trulyIdle)
-
- property bool _switchHold: false
- Timer {
- id: _switchHoldTimer
- interval: 650
- repeat: false
- onTriggered: _switchHold = false
- }
-
- onActivePlayerChanged: {
- if (!activePlayer) {
- isSwitching = false;
- _switchHold = false;
- return;
- }
- isSwitching = true;
- _switchHold = true;
- _switchHoldTimer.restart();
- TrackArtService.loadArtwork(activePlayer.trackArtUrl);
- }
-
- function maybeFinishSwitch() {
- if (activePlayer && activePlayer.trackTitle !== "") {
- isSwitching = false;
- _switchHold = false;
- }
- }
-
- readonly property real ratio: {
- if (!activePlayer || !activePlayer.length || activePlayer.length <= 0) {
- return 0;
- }
- const pos = (activePlayer.position || 0) % Math.max(1, activePlayer.length);
- const calculatedRatio = pos / activePlayer.length;
- return Math.max(0, Math.min(1, calculatedRatio));
- }
-
- implicitWidth: SettingsData.showWeekNumber ? 736 : 700
- implicitHeight: playerContent.height + playerContent.anchors.topMargin * 2
-
- Connections {
- target: activePlayer
- function onTrackTitleChanged() {
- _switchHoldTimer.restart();
- maybeFinishSwitch();
- }
- function onTrackArtUrlChanged() {
- TrackArtService.loadArtwork(activePlayer.trackArtUrl);
- }
- }
-
- Connections {
- target: MprisController
- function onAvailablePlayersChanged() {
- const count = (MprisController.availablePlayers?.length || 0);
- if (count === 0) {
- isSwitching = false;
- _switchHold = false;
- } else {
- _switchHold = true;
- _switchHoldTimer.restart();
- }
- }
- }
-
- 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"))
- return "tv";
- if (name.includes("usb"))
- return "headset";
- if (name.includes("analog") || name.includes("built-in"))
- return "speaker";
-
- return "speaker";
- }
-
- function getVolumeIcon() {
- if (!volumeAvailable)
- return "volume_off";
-
- const volume = currentVolume;
-
- if (usePlayerVolume) {
- if (volume === 0.0)
- return "music_off";
- return "music_note";
- }
-
- if (volume === 0.0)
- return "volume_off";
- if (volume <= 0.33)
- return "volume_down";
- if (volume <= 0.66)
- return "volume_up";
- return "volume_up";
- }
-
- function adjustVolume(step) {
- if (!volumeAvailable)
- return;
- const maxVol = usePlayerVolume ? 100 : AudioService.sinkMaxVolume;
- const current = Math.round(currentVolume * 100);
- const newVolume = Math.min(maxVol, Math.max(0, current + step));
-
- SessionData.suppressOSDTemporarily();
- if (usePlayerVolume) {
- activePlayer.volume = newVolume / 100;
- } else if (AudioService.sink?.audio) {
- AudioService.sink.audio.volume = newVolume / 100;
- }
- }
-
- property bool isSeeking: false
-
- Timer {
- interval: 1000
- running: activePlayer?.playbackState === MprisPlaybackState.Playing && !isSeeking
- repeat: true
- onTriggered: activePlayer?.positionChanged()
- }
-
- Item {
- id: bgContainer
- anchors.fill: parent
- visible: TrackArtService._bgArtSource !== ""
-
- Image {
- id: bgImage
- anchors.centerIn: parent
- width: Math.max(parent.width, parent.height) * 1.1
- height: width
- source: TrackArtService._bgArtSource
- fillMode: Image.PreserveAspectCrop
- asynchronous: true
- cache: true
- visible: false
- onStatusChanged: {
- if (status === Image.Ready)
- maybeFinishSwitch();
- }
- }
-
- Item {
- id: blurredBg
- anchors.fill: parent
- visible: false
-
- MultiEffect {
- anchors.centerIn: parent
- width: bgImage.width
- height: bgImage.height
- source: bgImage
- blurEnabled: true
- blurMax: 64
- blur: 0.8
- saturation: -0.2
- brightness: -0.25
- }
- }
-
- Rectangle {
- id: bgMask
- anchors.fill: parent
- radius: Theme.cornerRadius
- visible: false
- layer.enabled: true
- }
-
- MultiEffect {
- anchors.fill: parent
- source: blurredBg
- maskEnabled: true
- maskSource: bgMask
- maskThresholdMin: 0.5
- maskSpreadAtMin: 1.0
- opacity: 0.7
- }
-
- Rectangle {
- anchors.fill: parent
- radius: Theme.cornerRadius
- color: Theme.surface
- opacity: 0.3
- }
- }
-
- Column {
- anchors.centerIn: parent
- spacing: Theme.spacingM
- visible: showNoPlayerNow
-
- DankIcon {
- name: "music_note"
- size: Theme.iconSize * 3
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- StyledText {
- text: I18n.tr("No Active Players")
- font.pixelSize: Theme.fontSizeLarge
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
- anchors.horizontalCenter: parent.horizontalCenter
- }
- }
-
- Item {
- anchors.fill: parent
- clip: false
- visible: !_noneAvailable && (!showNoPlayerNow)
- ColumnLayout {
- id: playerContent
- width: 484
- height: 370
- spacing: Theme.spacingXS
- anchors.top: parent.top
- anchors.topMargin: 20
- anchors.horizontalCenter: parent.horizontalCenter
-
- Item {
- width: parent.width
- height: 200
- clip: false
-
- DankAlbumArt {
- width: Math.min(parent.width * 0.8, parent.height * 0.9)
- height: width
- anchors.centerIn: parent
- activePlayer: root.activePlayer
- }
- }
-
- // Song Info and Controls Section
- Item {
- width: parent.width
- Layout.fillHeight: true
-
- Column {
- id: songInfo
- width: parent.width
- spacing: Theme.spacingXS
- anchors.top: parent.top
- anchors.horizontalCenter: parent.horizontalCenter
-
- StyledText {
- text: activePlayer?.trackTitle || I18n.tr("Unknown Track")
- font.pixelSize: Theme.fontSizeLarge
- font.weight: Font.Bold
- color: Theme.surfaceText
- width: parent.width
- horizontalAlignment: Text.AlignHCenter
- elide: Text.ElideRight
- wrapMode: Text.WordWrap
- maximumLineCount: 2
- }
-
- StyledText {
- text: activePlayer?.trackTitle || I18n.tr("Unknown Artist")
- font.pixelSize: Theme.fontSizeMedium
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
- width: parent.width
- horizontalAlignment: Text.AlignHCenter
- elide: Text.ElideRight
- wrapMode: Text.WordWrap
- maximumLineCount: 1
- }
-
- StyledText {
- text: activePlayer?.trackAlbum || ""
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
- width: parent.width
- horizontalAlignment: Text.AlignHCenter
- elide: Text.ElideRight
- wrapMode: Text.WordWrap
- maximumLineCount: 1
- visible: text.length > 0
- }
- }
-
- Item {
- id: seekbarContainer
- width: parent.width
- anchors.top: songInfo.bottom
- anchors.bottom: playbackControls.top
- anchors.horizontalCenter: parent.horizontalCenter
-
- Column {
- width: parent.width
- spacing: 2
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
- anchors.verticalCenterOffset: parent.height * 0.2
-
- DankSeekbar {
- width: parent.width * 0.8
- height: 20
- anchors.horizontalCenter: parent.horizontalCenter
- activePlayer: root.activePlayer
- isSeeking: root.isSeeking
- onIsSeekingChanged: root.isSeeking = isSeeking
- }
-
- Item {
- width: parent.width * 0.8
- height: 16
- anchors.horizontalCenter: parent.horizontalCenter
-
- StyledText {
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- text: {
- if (!activePlayer)
- return "0:00";
- const rawPos = Math.max(0, activePlayer.position || 0);
- const pos = activePlayer.length ? rawPos % Math.max(1, activePlayer.length) : rawPos;
- const minutes = Math.floor(pos / 60);
- const seconds = Math.floor(pos % 60);
- const timeStr = minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
- return timeStr;
- }
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceVariantText
- }
-
- StyledText {
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- text: {
- if (!activePlayer || !activePlayer.length)
- return "0:00";
- const dur = Math.max(0, activePlayer.length || 0);
- const minutes = Math.floor(dur / 60);
- const seconds = Math.floor(dur % 60);
- return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
- }
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceVariantText
- }
- }
- }
- }
-
- Item {
- id: playbackControls
- width: parent.width
- height: 50
- anchors.bottom: parent.bottom
-
- Row {
- anchors.centerIn: parent
- spacing: Theme.spacingM
- height: parent.height
-
- Item {
- width: 50
- height: 50
- anchors.verticalCenter: parent.verticalCenter
- visible: activePlayer && activePlayer.shuffleSupported
-
- Rectangle {
- width: 40
- height: 40
- radius: 20
- anchors.centerIn: parent
- color: shuffleArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "shuffle"
- size: 20
- color: activePlayer && activePlayer.shuffle ? Theme.primary : Theme.surfaceText
- }
-
- MouseArea {
- id: shuffleArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (activePlayer && activePlayer.canControl && activePlayer.shuffleSupported) {
- activePlayer.shuffle = !activePlayer.shuffle;
- }
- }
- }
- }
- }
-
- Item {
- width: 50
- height: 50
- anchors.verticalCenter: parent.verticalCenter
-
- Rectangle {
- width: 40
- height: 40
- radius: 20
- anchors.centerIn: parent
- color: prevBtnArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "skip_previous"
- size: 24
- color: Theme.surfaceText
- }
-
- MouseArea {
- id: prevBtnArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: MprisController.previousOrRewind()
- }
- }
- }
-
- Item {
- width: 50
- height: 50
- anchors.verticalCenter: parent.verticalCenter
-
- Rectangle {
- width: 50
- height: 50
- radius: 25
- anchors.centerIn: parent
- color: Theme.primary
-
- DankIcon {
- anchors.centerIn: parent
- name: activePlayer && activePlayer.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow"
- size: 28
- color: Theme.background
- weight: 500
- }
-
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: activePlayer && activePlayer.togglePlaying()
- }
-
- ElevationShadow {
- anchors.fill: parent
- z: -1
- level: Theme.elevationLevel1
- fallbackOffset: 1
- targetRadius: parent.radius
- targetColor: parent.color
- shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
- shadowEnabled: Theme.elevationEnabled
- }
- }
- }
-
- Item {
- width: 50
- height: 50
- anchors.verticalCenter: parent.verticalCenter
-
- Rectangle {
- width: 40
- height: 40
- radius: 20
- anchors.centerIn: parent
- color: nextBtnArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "skip_next"
- size: 24
- color: Theme.surfaceText
- }
-
- MouseArea {
- id: nextBtnArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: activePlayer && activePlayer.next()
- }
- }
- }
-
- Item {
- width: 50
- height: 50
- anchors.verticalCenter: parent.verticalCenter
- visible: activePlayer && activePlayer.loopSupported
-
- Rectangle {
- width: 40
- height: 40
- radius: 20
- anchors.centerIn: parent
- color: repeatArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: {
- if (!activePlayer)
- return "repeat";
- switch (activePlayer.loopState) {
- case MprisLoopState.Track:
- return "repeat_one";
- case MprisLoopState.Playlist:
- return "repeat";
- default:
- return "repeat";
- }
- }
- size: 20
- color: activePlayer && activePlayer.loopState !== MprisLoopState.None ? Theme.primary : Theme.surfaceText
- }
-
- MouseArea {
- id: repeatArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (activePlayer && activePlayer.canControl && activePlayer.loopSupported) {
- switch (activePlayer.loopState) {
- case MprisLoopState.None:
- activePlayer.loopState = MprisLoopState.Playlist;
- break;
- case MprisLoopState.Playlist:
- activePlayer.loopState = MprisLoopState.Track;
- break;
- case MprisLoopState.Track:
- activePlayer.loopState = MprisLoopState.None;
- break;
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
- }
-
- Rectangle {
- id: playerSelectorButton
- width: 40
- height: 40
- radius: 20
- x: isRightEdge ? Theme.spacingM : parent.width - 40 - Theme.spacingM
- y: 185
- color: playerSelectorArea.containsMouse || playersExpanded ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) : "transparent"
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
- border.width: 1
- z: 100
- visible: (allPlayers?.length || 0) >= 1
-
- DankIcon {
- anchors.centerIn: parent
- name: "assistant_device"
- size: 18
- color: Theme.surfaceText
- }
-
- MouseArea {
- id: playerSelectorArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (playersExpanded) {
- hideDropdowns();
- return;
- }
- hideDropdowns();
- playersExpanded = true;
- const buttonsOnRight = !isRightEdge;
- const btnY = playerSelectorButton.y + playerSelectorButton.height / 2;
- const screenX = buttonsOnRight ? (popoutX + popoutWidth) : popoutX;
- const screenY = popoutY + contentOffsetY + btnY;
- showPlayersDropdown(Qt.point(screenX, screenY), targetScreen, buttonsOnRight, activePlayer, allPlayers);
- }
- onEntered: sharedTooltip.show(I18n.tr("Media Players"), playerSelectorButton, 0, 0, isRightEdge ? "right" : "left")
- onExited: sharedTooltip.hide()
- }
- }
-
- Rectangle {
- id: volumeButton
- width: 40
- height: 40
- radius: 20
- x: isRightEdge ? Theme.spacingM : parent.width - 40 - Theme.spacingM
- y: 130
- color: volumeButtonArea.containsMouse && volumeAvailable || volumeExpanded ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) : "transparent"
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, volumeAvailable ? 0.3 : 0.15)
- border.width: 1
- z: 101
- enabled: volumeAvailable
-
- property real previousVolume: 0.0
-
- DankIcon {
- anchors.centerIn: parent
- name: getVolumeIcon()
- size: 18
- color: volumeAvailable && currentVolume > 0 ? Theme.primary : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, volumeAvailable ? 1.0 : 0.5)
- }
-
- MouseArea {
- id: volumeButtonArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onEntered: {
- if (volumeExpanded)
- return;
- hideDropdowns();
- volumeExpanded = true;
- const buttonsOnRight = !isRightEdge;
- const btnY = volumeButton.y + volumeButton.height / 2;
- const screenX = buttonsOnRight ? (popoutX + popoutWidth) : popoutX;
- const screenY = popoutY + contentOffsetY + btnY;
- showVolumeDropdown(Qt.point(screenX, screenY), targetScreen, buttonsOnRight, activePlayer, allPlayers);
- }
- onExited: {
- if (volumeExpanded)
- volumeButtonExited();
- }
- onClicked: {
- SessionData.suppressOSDTemporarily();
- if (currentVolume > 0) {
- volumeButton.previousVolume = currentVolume;
- if (usePlayerVolume) {
- activePlayer.volume = 0;
- } else if (AudioService.sink?.audio) {
- AudioService.sink.audio.volume = 0;
- }
- } else {
- const restoreVolume = volumeButton.previousVolume > 0 ? volumeButton.previousVolume : 0.5;
- if (usePlayerVolume) {
- activePlayer.volume = restoreVolume;
- } else if (AudioService.sink?.audio) {
- AudioService.sink.audio.volume = restoreVolume;
- }
- }
- }
- onWheel: wheelEvent => {
- SessionData.suppressOSDTemporarily();
- const delta = wheelEvent.angleDelta.y;
- const current = (currentVolume * 100) || 0;
- const maxVol = usePlayerVolume ? 100 : AudioService.sinkMaxVolume;
- const newVolume = delta > 0 ? Math.min(maxVol, current + 5) : Math.max(0, current - 5);
-
- if (usePlayerVolume) {
- activePlayer.volume = newVolume / 100;
- } else if (AudioService.sink?.audio) {
- AudioService.sink.audio.volume = newVolume / 100;
- }
- wheelEvent.accepted = true;
- }
- }
- }
-
- Rectangle {
- id: audioDevicesButton
- width: 40
- height: 40
- radius: 20
- x: isRightEdge ? Theme.spacingM : parent.width - 40 - Theme.spacingM
- y: 240
- color: audioDevicesArea.containsMouse || devicesExpanded ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) : "transparent"
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.3)
- border.width: 1
- z: 100
-
- DankIcon {
- anchors.centerIn: parent
- name: devicesExpanded ? "expand_less" : "speaker"
- size: 18
- color: Theme.surfaceText
- }
-
- MouseArea {
- id: audioDevicesArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (devicesExpanded) {
- hideDropdowns();
- return;
- }
- hideDropdowns();
- devicesExpanded = true;
- const buttonsOnRight = !isRightEdge;
- const btnY = audioDevicesButton.y + audioDevicesButton.height / 2;
- const screenX = buttonsOnRight ? (popoutX + popoutWidth) : popoutX;
- const screenY = popoutY + contentOffsetY + btnY;
- showAudioDevicesDropdown(Qt.point(screenX, screenY), targetScreen, buttonsOnRight);
- }
- onEntered: sharedTooltip.show(I18n.tr("Output Device"), audioDevicesButton, 0, 0, isRightEdge ? "right" : "left")
- onExited: sharedTooltip.hide()
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/CalendarOverviewCard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/CalendarOverviewCard.qml
deleted file mode 100644
index 1972f06..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/CalendarOverviewCard.qml
+++ /dev/null
@@ -1,539 +0,0 @@
-import QtQuick
-import Quickshell
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Rectangle {
- id: root
-
- implicitWidth: SettingsData.showWeekNumber ? 736 : 700
-
- property bool showEventDetails: false
- property date selectedDate: systemClock.date
- property var selectedDateEvents: []
- property bool hasEvents: selectedDateEvents && selectedDateEvents.length > 0
-
- signal closeDash
-
- function weekStartQt() {
- if (SettingsData.firstDayOfWeek >= 7 || SettingsData.firstDayOfWeek < 0) {
- return Qt.locale().firstDayOfWeek;
- }
- return SettingsData.firstDayOfWeek;
- }
-
- function weekStartJs() {
- return weekStartQt() % 7;
- }
-
- function startOfWeek(dateObj) {
- const d = new Date(dateObj);
- const jsDow = d.getDay();
- const diff = (jsDow - weekStartJs() + 7) % 7;
- d.setDate(d.getDate() - diff);
- return d;
- }
-
- function endOfWeek(dateObj) {
- const d = new Date(dateObj);
- const jsDow = d.getDay();
- const add = (weekStartJs() + 6 - jsDow + 7) % 7;
- d.setDate(d.getDate() + add);
- return d;
- }
-
- function getWeekNumber(dateObj) {
- // Set time to noon to avoid potential Daylight Saving Time related bugs
- const weekStartDay = startOfWeek(dateObj);
- weekStartDay.setHours(12, 0, 0, 0);
-
- let week1Start;
-
- if (weekStartJs() === 1) {
- // ISO 8601 Standard, week start on Monday
- // A week belongs to the year its Thursday falls in
- // So we have to get the yearTarget from weekStartDay instead of dateObj
- let yearTarget = weekStartDay;
- yearTarget.setDate(yearTarget.getDate() + 3); // Monday + 3 = Thursday
-
- // Week 1 is the week containing Jan 4th
- const jan4 = new Date(yearTarget.getFullYear(), 0, 4);
- week1Start = startOfWeek(jan4);
- } else {
- // Traditional / US Standard, week start on Sunday
- // A week belongs to the year its Sunday falls in
- let yearTarget = weekStartDay;
- yearTarget.setDate(yearTarget.getDate() + 6); // Monday + 6 = Sunday
-
- // Week 1 is the week containing Jan 1st
- const jan1 = new Date(yearTarget.getFullYear(), 0, 1);
- week1Start = startOfWeek(jan1);
- }
-
- week1Start.setHours(12, 0, 0, 0);
-
- const diffDays = Math.round((weekStartDay.getTime() - week1Start.getTime()) / 86400000); // Number of miliseconds in a day
- return Math.floor(diffDays / 7) + 1;
- }
-
- function updateSelectedDateEvents() {
- if (CalendarService && CalendarService.khalAvailable) {
- const events = CalendarService.getEventsForDate(selectedDate);
- selectedDateEvents = events;
- } else {
- selectedDateEvents = [];
- }
- }
-
- function loadEventsForMonth() {
- if (!CalendarService || !CalendarService.khalAvailable) {
- return;
- }
-
- const firstOfMonth = new Date(calendarGrid.displayDate.getFullYear(), calendarGrid.displayDate.getMonth(), 1);
- const lastOfMonth = new Date(calendarGrid.displayDate.getFullYear(), calendarGrid.displayDate.getMonth() + 1, 0);
-
- const startDate = startOfWeek(firstOfMonth);
- startDate.setDate(startDate.getDate() - 7);
-
- const endDate = endOfWeek(lastOfMonth);
- endDate.setDate(endDate.getDate() + 7);
-
- CalendarService.loadEvents(startDate, endDate);
- }
-
- onSelectedDateChanged: updateSelectedDateEvents()
- Component.onCompleted: {
- loadEventsForMonth();
- updateSelectedDateEvents();
- }
-
- Connections {
- function onEventsByDateChanged() {
- updateSelectedDateEvents();
- }
-
- function onKhalAvailableChanged() {
- if (CalendarService && CalendarService.khalAvailable) {
- loadEventsForMonth();
- }
- updateSelectedDateEvents();
- }
-
- target: CalendarService
- enabled: CalendarService !== null
- }
-
- radius: Theme.cornerRadius
- color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.05)
- border.width: 1
-
- Column {
- anchors.fill: parent
- anchors.margins: Theme.spacingM
- spacing: Theme.spacingS
-
- Item {
- width: parent.width
- height: 40
- visible: showEventDetails
-
- Rectangle {
- width: 32
- height: 32
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: parent.left
- anchors.leftMargin: Theme.spacingS
- radius: Theme.cornerRadius
- color: backButtonArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "arrow_back"
- size: 14
- color: Theme.primary
- }
-
- MouseArea {
- id: backButtonArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: root.showEventDetails = false
- }
- }
-
- StyledText {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.leftMargin: 32 + Theme.spacingS * 2
- anchors.rightMargin: Theme.spacingS
- height: 40
- anchors.verticalCenter: parent.verticalCenter
- text: {
- const dateStr = Qt.formatDate(selectedDate, "MMM d");
- if (selectedDateEvents && selectedDateEvents.length > 0) {
- const eventCount = selectedDateEvents.length === 1 ? I18n.tr("1 event") : selectedDateEvents.length + " " + I18n.tr("events");
- return dateStr + " • " + eventCount;
- }
- return dateStr;
- }
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.surfaceText
- font.weight: Font.Medium
- verticalAlignment: Text.AlignVCenter
- elide: Text.ElideRight
- }
- }
-
- Row {
- width: parent.width
- height: 28
- visible: !showEventDetails
-
- Rectangle {
- width: 28
- height: 28
- radius: Theme.cornerRadius
- color: prevMonthArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "chevron_left"
- size: 14
- color: Theme.primary
- }
-
- MouseArea {
- id: prevMonthArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- let newDate = new Date(calendarGrid.displayDate);
- newDate.setMonth(newDate.getMonth() - 1);
- calendarGrid.displayDate = newDate;
- loadEventsForMonth();
- }
- }
- }
-
- StyledText {
- width: parent.width - 56
- height: 28
- text: calendarGrid.displayDate.toLocaleDateString(I18n.locale(), "MMMM yyyy")
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.surfaceText
- font.weight: Font.Medium
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- }
-
- Rectangle {
- width: 28
- height: 28
- radius: Theme.cornerRadius
- color: nextMonthArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "chevron_right"
- size: 14
- color: Theme.primary
- }
-
- MouseArea {
- id: nextMonthArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- let newDate = new Date(calendarGrid.displayDate);
- newDate.setMonth(newDate.getMonth() + 1);
- calendarGrid.displayDate = newDate;
- loadEventsForMonth();
- }
- }
- }
- }
-
- Row {
- width: parent.width
- height: parent.height - 28 - Theme.spacingS
- visible: !showEventDetails
- spacing: SettingsData.showWeekNumber ? Theme.spacingS : 0
-
- Column {
- id: weekNumberColumn
- visible: SettingsData.showWeekNumber
- width: SettingsData.showWeekNumber ? 28 : 0
- height: parent.height
- spacing: Theme.spacingS
-
- Item {
- width: parent.width
- height: 18
- }
-
- Grid {
- width: parent.width
- height: parent.height - 18 - Theme.spacingS
- columns: 1
- rows: 6
-
- Repeater {
- model: 6
- Rectangle {
- width: parent.width
- height: parent.height / 6
- color: "transparent"
-
- StyledText {
- anchors.centerIn: parent
- text: {
- const rowDate = new Date(calendarGrid.firstDay);
- rowDate.setDate(rowDate.getDate() + index * 7);
- return root.getWeekNumber(rowDate);
- }
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
- font.weight: Font.Medium
- }
- }
- }
- }
- }
-
- Column {
- width: SettingsData.showWeekNumber ? (parent.width - weekNumberColumn.width - parent.spacing) : parent.width
- height: parent.height
- spacing: Theme.spacingS
-
- Row {
- width: parent.width
- height: 18
-
- Repeater {
- model: {
- const days = [];
- const qtFirst = weekStartQt();
- for (let i = 0; i < 7; ++i) {
- const qtDay = ((qtFirst - 1 + i) % 7) + 1;
- days.push(I18n.locale().dayName(qtDay, Locale.ShortFormat));
- }
- return days;
- }
-
- Rectangle {
- width: parent.width / 7
- height: 18
- color: "transparent"
-
- StyledText {
- anchors.centerIn: parent
- text: modelData
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6)
- font.weight: Font.Medium
- }
- }
- }
- }
-
- Grid {
- id: calendarGrid
- width: parent.width
- height: parent.height - 18 - Theme.spacingS
- columns: 7
- rows: 6
-
- 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);
- }
-
- Repeater {
- model: 42
-
- Rectangle {
- readonly property date dayDate: {
- const date = new Date(parent.firstDay);
- date.setDate(date.getDate() + index);
- return date;
- }
- readonly property bool isCurrentMonth: dayDate.getMonth() === calendarGrid.displayDate.getMonth()
- readonly property bool isToday: dayDate.toDateString() === new Date().toDateString()
- readonly property bool isSelected: dayDate.toDateString() === calendarGrid.selectedDate.toDateString()
-
- width: parent.width / 7
- height: parent.height / 6
- color: "transparent"
-
- Rectangle {
- anchors.centerIn: parent
- width: Math.min(parent.width - 4, parent.height - 4, 32)
- height: width
- color: isToday ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : dayArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08) : "transparent"
- radius: Theme.cornerRadius
-
- StyledText {
- anchors.centerIn: parent
- text: dayDate.getDate()
- font.pixelSize: Theme.fontSizeSmall
- color: isToday ? Theme.primary : isCurrentMonth ? Theme.surfaceText : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.4)
- font.weight: isToday ? Font.Medium : Font.Normal
- }
-
- Rectangle {
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottomMargin: 4
- width: 12
- height: 2
- radius: Theme.cornerRadius
- visible: CalendarService && CalendarService.khalAvailable && CalendarService.hasEventsForDate(dayDate)
- color: isToday ? Qt.lighter(Theme.primary, 1.3) : Theme.primary
- opacity: isToday ? 0.9 : 0.7
-
- Behavior on opacity {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
- }
-
- MouseArea {
- id: dayArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (CalendarService && CalendarService.khalAvailable && CalendarService.hasEventsForDate(dayDate)) {
- root.selectedDate = dayDate;
- root.showEventDetails = true;
- }
- }
- }
- }
- }
- }
- }
- }
-
- DankListView {
- width: parent.width - Theme.spacingS * 2
- height: parent.height - (showEventDetails ? 40 : 28 + 18) - Theme.spacingS
- anchors.horizontalCenter: parent.horizontalCenter
- model: selectedDateEvents
- visible: showEventDetails
- clip: true
- spacing: Theme.spacingXS
-
- delegate: Rectangle {
- width: parent ? parent.width : 0
- height: eventContent.implicitHeight + Theme.spacingS
- radius: Theme.cornerRadius
- color: {
- if (modelData.url && eventMouseArea.containsMouse) {
- return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
- } else if (eventMouseArea.containsMouse) {
- return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.06);
- }
- return Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency);
- }
- border.color: {
- if (modelData.url && eventMouseArea.containsMouse) {
- return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3);
- } else if (eventMouseArea.containsMouse) {
- return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15);
- }
- return "transparent";
- }
- border.width: 1
-
- Rectangle {
- width: 3
- height: parent.height - 6
- anchors.left: parent.left
- anchors.leftMargin: 3
- anchors.verticalCenter: parent.verticalCenter
- radius: Theme.cornerRadius
- color: Theme.primary
- opacity: 0.8
- }
-
- Column {
- id: eventContent
-
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: Theme.spacingS + 6
- anchors.rightMargin: Theme.spacingXS
- spacing: 2
-
- StyledText {
- width: parent.width
- text: modelData.title
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- font.weight: Font.Medium
- elide: Text.ElideRight
- maximumLineCount: 1
- }
-
- StyledText {
- width: parent.width
- text: {
- if (!modelData || modelData.allDay) {
- return I18n.tr("All day");
- } else if (modelData.start && modelData.end) {
- const timeFormat = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP";
- const startTime = Qt.formatTime(modelData.start, timeFormat);
- if (modelData.start.toDateString() !== modelData.end.toDateString() || modelData.start.getTime() !== modelData.end.getTime()) {
- return startTime + " – " + Qt.formatTime(modelData.end, timeFormat);
- }
- return startTime;
- }
- return "";
- }
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
- font.weight: Font.Normal
- visible: text !== ""
- }
- }
-
- MouseArea {
- id: eventMouseArea
-
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: modelData.url ? Qt.PointingHandCursor : Qt.ArrowCursor
- enabled: modelData.url !== ""
- onClicked: {
- if (modelData.url && modelData.url !== "") {
- if (Qt.openUrlExternally(modelData.url) === false) {
- console.warn("Failed to open URL: " + modelData.url);
- } else {
- root.closeDash();
- }
- }
- }
- }
- }
- }
- }
-
- SystemClock {
- id: systemClock
- precision: SystemClock.Hours
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/Card.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/Card.qml
deleted file mode 100644
index 8996c81..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/Card.qml
+++ /dev/null
@@ -1,24 +0,0 @@
-import QtQuick
-import qs.Common
-
-Rectangle {
- id: card
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- property int pad: Theme.spacingM
-
- radius: Theme.cornerRadius
- color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
- border.width: 1
-
- default property alias content: contentItem.data
-
- Item {
- id: contentItem
- anchors.fill: parent
- anchors.margins: card.pad
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/ClockCard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/ClockCard.qml
deleted file mode 100644
index 5f597c3..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/ClockCard.qml
+++ /dev/null
@@ -1,113 +0,0 @@
-import QtQuick
-import QtQuick.Effects
-import Quickshell
-import qs.Common
-import qs.Widgets
-
-Card {
- id: root
-
- Column {
- anchors.centerIn: parent
- spacing: 0
-
- Column {
- spacing: -8
- anchors.horizontalCenter: parent.horizontalCenter
-
- Row {
- spacing: 0
- anchors.horizontalCenter: parent.horizontalCenter
-
- StyledText {
- text: {
- if (SettingsData.use24HourClock) {
- return String(systemClock?.date?.getHours()).padStart(2, '0').charAt(0)
- } else {
- const hours = systemClock?.date?.getHours()
- const display = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours
- return String(display).padStart(2, '0').charAt(0)
- }
- }
- font.pixelSize: 48
- color: Theme.primary
- font.weight: Font.Medium
- width: 28
- horizontalAlignment: Text.AlignHCenter
- }
-
- StyledText {
- text: {
- if (SettingsData.use24HourClock) {
- return String(systemClock?.date?.getHours()).padStart(2, '0').charAt(1)
- } else {
- const hours = systemClock?.date?.getHours()
- const display = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours
- return String(display).padStart(2, '0').charAt(1)
- }
- }
- font.pixelSize: 48
- color: Theme.primary
- font.weight: Font.Medium
- width: 28
- horizontalAlignment: Text.AlignHCenter
- }
- }
-
- Row {
- spacing: 0
- anchors.horizontalCenter: parent.horizontalCenter
-
- StyledText {
- text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(0)
- font.pixelSize: 48
- color: Theme.primary
- font.weight: Font.Medium
- width: 28
- horizontalAlignment: Text.AlignHCenter
- }
-
- StyledText {
- text: String(systemClock?.date?.getMinutes()).padStart(2, '0').charAt(1)
- font.pixelSize: 48
- color: Theme.primary
- font.weight: Font.Medium
- width: 28
- horizontalAlignment: Text.AlignHCenter
- }
- }
- }
-
- Row {
- visible: SettingsData.showSeconds
- spacing: 0
- anchors.horizontalCenter: parent.horizontalCenter
-
- StyledText {
- text: String(systemClock?.date?.getSeconds()).padStart(2, '0')
- font.pixelSize: 24
- color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.7)
- font.weight: Font.Medium
- horizontalAlignment: Text.AlignHCenter
- }
- }
-
- Item {
- width: 1
- height: Theme.spacingXS
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- StyledText {
- text: systemClock?.date?.toLocaleDateString(I18n.locale(), "MMM dd")
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
- anchors.horizontalCenter: parent.horizontalCenter
- }
- }
-
- SystemClock {
- id: systemClock
- precision: SettingsData.showSeconds ? SystemClock.Seconds : SystemClock.Minutes
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/MediaOverviewCard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/MediaOverviewCard.qml
deleted file mode 100644
index 35f4f47..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/MediaOverviewCard.qml
+++ /dev/null
@@ -1,211 +0,0 @@
-import QtQuick
-import QtQuick.Effects
-import QtQuick.Shapes
-import Quickshell.Services.Mpris
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Card {
- id: root
- clip: false
-
- signal clicked()
-
- property MprisPlayer activePlayer: MprisController.activePlayer
- property real currentPosition: activePlayer?.positionSupported ? activePlayer.position : 0
- property real displayPosition: currentPosition
-
- readonly property real ratio: {
- if (!activePlayer || activePlayer.length <= 0) return 0
- const pos = displayPosition % Math.max(1, activePlayer.length)
- const calculatedRatio = pos / activePlayer.length
- return Math.max(0, Math.min(1, calculatedRatio))
- }
-
- onActivePlayerChanged: {
- if (activePlayer?.positionSupported) {
- currentPosition = Qt.binding(() => activePlayer?.position || 0)
- } else {
- currentPosition = 0
- }
- }
-
- Timer {
- interval: 300
- running: activePlayer?.playbackState === MprisPlaybackState.Playing && !isSeeking
- repeat: true
- onTriggered: activePlayer?.positionSupported && activePlayer.positionChanged()
- }
-
- property bool isSeeking: false
-
- Column {
- anchors.centerIn: parent
- spacing: Theme.spacingS
- visible: !activePlayer
-
- DankIcon {
- name: "music_note"
- size: Theme.iconSize
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- StyledText {
- text: I18n.tr("No Media")
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
- anchors.horizontalCenter: parent.horizontalCenter
- }
- }
-
- Column {
- anchors.centerIn: parent
- width: parent.width - Theme.spacingXS * 2
- spacing: Theme.spacingL
- visible: activePlayer
-
- Item {
- width: 140
- height: 110
- anchors.horizontalCenter: parent.horizontalCenter
- clip: false
-
- DankAlbumArt {
- width: 110
- height: 80
- anchors.centerIn: parent
- activePlayer: root.activePlayer
- albumSize: 76
- animationScale: 1.05
- }
- }
-
- Column {
- width: parent.width
- spacing: Theme.spacingXS
- topPadding: Theme.spacingL
-
- StyledText {
- text: activePlayer?.trackTitle || I18n.tr("Unknown")
- font.pixelSize: Theme.fontSizeSmall
- font.weight: Font.Medium
- color: Theme.surfaceText
- width: parent.width
- elide: Text.ElideRight
- maximumLineCount: 1
- horizontalAlignment: Text.AlignHCenter
- }
-
- StyledText {
- text: activePlayer?.trackArtist || I18n.tr("Unknown Artist")
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
- width: parent.width
- elide: Text.ElideRight
- maximumLineCount: 1
- horizontalAlignment: Text.AlignHCenter
- }
- }
-
- DankSeekbar {
- width: parent.width + 4
- height: 20
- x: -2
- activePlayer: root.activePlayer
- isSeeking: root.isSeeking
- onIsSeekingChanged: root.isSeeking = isSeeking
- }
-
- Item {
- width: parent.width
- height: 32
-
- Row {
- spacing: Theme.spacingS
- anchors.centerIn: parent
-
- Rectangle {
- width: 28
- height: 28
- radius: 14
- anchors.verticalCenter: playPauseButton.verticalCenter
- color: prevArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "skip_previous"
- size: 14
- color: Theme.surfaceText
- }
-
- MouseArea {
- id: prevArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: MprisController.previousOrRewind()
- }
- }
-
- Rectangle {
- id: playPauseButton
- width: 32
- height: 32
- radius: 16
- color: Theme.primary
-
- DankIcon {
- anchors.centerIn: parent
- name: activePlayer?.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow"
- size: 16
- color: Theme.background
- }
-
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: activePlayer?.togglePlaying()
- }
- }
-
- Rectangle {
- width: 28
- height: 28
- radius: 14
- anchors.verticalCenter: playPauseButton.verticalCenter
- color: nextArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "skip_next"
- size: 14
- color: Theme.surfaceText
- }
-
- MouseArea {
- id: nextArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: activePlayer?.next()
- }
- }
- }
- }
- }
-
- MouseArea {
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.bottomMargin: 123
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: root.clicked()
- visible: activePlayer
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/SystemMonitorCard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/SystemMonitorCard.qml
deleted file mode 100644
index cb7089b..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/SystemMonitorCard.qml
+++ /dev/null
@@ -1,178 +0,0 @@
-import QtQuick
-import QtQuick.Effects
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Card {
- id: root
-
- Component.onCompleted: {
- DgopService.addRef(["cpu", "memory", "system"])
- }
- Component.onDestruction: {
- DgopService.removeRef(["cpu", "memory", "system"])
- }
-
- Row {
- anchors.fill: parent
- anchors.margins: Theme.spacingS
- spacing: Theme.spacingM
-
- // CPU Bar
- Column {
- width: (parent.width - 2 * Theme.spacingM) / 3
- height: parent.height
- spacing: Theme.spacingS
-
- Rectangle {
- width: 8
- height: parent.height - Theme.iconSizeSmall - Theme.spacingS
- radius: 4
- anchors.horizontalCenter: parent.horizontalCenter
- color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
-
- Rectangle {
- width: parent.width
- height: parent.height * Math.min((DgopService.cpuUsage || 6) / 100, 1)
- radius: parent.radius
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- color: {
- if (DgopService.cpuUsage > 80) return Theme.error
- if (DgopService.cpuUsage > 60) return Theme.warning
- return Theme.primary
- }
-
- Behavior on height {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
- }
-
- Item {
- width: parent.width
- height: Theme.iconSizeSmall
-
- DankIcon {
- name: "memory"
- size: Theme.iconSizeSmall
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- color: {
- if (DgopService.cpuUsage > 80) return Theme.error
- if (DgopService.cpuUsage > 60) return Theme.warning
- return Theme.primary
- }
- }
- }
- }
-
- // Temperature Bar
- Column {
- width: (parent.width - 2 * Theme.spacingM) / 3
- height: parent.height
- spacing: Theme.spacingS
-
- Rectangle {
- width: 8
- height: parent.height - Theme.iconSizeSmall - Theme.spacingS
- radius: 4
- anchors.horizontalCenter: parent.horizontalCenter
- color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
-
- Rectangle {
- width: parent.width
- height: parent.height * Math.min(Math.max((DgopService.cpuTemperature || 40) / 100, 0), 1)
- radius: parent.radius
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- color: {
- if (DgopService.cpuTemperature > 85) return Theme.error
- if (DgopService.cpuTemperature > 69) return Theme.warning
- return Theme.primary
- }
-
- Behavior on height {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
- }
-
- Item {
- width: parent.width
- height: Theme.iconSizeSmall
-
- DankIcon {
- name: "device_thermostat"
- size: Theme.iconSizeSmall
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- color: {
- if (DgopService.cpuTemperature > 85) return Theme.error
- if (DgopService.cpuTemperature > 69) return Theme.warning
- return Theme.primary
- }
- }
- }
- }
-
- // RAM Bar
- Column {
- width: (parent.width - 2 * Theme.spacingM) / 3
- height: parent.height
- spacing: Theme.spacingS
-
- Rectangle {
- width: 8
- height: parent.height - Theme.iconSizeSmall - Theme.spacingS
- radius: 4
- anchors.horizontalCenter: parent.horizontalCenter
- color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
-
- Rectangle {
- width: parent.width
- height: parent.height * Math.min((DgopService.memoryUsage || 42) / 100, 1)
- radius: parent.radius
- anchors.bottom: parent.bottom
- anchors.horizontalCenter: parent.horizontalCenter
- color: {
- if (DgopService.memoryUsage > 90) return Theme.error
- if (DgopService.memoryUsage > 75) return Theme.warning
- return Theme.primary
- }
-
- Behavior on height {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
- }
-
- Item {
- width: parent.width
- height: Theme.iconSizeSmall
-
- DankIcon {
- name: "developer_board"
- size: Theme.iconSizeSmall
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.bottom: parent.bottom
- color: {
- if (DgopService.memoryUsage > 90) return Theme.error
- if (DgopService.memoryUsage > 75) return Theme.warning
- return Theme.primary
- }
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/UserInfoCard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/UserInfoCard.qml
deleted file mode 100644
index 0d90b44..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/UserInfoCard.qml
+++ /dev/null
@@ -1,110 +0,0 @@
-import QtQuick
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Card {
- id: root
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- Component.onCompleted: DgopService.addRef("system")
- Component.onDestruction: DgopService.removeRef("system")
-
- Row {
- anchors.left: parent.left
- anchors.leftMargin: Theme.spacingM
- anchors.verticalCenter: parent.verticalCenter
- spacing: Theme.spacingM
-
- DankCircularImage {
- id: avatarContainer
-
- width: 77
- height: 77
- anchors.verticalCenter: parent.verticalCenter
- imageSource: {
- if (PortalService.profileImage === "")
- return "";
-
- if (PortalService.profileImage.startsWith("/"))
- return "file://" + PortalService.profileImage;
-
- return PortalService.profileImage;
- }
- fallbackIcon: "person"
- }
-
- Column {
- spacing: Theme.spacingS
- anchors.verticalCenter: parent.verticalCenter
-
- StyledText {
- text: UserInfoService.username || I18n.tr("brandon")
- font.pixelSize: Theme.fontSizeLarge
- font.weight: Font.Medium
- color: Theme.surfaceText
- elide: Text.ElideRight
- width: parent.parent.parent.width - avatarContainer.width - Theme.spacingM * 3
- horizontalAlignment: Text.AlignLeft
- }
-
- Row {
- anchors.left: parent.left
- spacing: Theme.spacingS
-
- SystemLogo {
- width: 16
- height: 16
- anchors.verticalCenter: parent.verticalCenter
- colorOverride: Theme.primary
- }
-
- StyledText {
- text: {
- if (CompositorService.isNiri)
- return I18n.tr("on Niri");
- if (CompositorService.isHyprland)
- return I18n.tr("on Hyprland");
- // technically they might not be on mangowc, but its what we support in the docs
- if (CompositorService.isDwl)
- return I18n.tr("on MangoWC");
- if (CompositorService.isSway)
- return I18n.tr("on Sway");
- if (CompositorService.isScroll)
- return I18n.tr("on Scroll");
- if (CompositorService.isMiracle)
- return I18n.tr("on Miracle WM");
- return "";
- }
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.8)
- anchors.verticalCenter: parent.verticalCenter
- elide: Text.ElideRight
- width: parent.parent.parent.parent.width - avatarContainer.width - Theme.spacingM * 3 - 16 - Theme.spacingS
- horizontalAlignment: Text.AlignLeft
- }
- }
-
- Row {
- anchors.left: parent.left
- spacing: Theme.spacingS
-
- DankIcon {
- name: "schedule"
- size: 16
- color: Theme.primary
- anchors.verticalCenter: parent.verticalCenter
- }
-
- StyledText {
- text: DgopService.shortUptime || I18n.tr("up")
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
- anchors.verticalCenter: parent.verticalCenter
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/WeatherOverviewCard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/WeatherOverviewCard.qml
deleted file mode 100644
index 0bba92e..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/Overview/WeatherOverviewCard.qml
+++ /dev/null
@@ -1,94 +0,0 @@
-import QtQuick
-import QtQuick.Controls
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Card {
- id: root
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- signal clicked
-
- Component.onCompleted: WeatherService.addRef()
- Component.onDestruction: WeatherService.removeRef()
-
- Column {
- anchors.centerIn: parent
- spacing: Theme.spacingS
- visible: !WeatherService.weather.available
-
- DankIcon {
- name: "cloud_off"
- size: 24
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- StyledText {
- text: WeatherService.weather.loading ? I18n.tr("Loading...") : I18n.tr("No Weather")
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- Button {
- text: I18n.tr("Refresh")
- flat: true
- visible: !WeatherService.weather.loading
- anchors.horizontalCenter: parent.horizontalCenter
- onClicked: WeatherService.forceRefresh()
- }
- }
-
- Row {
- anchors.left: parent.left
- anchors.leftMargin: Theme.spacingL
- anchors.verticalCenter: parent.verticalCenter
- spacing: Theme.spacingL
- visible: WeatherService.weather.available
-
- 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 {
- anchors.left: parent.left
- text: {
- const temp = SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp;
- if (temp === undefined || temp === null)
- return "--°" + (SettingsData.useFahrenheit ? "F" : "C");
- return temp + "°" + (SettingsData.useFahrenheit ? "F" : "C");
- }
- font.pixelSize: Theme.fontSizeXLarge + 4
- color: Theme.surfaceText
- font.weight: Font.Light
- }
-
- StyledText {
- text: WeatherService.getWeatherCondition(WeatherService.weather.wCode)
- font.pixelSize: Theme.fontSizeSmall
- color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
- elide: Text.ElideRight
- width: parent.parent.parent.width - 48 - Theme.spacingL * 2
- horizontalAlignment: Text.AlignLeft
- }
- }
- }
-
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: root.clicked()
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/OverviewTab.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/OverviewTab.qml
deleted file mode 100644
index de7ea35..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/OverviewTab.qml
+++ /dev/null
@@ -1,75 +0,0 @@
-import QtQuick
-import qs.Common
-import qs.Modules.DankDash.Overview
-
-Item {
- id: root
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- implicitWidth: SettingsData.showWeekNumber ? 736 : 700
- implicitHeight: 410
-
- signal switchToWeatherTab
- signal switchToMediaTab
- signal closeDash
-
- Item {
- anchors.fill: parent
- // Clock - top left (narrower and shorter)
- ClockCard {
- x: 0
- y: 0
- width: parent.width * 0.2 - Theme.spacingM * 2
- height: 180
- }
-
- // Weather - top middle-left (narrower)
- WeatherOverviewCard {
- x: SettingsData.weatherEnabled ? parent.width * 0.2 - Theme.spacingM : 0
- y: 0
- width: SettingsData.weatherEnabled ? parent.width * 0.3 : 0
- height: 100
- visible: SettingsData.weatherEnabled
-
- onClicked: root.switchToWeatherTab()
- }
-
- // UserInfo - top middle-right (extend when weather disabled)
- UserInfoCard {
- x: SettingsData.weatherEnabled ? parent.width * 0.5 : parent.width * 0.2 - Theme.spacingM
- y: 0
- width: SettingsData.weatherEnabled ? parent.width * 0.5 : parent.width * 0.8
- height: 100
- }
-
- // SystemMonitor - middle left (narrow and shorter)
- SystemMonitorCard {
- x: 0
- y: 180 + Theme.spacingM
- width: parent.width * 0.2 - Theme.spacingM * 2
- height: 220
- }
-
- // Calendar - bottom middle (wider and taller)
- CalendarOverviewCard {
- x: parent.width * 0.2 - Theme.spacingM
- y: 100 + Theme.spacingM
- width: parent.width * 0.6
- height: 300
-
- onCloseDash: root.closeDash()
- }
-
- // Media - bottom right (narrow and taller)
- MediaOverviewCard {
- x: parent.width * 0.8
- y: 100 + Theme.spacingM
- width: parent.width * 0.2
- height: 300
-
- onClicked: root.switchToMediaTab()
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WallpaperTab.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WallpaperTab.qml
deleted file mode 100644
index 1f35b00..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WallpaperTab.qml
+++ /dev/null
@@ -1,590 +0,0 @@
-import Qt.labs.folderlistmodel
-import QtCore
-import QtQuick
-import QtQuick.Effects
-import qs.Common
-import qs.Modals.FileBrowser
-import qs.Widgets
-
-Item {
- id: root
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- implicitWidth: SettingsData.showWeekNumber ? 736 : 700
- implicitHeight: 410
-
- property string wallpaperDir: ""
- property int currentPage: 0
- property int itemsPerPage: 16
- property int totalPages: Math.max(1, Math.ceil(wallpaperFolderModel.count / itemsPerPage))
- property bool active: false
- property Item focusTarget: wallpaperGrid
- property Item tabBarItem: null
- property int gridIndex: 0
- property Item keyForwardTarget: null
- property var parentPopout: null
- property int lastPage: 0
- property bool enableAnimation: false
- property string homeDir: StandardPaths.writableLocation(StandardPaths.HomeLocation)
- property string selectedFileName: ""
- property var targetScreen: null
- property string targetScreenName: targetScreen ? targetScreen.name : ""
-
- signal requestTabChange(int newIndex)
-
- function getCurrentWallpaper() {
- if (SessionData.perMonitorWallpaper && targetScreenName) {
- return SessionData.getMonitorWallpaper(targetScreenName);
- }
- return SessionData.wallpaperPath;
- }
-
- function setCurrentWallpaper(path) {
- if (SessionData.perMonitorWallpaper && targetScreenName) {
- SessionData.setMonitorWallpaper(targetScreenName, path);
- } else {
- SessionData.setWallpaper(path);
- }
- }
-
- onCurrentPageChanged: {
- if (currentPage !== lastPage) {
- enableAnimation = false;
- lastPage = currentPage;
- }
- updateSelectedFileName();
- }
-
- onGridIndexChanged: {
- updateSelectedFileName();
- }
-
- onVisibleChanged: {
- if (visible && active) {
- setInitialSelection();
- }
- }
-
- Component.onCompleted: {
- loadWallpaperDirectory();
- }
-
- onActiveChanged: {
- if (active && visible) {
- setInitialSelection();
- }
- }
-
- function handleKeyEvent(event) {
- const columns = 4;
- const currentCol = gridIndex % columns;
- const visibleCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
-
- if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
- if (gridIndex >= 0 && gridIndex < visibleCount) {
- const absoluteIndex = currentPage * itemsPerPage + gridIndex;
- if (absoluteIndex < wallpaperFolderModel.count) {
- const filePath = wallpaperFolderModel.get(absoluteIndex, "filePath");
- if (filePath) {
- setCurrentWallpaper(filePath.toString().replace(/^file:\/\//, ''));
- }
- }
- }
- return true;
- }
-
- if (event.key === Qt.Key_Right || event.key === Qt.Key_L) {
- if (I18n.isRtl) {
- if (gridIndex > 0) {
- gridIndex--;
- } else if (currentPage > 0) {
- currentPage--;
- const prevPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
- gridIndex = prevPageCount - 1;
- }
- } else {
- if (gridIndex + 1 < visibleCount) {
- gridIndex++;
- } else if (currentPage < totalPages - 1) {
- gridIndex = 0;
- currentPage++;
- }
- }
- return true;
- }
-
- if (event.key === Qt.Key_Left || event.key === Qt.Key_H) {
- if (I18n.isRtl) {
- if (gridIndex + 1 < visibleCount) {
- gridIndex++;
- } else if (currentPage < totalPages - 1) {
- gridIndex = 0;
- currentPage++;
- }
- } else {
- if (gridIndex > 0) {
- gridIndex--;
- } else if (currentPage > 0) {
- currentPage--;
- const prevPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
- gridIndex = prevPageCount - 1;
- }
- }
- return true;
- }
-
- if (event.key === Qt.Key_Down || event.key === Qt.Key_J) {
- if (gridIndex + columns < visibleCount) {
- gridIndex += columns;
- } else if (currentPage < totalPages - 1) {
- gridIndex = currentCol;
- currentPage++;
- }
- return true;
- }
-
- if (event.key === Qt.Key_Up || event.key === Qt.Key_K) {
- if (gridIndex >= columns) {
- gridIndex -= columns;
- } else if (currentPage > 0) {
- currentPage--;
- const prevPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
- const prevPageRows = Math.ceil(prevPageCount / columns);
- gridIndex = (prevPageRows - 1) * columns + currentCol;
- gridIndex = Math.min(gridIndex, prevPageCount - 1);
- }
- return true;
- }
-
- if (event.key === Qt.Key_PageUp && currentPage > 0) {
- gridIndex = 0;
- currentPage--;
- return true;
- }
-
- if (event.key === Qt.Key_PageDown && currentPage < totalPages - 1) {
- gridIndex = 0;
- currentPage++;
- return true;
- }
-
- if (event.key === Qt.Key_Home && event.modifiers & Qt.ControlModifier) {
- gridIndex = 0;
- currentPage = 0;
- return true;
- }
-
- if (event.key === Qt.Key_End && event.modifiers & Qt.ControlModifier) {
- currentPage = totalPages - 1;
- const lastPageCount = Math.min(itemsPerPage, wallpaperFolderModel.count - currentPage * itemsPerPage);
- gridIndex = Math.max(0, lastPageCount - 1);
- return true;
- }
-
- return false;
- }
-
- function setInitialSelection() {
- const currentWallpaper = getCurrentWallpaper();
- if (!currentWallpaper || wallpaperFolderModel.count === 0) {
- gridIndex = 0;
- updateSelectedFileName();
- Qt.callLater(() => {
- enableAnimation = true;
- });
- return;
- }
-
- for (var i = 0; i < wallpaperFolderModel.count; i++) {
- const filePath = wallpaperFolderModel.get(i, "filePath");
- if (filePath && filePath.toString().replace(/^file:\/\//, '') === currentWallpaper) {
- const targetPage = Math.floor(i / itemsPerPage);
- const targetIndex = i % itemsPerPage;
- currentPage = targetPage;
- gridIndex = targetIndex;
- updateSelectedFileName();
- Qt.callLater(() => {
- enableAnimation = true;
- });
- return;
- }
- }
- gridIndex = 0;
- updateSelectedFileName();
- Qt.callLater(() => {
- enableAnimation = true;
- });
- }
-
- function loadWallpaperDirectory() {
- const currentWallpaper = getCurrentWallpaper();
-
- if (!currentWallpaper || currentWallpaper.startsWith("#")) {
- if (CacheData.wallpaperLastPath && CacheData.wallpaperLastPath !== "") {
- wallpaperDir = CacheData.wallpaperLastPath;
- } else {
- wallpaperDir = "";
- }
- return;
- }
-
- wallpaperDir = currentWallpaper.substring(0, currentWallpaper.lastIndexOf('/'));
- }
-
- function updateSelectedFileName() {
- if (wallpaperFolderModel.count === 0) {
- selectedFileName = "";
- return;
- }
-
- const absoluteIndex = currentPage * itemsPerPage + gridIndex;
- if (absoluteIndex < wallpaperFolderModel.count) {
- const filePath = wallpaperFolderModel.get(absoluteIndex, "filePath");
- if (filePath) {
- const pathStr = filePath.toString().replace(/^file:\/\//, '');
- selectedFileName = pathStr.substring(pathStr.lastIndexOf('/') + 1);
- return;
- }
- }
- selectedFileName = "";
- }
-
- Connections {
- target: SessionData
- function onWallpaperPathChanged() {
- loadWallpaperDirectory();
- if (visible && active) {
- setInitialSelection();
- }
- }
- function onMonitorWallpapersChanged() {
- loadWallpaperDirectory();
- if (visible && active) {
- setInitialSelection();
- }
- }
- function onPerMonitorWallpaperChanged() {
- loadWallpaperDirectory();
- if (visible && active) {
- setInitialSelection();
- }
- }
- }
-
- onTargetScreenNameChanged: {
- loadWallpaperDirectory();
- if (visible && active) {
- setInitialSelection();
- }
- }
-
- Connections {
- target: wallpaperFolderModel
- function onCountChanged() {
- if (wallpaperFolderModel.status === FolderListModel.Ready) {
- if (visible && active) {
- setInitialSelection();
- }
- updateSelectedFileName();
- }
- }
- function onStatusChanged() {
- if (wallpaperFolderModel.status === FolderListModel.Ready && wallpaperFolderModel.count > 0) {
- if (visible && active) {
- setInitialSelection();
- }
- updateSelectedFileName();
- }
- }
- }
-
- FolderListModel {
- id: wallpaperFolderModel
-
- showDirsFirst: false
- showDotAndDotDot: false
- showHidden: false
- caseSensitive: false
- nameFilters: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp", "*.jxl", "*.avif", "*.heif", "*.exr"]
- showFiles: true
- showDirs: false
- sortField: FolderListModel.Name
- folder: wallpaperDir ? "file://" + wallpaperDir.split('/').map(s => encodeURIComponent(s)).join('/') : ""
- }
-
- FileBrowserSurfaceModal {
- id: wallpaperBrowser
-
- browserTitle: I18n.tr("Select Wallpaper Directory", "wallpaper directory file browser title")
- browserIcon: "folder_open"
- browserType: "wallpaper"
- showHiddenFiles: false
- fileExtensions: ["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.gif", "*.webp", "*.jxl", "*.avif", "*.heif", "*.exr"]
- parentPopout: root.parentPopout
-
- onFileSelected: path => {
- const cleanPath = path.replace(/^file:\/\//, '');
- setCurrentWallpaper(cleanPath);
-
- const dirPath = cleanPath.substring(0, cleanPath.lastIndexOf('/'));
- if (dirPath) {
- wallpaperDir = dirPath;
- CacheData.wallpaperLastPath = dirPath;
- CacheData.saveCache();
- }
- close();
- }
- }
-
- Column {
- anchors.fill: parent
- spacing: 0
-
- Item {
- width: parent.width
- height: parent.height - 50
-
- GridView {
- id: wallpaperGrid
- anchors.centerIn: parent
- width: parent.width - Theme.spacingS
- height: parent.height - Theme.spacingS
- cellWidth: width / 4
- cellHeight: height / 4
- clip: true
- enabled: root.active
- interactive: root.active
- boundsBehavior: Flickable.StopAtBounds
- keyNavigationEnabled: false
- activeFocusOnTab: false
- highlightFollowsCurrentItem: true
- highlightMoveDuration: enableAnimation ? Theme.shortDuration : 0
- focus: false
-
- highlight: Item {
- z: 1000
- Rectangle {
- anchors.fill: parent
- anchors.margins: Theme.spacingXS
- color: "transparent"
- border.width: 3
- border.color: Theme.primary
- radius: Theme.cornerRadius
- }
- }
-
- model: {
- const startIndex = currentPage * itemsPerPage;
- const endIndex = Math.min(startIndex + itemsPerPage, wallpaperFolderModel.count);
- const items = [];
- for (var i = startIndex; i < endIndex; i++) {
- const filePath = wallpaperFolderModel.get(i, "filePath");
- if (filePath) {
- items.push(filePath.toString().replace(/^file:\/\//, ''));
- }
- }
- return items;
- }
-
- onModelChanged: {
- const clampedIndex = model.length > 0 ? Math.min(Math.max(0, gridIndex), model.length - 1) : 0;
- if (gridIndex !== clampedIndex) {
- gridIndex = clampedIndex;
- }
- }
-
- onCountChanged: {
- if (count > 0) {
- const clampedIndex = Math.min(gridIndex, count - 1);
- currentIndex = clampedIndex;
- positionViewAtIndex(clampedIndex, GridView.Contain);
- }
- Qt.callLater(() => {
- enableAnimation = true;
- });
- }
-
- Connections {
- target: root
- function onGridIndexChanged() {
- if (wallpaperGrid.count > 0) {
- wallpaperGrid.currentIndex = gridIndex;
- if (!enableAnimation) {
- wallpaperGrid.positionViewAtIndex(gridIndex, GridView.Contain);
- }
- }
- }
- }
-
- delegate: Item {
- width: wallpaperGrid.cellWidth
- height: wallpaperGrid.cellHeight
-
- property string wallpaperPath: modelData || ""
- property bool isSelected: getCurrentWallpaper() === modelData
-
- Rectangle {
- id: wallpaperCard
- anchors.fill: parent
- anchors.margins: Theme.spacingXS
- color: Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency)
- radius: Theme.cornerRadius
- clip: true
-
- Rectangle {
- anchors.fill: parent
- color: isSelected ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.15) : "transparent"
- radius: parent.radius
-
- Behavior on color {
- ColorAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
-
- Rectangle {
- id: maskRect
- width: thumbnailImage.width
- height: thumbnailImage.height
- radius: Theme.cornerRadius
- visible: false
- layer.enabled: true
- }
-
- CachingImage {
- id: thumbnailImage
- anchors.fill: parent
- imagePath: modelData || ""
- maxCacheSize: 256
-
- layer.enabled: true
- layer.effect: MultiEffect {
- maskEnabled: true
- maskThresholdMin: 0.5
- maskSpreadAtMin: 1.0
- maskSource: maskRect
- }
- }
-
- StateLayer {
- anchors.fill: parent
- cornerRadius: parent.radius
- stateColor: Theme.primary
- }
-
- MouseArea {
- id: wallpaperMouseArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
-
- onClicked: {
- gridIndex = index;
- if (modelData) {
- setCurrentWallpaper(modelData);
- }
- }
- }
- }
- }
- }
-
- StyledText {
- anchors.centerIn: parent
- visible: wallpaperFolderModel.count === 0
- text: I18n.tr("No wallpapers found\n\nClick the folder icon below to browse")
- font.pixelSize: 14
- color: Theme.outline
- horizontalAlignment: Text.AlignHCenter
- }
- }
-
- Column {
- width: parent.width
- height: 50
-
- Row {
- width: parent.width
- height: 32
- spacing: Theme.spacingS
-
- Item {
- width: (parent.width - controlsRow.width - browseButton.width - Theme.spacingS) / 2
- height: parent.height
- }
-
- Row {
- id: controlsRow
- anchors.verticalCenter: parent.verticalCenter
- spacing: Theme.spacingS
-
- DankActionButton {
- anchors.verticalCenter: parent.verticalCenter
- iconName: "skip_previous"
- iconSize: 20
- buttonSize: 32
- enabled: currentPage > 0
- opacity: enabled ? 1.0 : 0.3
- onClicked: {
- if (currentPage > 0) {
- currentPage--;
- }
- }
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: wallpaperFolderModel.count > 0
- ? (wallpaperFolderModel.count === 1
- ? I18n.tr("%1 wallpaper • %2 / %3").arg(wallpaperFolderModel.count).arg(currentPage + 1).arg(totalPages)
- : I18n.tr("%1 wallpapers • %2 / %3").arg(wallpaperFolderModel.count).arg(currentPage + 1).arg(totalPages))
- : I18n.tr("No wallpapers")
- font.pixelSize: 14
- color: Theme.surfaceText
- opacity: 0.7
- }
-
- DankActionButton {
- anchors.verticalCenter: parent.verticalCenter
- iconName: "skip_next"
- iconSize: 20
- buttonSize: 32
- enabled: currentPage < totalPages - 1
- opacity: enabled ? 1.0 : 0.3
- onClicked: {
- if (currentPage < totalPages - 1) {
- currentPage++;
- }
- }
- }
- }
-
- DankActionButton {
- id: browseButton
- anchors.verticalCenter: parent.verticalCenter
- iconName: "folder_open"
- iconSize: 20
- buttonSize: 32
- opacity: 0.7
- onClicked: wallpaperBrowser.open()
- }
- }
-
- StyledText {
- width: parent.width
- height: 18
- text: selectedFileName
- font.pixelSize: 12
- color: Theme.surfaceText
- opacity: 0.5
- visible: selectedFileName !== ""
- elide: Text.ElideMiddle
- horizontalAlignment: Text.AlignHCenter
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WeatherForecastCard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WeatherForecastCard.qml
deleted file mode 100644
index 5c57b65..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WeatherForecastCard.qml
+++ /dev/null
@@ -1,206 +0,0 @@
-import QtQuick
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Rectangle {
- id: root
- radius: Theme.cornerRadius
-
- property var date: null
- property var daily: true
- property var forecastData: null
- property var dense: false
-
- readonly property bool isCurrent: {
- if (daily) {
- date ? WeatherService.calendarDayDifference(new Date(), date) === 0 : false;
- } else {
- date ? WeatherService.calendarHourDifference(new Date(), date) === 0 : false;
- }
- }
-
- readonly property string dateText: {
- if (daily)
- return root.forecastData?.day ?? "--";
- if (!root.forecastData?.rawTime)
- return root.forecastData?.time ?? "--";
- try {
- const date = new Date(root.forecastData.rawTime);
- const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP";
- return date.toLocaleTimeString(Qt.locale(), format);
- } catch (e) {
- return root.forecastData?.time ?? "--";
- }
- }
-
- readonly property var minTemp: WeatherService.formatTemp(root.forecastData?.tempMin)
- readonly property var maxTemp: WeatherService.formatTemp(root.forecastData?.tempMax)
- readonly property string minMaxTempText: (minTemp ?? "--") + "/" + (maxTemp ?? "--")
-
- readonly property var temp: WeatherService.formatTemp(root.forecastData?.temp)
- readonly property string tempText: temp ?? "--"
-
- readonly property var feelsLikeTemp: WeatherService.formatTemp(root.forecastData?.feelsLike)
- readonly property string feelsLikeText: feelsLikeTemp ?? "--"
-
- readonly property var humidity: WeatherService.formatPercent(root.forecastData?.humidity)
- readonly property string humidityText: humidity ?? "--"
-
- readonly property var wind: {
- SettingsData.windSpeedUnit;
- SettingsData.useFahrenheit;
- return WeatherService.formatSpeed(root.forecastData?.wind);
- }
- readonly property string windText: wind ?? "--"
-
- readonly property var pressure: {
- SettingsData.useFahrenheit;
- return WeatherService.formatPressure(root.forecastData?.pressure);
- }
- readonly property string pressureText: pressure ?? "--"
-
- readonly property var precipitation: root.forecastData?.precipitationProbability
- readonly property string precipitationText: precipitation + "%" ?? "--"
-
- readonly property var visibility: WeatherService.formatVisibility(root.forecastData?.visibility)
- readonly property string visibilityText: visibility ?? "--"
-
- readonly property var values: daily ? [] : [
- {
- "name"// 'name': "Temperature",
- :
- // 'text': root.tempText,
- // 'icon': "thermometer"
- // }, {
- // 'name': "Feels Like",
- // 'text': root.feelsLikeText,
- // 'icon': "thermostat"
- // }, {
- I18n.tr("Humidity"),
- "text": root.humidityText,
- "icon": "humidity_low"
- },
- {
- "name": I18n.tr("Wind Speed"),
- "text": root.windText,
- "icon": "air"
- },
- {
- "name": I18n.tr("Pressure"),
- "text": root.pressureText,
- "icon": "speed"
- },
- {
- "name": I18n.tr("Precipitation Chance"),
- "text": root.precipitationText,
- "icon": "rainy"
- },
- {
- "name": I18n.tr("Visibility"),
- "text": root.visibilityText,
- "icon": "wb_sunny"
- }
- ]
-
- color: isCurrent ? Theme.withAlpha(Theme.primary, 0.1) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- border.color: isCurrent ? Theme.withAlpha(Theme.primary, 0.3) : "transparent"
- border.width: isCurrent ? 1 : 0
-
- Column {
- anchors.centerIn: parent
- spacing: Theme.spacingXS
-
- StyledText {
- text: root.forecastData != null ? root.dateText : I18n.tr("Forecast Not Available")
- font.pixelSize: Theme.fontSizeSmall
- color: root.isCurrent ? Theme.primary : (root.forecastData ? Theme.surfaceText : Theme.outline)
- font.weight: root.isCurrent ? Font.Medium : Font.Normal
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- Row {
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Theme.spacingM
- visible: root.forecastData != null
-
- Column {
- spacing: Theme.spacingXS
-
- DankIcon {
- name: root.forecastData ? WeatherService.getWeatherIcon(root.forecastData.wCode || 0, root.forecastData.isDay ?? true) : "cloud"
- size: Theme.iconSize
- color: root.isCurrent ? Theme.primary : Theme.withAlpha(Theme.primary, 0.8)
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- StyledText {
- text: root.daily ? root.minMaxTempText : root.tempText
- font.pixelSize: Theme.fontSizeSmall
- color: root.isCurrent ? Theme.primary : Theme.surfaceText
- font.weight: Font.Medium
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- StyledText {
- text: root.feelsLikeText
- font.pixelSize: Theme.fontSizeSmall
- color: root.isCurrent ? Theme.primary : Theme.surfaceText
- font.weight: Font.Medium
- anchors.horizontalCenter: parent.horizontalCenter
- visible: !root.daily
- }
- }
-
- Column {
- id: detailsColumn
- spacing: 2
- visible: !root.dense
- width: implicitWidth
-
- states: [
- State {
- name: "dense"
- when: root.dense
- PropertyChanges {
- target: detailsColumn
- opacity: 0
- width: 0
- }
- }
- ]
-
- transitions: [
- Transition {
- NumberAnimation {
- properties: "opacity,width"
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- ]
-
- Repeater {
- model: root.values.length
- Row {
- spacing: 2
-
- DankIcon {
- name: root.values[index].icon
- size: 8
- color: Theme.withAlpha(Theme.surfaceText, 0.6)
- anchors.verticalCenter: parent.verticalCenter
- }
-
- StyledText {
- text: root.values[index].text
- font.pixelSize: Theme.fontSizeSmall - 2
- color: Theme.withAlpha(Theme.surfaceText, 0.6)
- anchors.verticalCenter: parent.verticalCenter
- }
- }
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WeatherTab.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WeatherTab.qml
deleted file mode 100644
index 21ea656..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/DankDash/WeatherTab.qml
+++ /dev/null
@@ -1,1124 +0,0 @@
-import QtQuick
-import QtQuick.Effects
-import QtQuick.Shapes
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Item {
- id: root
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- implicitWidth: SettingsData.showWeekNumber ? 736 : 700
- implicitHeight: 410
- property bool syncing: false
- property bool showHourly: false
- property bool available: WeatherService.weather.available
-
- function syncFrom(type) {
- if (!dailyLoader.item || !hourlyLoader.item)
- return;
- const hourlyList = hourlyLoader.item;
- const dailyList = dailyLoader.item;
- syncing = true;
-
- try {
- if (type === "hour") {
- const date = new Date();
- date.setHours(hourlyList.currentIndex);
- dateStepper.currentDate = date;
-
- dailyList.currentIndex = Math.max(0, Math.min((WeatherService.weather.forecast?.length ?? 1) - 1, WeatherService.calendarDayDifference((new Date()), date)));
- } else if (type === "day") {
- const date = new Date(dateStepper.currentDate);
- date.setMonth((new Date()).getMonth());
- date.setDate((new Date()).getDate() + dailyList.currentIndex);
- dateStepper.currentDate = date;
-
- const hourIndex = Math.max(0, Math.min((WeatherService.weather.hourlyForecast?.length ?? 1) - 1, WeatherService.calendarHourDifference((new Date()), date) + (new Date).getHours()));
- hourlyList.currentIndex = hourIndex;
- } else if (type === "date") {
- const date = dateStepper.currentDate;
- dailyList.currentIndex = Math.max(0, Math.min((WeatherService.weather.forecast?.length ?? 1) - 1, WeatherService.calendarDayDifference((new Date()), date)));
- hourlyList.currentIndex = Math.max(0, Math.min((WeatherService.weather.hourlyForecast?.length ?? 1) - 1, WeatherService.calendarHourDifference((new Date()), date) + (new Date()).getHours()));
- }
- } catch (e) {
- console.warn("Weather Date Sync Error:", e);
- }
-
- syncing = false;
- }
-
- readonly property string sunriseTimeText: {
- if (!WeatherService.weather.rawSunrise)
- return WeatherService.weather.sunrise || "";
- try {
- const date = new Date(WeatherService.weather.rawSunrise);
- const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP";
- return date.toLocaleTimeString(Qt.locale(), format);
- } catch (e) {
- return WeatherService.weather.sunrise || "";
- }
- }
-
- readonly property string sunsetTimeText: {
- if (!WeatherService.weather.rawSunset)
- return WeatherService.weather.sunset || "";
- try {
- const date = new Date(WeatherService.weather.rawSunset);
- const format = SettingsData.use24HourClock ? "HH:mm" : "h:mm AP";
- return date.toLocaleTimeString(Qt.locale(), format);
- } catch (e) {
- return WeatherService.weather.sunset || "";
- }
- }
-
- readonly property var heroMetrics: {
- SettingsData.useFahrenheit;
- SettingsData.windSpeedUnit;
- return [
- {
- "icon": "humidity_low",
- "label": I18n.tr("Humidity"),
- "value": WeatherService.formatPercent(WeatherService.weather.humidity) ?? "--"
- },
- {
- "icon": "air",
- "label": I18n.tr("Wind"),
- "value": WeatherService.formatSpeed(WeatherService.weather.wind) ?? "--"
- },
- {
- "icon": "speed",
- "label": I18n.tr("Pressure"),
- "value": WeatherService.formatPressure(WeatherService.weather.pressure) ?? "--"
- },
- {
- "icon": "rainy",
- "label": I18n.tr("Precipitation"),
- "value": (WeatherService.weather.precipitationProbability ?? 0) + "%"
- },
- {
- "icon": "wb_twilight",
- "label": I18n.tr("Sunrise"),
- "value": root.sunriseTimeText || "--"
- },
- {
- "icon": "bedtime",
- "label": I18n.tr("Sunset"),
- "value": root.sunsetTimeText || "--"
- }
- ];
- }
-
- Column {
- id: unavailableColumn
- anchors.centerIn: parent
- spacing: Theme.spacingL
- visible: !root.available
-
- DankIcon {
- name: "cloud_off"
- size: Theme.iconSize * 2
- color: Theme.withAlpha(Theme.surfaceText, 0.5)
- anchors.horizontalCenter: parent.horizontalCenter
- }
-
- Row {
- width: refreshButtonTwo.width + refreshText.width
- height: refreshButtonTwo.height
- spacing: Theme.spacingS
-
- StyledText {
- id: refreshText
- text: I18n.tr("No Weather Data Available")
- font.pixelSize: Theme.fontSizeLarge
- color: Theme.withAlpha(Theme.surfaceText, 0.7)
- anchors.verticalCenter: parent.verticalCenter
- }
-
- DankIcon {
- id: refreshButtonTwo
- name: "refresh"
- size: Theme.iconSize - 4
- color: Theme.withAlpha(Theme.surfaceText, 0.4)
- anchors.top: parent.top
- anchors.verticalCenter: parent.verticalCenter
-
- property bool isRefreshing: false
- enabled: !isRefreshing
-
- MouseArea {
- id: refreshButtonMouseAreaTwo
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: parent.enabled ? Qt.PointingHandCursor : Qt.ForbiddenCursor
- enabled: parent.enabled
-
- Timer {
- id: hoverDelayTwo
- interval: 300
- repeat: false
- onTriggered: {
- refreshButtonTooltipTwo.show(I18n.tr("Refresh Weather"), refreshButtonTwo, 0, 0, "left");
- }
- }
-
- onEntered: {
- hoverDelayTwo.restart();
- }
-
- onExited: {
- hoverDelayTwo.stop();
- refreshButtonTooltipTwo.hide();
- }
-
- onClicked: {
- refreshButtonTwo.isRefreshing = true;
- WeatherService.forceRefresh();
- refreshTimerTwo.restart();
- }
- }
-
- DankTooltipV2 {
- id: refreshButtonTooltipTwo
- }
-
- Timer {
- id: refreshTimerTwo
- interval: 2000
- onTriggered: refreshButtonTwo.isRefreshing = false
- }
-
- NumberAnimation on rotation {
- running: refreshButtonTwo.isRefreshing
- from: 0
- to: 360
- duration: 1000
- loops: Animation.Infinite
- }
- }
- }
- }
-
- Column {
- id: mainColumn
- anchors.fill: parent
- visible: root.available
- spacing: Theme.spacingS
-
- Rectangle {
- id: heroCard
- width: parent.width
- height: heroContent.height + Theme.spacingL * 2
- radius: Theme.cornerRadius
- color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- border.color: Theme.withAlpha(Theme.outline, 0.08)
- border.width: 1
-
- Column {
- id: heroContent
- x: Theme.spacingL
- y: Theme.spacingL
- width: parent.width - Theme.spacingL * 2
- spacing: Theme.spacingM
-
- Item {
- width: parent.width
- height: Math.max(heroLeft.height, heroMetricsGrid.height)
-
- Row {
- id: heroLeft
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- spacing: Theme.spacingL
-
- DankIcon {
- id: weatherIcon
- name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
- size: Theme.iconSize * 2
- color: Theme.primary
- anchors.verticalCenter: parent.verticalCenter
-
- layer.enabled: Theme.elevationEnabled
- layer.effect: MultiEffect {
- shadowEnabled: Theme.elevationEnabled
- shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel1)
- shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel1, 1)
- shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel1 && Theme.elevationLevel1.blurPx !== undefined ? Theme.elevationLevel1.blurPx : 4) / Theme.elevationBlurMax)) : 0
- blurMax: Theme.elevationBlurMax
- shadowColor: Theme.elevationShadowColor(Theme.elevationLevel1)
- shadowOpacity: Theme.elevationLevel1 && Theme.elevationLevel1.alpha !== undefined ? Theme.elevationLevel1.alpha : 0.2
- }
- }
-
- Column {
- id: tempColumn
- spacing: Theme.spacingXS
- anchors.verticalCenter: parent.verticalCenter
-
- Item {
- anchors.left: parent.left
- width: tempText.width + unitText.width + Theme.spacingXS
- height: tempText.height
-
- StyledText {
- id: tempText
- LayoutMirroring.enabled: false
- text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°"
- font.pixelSize: Theme.fontSizeXLarge + 8
- color: Theme.surfaceText
- font.weight: Font.Light
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- }
-
- StyledText {
- id: unitText
- LayoutMirroring.enabled: false
- text: SettingsData.useFahrenheit ? "F" : "C"
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.withAlpha(Theme.surfaceText, 0.7)
- anchors.left: tempText.right
- anchors.leftMargin: Theme.spacingXS
- anchors.verticalCenter: parent.verticalCenter
-
- MouseArea {
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (WeatherService.weather.available)
- SettingsData.set("useFahrenheit", !SettingsData.useFahrenheit);
- }
- enabled: WeatherService.weather.available
- }
- }
- }
-
- StyledText {
- text: WeatherService.getWeatherCondition(WeatherService.weather.wCode)
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.withAlpha(Theme.surfaceText, 0.7)
- anchors.left: parent.left
- }
-
- StyledText {
- property var feelsLike: SettingsData.useFahrenheit ? (WeatherService.weather.feelsLikeF || WeatherService.weather.tempF) : (WeatherService.weather.feelsLike || WeatherService.weather.temp)
- text: I18n.tr("Feels Like %1°", "weather feels like temperature").arg(feelsLike)
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.withAlpha(Theme.surfaceText, 0.5)
- anchors.left: parent.left
- }
-
- StyledText {
- text: WeatherService.weather.city || ""
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.withAlpha(Theme.surfaceText, 0.5)
- visible: text.length > 0
- anchors.left: parent.left
- }
- }
- }
-
- Grid {
- id: heroMetricsGrid
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- columns: 3
- columnSpacing: Theme.spacingXL
- rowSpacing: Theme.spacingS
-
- Repeater {
- model: root.heroMetrics
-
- Row {
- spacing: Theme.spacingXS
-
- DankIcon {
- name: modelData.icon
- size: Theme.iconSizeSmall - 2
- color: Theme.withAlpha(Theme.surfaceText, 0.5)
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Column {
- spacing: 2
-
- StyledText {
- text: modelData.label
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.withAlpha(Theme.surfaceText, 0.5)
- anchors.left: parent.left
- }
-
- StyledText {
- text: modelData.value
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.surfaceText
- anchors.left: parent.left
- }
- }
- }
- }
- }
- }
- }
- }
-
- Item {
- id: skyDateRow
- width: parent.width
- height: dateStepper.height
-
- Item {
- id: dateStepper
- height: dateStepperInner.height + Theme.spacingM * 2
- width: dateStepperInner.width
-
- property var currentDate: new Date()
-
- readonly property var changeDate: (magnitudeIndex, sign) => {
- switch (magnitudeIndex) {
- case 0:
- break;
- case 1:
- var newDate = new Date(dateStepper.currentDate);
- newDate.setMonth(dateStepper.currentDate.getMonth() + sign * 1);
- dateStepper.currentDate = newDate;
- break;
- case 2:
- dateStepper.currentDate = new Date(dateStepper.currentDate.getTime() + sign * 24 * 3600 * 1000);
- break;
- case 3:
- dateStepper.currentDate = new Date(dateStepper.currentDate.getTime() + sign * 3600 * 1000);
- break;
- case 4:
- dateStepper.currentDate = new Date(dateStepper.currentDate.getTime() + sign * 5 * 60 * 1000);
- break;
- }
- }
- readonly property var splitDate: Qt.formatDateTime(dateStepper.currentDate, SettingsData.use24HourClock ? "yyyy.MM.dd.HH.mm" : "yyyy.MM.dd.hh.mm.AP").split('.')
-
- Item {
- id: dateStepperInner
- anchors.horizontalCenter: parent.horizontalCenter
- anchors.verticalCenter: parent.verticalCenter
- readonly property var space: Theme.spacingXS
- width: yearStepper.width + monthStepper.width + dayStepper.width + hourStepper.width + minuteStepper.width + (suffix.visible ? suffix.width : 0) + 10.5 * space + 2 * dateStepperInnerPadding.width
- height: Math.max(yearStepper.height, monthStepper.height, dayStepper.height, hourStepper.height, minuteStepper.height)
-
- Item {
- id: dateStepperInnerPadding
- width: dateResetButton.width
- }
-
- DankNumberStepper {
- id: yearStepper
- anchors.left: dateStepperInnerPadding.right
- anchors.leftMargin: parent.space
- width: implicitWidth
- text: dateStepper.splitDate[0]
- }
-
- DankNumberStepper {
- id: monthStepper
- width: implicitWidth
- anchors.left: yearStepper.right
- anchors.leftMargin: parent.space
- text: dateStepper.splitDate[1]
- onIncrement: () => dateStepper.changeDate(1, +1)
- onDecrement: () => dateStepper.changeDate(1, -1)
- }
-
- DankNumberStepper {
- id: dayStepper
- width: implicitWidth
- anchors.left: monthStepper.right
- anchors.leftMargin: parent.space
- text: dateStepper.splitDate[2]
- onIncrement: () => dateStepper.changeDate(2, +1)
- onDecrement: () => dateStepper.changeDate(2, -1)
- }
-
- DankNumberStepper {
- id: hourStepper
- width: implicitWidth
- anchors.left: dayStepper.right
- anchors.leftMargin: 1.5 * parent.space
- text: dateStepper.splitDate[3]
- onIncrement: () => dateStepper.changeDate(3, +1)
- onDecrement: () => dateStepper.changeDate(3, -1)
- }
-
- DankNumberStepper {
- id: minuteStepper
- width: implicitWidth
- anchors.left: hourStepper.right
- anchors.leftMargin: parent.space
- text: dateStepper.splitDate[4]
- onIncrement: () => dateStepper.changeDate(4, +1)
- onDecrement: () => dateStepper.changeDate(4, -1)
- }
-
- Item {
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: yearStepper.right
- anchors.right: monthStepper.left
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- anchors.horizontalCenter: parent.horizontalCenter
- text: "-"
- }
- }
- Item {
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: monthStepper.right
- anchors.right: dayStepper.left
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- anchors.horizontalCenter: parent.horizontalCenter
- text: "-"
- }
- }
- Item {
- anchors.verticalCenter: parent.verticalCenter
- anchors.left: hourStepper.right
- anchors.right: minuteStepper.left
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- anchors.horizontalCenter: parent.horizontalCenter
- text: ":"
- }
- }
- StyledText {
- id: suffix
- visible: !SettingsData.use24HourClock
- anchors.verticalCenter: minuteStepper.verticalCenter
- anchors.left: minuteStepper.right
- anchors.leftMargin: 2 * parent.space
- isMonospace: true
- text: dateStepper.splitDate[5] ?? ""
- font.pixelSize: Theme.fontSizeSmall
- }
- DankActionButton {
- id: dateResetButton
- anchors.verticalCenter: parent.verticalCenter
- anchors.right: parent.right
- enabled: Math.abs(dateStepper.currentDate - new Date()) > 1000
- iconColor: enabled ? Theme.blendAlpha(Theme.surfaceText, 0.5) : "transparent"
- iconSize: 12
- buttonSize: 20
- iconName: "replay"
- onClicked: {
- dateStepper.currentDate = new Date();
- }
- }
- }
-
- onCurrentDateChanged: if (!syncing)
- root.syncFrom("date")
- }
-
- Rectangle {
- id: skyBox
- anchors.left: dateStepper.right
- anchors.leftMargin: Theme.spacingM
- anchors.right: parent.right
- height: parent.height
-
- LayoutMirroring.enabled: false
- LayoutMirroring.childrenInherit: true
-
- property var backgroundOpacity: 0.3
- property var sunTime: WeatherService.getCurrentSunTime(dateStepper.currentDate)
- property var periodIndex: sunTime?.periodIndex
- property var periodPercent: sunTime?.periodPercent
- property var blackColor: Theme.blend(Theme.surface, Qt.rgba(0, 0, 0, 255), 0.2)
- property var redColor: Theme.secondary
- property var blueColor: Theme.primary
- function blackBlue(r) {
- return Theme.blend(blackColor, blueColor, r);
- }
- property var topColor: {
- const colorMap = [blackColor, Theme.withAlpha(blackBlue(0.0), 0.8), Theme.withAlpha(blackBlue(0.2), 0.7), Theme.withAlpha(blackBlue(0.5), 0.6), Theme.withAlpha(blackBlue(0.7), 0.6), Theme.withAlpha(blackBlue(0.9), 0.6), Theme.withAlpha(blackBlue(1.0), 0.6), Theme.withAlpha(blackBlue(0.9), 0.6), Theme.withAlpha(blackBlue(0.7), 0.6), Theme.withAlpha(blackBlue(0.5), 0.6), Theme.withAlpha(blackBlue(0.2), 0.7), Theme.withAlpha(blackBlue(0.0), 0.8), blackColor, blackColor];
- const index = periodIndex ?? 0;
- return Theme.blend(colorMap[index], colorMap[index + 1], periodPercent ?? 0);
- }
- property var sunColor: {
- const colorMap = [Theme.withAlpha(redColor, 0.05), Theme.withAlpha(redColor, 0.1), Theme.withAlpha(redColor, 0.3), Theme.withAlpha(redColor, 0.4), Theme.withAlpha(redColor, 0.5), Theme.withAlpha(blueColor, 0.2), Theme.withAlpha(blueColor, 0.0), Theme.withAlpha(blueColor, 0.2), Theme.withAlpha(redColor, 0.5), Theme.withAlpha(redColor, 0.4), Theme.withAlpha(redColor, 0.3), Theme.withAlpha(redColor, 0.1), Theme.withAlpha(redColor, 0.05), Theme.withAlpha(redColor, 0.0)];
- const index = periodIndex ?? 0;
- return Theme.blend(colorMap[index], colorMap[index + 1], periodPercent ?? 0);
- }
-
- color: "transparent"
-
- Rectangle {
- anchors.fill: parent
- opacity: skyBox.backgroundOpacity
-
- gradient: Gradient {
- GradientStop {
- position: 0.0
- color: Theme.withAlpha(skyBox.blackColor, 0.0)
- }
- GradientStop {
- position: 0.05
- color: skyBox.topColor
- }
- GradientStop {
- position: 0.3
- color: skyBox.topColor
- }
- GradientStop {
- position: 0.5
- color: skyBox.topColor
- }
- GradientStop {
- position: 0.501
- color: skyBox.blackColor
- }
- GradientStop {
- position: 0.9
- color: skyBox.blackColor
- }
- GradientStop {
- position: 1.0
- color: Theme.withAlpha(skyBox.blackColor, 0.0)
- }
- }
- }
-
- property var currentDate: dateStepper.currentDate
- property var hMargin: 0
- property var vMargin: Theme.spacingM
- property var effectiveHeight: skyBox.height - 2 * vMargin
- property var effectiveWidth: skyBox.width - 2 * hMargin
-
- StyledText {
- text: parent.sunTime?.period ?? ""
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.withAlpha(Theme.surfaceText, 0.7)
- x: 0
- y: 0
- }
-
- Shape {
- id: skyShape
- anchors.left: parent.left
- anchors.top: parent.top
- anchors.right: parent.right
- height: parent.height / 2
- opacity: skyBox.backgroundOpacity
-
- ShapePath {
- strokeColor: "transparent"
- fillGradient: RadialGradient {
- centerX: skyBox.hMargin + sun.x + sun.width / 2
- centerY: skyBox.vMargin + sun.y + 30
- centerRadius: {
- const a = Math.abs((skyBox.sunTime?.dayPercent ?? 0) - 0.5);
- const out = 200 * (0.5 - a * a);
- return out;
- }
- focalX: skyBox.hMargin + sun.x + sun.width / 2
- focalY: skyBox.vMargin + sun.y
- GradientStop {
- position: 0
- color: skyBox.sunColor
- }
- GradientStop {
- position: 0.3
- color: Theme.blendAlpha(skyBox.sunColor, 0.5)
- }
- GradientStop {
- position: 1
- color: "transparent"
- }
- }
- PathLine {
- x: 0
- y: 0
- }
- PathLine {
- x: skyShape.width
- y: 0
- }
- PathLine {
- x: skyShape.width
- y: skyShape.height
- }
- PathLine {
- x: 0
- y: skyShape.height
- }
- }
-
- ShapePath {
- strokeColor: "transparent"
- fillGradient: RadialGradient {
- centerX: sun.x
- centerY: sun.y
- centerRadius: 500
- focalX: centerX
- focalY: centerY + 0.99 * (centerRadius - focalRadius)
- focalRadius: 10
- GradientStop {
- position: 0
- color: skyBox.sunColor
- }
- GradientStop {
- position: 0.45
- color: skyBox.sunColor
- }
- GradientStop {
- position: 0.55
- color: "transparent"
- }
- GradientStop {
- position: 1
- color: "transparent"
- }
- }
- PathLine {
- x: 0
- y: 0
- }
- PathLine {
- x: skyShape.width
- y: 0
- }
- PathLine {
- x: skyShape.width
- y: skyShape.height
- }
- PathLine {
- x: 0
- y: skyShape.height
- }
- }
- }
-
- Canvas {
- id: ecliptic
- anchors.fill: parent
- property var points: WeatherService.getEcliptic(dateStepper.currentDate)
-
- function getX(index) {
- return points[index].h * skyBox.effectiveWidth + skyBox.hMargin;
- }
- function getY(index) {
- return points[index].v * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 + skyBox.vMargin;
- }
-
- onPointsChanged: requestPaint()
-
- onPaint: {
- var ctx = getContext("2d");
- ctx.clearRect(0, 0, width, height);
- if (!points || points.length === 0)
- return;
- ctx.beginPath();
- ctx.moveTo(getX(0), getY(0));
- for (var i = 1; i < points.length; i++) {
- ctx.lineTo(getX(i), getY(i));
- }
- ctx.strokeStyle = Theme.withAlpha(Theme.outline, 0.2);
- ctx.stroke();
- }
- }
-
- property real latitude: WeatherService.getLocation()?.latitude ?? 0
- property real sunDeclination: WeatherService.getSunDeclination(dateStepper.currentDate)
-
- readonly property bool solarNoonIsSouth: latitude > sunDeclination
-
- StyledText {
- id: middle
- text: skyBox.solarNoonIsSouth ? "S" : "N"
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.primary
- x: skyBox.width / 2 - middle.width / 2
- y: skyBox.height / 2 - middle.height / 2
- }
-
- StyledText {
- id: left
- text: skyBox.solarNoonIsSouth ? "E" : "W"
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.primary
- x: skyBox.width / 4 - left.width / 2
- y: skyBox.height / 2 - left.height / 2
- }
-
- StyledText {
- id: right
- text: skyBox.solarNoonIsSouth ? "W" : "E"
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.primary
- x: 3 * skyBox.width / 4 - right.width / 2
- y: skyBox.height / 2 - right.height / 2
- }
-
- Rectangle {
- height: 1
- anchors.leftMargin: Theme.spacingS
- anchors.rightMargin: Theme.spacingS
- anchors.left: right.right
- anchors.right: skyBox.right
- anchors.verticalCenter: middle.verticalCenter
- color: Theme.outline
- }
-
- Rectangle {
- height: 1
- anchors.leftMargin: Theme.spacingS
- anchors.rightMargin: Theme.spacingS
- anchors.left: middle.right
- anchors.right: right.left
- anchors.verticalCenter: middle.verticalCenter
- color: Theme.outline
- }
-
- Rectangle {
- height: 1
- anchors.leftMargin: Theme.spacingS
- anchors.rightMargin: Theme.spacingS
- anchors.left: left.right
- anchors.right: middle.left
- anchors.verticalCenter: middle.verticalCenter
- color: Theme.outline
- }
-
- Rectangle {
- height: 1
- anchors.leftMargin: Theme.spacingS
- anchors.rightMargin: Theme.spacingS
- anchors.left: skyBox.left
- anchors.right: left.left
- anchors.verticalCenter: middle.verticalCenter
- color: Theme.outline
- }
-
- DankNFIcon {
- id: moonPhase
- name: WeatherService.getMoonPhase(skyBox.currentDate) || ""
- size: Theme.fontSizeXLarge
- color: Theme.withAlpha(Theme.surfaceText, 0.7)
- rotation: (WeatherService.getMoonAngle(skyBox.currentDate) || 0) / Math.PI * 180
- visible: !!pos
-
- property var pos: WeatherService.getSkyArcPosition(skyBox.currentDate, false)
- x: (pos?.h ?? 0) * skyBox.effectiveWidth - (moonPhase.width / 2) + skyBox.hMargin
- y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (moonPhase.height / 2) + skyBox.vMargin
-
- layer.enabled: Theme.elevationEnabled
- layer.effect: MultiEffect {
- shadowEnabled: Theme.elevationEnabled
- shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel2)
- shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel2, 4)
- shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel2 && Theme.elevationLevel2.blurPx !== undefined ? Theme.elevationLevel2.blurPx : 8) / Theme.elevationBlurMax)) : 0
- blurMax: Theme.elevationBlurMax
- shadowColor: Theme.elevationShadowColor(Theme.elevationLevel2)
- }
- }
-
- DankIcon {
- id: sun
- name: "light_mode"
- size: Theme.fontSizeXLarge
- color: Theme.primary
- visible: !!pos
-
- property var pos: WeatherService.getSkyArcPosition(skyBox.currentDate, true)
- x: (pos?.h ?? 0) * skyBox.effectiveWidth - (sun.width / 2) + skyBox.hMargin
- y: (pos?.v ?? 0) * -(skyBox.effectiveHeight / 2) + skyBox.effectiveHeight / 2 - (sun.height / 2) + skyBox.vMargin
-
- layer.enabled: Theme.elevationEnabled
- layer.effect: MultiEffect {
- shadowEnabled: Theme.elevationEnabled
- shadowHorizontalOffset: Theme.elevationOffsetX(Theme.elevationLevel2)
- shadowVerticalOffset: Theme.elevationOffsetY(Theme.elevationLevel2, 4)
- shadowBlur: Theme.elevationEnabled ? Math.max(0, Math.min(1, (Theme.elevationLevel2 && Theme.elevationLevel2.blurPx !== undefined ? Theme.elevationLevel2.blurPx : 8) / Theme.elevationBlurMax)) : 0
- blurMax: Theme.elevationBlurMax
- shadowColor: Theme.elevationShadowColor(Theme.elevationLevel2)
- }
- }
- }
- }
-
- Item {
- id: chipsRow
- width: parent.width
- height: forecastChips.height
-
- DankFilterChips {
- id: forecastChips
- anchors.left: parent.left
- anchors.verticalCenter: parent.verticalCenter
- model: [I18n.tr("Daily"), I18n.tr("Hourly")]
- currentIndex: root.showHourly ? 1 : 0
- showCheck: false
- showCounts: false
- onSelectionChanged: index => {
- root.showHourly = index === 1;
- }
- }
-
- DankActionButton {
- id: denseButton
- anchors.right: refreshButton.left
- anchors.rightMargin: Theme.spacingXS
- anchors.verticalCenter: parent.verticalCenter
- visible: root.showHourly && hourlyLoader.item !== null
- iconName: SessionData.weatherHourlyDetailed ? "tile_large" : "tile_medium"
- onClicked: SessionData.setWeatherHourlyDetailed(!SessionData.weatherHourlyDetailed)
- }
-
- DankIcon {
- id: refreshButton
- name: "refresh"
- size: Theme.iconSize - 4
- color: Theme.withAlpha(Theme.surfaceText, 0.4)
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
-
- property bool isRefreshing: false
- enabled: !isRefreshing
-
- MouseArea {
- id: refreshButtonMouseArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: parent.enabled ? Qt.PointingHandCursor : Qt.ForbiddenCursor
- enabled: parent.enabled
-
- Timer {
- id: hoverDelay
- interval: 300
- repeat: false
- onTriggered: {
- refreshButtonTooltip.show(I18n.tr("Refresh Weather"), refreshButton, 0, 0, "left");
- }
- }
-
- onEntered: {
- hoverDelay.restart();
- }
-
- onExited: {
- hoverDelay.stop();
- refreshButtonTooltip.hide();
- }
-
- onClicked: {
- refreshButton.isRefreshing = true;
- WeatherService.forceRefresh();
- refreshTimer.restart();
- }
- }
-
- DankTooltipV2 {
- id: refreshButtonTooltip
- }
-
- Timer {
- id: refreshTimer
- interval: 2000
- onTriggered: refreshButton.isRefreshing = false
- }
-
- NumberAnimation on rotation {
- running: refreshButton.isRefreshing
- from: 0
- to: 360
- duration: 1000
- loops: Animation.Infinite
- }
- }
- }
-
- Item {
- width: parent.width
- height: root.height - heroCard.height - skyDateRow.height - chipsRow.height - mainColumn.spacing * 3
-
- Loader {
- id: dailyLoader
- anchors.fill: parent
- sourceComponent: dailyComponent
- active: root.visible && root.available
- visible: !root.showHourly
- asynchronous: true
- opacity: 0
- onLoaded: {
- root.syncing = true;
- item.currentIndex = item.initialIndex;
- item.positionViewAtIndex(item.initialIndex, ListView.SnapPosition);
- root.syncing = false;
- opacity = 1;
- }
- }
-
- Loader {
- id: hourlyLoader
- anchors.fill: parent
- sourceComponent: hourlyComponent
- active: root.visible && root.available
- visible: root.showHourly
- asynchronous: true
- opacity: 0
- onLoaded: {
- root.syncing = true;
- item.currentIndex = item.initialIndex;
- item.positionViewAtIndex(item.initialIndex, ListView.SnapPosition);
- root.syncing = false;
- opacity = 1;
- }
- }
- }
- }
-
- Component {
- id: hourlyComponent
- ListView {
- id: hourlyList
- anchors.fill: parent
- orientation: ListView.Horizontal
- spacing: Theme.spacingS
- clip: true
- snapMode: ListView.SnapToItem
- highlightRangeMode: ListView.StrictlyEnforceRange
- highlightMoveDuration: 0
- interactive: true
-
- property var cardHeight: height
- property var cardWidth: ((hourlyList.width + hourlyList.spacing) / hourlyList.visibleCount) - hourlyList.spacing
- property int initialIndex: (new Date()).getHours()
- property bool dense: !SessionData.weatherHourlyDetailed
- property int visibleCount: dense ? 10 : 5
-
- model: WeatherService.weather.hourlyForecast?.length ?? 0
-
- delegate: WeatherForecastCard {
- width: hourlyList.cardWidth
- height: hourlyList.cardHeight
- dense: hourlyList.dense
- daily: false
-
- date: {
- const d = new Date();
- d.setHours(index);
- return d;
- }
- forecastData: WeatherService.weather.hourlyForecast[index]
- }
-
- onCurrentIndexChanged: if (!syncing)
- root.syncFrom("hour")
-
- states: [
- State {
- name: "denseState"
- when: hourlyList.dense
- PropertyChanges {
- target: hourlyList
- visibleCount: 10
- }
- },
- State {
- name: "normalState"
- when: !hourlyList.dense
- PropertyChanges {
- target: hourlyList
- visibleCount: 5
- }
- }
- ]
-
- transitions: [
- Transition {
- NumberAnimation {
- properties: "visibleCount"
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- ]
-
- MouseArea {
- anchors.fill: parent
- onWheel: wheel => {
- if (wheel.modifiers & Qt.ShiftModifier) {
- if (wheel.angleDelta.y % 120 == 0 && wheel.angleDelta.x == 0) {
- const newIndex = hourlyList.currentIndex - Math.sign(wheel.angleDelta.y);
- if (newIndex < hourlyList.model && newIndex >= 0) {
- hourlyList.currentIndex = newIndex;
- wheel.accepted = true;
- return;
- }
- }
- }
- wheel.accepted = false;
- }
- }
- }
- }
-
- Component {
- id: dailyComponent
- ListView {
- id: dailyList
- anchors.fill: parent
- orientation: ListView.Horizontal
- spacing: Theme.spacingS
- clip: true
- snapMode: ListView.SnapToItem
- highlightRangeMode: ListView.StrictlyEnforceRange
- highlightMoveDuration: 0
- interactive: true
-
- property var cardHeight: height
- property var cardWidth: ((dailyList.width + dailyList.spacing) / dailyList.visibleCount) - dailyList.spacing
- property int initialIndex: 0
- property bool dense: false
- property int visibleCount: 7
-
- model: WeatherService.weather.forecast?.length ?? 0
-
- delegate: WeatherForecastCard {
- width: dailyList.cardWidth
- height: dailyList.cardHeight
- dense: true
- daily: true
-
- date: {
- const date = new Date();
- date.setDate(date.getDate() + index);
- return date;
- }
- forecastData: WeatherService.weather.forecast[index]
- }
-
- onCurrentIndexChanged: if (!syncing)
- root.syncFrom("day")
-
- MouseArea {
- anchors.fill: parent
- onWheel: wheel => {
- if (wheel.modifiers & Qt.ShiftModifier) {
- if (wheel.angleDelta.y % 120 == 0 && wheel.angleDelta.x == 0) {
- const newIndex = dailyList.currentIndex - Math.sign(wheel.angleDelta.y);
- if (newIndex < dailyList.model && newIndex >= 0) {
- dailyList.currentIndex = newIndex;
- wheel.accepted = true;
- return;
- }
- }
- }
- wheel.accepted = false;
- }
- }
- }
- }
-}