1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-10 15:32:52 -05:00

Animation improvements, fix SysTray

This commit is contained in:
bbedward
2025-07-14 13:50:00 -04:00
parent d5d45b11c3
commit fff7dace3b
9 changed files with 255 additions and 116 deletions

View File

@@ -470,7 +470,6 @@ PanelWindow {
source: parent.entryType === "image" && parent.entryId ? "file://" + parent.tempImagePath : "" source: parent.entryType === "image" && parent.entryId ? "file://" + parent.tempImagePath : ""
Component.onCompleted: { Component.onCompleted: {
console.log("Image preview initializing for entry:", parent.entryId, "path:", parent.tempImagePath)
if (parent.entryType === "image" && parent.entryId) { if (parent.entryType === "image" && parent.entryId) {
// Simple approach: use shell redirection to write to file // Simple approach: use shell redirection to write to file
imageDecodeProcess.entryId = parent.entryId imageDecodeProcess.entryId = parent.entryId
@@ -482,11 +481,8 @@ PanelWindow {
} }
onStatusChanged: { onStatusChanged: {
console.log("Image preview status changed:", status, "for path:", source)
if (status === Image.Error) { if (status === Image.Error) {
console.warn("Failed to load image from:", source) console.warn("Failed to load clipboard image from:", source)
} else if (status === Image.Ready) {
console.log("Successfully loaded image:", source)
} }
} }
@@ -790,16 +786,12 @@ PanelWindow {
property var imagePreview: null property var imagePreview: null
onExited: (exitCode) => { onExited: (exitCode) => {
console.log("Image decode process exited with code:", exitCode, "for entry:", entryId)
if (exitCode === 0 && imagePreview && tempPath) { if (exitCode === 0 && imagePreview && tempPath) {
console.log("Image decoded successfully to:", tempPath)
// Force the Image component to reload // Force the Image component to reload
Qt.callLater(function() { Qt.callLater(function() {
imagePreview.source = "" imagePreview.source = ""
imagePreview.source = "file://" + tempPath imagePreview.source = "file://" + tempPath
}) })
} else {
console.warn("Failed to decode clipboard image for entry:", entryId)
} }
} }

View File

@@ -34,14 +34,7 @@ PanelWindow {
Rectangle { Rectangle {
width: Math.min(600, parent.width - Theme.spacingL * 2) width: Math.min(600, parent.width - Theme.spacingL * 2)
height: { height: controlCenterPopup.powerOptionsExpanded ? 570 : 500
let baseHeight = Math.min(500, parent.height - Theme.barHeight - Theme.spacingS * 2)
// Expand container when power menu is open
if (controlCenterPopup.powerOptionsExpanded) {
baseHeight += 70 // Extra space for power options
}
return baseHeight
}
x: Math.max(Theme.spacingL, parent.width - width - Theme.spacingL) x: Math.max(Theme.spacingL, parent.width - width - Theme.spacingL)
y: Theme.barHeight + Theme.spacingXS y: Theme.barHeight + Theme.spacingXS
color: Theme.surfaceContainer color: Theme.surfaceContainer
@@ -49,8 +42,61 @@ PanelWindow {
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 1 border.width: 1
// TopBar dropdown animation - optimized for performance
transform: [
Scale {
id: scaleTransform
origin.x: parent.width // Scale from top-right corner
origin.y: 0
xScale: root.controlCenterVisible ? 1.0 : 0.95
yScale: root.controlCenterVisible ? 1.0 : 0.8
},
Translate {
id: translateTransform
x: root.controlCenterVisible ? 0 : 15 // Slide slightly left when hidden
y: root.controlCenterVisible ? 0 : -30
}
]
// Single coordinated animation for better performance
states: [
State {
name: "visible"
when: root.controlCenterVisible
PropertyChanges { target: scaleTransform; xScale: 1.0; yScale: 1.0 }
PropertyChanges { target: translateTransform; x: 0; y: 0 }
},
State {
name: "hidden"
when: !root.controlCenterVisible
PropertyChanges { target: scaleTransform; xScale: 0.95; yScale: 0.8 }
PropertyChanges { target: translateTransform; x: 15; y: -30 }
}
]
// Power menu height animation
Behavior on height {
NumberAnimation {
duration: Theme.shortDuration // Faster for height changes
easing.type: Theme.standardEasing
}
}
transitions: [
Transition {
from: "*"; to: "*"
ParallelAnimation {
NumberAnimation {
targets: [scaleTransform, translateTransform]
properties: "xScale,yScale,x,y"
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
]
opacity: root.controlCenterVisible ? 1.0 : 0.0 opacity: root.controlCenterVisible ? 1.0 : 0.0
scale: root.controlCenterVisible ? 1.0 : 0.85
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {
@@ -59,19 +105,7 @@ PanelWindow {
} }
} }
Behavior on scale { // Height animation handled by states below for better performance
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on height {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Column { Column {
anchors.fill: parent anchors.fill: parent
@@ -115,11 +149,12 @@ PanelWindow {
} }
// Circular clipping container for profile image // Circular clipping container for profile image
ClippingRectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
anchors.margins: 1 anchors.margins: 1
radius: 31 radius: 31
antialiasing: true color: "transparent"
clip: true
visible: parent.hasImage visible: parent.hasImage
Image { Image {
@@ -135,14 +170,14 @@ PanelWindow {
return Prefs.profileImage return Prefs.profileImage
} }
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
smooth: true smooth: false // Disable smooth scaling during animations for performance
asynchronous: true asynchronous: true
mipmap: true mipmap: false // Disable mipmap for better performance
cache: false cache: true // Enable caching to prevent reloads
onStatusChanged: { // Optimize source size to prevent unnecessary scaling
console.log("Control Center profile image status:", status, "source:", source) sourceSize.width: 64
} sourceSize.height: 64
} }
} }
@@ -322,7 +357,7 @@ PanelWindow {
} }
} }
// Animated Collapsible Power Options (moved here for better integration) // Animated Collapsible Power Options (optimized)
Rectangle { Rectangle {
width: parent.width width: parent.width
height: controlCenterPopup.powerOptionsExpanded ? 60 : 0 height: controlCenterPopup.powerOptionsExpanded ? 60 : 0
@@ -333,38 +368,25 @@ PanelWindow {
opacity: controlCenterPopup.powerOptionsExpanded ? 1.0 : 0.0 opacity: controlCenterPopup.powerOptionsExpanded ? 1.0 : 0.0
clip: true clip: true
// Single coordinated animation for power options
Behavior on height { Behavior on height {
NumberAnimation { NumberAnimation {
duration: Theme.mediumDuration duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.standardEasing
} }
} }
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {
duration: Theme.mediumDuration duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.standardEasing
}
}
Behavior on border.width {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
} }
} }
Row { Row {
anchors.centerIn: parent anchors.centerIn: parent
spacing: Theme.spacingL spacing: Theme.spacingL
opacity: controlCenterPopup.powerOptionsExpanded ? 1.0 : 0.0 visible: controlCenterPopup.powerOptionsExpanded
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
// Logout // Logout
Rectangle { Rectangle {
@@ -611,29 +633,14 @@ PanelWindow {
// Tab content area // Tab content area
Rectangle { Rectangle {
width: parent.width width: parent.width
height: { height: controlCenterPopup.powerOptionsExpanded ? 240 : 300
// More generous height calculation - use most of the available space
let baseHeight = parent.height
// Subtract only the essential fixed elements
baseHeight -= 90 + Theme.spacingL // User header + spacing
baseHeight -= 40 + Theme.spacingM // Tab buttons + spacing
baseHeight -= Theme.spacingM // Bottom spacing
// Subtract power options height when expanded
if (controlCenterPopup.powerOptionsExpanded) {
baseHeight -= 60 + Theme.spacingL
}
return Math.max(300, baseHeight) // Higher minimum height for better content display
}
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08) color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08)
Behavior on height { Behavior on height {
NumberAnimation { NumberAnimation {
duration: Theme.mediumDuration duration: Theme.shortDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.standardEasing
} }
} }

View File

@@ -50,17 +50,55 @@ PanelWindow {
border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12) border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.12)
border.width: 1 border.width: 1
opacity: root.notificationHistoryVisible ? 1.0 : 0.0 // TopBar dropdown animation - slide down from bar (consistent with other TopBar widgets)
scale: root.notificationHistoryVisible ? 1.0 : 0.85 transform: [
Scale {
id: scaleTransform
origin.x: parent.width // Scale from top-right corner
origin.y: 0
xScale: root.notificationHistoryVisible ? 1.0 : 0.95
yScale: root.notificationHistoryVisible ? 1.0 : 0.8
},
Translate {
id: translateTransform
x: root.notificationHistoryVisible ? 0 : 15 // Slide slightly left when hidden
y: root.notificationHistoryVisible ? 0 : -30
}
]
Behavior on opacity { opacity: root.notificationHistoryVisible ? 1.0 : 0.0
// Single coordinated animation for better performance
states: [
State {
name: "visible"
when: root.notificationHistoryVisible
PropertyChanges { target: scaleTransform; xScale: 1.0; yScale: 1.0 }
PropertyChanges { target: translateTransform; x: 0; y: 0 }
},
State {
name: "hidden"
when: !root.notificationHistoryVisible
PropertyChanges { target: scaleTransform; xScale: 0.95; yScale: 0.8 }
PropertyChanges { target: translateTransform; x: 15; y: -30 }
}
]
transitions: [
Transition {
from: "*"; to: "*"
ParallelAnimation {
NumberAnimation { NumberAnimation {
targets: [scaleTransform, translateTransform]
properties: "xScale,yScale,x,y"
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing
} }
} }
}
]
Behavior on scale { Behavior on opacity {
NumberAnimation { NumberAnimation {
duration: Theme.mediumDuration duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing easing.type: Theme.emphasizedEasing

View File

@@ -41,16 +41,50 @@ PanelWindow {
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
border.width: 0 // Remove border completely border.width: 0 // Remove border completely
opacity: root.showNotificationPopup ? 1.0 : 0.0 // TopBar dropdown animation - slide down from bar
transform: [
// Transform for swipe animations Translate {
transform: Translate {
id: swipeTransform id: swipeTransform
x: 0 x: 0
y: root.showNotificationPopup ? 0 : -30
Behavior on y {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
},
Scale {
id: scaleTransform
origin.x: parent.width
origin.y: 0
xScale: root.showNotificationPopup ? 1.0 : 0.95
yScale: root.showNotificationPopup ? 1.0 : 0.8
Behavior on xScale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
} }
Behavior on yScale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
]
opacity: root.showNotificationPopup ? 1.0 : 0.0
Behavior on opacity { Behavior on opacity {
NumberAnimation { duration: 200; easing.type: Easing.OutQuad } NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
} }
// Drag area for swipe gestures // Drag area for swipe gestures

View File

@@ -52,8 +52,51 @@ PanelWindow {
border.width: 1 border.width: 1
clip: true clip: true
// TopBar dropdown animation - slide down from bar
transform: [
Scale {
id: scaleTransform
origin.x: parent.width * 0.85 // Scale from top-right
origin.y: 0
xScale: processDropdown.isVisible ? 1.0 : 0.95
yScale: processDropdown.isVisible ? 1.0 : 0.8
Behavior on xScale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on yScale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
},
Translate {
id: translateTransform
x: processDropdown.isVisible ? 0 : 20
y: processDropdown.isVisible ? 0 : -30
Behavior on x {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on y {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
]
opacity: processDropdown.isVisible ? 1.0 : 0.0 opacity: processDropdown.isVisible ? 1.0 : 0.0
scale: processDropdown.isVisible ? 1.0 : 0.85
// Add shadow effect // Add shadow effect
layer.enabled: true layer.enabled: true
@@ -66,7 +109,6 @@ PanelWindow {
shadowOpacity: processDropdown.isVisible ? 0.15 : 0 shadowOpacity: processDropdown.isVisible ? 0.15 : 0
} }
// Smooth animations
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {
duration: Theme.mediumDuration duration: Theme.mediumDuration
@@ -74,13 +116,6 @@ PanelWindow {
} }
} }
Behavior on scale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
// Click inside dropdown - consume the event // Click inside dropdown - consume the event
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent

View File

@@ -320,12 +320,23 @@ PanelWindow {
shadowColor: Qt.rgba(0, 0, 0, 0.3) shadowColor: Qt.rgba(0, 0, 0, 0.3)
shadowOpacity: 0.3 shadowOpacity: 0.3
} }
transform: Scale { origin.x: width/2; origin.y: height/2; xScale: spotlightOpen?1:0.9; yScale: spotlightOpen?1:0.9; // Center-screen fade with subtle scale
Behavior on xScale { NumberAnimation { duration: Theme.mediumDuration; easing.type: Easing.OutBack; easing.overshoot:1.1 } } opacity: spotlightOpen ? 1.0 : 0.0
Behavior on yScale { NumberAnimation { duration: Theme.mediumDuration; easing.type: Easing.OutBack; easing.overshoot:1.1 } } scale: spotlightOpen ? 1.0 : 0.96
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
Behavior on scale {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
} }
opacity: spotlightOpen?1:0
Behavior on opacity { NumberAnimation { duration: Theme.mediumDuration; easing.type: Theme.emphasizedEasing } }
Column { Column {
anchors.fill: parent; anchors.margins: Theme.spacingXL; spacing: Theme.spacingL anchors.fill: parent; anchors.margins: Theme.spacingXL; spacing: Theme.spacingL

View File

@@ -64,10 +64,7 @@ Rectangle {
} }
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
if (trayItem.hasMenu) { if (trayItem.hasMenu) {
console.log("Right-click detected, showing menu for:", trayItem.title || "Unknown")
customTrayMenu.showMenu(mouse.x, mouse.y) customTrayMenu.showMenu(mouse.x, mouse.y)
} else {
console.log("No menu available for:", trayItem.title || "Unknown")
} }
} }
} }

View File

@@ -65,6 +65,7 @@ PanelWindow {
property real trayMenuY: 0 property real trayMenuY: 0
// Proxy objects for external connections // Proxy objects for external connections
QtObject { QtObject {
@@ -231,13 +232,14 @@ PanelWindow {
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
visible: Prefs.showSystemTray visible: Prefs.showSystemTray
onMenuRequested: (menu, item, x, y) => { onMenuRequested: (menu, item, x, y) => {
topBar.currentTrayMenu = menu if (topBar.shellRoot) {
topBar.currentTrayItem = item topBar.shellRoot.currentTrayMenu = menu
topBar.trayMenuX = rightSection.x + rightSection.width - 400 - Theme.spacingL topBar.shellRoot.currentTrayItem = item
topBar.trayMenuY = Theme.barHeight + Theme.spacingS topBar.shellRoot.trayMenuX = rightSection.x + rightSection.width - 400 - Theme.spacingL
console.log("Showing menu at:", topBar.trayMenuX, topBar.trayMenuY) topBar.shellRoot.trayMenuY = Theme.barHeight - Theme.spacingXS
topBar.shellRoot.showTrayMenu = true
}
menu.menuVisible = true menu.menuVisible = true
topBar.showTrayMenu = true
} }
} }

View File

@@ -27,7 +27,7 @@ PanelWindow {
id: menuContainer id: menuContainer
x: root.trayMenuX x: root.trayMenuX
y: root.trayMenuY y: root.trayMenuY
width: 180 width: Math.max(180, Math.min(300, menuList.maxTextWidth + Theme.spacingL * 2))
height: Math.max(60, menuList.contentHeight + Theme.spacingS * 2) height: Math.max(60, menuList.contentHeight + Theme.spacingS * 2)
color: Theme.surfaceContainer color: Theme.surfaceContainer
radius: Theme.cornerRadiusLarge radius: Theme.cornerRadiusLarge
@@ -78,6 +78,27 @@ PanelWindow {
id: menuList id: menuList
anchors.fill: parent anchors.fill: parent
spacing: 1 spacing: 1
// Calculate maximum text width for dynamic menu sizing
property real maxTextWidth: {
let maxWidth = 0
if (model && model.values) {
for (let i = 0; i < model.values.length; i++) {
const item = model.values[i]
if (item && item.text) {
const textWidth = textMetrics.advanceWidth * item.text.length * 0.6
maxWidth = Math.max(maxWidth, textWidth)
}
}
}
return Math.min(maxWidth, 280) // Cap at reasonable width
}
TextMetrics {
id: textMetrics
font.pixelSize: Theme.fontSizeSmall
text: "M"
}
model: ScriptModel { model: ScriptModel {
values: menuOpener.children ? [...menuOpener.children.values].filter(item => { values: menuOpener.children ? [...menuOpener.children.values].filter(item => {
// Filter out empty items and separators // Filter out empty items and separators
@@ -114,6 +135,8 @@ PanelWindow {
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
font.weight: Font.Normal font.weight: Font.Normal
elide: Text.ElideRight
maximumLineCount: 1
} }
} }