Add AppLauncher
This commit is contained in:
parent
4635aec80e
commit
2b39cbfe01
6 changed files with 788 additions and 19 deletions
139
Services/Clipboard.qml
Normal file
139
Services/Clipboard.qml
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
pragma Singleton
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import qs.Services
|
||||
|
||||
Singleton {
|
||||
id: root
|
||||
|
||||
property var history: []
|
||||
property bool initialized: false
|
||||
|
||||
// Internal state
|
||||
property bool _enabled: true
|
||||
|
||||
Timer {
|
||||
interval: 1000
|
||||
repeat: true
|
||||
running: root._enabled
|
||||
onTriggered: root.refresh()
|
||||
}
|
||||
|
||||
// Detect current clipboard types (text/image)
|
||||
Process {
|
||||
id: typeProcess
|
||||
property bool isLoading: false
|
||||
property var currentTypes: []
|
||||
|
||||
onExited: (exitCode, exitStatus) => {
|
||||
if (exitCode === 0) {
|
||||
currentTypes = String(stdout.text).trim().split('\n').filter(t => t)
|
||||
|
||||
const imageType = currentTypes.find(t => t.startsWith('image/'))
|
||||
if (imageType) {
|
||||
imageProcess.mimeType = imageType
|
||||
imageProcess.command = ["sh", "-c", `wl-paste -n -t "${imageType}" | base64 -w 0`]
|
||||
imageProcess.running = true
|
||||
} else {
|
||||
textProcess.command = ["wl-paste", "-n", "--type", "text/plain"]
|
||||
textProcess.running = true
|
||||
}
|
||||
} else {
|
||||
typeProcess.isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
stdout: StdioCollector {}
|
||||
}
|
||||
|
||||
// Read image data
|
||||
Process {
|
||||
id: imageProcess
|
||||
property string mimeType: ""
|
||||
|
||||
onExited: (exitCode, exitStatus) => {
|
||||
if (exitCode === 0) {
|
||||
const base64 = stdout.text.trim()
|
||||
if (base64) {
|
||||
const entry = {
|
||||
type: 'image',
|
||||
mimeType: mimeType,
|
||||
data: `data:${mimeType};base64,${base64}`,
|
||||
timestamp: new Date().getTime()
|
||||
}
|
||||
|
||||
const exists = root.history.find(item => item.type === 'image' && item.data === entry.data)
|
||||
if (!exists) {
|
||||
root.history = [entry, ...root.history].slice(0, 20)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!textProcess.isLoading) {
|
||||
root.initialized = true
|
||||
}
|
||||
typeProcess.isLoading = false
|
||||
}
|
||||
|
||||
stdout: StdioCollector {}
|
||||
}
|
||||
|
||||
// Read text data
|
||||
Process {
|
||||
id: textProcess
|
||||
property bool isLoading: false
|
||||
|
||||
onExited: (exitCode, exitStatus) => {
|
||||
if (exitCode === 0) {
|
||||
const content = String(stdout.text).trim()
|
||||
if (content) {
|
||||
const entry = {
|
||||
type: 'text',
|
||||
content: content,
|
||||
timestamp: new Date().getTime()
|
||||
}
|
||||
|
||||
const exists = root.history.find(item => {
|
||||
if (item.type === 'text') {
|
||||
return item.content === content
|
||||
}
|
||||
return item === content
|
||||
})
|
||||
|
||||
if (!exists) {
|
||||
const newHistory = root.history.map(item => {
|
||||
if (typeof item === 'string') {
|
||||
return {
|
||||
type: 'text',
|
||||
content: item,
|
||||
timestamp: new Date().getTime()
|
||||
}
|
||||
}
|
||||
return item
|
||||
})
|
||||
|
||||
root.history = [entry, ...newHistory].slice(0, 20)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
textProcess.isLoading = false
|
||||
}
|
||||
|
||||
root.initialized = true
|
||||
typeProcess.isLoading = false
|
||||
}
|
||||
|
||||
stdout: StdioCollector {}
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
if (!typeProcess.isLoading && !textProcess.isLoading) {
|
||||
typeProcess.isLoading = true
|
||||
typeProcess.command = ["wl-paste", "-l"]
|
||||
typeProcess.running = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -37,7 +37,8 @@ Item {
|
|||
IpcHandler {
|
||||
target: "appLauncher"
|
||||
|
||||
function toggle() {// TODO
|
||||
function toggle() {
|
||||
appLauncherPanel.isLoaded = !appLauncherPanel.isLoaded
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue