From 306fa6f014319c81b24c11196d5a14a651ee85a3 Mon Sep 17 00:00:00 2001 From: "exe.dev user" Date: Mon, 4 May 2026 12:21:43 +0000 Subject: [PATCH] feat(setup): clearer "Open Telegram" copy + mobile fallback hint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two friction points in the Telegram channel's "Open Telegram" card, both surfaced when running setup on a VM-via-SSH where the user's local laptop has no Telegram client installed: 1. The opening sentence read "Opening @yourbot in Telegram so it's ready when the pairing code shows up." On a headless device that's misleading — nothing is auto-opened, the user has to click the link or use their phone. Rewrite as a direct, action-led instruction on the headless flow only: Open @yourbot in Telegram now — the pairing code is coming next, and that's where you'll send it. Plus a "Get started: " line and a full-strength mobile fallback hint inside the card so headless users have all self-serve options visible. On non-headless the original status-style line stays accurate (`xdg-open` / `open` does fire for users with Telegram desktop installed), so the card stays a single line. 2. Clicking `https://t.me/yourbot` silently fails when the user's local device has no Telegram client. Non-headless gains: - a "(must be installed here)" qualifier on the confirm prompt so users without Telegram desktop know up-front; - a single combined dim fallback line below the prompt: "If browser does not appear, please visit: — or search for @yourbot on your mobile." Direct `p.confirm` + `openUrl` instead of `confirmThenOpen` for the non-headless branch so we control the dim line fully (single combined line vs the helper's default URL-only line). Headless layout drives the same self-serve content via the card body itself; no confirm prompt fires there. --- setup/channels/telegram.ts | 40 ++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/setup/channels/telegram.ts b/setup/channels/telegram.ts index bf474f2..7117f5d 100644 --- a/setup/channels/telegram.ts +++ b/setup/channels/telegram.ts @@ -21,7 +21,8 @@ import * as p from '@clack/prompts'; import k from 'kleur'; import * as setupLog from '../logs.js'; -import { confirmThenOpen, formatNoteLink } from '../lib/browser.js'; +import { openUrl } from '../lib/browser.js'; +import { isHeadless } from '../platform.js'; import { askOperatorRole } from '../lib/role-prompt.js'; import { type Block, @@ -48,14 +49,37 @@ export async function runTelegramChannel(displayName: string): Promise { // installed, or the bot's web profile if not. tg://resolve?domain= is // more direct but silently fails when the scheme isn't registered. const botUrl = `https://t.me/${botUsername}`; - note( - [ + // Two card variants — auto-open fires only on GUI, so headless users + // need full self-serve instructions inside the card itself, while GUI + // users get a leaner status line plus the auto-open + a single + // combined dim fallback line (URL + mobile alternative) on the + // confirm prompt below. + if (isHeadless()) { + note( + [ + `Open @${botUsername} in Telegram now — the pairing code is coming next, and that's where you'll send it.`, + '', + `Get started: ${botUrl}`, + '', + `Don't have Telegram installed here? Open it on any device and search for @${botUsername}`, + ].join('\n'), + 'Open Telegram', + ); + } else { + note( `Opening @${botUsername} in Telegram so it's ready when the pairing code shows up.`, - formatNoteLink(botUrl), - ].filter((line): line is string => line !== null).join('\n'), - 'Open Telegram', - ); - await confirmThenOpen(botUrl, 'Press Enter to open Telegram'); + 'Open Telegram', + ); + ensureAnswer( + await p.confirm({ + message: `Press Enter to open Telegram (must be installed here)\n${k.dim( + `If browser does not appear, please visit: ${botUrl} — or search for @${botUsername} in Telegram`, + )}`, + initialValue: true, + }), + ); + openUrl(botUrl); + } const install = await runQuietChild( 'telegram-install',