diff --git a/Model.js b/Model.js index 46089a6..41075f5 100644 --- a/Model.js +++ b/Model.js @@ -59,6 +59,14 @@ function accountLabel(account) { return String(account.id || "Unknown account") } +function loginPlan(needsLogin, authUrl) { + var url = String(authUrl || "").trim() + if (needsLogin === true && /^https?:\/\//.test(url)) { + return { authUrl: url, command: [] } + } + return { authUrl: "", command: ["tailscale", "up"] } +} + function peerFromStatus(id, peer) { return { id: id, @@ -270,6 +278,7 @@ if (typeof module !== "undefined") { displayHostName: displayHostName, osIcon: osIcon, accountLabel: accountLabel, + loginPlan: loginPlan, isMullvadPeer: isMullvadPeer, peerFromStatus: peerFromStatus, parseExitNodeList: parseExitNodeList, diff --git a/Panel.qml b/Panel.qml index 0f8f0b4..a6e084f 100644 --- a/Panel.qml +++ b/Panel.qml @@ -498,6 +498,56 @@ Panel { } } + CursorSurface { + id: connectionRow + visible: tailscale.installed && !tailscale.running + width: parent.width + implicitHeight: connectionText.implicitHeight + Style.spacing.rowPaddingX + hasCursor: root.cursorActive && root.focusSection === "header" + foreground: root.foreground + fill: root.hoverFill + + MouseArea { + anchors.fill: parent + hoverEnabled: true + enabled: !tailscale.busy + cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor + onEntered: { + root.cursorActive = true + root.focusSection = "header" + } + onClicked: tailscale.loginOrUp() + } + + Column { + id: connectionText + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: Style.space(12) + anchors.rightMargin: Style.space(12) + spacing: Style.space(2) + + Text { + width: parent.width + text: tailscale.needsLogin ? "Authorize this device" : "Connect Tailscale" + color: root.foreground + font.family: root.fontFamily + font.pixelSize: Style.font.body + font.weight: Font.Medium + } + + Text { + width: parent.width + text: tailscale.needsLogin ? "Open Tailscale to restore this device's access" : "Reconnect with the current Tailscale settings" + color: root.dim + font.family: root.fontFamily + font.pixelSize: Style.font.caption + wrapMode: Text.WordWrap + } + } + } + Text { visible: tailscale.actionStatus !== "" || tailscale.lastError !== "" width: parent.width diff --git a/Service.qml b/Service.qml index 820d3b4..aef8bfc 100644 --- a/Service.qml +++ b/Service.qml @@ -244,15 +244,19 @@ Item { function loginOrUp() { if (!installed || loginProcess.running) return + var plan = Model.loginPlan(needsLogin, authUrl) + if (plan.authUrl !== "") { + _loginUrlOpened = false + openAuthUrlFrom(plan.authUrl, true) + return + } _loginOutput = "" _loginError = "" actionStatus = needsLogin ? "Starting Tailscale login…" : "Turning Tailscale on…" _loginInProgress = needsLogin _loginUrlOpened = false _preLoginAuthUrl = authUrl - var command = ["tailscale", "up"] - if (needsLogin) command.push("--force-reauth") - loginProcess.command = command + loginProcess.command = plan.command loginProcess.running = true if (needsLogin) loginTimeoutTimer.restart() } @@ -317,9 +321,7 @@ Item { _loginUrlOpened = true _loginInProgress = false loginTimeoutTimer.stop() - Qt.openUrlExternally(url) - actionStatus = "Opened login link" - actionStatusTimer.restart() + Quickshell.execDetached(["omarchy-launch-browser", url]) return true } return false