feat(docs): In-app documentation browser with Jekyll site and Docusaurus sync#5445
Merged
Conversation
55776d0 to
9275da0
Compare
❌ 1 Tests Failed:
View the top 1 failed test(s) by shortest run time
To view more test analytics, go to the Test Analytics Dashboard |
70497d3 to
36cf06e
Compare
… and multiplatform-markdown-renderer
…ackHandler, placeholder screenshots
- Create DocsPreviews.kt with 8 preview composables for docs UI screens - Add screenshot test wrappers in DocsScreenshotTests.kt - Generate 16 reference images (8 light + 8 dark mode) - Replace placeholder screenshots with real Compose preview renders - Inline screenshots into all 14 user guide markdown docs - Sync updated docs to composeResources for in-app display - Fix detekt issues: MagicNumber, LongMethod, ReturnCount, LoopWithTooManyJumpStatements, PreviewPublic, lambda tense - Rename onPageSelected → onSelectPage (Compose naming convention) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Update `DefaultDocBundleLoader` to explicitly bind to the `DocBundleLoader` interface in Koin - Add `FeatureDocsModule` to `DesktopKoinModule` to enable documentation support in the desktop application
…tection - Update `MeshtasticDatabaseTest` to use Room 3 `MigrationTestHelper` with `BundledSQLiteDriver` and `runBlocking` for KMP compatibility - Update `DatabaseManagerLegacyCleanupTest` to use `DataStore` instead of `SharedPreferences`, matching the current `DatabaseManager` architecture - Modify build-logic to recognize `src/androidDeviceTest` source sets when determining if instrumented tests should be enabled - Add `compileAndroidDeviceTest` dependencies to the root convention plugin for `:core:database` and `:core:model` to catch compilation breakages early in the build process
… (FR-038) - Create ComposeResourceImageTransformer using Res.getUri() + Coil 3 - Wire transformer into DocsPageRouteScreen Markdown composable - Update syncDocsToComposeResources to include screenshots - Add docs-screenshot-aliases.properties for CST-to-semantic renaming - Refactor copyDocsScreenshots to read manifest at configuration time - Fix markdown image paths to root-relative for Jekyll resolution - Remove redirect_to from docs/index.md for local rendering - Add coil dependency and synced assets to .gitignore - Update spec artifacts and reference screenshots Tasks: T061, T062, T083, T084
These files are generated by syncDocsToComposeResources and are already listed in .gitignore.
- Add iconId field to DocPage model for per-page icons - Add DocPageIconResolver composable mapping iconId to MeshtasticIcons - Render leading icons in DocsBrowserScreen TOC list items - Add signal-meter.md and units-and-locale.md user doc pages - Update DocBundleLoader with new pages and icon mappings - Update DocsPreviews with iconId and new sample pages
- onboarding.md: add CriticalAlerts permission, expand permissions section - nodes.md: correct filters (6 toggles + search) and sorts (7 options) - messages-and-channels.md: add reactions, message actions, expand quick chat - desktop.md: add keyboard shortcuts table, structure system tray section - map-and-waypoints.md: expand waypoint expiration and locked behavior - tak.md: expand TAK/TAK_TRACKER roles, add CoT format - mqtt.md: add message formats and encryption/privacy sections
- Upgrade to just-the-docs v0.11.0 with remote_theme for GitHub Pages - Add Meshtastic M3 color scheme (Green 700 primary, Neutral palette) - Add dynamic copyright footer - Add user.md and developer.md section index pages with What's New - Update index.md with Quick Links table - Update Gemfile to Jekyll 4.3 with required gems - Restructure versions.yml for nested format
Runs weekly to detect doc pages not updated since their source code changed. Uses ubuntu-24.04-arm runner per CI conventions.
- Mark TOC icons, content validation, and Jekyll upgrade tasks complete - Add Phase 9 tasks (T200-T206) for Apple alignment - Update session context with current state
- Fix sidebar nav by overriding circular parent refs in user.md/developer.md - Strip .md extensions from 10 internal links for Jekyll compatibility - Add M3-aligned dark color scheme (meshtastic-dark.scss) from Color.kt - Refresh light scheme with explicit $color-scheme and M3 tokens - Add light/dark toggle with localStorage persistence and OS preference - Add Inter + JetBrains Mono fonts, M3-style rounded corners, transitions - Wire DocsLinkUriHandler for in-app markdown link navigation via CompositionLocalProvider + custom UriHandler
- Add Mutex for cache concurrency safety - Use atomic file writes (temp + atomicMove) to prevent partial reads - Touch files on read to maintain proper access-time eviction order - Move I/O off main thread with withContext(ioDispatcher) - Key LaunchedEffect on locale so content refreshes on locale change - Log segment translation failures instead of swallowing silently - Replace generic Exception catches with IOException for detekt Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e tests - Show 'Community translated' or 'Auto-translated' subtitle in TopAppBar when viewing non-English content - Auto-download ML Kit models on first translation attempt instead of requiring separate download UX flow - Show English content immediately while ML Kit translates in background - Move TranslationSource enum to model package for reuse - Add TranslationCascadeTest with 8 tests covering service contracts - Update spec tasks.md with Phase 14 documenting all translation work Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…rce off main thread - Remove @single annotation from DocTranslationCache to prevent ComponentScan from attempting to instantiate it without Context (it's provided explicitly via GoogleAiModule factory) - Wrap hasTranslatedResource() call in withContext(ioDispatcher) to avoid CMP resource I/O on the main thread Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- DocBundleLoader.readPageLocalized() loads Crowdin locale-qualified files directly (CMP Res.readBytes doesn't auto-resolve locale variants) - DocsNavigation cascade now correctly: Crowdin → ML Kit → English - MarkdownTranslationSegmenter translates link-only lines (TOC) - Cache touchFile uses lightweight sidecar (.access) mtime instead of rewriting full cache entry (corruption risk eliminated) - Detekt suppressions for LongMethod, TooManyFunctions, ReturnCount Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Jekyll config: locale-scoped defaults (nav_exclude, locale_page layout)
- Language switcher: globe dropdown in header, detects available pages
- locale_page layout: community translation banner, RTL support, lang attr
- DocsTasks: generateDocsBundle discovers docs/{locale}/user/ dirs,
produces locale-qualified HTML + index entries + locales.json manifest
- translations.md landing page with Crowdin CTA
- crowdin.yml already maps docs/user/*.md → docs/{locale}/user/*.md
Same markdown source now serves both:
- In-app: CMP composeResources via syncTranslatedDocs task
- Web: Jekyll GH Pages with locale routing and language switcher
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- _data/locales.yml: all 38 Android locales with native names and dir - _config.yml: scope defaults for all locale paths - DocsTasks: regex accepts region-qualified codes (pt-BR, zh-CN) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Crowdin's %two_letters_code% only produces 2-letter codes (pt, zh), losing regional distinctions. %locale% produces the full locale code for regional variants (pt-BR, zh-CN, zh-TW) while keeping simple codes for non-regional languages (fr, es, de). This matches our Android resource structure which distinguishes pt vs pt-BR and zh-CN vs zh-TW. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace brittle locale.replace("-", "-r") with proper bcp47ToCmpQualifier()
in build script and consolidate runtime locale resolution:
- Add currentLocaleQualifier() expect/actual that returns CMP-format
qualifier (e.g. "pt-rBR", "fr") directly from system Locale
- DocBundleLoader tries qualifiers in specificity order: region-qualified
first (files-pt-rBR/), then language-only (files-pt/), then English
- Build-side bcp47ToCmpQualifier() properly handles 2-letter regions,
and falls back to BCP-47 b+ format for script tags (sr-Latn)
- CMP files/ resources don't support auto locale resolution (confirmed
in official docs) so manual path construction is required
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
%android_code% outputs Android/CMP qualifier format directly (pt-rBR, zh-rCN, fr), removing the need for bcp47ToCmpQualifier() conversion. Pipeline is now zero-conversion: Crowdin → docs/pt-rBR/user/foo.md (already CMP format) Sync → files-pt-rBR/docs/user/foo.md (just prepend files-) Runtime→ files-pt-rBR/docs/user/foo.md (direct match) Updated Jekyll config and locales.yml to use Android qualifier format for consistency across the entire docs pipeline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Locale-qualified HTML pages (docs/pt-rBR/user/foo.html) need ../../styles/docs.css, not ../styles/docs.css (one extra level deep) - Heading regex now requires space after # per CommonMark spec, preventing corruption of lines like ##hashtag or #noSpace Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
55acac8 to
6ce21af
Compare
DocTranslationCache is constructed via a factory function that provides the Path from Context.cacheDir, but Koin verify still introspects the class constructor params. Adding these types to extraTypes suppresses the false MissingKoinDefinitionException. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Updates spec to reflect the implemented translation system: - FR-048: Three-tier translation cascade (Crowdin → ML Kit → English) - FR-049: Zero-conversion locale pipeline via %android_code% - FR-050: Jekyll i18n with Android qualifier paths - FR-051: currentLocaleQualifier() expect/actual - SC-022–025: Corresponding success criteria - Updated Assumptions: translation now in scope for User Guide - Added Session 2026-05-18 clarification notes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Addresses quality gaps identified in cross-platform audit vs meshtastic-apple: nodes.md: - Added 'Choosing a Role' guidance with practical use cases - Added Client Hidden role (was missing) - Added encryption indicator icons section with PKI explanation - Added mesh topology tip (Router:Client ratio guidance) settings-radio-user.md: - Expanded modem preset table with SNR limits and km range estimates - Added 'Choosing a Modem Preset' section with scenario-based guidance - Clarified TX Power 0 = region max (not 0 dBm) - Added warning about preset mismatch between nodes messages-and-channels.md: - Added delivery error codes table (10 errors with cause and fix) - Expanded channel security to 4-level icon table with AES bit info - Added tip about error self-resolution tak.md: - Added TAK Identity section (team/role/callsign) - Added wire format V1/V2 comparison table - Added troubleshooting table (5 common issues with solutions) map-and-waypoints.md: - Simplified confusing 'Boundary' expiration language - Clarified expiration countdown starts at creation time Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Upgrades the Chirpy AI assistant for significantly better helpfulness: - Add systemInstruction with rich Meshtastic-knowledgeable persona - Add cloud model with Tool.googleSearch() for web-grounded answers (accesses meshtastic.org and community content when online) - Implement on-device → cloud fallback cascade: 1. Try on-device first (fast, private, offline) 2. If answer seems insufficient, fall back to cloud with grounding - Update isSupported() to always return true on Google flavor (cloud model is always available even without AICore) - Remove overly restrictive 'if not in docs, refuse' behavior - System prompt now encourages using training knowledge about meshtastic.org when bundled docs don't cover the topic Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Upgrade model from gemini-2.5-flash-lite to gemini-3.1-flash-lite (latest stable, released 2026-05-07, free tier, improved quality) - Add Tool.urlContext() alongside Google Search grounding so Chirpy can directly access meshtastic.org/docs when cloud inference is used - Append meshtastic.org URL hint to cloud-grounded prompts for better URL context tool activation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace Tool.googleSearch() with Tool.urlContext() so Chirpy only fetches content from explicitly-provided official URLs: - meshtastic.org/docs - github.com/meshtastic/Meshtastic-Android - github.com/meshtastic/firmware This prevents the model from pulling context from random forums, blogs, or third-party sites that may contain outdated or incorrect information. The system instruction also explicitly forbids citing non-official sources. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use model.startChat() + chat.sendMessage() so Chirpy maintains full conversation history across messages. This enables natural follow-up questions like 'can you explain that more?' or 'what about X?' Architecture: - First message: try on-device for speed, seed cloud chat session - Subsequent messages: use cloud chat (has full conversation context) - resetSession() clears the chat when opening a fresh conversation Also adds resetSession() to AIDocAssistant interface (no-op on keyword fallback platforms). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The usedOnDeviceModel field was hardcoded to false even when the on-device model successfully generated the answer. Refactored generateWithChat() to return a ChatResult data class that tracks which model produced the answer. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
InferenceMode.PREFER_ON_DEVICE silently falls back to cloud when on-device isn't available, causing: 1. usedOnDeviceModel incorrectly reporting true (it was cloud) 2. Redundant cloud chat seeding call (double API usage) Switch to ONLY_ON_DEVICE so failures are explicit — the caught exception routes cleanly to the cloud chat path instead. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The docs screenshots use a markdown renderer that produces slight pixel differences between macOS (local) and Linux (CI). Increase tolerance from 0.05% to 0.5% to accommodate platform font rendering differences while still catching meaningful visual regressions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
172fdc7 to
2897b8b
Compare
Reference images for Chirpy and DocsPageContent screenshots were generated on macOS, which uses different font metrics than Linux CI. This caused 62% pixel differences due to text wrapping at different character positions despite identical layout constraints. Replace references with the CI-rendered actual images (verified visually correct) so that validation matches the Linux rendering environment. Revert threshold from 0.02f back to 0.0005f since references now match the CI platform. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
90d2366 to
a460211
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a full in-app documentation browser to the Meshtastic Android & Desktop app, backed by a Jekyll site for standalone browsing and a Docusaurus sync pipeline for meshtastic.org.
What's included
In-app docs browser (
feature/docs)MeshtasticIconsComposeResourceImageTransformermeshtastic://docs/{pageId})Jekyll site (
docs/)Docusaurus sync (Phase 10)
scripts/sync-android-docs.js— transforms Jekyll → Docusaurus formatcwebpNew content pages (Phase 10)
docs/user/translate.md— Crowdin contribution guidedocs/developer/measurement.md— MetricFormatter API guideScreenshot testing
@PreviewLightDarkpreviews inDocsPreviews.ktDocsScreenshotTests.ktVerification
./gradlew spotlessApply detekt assembleDebug test allTestspassesRelated
specs/20260507-161858-app-docs-markdown/