1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 13:32:50 -05:00

launcher v2: sort order preference for plugin results

This commit is contained in:
bbedward
2026-01-21 14:08:40 -05:00
parent 3507c6cec3
commit 6ac2a305f7
4 changed files with 265 additions and 99 deletions

View File

@@ -96,6 +96,28 @@ Singleton {
saveSettings();
}
property var launcherPluginOrder: []
onLauncherPluginOrderChanged: saveSettings()
function setLauncherPluginOrder(order) {
launcherPluginOrder = order;
}
function getOrderedLauncherPlugins(allPlugins) {
if (!launcherPluginOrder || launcherPluginOrder.length === 0)
return allPlugins;
const orderMap = {};
for (let i = 0; i < launcherPluginOrder.length; i++)
orderMap[launcherPluginOrder[i]] = i;
return allPlugins.slice().sort((a, b) => {
const aOrder = orderMap[a.id] ?? 9999;
const bOrder = orderMap[b.id] ?? 9999;
if (aOrder !== bOrder)
return aOrder - bOrder;
return a.name.localeCompare(b.name);
});
}
property alias dankBarLeftWidgetsModel: leftWidgetsModel
property alias dankBarCenterWidgetsModel: centerWidgetsModel
property alias dankBarRightWidgetsModel: rightWidgetsModel

View File

