Files
DankMaterialShell/quickshell/Modals/Greeter/GreeterPluginsPage.qml
T

221 lines
7.7 KiB
QML

import QtQuick
import qs.Common
import qs.Modules.Settings
import qs.Services
import qs.Widgets
Item {
id: root
property var greeterRoot: parent ? parent.greeterRoot : null
readonly property var curatedPluginIds: ["quickCapture", "dankKDEConnect", "wallpaperCarousel", "calculator", "emojiLauncher", "dockerManager", "amdGpuMonitor", "bongoCat"]
readonly property real headerIconContainerSize: Math.round(Theme.iconSize * 2)
property var curatedPlugins: []
property bool isLoading: false
property string loadError: ""
function refresh() {
isLoading = true;
loadError = "";
DMSService.listPlugins(response => {
isLoading = false;
if (response.error) {
loadError = response.error;
return;
}
curatedPlugins = curate(response.result || []);
});
if (DMSService.apiVersion >= 8)
DMSService.listInstalled();
}
function curate(registry) {
const byId = {};
for (let i = 0; i < registry.length; i++)
byId[registry[i].id] = registry[i];
const result = [];
for (let i = 0; i < curatedPluginIds.length; i++) {
const plugin = byId[curatedPluginIds[i]];
if (plugin)
result.push(plugin);
}
return result;
}
function markInstalled(installedList) {
const installedKeys = {};
for (let i = 0; i < installedList.length; i++) {
const plugin = installedList[i];
if (plugin.id)
installedKeys[plugin.id] = true;
if (plugin.name)
installedKeys[plugin.name] = true;
}
curatedPlugins = curatedPlugins.map(p => Object.assign({}, p, {
"installed": installedKeys[p.id] || installedKeys[p.name] || false
}));
}
Component.onCompleted: refresh()
Connections {
target: DMSService
function onInstalledPluginsReceived(plugins) {
root.markInstalled(plugins);
}
function onIsConnectedChanged() {
if (DMSService.isConnected && root.curatedPlugins.length === 0 && !root.isLoading)
root.refresh();
}
}
DankFlickable {
anchors.fill: parent
clip: true
contentHeight: mainColumn.height + Theme.spacingL * 2
contentWidth: width
Column {
id: mainColumn
anchors.horizontalCenter: parent.horizontalCenter
width: Math.min(640, parent.width - Theme.spacingXL * 2)
topPadding: Theme.spacingL
spacing: Theme.spacingL
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: Theme.spacingM
Rectangle {
width: root.headerIconContainerSize
height: root.headerIconContainerSize
radius: Math.round(root.headerIconContainerSize * 0.29)
color: Theme.primaryContainer
anchors.verticalCenter: parent.verticalCenter
DankIcon {
anchors.centerIn: parent
name: "extension"
size: Theme.iconSize + 4
color: Theme.primary
}
}
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingXXS
StyledText {
text: I18n.tr("Popular Plugins", "greeter plugins page title")
font.pixelSize: Theme.fontSizeXLarge
font.weight: Font.Bold
color: Theme.surfaceText
}
StyledText {
text: I18n.tr("Community favorites to get you started", "greeter plugins page subtitle")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
}
}
}
StyledText {
width: parent.width
text: I18n.tr("You can extend DMS with more applets, launcher features, and widgets through the plugin system. Hundreds are available on the official DMS registry, built by the community and the DMS team. Install some now, or later through the DMS CLI or the Settings window.", "greeter plugins page intro")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
}
Item {
width: parent.width
height: Math.round(Theme.fontSizeMedium * 8)
visible: root.isLoading
DankSpinner {
anchors.centerIn: parent
running: root.isLoading
}
}
Column {
width: parent.width
spacing: Theme.spacingS
visible: !root.isLoading && root.loadError !== ""
DankIcon {
anchors.horizontalCenter: parent.horizontalCenter
name: "cloud_off"
size: Theme.iconSize + 16
color: Theme.outline
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: I18n.tr("Couldn't load plugins", "plugin registry fetch error")
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceVariantText
}
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: root.loadError
font.pixelSize: Theme.fontSizeSmall
color: Theme.outline
}
DankButton {
anchors.horizontalCenter: parent.horizontalCenter
text: I18n.tr("Retry", "retry failed action button")
iconName: "refresh"
backgroundColor: Theme.surfaceContainerHighest
textColor: Theme.surfaceText
onClicked: root.refresh()
}
}
Grid {
width: parent.width
columns: 2
rowSpacing: Theme.spacingS
columnSpacing: Theme.spacingS
visible: !root.isLoading && root.curatedPlugins.length > 0
Repeater {
model: root.curatedPlugins
PluginCard {
required property var modelData
width: (parent.width - Theme.spacingS) / 2
previewHeight: Math.round(width * 0.45)
plugin: modelData
installed: modelData.installed || false
onClicked: {
if (modelData.repo)
Qt.openUrlExternally(modelData.repo);
}
onInstallRequested: PluginService.installFromRegistry(modelData.name, modelData.type === "desktop")
}
}
}
GreeterSettingsCard {
width: parent.width
iconName: "explore"
title: I18n.tr("Browse Plugins", "plugin browser window title")
description: I18n.tr("Browse or search plugins")
visible: !root.isLoading && root.loadError === ""
onClicked: PopoutService.openSettingsWithTab("plugins")
}
}
}
}