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

launcher: reemove background from list and add a bottom fade

This commit is contained in:
bbedward
2025-12-05 10:04:19 -05:00
parent e56481f6d7
commit 5faa1a993a
4 changed files with 150 additions and 60 deletions

View File

@@ -10,12 +10,31 @@ Rectangle {
property var fileSearchController: null property var fileSearchController: null
function resetScroll() { function resetScroll() {
filesList.contentY = 0 filesList.contentY = 0;
} }
color: "transparent" color: "transparent"
clip: true clip: true
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 32
z: 100
visible: filesList.contentHeight > filesList.height && (filesList.currentIndex < filesList.count - 1 || filesList.contentY < filesList.contentHeight - filesList.height - 1)
gradient: Gradient {
GradientStop {
position: 0.0
color: "transparent"
}
GradientStop {
position: 1.0
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
}
}
}
DankListView { DankListView {
id: filesList id: filesList
@@ -30,18 +49,22 @@ Rectangle {
function ensureVisible(index) { function ensureVisible(index) {
if (index < 0 || index >= count) if (index < 0 || index >= count)
return return;
const itemY = index * (itemHeight + itemSpacing);
const itemY = index * (itemHeight + itemSpacing) const itemBottom = itemY + itemHeight;
const itemBottom = itemY + itemHeight const fadeHeight = 32;
const isLastItem = index === count - 1;
if (itemY < contentY) if (itemY < contentY)
contentY = itemY contentY = itemY;
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height - (isLastItem ? 0 : fadeHeight))
contentY = itemBottom - height contentY = Math.min(itemBottom - height + (isLastItem ? 0 : fadeHeight), contentHeight - height);
} }
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.topMargin: Theme.spacingS
anchors.bottomMargin: 1
model: fileSearchController ? fileSearchController.model : null model: fileSearchController ? fileSearchController.model : null
currentIndex: fileSearchController ? fileSearchController.selectedIndex : -1 currentIndex: fileSearchController ? fileSearchController.selectedIndex : -1
clip: true clip: true
@@ -53,26 +76,26 @@ Rectangle {
onCurrentIndexChanged: { onCurrentIndexChanged: {
if (keyboardNavigationActive) if (keyboardNavigationActive)
ensureVisible(currentIndex) ensureVisible(currentIndex);
} }
onItemClicked: function (index) { onItemClicked: function (index) {
if (fileSearchController) { if (fileSearchController) {
const item = fileSearchController.model.get(index) const item = fileSearchController.model.get(index);
fileSearchController.openFile(item.filePath) fileSearchController.openFile(item.filePath);
} }
} }
onItemRightClicked: function (index) { onItemRightClicked: function (index) {
if (fileSearchController) { if (fileSearchController) {
const item = fileSearchController.model.get(index) const item = fileSearchController.model.get(index);
fileSearchController.openFolder(item.filePath) fileSearchController.openFolder(item.filePath);
} }
} }
onKeyboardNavigationReset: { onKeyboardNavigationReset: {
if (fileSearchController) if (fileSearchController)
fileSearchController.keyboardNavigationActive = false fileSearchController.keyboardNavigationActive = false;
} }
delegate: Rectangle { delegate: Rectangle {
@@ -86,7 +109,7 @@ Rectangle {
width: ListView.view.width width: ListView.view.width
height: filesList.itemHeight height: filesList.itemHeight
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: ListView.isCurrentItem ? Theme.primaryPressed : fileMouseArea.containsMouse ? Theme.primaryHoverLight : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) color: ListView.isCurrentItem ? Theme.widgetBaseHoverColor : fileMouseArea.containsMouse ? Theme.widgetBaseHoverColor : "transparent"
Row { Row {
anchors.fill: parent anchors.fill: parent
@@ -109,16 +132,16 @@ Rectangle {
id: nerdIcon id: nerdIcon
anchors.centerIn: parent anchors.centerIn: parent
name: { name: {
const lowerName = fileName.toLowerCase() const lowerName = fileName.toLowerCase();
if (lowerName.startsWith("dockerfile")) if (lowerName.startsWith("dockerfile"))
return "docker" return "docker";
if (lowerName.startsWith("makefile")) if (lowerName.startsWith("makefile"))
return "makefile" return "makefile";
if (lowerName.startsWith("license")) if (lowerName.startsWith("license"))
return "license" return "license";
if (lowerName.startsWith("readme")) if (lowerName.startsWith("readme"))
return "readme" return "readme";
return fileExtension.toLowerCase() return fileExtension.toLowerCase();
} }
size: Theme.fontSizeXLarge size: Theme.fontSizeXLarge
color: Theme.surfaceText color: Theme.surfaceText
@@ -196,18 +219,18 @@ Rectangle {
z: 10 z: 10
onEntered: { onEntered: {
if (filesList.hoverUpdatesSelection && !filesList.keyboardNavigationActive) if (filesList.hoverUpdatesSelection && !filesList.keyboardNavigationActive)
filesList.currentIndex = index filesList.currentIndex = index;
} }
onPositionChanged: { onPositionChanged: {
filesList.keyboardNavigationReset() filesList.keyboardNavigationReset();
} }
onClicked: mouse => { onClicked: mouse => {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
filesList.itemClicked(index) filesList.itemClicked(index);
} else if (mouse.button === Qt.RightButton) { } else if (mouse.button === Qt.RightButton) {
filesList.itemRightClicked(index) filesList.itemRightClicked(index);
} }
} }
} }
} }
} }
@@ -219,21 +242,21 @@ Rectangle {
StyledText { StyledText {
property string displayText: { property string displayText: {
if (!fileSearchController) { if (!fileSearchController) {
return "" return "";
} }
if (!DSearchService.dsearchAvailable) { if (!DSearchService.dsearchAvailable) {
return I18n.tr("DankSearch not available") return I18n.tr("DankSearch not available");
} }
if (fileSearchController.isSearching) { if (fileSearchController.isSearching) {
return I18n.tr("Searching...") return I18n.tr("Searching...");
} }
if (fileSearchController.searchQuery.length === 0) { if (fileSearchController.searchQuery.length === 0) {
return I18n.tr("Enter a search query") return I18n.tr("Enter a search query");
} }
if (!fileSearchController.model || fileSearchController.model.count === 0) { if (!fileSearchController.model || fileSearchController.model.count === 0) {
return I18n.tr("No files found") return I18n.tr("No files found");
} }
return "" return "";
} }
text: displayText text: displayText

View File

@@ -51,6 +51,33 @@ Rectangle {
color: "transparent" color: "transparent"
clip: true clip: true
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 32
z: 100
visible: {
if (!appLauncher)
return false;
const view = appLauncher.viewMode === "list" ? resultsList : (gridLoader.item || resultsList);
const isLastItem = appLauncher.viewMode === "list" ? view.currentIndex >= view.count - 1 : (gridLoader.item ? Math.floor(view.currentIndex / view.actualColumns) >= Math.floor((view.count - 1) / view.actualColumns) : false);
const hasOverflow = view.contentHeight > view.height;
const atBottom = view.contentY >= view.contentHeight - view.height - 1;
return hasOverflow && (!isLastItem || !atBottom);
}
gradient: Gradient {
GradientStop {
position: 0.0
color: "transparent"
}
GradientStop {
position: 1.0
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
}
}
}
DankListView { DankListView {
id: resultsList id: resultsList
@@ -70,14 +97,19 @@ Rectangle {
return; return;
const itemY = index * (itemHeight + itemSpacing); const itemY = index * (itemHeight + itemSpacing);
const itemBottom = itemY + itemHeight; const itemBottom = itemY + itemHeight;
const fadeHeight = 32;
const isLastItem = index === count - 1;
if (itemY < contentY) if (itemY < contentY)
contentY = itemY; contentY = itemY;
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height - (isLastItem ? 0 : fadeHeight))
contentY = itemBottom - height; contentY = Math.min(itemBottom - height + (isLastItem ? 0 : fadeHeight), contentHeight - height);
} }
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.topMargin: Theme.spacingS
anchors.bottomMargin: 1
visible: appLauncher && appLauncher.viewMode === "list" visible: appLauncher && appLauncher.viewMode === "list"
model: appLauncher ? appLauncher.model : null model: appLauncher ? appLauncher.model : null
currentIndex: appLauncher ? appLauncher.selectedIndex : -1 currentIndex: appLauncher ? appLauncher.selectedIndex : -1
@@ -127,7 +159,10 @@ Rectangle {
property real _lastWidth: 0 property real _lastWidth: 0
anchors.fill: parent anchors.fill: parent
anchors.margins: Theme.spacingS anchors.leftMargin: Theme.spacingS
anchors.rightMargin: Theme.spacingS
anchors.topMargin: Theme.spacingS
anchors.bottomMargin: 1
visible: appLauncher && appLauncher.viewMode === "grid" visible: appLauncher && appLauncher.viewMode === "grid"
active: appLauncher && appLauncher.viewMode === "grid" active: appLauncher && appLauncher.viewMode === "grid"
asynchronous: false asynchronous: false
@@ -177,10 +212,12 @@ Rectangle {
return; return;
const itemY = Math.floor(index / actualColumns) * cellHeight; const itemY = Math.floor(index / actualColumns) * cellHeight;
const itemBottom = itemY + cellHeight; const itemBottom = itemY + cellHeight;
const fadeHeight = 32;
const isLastRow = Math.floor(index / actualColumns) >= Math.floor((count - 1) / actualColumns);
if (itemY < contentY) if (itemY < contentY)
contentY = itemY; contentY = itemY;
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height - (isLastRow ? 0 : fadeHeight))
contentY = itemBottom - height; contentY = Math.min(itemBottom - height + (isLastRow ? 0 : fadeHeight), contentHeight - height);
} }
anchors.fill: parent anchors.fill: parent

View File

@@ -406,6 +406,34 @@ DankPopout {
} }
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: "transparent" color: "transparent"
clip: true
Rectangle {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 32
z: 100
visible: {
if (appDrawerPopout.searchMode !== "apps")
return false;
const view = appLauncher.viewMode === "list" ? appList : appGrid;
const isLastItem = view.currentIndex >= view.count - 1;
const hasOverflow = view.contentHeight > view.height;
const atBottom = view.contentY >= view.contentHeight - view.height - 1;
return hasOverflow && (!isLastItem || !atBottom);
}
gradient: Gradient {
GradientStop {
position: 0.0
color: "transparent"
}
GradientStop {
position: 1.0
color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
}
}
}
DankListView { DankListView {
id: appList id: appList
@@ -426,14 +454,16 @@ DankPopout {
return; return;
var itemY = index * (itemHeight + itemSpacing); var itemY = index * (itemHeight + itemSpacing);
var itemBottom = itemY + itemHeight; var itemBottom = itemY + itemHeight;
var fadeHeight = 32;
var isLastItem = index === count - 1;
if (itemY < contentY) if (itemY < contentY)
contentY = itemY; contentY = itemY;
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height - (isLastItem ? 0 : fadeHeight))
contentY = itemBottom - height; contentY = Math.min(itemBottom - height + (isLastItem ? 0 : fadeHeight), contentHeight - height);
} }
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: Theme.spacingS anchors.bottomMargin: 1
visible: appDrawerPopout.searchMode === "apps" && appLauncher.viewMode === "list" visible: appDrawerPopout.searchMode === "apps" && appLauncher.viewMode === "list"
model: appLauncher.model model: appLauncher.model
currentIndex: appLauncher.selectedIndex currentIndex: appLauncher.selectedIndex
@@ -511,14 +541,16 @@ DankPopout {
return; return;
var itemY = Math.floor(index / actualColumns) * cellHeight; var itemY = Math.floor(index / actualColumns) * cellHeight;
var itemBottom = itemY + cellHeight; var itemBottom = itemY + cellHeight;
var fadeHeight = 32;
var isLastRow = Math.floor(index / actualColumns) >= Math.floor((count - 1) / actualColumns);
if (itemY < contentY) if (itemY < contentY)
contentY = itemY; contentY = itemY;
else if (itemBottom > contentY + height) else if (itemBottom > contentY + height - (isLastRow ? 0 : fadeHeight))
contentY = itemBottom - height; contentY = Math.min(itemBottom - height + (isLastRow ? 0 : fadeHeight), contentHeight - height);
} }
anchors.fill: parent anchors.fill: parent
anchors.bottomMargin: Theme.spacingS anchors.bottomMargin: 1
visible: appDrawerPopout.searchMode === "apps" && appLauncher.viewMode === "grid" visible: appDrawerPopout.searchMode === "apps" && appLauncher.viewMode === "grid"
model: appLauncher.model model: appLauncher.model
clip: true clip: true

View File

@@ -1,6 +1,4 @@
import QtQuick import QtQuick
import QtQuick.Controls
import Quickshell
import qs.Common import qs.Common
import qs.Widgets import qs.Widgets
@@ -29,12 +27,12 @@ Rectangle {
signal itemClicked(int index, var modelData) signal itemClicked(int index, var modelData)
signal itemRightClicked(int index, var modelData, real mouseX, real mouseY) signal itemRightClicked(int index, var modelData, real mouseX, real mouseY)
signal keyboardNavigationReset() signal keyboardNavigationReset
width: listView.width width: listView.width
height: itemHeight height: itemHeight
radius: Theme.cornerRadius radius: Theme.cornerRadius
color: isCurrentItem ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : mouseArea.containsMouse ? Theme.withAlpha(Theme.surfaceContainerHighest, Theme.popupTransparency) : Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency) color: isCurrentItem ? Theme.widgetBaseHoverColor : mouseArea.containsMouse ? Theme.widgetBaseHoverColor : "transparent"
Row { Row {
anchors.fill: parent anchors.fill: parent
@@ -97,27 +95,27 @@ Rectangle {
z: 10 z: 10
onEntered: { onEntered: {
if (root.hoverUpdatesSelection && !root.keyboardNavigationActive) if (root.hoverUpdatesSelection && !root.keyboardNavigationActive)
root.listView.currentIndex = root.index root.listView.currentIndex = root.index;
} }
onPositionChanged: { onPositionChanged: {
root.keyboardNavigationReset() root.keyboardNavigationReset();
} }
onClicked: mouse => { onClicked: mouse => {
if (mouse.button === Qt.LeftButton) { if (mouse.button === Qt.LeftButton) {
root.itemClicked(root.index, root.model) root.itemClicked(root.index, root.model);
} }
} }
onPressAndHold: mouse => { onPressAndHold: mouse => {
if (!root.isPlugin) { if (!root.isPlugin) {
const globalPos = mapToItem(null, mouse.x, mouse.y) const globalPos = mapToItem(null, mouse.x, mouse.y);
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y) root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y);
} }
} }
onPressed: mouse => { onPressed: mouse => {
if (mouse.button === Qt.RightButton && !root.isPlugin) { if (mouse.button === Qt.RightButton && !root.isPlugin) {
const globalPos = mapToItem(null, mouse.x, mouse.y) const globalPos = mapToItem(null, mouse.x, mouse.y);
root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y) root.itemRightClicked(root.index, root.model, globalPos.x, globalPos.y);
mouse.accepted = true mouse.accepted = true;
} }
} }
} }