Launcher: first refactoring pass
This commit is contained in:
parent
80a2e69eaa
commit
742a600e38
5 changed files with 383 additions and 666 deletions
105
Modules/Launcher/Plugins/CalculatorPlugin.qml
Normal file
105
Modules/Launcher/Plugins/CalculatorPlugin.qml
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
import QtQuick
|
||||
import qs.Services
|
||||
import "../../../Helpers/AdvancedMath.js" as AdvancedMath
|
||||
|
||||
QtObject {
|
||||
property var launcher: null
|
||||
property string name: "Calculator"
|
||||
|
||||
function handleCommand(query) {
|
||||
// Handle >calc command or direct math expressions after >
|
||||
return query.startsWith(">calc") || (query.startsWith(">") && query.length > 1 && isMathExpression(
|
||||
query.substring(1)))
|
||||
}
|
||||
|
||||
function commands() {
|
||||
return [{
|
||||
"name": ">calc",
|
||||
"description": "Calculator - evaluate mathematical expressions",
|
||||
"icon": "accessories-calculator",
|
||||
"onActivate": function () {
|
||||
launcher.setSearchText(">calc ")
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
function getResults(query) {
|
||||
let expression = ""
|
||||
|
||||
if (query.startsWith(">calc")) {
|
||||
expression = query.substring(5).trim()
|
||||
} else if (query.startsWith(">")) {
|
||||
expression = query.substring(1).trim()
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
|
||||
if (!expression) {
|
||||
return [{
|
||||
"name": "Calculator",
|
||||
"description": "Enter a mathematical expression",
|
||||
"icon": "accessories-calculator",
|
||||
"onActivate": function () {}
|
||||
}]
|
||||
}
|
||||
|
||||
try {
|
||||
let result = AdvancedMath.evaluate(expression.trim())
|
||||
|
||||
return [{
|
||||
"name": AdvancedMath.formatResult(result),
|
||||
"description": `${expression} = ${result}`,
|
||||
"icon": "accessories-calculator",
|
||||
"onActivate": function () {
|
||||
// Copy result to clipboard if service available
|
||||
// if (typeof ClipboardService !== 'undefined') {
|
||||
// ClipboardService.copy(result.toString())
|
||||
// }
|
||||
launcher.close()
|
||||
}
|
||||
}]
|
||||
} catch (error) {
|
||||
return [{
|
||||
"name": "Error",
|
||||
"description": error.message || "Invalid expression",
|
||||
"icon": "dialog-error",
|
||||
"onActivate": function () {}
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
function evaluateExpression(expr) {
|
||||
// Sanitize input - only allow safe characters
|
||||
const sanitized = expr.replace(/[^0-9\+\-\*\/\(\)\.\s\%]/g, '')
|
||||
if (sanitized !== expr) {
|
||||
throw new Error("Invalid characters in expression")
|
||||
}
|
||||
|
||||
// Don't allow empty expressions
|
||||
if (!sanitized.trim()) {
|
||||
throw new Error("Empty expression")
|
||||
}
|
||||
|
||||
try {
|
||||
// Use Function constructor for safe evaluation
|
||||
// This is safer than eval() but still evaluate math
|
||||
const result = Function('"use strict"; return (' + sanitized + ')')()
|
||||
|
||||
// Check for valid result
|
||||
if (!isFinite(result)) {
|
||||
throw new Error("Result is not a finite number")
|
||||
}
|
||||
|
||||
// Round to reasonable precision to avoid floating point issues
|
||||
return Math.round(result * 1000000000) / 1000000000
|
||||
} catch (e) {
|
||||
throw new Error("Invalid mathematical expression")
|
||||
}
|
||||
}
|
||||
|
||||
function isMathExpression(expr) {
|
||||
// Check if string looks like a math expression
|
||||
// Allow digits, operators, parentheses, decimal points, and whitespace
|
||||
return /^[\d\s\+\-\*\/\(\)\.\%]+$/.test(expr)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue