Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion ryoku/shell/quickshell/ryoshot/Icon.qml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ Item {
"mic": "M9 5a3 3 0 0 1 6 0v7a3 3 0 0 1 -6 0z M6 12a6 6 0 0 0 12 0 M12 18v3 M9 21h6",
"keyboard": "M3 6h18v12H3z M6 9h1 M10 9h1 M14 9h1 M18 9h1 M6 12h1 M10 12h1 M14 12h1 M18 12h1 M7 15h10",
"webcam": "M5 7h14v10H5z M15 12a3 3 0 1 1 -6 0a3 3 0 0 1 6 0z M12 17v3 M9 20h6",
"folder": "M3 6h7l2 2h9v11H3z"
"folder": "M3 6h7l2 2h9v11H3z",
"phone": "M6 2h12a2 2 0 0 1 2 2v16a2 2 0 0 1 -2 2H6a2 2 0 0 1 -2 -2V4a2 2 0 0 1 2 -2z M11 5h2 M12 18h.01"
})

readonly property string d: defs[name] !== undefined ? defs[name] : ""
Expand All @@ -70,3 +71,4 @@ Item {
}
}
}
"rect": "M5 6h14a1 1 0 0 1 1 1v10a1 1 0 0 1 -1 1H5a1 1 0 0 1 -1 -1V7a1 1 0 0 1 1 -1z",
3 changes: 2 additions & 1 deletion ryoku/shell/quickshell/ryoshot/IconButton.qml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Rectangle {
property bool dim: false
property string tooltip: ""
property real iconSize: 18
property color customTint: "transparent"

signal clicked()

Expand All @@ -22,7 +23,7 @@ Rectangle {
anchors.centerIn: parent
name: btn.icon
size: btn.iconSize
tint: btn.active ? Theme.accentInk : (btn.dim ? Theme.inkFaint : Theme.inkDim)
tint: btn.customTint.a > 0 ? btn.customTint : (btn.active ? Theme.accentInk : (btn.dim ? Theme.inkFaint : Theme.inkDim))
}

MouseArea {
Expand Down
2 changes: 2 additions & 0 deletions ryoku/shell/quickshell/ryoshot/ShortcutSheet.qml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Item {
{ key: "Ctrl+S", label: I18n.tr("Save") },
{ key: "Ctrl+P", label: I18n.tr("Pin") },
{ key: "Ctrl+U", label: I18n.tr("Upload") },
{ key: "Ctrl+K", label: I18n.tr("Send to phone") },
{ key: "Ctrl+B", label: I18n.tr("Beautify") },
{ key: "Enter", label: I18n.tr("Copy and save") },
{ key: "Ctrl+Z", label: I18n.tr("Undo") },
Expand Down Expand Up @@ -140,3 +141,4 @@ Item {
}
}
}
{ key: "Ctrl+C", label: I18n.tr("Copy") },
11 changes: 11 additions & 0 deletions ryoku/shell/quickshell/ryoshot/Toolbar.qml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Item {
property bool canUndo: false
property bool canRedo: false
property bool settingsOpen: false
property bool phoneConnected: false
property string phoneDeviceName: ""

readonly property real colorCenterX: colorBtn.x + row.x + colorBtn.width / 2
readonly property real widthCenterX: widthBtn.x + row.x + widthBtn.width / 2
Expand All @@ -36,6 +38,7 @@ Item {
signal copyRequested()
signal saveRequested()
signal uploadRequested()
signal phoneRequested()
signal pinRequested()
signal helpRequested()
signal settingsRequested()
Expand Down Expand Up @@ -204,6 +207,14 @@ Item {
IconButton { icon: "save"; tooltip: I18n.tr("Save") + " (ctrl+s)"; onClicked: tb.saveRequested() }
IconButton { icon: "pin"; tooltip: I18n.tr("Pin to desktop") + " (ctrl+p)"; onClicked: tb.pinRequested() }
IconButton { icon: "upload"; tooltip: I18n.tr("Upload") + " (ctrl+u)"; onClicked: tb.uploadRequested() }
IconButton {
icon: "phone"
customTint: tb.phoneConnected ? "transparent" : Theme.danger
tooltip: (tb.phoneConnected
? (tb.phoneDeviceName.length > 0 ? I18n.tr("Send to %1").arg(tb.phoneDeviceName) : I18n.tr("Send to phone"))
: I18n.tr("Send to phone (no device connected)")) + " (ctrl+k)"
onClicked: tb.phoneRequested()
}

Rectangle { Layout.preferredWidth: 1; Layout.preferredHeight: 20; color: Theme.hair; Layout.leftMargin: 3; Layout.rightMargin: 3 }

Expand Down
79 changes: 79 additions & 0 deletions ryoku/shell/quickshell/ryoshot/shell.qml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ ShellRoot {
property bool textEditing: false
property string openPopover: ""
property bool eyedropArmed: false
property bool phoneConnected: false
property string phoneDeviceName: ""

onPhaseChanged: {
if (phase === "editing" && !kdeStateProc.running)
kdeStateProc.running = true;
}

property var selectedIndex: null
property var moveOffset: null
Expand Down Expand Up @@ -1034,6 +1041,14 @@ ShellRoot {
});
}

function doSendPhone() {
var tmp = "/tmp/ryoshot-phone-" + Date.now() + ".png";
grabTo(tmp, function (ok) {
if (ok) { root.shutter(); kdePhoneProc.run(tmp); }
else Qt.quit();
});
}

/**
* Pins the finished shot: the PNG lands in the pin directory, the poke file
* wakes an already running host, and the flock spawn starts one if there is
Expand Down Expand Up @@ -1261,6 +1276,66 @@ ShellRoot {
}
}

Process {
id: kdePhoneProc
stdout: StdioCollector { id: kdePhoneOut }
function run(file) {
command = ["sh", "-c",
"dev=$(kdeconnect-cli -a --id-only 2>/dev/null | head -n 1)\n" +
"name=$(kdeconnect-cli -a --name-only 2>/dev/null | head -n 1)\n" +
"if [ -z \"$dev\" ]; then\n" +
" rm -f -- \"$1\"\n" +
" exit 2\n" +
"fi\n" +
"if kdeconnect-cli -d \"$dev\" --share \"$1\" >/dev/null 2>&1; then\n" +
" echo \"$name\"\n" +
" (sleep 15; rm -f -- \"$1\") &\n" +
" exit 0\n" +
"else\n" +
" (sleep 5; rm -f -- \"$1\") &\n" +
" exit 1\n" +
"fi",
"sh", file];
running = true;
}
onExited: (code) => {
var devName = kdePhoneOut.text.trim();
console.log("ryoshot: kdeconnect exit " + code + " target=" + JSON.stringify(devName));
if (code === 0) {
root.phoneConnected = true;
if (devName.length > 0) root.phoneDeviceName = devName;
var msg = devName.length > 0 ? I18n.tr("Sent to %1").arg(devName) : I18n.tr("Sent to phone");
root.notifySend(I18n.tr("Transferred via KDE Connect"), msg);
root.quitSoon();
} else if (code === 2) {
root.phoneConnected = false;
root.phoneDeviceName = "";
root.notifySend(I18n.tr("KDE Connect"), I18n.tr("No reachable device found"));
Qt.quit();
} else {
root.notifySend(I18n.tr("KDE Connect"), I18n.tr("Transfer failed"));
Qt.quit();
}
}
}

Process {
id: kdeStateProc
stdout: StdioCollector { id: kdeStateOut }
command: ["sh", "-c", "kdeconnect-cli -a --name-only 2>/dev/null | head -n 1"]
Component.onCompleted: running = true
onExited: (code) => {
if (code === 0) {
var name = kdeStateOut.text.trim();
root.phoneConnected = name.length > 0;
root.phoneDeviceName = name;
} else {
root.phoneConnected = false;
root.phoneDeviceName = "";
}
}
}

// Upload the crop, then open a reverse-image search on the hosted URL. Bing is
// the default engine iRiS settled on (Google and Yandex paste endpoints broke).
Process {
Expand Down Expand Up @@ -1345,6 +1420,7 @@ ShellRoot {
if (e.key === Qt.Key_S) { root.exportSaveOrStyled(); return true; }
if (e.key === Qt.Key_P) { root.doPin(); return true; }
if (e.key === Qt.Key_U) { root.doUpload(); return true; }
if (e.key === Qt.Key_K) { root.doSendPhone(); return true; }
if (e.key === Qt.Key_B) { root.openBeautify(); return true; }
if (e.key === Qt.Key_Z) { if (shift) root.redo(); else root.undo(); return true; }
if (e.key === Qt.Key_Y) { root.redo(); return true; }
Expand Down Expand Up @@ -1523,6 +1599,8 @@ ShellRoot {
canUndo: { root.annRevision; return root.model ? root.model.canUndo() : false; }
canRedo: { root.annRevision; return root.model ? root.model.canRedo() : false; }
settingsOpen: root.settingsOpen
phoneConnected: root.phoneConnected
phoneDeviceName: root.phoneDeviceName

x: {
if (!win.selLocal) return 0;
Expand All @@ -1546,6 +1624,7 @@ ShellRoot {
onCopyRequested: root.exportCopyOrStyled()
onSaveRequested: root.exportSaveOrStyled()
onUploadRequested: root.doUpload()
onPhoneRequested: root.doSendPhone()
onPinRequested: root.doPin()
onHelpRequested: root.shortcutsOpen = !root.shortcutsOpen
onSettingsRequested: root.settingsOpen = !root.settingsOpen
Expand Down
Loading