waffles: start: more search progress

This commit is contained in:
end-4
2025-12-03 23:23:08 +01:00
parent 4055ad48fa
commit 71c1fbe1dd
12 changed files with 356 additions and 57 deletions
@@ -64,7 +64,7 @@ Singleton {
property color bg0: "#1C1C1C"
property color bg0Border: "#404040"
property color bg1Base: "#2C2C2C"
property color bg1: "#a8a8a8"
property color bg1: '#9f9f9f'
property color bg1Hover: "#b3b3b3"
property color bg1Active: '#727272'
property color bg1Border: '#bebebe'
@@ -125,6 +125,7 @@ Singleton {
property color accentUnfocused: root.dark ? root.darkColors.accentUnfocused : root.lightColors.accentUnfocused
property color accentFg: ColorUtils.isDark(accent) ? "#FFFFFF" : "#000000"
property color selection: Appearance.colors.colPrimaryContainer
property color selectionFg: Appearance.colors.colOnPrimaryContainer
}
radius: QtObject {
@@ -44,6 +44,7 @@ WButton {
radius: Looks.radius.medium
color: root.color
Behavior on color {
enabled: root.animateChoiceHighlight
animation: Looks.transition.color.createObject(this)
}
@@ -14,17 +14,18 @@ Menu {
property bool downDirection: false
property bool hasIcons: false // TODO: implement
implicitWidth: background.implicitWidth + root.padding * 2
implicitHeight: background.implicitHeight + root.padding * 2
implicitWidth: background.implicitWidth + margins * 2
implicitHeight: background.implicitHeight + margins * 2
margins: 10
padding: 3
property real sourceEdgeMargin: -implicitHeight
clip: true
enter: Transition {
NumberAnimation {
property: "sourceEdgeMargin"
from: -root.implicitHeight
to: root.padding
to: root.margins
duration: 200
easing.type: Easing.BezierSpline
easing.bezierCurve: Looks.transition.easing.bezierCurve.easeIn
@@ -33,7 +34,7 @@ Menu {
exit: Transition {
NumberAnimation {
property: "sourceEdgeMargin"
from: root.padding
from: root.margins
to: -root.implicitHeight
duration: 150
easing.type: Easing.BezierSpline
@@ -41,43 +42,55 @@ Menu {
}
}
background: WPane {
anchors {
left: parent.left
right: parent.right
top: root.downDirection ? parent.top : undefined
bottom: root.downDirection ? undefined : parent.bottom
margins: root.padding
topMargin: root.downDirection ? root.sourceEdgeMargin : root.padding
bottomMargin: root.downDirection ? root.padding : root.sourceEdgeMargin
}
contentItem: Rectangle {
color: Looks.colors.bg1Base
implicitWidth: menuListView.implicitWidth + root.padding * 2
implicitHeight: root.contentItem.implicitHeight + root.padding * 2
background: Item {
id: bgItem
implicitWidth: bgPane.implicitWidth
implicitHeight: bgPane.implicitHeight
WPane {
id: bgPane
anchors {
left: parent.left
right: parent.right
top: root.downDirection ? parent.top : undefined
bottom: root.downDirection ? undefined : parent.bottom
margins: root.margins
topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins
bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin
}
contentItem: Rectangle {
color: Looks.colors.bg1Base
implicitWidth: menuListView.implicitWidth + root.padding * 2
implicitHeight: root.contentItem.implicitHeight + root.padding * 2
}
}
}
contentItem: ListView {
id: menuListView
anchors {
left: parent.left
right: parent.right
top: root.downDirection ? parent.top : undefined
bottom: root.downDirection ? undefined : parent.bottom
margins: root.padding * 2
topMargin: root.downDirection ? root.sourceEdgeMargin : root.padding
bottomMargin: root.downDirection ? root.padding : root.sourceEdgeMargin
}
implicitHeight: contentHeight
implicitWidth: Array.from({
length: count
}, (_, i) => itemAtIndex(i)?.implicitWidth ?? 0).reduce((a, b) => a > b ? a : b)
contentItem: Item {
implicitWidth: menuListView.implicitWidth
implicitHeight: menuListView.implicitHeight
ListView {
id: menuListView
anchors {
left: parent.left
right: parent.right
top: root.downDirection ? parent.top : undefined
bottom: root.downDirection ? undefined : parent.bottom
margins: root.margins // ????
topMargin: root.downDirection ? root.sourceEdgeMargin : root.margins
bottomMargin: root.downDirection ? root.margins : root.sourceEdgeMargin
}
implicitHeight: contentHeight
implicitWidth: Array.from({
length: count
}, (_, i) => itemAtIndex(i)?.implicitWidth ?? 0).reduce((a, b) => a > b ? a : b)
model: root.contentModel
model: root.contentModel
}
}
delegate: WMenuItem {
id: menuItemDelegate
width: ListView.view?.width
}
}
@@ -10,14 +10,17 @@ WButton {
id: root
property alias iconName: iconContent.icon
property alias iconSize: iconContent.implicitSize
property alias monochrome: iconContent.monochrome
implicitWidth: 40
implicitHeight: 40
contentItem: FluentIcon {
id: iconContent
anchors.centerIn: parent
implicitSize: 18
icon: root.iconName
contentItem: Item {
FluentIcon {
id: iconContent
anchors.centerIn: parent
implicitSize: 18
icon: root.iconName
}
}
}
@@ -15,4 +15,5 @@ TextInput {
}
selectionColor: Looks.colors.selection
selectedTextColor: Looks.colors.selectionFg
}
@@ -12,26 +12,36 @@ import qs.modules.waffle.looks
FooterRectangle {
id: root
property real horizontalPadding: 32
property real verticalPadding: 16
property bool searching: text.length > 0
property alias text: searchInput.text
implicitHeight: outline.implicitHeight + verticalPadding * 2
Component.onCompleted: searchInput.forceActiveFocus()
focus: true
color: searching ? Looks.colors.bgPanelBody : Looks.colors.bgPanelFooter
implicitWidth: 832 // TODO: Make sizes naturally inferred
implicitHeight: 63
Behavior on horizontalPadding {
enabled: Config.options.waffles.tweaks.smootherSearchBar
animation: Looks.transition.move.createObject(this)
}
Behavior on verticalPadding {
enabled: Config.options.waffles.tweaks.smootherSearchBar
animation: Looks.transition.move.createObject(this)
}
Rectangle {
id: outline
anchors {
fill: parent
leftMargin: 32
rightMargin: 32
topMargin: 16
bottomMargin: 15
left: parent.left
right: parent.right
leftMargin: root.horizontalPadding
rightMargin: root.horizontalPadding
verticalCenter: parent.verticalCenter
}
implicitHeight: 32
color: "transparent"
radius: height / 2
border.width: 1
@@ -12,5 +12,25 @@ import qs.modules.waffle.looks
BodyRectangle {
id: root
property string searchText: LauncherSearch.query
ColumnLayout {
anchors {
fill: parent
topMargin: 2
leftMargin: 24
rightMargin: 24
}
spacing: 12
TagStrip {
Layout.fillWidth: true
Layout.fillHeight: false
}
SearchResults {
Layout.fillWidth: true
Layout.fillHeight: true
}
}
}
@@ -0,0 +1,60 @@
import qs.modules.waffle.looks
import qs.modules.common.functions
import qs.modules.common
import qs.services
import qs
import Quickshell
import QtQuick.Layouts
import QtQuick.Controls
import QtQuick
pragma ComponentBehavior: Bound
RowLayout {
id: root
function focusFirstItem() {
resultList.currentIndex = 0;
}
ResultList {
id: resultList
Layout.fillHeight: true
Layout.fillWidth: true
}
ResultPreview {
Layout.preferredWidth: 386
Layout.leftMargin: 1
Layout.rightMargin: 1
}
component ResultList: ListView {
section {
criteria: ViewSection.FullString
property: "type"
}
clip: true
spacing: 4
model: ScriptModel {
values: {
// TODO: categorize and have max per category
LauncherSearch.results.slice(0, 10)
}
onValuesChanged: {
root.focusFirstItem();
}
}
delegate: WSearchResultButton {
required property int index
required property var modelData
entry: modelData
firstEntry: index === 0
width: ListView.view?.width
}
}
component ResultPreview: Rectangle {
Layout.fillHeight: true
color: Looks.colors.bg1
radius: Looks.radius.large
}
}
@@ -14,26 +14,43 @@ WBarAttachedPanelContent {
id: root
property bool searching: false
property string searchText: ""
property string searchText: LauncherSearch.query
contentItem: WPane {
contentItem: WPanelPageColumn {
SearchBar {
focus: true
Layout.fillWidth: true
implicitWidth: 832 // TODO: Make sizes naturally inferred
horizontalPadding: root.searching ? 24 : 32
// verticalPadding: root.searching ? 32 : 16 // TODO: make this not nuke the panel
Synchronizer on searching {
property alias target: root.searching
}
Synchronizer on text {
property alias source: root.searchText
text: root.searchText
onTextChanged: {
LauncherSearch.query = text;
}
}
Loader {
id: pageContentLoader
Item {
implicitHeight: root.searching ? 736 : 736 // TODO: Make sizes naturally inferred
Layout.fillWidth: true
source: root.searching ? "SearchPageContent.qml" : "StartPageContent.qml"
Loader {
id: pageContentLoader
anchors.fill: parent
sourceComponent: root.searching ? searchPageComp : startPageComp
}
}
}
}
Component {
id: searchPageComp
SearchPageContent {}
}
Component {
id: startPageComp
StartPageContent {}
}
}
@@ -17,7 +17,7 @@ WPanelPageColumn {
WPanelSeparator {}
BodyRectangle {
implicitHeight: 736 // TODO: Make sizes naturally inferred
Layout.fillHeight: true
}
WPanelSeparator {}
@@ -0,0 +1,92 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.functions
import qs.modules.waffle.looks
RowLayout {
WPanelIconButton {
implicitWidth: 36
implicitHeight: 36
iconSize: 24
iconName: "arrow-left"
onClicked: LauncherSearch.query = ""
}
ListView {
id: tagListView
Layout.fillWidth: true
Layout.fillHeight: true
orientation: Qt.Horizontal
spacing: 4
model: [
{
name: Translation.tr("All"),
prefix: ""
},
{
name: Translation.tr("Apps"),
prefix: Config.options.search.prefix.app
},
{
name: Translation.tr("Actions"),
prefix: Config.options.search.prefix.action
},
{
name: Translation.tr("Clipboard"),
prefix: Config.options.search.prefix.clipboard
},
{
name: Translation.tr("Emojis"),
prefix: Config.options.search.prefix.emojis
},
{
name: Translation.tr("Math"),
prefix: Config.options.search.prefix.math
},
{
name: Translation.tr("Commands"),
prefix: Config.options.search.prefix.shellCommand
},
{
name: Translation.tr("Web"),
prefix: Config.options.search.prefix.webSearch
},
]
delegate: WBorderedButton {
id: tagButton
required property var modelData
border.width: 1
radius: height / 2
implicitWidth: tagButtonText.implicitWidth + 12 * 2
implicitHeight: 32
checked: {
if (modelData.prefix != "") {
return LauncherSearch.query.startsWith(modelData.prefix);
} else {
return !tagListView.model.some(i => (i.prefix != "" && LauncherSearch.query.startsWith(i.prefix)))
}
}
contentItem: Item {
WText {
id: tagButtonText
anchors.centerIn: parent
color: tagButton.fgColor
text: tagButton.modelData.name
font.pixelSize: Looks.font.pixelSize.large
}
}
onClicked: LauncherSearch.ensurePrefix(tagButton.modelData.prefix)
}
}
WPanelIconButton {
implicitWidth: 36
implicitHeight: 36
iconSize: 24
iconName: "more-horizontal"
}
}
@@ -0,0 +1,81 @@
import QtQuick
import QtQuick.Layouts
import Quickshell
import qs
import qs.services
import qs.modules.common
import qs.modules.common.models
import qs.modules.common.functions
import qs.modules.common.widgets
import qs.modules.waffle.looks
WChoiceButton {
id: root
required property LauncherSearchResult entry
property bool firstEntry: false
checked: focus
animateChoiceHighlight: false
implicitWidth: contentLayout.implicitWidth + leftPadding + rightPadding
implicitHeight: contentLayout.implicitHeight + topPadding + bottomPadding
onClicked: {
GlobalStates.searchOpen = false
root.entry.execute()
}
contentItem: RowLayout {
id: contentLayout
spacing: 8
EntryIcon {}
EntryNameColumn {
Layout.fillWidth: true
Layout.alignment: Qt.AlignVCenter
}
}
component EntryIcon: Item {
implicitWidth: 24
implicitHeight: 24
Loader {
anchors.centerIn: parent
active: root.entry.iconType === LauncherSearchResult.IconType.System
sourceComponent: WAppIcon {
implicitSize: 24
tryCustomIcon: false
iconName: root.entry.iconName
}
}
Loader {
anchors.centerIn: parent
active: root.entry.iconType === LauncherSearchResult.IconType.Text
sourceComponent: WText {
text: root.entry.iconName
font.pixelSize: 24
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
}
}
component EntryNameColumn: ColumnLayout {
spacing: 4
WText {
Layout.fillWidth: true
wrapMode: Text.Wrap
text: root.entry.name
font.pixelSize: Looks.font.pixelSize.large
maximumLineCount: 2
}
WText {
Layout.fillWidth: true
visible: root.firstEntry
text: root.entry.type
color: Looks.colors.accentUnfocused
}
}
}