@@ -416,7 +416,8 @@ var SPEC = {
desktopWidgetGroups: { def: [] },
builtInPluginSettings: { def: {} },
launcherPluginVisibility: { def: {} }
launcherPluginVisibility: { def: {} },
launcherPluginOrder: { def: [] }
};
function getValidKeys() {

View File

@@ -431,35 +431,29 @@ Item {
if (searchMode === "all") {
if (searchQuery) {
var allPluginIds = getVisibleLauncherPluginIds();
for (var i = 0; i < allPluginIds.length; i++) {
var pluginId = allPluginIds[i];
var pItems = getPluginItems(pluginId, searchQuery);
allItems = allItems.concat(pItems);
}
var allBuiltInIds = getVisibleBuiltInLauncherIds();
for (var i = 0; i < allBuiltInIds.length; i++) {
var pluginId = allBuiltInIds[i];
var blItems = AppSearchService.getBuiltInLauncherItems(pluginId, searchQuery);
for (var j = 0; j < blItems.length; j++) {
allItems.push(transformBuiltInLauncherItem(blItems[j], pluginId));
var allPluginsOrdered = getAllVisiblePluginsOrdered();
for (var i = 0; i < allPluginsOrdered.length; i++) {
var plugin = allPluginsOrdered[i];
if (plugin.isBuiltIn) {
var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
for (var j = 0; j < blItems.length; j++)
allItems.push(transformBuiltInLauncherItem(blItems[j], plugin.id));
} else {
var pItems = getPluginItems(plugin.id, searchQuery);
allItems = allItems.concat(pItems);
}
}
} else {
var emptyTriggerPlugins = getEmptyTriggerPlugins();
for (var i = 0; i < emptyTriggerPlugins.length; i++) {
var pluginId = emptyTriggerPlugins[i];
var pItems = getPluginItems(pluginId, searchQuery);
allItems = allItems.concat(pItems);
}
var builtInLauncherPlugins = getBuiltInEmptyTriggerLaunchers();
for (var i = 0; i < builtInLauncherPlugins.length; i++) {
var pluginId = builtInLauncherPlugins[i];
var blItems = AppSearchService.getBuiltInLauncherItems(pluginId, searchQuery);
for (var j = 0; j < blItems.length; j++) {
allItems.push(transformBuiltInLauncherItem(blItems[j], pluginId));
var emptyTriggerOrdered = getEmptyTriggerPluginsOrdered();
for (var i = 0; i < emptyTriggerOrdered.length; i++) {
var plugin = emptyTriggerOrdered[i];
if (plugin.isBuiltIn) {
var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
for (var j = 0; j < blItems.length; j++)
allItems.push(transformBuiltInLauncherItem(blItems[j], plugin.id));
} else {
var pItems = getPluginItems(plugin.id, searchQuery);
allItems = allItems.concat(pItems);
}
}
@@ -859,9 +853,10 @@ Item {
function getEmptyTriggerPlugins() {
var plugins = PluginService.getPluginsWithEmptyTrigger();
return plugins.filter(function (pluginId) {
var visible = plugins.filter(function (pluginId) {
return SettingsData.getPluginAllowWithoutTrigger(pluginId);
});
return sortPluginIdsByOrder(visible);
}
function getAllLauncherPluginIds() {
@@ -871,9 +866,10 @@ Item {
function getVisibleLauncherPluginIds() {
var launchers = PluginService.getLauncherPlugins();
return Object.keys(launchers).filter(function (pluginId) {
var visible = Object.keys(launchers).filter(function (pluginId) {
return SettingsData.getPluginAllowWithoutTrigger(pluginId);
});
return sortPluginIdsByOrder(visible);
}
function getAllBuiltInLauncherIds() {
@@ -883,9 +879,88 @@ Item {
function getVisibleBuiltInLauncherIds() {
var launchers = AppSearchService.getBuiltInLauncherPlugins();
return Object.keys(launchers).filter(function (pluginId) {
var visible = Object.keys(launchers).filter(function (pluginId) {
return SettingsData.getPluginAllowWithoutTrigger(pluginId);
});
return sortPluginIdsByOrder(visible);
}
function sortPluginIdsByOrder(pluginIds) {
var order = SettingsData.launcherPluginOrder || [];
if (order.length === 0)
return pluginIds;
var orderMap = {};
for (var i = 0; i < order.length; i++)
orderMap[order[i]] = i;
return pluginIds.slice().sort(function (a, b) {
var aOrder = orderMap[a] !== undefined ? orderMap[a] : 9999;
var bOrder = orderMap[b] !== undefined ? orderMap[b] : 9999;
return aOrder - bOrder;
});
}
function getAllVisiblePluginsOrdered() {
var thirdPartyLaunchers = PluginService.getLauncherPlugins() || {};
var builtInLaunchers = AppSearchService.getBuiltInLauncherPlugins() || {};
var all = [];
for (var id in thirdPartyLaunchers) {
if (SettingsData.getPluginAllowWithoutTrigger(id))
all.push({
id: id,
isBuiltIn: false
});
}
for (var id in builtInLaunchers) {
if (SettingsData.getPluginAllowWithoutTrigger(id))
all.push({
id: id,
isBuiltIn: true
});
}
var order = SettingsData.launcherPluginOrder || [];
if (order.length === 0)
return all;
var orderMap = {};
for (var i = 0; i < order.length; i++)
orderMap[order[i]] = i;
return all.sort(function (a, b) {
var aOrder = orderMap[a.id] !== undefined ? orderMap[a.id] : 9999;
var bOrder = orderMap[b.id] !== undefined ? orderMap[b.id] : 9999;
return aOrder - bOrder;
});
}
function getEmptyTriggerPluginsOrdered() {
var thirdParty = PluginService.getPluginsWithEmptyTrigger() || [];
var builtIn = AppSearchService.getBuiltInLauncherPluginsWithEmptyTrigger() || [];
var all = [];
for (var i = 0; i < thirdParty.length; i++) {
var id = thirdParty[i];
if (SettingsData.getPluginAllowWithoutTrigger(id))
all.push({
id: id,
isBuiltIn: false
});
}
for (var i = 0; i < builtIn.length; i++) {
var id = builtIn[i];
if (SettingsData.getPluginAllowWithoutTrigger(id))
all.push({
id: id,
isBuiltIn: true
});
}
var order = SettingsData.launcherPluginOrder || [];
if (order.length === 0)
return all;
var orderMap = {};
for (var i = 0; i < order.length; i++)
orderMap[order[i]] = i;
return all.sort(function (a, b) {
var aOrder = orderMap[a.id] !== undefined ? orderMap[a.id] : 9999;
var bOrder = orderMap[b.id] !== undefined ? orderMap[b.id] : 9999;
return aOrder - bOrder;
});
}
function getPluginBrowseItems() {
@@ -948,9 +1023,10 @@ Item {
function getBuiltInEmptyTriggerLaunchers() {
var plugins = AppSearchService.getBuiltInLauncherPluginsWithEmptyTrigger();
return plugins.filter(function (pluginId) {
var visible = plugins.filter(function (pluginId) {
return SettingsData.getPluginAllowWithoutTrigger(pluginId);
});
return sortPluginIdsByOrder(visible);
}
function getPluginItems(pluginId, query) {

View File

@@ -581,6 +581,7 @@ Item {
property var allLauncherPlugins: {
SettingsData.launcherPluginVisibility;
SettingsData.launcherPluginOrder;
var plugins = [];
var builtIn = AppSearchService.getBuiltInLauncherPlugins() || {};
for (var pluginId in builtIn) {
@@ -607,109 +608,175 @@ Item {
trigger: PluginService.getPluginTrigger(pluginId) || ""
});
}
return plugins.sort((a, b) => a.name.localeCompare(b.name));
return SettingsData.getOrderedLauncherPlugins(plugins);
}
function reorderPlugin(fromIndex, toIndex) {
if (fromIndex === toIndex)
return;
var currentOrder = allLauncherPlugins.map(p => p.id);
var item = currentOrder.splice(fromIndex, 1)[0];
currentOrder.splice(toIndex, 0, item);
SettingsData.setLauncherPluginOrder(currentOrder);
}
StyledText {
width: parent.width
text: I18n.tr("Control which plugins appear in 'All' mode without requiring a trigger prefix. Disabled plugins will only show when using their trigger.")
text: I18n.tr("Control which plugins appear in 'All' mode without requiring a trigger prefix. Drag to reorder.")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
wrapMode: Text.WordWrap
}
Column {
id: pluginVisibilityColumn
width: parent.width
spacing: Theme.spacingS
Repeater {
model: pluginVisibilityCard.allLauncherPlugins
delegate: Rectangle {
id: visibilityDelegate
delegate: Item {
id: visibilityDelegateItem
required property var modelData
required property int index
width: parent.width
property bool held: pluginDragArea.pressed
property real originalY: y
width: pluginVisibilityColumn.width
height: 52
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.3)
z: held ? 2 : 1
Row {
anchors.left: parent.left
anchors.leftMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
Rectangle {
id: visibilityDelegate
width: parent.width
height: 52
radius: Theme.cornerRadius
color: visibilityDelegateItem.held ? Theme.surfaceHover : Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.3)
Item {
width: Theme.iconSize
height: Theme.iconSize
Row {
anchors.left: parent.left
anchors.leftMargin: 28
anchors.verticalCenter: parent.verticalCenter
spacing: Theme.spacingM
DankIcon {
anchors.centerIn: parent
visible: visibilityDelegate.modelData.iconType !== "unicode"
name: visibilityDelegate.modelData.icon
size: Theme.iconSize
color: Theme.primary
Item {
width: Theme.iconSize
height: Theme.iconSize
anchors.verticalCenter: parent.verticalCenter
DankIcon {
anchors.centerIn: parent
visible: visibilityDelegateItem.modelData.iconType !== "unicode"
name: visibilityDelegateItem.modelData.icon
size: Theme.iconSize
color: Theme.primary
}
StyledText {
anchors.centerIn: parent
visible: visibilityDelegateItem.modelData.iconType === "unicode"
text: visibilityDelegateItem.modelData.icon
font.pixelSize: Theme.iconSize
color: Theme.primary
}
}
StyledText {
anchors.centerIn: parent
visible: visibilityDelegate.modelData.iconType === "unicode"
text: visibilityDelegate.modelData.icon
font.pixelSize: Theme.iconSize
color: Theme.primary
Column {
anchors.verticalCenter: parent.verticalCenter
spacing: 2
Row {
spacing: Theme.spacingS
StyledText {
text: visibilityDelegateItem.modelData.name
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
}
Rectangle {
visible: visibilityDelegateItem.modelData.isBuiltIn
width: dmsBadgeLabel.implicitWidth + Theme.spacingS
height: 16
radius: 8
color: Theme.primaryContainer
anchors.verticalCenter: parent.verticalCenter
StyledText {
id: dmsBadgeLabel
anchors.centerIn: parent
text: "DMS"
font.pixelSize: Theme.fontSizeSmall - 2
color: Theme.primaryText
}
}
}
StyledText {
text: visibilityDelegateItem.modelData.trigger ? I18n.tr("Trigger: %1").arg(visibilityDelegateItem.modelData.trigger) : I18n.tr("No trigger")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
}
}
}
Column {
DankToggle {
anchors.right: parent.right
anchors.rightMargin: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
spacing: 2
Row {
spacing: Theme.spacingS
StyledText {
text: visibilityDelegate.modelData.name
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
}
Rectangle {
visible: visibilityDelegate.modelData.isBuiltIn
width: dmsLabel.implicitWidth + Theme.spacingS
height: 16
radius: 8
color: Theme.primaryContainer
anchors.verticalCenter: parent.verticalCenter
StyledText {
id: dmsLabel
anchors.centerIn: parent
text: "DMS"
font.pixelSize: Theme.fontSizeSmall - 2
color: Theme.primaryText
}
}
}
StyledText {
text: visibilityDelegate.modelData.trigger ? I18n.tr("Trigger: %1").arg(visibilityDelegate.modelData.trigger) : I18n.tr("No trigger")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
checked: SettingsData.getPluginAllowWithoutTrigger(visibilityDelegateItem.modelData.id)
onToggled: function (isChecked) {
SettingsData.setPluginAllowWithoutTrigger(visibilityDelegateItem.modelData.id, isChecked);
}
}
}
DankToggle {
id: visibilityToggle
anchors.right: parent.right
anchors.rightMargin: Theme.spacingM
MouseArea {
id: pluginDragArea
anchors.left: parent.left
anchors.top: parent.top
width: 28
height: parent.height
hoverEnabled: true
cursorShape: Qt.SizeVerCursor
drag.target: visibilityDelegateItem.held ? visibilityDelegateItem : undefined
drag.axis: Drag.YAxis
preventStealing: true
onPressed: {
visibilityDelegateItem.originalY = visibilityDelegateItem.y;
}
onReleased: {
if (!drag.active) {
visibilityDelegateItem.y = visibilityDelegateItem.originalY;
return;
}
const spacing = Theme.spacingS;
const itemH = visibilityDelegateItem.height + spacing;
var newIndex = Math.round(visibilityDelegateItem.y / itemH);
newIndex = Math.max(0, Math.min(newIndex, pluginVisibilityCard.allLauncherPlugins.length - 1));
pluginVisibilityCard.reorderPlugin(visibilityDelegateItem.index, newIndex);
visibilityDelegateItem.y = visibilityDelegateItem.originalY;
}
}
DankIcon {
x: Theme.spacingXS
anchors.verticalCenter: parent.verticalCenter
checked: SettingsData.getPluginAllowWithoutTrigger(visibilityDelegate.modelData.id)
onToggled: function (isChecked) {
SettingsData.setPluginAllowWithoutTrigger(visibilityDelegate.modelData.id, isChecked);
name: "drag_indicator"
size: 18
color: Theme.outline
opacity: pluginDragArea.containsMouse || pluginDragArea.pressed ? 1 : 0.5
}
Behavior on y {
enabled: !pluginDragArea.pressed && !pluginDragArea.drag.active
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}