Files

312 lines
12 KiB
QML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import QtQuick
import QtQuick.Dialogs
import qs.config
import qs.services
Item {
id: root
property bool expanded: false
signal toggleExpanded
readonly property var phone: KdeConnect.preferredPhone
readonly property var actionModels: phoneActions.actionModels
PhoneActions {
id: phoneActions
}
implicitHeight: content.implicitHeight
Column {
id: content
width: parent.width
spacing: 6
ControlSectionHeader {
width: parent.width
label: "Phone"
action: root.phone ? (root.expanded ? "Details ⌃" : "Details ") : "Refresh"
onActionTriggered: {
if (root.phone)
root.toggleExpanded();
else
KdeConnect.refresh();
}
}
Rectangle {
width: parent.width
height: phoneContent.implicitHeight + 22
radius: Theme.cardRadius + 2
color: Theme.alpha(Theme.fg, 0.055)
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.05)
Column {
id: phoneContent
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 11
spacing: 9
Item {
width: parent.width
height: 46
Rectangle {
id: phoneSilhouette
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
width: 29
height: 43
radius: 8
color: Theme.alpha(Theme.accent, 0.07)
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.42)
Rectangle {
anchors.top: parent.top
anchors.topMargin: 4
anchors.horizontalCenter: parent.horizontalCenter
width: 10
height: 2
radius: 1
color: Theme.alpha(Theme.fg, 0.35)
}
Rectangle {
anchors.right: parent.right
anchors.rightMargin: -3
anchors.top: parent.top
anchors.topMargin: 10
width: 6
height: 6
radius: 3
visible: KdeConnect.phoneReachable
color: Theme.ok
}
}
Column {
anchors.left: phoneSilhouette.right
anchors.leftMargin: 11
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: 3
Text {
width: parent.width
text: root.phone?.name ?? (KdeConnect.available ? "No paired phone" : "KDE Connect unavailable")
color: Theme.fg
elide: Text.ElideRight
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
font.weight: Font.DemiBold
}
Text {
width: parent.width
text: root.phone
? (KdeConnect.phoneReachable ? "● Nearby on Wi-Fi" : "Not nearby")
: (KdeConnect.available ? "Pair a device to continue" : "Open settings to repair the service")
color: KdeConnect.phoneReachable ? Theme.ok : Theme.fgDim
elide: Text.ElideRight
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
}
}
Grid {
id: actionsGrid
width: parent.width
columns: 4
spacing: 7
Repeater {
model: root.actionModels
Rectangle {
id: actionButton
required property var modelData
width: (actionsGrid.width - actionsGrid.spacing * Math.max(0, root.actionModels.length - 1)) / Math.max(1, root.actionModels.length)
height: 48
radius: 11
color: actionMouse.containsMouse && actionMouse.enabled
? Theme.alpha(Theme.accent, 0.15)
: Theme.alpha(Theme.accent, 0.075)
border.width: actionMouse.activeFocus ? 2 : 0
border.color: Theme.accent
opacity: actionMouse.enabled ? 1 : 0.48
Accessible.role: Accessible.Button
Accessible.name: actionButton.modelData.label
Accessible.description: root.actionAccessibleDescription(actionButton.modelData.id)
Accessible.focusable: actionMouse.enabled
Accessible.focused: actionMouse.activeFocus
Accessible.onPressAction: {
if (actionMouse.enabled)
root.invoke(actionButton.modelData.id);
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 7
text: actionButton.modelData.glyph
color: Theme.accent
font.family: Theme.fontMono
font.pixelSize: 13
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 6
text: actionButton.modelData.label
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: 9
font.weight: Font.Medium
}
MouseArea {
id: actionMouse
anchors.fill: parent
enabled: root.actionEnabled(actionButton.modelData.id)
hoverEnabled: true
activeFocusOnTab: enabled
cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
onClicked: root.invoke(actionButton.modelData.id)
Keys.onReturnPressed: root.invoke(actionButton.modelData.id)
Keys.onSpacePressed: root.invoke(actionButton.modelData.id)
}
}
}
}
Text {
width: parent.width
visible: root.phone && !KdeConnect.phoneReachable && root.actionModels.length > 0
text: "KDE Connect actions are unavailable until the iPhone reconnects"
color: Theme.fgMuted
horizontalAlignment: Text.AlignHCenter
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
Text {
width: parent.width
visible: !SystemSettings.bluebubblesAvailable
text: "BlueBubbles is not installed"
color: Theme.fgMuted
horizontalAlignment: Text.AlignHCenter
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
Text {
width: parent.width
visible: KdeConnect.lastError !== ""
text: root.errorText(KdeConnect.lastError)
color: Theme.warn
horizontalAlignment: Text.AlignHCenter
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
Rectangle {
width: parent.width
height: 1
visible: KdeConnect.recentExchange !== null
color: Theme.alpha(Theme.fg, 0.07)
}
RecentExchange {
width: parent.width
height: visible ? implicitHeight : 0
visible: KdeConnect.recentExchange !== null
exchange: KdeConnect.recentExchange ?? ({})
}
}
}
Section {
width: parent.width
expanded: root.expanded && root.phone !== null
Column {
width: parent.width
spacing: 2
RowButton {
width: parent.width
icon: "network-wireless-symbolic"
label: "Connection"
sublabel: KdeConnect.phoneReachable ? "Nearby on Wi-Fi" : "Waiting for the phone"
selected: KdeConnect.phoneReachable
onClicked: KdeConnect.refresh()
}
RowButton {
width: parent.width
icon: "preferences-system-symbolic"
label: "Device settings"
sublabel: "Pairing, plugins and service health"
onClicked: {
ShellState.close();
ShellState.openSettings("connectivity");
}
}
}
}
}
FileDialog {
id: fileDialog
title: root.phone ? "Send a file to " + root.phone.name : "Send a file"
fileMode: FileDialog.OpenFile
nameFilters: ["All files (*)"]
onAccepted: {
const path = root.localPath(selectedFile);
if (path !== "")
KdeConnect.sendFile(path);
}
}
function invoke(action: string): void {
if (action === "share")
fileDialog.open();
else if (action === "clipboard")
KdeConnect.sendClipboard();
else if (action === "ring")
KdeConnect.ring();
else if (action === "messages") {
if (SystemSettings.bluebubblesAvailable && SystemSettings.openApplication("bluebubbles"))
ShellState.close();
}
}
function actionEnabled(action: string): bool {
return phoneActions.actionEnabled(action);
}
function actionAccessibleDescription(action: string): string {
if (action === "messages")
return SystemSettings.bluebubblesAvailable ? "Opens BlueBubbles" : "BlueBubbles is not installed";
return root.actionEnabled(action) ? "Available through KDE Connect" : "Unavailable through KDE Connect";
}
function localPath(selectedUrl: url): string {
const value = String(selectedUrl);
if (!value.startsWith("file://"))
return "";
return decodeURIComponent(value.slice(7));
}
function errorText(code: string): string {
if (code === "device-offline")
return "The iPhone is not nearby";
if (code === "unsupported-action")
return "That action is not available on this iPhone";
return "The phone action did not finish";
}
}