mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-30 15:07:49 -04:00
193 lines
5.9 KiB
QML
193 lines
5.9 KiB
QML
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import QtQuick.Layouts
|
|
import qs.Common
|
|
import qs.Modules.ControlCenter
|
|
import qs.Widgets
|
|
import "../utils/widgets.js" as WidgetUtils
|
|
|
|
DankBottomSheet {
|
|
id: root
|
|
|
|
property var widgets: []
|
|
readonly property string query: searchField.text.trim()
|
|
readonly property var matches: WidgetUtils.filterWidgets(widgets, query)
|
|
readonly property var categories: [
|
|
{
|
|
"id": "user",
|
|
"title": I18n.tr("User")
|
|
},
|
|
{
|
|
"id": "network",
|
|
"title": I18n.tr("Network")
|
|
},
|
|
{
|
|
"id": "audio",
|
|
"title": I18n.tr("Audio")
|
|
},
|
|
{
|
|
"id": "display",
|
|
"title": I18n.tr("Display")
|
|
},
|
|
{
|
|
"id": "system",
|
|
"title": I18n.tr("System")
|
|
},
|
|
{
|
|
"id": "plugins",
|
|
"title": I18n.tr("Plugins")
|
|
}
|
|
]
|
|
readonly property var shownCategories: categories.filter(category => widgets.some(widget => (widget.category ?? "plugins") === category.id))
|
|
|
|
signal chosen(string widgetId)
|
|
signal clearRequested
|
|
|
|
title: I18n.tr("Widgets")
|
|
initialFocusItem: searchField
|
|
|
|
onOpenedChanged: {
|
|
if (opened)
|
|
searchField.text = "";
|
|
}
|
|
|
|
headerActions: [
|
|
DankActionButton {
|
|
buttonSize: Theme.buttonHeightS
|
|
iconName: "clear_all"
|
|
iconColor: Theme.error
|
|
tooltipText: I18n.tr("Clear All")
|
|
onClicked: root.clearRequested()
|
|
}
|
|
]
|
|
|
|
component PreviewGrid: Grid {
|
|
id: grid
|
|
|
|
property var entries: []
|
|
|
|
signal chosen(string widgetId)
|
|
|
|
columns: Math.max(1, Math.floor((width + spacing) / (CcMetrics.previewMinWidth + spacing)))
|
|
spacing: Theme.spacingS
|
|
|
|
Repeater {
|
|
model: grid.entries
|
|
|
|
StyledButton {
|
|
id: preview
|
|
|
|
required property var modelData
|
|
readonly property bool isUser: modelData.id === "user"
|
|
readonly property bool available: modelData.enabled !== false
|
|
|
|
width: (grid.width - grid.spacing * (grid.columns - 1)) / grid.columns
|
|
height: CcMetrics.previewTileHeight + Theme.spacingXS + label.implicitHeight + Theme.spacingS * 2
|
|
radius: Theme.cornerRadiusL
|
|
Accessible.name: modelData.text
|
|
Accessible.description: modelData.warning ?? modelData.description ?? ""
|
|
onClicked: {
|
|
if (!available)
|
|
return;
|
|
grid.chosen(modelData.id);
|
|
}
|
|
|
|
Rectangle {
|
|
id: miniTile
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
y: Theme.spacingS
|
|
width: preview.isUser ? height : parent.width - Theme.spacingS * 2
|
|
height: CcMetrics.previewTileHeight
|
|
radius: Theme.fullRadius(width, height)
|
|
color: preview.available ? CcMetrics.tileInactiveColor : Theme.onSurface_12
|
|
border.width: Theme.layerOutlineWidth
|
|
border.color: Theme.outlineMedium
|
|
|
|
DankIcon {
|
|
anchors.centerIn: parent
|
|
name: preview.modelData.icon
|
|
size: CcMetrics.iconBoxIconSize
|
|
color: preview.available ? CcMetrics.tileInactiveIcon : Theme.onSurface_38
|
|
}
|
|
}
|
|
|
|
StyledText {
|
|
id: label
|
|
anchors.top: miniTile.bottom
|
|
anchors.topMargin: Theme.spacingXS
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
width: parent.width - Theme.spacingXS * 2
|
|
text: preview.modelData.text
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
color: preview.available ? Theme.surfaceText : Theme.onSurface_38
|
|
horizontalAlignment: Text.AlignHCenter
|
|
wrapMode: Text.Wrap
|
|
maximumLineCount: 2
|
|
elide: Text.ElideRight
|
|
}
|
|
|
|
FocusRing {
|
|
visible: preview.visualFocus
|
|
}
|
|
|
|
StateLayer {
|
|
control: preview
|
|
tooltipText: preview.modelData.warning ?? ""
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
DankSearchField {
|
|
id: searchField
|
|
width: parent.width
|
|
height: Theme.fieldHeightLarge
|
|
placeholderText: I18n.tr("Search widgets...")
|
|
onAccepted: {
|
|
const first = root.matches.find(widget => widget.enabled !== false);
|
|
if (first)
|
|
root.chosen(first.id);
|
|
}
|
|
}
|
|
|
|
Repeater {
|
|
model: root.query === "" ? root.shownCategories : []
|
|
|
|
DankCollapsibleSection {
|
|
id: section
|
|
|
|
required property var modelData
|
|
required property int index
|
|
|
|
width: parent?.width ?? 0
|
|
title: modelData.title
|
|
expanded: index === 0
|
|
|
|
PreviewGrid {
|
|
Layout.fillWidth: true
|
|
entries: root.widgets.filter(widget => (widget.category ?? "plugins") === section.modelData.id)
|
|
onChosen: widgetId => root.chosen(widgetId)
|
|
}
|
|
}
|
|
}
|
|
|
|
PreviewGrid {
|
|
width: parent.width
|
|
visible: root.query !== ""
|
|
entries: root.query !== "" ? root.matches : []
|
|
onChosen: widgetId => root.chosen(widgetId)
|
|
}
|
|
|
|
StyledText {
|
|
width: parent.width
|
|
visible: root.matches.length === 0
|
|
topPadding: Theme.spacingL
|
|
bottomPadding: Theme.spacingL
|
|
text: I18n.tr("No widgets available")
|
|
font.pixelSize: Theme.fontSizeMedium
|
|
color: Theme.surfaceVariantText
|
|
horizontalAlignment: Text.AlignHCenter
|
|
}
|
|
}
|