Refactor AppLauncher, fix clipboardhistory, add persistent history (max 50 entries), add advanced math stuff
This commit is contained in:
parent
7ce8e51fa3
commit
044da17763
5 changed files with 690 additions and 263 deletions
158
Modules/AppLauncher/ClipboardHistory.qml
Normal file
158
Modules/AppLauncher/ClipboardHistory.qml
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import QtQuick
|
||||
import Quickshell
|
||||
import qs.Commons
|
||||
import qs.Services
|
||||
|
||||
QtObject {
|
||||
id: clipboardHistory
|
||||
|
||||
// Copy helpers for different content types
|
||||
function copyImageBase64(mime, base64) {
|
||||
Quickshell.execDetached(["sh", "-lc", `printf %s ${base64} | base64 -d | wl-copy -t '${mime}'`])
|
||||
}
|
||||
|
||||
function copyText(text) {
|
||||
// Use printf with proper quoting to handle special characters
|
||||
Quickshell.execDetached(["sh", "-c", `printf '%s' ${JSON.stringify(text)} | wl-copy -t text/plain`])
|
||||
}
|
||||
|
||||
// Create clipboard entry for display
|
||||
function createClipboardEntry(clip, index) {
|
||||
if (clip.type === 'image') {
|
||||
return {
|
||||
"isClipboard": true,
|
||||
"name": "Image from " + new Date(clip.timestamp).toLocaleTimeString(),
|
||||
"content": "Image: " + clip.mimeType,
|
||||
"icon": "image",
|
||||
"type": 'image',
|
||||
"data": clip.data,
|
||||
"timestamp": clip.timestamp,
|
||||
"index": index,
|
||||
"execute": function () {
|
||||
const dataParts = clip.data.split(',')
|
||||
const base64Data = dataParts.length > 1 ? dataParts[1] : clip.data
|
||||
copyImageBase64(clip.mimeType, base64Data)
|
||||
Quickshell.execDetached(["notify-send", "Clipboard", "Image copied: " + clip.mimeType])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Handle text content
|
||||
const textContent = clip.content || clip
|
||||
let displayContent = textContent
|
||||
let previewContent = ""
|
||||
|
||||
// Normalize whitespace for display
|
||||
displayContent = displayContent.replace(/\s+/g, ' ').trim()
|
||||
|
||||
// Create preview for long content
|
||||
if (displayContent.length > 50) {
|
||||
previewContent = displayContent
|
||||
displayContent = displayContent.split('\n')[0].substring(0, 50) + "..."
|
||||
}
|
||||
|
||||
return {
|
||||
"isClipboard": true,
|
||||
"name": displayContent,
|
||||
"content": previewContent || textContent,
|
||||
"icon": "content_paste",
|
||||
"type": 'text',
|
||||
"timestamp": clip.timestamp,
|
||||
"index": index,
|
||||
"textData": textContent, // Store the text data for the execute function
|
||||
"execute": function () {
|
||||
const text = this.textData || clip.content || clip
|
||||
Quickshell.clipboardText = String(text)
|
||||
copyText(String(text))
|
||||
var preview = (text.length > 50) ? text.slice(0, 50) + "…" : text
|
||||
Quickshell.execDetached(["notify-send", "Clipboard", "Text copied: " + preview])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create empty state entry
|
||||
function createEmptyEntry() {
|
||||
return {
|
||||
"isClipboard": true,
|
||||
"name": "No clipboard history",
|
||||
"content": "No matching clipboard entries found",
|
||||
"icon": "content_paste_off",
|
||||
"execute": function () {
|
||||
// Do nothing for empty state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process clipboard queries
|
||||
function processQuery(query) {
|
||||
const results = []
|
||||
|
||||
if (!query.startsWith(">clip")) {
|
||||
return results
|
||||
}
|
||||
|
||||
// Extract search term after ">clip "
|
||||
const searchTerm = query.slice(5).trim()
|
||||
|
||||
// Note: Clipboard refresh should be handled externally to avoid binding loops
|
||||
|
||||
// Process each clipboard item
|
||||
ClipboardService.history.forEach(function (clip, index) {
|
||||
let searchContent = clip.type === 'image' ? clip.mimeType : clip.content || clip
|
||||
|
||||
// Apply search filter if provided
|
||||
if (!searchTerm || searchContent.toLowerCase().includes(searchTerm.toLowerCase())) {
|
||||
const entry = createClipboardEntry(clip, index)
|
||||
results.push(entry)
|
||||
}
|
||||
})
|
||||
|
||||
// Show empty state if no results
|
||||
if (results.length === 0) {
|
||||
results.push(createEmptyEntry())
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// Create command entry for clipboard mode (deprecated - use direct creation in parent)
|
||||
function createCommandEntry() {
|
||||
return {
|
||||
"isCommand": true,
|
||||
"name": ">clip",
|
||||
"content": "Clipboard history - browse and restore clipboard items",
|
||||
"icon": "content_paste",
|
||||
"execute": function () {
|
||||
// This should be handled by the parent component
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utility function to refresh clipboard
|
||||
function refresh() {
|
||||
ClipboardService.refresh()
|
||||
}
|
||||
|
||||
// Get clipboard history count
|
||||
function getHistoryCount() {
|
||||
return ClipboardService.history ? ClipboardService.history.length : 0
|
||||
}
|
||||
|
||||
// Get formatted timestamp for display
|
||||
function formatTimestamp(timestamp) {
|
||||
return new Date(timestamp).toLocaleTimeString()
|
||||
}
|
||||
|
||||
// Get clipboard entry by index
|
||||
function getEntryByIndex(index) {
|
||||
if (ClipboardService.history && index >= 0 && index < ClipboardService.history.length) {
|
||||
return ClipboardService.history[index]
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Clear all clipboard history
|
||||
function clearAll() {
|
||||
ClipboardService.clearHistory()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue