1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-07 14:05:38 -05:00

Enhancements to launcher and other warning fixes

- Persist grid/list setting
- Alignment improvement
This commit is contained in:
bbedward
2025-07-14 12:46:36 -04:00
parent 603ac51df0
commit 4486e79afe
15 changed files with 322 additions and 282 deletions

View File

@@ -27,6 +27,10 @@ Singleton {
property bool showSystemResources: true property bool showSystemResources: true
property bool showSystemTray: true property bool showSystemTray: true
// View mode preferences for launchers
property string appLauncherViewMode: "list"
property string spotlightLauncherViewMode: "list"
Component.onCompleted: loadSettings() Component.onCompleted: loadSettings()
@@ -73,6 +77,8 @@ Singleton {
showClipboard = settings.showClipboard !== undefined ? settings.showClipboard : true showClipboard = settings.showClipboard !== undefined ? settings.showClipboard : true
showSystemResources = settings.showSystemResources !== undefined ? settings.showSystemResources : true showSystemResources = settings.showSystemResources !== undefined ? settings.showSystemResources : true
showSystemTray = settings.showSystemTray !== undefined ? settings.showSystemTray : true showSystemTray = settings.showSystemTray !== undefined ? settings.showSystemTray : true
appLauncherViewMode = settings.appLauncherViewMode !== undefined ? settings.appLauncherViewMode : "list"
spotlightLauncherViewMode = settings.spotlightLauncherViewMode !== undefined ? settings.spotlightLauncherViewMode : "list"
console.log("Loaded settings - themeIndex:", themeIndex, "isDynamic:", themeIsDynamic, "lightMode:", isLightMode, "transparency:", topBarTransparency, "recentApps:", recentlyUsedApps.length) console.log("Loaded settings - themeIndex:", themeIndex, "isDynamic:", themeIsDynamic, "lightMode:", isLightMode, "transparency:", topBarTransparency, "recentApps:", recentlyUsedApps.length)
applyStoredTheme() applyStoredTheme()
@@ -102,7 +108,9 @@ Singleton {
showMusic, showMusic,
showClipboard, showClipboard,
showSystemResources, showSystemResources,
showSystemTray showSystemTray,
appLauncherViewMode,
spotlightLauncherViewMode
}, null, 2)) }, null, 2))
console.log("Saving settings - themeIndex:", themeIndex, "isDynamic:", themeIsDynamic, "lightMode:", isLightMode, "transparency:", topBarTransparency, "recentApps:", recentlyUsedApps.length) console.log("Saving settings - themeIndex:", themeIndex, "isDynamic:", themeIsDynamic, "lightMode:", isLightMode, "transparency:", topBarTransparency, "recentApps:", recentlyUsedApps.length)
} }
@@ -257,4 +265,17 @@ Singleton {
showSystemTray = enabled showSystemTray = enabled
saveSettings() saveSettings()
} }
// View mode setters
function setAppLauncherViewMode(mode) {
console.log("Prefs setAppLauncherViewMode called - appLauncherViewMode:", mode)
appLauncherViewMode = mode
saveSettings()
}
function setSpotlightLauncherViewMode(mode) {
console.log("Prefs setSpotlightLauncherViewMode called - spotlightLauncherViewMode:", mode)
spotlightLauncherViewMode = mode
saveSettings()
}
} }

View File

@@ -455,8 +455,8 @@ QtObject {
property color surfaceVariant: isDynamicTheme ? Colors.surfaceVariant : getCurrentTheme().surfaceVariant property color surfaceVariant: isDynamicTheme ? Colors.surfaceVariant : getCurrentTheme().surfaceVariant
property color surfaceVariantText: isDynamicTheme ? Colors.surfaceVariantText : getCurrentTheme().surfaceVariantText property color surfaceVariantText: isDynamicTheme ? Colors.surfaceVariantText : getCurrentTheme().surfaceVariantText
property color surfaceTint: isDynamicTheme ? Colors.surfaceTint : getCurrentTheme().surfaceTint property color surfaceTint: isDynamicTheme ? Colors.surfaceTint : getCurrentTheme().surfaceTint
property color background: isDynamicTheme ? Colors.background : getCurrentTheme().background property color background: isDynamicTheme ? Colors.bg : getCurrentTheme().background
property color backgroundText: isDynamicTheme ? Colors.backgroundText : getCurrentTheme().backgroundText property color backgroundText: isDynamicTheme ? Colors.surfaceText : getCurrentTheme().backgroundText
property color outline: isDynamicTheme ? Colors.outline : getCurrentTheme().outline property color outline: isDynamicTheme ? Colors.outline : getCurrentTheme().outline
property color surfaceContainer: isDynamicTheme ? Colors.surfaceContainer : getCurrentTheme().surfaceContainer property color surfaceContainer: isDynamicTheme ? Colors.surfaceContainer : getCurrentTheme().surfaceContainer
property color surfaceContainerHigh: isDynamicTheme ? Colors.surfaceContainerHigh : getCurrentTheme().surfaceContainerHigh property color surfaceContainerHigh: isDynamicTheme ? Colors.surfaceContainerHigh : getCurrentTheme().surfaceContainerHigh

View File

@@ -56,7 +56,7 @@ Singleton {
root.focusedAppId = windowData.app_id || "" root.focusedAppId = windowData.app_id || ""
root.focusedWindowTitle = windowData.title || "" root.focusedWindowTitle = windowData.title || ""
root.focusedAppName = getDisplayName(windowData.app_id || "") root.focusedAppName = getDisplayName(windowData.app_id || "")
root.focusedWindowId = windowData.id || -1 root.focusedWindowId = parseInt(windowData.id) || -1
} catch (e) { } catch (e) {
console.warn("FocusedWindowService: Failed to parse focused window data:", e) console.warn("FocusedWindowService: Failed to parse focused window data:", e)
clearFocusedWindow() clearFocusedWindow()

View File

@@ -36,7 +36,7 @@ PanelWindow {
property var recentApps: Prefs.getRecentApps() property var recentApps: Prefs.getRecentApps()
property var pinnedApps: ["firefox", "code", "terminal", "file-manager"] property var pinnedApps: ["firefox", "code", "terminal", "file-manager"]
property bool showCategories: false property bool showCategories: false
property string viewMode: "list" // "list" or "grid" property string viewMode: Prefs.appLauncherViewMode // "list" or "grid"
property int selectedIndex: 0 property int selectedIndex: 0
// Search debouncing // Search debouncing
@@ -625,7 +625,10 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: viewMode = "list" onClicked: {
viewMode = "list"
Prefs.setAppLauncherViewMode("list")
}
} }
} }
@@ -650,7 +653,10 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: viewMode = "grid" onClicked: {
viewMode = "grid"
Prefs.setAppLauncherViewMode("grid")
}
} }
} }
} }
@@ -721,18 +727,18 @@ PanelWindow {
GridView { GridView {
id: appGrid id: appGrid
width: parent.width anchors.fill: parent
anchors.margins: Theme.spacingS anchors.margins: Theme.spacingS
// Responsive cell sizes based on screen width // Responsive cell sizes based on screen width - 4 columns
property int baseCellWidth: Math.max(100, Math.min(140, width / 8)) property int columnsCount: 4
property int baseCellWidth: (width - Theme.spacingS * 2) / columnsCount
property int baseCellHeight: baseCellWidth + 20 property int baseCellHeight: baseCellWidth + 20
cellWidth: baseCellWidth cellWidth: baseCellWidth
cellHeight: baseCellHeight cellHeight: baseCellHeight
// Center the grid content // Center the grid content
property int columnsCount: Math.floor(width / cellWidth)
property int remainingSpace: width - (columnsCount * cellWidth) property int remainingSpace: width - (columnsCount * cellWidth)
leftMargin: Math.max(Theme.spacingS, remainingSpace / 2) leftMargin: Math.max(Theme.spacingS, remainingSpace / 2)
rightMargin: leftMargin rightMargin: leftMargin
@@ -983,7 +989,7 @@ PanelWindow {
Text { Text {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: 88 width: appGrid.cellWidth - 12
text: model.name text: model.name
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText

View File

@@ -70,9 +70,7 @@ PanelWindow {
// Main row with widgets and calendar // Main row with widgets and calendar
let widgetHeight = 160 // Media widget always present let widgetHeight = 160 // Media widget always present
if (weather?.available) { widgetHeight += (weather ? 140 : 80) + theme.spacingM // Weather widget always present
widgetHeight += (weather ? 140 : 80) + theme.spacingM
}
let calendarHeight = 300 let calendarHeight = 300
let mainRowHeight = Math.max(widgetHeight, calendarHeight) let mainRowHeight = Math.max(widgetHeight, calendarHeight)
@@ -169,9 +167,7 @@ PanelWindow {
width: parent.width width: parent.width
height: { height: {
let widgetHeight = 160 // Media widget always present let widgetHeight = 160 // Media widget always present
if (weather?.available) { widgetHeight += (weather ? 140 : 80) + theme.spacingM // Weather widget always present
widgetHeight += (weather ? 140 : 80) + theme.spacingM
}
let calendarHeight = 300 let calendarHeight = 300
return Math.max(widgetHeight, calendarHeight) return Math.max(widgetHeight, calendarHeight)
} }
@@ -186,7 +182,7 @@ PanelWindow {
visible: hasAnyWidgets visible: hasAnyWidgets
anchors.top: parent.top anchors.top: parent.top
property bool hasAnyWidgets: true || weather?.available // Always show media widget property bool hasAnyWidgets: true // Always show media widget and weather widget
MediaPlayerWidget { MediaPlayerWidget {
visible: true // Always visible - shows placeholder when no media visible: true // Always visible - shows placeholder when no media
@@ -196,7 +192,7 @@ PanelWindow {
} }
WeatherWidget { WeatherWidget {
visible: weather?.available visible: true // Always visible - shows placeholder when no weather
width: parent.width width: parent.width
height: weather ? 140 : 80 height: weather ? 140 : 80
theme: centerCommandCenter.theme theme: centerCommandCenter.theme

View File

@@ -75,133 +75,119 @@ Rectangle {
} }
} }
Item { // Header - always visible when widget is shown
anchors.fill: parent Row {
id: headerRow
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
anchors.margins: theme.spacingL anchors.margins: theme.spacingL
spacing: theme.spacingS
Column { Text {
anchors.fill: parent text: "event"
spacing: theme.spacingM font.family: theme.iconFont
font.pixelSize: theme.iconSize - 2
// Header - always visible when widget is shown color: theme.primary
Item { anchors.verticalCenter: parent.verticalCenter
width: parent.width
height: headerRow.height
Row {
id: headerRow
width: parent.width
spacing: theme.spacingS
Text {
text: "event"
font.family: theme.iconFont
font.pixelSize: theme.iconSize - 2
color: theme.primary
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: hasEvents ?
(Qt.formatDate(selectedDate, "MMM d") + " • " +
(selectedDateEvents.length === 1 ? "1 event" : selectedDateEvents.length + " events")) :
Qt.formatDate(selectedDate, "MMM d")
font.pixelSize: theme.fontSizeMedium
color: theme.surfaceText
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
}
}
} }
// Content area Text {
Rectangle { text: hasEvents ?
anchors.fill: parent (Qt.formatDate(selectedDate, "MMM d") + " • " +
anchors.margins: theme.spacingL (selectedDateEvents.length === 1 ? "1 event" : selectedDateEvents.length + " events")) :
color: "transparent" Qt.formatDate(selectedDate, "MMM d")
font.pixelSize: theme.fontSizeMedium
// No events placeholder - absolutely centered in this gray container color: theme.surfaceText
Column { font.weight: Font.Medium
anchors.centerIn: parent anchors.verticalCenter: parent.verticalCenter
spacing: theme.spacingXS }
visible: !hasEvents }
// No events placeholder - centered in entire widget (not just content area)
Column {
anchors.centerIn: parent
spacing: theme.spacingXS
visible: !hasEvents
Text { Text {
text: "event_busy" text: "event_busy"
font.family: theme.iconFont font.family: theme.iconFont
font.pixelSize: theme.iconSize + 8 font.pixelSize: theme.iconSize + 8
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.3) color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.3)
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
Text { Text {
text: "No events" text: "No events"
font.pixelSize: theme.fontSizeMedium font.pixelSize: theme.fontSizeMedium
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.5) color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.5)
font.weight: Font.Normal font.weight: Font.Normal
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }
}
// Events list - positioned below header when there are events
ListView {
id: eventsList
anchors.top: headerRow.bottom
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.margins: theme.spacingL
anchors.topMargin: theme.spacingM
visible: hasEvents
clip: true
spacing: theme.spacingS
boundsMovement: Flickable.StopAtBounds
boundsBehavior: Flickable.StopAtBounds
ScrollBar.vertical: ScrollBar {
policy: eventsList.contentHeight > eventsList.height ? ScrollBar.AsNeeded : ScrollBar.AlwaysOff
}
delegate: Rectangle {
width: eventsList.width
height: eventContent.implicitHeight + theme.spacingM
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 Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.06)
// Events list }
ListView { border.color: {
id: eventsList if (modelData.url && eventMouseArea.containsMouse) {
anchors.fill: parent return Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.3)
anchors.margins: theme.spacingM } else if (eventMouseArea.containsMouse) {
anchors.topMargin: theme.spacingM + 2 return Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.15)
visible: hasEvents }
clip: true return "transparent"
spacing: theme.spacingS }
boundsMovement: Flickable.StopAtBounds border.width: 1
boundsBehavior: Flickable.StopAtBounds
// Event indicator strip
ScrollBar.vertical: ScrollBar { Rectangle {
policy: eventsList.contentHeight > eventsList.height ? ScrollBar.AsNeeded : ScrollBar.AlwaysOff width: 4
} height: parent.height - 8
anchors.left: parent.left
delegate: Rectangle { anchors.leftMargin: 4
width: eventsList.width anchors.verticalCenter: parent.verticalCenter
height: eventContent.implicitHeight + theme.spacingM radius: 2
radius: theme.cornerRadius color: theme.primary
color: { opacity: 0.8
if (modelData.url && eventMouseArea.containsMouse) { }
return Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.12)
} else if (eventMouseArea.containsMouse) { Column {
return Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.06) id: eventContent
} anchors.left: parent.left
return Qt.rgba(theme.surfaceVariant.r, theme.surfaceVariant.g, theme.surfaceVariant.b, 0.06) anchors.right: parent.right
} anchors.verticalCenter: parent.verticalCenter
border.color: { anchors.leftMargin: theme.spacingL + 4
if (modelData.url && eventMouseArea.containsMouse) { anchors.rightMargin: theme.spacingM
return Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.3) spacing: 6
} else if (eventMouseArea.containsMouse) {
return Qt.rgba(theme.primary.r, theme.primary.g, theme.primary.b, 0.15)
}
return "transparent"
}
border.width: 1
// Event indicator strip
Rectangle {
width: 4
height: parent.height - 8
anchors.left: parent.left
anchors.leftMargin: 4
anchors.verticalCenter: parent.verticalCenter
radius: 2
color: theme.primary
opacity: 0.8
}
Column {
id: eventContent
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: theme.spacingL + 4
anchors.rightMargin: theme.spacingM
spacing: 6
Text { Text {
width: parent.width width: parent.width
@@ -280,39 +266,36 @@ Rectangle {
} }
} }
} }
MouseArea { MouseArea {
id: eventMouseArea id: eventMouseArea
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: modelData.url ? Qt.PointingHandCursor : Qt.ArrowCursor cursorShape: modelData.url ? Qt.PointingHandCursor : Qt.ArrowCursor
enabled: modelData.url !== "" enabled: modelData.url !== ""
onClicked: { onClicked: {
if (modelData.url && modelData.url !== "") { if (modelData.url && modelData.url !== "") {
if (Qt.openUrlExternally(modelData.url) === false) { if (Qt.openUrlExternally(modelData.url) === false) {
console.warn("Couldn't open", modelData.url) console.warn("Couldn't open", modelData.url)
}
}
}
}
Behavior on color {
ColorAnimation {
duration: theme.shortDuration
easing.type: theme.standardEasing
}
}
Behavior on border.color {
ColorAnimation {
duration: theme.shortDuration
easing.type: theme.standardEasing
}
} }
} }
} }
} }
Behavior on color {
ColorAnimation {
duration: theme.shortDuration
easing.type: theme.standardEasing
}
}
Behavior on border.color {
ColorAnimation {
duration: theme.shortDuration
easing.type: theme.standardEasing
}
}
} }
} }
} }

