fix(telegram): show copyable /start command for pairing#2584
Conversation
…able deep link Telegram desktop ignores ?start=TOKEN for already-started bots — the deep link opens the conversation but sends /start without the payload. Replace the "Open Telegram" button UI with a copyable /start TOKEN command so users can paste it directly into the bot, which works on all clients. The deep link on the bot username is kept as a convenience to open Telegram, but pairing no longer depends on the start parameter being forwarded.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR fixes a known Telegram deep-link limitation: desktop clients that have already started the bot silently strip the Key changes:
Confidence Score: 5/5Safe to merge — the fix is correct, XSS hygiene is maintained, and the one open item is a non-blocking UX polish. All remaining findings are P2 style/UX suggestions (silent clipboard failure feedback). No correctness, data-integrity, or security issues were found. escapeHtml is applied consistently to all dynamic content in the innerHTML template, and the data-cmd to dataset.cmd HTML-entity round-trip is handled correctly by the browser. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
actor User
participant UI as Settings UI
participant API as /api/notification-channels
participant TG as Telegram
User->>UI: Clicks "Connect Telegram"
UI->>API: POST create-pairing-token
API-->>UI: { token, expiresAt }
UI-->>User: Show inline link + /start TOKEN + Copy button
alt User clicks Copy button
User->>UI: Clicks "Copy"
UI->>UI: navigator.clipboard.writeText("/start TOKEN")
UI-->>User: Button shows "Copied!" for 2s
User->>TG: Opens bot link, pastes & sends /start TOKEN
TG-->>API: Bot receives /start TOKEN payload
API->>API: claimPairingToken(TOKEN)
API-->>UI: Channel verified (poll detects)
UI-->>User: Pairing complete
else Token expires
UI->>UI: Countdown reaches 0, poll stops
UI-->>User: Reload pairing section
end
Reviews (1): Last reviewed commit: "fix(telegram): show /start command with ..." | Re-trigger Greptile |
src/services/preferences-content.ts
Outdated
| navigator.clipboard.writeText(cmd).then(() => { | ||
| btn.textContent = 'Copied!'; | ||
| setTimeout(() => { btn.textContent = 'Copy'; }, 2000); | ||
| }).catch(() => {}); |
There was a problem hiding this comment.
Silent clipboard failure gives no user feedback
When navigator.clipboard.writeText is rejected (e.g. clipboard permission denied, insecure context outside Tauri), the .catch(() => {}) swallows the error completely. The button label never changes from "Copy", so the user sees no reaction and may assume the click didn't register.
Consider surfacing a brief error state so the user knows to copy manually:
| navigator.clipboard.writeText(cmd).then(() => { | |
| btn.textContent = 'Copied!'; | |
| setTimeout(() => { btn.textContent = 'Copy'; }, 2000); | |
| }).catch(() => {}); | |
| navigator.clipboard.writeText(cmd).then(() => { | |
| btn.textContent = 'Copied!'; | |
| setTimeout(() => { btn.textContent = 'Copy'; }, 2000); | |
| }).catch(() => { | |
| btn.textContent = 'Failed'; | |
| setTimeout(() => { btn.textContent = 'Copy'; }, 2000); | |
| }); |
Generates an inline SVG QR code (uqr, no canvas required) encoding the t.me deep link so mobile users can scan instead of copy/paste. Desktop users still have the copy command + Open Telegram button. Layout: QR on the left (88×88), copy row + Open Telegram on the right.
- Open Telegram is now the primary action (button first) - Copy /start command is the visible fallback, always shown - QR code moves to right side as mobile convenience (not primary path) - Polling never calls reloadNotifSection on expiry; instead renders an in-place expired state with Generate new code button so users don't lose context - Generate new code and Try again re-use the same startTelegramPairing handler without backing out - Countdown shows Waiting... Ns instead of bare Ns - Clipboard fallback via execCommand when navigator.clipboard unavailable - Loading state shows Generating code... while token is being created
Two bugs from review:
- navigator.clipboard may be undefined; accessing .writeText on it threw
synchronously before .catch could run
- document.execCommand('copy') without a selected element copies nothing
Fix: guard with navigator.clipboard?.writeText, and in the fallback create
a temporary off-screen textarea, select its content, then execCommand.
Problem
Telegram desktop ignores
?start=TOKENfor bots the user has already started. The deep link opens the bot but sends just/startwith no payload —claimPairingTokennever matches, channel never pairs.Fix
Show the
/start TOKENcommand inline with a Copy button. User clicks the bot link to open Telegram, pastes the command and sends. Works on all clients.Post-Deploy Validation
Send copied command to bot → should receive welcome message.