feat(ui): using panel opacity on all nboxes (unless marked as opaque) + launcher adjustments for a nice transluent look

This commit is contained in:
Lemmy
2026-03-06 20:54:30 -05:00
parent b47a6e22bb
commit 76e7f30fcb
4 changed files with 120 additions and 98 deletions
+17 -13
View File
@@ -88,11 +88,20 @@ SmartPanel {
}
// Preview Panel (external) - uses provider's preview component
NDropShadow {
source: previewBox
anchors.fill: previewBox
autoPaddingEnabled: true
visible: previewBox.visible
z: previewBox.z - 1
}
NBox {
id: previewBox
visible: root.previewActive
width: root.previewPanelWidth
height: Math.round(400 * Style.uiScaleRatio)
forceOpaque: true // no blur for now
x: root.panelAnchorRight ? -(root.previewPanelWidth + Style.marginM) : ui.width + Style.marginM
y: {
var view = launcherCore.resultsView;
@@ -150,20 +159,15 @@ SmartPanel {
}
// Core launcher (state, providers, UI)
NBox {
LauncherCore {
id: launcherCore
anchors.fill: parent
anchors.margins: Style.marginL
LauncherCore {
id: launcherCore
anchors.fill: parent
screen: root.screen
isOpen: root.isPanelOpen
onRequestClose: root.close()
// Defer so the signal emission completes before SmartPanel
// sets isPanelOpen=false and the contentLoader destroys us.
onRequestCloseImmediately: Qt.callLater(root.closeImmediately)
}
screen: root.screen
isOpen: root.isPanelOpen
onRequestClose: root.close()
// Defer so the signal emission completes before SmartPanel
// sets isPanelOpen=false and the contentLoader destroys us.
onRequestCloseImmediately: Qt.callLater(root.closeImmediately)
}
// Update preview when selection changes
+17 -13
View File
@@ -159,6 +159,12 @@ Rectangle {
}
}
onSearchTextChanged: {
if (isOpen) {
updateResults();
}
}
function onOpened() {
ignoreMouseHover = true;
globalMouseInitialized = false;
@@ -188,11 +194,6 @@ Rectangle {
}
}
onSearchTextChanged: {
if (isOpen)
updateResults();
}
function close() {
requestClose();
}
@@ -783,7 +784,7 @@ Rectangle {
horizontalPolicy: ScrollBar.AlwaysOff
verticalPolicy: ScrollBar.AlwaysOff
reserveScrollbarSpace: false
gradientColor: Color.mSurfaceVariant
gradientColor: Settings.data.ui.panelBackgroundOpacity < 1 ? "transparent" : Color.mSurfaceVariant
wheelScrollMultiplier: 4.0
width: parent.width
@@ -806,6 +807,12 @@ Rectangle {
property bool isSelected: (!root.ignoreMouseHover && mouseArea.containsMouse) || (index === root.selectedIndex)
width: resultsList.availableWidth
implicitHeight: root.entryHeight
clip: true
color: entry.isSelected ? Color.mHover : Color.mSurface
forceOpaque: entry.isSelected
// Prepare item when it becomes visible (e.g., decode images)
Component.onCompleted: {
var provider = modelData.provider;
@@ -814,11 +821,6 @@ Rectangle {
}
}
width: resultsList.availableWidth
implicitHeight: root.entryHeight
clip: true
color: entry.isSelected ? Color.mHover : Color.mSurface
Behavior on color {
ColorAnimation {
duration: Style.animationFast
@@ -1086,6 +1088,7 @@ Rectangle {
NBox {
anchors.fill: parent
color: Color.mSurfaceVariant
forceOpaque: true
Layout.fillWidth: true
Layout.fillHeight: true
@@ -1131,7 +1134,7 @@ Rectangle {
}
}
// --------------------------
// // --------------------------
// GRID VIEW
Component {
id: gridViewComponent
@@ -1141,7 +1144,7 @@ Rectangle {
horizontalPolicy: ScrollBar.AlwaysOff
verticalPolicy: ScrollBar.AlwaysOff
reserveScrollbarSpace: false
gradientColor: Color.mSurfaceVariant
gradientColor: Settings.data.ui.panelBackgroundOpacity < 1 ? "transparent" : Color.mSurfaceVariant
wheelScrollMultiplier: 4.0
trackedSelectionIndex: root.selectedIndex
@@ -1211,6 +1214,7 @@ Rectangle {
anchors.fill: parent
anchors.margins: Style.marginXXS
color: gridEntryContainer.isSelected ? Color.mHover : Color.mSurface
forceOpaque: gridEntryContainer.isSelected
Behavior on color {
ColorAnimation {
@@ -57,8 +57,8 @@ Variants {
}
Region {
x: Math.round(previewBox.visible ? launcherPanel.x + previewBox.x : 0)
y: Math.round(previewBox.visible ? launcherPanel.y + previewBox.y : 0)
x: Math.round(previewBox.visible ? previewBox.x : 0)
y: Math.round(previewBox.visible ? previewBox.y : 0)
width: Math.round(previewBox.visible ? previewBox.width : 0)
height: Math.round(previewBox.visible ? previewBox.height : 0)
radius: Style.radiusL
@@ -337,83 +337,88 @@ Variants {
Component.onCompleted: PanelService.overlayLauncherCore = launcherCore
Component.onDestruction: PanelService.overlayLauncherCore = null
}
}
// Preview Panel - clipboard preview positioned outside panel bounds
NDropShadow {
source: previewBox
anchors.fill: previewBox
autoPaddingEnabled: true
visible: previewBox.visible
// Preview Panel - positioned as sibling of launcherPanel to avoid shadow bleed
NDropShadow {
source: previewBox
anchors.fill: previewBox
autoPaddingEnabled: true
visible: previewBox.visible
z: previewBox.z - 1
}
NBox {
id: previewBox
visible: launcherWindow.previewActive
width: launcherWindow.previewPanelWidth
height: Math.round(400 * Style.uiScaleRatio)
forceOpaque: true
x: {
if (panelPosition.endsWith("_right"))
return launcherPanel.x - launcherWindow.previewPanelWidth - Style.marginM;
return launcherPanel.x + launcherPanel.width + Style.marginM;
}
y: {
var view = launcherCore.resultsView;
if (!view)
return launcherPanel.y + Style.marginL;
var row = launcherCore.isGridView ? Math.floor(launcherCore.selectedIndex / launcherCore.gridColumns) : launcherCore.selectedIndex;
var gridCellSize = Math.floor((launcherWindow.listPanelWidth - (2 * Style.marginXS) - ((launcherCore.targetGridColumns - 1) * Style.marginS)) / launcherCore.targetGridColumns);
var itemHeight = launcherCore.isGridView ? (gridCellSize + Style.marginXXS) : (launcherCore.entryHeight + (view.spacing || 0));
var yPos = row * itemHeight - (view.contentY || 0);
var mapped = view.mapToItem(launcherWindow.contentItem, 0, yPos);
return Math.max(launcherPanel.y + Style.marginL, Math.min(mapped.y, launcherPanel.y + launcherPanel.height - previewBox.height - Style.marginL));
}
NBox {
id: previewBox
visible: launcherWindow.previewActive
width: launcherWindow.previewPanelWidth
height: Math.round(400 * Style.uiScaleRatio)
x: panelPosition.endsWith("_right") ? -(launcherWindow.previewPanelWidth + Style.marginM) : launcherPanel.width + Style.marginM
y: {
var view = launcherCore.resultsView;
if (!view)
return Style.marginL;
var row = launcherCore.isGridView ? Math.floor(launcherCore.selectedIndex / launcherCore.gridColumns) : launcherCore.selectedIndex;
var gridCellSize = Math.floor((launcherWindow.listPanelWidth - (2 * Style.marginXS) - ((launcherCore.targetGridColumns - 1) * Style.marginS)) / launcherCore.targetGridColumns);
var itemHeight = launcherCore.isGridView ? (gridCellSize + Style.marginXXS) : (launcherCore.entryHeight + (view.spacing || 0));
var yPos = row * itemHeight - (view.contentY || 0);
var mapped = view.mapToItem(launcherPanel, 0, yPos);
return Math.max(Style.marginL, Math.min(mapped.y, launcherPanel.height - previewBox.height - Style.marginL));
opacity: visible ? 1.0 : 0.0
Behavior on opacity {
NumberAnimation {
duration: Style.animationFast
}
z: -1
}
Behavior on y {
NumberAnimation {
duration: Style.animationFast
easing.type: Easing.OutCubic
}
}
opacity: visible ? 1.0 : 0.0
Behavior on opacity {
NumberAnimation {
duration: Style.animationFast
}
}
Behavior on y {
NumberAnimation {
duration: Style.animationFast
easing.type: Easing.OutCubic
}
}
Loader {
id: previewLoader
anchors.fill: parent
active: launcherWindow.previewActive
source: {
if (!active)
return "";
var provider = launcherCore.activeProvider;
if (provider && provider.previewComponentPath)
return provider.previewComponentPath;
Loader {
id: previewLoader
anchors.fill: parent
active: launcherWindow.previewActive
source: {
if (!active)
return "";
}
var provider = launcherCore.activeProvider;
if (provider && provider.previewComponentPath)
return provider.previewComponentPath;
return "";
}
onLoaded: updatePreviewItem()
onItemChanged: updatePreviewItem()
onLoaded: updatePreviewItem()
onItemChanged: updatePreviewItem()
function updatePreviewItem() {
if (!item || launcherCore.selectedIndex < 0 || !launcherCore.results[launcherCore.selectedIndex])
return;
var provider = launcherCore.activeProvider;
if (provider && provider.getPreviewData) {
item.currentItem = provider.getPreviewData(launcherCore.results[launcherCore.selectedIndex]);
} else {
item.currentItem = launcherCore.results[launcherCore.selectedIndex];
}
function updatePreviewItem() {
if (!item || launcherCore.selectedIndex < 0 || !launcherCore.results[launcherCore.selectedIndex])
return;
var provider = launcherCore.activeProvider;
if (provider && provider.getPreviewData) {
item.currentItem = provider.getPreviewData(launcherCore.results[launcherCore.selectedIndex]);
} else {
item.currentItem = launcherCore.results[launcherCore.selectedIndex];
}
}
}
}
// Update preview when selection changes
Connections {
target: launcherCore
function onSelectedIndexChanged() {
if (previewLoader.item)
previewLoader.updatePreviewItem();
}
// Update preview when selection changes
Connections {
target: launcherCore
function onSelectedIndexChanged() {
if (previewLoader.item)
previewLoader.updatePreviewItem();
}
}
}