View File

@@ -27,43 +27,43 @@ Rectangle {
shadowOpacity: 0.1 shadowOpacity: 0.1
} }
// Placeholder when no weather - centered in entire widget
Column {
anchors.centerIn: parent
spacing: theme.spacingS
visible: !weather || !weather.available || weather.temp === 0
Text {
text: "cloud_off"
font.family: theme.iconFont
font.pixelSize: theme.iconSize + 8
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.5)
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "No Weather Data"
font.pixelSize: theme.fontSizeMedium
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter
}
}
// Weather content when available - original Column structure
Column { Column {
anchors.fill: parent anchors.fill: parent
anchors.margins: theme.spacingL anchors.margins: theme.spacingL
spacing: theme.spacingM spacing: theme.spacingS
visible: weather && weather.available && weather.temp !== 0
// Show different content based on whether we have weather data // Weather header info
Item { Item {
width: parent.width width: parent.width
height: 60 height: 60
// Placeholder when no weather
Column {
anchors.centerIn: parent
spacing: theme.spacingS
visible: !weather || !weather.available || weather.temp === 0
Text {
text: "cloud_off"
font.family: theme.iconFont
font.pixelSize: theme.iconSize + 8
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.5)
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "No Weather Data"
font.pixelSize: theme.fontSizeMedium
color: Qt.rgba(theme.surfaceText.r, theme.surfaceText.g, theme.surfaceText.b, 0.7)
anchors.horizontalCenter: parent.horizontalCenter
}
}
// Normal weather info when available
Row { Row {
anchors.fill: parent anchors.fill: parent
spacing: theme.spacingL spacing: theme.spacingL
visible: weather && weather.available && weather.temp !== 0
// Weather icon // Weather icon
Text { Text {
@@ -108,7 +108,6 @@ Rectangle {
columns: 2 columns: 2
spacing: theme.spacingM spacing: theme.spacingM
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
visible: weather && weather.available && weather.temp !== 0
Row { Row {
spacing: theme.spacingXS spacing: theme.spacingXS

View File

@@ -836,6 +836,17 @@ PanelWindow {
console.warn("ClipboardHistory: Failed to load clipboard history") console.warn("ClipboardHistory: Failed to load clipboard history")
} }
} }
// Handle keyboard shortcuts
Keys.onPressed: (event) => {
if (event.key === Qt.Key_Escape) {
clipboardHistory.hide()
}
}
Component.onCompleted: {
focus = true
}
} }
Process { Process {
@@ -874,11 +885,6 @@ PanelWindow {
} }
} }
Keys.onPressed: (event) => {
if (event.key === Qt.Key_Escape) {
hide()
}
}
IpcHandler { IpcHandler {
target: "clipboard" target: "clipboard"

View File

@@ -153,7 +153,7 @@ PanelWindow {
color: "transparent" color: "transparent"
border.color: Qt.rgba(0, 0, 0, 0.15) // Subtle dark outline border.color: Qt.rgba(0, 0, 0, 0.15) // Subtle dark outline
border.width: 1 border.width: 1
visible: hasImage visible: parent.hasImage
} }
// Highlight ring to make it pop // Highlight ring to make it pop
@@ -164,7 +164,7 @@ PanelWindow {
color: "transparent" color: "transparent"
border.color: Qt.rgba(255, 255, 255, 0.1) // Subtle light ring border.color: Qt.rgba(255, 255, 255, 0.1) // Subtle light ring
border.width: 1 border.width: 1
visible: hasImage visible: parent.hasImage
} }
// Fallback icon for no profile picture (generic person) // Fallback icon for no profile picture (generic person)
@@ -173,7 +173,7 @@ PanelWindow {
text: "person" text: "person"
font.family: Theme.iconFont font.family: Theme.iconFont
font.pixelSize: Theme.iconSize + 8 font.pixelSize: Theme.iconSize + 8
color: Theme.onPrimary color: Theme.primaryText
visible: Prefs.profileImage === "" visible: Prefs.profileImage === ""
} }
@@ -183,7 +183,7 @@ PanelWindow {
text: "warning" text: "warning"
font.family: Theme.iconFont font.family: Theme.iconFont
font.pixelSize: Theme.iconSize + 8 font.pixelSize: Theme.iconSize + 8
color: Theme.onPrimary color: Theme.primaryText
visible: Prefs.profileImage !== "" && profileImage.status === Image.Error visible: Prefs.profileImage !== "" && profileImage.status === Image.Error
} }
} }

View File

@@ -144,7 +144,7 @@ PanelWindow {
Text { Text {
text: "Confirm" text: "Confirm"
font.pixelSize: Theme.fontSizeMedium font.pixelSize: Theme.fontSizeMedium
color: Theme.onPrimary color: Theme.primaryText
font.weight: Font.Medium font.weight: Font.Medium
anchors.centerIn: parent anchors.centerIn: parent
} }

View File

@@ -245,8 +245,7 @@ PanelWindow {
Row { Row {
id: columnHeaders id: columnHeaders
Layout.fillWidth: true Layout.fillWidth: true
anchors.left: parent.left Layout.leftMargin: 8
anchors.leftMargin: 8
spacing: 8 spacing: 8
// Icon placeholder + Process name // Icon placeholder + Process name
@@ -466,8 +465,8 @@ PanelWindow {
} }
// Material 3 animations // Material 3 animations
opacity: menuVisible ? 1.0 : 0.0 opacity: processContextMenuWindow.menuVisible ? 1.0 : 0.0
scale: menuVisible ? 1.0 : 0.85 scale: processContextMenuWindow.menuVisible ? 1.0 : 0.85
Behavior on opacity { Behavior on opacity {
NumberAnimation { NumberAnimation {

View File

@@ -217,7 +217,7 @@ PanelWindow {
text: profileImageInput.text === "" ? "person" : "warning" text: profileImageInput.text === "" ? "person" : "warning"
font.family: Theme.iconFont font.family: Theme.iconFont
font.pixelSize: Theme.iconSize + 8 font.pixelSize: Theme.iconSize + 8
color: Theme.onPrimary color: Theme.primaryText
visible: !avatarBox.hasImage visible: !avatarBox.hasImage
} }

View File

@@ -80,7 +80,7 @@ Rectangle {
radius: 10 radius: 10
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
x: root.checked ? parent.width - width - 2 : 2 x: root.checked ? parent.width - width - 2 : 2
color: root.checked ? Theme.onPrimary : Theme.surfaceText color: root.checked ? Theme.primaryText : Theme.surfaceText
Behavior on x { Behavior on x {
NumberAnimation { NumberAnimation {

View File

@@ -22,7 +22,7 @@ PanelWindow {
return result.concat(allCategories.filter(cat => cat !== "All")) return result.concat(allCategories.filter(cat => cat !== "All"))
} }
property string selectedCategory: "All" property string selectedCategory: "All"
property string viewMode: "list" // "list" or "grid" property string viewMode: Prefs.spotlightLauncherViewMode // "list" or "grid"
// Search debouncing // Search debouncing
Timer { Timer {
@@ -510,7 +510,10 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: viewMode = "list" onClicked: {
viewMode = "list"
Prefs.setSpotlightLauncherViewMode("list")
}
} }
} }
@@ -537,7 +540,10 @@ PanelWindow {
anchors.fill: parent anchors.fill: parent
hoverEnabled: true hoverEnabled: true
cursorShape: Qt.PointingHandCursor cursorShape: Qt.PointingHandCursor
onClicked: viewMode = "grid" onClicked: {
viewMode = "grid"
Prefs.setSpotlightLauncherViewMode("grid")
}
} }
} }
} }
@@ -598,19 +604,35 @@ PanelWindow {
anchors.margins: Theme.spacingM anchors.margins: Theme.spacingM
spacing: Theme.spacingL spacing: Theme.spacingL
Rectangle { Item {
width: 40 width: 40
height: 40 height: 40
radius: Theme.cornerRadius
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2)
border.width: 1
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
IconImage { IconImage {
id: listIconImg
anchors.fill: parent anchors.fill: parent
anchors.margins: 4
source: model.icon ? Quickshell.iconPath(model.icon, "") : "" source: model.icon ? Quickshell.iconPath(model.icon, "") : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
}
Rectangle {
anchors.fill: parent
visible: !listIconImg.visible
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.10)
radius: Theme.cornerRadiusLarge
border.width: 1
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.20)
Text {
anchors.centerIn: parent
text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
font.pixelSize: 20
color: Theme.primary
font.weight: Font.Bold
}
} }
} }
@@ -650,56 +672,60 @@ PanelWindow {
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AlwaysOn } ScrollBar.vertical: ScrollBar { policy: ScrollBar.AlwaysOn }
} }
// Grid view // Grid view scroll container
GridView { ScrollView {
id: resultsGrid anchors.fill: parent
// Center the grid within the parent space
anchors.centerIn: parent
width: Math.min(parent.width, baseCellWidth * 6 + 16) // Optimal width for 6 columns plus spacing
height: parent.height
visible: viewMode === "grid"
model: filteredModel
clip: true clip: true
focus: spotlightOpen visible: viewMode === "grid"
interactive: true ScrollBar.vertical.policy: ScrollBar.AsNeeded
flickDeceleration: 8000 ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
maximumFlickVelocity: 15000
// Optimized cell sizes for maximum space efficiency - 6 columns GridView {
property int baseCellWidth: Math.max(85, Math.min(100, width / 6)) id: resultsGrid
property int baseCellHeight: baseCellWidth + 30
cellWidth: baseCellWidth
cellHeight: baseCellHeight
// Use full width with minimal 2px right margin for scrollbar
leftMargin: 0
rightMargin: 2
topMargin: Theme.spacingXS
bottomMargin: Theme.spacingXS
// Make mouse wheel scrolling more responsive
property real wheelStepSize: 60
MouseArea {
anchors.fill: parent anchors.fill: parent
acceptedButtons: Qt.NoButton anchors.margins: Theme.spacingS
propagateComposedEvents: true
z: -1
onWheel: (wheel) => { model: filteredModel
var delta = wheel.angleDelta.y focus: spotlightOpen
var steps = delta / 120 // Standard wheel step interactive: true
resultsGrid.contentY -= steps * resultsGrid.wheelStepSize flickDeceleration: 8000
maximumFlickVelocity: 15000
// Responsive cell sizes based on screen width - wider cells for better fill
property int baseCellWidth: Math.max(120, Math.min(160, width / 6))
property int baseCellHeight: baseCellWidth + 20
cellWidth: baseCellWidth
cellHeight: baseCellHeight
// Center the grid content with better fill
property int columnsCount: Math.floor(width / cellWidth)
property int remainingSpace: width - (columnsCount * cellWidth)
leftMargin: Math.max(Theme.spacingXS, remainingSpace / 2)
rightMargin: leftMargin
// Make mouse wheel scrolling more responsive
property real wheelStepSize: 60
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton
propagateComposedEvents: true
z: -1
// Ensure we stay within bounds onWheel: (wheel) => {
if (resultsGrid.contentY < 0) { var delta = wheel.angleDelta.y
resultsGrid.contentY = 0 var steps = delta / 120 // Standard wheel step
} else if (resultsGrid.contentY > resultsGrid.contentHeight - resultsGrid.height) { resultsGrid.contentY -= steps * resultsGrid.wheelStepSize
resultsGrid.contentY = Math.max(0, resultsGrid.contentHeight - resultsGrid.height)
// Ensure we stay within bounds
if (resultsGrid.contentY < 0) {
resultsGrid.contentY = 0
} else if (resultsGrid.contentY > resultsGrid.contentHeight - resultsGrid.height) {
resultsGrid.contentY = Math.max(0, resultsGrid.contentHeight - resultsGrid.height)
}
} }
} }
}
delegate: Rectangle { delegate: Rectangle {
width: resultsGrid.cellWidth - 8 width: resultsGrid.cellWidth - 8
@@ -720,24 +746,36 @@ PanelWindow {
height: iconSize height: iconSize
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
IconImage {
id: iconImg
anchors.fill: parent
source: model.icon ? Quickshell.iconPath(model.icon, "") : ""
smooth: true
asynchronous: true
visible: status === Image.Ready
}
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
radius: Theme.cornerRadius visible: !iconImg.visible
color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.1) color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.10)
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2) radius: Theme.cornerRadiusLarge
border.width: 1 border.width: 1
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.20)
IconImage {
anchors.fill: parent Text {
anchors.margins: 4 anchors.centerIn: parent
source: model.icon ? Quickshell.iconPath(model.icon, "") : "" text: (model.name && model.name.length > 0) ? model.name.charAt(0).toUpperCase() : "A"
font.pixelSize: Math.min(24, parent.width * 0.5)
color: Theme.primary
font.weight: Font.Bold
} }
} }
} }
Text { Text {
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
width: resultsGrid.cellWidth - 16 width: resultsGrid.cellWidth - 12
text: model.name text: model.name
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText color: Theme.surfaceText
@@ -759,10 +797,9 @@ PanelWindow {
onClicked: launchApp(model) onClicked: launchApp(model)
} }
} }
ScrollBar.vertical: ScrollBar { policy: ScrollBar.AsNeeded }
} }
} }
}
} }
} }

View File

@@ -320,13 +320,6 @@ ShellRoot {
onClipboardRequested: { onClipboardRequested: {
clipboardHistoryPopup.toggle() clipboardHistoryPopup.toggle()
} }
onShowTrayMenuChanged: root.showTrayMenu = showTrayMenu
onCurrentTrayMenuChanged: root.currentTrayMenu = currentTrayMenu
onCurrentTrayItemChanged: root.currentTrayItem = currentTrayItem
onTrayMenuXChanged: root.trayMenuX = trayMenuX
onTrayMenuYChanged: root.trayMenuY = trayMenuY
} }
} }