From ddf76139d96165d0c5a2f80dfc732465b1afc5df Mon Sep 17 00:00:00 2001
From: Val Alexander
Date: Sat, 4 Apr 2026 14:09:30 -0500
Subject: [PATCH 1/2] Switch mobile pairing to link-based flow
- Replace QR display with a copyable pairing link
- Update mobile pairing copy in settings and onboarding
---
.../components/mobile/MobilePairingScreen.tsx | 4 +-
.../src/components/mobile/PairingQrCode.tsx | 57 +++++++++----------
apps/web/src/routes/_chat.settings.tsx | 6 +-
3 files changed, 32 insertions(+), 35 deletions(-)
diff --git a/apps/web/src/components/mobile/MobilePairingScreen.tsx b/apps/web/src/components/mobile/MobilePairingScreen.tsx
index a9522f9b2..d62748f7d 100644
--- a/apps/web/src/components/mobile/MobilePairingScreen.tsx
+++ b/apps/web/src/components/mobile/MobilePairingScreen.tsx
@@ -97,8 +97,8 @@ export function MobilePairingScreen() {
Pair this device
- Open Settings → Mobile Companion on your desktop to show a QR
- pairing code, then copy the link and paste it below.
+ Open Settings → Mobile Companion on your desktop to generate a
+ pairing link, then copy the link and paste it below.
diff --git a/apps/web/src/components/mobile/PairingQrCode.tsx b/apps/web/src/components/mobile/PairingQrCode.tsx
index 935060dde..c54197183 100644
--- a/apps/web/src/components/mobile/PairingQrCode.tsx
+++ b/apps/web/src/components/mobile/PairingQrCode.tsx
@@ -1,8 +1,8 @@
import { useCallback, useEffect, useState } from "react";
-import { generateQrSvg } from "../../lib/qrCode";
import { resolveServerHttpOrigin } from "../../lib/runtimeBridge";
import { Button } from "../ui/button";
+import { Input } from "../ui/input";
interface PairingInfo {
pairingUrl: string;
@@ -11,17 +11,14 @@ interface PairingInfo {
}
/**
- * PairingQrCode renders a QR code on the desktop web app that mobile devices
- * can scan to pair. It fetches a short-lived pairing link from the server's
- * `/api/pairing` endpoint and displays it as a scannable QR code.
- *
- * The QR code auto-refreshes when the pairing link expires.
+ * PairingLink renders the desktop pairing link used to connect a mobile
+ * device. It fetches a short-lived pairing link from the server's
+ * `/api/pairing` endpoint and lets the user copy it directly.
*/
-export function PairingQrCode() {
+export function PairingLink() {
const [pairing, setPairing] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
- const [svgHtml, setSvgHtml] = useState(null);
const [expiresIn, setExpiresIn] = useState(null);
const [copied, setCopied] = useState(false);
@@ -39,15 +36,12 @@ export function PairingQrCode() {
if ("error" in data) {
setError(data.error as unknown as string);
setPairing(null);
- setSvgHtml(null);
return;
}
setPairing(data);
- setSvgHtml(generateQrSvg(data.pairingUrl));
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to generate pairing link.");
setPairing(null);
- setSvgHtml(null);
} finally {
setLoading(false);
}
@@ -100,11 +94,11 @@ export function PairingQrCode() {
};
return (
-
- {expiresIn > 0 ? <>Expires in {formatTime(expiresIn)}> : <>Refreshing...>}
+ Copy this link and open it on the mobile app or device you want to pair.