130 lines
3.4 KiB
QML
130 lines
3.4 KiB
QML
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Hyprland
|
|
import Quickshell.Io
|
|
pragma Singleton
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
property var entries: []
|
|
property bool loading: false
|
|
property string error: ""
|
|
property string targetAddress: ""
|
|
property string pendingPassword: ""
|
|
property var passwordProcess: null
|
|
|
|
signal passwordReady(string password, string targetAddress)
|
|
|
|
function refresh() {
|
|
if (listReader.running)
|
|
return;
|
|
|
|
root.loading = true;
|
|
root.error = "";
|
|
listReader.command = ["rbw", "list", "--fields", "id,name,user,folder"];
|
|
listReader.running = true;
|
|
}
|
|
|
|
function getPassword(id, target) {
|
|
if (root.passwordProcess)
|
|
return;
|
|
|
|
root.targetAddress = target || "";
|
|
root.error = "";
|
|
root.passwordProcess = passwordProcessComponent.createObject(root, { entryId: id });
|
|
if (!root.passwordProcess) {
|
|
root.error = "Could not start rbw.";
|
|
return;
|
|
}
|
|
root.passwordProcess.running = true;
|
|
}
|
|
|
|
function typePassword(password, target) {
|
|
root.pendingPassword = password;
|
|
root.targetAddress = target || "";
|
|
typeDelay.restart();
|
|
}
|
|
|
|
Process {
|
|
id: listReader
|
|
|
|
command: []
|
|
stdout: StdioCollector {
|
|
id: listOutput
|
|
}
|
|
|
|
onExited: (code) => {
|
|
root.loading = false;
|
|
if (code !== 0) {
|
|
root.error = "Could not read the vault. Unlock it with rbw, then retry.";
|
|
root.entries = [];
|
|
return;
|
|
}
|
|
|
|
root.entries = listOutput.text.split(/\r?\n/).filter((line) => line !== "").map((line) => {
|
|
const fields = line.split("\t");
|
|
return {
|
|
id: fields[0] || "",
|
|
name: fields[1] || "Untitled",
|
|
user: fields[2] || "",
|
|
folder: fields[3] || ""
|
|
};
|
|
}).filter((entry) => entry.id !== "");
|
|
root.error = "";
|
|
}
|
|
}
|
|
|
|
Component {
|
|
id: passwordProcessComponent
|
|
|
|
Process {
|
|
id: passwordJob
|
|
|
|
property string entryId: ""
|
|
command: ["rbw", "get", entryId]
|
|
stdout: StdioCollector {
|
|
id: passwordOutput
|
|
}
|
|
|
|
onExited: (code) => {
|
|
if (root.passwordProcess === passwordJob)
|
|
root.passwordProcess = null;
|
|
if (code !== 0) {
|
|
root.error = "Could not read that password.";
|
|
} else {
|
|
root.passwordReady(passwordOutput.text.replace(/\r?\n$/, ""), root.targetAddress);
|
|
}
|
|
passwordJob.destroy();
|
|
}
|
|
}
|
|
}
|
|
|
|
Process {
|
|
id: typer
|
|
|
|
command: ["wtype", "-"]
|
|
stdinEnabled: true
|
|
onStarted: {
|
|
write(root.pendingPassword);
|
|
stdinEnabled = false;
|
|
root.pendingPassword = "";
|
|
root.targetAddress = "";
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
id: typeDelay
|
|
|
|
interval: 260
|
|
onTriggered: {
|
|
if (root.targetAddress !== "")
|
|
Hyprland.dispatch("focuswindow address:" + root.targetAddress);
|
|
|
|
typer.running = false;
|
|
typer.stdinEnabled = true;
|
|
typer.running = true;
|
|
}
|
|
}
|
|
}
|