diff --git a/components/screenshot.tsx b/components/screenshot.tsx index b55446a2..aef1612d 100644 --- a/components/screenshot.tsx +++ b/components/screenshot.tsx @@ -4,11 +4,13 @@ export function Screenshot({ alt, caption, width, + lang = "en", }: { src?: string alt: string caption?: string width?: number + lang?: string }) { return (
@@ -17,7 +19,8 @@ export function Screenshot({ {alt} ) : (
- Screenshot needed: {alt} + {{ en: "Screenshot needed", ru: "Нужен скриншот", es: "Falta una captura" }[lang] ?? "Screenshot needed"}:{" "} + {alt}
)} {caption &&
{caption}
} diff --git a/components/tool-installation-intro.tsx b/components/tool-installation-intro.tsx index 4dd69212..4af4ce59 100644 --- a/components/tool-installation-intro.tsx +++ b/components/tool-installation-intro.tsx @@ -1,5 +1,7 @@ +import { Accordion, Accordions } from "fumadocs-ui/components/accordion" import Link from "next/link" import { InstallTool } from "@/components/install-tool" +import { Screenshot } from "@/components/screenshot" import { CopyText } from "@/components/text-snippet" import type { Tool } from "@/lib/shared" import { toolInstallationGuide } from "@/lib/tool-installation" @@ -29,17 +31,45 @@ export function ToolInstallationIntro({ tool, lang }: { tool: Tool; lang: string {section.steps && (
    {section.steps.map((step) => ( -
  1. {step}
  2. +
  3. + {step.text} + {step.screenshots.map((image) => ( + + ))} +
  4. ))}
)} {section.fallback && ( - <> -

{section.fallback.title}

- {section.fallback.paragraphs.map((paragraph) => ( -

{paragraph}

+
+ + + {section.fallback.command && } + {section.fallback.steps.length > 0 && ( +
    + {section.fallback.steps.map((step) => ( +
  1. + {step.text} + {step.screenshots.map((image) => ( + + ))} +
  2. + ))} +
+ )} + {section.fallback.paragraphs.map((paragraph) => ( +

{paragraph}

+ ))} +
+
+
+ )} + {section.recovery && ( + )} {section.links.map((link) => (

diff --git a/docs/screenshots-to-capture.md b/docs/screenshots-to-capture.md index c324ae4a..73c552a1 100644 --- a/docs/screenshots-to-capture.md +++ b/docs/screenshots-to-capture.md @@ -1,53 +1,49 @@ -# Screenshots to capture for "Install and log in" - -The page `content/docs/installation.mdx` shows a dashed "Screenshot needed" box in each place still -missing. Save each file under `public/screenshots/` with the exact name given; then the box is -replaced with the image. - -## How to get a fresh login on screen - -Run, from this folder: - -```sh -bin/login-screenshot tg -``` - -or `bin/login-screenshot max`. The script runs `setup` with empty throwaway folders, so the CLI -behaves like a first install and cannot see your real login, archive or settings. Your real login -keeps working. At the end it logs the test device out and deletes the folders. - -One thing stays behind on Telegram: if you finish the test login, the app ID and hash are saved in -your system keyring under an entry named after the deleted folder. It is harmless. - -## Before you start - -- Publish a QR screenshot only after confirming that its code has expired or been used successfully; otherwise cover the entire QR before sharing it. -- **Blur** phone numbers, names, usernames, the api_hash, login codes and chat titles. -- PNG or JPG. Phone screenshots at the phone's own size; terminal screenshots with a normal-width - window (about 100 columns). -- Crop to the part that matters: the prompt, the message, the menu item. - -## Telegram - -| # | File | What it must show | Status | -|---|---|---|---| -| 1 | `telegram/code-message.jpg` | The message from **Telegram** with the code for my.telegram.org | ✅ done | -| 2 | `telegram/terminal-qr.png` | The terminal during `bin/login-screenshot tg`, showing the QR code | needed | -| 3 | `telegram/add-device.jpg` | **Settings → Devices** with the **Add Device** button | ✅ done | - -## MAX - -| # | File | What it must show | Status | -|---|---|---|---| -| 4 | `max/terminal-qr.png` | The terminal during `max setup`, showing the QR code and completed setup | ✅ done | -| 5 | `max/devices-scanner.png` | MAX on your phone: **Settings → Devices**, with the button that opens the QR scanner | needed | - -## Optional - -| File | What it must show | -|---|---| -| `telegram/phone-prompt.png` | The terminal asking "phone number, international format:" (number blurred if typed) | -| `telegram/logged-in.png` | The end of setup: "Telegram is ready" and the five chats (names blurred) | -| `max/logged-in.png` | The end of `max setup`: the account line and the five chats (names blurred) | - -When the files are in place, tell me and I switch each placeholder to its image. +# Installation screenshots + +The Telegram and MAX installation guides show screenshots beside the relevant login steps: +`/{en,ru,es}/docs/tg/installation` and `/{en,ru,es}/docs/max/installation`. +The general installation page explains the shared setup and links to these guides. + +`lib/installation-screenshots.ts` owns placements, localized descriptions and capture filenames. +`components/screenshot.tsx` renders existing images or a localized dashed placeholder. The same +images and placeholder descriptions appear in the guides' Markdown counterparts. + +After saving a reviewed image under `public/screenshots/`, set its slot's `src` in +`lib/installation-screenshots.ts` to its target path. Saving the file alone does not replace a +placeholder. Check all three locales and mobile rendering before publishing. + +## Captures and placement + +| File | Placement | Status | +| --- | --- | --- | +| `telegram/code-message.jpg` | Code for my.telegram.org, before account QR login | Existing, restored | +| `telegram/terminal-qr.png` | Telegram account-login QR in the terminal | Needed | +| `telegram/add-device.jpg` | Phone Settings → Devices → Add Device | Existing, restored | +| `telegram/my-telegram-login.png` | Browser fallback: phone number and confirmation code | Existing, restored | +| `telegram/my-telegram-api-tools.png` | Browser fallback: API development tools | Existing, restored | +| `telegram/my-telegram-credentials.png` | Browser fallback: App api_id and App api_hash | Existing, restored | +| `max/terminal-qr-current.png` | Current MAX setup's account-login QR | Fresh capture needed | +| `max/devices-scanner.png` | MAX phone Settings → Devices, QR scanner | Needed | + +The older `max/terminal-qr.png` remains available as historical material. Its terminal output +uses earlier setup wording and step labels, so the current guide does not present it as the current +setup screen. Capture its replacement from the current supported tool. + +## Capture procedure + +With authorization to perform a live account login, run `bin/login-screenshot tg` or +`bin/login-screenshot max` from this repository. The script runs setup in throwaway folders, +keeps the existing login/archive/settings separate, and logs the test device out at the end. +Review the script's cleanup, including any application registration retained in the system +keyring, before a live capture. This documentation edit does not itself perform a login. + +Before publishing: + +- Confirm a QR code is expired or already used; otherwise cover the entire QR. +- Hide phone numbers, names, usernames, app hashes, login codes and private chat titles. +- Crop to the step the image explains, retaining the relevant label or prompt. +- Use PNG/JPG; preserve phone screenshots' proportions and a readable terminal width. +- Check the text against the current tool's supported commands and setup sequence. + +Optional later captures: `telegram/phone-prompt.png`, `telegram/logged-in.png` and +`max/logged-in.png`. These are not required to replace the current login placeholders. diff --git a/lib/installation-screenshots.ts b/lib/installation-screenshots.ts new file mode 100644 index 00000000..f829b543 --- /dev/null +++ b/lib/installation-screenshots.ts @@ -0,0 +1,80 @@ +export type InstallationScreenshot = { + src?: string + target: string + alt: string + width?: number +} + +const descriptions = { + en: [ + "Telegram message with the login code for my.telegram.org", + "Terminal showing the Telegram account-login QR code", + "Telegram Settings → Devices, with Add Device highlighted", + "my.telegram.org form for entering the phone number and confirmation code", + "my.telegram.org menu with API development tools highlighted", + "App configuration with App api_id and App api_hash highlighted", + "Terminal showing the MAX login QR code during setup", + "MAX Settings → Devices, with the QR scanner button", + ], + ru: [ + "Сообщение Telegram с кодом для входа на my.telegram.org", + "Терминал с QR-кодом для входа в аккаунт Telegram", + "Telegram: Настройки → Устройства, выделена кнопка Add Device", + "Форма my.telegram.org для номера телефона и кода подтверждения", + "Меню my.telegram.org, выделен пункт API development tools", + "App configuration, выделены App api_id и App api_hash", + "Терминал с QR-кодом для входа в MAX при настройке", + "MAX: Настройки → Устройства, кнопка сканера QR-кода", + ], + es: [ + "Mensaje de Telegram con el código para acceder a my.telegram.org", + "Terminal con el QR de inicio de sesión de Telegram", + "Telegram: Configuración → Dispositivos, con Add Device resaltado", + "Formulario de my.telegram.org para el teléfono y el código de confirmación", + "Menú de my.telegram.org con API development tools resaltado", + "App configuration con App api_id y App api_hash resaltados", + "Terminal con el QR de inicio de sesión de MAX durante la configuración", + "MAX: configuración y dispositivos, con el botón del escáner QR", + ], +} + +export function installationScreenshots(tool: string, lang: string) { + const labels = descriptions[lang === "ru" || lang === "es" ? lang : "en"] + const image = (file: string, index: number, width?: number): InstallationScreenshot => ({ + src: `/screenshots/${file}`, + target: `/screenshots/${file}`, + alt: labels[index], + width, + }) + const slot = (file: string, index: number, width?: number): InstallationScreenshot => ({ + target: `/screenshots/${file}`, + alt: labels[index], + width, + }) + return tool === "tg" + ? { + login: { + 1: [image("telegram/code-message.jpg", 0, 360)], + 2: [slot("telegram/terminal-qr.png", 1)], + 3: [image("telegram/add-device.jpg", 2, 360)], + } as Record, + browser: { + 0: [image("telegram/my-telegram-login.png", 3)], + 1: [image("telegram/my-telegram-api-tools.png", 4)], + 3: [image("telegram/my-telegram-credentials.png", 5)], + } as Record, + } + : { + login: { + 0: [slot("max/terminal-qr-current.png", 6, 1000)], + 1: [slot("max/devices-scanner.png", 7, 360)], + } as Record, + browser: {} as Record, + } +} + +export function screenshotMarkdown(screenshot: InstallationScreenshot, lang: string) { + if (screenshot.src) return `![${screenshot.alt}](${screenshot.src})` + const label = { en: "Screenshot needed", ru: "Нужен скриншот", es: "Falta una captura" }[lang] ?? "Screenshot needed" + return `*${label}: ${screenshot.alt}*` +} diff --git a/lib/tool-installation.ts b/lib/tool-installation.ts index c196970e..7f4f9818 100644 --- a/lib/tool-installation.ts +++ b/lib/tool-installation.ts @@ -1,3 +1,4 @@ +import { installationScreenshots, screenshotMarkdown } from "./installation-screenshots" import { wordsFor } from "./words" const copy = { @@ -28,14 +29,12 @@ Connect the tool's instructions to my agent. Then show my account and a few chat "If the agent cannot provide an interactive login prompt, open Terminal on macOS/Linux or PowerShell on Windows yourself and run the setup command below. Follow its prompts; keep the window open until the account check finishes.", tgSteps: [ "When setup asks for your phone number, enter it with the country code, for example +44… . This first confirmation lets the tool prepare the connection details that Telegram requires for your account.", - "Open Telegram on your phone and find the service message from Telegram with the code for my.telegram.org. Enter that code at the setup prompt. The tool reads your existing connection details or creates them for you; you do not need to write a program.", + "Open Telegram on your phone and find the service message from Telegram with the code for my.telegram.org. This code arrives in Telegram, not by SMS. Enter it at the setup prompt. The tool reads your existing connection details or creates them for you; you do not need to write a program.", "Next, wait for the account-login QR code on your computer. These are separate confirmations: the earlier code prepares the connection, while this QR code signs the tool in to your account.", - "In Telegram on your phone, open Settings → Devices and choose Link Desktop Device or Add Device. Allow camera access if asked, then point the scanner at the QR code shown by setup on your computer.", + "In Telegram on your phone, open Settings → Devices and choose Link Desktop Device or Add Device. Allow camera access if asked, then point the scanner at the QR code shown by setup on your computer. Use Telegram’s scanner, rather than the phone’s regular camera app.", "If setup asks for your additional Telegram password, enter the password you previously set in Telegram. This is different from the one-time code. Password input is hidden; type it and press Enter.", "Wait for setup to confirm the login and check your account and chats. This computer will appear among the connected devices in Telegram. If you interrupted setup, ask the agent to resume it; a completed login can be reused.", ], - tgFallback: - "If automatic connection setup fails, ask the agent to use browser registration. Open my.telegram.org/apps, sign in with your phone number and the code sent to Telegram, then open API development tools. For a new application, choose a name and short name, select Desktop, and create it. Enter App api_id and App api_hash when the setup terminal asks, then continue to QR login. These values identify the connection; they are not a bot token.", tgPhone: "If you cannot scan the QR code, ask the agent to choose phone-number login. Enter your number and the new login code at the setup prompts, followed by your additional Telegram password if requested. Use the delivery method shown by setup; the code may arrive in Telegram rather than by SMS.", maxSteps: [ @@ -53,6 +52,26 @@ Connect the tool's instructions to my agent. Then show my account and a few chat "Ask your agent to show your account and a few chats. Check that the name and chats belong to the account you intended to connect. If they do, the connection is ready. Finding older messages may require a separate history download; setup does not download your entire history.", archive: "Download the history you need", tasks: "Try your first task", + registrationWhy: + "Telegram first registers the program that will connect to your account. The app ID and app hash identify that connection; they do not grant access to messages on their own. The code for my.telegram.org lets setup complete this registration. Scanning the QR code is the separate step that authorises account access.", + deviceWhy: + "Login adds this computer as another device on your account, like a desktop messaging app. You can review it and revoke its access in your phone's device list. Setup connects your account; it does not download your entire chat history.", + browserSteps: [ + "Open my.telegram.org/apps and sign in with your phone number. Enter the code from the Telegram service chat on that page, rather than in the agent chat.", + "Choose API development tools. You need the application settings, rather than Delete account.", + "If there is no application yet, choose a title and short name, select Desktop and create it. If an application already exists, use it.", + "Enter App api_id and App api_hash in the setup terminal when prompted. The hash stays hidden while you type. These are connection identifiers, not a bot token.", + "Continue with the QR login described above.", + ], + recovery: [ + "Command not found: open a new terminal or restart the agent so it sees the installed tool. For Windows repairs, use the technical installation instructions below.", + "Not logged in: repeat setup and confirm the account login. For an expired session, follow the login help linked above.", + "A chat or older messages are missing: ask the agent to download the chat and period you need. An empty local history does not mean the chat has no messages.", + ], + agentCheck: + "If setup asks which agent you use, choose yours. Open a new agent session if the installed instructions have not loaded. If it still cannot use the tool, follow Connect your agent.", + agents: "Connect your agent", + permissions: "Choose what the agent may do", reference: "Manual setup and technical details", }, ru: { @@ -82,14 +101,12 @@ Connect the tool's instructions to my agent. Then show my account and a few chat "Если агент не может открыть ввод для подтверждения входа, откройте сами «Терминал» в macOS/Linux или PowerShell в Windows и запустите настройку командой ниже. Следуйте вопросам настройки и не закрывайте окно до проверки аккаунта.", tgSteps: [ "Когда настройка попросит номер телефона, введите его с кодом страны, например +7… . Это первое подтверждение нужно, чтобы инструмент подготовил данные подключения, которые Telegram требует для вашего аккаунта.", - "Откройте Telegram на телефоне и найдите служебное сообщение Telegram с кодом для my.telegram.org. Введите этот код в запросе настройки. Инструмент получит уже созданные данные подключения или создаст их за вас — писать программу не нужно.", + "Откройте Telegram на телефоне и найдите служебное сообщение Telegram с кодом для my.telegram.org. Этот код приходит в Telegram, а не по SMS. Введите его в запросе настройки. Инструмент получит уже созданные данные подключения или создаст их за вас — писать программу не нужно.", "Затем дождитесь QR-кода для входа в аккаунт на экране компьютера. Это два отдельных подтверждения: предыдущий код нужен для настройки подключения, а QR-код — для входа инструмента в ваш аккаунт.", - "В Telegram на телефоне откройте «Настройки» → «Устройства» и выберите «Подключить устройство» или «Привязать настольное устройство». Разрешите доступ к камере, если приложение попросит, и наведите сканер на QR-код, который настройка показала на компьютере.", + "В Telegram на телефоне откройте «Настройки» → «Устройства» и выберите «Добавить устройство» (Add Device) или «Привязать настольное устройство». Разрешите доступ к камере, если приложение попросит, и наведите сканер на QR-код, который настройка показала на компьютере. Используйте сканер внутри Telegram, а не обычное приложение камеры.", "Если настройка попросит дополнительный пароль Telegram, введите пароль, который вы ранее задали в Telegram. Это не одноразовый код. При вводе пароль не отображается — наберите его и нажмите Enter.", "Дождитесь подтверждения входа и проверки аккаунта и чатов. Компьютер появится в списке подключённых устройств Telegram. Если настройка прервалась, попросите агента продолжить её; уже выполненный вход можно использовать повторно.", ], - tgFallback: - "Если автоматическая настройка подключения не получилась, попросите агента выбрать регистрацию через браузер. Откройте my.telegram.org/apps, войдите по номеру телефона и коду из Telegram и выберите API development tools. Для нового приложения укажите название и краткое имя, выберите Desktop и создайте приложение. Введите App api_id и App api_hash, когда терминал настройки попросит их, затем продолжите вход по QR-коду. Эти значения обозначают подключение, а не токен бота.", tgPhone: "Если не получается отсканировать QR-код, попросите агента выбрать вход по номеру телефона. Введите номер и новый код для входа в запросах настройки, затем дополнительный пароль Telegram, если его попросят. Способ доставки кода покажет настройка: он может прийти в Telegram, а не по SMS.", maxSteps: [ @@ -107,6 +124,26 @@ Connect the tool's instructions to my agent. Then show my account and a few chat "Попросите агента показать ваш аккаунт и несколько чатов. Проверьте, что имя и чаты относятся к тому аккаунту, который вы хотели подключить. Если всё верно, подключение готово. Для поиска в старых сообщениях может понадобиться отдельно скачать нужный период; настройка не скачивает всю историю.", archive: "Скачать нужную историю", tasks: "Попробовать первую задачу", + registrationWhy: + "Сначала Telegram регистрирует программу, которая будет подключаться к аккаунту. App api_id и App api_hash обозначают это подключение; сами по себе они не дают доступа к сообщениям. Код для my.telegram.org позволяет настройке выполнить регистрацию. Сканирование QR-кода — отдельный шаг, который разрешает доступ к аккаунту.", + deviceWhy: + "Вход добавляет этот компьютер как ещё одно устройство аккаунта, подобно настольному приложению мессенджера. Его можно проверить и отключить в списке устройств на телефоне. Настройка подключает аккаунт, но не скачивает всю историю чатов.", + browserSteps: [ + "Откройте my.telegram.org/apps и войдите по номеру телефона. Код из служебного чата Telegram введите на этой странице, а не в чат с агентом.", + "Выберите API development tools. Нужны настройки приложения, а не Delete account.", + "Если приложения ещё нет, укажите название и краткое имя, выберите Desktop и создайте приложение. Если оно уже есть, используйте его.", + "Введите App api_id и App api_hash в терминал настройки, когда он попросит их. Хэш при вводе скрыт. Это данные подключения, а не токен бота.", + "Продолжите вход по QR-коду, как описано выше.", + ], + recovery: [ + "Команда не найдена: откройте новый терминал или перезапустите агента, чтобы он увидел установленный инструмент. Исправления для Windows есть в технических инструкциях установки ниже.", + "Нет входа в аккаунт: повторите настройку и подтвердите вход. Если сессия истекла, следуйте руководству по входу, ссылка на которое дана выше.", + "Не видно чата или старых сообщений: попросите агента скачать нужный чат и период. Пустая локальная история не означает, что в чате нет сообщений.", + ], + agentCheck: + "Если настройка спросит, какого агента вы используете, выберите своего. Откройте новую сессию агента, если установленные инструкции ещё не загрузились. Если он по-прежнему не умеет пользоваться инструментом, следуйте руководству подключения агента.", + agents: "Подключить агента", + permissions: "Выбрать, что разрешено агенту", reference: "Самостоятельная установка и технические детали", }, es: { @@ -136,14 +173,12 @@ Conecta las instrucciones de la herramienta a mi agente. Al final muestra mi cue "Si el agente no puede ofrecer un campo interactivo para confirmar el acceso, abre Terminal en macOS/Linux o PowerShell en Windows y ejecuta el comando de configuración de abajo. Sigue sus preguntas y mantén la ventana abierta hasta que termine la comprobación de la cuenta.", tgSteps: [ "Cuando la configuración pida tu número de teléfono, introdúcelo con el prefijo del país, por ejemplo +34… . Esta primera confirmación permite preparar los datos de conexión que Telegram requiere para tu cuenta.", - "Abre Telegram en el teléfono y busca el mensaje de servicio de Telegram con el código para my.telegram.org. Introduce el código cuando lo pida la configuración. La herramienta obtiene los datos de conexión existentes o los crea por ti; no necesitas programar.", + "Abre Telegram en el teléfono y busca el mensaje de servicio de Telegram con el código para my.telegram.org. Este código llega a Telegram, no por SMS. Introdúcelo cuando lo pida la configuración. La herramienta obtiene los datos de conexión existentes o los crea por ti; no necesitas programar.", "Después espera a que aparezca el código QR de inicio de sesión en el ordenador. Son dos confirmaciones distintas: el primer código prepara la conexión y el QR conecta la herramienta a tu cuenta.", - "En Telegram en el teléfono, abre Configuración → Dispositivos y elige Vincular dispositivo o Vincular dispositivo de escritorio. Permite el acceso a la cámara si se solicita y apunta el escáner al QR que muestra la configuración en el ordenador.", + "En Telegram en el teléfono, abre Configuración → Dispositivos y elige Vincular dispositivo o Vincular dispositivo de escritorio. Permite el acceso a la cámara si se solicita y apunta el escáner al QR que muestra la configuración en el ordenador. Usa el escáner de Telegram, en lugar de la cámara habitual del teléfono.", "Si la configuración pide la contraseña adicional de Telegram, introduce la que habías establecido en Telegram. Es distinta del código de un solo uso. La contraseña no se muestra al escribir; introdúcela y pulsa Enter.", "Espera a la confirmación del inicio de sesión y a la comprobación de la cuenta y los chats. El ordenador aparecerá entre los dispositivos conectados en Telegram. Si interrumpiste la configuración, pide al agente que la continúe; puede reutilizar el acceso ya confirmado.", ], - tgFallback: - "Si falla la preparación automática de la conexión, pide al agente que elija el registro en el navegador. Abre my.telegram.org/apps, inicia sesión con tu número y el código recibido en Telegram y entra en API development tools. Para una aplicación nueva, elige un nombre y un nombre corto, selecciona Desktop y créala. Introduce App api_id y App api_hash cuando el terminal de configuración los pida y continúa con el QR. Estos valores identifican la conexión; no son un token de bot.", tgPhone: "Si no puedes escanear el QR, pide al agente que elija el inicio de sesión por número de teléfono. Introduce el número y el nuevo código cuando lo pida la configuración, seguido de la contraseña adicional de Telegram si se solicita. Sigue el método de entrega que indique la configuración: el código puede llegar a Telegram en lugar de por SMS.", maxSteps: [ @@ -161,6 +196,26 @@ Conecta las instrucciones de la herramienta a mi agente. Al final muestra mi cue "Pide al agente que muestre tu cuenta y algunos chats. Comprueba que el nombre y los chats pertenecen a la cuenta que querías conectar. Si es así, la conexión está lista. Para buscar mensajes antiguos puede ser necesario descargar ese período por separado; la configuración no descarga todo el historial.", archive: "Descargar el historial que necesitas", tasks: "Probar la primera tarea", + registrationWhy: + "Telegram registra primero el programa que se conectará a la cuenta. App api_id y App api_hash identifican esa conexión; por sí solos no permiten leer mensajes. El código de my.telegram.org permite completar el registro. Escanear el QR es el paso separado que autoriza el acceso a la cuenta.", + deviceWhy: + "El acceso añade este ordenador como otro dispositivo de tu cuenta, igual que una aplicación de mensajería de escritorio. Puedes revisarlo y revocar su acceso desde la lista de dispositivos del teléfono. La configuración conecta la cuenta; no descarga todo el historial.", + browserSteps: [ + "Abre my.telegram.org/apps e inicia sesión con tu número. Introduce el código del chat de servicio de Telegram en esa página, en lugar del chat con el agente.", + "Elige API development tools. Necesitas los ajustes de la aplicación, en lugar de Delete account.", + "Si todavía no hay una aplicación, elige un título y un nombre corto, selecciona Desktop y créala. Si ya existe, úsala.", + "Introduce App api_id y App api_hash en el terminal de configuración cuando los pida. El hash permanece oculto al escribir. Son datos de conexión, no un token de bot.", + "Continúa con el inicio de sesión por QR descrito arriba.", + ], + recovery: [ + "Comando no encontrado: abre un terminal nuevo o reinicia el agente para que vea la herramienta instalada. Las instrucciones técnicas de abajo incluyen las soluciones para Windows.", + "No has iniciado sesión: repite la configuración y confirma el acceso. Para una sesión caducada, sigue la guía de acceso enlazada arriba.", + "Falta un chat o mensajes antiguos: pide al agente que descargue el chat y el período necesarios. Un historial local vacío no demuestra que el chat no tenga mensajes.", + ], + agentCheck: + "Si la configuración pregunta qué agente usas, elige el tuyo. Abre una sesión nueva del agente si las instrucciones instaladas aún no se han cargado. Si sigue sin poder usar la herramienta, consulta la guía de conexión del agente.", + agents: "Conectar el agente", + permissions: "Elegir qué puede hacer el agente", reference: "Instalación manual y detalles técnicos", }, } @@ -169,6 +224,7 @@ export function toolInstallationGuide(tool: string, lang: string) { const text = copy[lang === "ru" || lang === "es" ? lang : "en"] const name = tool === "tg" ? "Telegram" : "MAX" const root = `/${lang}/docs` + const screenshots = installationScreenshots(tool, lang) return { intro: text.intro(name), title: wordsFor(lang).navigation.installGuide, @@ -190,12 +246,20 @@ export function toolInstallationGuide(tool: string, lang: string) { { id: "install-login", title: text.titles[2], - paragraphs: [text.login, text.manualLogin], + paragraphs: [text.login, text.deviceWhy, ...(tool === "tg" ? [text.registrationWhy] : []), text.manualLogin], command: `${tool} setup`, - steps: tool === "tg" ? text.tgSteps : text.maxSteps, + steps: (tool === "tg" ? text.tgSteps : text.maxSteps).map((text, index) => ({ + text, + screenshots: screenshots.login[index] ?? [], + })), fallback: { title: text.fallback, - paragraphs: tool === "tg" ? [text.tgFallback, text.tgPhone] : [text.maxFallback], + paragraphs: tool === "tg" ? [text.tgPhone] : [text.maxFallback], + command: tool === "tg" ? "tg setup --app browser" : undefined, + steps: + tool === "tg" + ? text.browserSteps.map((text, index) => ({ text, screenshots: screenshots.browser[index] ?? [] })) + : [], }, links: [ { @@ -208,10 +272,13 @@ export function toolInstallationGuide(tool: string, lang: string) { { id: "install-check", title: text.titles[3], - paragraphs: [text.check], + paragraphs: [text.check, text.agentCheck], + recovery: text.recovery, links: [ { label: text.tasks, href: `${root}/first-tasks` }, { label: text.archive, href: `${root}/${tool}/archive` }, + { label: text.agents, href: `${root}/agents` }, + { label: text.permissions, href: `${root}/permissions` }, ], }, ], @@ -229,8 +296,28 @@ export function toolInstallationMarkdown(slugs: string[], lang: string) { ...section.paragraphs, ...(section.command ? [`\`\`\`sh\n${section.command}\n\`\`\``] : []), ...(section.request ? [`\`\`\`text\n${section.request}\n\`\`\``] : []), - ...(section.steps ? [section.steps.map((step, i) => `${i + 1}. ${step}`).join("\n")] : []), - ...(section.fallback ? [`#### ${section.fallback.title}`, ...section.fallback.paragraphs] : []), + ...(section.steps + ? [ + section.steps + .map( + (step, i) => + `${i + 1}. ${step.text}${step.screenshots.map((image) => `\n\n ${screenshotMarkdown(image, lang)}`).join("")}`, + ) + .join("\n"), + ] + : []), + ...(section.fallback + ? [ + `#### ${section.fallback.title}`, + ...(section.fallback.command ? [`\`\`\`sh\n${section.fallback.command}\n\`\`\``] : []), + ...section.fallback.steps.map( + (step, i) => + `${i + 1}. ${step.text}${step.screenshots.map((image) => `\n\n ${screenshotMarkdown(image, lang)}`).join("")}`, + ), + ...section.fallback.paragraphs, + ] + : []), + ...(section.recovery ? [section.recovery.map((item) => `- ${item}`).join("\n")] : []), ...section.links.map((link) => `[${link.label}](${link.href})`), ].join("\n\n"), ) diff --git a/tests/onboarding-merge.spec.ts b/tests/onboarding-merge.spec.ts index 3f612add..5491179d 100644 --- a/tests/onboarding-merge.spec.ts +++ b/tests/onboarding-merge.spec.ts @@ -47,19 +47,47 @@ for (const lang of ["en", "ru", "es"]) { await expect(page).toHaveURL(new RegExp(`/${lang}/docs/${tool}/installation$`)) await expect(page.locator("main")).toContainText(`@wirecat/${tool}-cli`) const login = page.locator("section[aria-labelledby=install-login]") - await expect(login.locator("ol")).toBeVisible() - await expect(login.locator("code")).toHaveText(`${tool} setup`) + await expect(login.locator("ol").first()).toBeVisible() + await expect(login.locator("code").first()).toHaveText(`${tool} setup`) }) test(`${lang}/${tool}: login instructions and request match the Markdown guide`, async ({ page }) => { await page.goto(`/${lang}/docs/${tool}/installation`) const login = page.locator("section[aria-labelledby=install-login]") + await login.locator("[data-installation-login-help] button").first().click() + await expect(login.locator("img")).toHaveCount(tool === "tg" ? 5 : 0) + await expect(login.locator("figure:not(:has(img))")).toHaveCount(tool === "tg" ? 1 : 2) + for (const image of await login.locator("img").all()) { + await image.scrollIntoViewIfNeeded() + await expect.poll(() => image.evaluate((node) => (node as HTMLImageElement).naturalWidth)).toBeGreaterThan(0) + } + const md = await page.request.get( `/llms.mdx/docs/${lang === "en" ? "" : `${lang}/`}${tool}/installation/content.md`, ) expect(md.status()).toBe(200) const markdown = await md.text() - for (const paragraph of await login.locator("p, li").allTextContents()) { + for (const image of await login + .locator("img") + .evaluateAll((nodes) => + nodes.map((node) => ({ src: node.getAttribute("src"), alt: node.getAttribute("alt") })), + )) { + expect(markdown).toContain(`![${image.alt}](${image.src})`) + } + for (const slot of await login.locator("figure:not(:has(img))").allTextContents()) { + expect(markdown).toContain(slot.trim()) + } + + for (const paragraph of await login.locator("p, li").evaluateAll((nodes) => + nodes + .map((node) => + [...node.childNodes] + .filter((child) => child.nodeType === Node.TEXT_NODE) + .map((child) => child.textContent) + .join(""), + ) + .filter((text) => text.trim() !== "" && text.trim() !== "→"), + )) { expect(markdown).toContain(paragraph.replace(/ →$/, "")) } expect(markdown).toContain(