mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-31 08:52:49 -05:00
launcher: optimize bindings and filters
This commit is contained in:
@@ -467,6 +467,7 @@ Item {
|
|||||||
Item {
|
Item {
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height - y
|
height: parent.height - y
|
||||||
|
opacity: parentModal?.isClosing ? 0 : 1
|
||||||
|
|
||||||
SpotlightResults {
|
SpotlightResults {
|
||||||
id: resultsView
|
id: resultsView
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import Quickshell.Hyprland
|
|||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Modals.Common
|
import qs.Modals.Common
|
||||||
import qs.Services
|
|
||||||
|
|
||||||
DankModal {
|
DankModal {
|
||||||
id: spotlightModal
|
id: spotlightModal
|
||||||
@@ -18,62 +17,69 @@ DankModal {
|
|||||||
property bool spotlightOpen: false
|
property bool spotlightOpen: false
|
||||||
property alias spotlightContent: spotlightContentInstance
|
property alias spotlightContent: spotlightContentInstance
|
||||||
property bool openedFromOverview: false
|
property bool openedFromOverview: false
|
||||||
|
property bool isClosing: false
|
||||||
|
|
||||||
function show() {
|
function resetContent() {
|
||||||
openedFromOverview = false;
|
if (!spotlightContent)
|
||||||
spotlightOpen = true;
|
return;
|
||||||
open();
|
|
||||||
|
|
||||||
Qt.callLater(() => {
|
|
||||||
if (spotlightContent && spotlightContent.searchField) {
|
|
||||||
spotlightContent.searchField.forceActiveFocus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showWithQuery(query) {
|
|
||||||
if (spotlightContent) {
|
|
||||||
if (spotlightContent.appLauncher) {
|
|
||||||
spotlightContent.appLauncher.searchQuery = query;
|
|
||||||
}
|
|
||||||
if (spotlightContent.searchField) {
|
|
||||||
spotlightContent.searchField.text = query;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spotlightOpen = true;
|
|
||||||
open();
|
|
||||||
|
|
||||||
Qt.callLater(() => {
|
|
||||||
if (spotlightContent && spotlightContent.searchField) {
|
|
||||||
spotlightContent.searchField.forceActiveFocus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function hide() {
|
|
||||||
openedFromOverview = false;
|
|
||||||
spotlightOpen = false;
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
onDialogClosed: {
|
|
||||||
if (spotlightContent) {
|
|
||||||
if (spotlightContent.appLauncher) {
|
if (spotlightContent.appLauncher) {
|
||||||
spotlightContent.appLauncher.searchQuery = "";
|
spotlightContent.appLauncher.searchQuery = "";
|
||||||
spotlightContent.appLauncher.selectedIndex = 0;
|
spotlightContent.appLauncher.selectedIndex = 0;
|
||||||
spotlightContent.appLauncher.setCategory(I18n.tr("All"));
|
spotlightContent.appLauncher.setCategory(I18n.tr("All"));
|
||||||
}
|
}
|
||||||
if (spotlightContent.fileSearchController) {
|
if (spotlightContent.fileSearchController)
|
||||||
spotlightContent.fileSearchController.reset();
|
spotlightContent.fileSearchController.reset();
|
||||||
}
|
if (spotlightContent.resetScroll)
|
||||||
if (spotlightContent.resetScroll) {
|
|
||||||
spotlightContent.resetScroll();
|
spotlightContent.resetScroll();
|
||||||
}
|
if (spotlightContent.searchField)
|
||||||
if (spotlightContent.searchField) {
|
|
||||||
spotlightContent.searchField.text = "";
|
spotlightContent.searchField.text = "";
|
||||||
|
spotlightContent.searchMode = "apps";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function show() {
|
||||||
|
openedFromOverview = false;
|
||||||
|
isClosing = false;
|
||||||
|
resetContent();
|
||||||
|
spotlightOpen = true;
|
||||||
|
if (spotlightContent?.appLauncher)
|
||||||
|
spotlightContent.appLauncher.ensureInitialized();
|
||||||
|
open();
|
||||||
|
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (spotlightContent?.searchField)
|
||||||
|
spotlightContent.searchField.forceActiveFocus();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showWithQuery(query) {
|
||||||
|
openedFromOverview = false;
|
||||||
|
isClosing = false;
|
||||||
|
resetContent();
|
||||||
|
spotlightOpen = true;
|
||||||
|
if (spotlightContent?.appLauncher) {
|
||||||
|
spotlightContent.appLauncher.ensureInitialized();
|
||||||
|
spotlightContent.appLauncher.searchQuery = query;
|
||||||
|
}
|
||||||
|
if (spotlightContent?.searchField)
|
||||||
|
spotlightContent.searchField.text = query;
|
||||||
|
open();
|
||||||
|
|
||||||
|
Qt.callLater(() => {
|
||||||
|
if (spotlightContent?.searchField)
|
||||||
|
spotlightContent.searchField.forceActiveFocus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function hide() {
|
||||||
|
openedFromOverview = false;
|
||||||
|
isClosing = true;
|
||||||
|
spotlightOpen = false;
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
onDialogClosed: {
|
||||||
|
isClosing = false;
|
||||||
|
resetContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggle() {
|
function toggle() {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ DankPopout {
|
|||||||
|
|
||||||
onOpened: {
|
onOpened: {
|
||||||
searchMode = "apps";
|
searchMode = "apps";
|
||||||
|
appLauncher.ensureInitialized();
|
||||||
appLauncher.searchQuery = "";
|
appLauncher.searchQuery = "";
|
||||||
appLauncher.selectedIndex = 0;
|
appLauncher.selectedIndex = 0;
|
||||||
appLauncher.setCategory(I18n.tr("All"));
|
appLauncher.setCategory(I18n.tr("All"));
|
||||||
@@ -344,7 +345,7 @@ DankPopout {
|
|||||||
width: parent.width - Theme.spacingS * 2
|
width: parent.width - Theme.spacingS * 2
|
||||||
height: 40
|
height: 40
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
visible: searchField.text.length === 0 && appDrawerPopout.searchMode === "apps"
|
visible: appDrawerPopout.searchMode === "apps"
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
width: 180
|
width: 180
|
||||||
@@ -404,7 +405,7 @@ DankPopout {
|
|||||||
height: {
|
height: {
|
||||||
let usedHeight = 40 + Theme.spacingS;
|
let usedHeight = 40 + Theme.spacingS;
|
||||||
usedHeight += 52 + Theme.spacingS;
|
usedHeight += 52 + Theme.spacingS;
|
||||||
usedHeight += (searchField.text.length === 0 && appDrawerPopout.searchMode === "apps" ? 40 : 0);
|
usedHeight += appDrawerPopout.searchMode === "apps" ? 40 : 0;
|
||||||
return parent.height - usedHeight;
|
return parent.height - usedHeight;
|
||||||
}
|
}
|
||||||
radius: Theme.cornerRadius
|
radius: Theme.cornerRadius
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import QtQuick
|
import QtQuick
|
||||||
import QtQuick.Controls
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import qs.Common
|
import qs.Common
|
||||||
import qs.Services
|
import qs.Services
|
||||||
import qs.Widgets
|
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -23,15 +21,15 @@ Item {
|
|||||||
property bool keyboardNavigationActive: false
|
property bool keyboardNavigationActive: false
|
||||||
property bool suppressUpdatesWhileLaunching: false
|
property bool suppressUpdatesWhileLaunching: false
|
||||||
property var categories: {
|
property var categories: {
|
||||||
const allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science")
|
const allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science");
|
||||||
const result = [I18n.tr("All")]
|
const result = [I18n.tr("All")];
|
||||||
return result.concat(allCategories.filter(cat => cat !== I18n.tr("All")))
|
return result.concat(allCategories.filter(cat => cat !== I18n.tr("All")));
|
||||||
}
|
}
|
||||||
readonly property var categoryIcons: categories.map(category => AppSearchService.getCategoryIcon(category))
|
readonly property var categoryIcons: categories.map(category => AppSearchService.getCategoryIcon(category))
|
||||||
property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
|
property var appUsageRanking: AppUsageHistoryData.appUsageRanking || {}
|
||||||
property alias model: filteredModel
|
property alias model: filteredModel
|
||||||
property var _watchApplications: AppSearchService.applications
|
|
||||||
property var _uniqueApps: []
|
property var _uniqueApps: []
|
||||||
|
property bool _initialized: false
|
||||||
property bool _isTriggered: false
|
property bool _isTriggered: false
|
||||||
property string _triggeredCategory: ""
|
property string _triggeredCategory: ""
|
||||||
property bool _updatingFromTrigger: false
|
property bool _updatingFromTrigger: false
|
||||||
@@ -40,98 +38,109 @@ Item {
|
|||||||
signal categorySelected(string category)
|
signal categorySelected(string category)
|
||||||
signal viewModeSelected(string mode)
|
signal viewModeSelected(string mode)
|
||||||
|
|
||||||
|
function ensureInitialized() {
|
||||||
|
if (_initialized)
|
||||||
|
return;
|
||||||
|
_initialized = true;
|
||||||
|
updateFilteredModel();
|
||||||
|
}
|
||||||
|
|
||||||
function updateCategories() {
|
function updateCategories() {
|
||||||
const allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science")
|
const allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science");
|
||||||
const result = [I18n.tr("All")]
|
const result = [I18n.tr("All")];
|
||||||
categories = result.concat(allCategories.filter(cat => cat !== I18n.tr("All")))
|
categories = result.concat(allCategories.filter(cat => cat !== I18n.tr("All")));
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: PluginService
|
target: PluginService
|
||||||
function onPluginLoaded() { updateCategories() }
|
function onPluginLoaded() {
|
||||||
function onPluginUnloaded() { updateCategories() }
|
updateCategories();
|
||||||
function onPluginListUpdated() { updateCategories() }
|
}
|
||||||
|
function onPluginUnloaded() {
|
||||||
|
updateCategories();
|
||||||
|
}
|
||||||
|
function onPluginListUpdated() {
|
||||||
|
updateCategories();
|
||||||
|
}
|
||||||
function onRequestLauncherUpdate(pluginId) {
|
function onRequestLauncherUpdate(pluginId) {
|
||||||
// Only update if we are actually looking at this plugin or in All category
|
// Only update if we are actually looking at this plugin or in All category
|
||||||
updateFilteredModel()
|
updateFilteredModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: SettingsData
|
target: SettingsData
|
||||||
function onSortAppsAlphabeticallyChanged() {
|
function onSortAppsAlphabeticallyChanged() {
|
||||||
updateFilteredModel()
|
updateFilteredModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function updateFilteredModel() {
|
function updateFilteredModel() {
|
||||||
if (suppressUpdatesWhileLaunching) {
|
if (suppressUpdatesWhileLaunching) {
|
||||||
suppressUpdatesWhileLaunching = false
|
suppressUpdatesWhileLaunching = false;
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
filteredModel.clear()
|
filteredModel.clear();
|
||||||
selectedIndex = 0
|
selectedIndex = 0;
|
||||||
keyboardNavigationActive = false
|
keyboardNavigationActive = false;
|
||||||
|
|
||||||
const triggerResult = checkPluginTriggers(searchQuery)
|
const triggerResult = checkPluginTriggers(searchQuery);
|
||||||
if (triggerResult.triggered) {
|
if (triggerResult.triggered) {
|
||||||
console.log("AppLauncher: Plugin trigger detected:", triggerResult.trigger, "for plugin:", triggerResult.pluginId)
|
console.log("AppLauncher: Plugin trigger detected:", triggerResult.trigger, "for plugin:", triggerResult.pluginId);
|
||||||
}
|
}
|
||||||
|
|
||||||
let apps = []
|
let apps = [];
|
||||||
const allCategory = I18n.tr("All")
|
const allCategory = I18n.tr("All");
|
||||||
const emptyTriggerPlugins = typeof PluginService !== "undefined" ? PluginService.getPluginsWithEmptyTrigger() : []
|
const emptyTriggerPlugins = typeof PluginService !== "undefined" ? PluginService.getPluginsWithEmptyTrigger() : [];
|
||||||
|
|
||||||
if (triggerResult.triggered) {
|
if (triggerResult.triggered) {
|
||||||
_isTriggered = true
|
_isTriggered = true;
|
||||||
_triggeredCategory = triggerResult.pluginCategory
|
_triggeredCategory = triggerResult.pluginCategory;
|
||||||
_updatingFromTrigger = true
|
_updatingFromTrigger = true;
|
||||||
selectedCategory = triggerResult.pluginCategory
|
selectedCategory = triggerResult.pluginCategory;
|
||||||
_updatingFromTrigger = false
|
_updatingFromTrigger = false;
|
||||||
apps = AppSearchService.getPluginItems(triggerResult.pluginCategory, triggerResult.query)
|
apps = AppSearchService.getPluginItems(triggerResult.pluginCategory, triggerResult.query);
|
||||||
} else {
|
} else {
|
||||||
if (_isTriggered) {
|
if (_isTriggered) {
|
||||||
_updatingFromTrigger = true
|
_updatingFromTrigger = true;
|
||||||
selectedCategory = allCategory
|
selectedCategory = allCategory;
|
||||||
_updatingFromTrigger = false
|
_updatingFromTrigger = false;
|
||||||
_isTriggered = false
|
_isTriggered = false;
|
||||||
_triggeredCategory = ""
|
_triggeredCategory = "";
|
||||||
}
|
}
|
||||||
if (searchQuery.length === 0) {
|
if (searchQuery.length === 0) {
|
||||||
if (selectedCategory === allCategory) {
|
if (selectedCategory === allCategory) {
|
||||||
let emptyTriggerItems = []
|
let emptyTriggerItems = [];
|
||||||
emptyTriggerPlugins.forEach(pluginId => {
|
emptyTriggerPlugins.forEach(pluginId => {
|
||||||
const plugin = PluginService.getLauncherPlugin(pluginId)
|
const plugin = PluginService.getLauncherPlugin(pluginId);
|
||||||
const pluginCategory = plugin.name || pluginId
|
const pluginCategory = plugin.name || pluginId;
|
||||||
const items = AppSearchService.getPluginItems(pluginCategory, "")
|
const items = AppSearchService.getPluginItems(pluginCategory, "");
|
||||||
emptyTriggerItems = emptyTriggerItems.concat(items)
|
emptyTriggerItems = emptyTriggerItems.concat(items);
|
||||||
})
|
});
|
||||||
apps = AppSearchService.applications.concat(emptyTriggerItems)
|
apps = AppSearchService.applications.concat(emptyTriggerItems);
|
||||||
} else {
|
} else {
|
||||||
apps = AppSearchService.getAppsInCategory(selectedCategory).slice(0, maxResults)
|
apps = AppSearchService.getAppsInCategory(selectedCategory).slice(0, maxResults);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (selectedCategory === allCategory) {
|
if (selectedCategory === allCategory) {
|
||||||
apps = AppSearchService.searchApplications(searchQuery)
|
apps = AppSearchService.searchApplications(searchQuery);
|
||||||
|
|
||||||
let emptyTriggerItems = []
|
let emptyTriggerItems = [];
|
||||||
emptyTriggerPlugins.forEach(pluginId => {
|
emptyTriggerPlugins.forEach(pluginId => {
|
||||||
const plugin = PluginService.getLauncherPlugin(pluginId)
|
const plugin = PluginService.getLauncherPlugin(pluginId);
|
||||||
const pluginCategory = plugin.name || pluginId
|
const pluginCategory = plugin.name || pluginId;
|
||||||
const items = AppSearchService.getPluginItems(pluginCategory, searchQuery)
|
const items = AppSearchService.getPluginItems(pluginCategory, searchQuery);
|
||||||
emptyTriggerItems = emptyTriggerItems.concat(items)
|
emptyTriggerItems = emptyTriggerItems.concat(items);
|
||||||
})
|
});
|
||||||
apps = apps.concat(emptyTriggerItems)
|
apps = apps.concat(emptyTriggerItems);
|
||||||
} else {
|
} else {
|
||||||
const categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
|
const categoryApps = AppSearchService.getAppsInCategory(selectedCategory);
|
||||||
if (categoryApps.length > 0) {
|
if (categoryApps.length > 0) {
|
||||||
const allSearchResults = AppSearchService.searchApplications(searchQuery)
|
const allSearchResults = AppSearchService.searchApplications(searchQuery);
|
||||||
const categoryNames = new Set(categoryApps.map(app => app.name))
|
const categoryNames = new Set(categoryApps.map(app => app.name));
|
||||||
apps = allSearchResults.filter(searchApp => categoryNames.has(searchApp.name)).slice(0, maxResults)
|
apps = allSearchResults.filter(searchApp => categoryNames.has(searchApp.name)).slice(0, maxResults);
|
||||||
} else {
|
} else {
|
||||||
apps = []
|
apps = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,34 +149,34 @@ Item {
|
|||||||
if (searchQuery.length === 0) {
|
if (searchQuery.length === 0) {
|
||||||
if (SettingsData.sortAppsAlphabetically) {
|
if (SettingsData.sortAppsAlphabetically) {
|
||||||
apps = apps.sort((a, b) => {
|
apps = apps.sort((a, b) => {
|
||||||
return (a.name || "").localeCompare(b.name || "")
|
return (a.name || "").localeCompare(b.name || "");
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
apps = apps.sort((a, b) => {
|
apps = apps.sort((a, b) => {
|
||||||
const aId = a.id || a.execString || a.exec || ""
|
const aId = a.id || a.execString || a.exec || "";
|
||||||
const bId = b.id || b.execString || b.exec || ""
|
const bId = b.id || b.execString || b.exec || "";
|
||||||
const aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0
|
const aUsage = appUsageRanking[aId] ? appUsageRanking[aId].usageCount : 0;
|
||||||
const bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0
|
const bUsage = appUsageRanking[bId] ? appUsageRanking[bId].usageCount : 0;
|
||||||
if (aUsage !== bUsage) {
|
if (aUsage !== bUsage) {
|
||||||
return bUsage - aUsage
|
return bUsage - aUsage;
|
||||||
}
|
}
|
||||||
return (a.name || "").localeCompare(b.name || "")
|
return (a.name || "").localeCompare(b.name || "");
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const seenNames = new Set()
|
const seenNames = new Set();
|
||||||
const uniqueApps = []
|
const uniqueApps = [];
|
||||||
apps.forEach(app => {
|
apps.forEach(app => {
|
||||||
if (app) {
|
if (app) {
|
||||||
const itemKey = app.name + "|" + (app.execString || app.exec || app.action || "")
|
const itemKey = app.name + "|" + (app.execString || app.exec || app.action || "");
|
||||||
if (seenNames.has(itemKey)) {
|
if (seenNames.has(itemKey)) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
seenNames.add(itemKey)
|
seenNames.add(itemKey);
|
||||||
uniqueApps.push(app)
|
uniqueApps.push(app);
|
||||||
|
|
||||||
const isPluginItem = app.action !== undefined
|
const isPluginItem = app.action !== undefined;
|
||||||
filteredModel.append({
|
filteredModel.append({
|
||||||
"name": app.name || "",
|
"name": app.name || "",
|
||||||
"exec": app.execString || app.exec || app.action || "",
|
"exec": app.execString || app.exec || app.action || "",
|
||||||
@@ -176,102 +185,114 @@ Item {
|
|||||||
"categories": app.categories || [],
|
"categories": app.categories || [],
|
||||||
"isPlugin": isPluginItem,
|
"isPlugin": isPluginItem,
|
||||||
"appIndex": uniqueApps.length - 1
|
"appIndex": uniqueApps.length - 1
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
root._uniqueApps = uniqueApps
|
root._uniqueApps = uniqueApps;
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectNext() {
|
function selectNext() {
|
||||||
if (filteredModel.count === 0) {
|
if (filteredModel.count === 0) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
keyboardNavigationActive = true
|
keyboardNavigationActive = true;
|
||||||
selectedIndex = viewMode === "grid" ? Math.min(selectedIndex + gridColumns, filteredModel.count - 1) : Math.min(selectedIndex + 1, filteredModel.count - 1)
|
selectedIndex = viewMode === "grid" ? Math.min(selectedIndex + gridColumns, filteredModel.count - 1) : Math.min(selectedIndex + 1, filteredModel.count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectPrevious() {
|
function selectPrevious() {
|
||||||
if (filteredModel.count === 0) {
|
if (filteredModel.count === 0) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
keyboardNavigationActive = true
|
keyboardNavigationActive = true;
|
||||||
selectedIndex = viewMode === "grid" ? Math.max(selectedIndex - gridColumns, 0) : Math.max(selectedIndex - 1, 0)
|
selectedIndex = viewMode === "grid" ? Math.max(selectedIndex - gridColumns, 0) : Math.max(selectedIndex - 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectNextInRow() {
|
function selectNextInRow() {
|
||||||
if (filteredModel.count === 0 || viewMode !== "grid") {
|
if (filteredModel.count === 0 || viewMode !== "grid") {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
keyboardNavigationActive = true
|
keyboardNavigationActive = true;
|
||||||
selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1)
|
selectedIndex = Math.min(selectedIndex + 1, filteredModel.count - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectPreviousInRow() {
|
function selectPreviousInRow() {
|
||||||
if (filteredModel.count === 0 || viewMode !== "grid") {
|
if (filteredModel.count === 0 || viewMode !== "grid") {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
keyboardNavigationActive = true
|
keyboardNavigationActive = true;
|
||||||
selectedIndex = Math.max(selectedIndex - 1, 0)
|
selectedIndex = Math.max(selectedIndex - 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchSelected() {
|
function launchSelected() {
|
||||||
if (filteredModel.count === 0 || selectedIndex < 0 || selectedIndex >= filteredModel.count) {
|
if (filteredModel.count === 0 || selectedIndex < 0 || selectedIndex >= filteredModel.count) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
const selectedApp = filteredModel.get(selectedIndex)
|
const selectedApp = filteredModel.get(selectedIndex);
|
||||||
launchApp(selectedApp)
|
launchApp(selectedApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchApp(appData) {
|
function launchApp(appData) {
|
||||||
if (!appData || typeof appData.appIndex === "undefined" || appData.appIndex < 0 || appData.appIndex >= _uniqueApps.length) {
|
if (!appData || typeof appData.appIndex === "undefined" || appData.appIndex < 0 || appData.appIndex >= _uniqueApps.length) {
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
suppressUpdatesWhileLaunching = true
|
suppressUpdatesWhileLaunching = true;
|
||||||
|
|
||||||
const actualApp = _uniqueApps[appData.appIndex]
|
const actualApp = _uniqueApps[appData.appIndex];
|
||||||
|
|
||||||
if (appData.isPlugin) {
|
if (appData.isPlugin) {
|
||||||
const pluginId = getPluginIdForItem(actualApp)
|
const pluginId = getPluginIdForItem(actualApp);
|
||||||
if (pluginId) {
|
if (pluginId) {
|
||||||
AppSearchService.executePluginItem(actualApp, pluginId)
|
AppSearchService.executePluginItem(actualApp, pluginId);
|
||||||
appLaunched(appData)
|
appLaunched(appData);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SessionService.launchDesktopEntry(actualApp)
|
SessionService.launchDesktopEntry(actualApp);
|
||||||
appLaunched(appData)
|
appLaunched(appData);
|
||||||
AppUsageHistoryData.addAppUsage(actualApp)
|
AppUsageHistoryData.addAppUsage(actualApp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCategory(category) {
|
function setCategory(category) {
|
||||||
selectedCategory = category
|
selectedCategory = category;
|
||||||
categorySelected(category)
|
categorySelected(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setViewMode(mode) {
|
function setViewMode(mode) {
|
||||||
viewMode = mode
|
viewMode = mode;
|
||||||
viewModeSelected(mode)
|
viewModeSelected(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchQueryChanged: {
|
onSearchQueryChanged: {
|
||||||
|
if (!_initialized)
|
||||||
|
return;
|
||||||
if (debounceSearch) {
|
if (debounceSearch) {
|
||||||
searchDebounceTimer.restart()
|
searchDebounceTimer.restart();
|
||||||
} else {
|
} else {
|
||||||
updateFilteredModel()
|
updateFilteredModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onSelectedCategoryChanged: {
|
onSelectedCategoryChanged: {
|
||||||
if (_updatingFromTrigger) {
|
if (_updatingFromTrigger || !_initialized)
|
||||||
return
|
return;
|
||||||
|
updateFilteredModel();
|
||||||
}
|
}
|
||||||
updateFilteredModel()
|
|
||||||
|
onAppUsageRankingChanged: {
|
||||||
|
if (_initialized)
|
||||||
|
updateFilteredModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: DesktopEntries
|
||||||
|
function onApplicationsChanged() {
|
||||||
|
if (!root._initialized)
|
||||||
|
return;
|
||||||
|
root.updateCategories();
|
||||||
|
root.updateFilteredModel();
|
||||||
}
|
}
|
||||||
onAppUsageRankingChanged: updateFilteredModel()
|
|
||||||
on_WatchApplicationsChanged: updateFilteredModel()
|
|
||||||
Component.onCompleted: {
|
|
||||||
updateFilteredModel()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
@@ -289,59 +310,67 @@ Item {
|
|||||||
// Plugin trigger system functions
|
// Plugin trigger system functions
|
||||||
function checkPluginTriggers(query) {
|
function checkPluginTriggers(query) {
|
||||||
if (!query || typeof PluginService === "undefined") {
|
if (!query || typeof PluginService === "undefined") {
|
||||||
return { triggered: false, pluginCategory: "", query: "" }
|
return {
|
||||||
|
triggered: false,
|
||||||
|
pluginCategory: "",
|
||||||
|
query: ""
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggers = PluginService.getAllPluginTriggers()
|
const triggers = PluginService.getAllPluginTriggers();
|
||||||
|
|
||||||
for (const trigger in triggers) {
|
for (const trigger in triggers) {
|
||||||
if (query.startsWith(trigger)) {
|
if (query.startsWith(trigger)) {
|
||||||
const pluginId = triggers[trigger]
|
const pluginId = triggers[trigger];
|
||||||
const plugin = PluginService.getLauncherPlugin(pluginId)
|
const plugin = PluginService.getLauncherPlugin(pluginId);
|
||||||
|
|
||||||
if (plugin) {
|
if (plugin) {
|
||||||
const remainingQuery = query.substring(trigger.length).trim()
|
const remainingQuery = query.substring(trigger.length).trim();
|
||||||
const result = {
|
const result = {
|
||||||
triggered: true,
|
triggered: true,
|
||||||
pluginId: pluginId,
|
pluginId: pluginId,
|
||||||
pluginCategory: plugin.name || pluginId,
|
pluginCategory: plugin.name || pluginId,
|
||||||
query: remainingQuery,
|
query: remainingQuery,
|
||||||
trigger: trigger
|
trigger: trigger
|
||||||
}
|
};
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { triggered: false, pluginCategory: "", query: "" }
|
return {
|
||||||
|
triggered: false,
|
||||||
|
pluginCategory: "",
|
||||||
|
query: ""
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPluginIdForItem(item) {
|
function getPluginIdForItem(item) {
|
||||||
if (!item || !item.categories || typeof PluginService === "undefined") {
|
if (!item || !item.categories || typeof PluginService === "undefined") {
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const launchers = PluginService.getLauncherPlugins()
|
const launchers = PluginService.getLauncherPlugins();
|
||||||
for (const pluginId in launchers) {
|
for (const pluginId in launchers) {
|
||||||
const plugin = launchers[pluginId]
|
const plugin = launchers[pluginId];
|
||||||
const pluginCategory = plugin.name || pluginId
|
const pluginCategory = plugin.name || pluginId;
|
||||||
|
|
||||||
let hasCategory = false
|
let hasCategory = false;
|
||||||
if (Array.isArray(item.categories)) {
|
if (Array.isArray(item.categories)) {
|
||||||
hasCategory = item.categories.includes(pluginCategory)
|
hasCategory = item.categories.includes(pluginCategory);
|
||||||
} else if (item.categories && typeof item.categories.count !== "undefined") {
|
} else if (item.categories && typeof item.categories.count !== "undefined") {
|
||||||
for (let i = 0; i < item.categories.count; i++) {
|
for (let i = 0; i < item.categories.count; i++) {
|
||||||
if (item.categories.get(i) === pluginCategory) {
|
if (item.categories.get(i) === pluginCategory) {
|
||||||
hasCategory = true
|
hasCategory = true;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCategory) {
|
if (hasCategory) {
|
||||||
return pluginId
|
return pluginId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,12 @@ Scope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onShouldShowSpotlightChanged: {
|
onShouldShowSpotlightChanged: {
|
||||||
if (shouldShowSpotlight || !isActiveScreen)
|
if (shouldShowSpotlight) {
|
||||||
|
if (spotlightContent?.appLauncher)
|
||||||
|
spotlightContent.appLauncher.ensureInitialized();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isActiveScreen)
|
||||||
return;
|
return;
|
||||||
Qt.callLater(() => keyboardFocusScope.forceActiveFocus());
|
Qt.callLater(() => keyboardFocusScope.forceActiveFocus());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import qs.Common
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var applications: DesktopEntries.applications.values.filter(app => !app.noDisplay)
|
property var applications: []
|
||||||
|
property var _cachedCategories: null
|
||||||
|
|
||||||
readonly property int maxResults: 10
|
readonly property int maxResults: 10
|
||||||
readonly property int frecencySampleSize: 10
|
readonly property int frecencySampleSize: 10
|
||||||
@@ -36,6 +37,20 @@ Singleton {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
function refreshApplications() {
|
||||||
|
applications = DesktopEntries.applications.values;
|
||||||
|
_cachedCategories = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: DesktopEntries
|
||||||
|
function onApplicationsChanged() {
|
||||||
|
root.refreshApplications();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: refreshApplications()
|
||||||
|
|
||||||
function tokenize(text) {
|
function tokenize(text) {
|
||||||
return text.toLowerCase().trim().split(/[\s\-_]+/).filter(w => w.length > 0);
|
return text.toLowerCase().trim().split(/[\s\-_]+/).filter(w => w.length > 0);
|
||||||
}
|
}
|
||||||
@@ -316,19 +331,20 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getAllCategories() {
|
function getAllCategories() {
|
||||||
const categories = new Set([I18n.tr("All")]);
|
if (_cachedCategories)
|
||||||
|
return _cachedCategories;
|
||||||
|
|
||||||
|
const categories = new Set([I18n.tr("All")]);
|
||||||
for (const app of applications) {
|
for (const app of applications) {
|
||||||
const appCategories = getCategoriesForApp(app);
|
const appCategories = getCategoriesForApp(app);
|
||||||
appCategories.forEach(cat => categories.add(cat));
|
appCategories.forEach(cat => categories.add(cat));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add plugin categories
|
|
||||||
const pluginCategories = getPluginCategories();
|
const pluginCategories = getPluginCategories();
|
||||||
pluginCategories.forEach(cat => categories.add(cat));
|
pluginCategories.forEach(cat => categories.add(cat));
|
||||||
|
|
||||||
const result = Array.from(categories).sort();
|
_cachedCategories = Array.from(categories).sort();
|
||||||
return result;
|
return _cachedCategories;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAppsInCategory(category) {
|
function getAppsInCategory(category) {
|
||||||
|
|||||||
Binary file not shown.
@@ -1,86 +0,0 @@
|
|||||||
const vscode = require("vscode");
|
|
||||||
const path = require("path");
|
|
||||||
const fs = require("fs");
|
|
||||||
|
|
||||||
let watcher = null;
|
|
||||||
let reloadTimeout = null;
|
|
||||||
|
|
||||||
function activate(context) {
|
|
||||||
const themesDir = path.join(context.extensionPath, "themes");
|
|
||||||
|
|
||||||
try {
|
|
||||||
watcher = vscode.workspace.createFileSystemWatcher(
|
|
||||||
new vscode.RelativePattern(themesDir, "*.json")
|
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!watcher) return;
|
|
||||||
|
|
||||||
const reloadTheme = () => {
|
|
||||||
if (reloadTimeout) clearTimeout(reloadTimeout);
|
|
||||||
|
|
||||||
reloadTimeout = setTimeout(async () => {
|
|
||||||
const config = vscode.workspace.getConfiguration("workbench");
|
|
||||||
const currentTheme = config.get("colorTheme");
|
|
||||||
|
|
||||||
if (!currentTheme?.includes("DankShell")) return;
|
|
||||||
|
|
||||||
let themeFile;
|
|
||||||
switch (true) {
|
|
||||||
case currentTheme.includes("Light"):
|
|
||||||
themeFile = path.join(themesDir, "dankshell-light.json");
|
|
||||||
break;
|
|
||||||
case currentTheme.includes("Dark"):
|
|
||||||
themeFile = path.join(themesDir, "dankshell-dark.json");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
themeFile = path.join(themesDir, "dankshell-default.json");
|
|
||||||
}
|
|
||||||
|
|
||||||
let themeData;
|
|
||||||
try {
|
|
||||||
const content = fs.readFileSync(themeFile, "utf8");
|
|
||||||
themeData = JSON.parse(content);
|
|
||||||
} catch (e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const themeKey = `[${currentTheme}]`;
|
|
||||||
|
|
||||||
if (themeData.colors) {
|
|
||||||
const colorConfig = config.get("colorCustomizations") || {};
|
|
||||||
colorConfig[themeKey] = themeData.colors;
|
|
||||||
await config.update(
|
|
||||||
"colorCustomizations",
|
|
||||||
colorConfig,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (themeData.tokenColors) {
|
|
||||||
const editorConfig = vscode.workspace.getConfiguration("editor");
|
|
||||||
const tokenConfig = editorConfig.get("tokenColorCustomizations") || {};
|
|
||||||
tokenConfig[themeKey] = { textMateRules: themeData.tokenColors };
|
|
||||||
await editorConfig.update(
|
|
||||||
"tokenColorCustomizations",
|
|
||||||
tokenConfig,
|
|
||||||
vscode.ConfigurationTarget.Global
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, 150);
|
|
||||||
};
|
|
||||||
|
|
||||||
watcher.onDidChange(reloadTheme);
|
|
||||||
watcher.onDidCreate(reloadTheme);
|
|
||||||
|
|
||||||
context.subscriptions.push(watcher);
|
|
||||||
}
|
|
||||||
|
|
||||||
function deactivate() {
|
|
||||||
if (reloadTimeout) clearTimeout(reloadTimeout);
|
|
||||||
if (watcher) watcher.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { activate, deactivate };
|
|
||||||
@@ -7,10 +7,6 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"vscode": "^1.70.0"
|
"vscode": "^1.70.0"
|
||||||
},
|
},
|
||||||
"main": "./extension.js",
|
|
||||||
"activationEvents": [
|
|
||||||
"onStartupFinished"
|
|
||||||
],
|
|
||||||
"categories": [
|
"categories": [
|
||||||
"Themes"
|
"Themes"
|
||||||
],
|
],
|
||||||
@@ -31,17 +27,20 @@
|
|||||||
{
|
{
|
||||||
"label": "Dynamic Base16 DankShell",
|
"label": "Dynamic Base16 DankShell",
|
||||||
"uiTheme": "vs-dark",
|
"uiTheme": "vs-dark",
|
||||||
"path": "./themes/dankshell-default.json"
|
"path": "./themes/dankshell-default.json",
|
||||||
|
"_watch": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Dynamic Base16 DankShell (Dark)",
|
"label": "Dynamic Base16 DankShell (Dark)",
|
||||||
"uiTheme": "vs-dark",
|
"uiTheme": "vs-dark",
|
||||||
"path": "./themes/dankshell-dark.json"
|
"path": "./themes/dankshell-dark.json",
|
||||||
|
"_watch": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Dynamic Base16 DankShell (Light)",
|
"label": "Dynamic Base16 DankShell (Light)",
|
||||||
"uiTheme": "vs",
|
"uiTheme": "vs",
|
||||||
"path": "./themes/dankshell-light.json"
|
"path": "./themes/dankshell-light.json",
|
||||||
|
"_watch": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user