2026-06-14 22:06:34 +00:00
<!doctype html>
< html lang = "en" class = "no-js" >
< head >
< meta charset = "utf-8" >
< meta name = "viewport" content = "width=device-width,initial-scale=1" >
< meta name = "description" content = "Documentation for the open source MeshCore firmware" >
< link rel = "canonical" href = "https://meshcore-dev.github.io/meshcore/design/trail_redesign/" >
2026-06-29 16:02:00 +00:00
< link rel = "prev" href = "../solo_ui_framework/" >
2026-06-14 22:06:34 +00:00
< link rel = "next" href = "../../solo_features/clock_screen/clock_screen/" >
< link rel = "icon" href = "../../assets/images/favicon.png" >
2026-07-18 08:11:35 +00:00
< meta name = "generator" content = "mkdocs-1.6.1, mkdocs-material-9.7.7" >
2026-06-14 22:06:34 +00:00
< title > Trail (Tools › Trail) — analiza i propozycja uporządkowania - MeshCore Docs</ title >
2026-07-18 08:11:35 +00:00
< link rel = "stylesheet" href = "../../assets/stylesheets/main.ec1eaa64.min.css" >
2026-06-14 22:06:34 +00:00
< link rel = "preconnect" href = "https://fonts.gstatic.com" crossorigin >
< link rel = "stylesheet" href = "https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback" >
< style >: root { --md-text-font : "Roboto" ; --md-code-font : "Roboto Mono" }</ style >
< link rel = "stylesheet" href = "../../_stylesheets/extra.css" >
< script > __md_scope = new URL ( "../.." , location ), __md_hash = e =>[... e ]. reduce ((( e , _ )=>( e << 5 ) - e + _ . charCodeAt ( 0 )), 0 ), __md_get = ( e , _ = localStorage , t = __md_scope )=> JSON . parse ( _ . getItem ( t . pathname + "." + e )), __md_set = ( e , _ , t = localStorage , a = __md_scope )=>{ try { t . setItem ( a . pathname + "." + e , JSON . stringify ( _ ))} catch ( e ){}}</ script >
</ head >
< body dir = "ltr" >
< input class = "md-toggle" data-md-toggle = "drawer" type = "checkbox" id = "__drawer" autocomplete = "off" >
< input class = "md-toggle" data-md-toggle = "search" type = "checkbox" id = "__search" autocomplete = "off" >
< label class = "md-overlay" for = "__drawer" ></ label >
< div data-md-component = "skip" >
< a href = "#trail-tools-trail-analiza-i-propozycja-uporzadkowania" class = "md-skip" >
Skip to content
</ a >
</ div >
< div data-md-component = "announce" >
</ div >
< header class = "md-header md-header--shadow" data-md-component = "header" >
< nav class = "md-header__inner md-grid" aria-label = "Header" >
< a href = "../.." title = "MeshCore Docs" class = "md-header__button md-logo" aria-label = "MeshCore Docs" data-md-component = "logo" >
< img src = "../../_assets/meshcore.svg" alt = "logo" >
</ a >
< label class = "md-header__button md-icon" for = "__drawer" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" >< path d = "M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z" /></ svg >
</ label >
< div class = "md-header__title" data-md-component = "header-title" >
< div class = "md-header__ellipsis" >
< div class = "md-header__topic" >
< span class = "md-ellipsis" >
MeshCore Docs
</ span >
</ div >
< div class = "md-header__topic" data-md-component = "header-topic" >
< span class = "md-ellipsis" >
Trail (Tools › Trail) — analiza i propozycja uporządkowania
</ span >
</ div >
</ div >
</ div >
< script > var palette = __md_get ( "__palette" ); if ( palette && palette . color ){ if ( "(prefers-color-scheme)" === palette . color . media ){ var media = matchMedia ( "(prefers-color-scheme: light)" ), input = document . querySelector ( media . matches ? "[data-md-color-media='(prefers-color-scheme: light)']" : "[data-md-color-media='(prefers-color-scheme: dark)']" ); palette . color . media = input . getAttribute ( "data-md-color-media" ), palette . color . scheme = input . getAttribute ( "data-md-color-scheme" ), palette . color . primary = input . getAttribute ( "data-md-color-primary" ), palette . color . accent = input . getAttribute ( "data-md-color-accent" )} for ( var [ key , value ] of Object . entries ( palette . color )) document . body . setAttribute ( "data-md-color-" + key , value )}</ script >
< label class = "md-header__button md-icon" for = "__search" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" >< path d = "M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5" /></ svg >
</ label >
< div class = "md-search" data-md-component = "search" role = "dialog" >
< label class = "md-search__overlay" for = "__search" ></ label >
< div class = "md-search__inner" role = "search" >
< form class = "md-search__form" name = "search" >
< input type = "text" class = "md-search__input" name = "query" aria-label = "Search" placeholder = "Search" autocapitalize = "off" autocorrect = "off" autocomplete = "off" spellcheck = "false" data-md-component = "search-query" required >
< label class = "md-search__icon md-icon" for = "__search" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" >< path d = "M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5" /></ svg >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" >< path d = "M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z" /></ svg >
</ label >
< nav class = "md-search__options" aria-label = "Search" >
< button type = "reset" class = "md-search__icon md-icon" title = "Clear" aria-label = "Clear" tabindex = "-1" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" >< path d = "M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" /></ svg >
</ button >
</ nav >
< div class = "md-search__suggest" data-md-component = "search-suggest" ></ div >
</ form >
< div class = "md-search__output" >
< div class = "md-search__scrollwrap" tabindex = "0" data-md-scrollfix >
< div class = "md-search-result" data-md-component = "search-result" >
< div class = "md-search-result__meta" >
Initializing search
</ div >
< ol class = "md-search-result__list" role = "presentation" ></ ol >
</ div >
</ div >
</ div >
</ div >
</ div >
< div class = "md-header__source" >
< a href = "https://github.com/meshcore-dev/meshcore/" title = "Go to repository" class = "md-source" data-md-component = "source" >
< div class = "md-source__icon md-icon" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 448 512" > <!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--> < path d = "M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4" /></ svg >
</ div >
< div class = "md-source__repository" >
meshcore-dev/meshcore
</ div >
</ a >
</ div >
</ nav >
</ header >
< div class = "md-container" data-md-component = "container" >
< main class = "md-main" data-md-component = "main" >
< div class = "md-main__inner md-grid" >
< div class = "md-sidebar md-sidebar--primary" data-md-component = "sidebar" data-md-type = "navigation" >
< div class = "md-sidebar__scrollwrap" >
< div class = "md-sidebar__inner" >
< nav class = "md-nav md-nav--primary" aria-label = "Navigation" data-md-level = "0" >
< label class = "md-nav__title" for = "__drawer" >
< a href = "../.." title = "MeshCore Docs" class = "md-nav__button md-logo" aria-label = "MeshCore Docs" data-md-component = "logo" >
< img src = "../../_assets/meshcore.svg" alt = "logo" >
</ a >
MeshCore Docs
</ label >
< div class = "md-nav__source" >
< a href = "https://github.com/meshcore-dev/meshcore/" title = "Go to repository" class = "md-source" data-md-component = "source" >
< div class = "md-source__icon md-icon" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 448 512" > <!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--> < path d = "M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4" /></ svg >
</ div >
< div class = "md-source__repository" >
meshcore-dev/meshcore
</ div >
</ a >
</ div >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "../.." class = "md-nav__link" >
< span class = "md-ellipsis" >
Introduction
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../cli_commands/" class = "md-nav__link" >
< span class = "md-ellipsis" >
CLI Commands
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../companion_protocol/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Companion Protocol
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../docs/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Local Documentation
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../faq/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Frequently Asked Questions
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../kiss_modem_protocol/" class = "md-nav__link" >
< span class = "md-ellipsis" >
MeshCore KISS Modem Protocol
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../nrf52_power_management/" class = "md-nav__link" >
< span class = "md-ellipsis" >
nRF52 Power Management
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../number_allocations/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Number Allocations
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../packet_format/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Packet Format
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../payloads/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Payload Format
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../qr_codes/" class = "md-nav__link" >
< span class = "md-ellipsis" >
QR Codes
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../stats_binary_frames/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Stats Binary Frame Structures
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "../../terminal_chat_cli/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Terminal Chat CLI
</ span >
</ a >
</ li >
< li class = "md-nav__item md-nav__item--active md-nav__item--nested" >
< input class = "md-nav__toggle md-toggle " type = "checkbox" id = "__nav_14" checked >
< label class = "md-nav__link" for = "__nav_14" id = "__nav_14_label" tabindex = "0" >
< span class = "md-ellipsis" >
Design
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< nav class = "md-nav" data-md-level = "1" aria-labelledby = "__nav_14_label" aria-expanded = "true" >
< label class = "md-nav__title" for = "__nav_14" >
< span class = "md-nav__icon md-icon" ></ span >
Design
</ label >
< ul class = "md-nav__list" data-md-scrollfix >
2026-06-15 07:23:54 +00:00
< li class = "md-nav__item" >
< a href = "../nearby_redesign/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Nearby Nodes — analiza i propozycja uporządkowania
</ span >
</ a >
</ li >
2026-06-29 16:02:00 +00:00
< li class = "md-nav__item" >
< a href = "../solo_ui_framework/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Solo UI framework — a guide for adding features
</ span >
</ a >
</ li >
2026-06-14 22:06:34 +00:00
< li class = "md-nav__item md-nav__item--active" >
< input class = "md-nav__toggle md-toggle" type = "checkbox" id = "__toc" >
< label class = "md-nav__link md-nav__link--active" for = "__toc" >
< span class = "md-ellipsis" >
Trail (Tools › Trail) — analiza i propozycja uporządkowania
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< a href = "./" class = "md-nav__link md-nav__link--active" >
< span class = "md-ellipsis" >
Trail (Tools › Trail) — analiza i propozycja uporządkowania
</ span >
</ a >
< nav class = "md-nav md-nav--secondary" aria-label = "Table of contents" >
< label class = "md-nav__title" for = "__toc" >
< span class = "md-nav__icon md-icon" ></ span >
Table of contents
</ label >
< ul class = "md-nav__list" data-md-component = "toc" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "#1-jak-ekran-jest-zbudowany-dzisiaj" class = "md-nav__link" >
< span class = "md-ellipsis" >
1. Jak ekran jest zbudowany dzisiaj
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#2-co-jest-nieuporzadkowane" class = "md-nav__link" >
< span class = "md-ellipsis" >
2. Co jest nieuporządkowane
</ span >
</ a >
< nav class = "md-nav" aria-label = "2. Co jest nieuporządkowane" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#21-popup-akcji-to-jedna-paska-lista-12-pozycji-z-mieszanymi-rolami" class = "md-nav__link" >
< span class = "md-ellipsis" >
2.1 Popup akcji to jedna płaska lista 12 pozycji z mieszanymi rolami
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#22-rendergrid-dostaje-11-skalarnych-parametrow-brak-wspolnej-projekcji" class = "md-nav__link" >
< span class = "md-ellipsis" >
2.2 renderGrid dostaje 11 skalarnych parametrów — brak wspólnej projekcji
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#23-wybor-kroku-siatki-wielostopniowa-heurystyka-z-nieaktualnym-komentarzem" class = "md-nav__link" >
< span class = "md-ellipsis" >
2.3 Wybór kroku siatki — wielostopniowa heurystyka z nieaktualnym komentarzem
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#24-drobne" class = "md-nav__link" >
< span class = "md-ellipsis" >
2.4 Drobne
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item" >
< a href = "#3-propozycja-uporzadkowania" class = "md-nav__link" >
< span class = "md-ellipsis" >
3. Propozycja uporządkowania
</ span >
</ a >
< nav class = "md-nav" aria-label = "3. Propozycja uporządkowania" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#31-popup-dwa-poziomy-zamiast-jednej-paskiej-listy" class = "md-nav__link" >
< span class = "md-ellipsis" >
3.1 Popup: dwa poziomy zamiast jednej płaskiej listy
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#32-mapa-wspolny-obiekt-projekcji" class = "md-nav__link" >
< span class = "md-ellipsis" >
3.2 Mapa: wspólny obiekt projekcji
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#33-siatka-uproszczenie-i-naprawa-komentarza" class = "md-nav__link" >
< span class = "md-ellipsis" >
3.3 Siatka: uproszczenie i naprawa komentarza
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item" >
< a href = "#4-proponowany-zakres-etapami" class = "md-nav__link" >
< span class = "md-ellipsis" >
4. Proponowany zakres (etapami)
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#5-decyzje-zatwierdzone-2026-06-14" class = "md-nav__link" >
< span class = "md-ellipsis" >
5. Decyzje (zatwierdzone 2026-06-14)
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item md-nav__item--nested" >
< input class = "md-nav__toggle md-toggle " type = "checkbox" id = "__nav_15" >
< label class = "md-nav__link" for = "__nav_15" id = "__nav_15_label" tabindex = "0" >
< span class = "md-ellipsis" >
Solo features
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< nav class = "md-nav" data-md-level = "1" aria-labelledby = "__nav_15_label" aria-expanded = "false" >
< label class = "md-nav__title" for = "__nav_15" >
< span class = "md-nav__icon md-icon" ></ span >
Solo features
</ label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item md-nav__item--nested" >
< input class = "md-nav__toggle md-toggle " type = "checkbox" id = "__nav_15_1" >
< label class = "md-nav__link" for = "__nav_15_1" id = "__nav_15_1_label" tabindex = "0" >
< span class = "md-ellipsis" >
Clock screen
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< nav class = "md-nav" data-md-level = "2" aria-labelledby = "__nav_15_1_label" aria-expanded = "false" >
< label class = "md-nav__title" for = "__nav_15_1" >
< span class = "md-nav__icon md-icon" ></ span >
Clock screen
</ label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "../../solo_features/clock_screen/clock_screen/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Clock screen
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item md-nav__item--nested" >
< input class = "md-nav__toggle md-toggle " type = "checkbox" id = "__nav_15_2" >
< label class = "md-nav__link" for = "__nav_15_2" id = "__nav_15_2_label" tabindex = "0" >
< span class = "md-ellipsis" >
Favourites dial
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< nav class = "md-nav" data-md-level = "2" aria-labelledby = "__nav_15_2_label" aria-expanded = "false" >
< label class = "md-nav__title" for = "__nav_15_2" >
< span class = "md-nav__icon md-icon" ></ span >
Favourites dial
</ label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "../../solo_features/favourites_dial/favourites_dial/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Favourites dial
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item md-nav__item--nested" >
< input class = "md-nav__toggle md-toggle " type = "checkbox" id = "__nav_15_3" >
< label class = "md-nav__link" for = "__nav_15_3" id = "__nav_15_3_label" tabindex = "0" >
< span class = "md-ellipsis" >
Message screen
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< nav class = "md-nav" data-md-level = "2" aria-labelledby = "__nav_15_3_label" aria-expanded = "false" >
< label class = "md-nav__title" for = "__nav_15_3" >
< span class = "md-nav__icon md-icon" ></ span >
Message screen
</ label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "../../solo_features/message_screen/message_screen/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Message screen
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item md-nav__item--nested" >
< input class = "md-nav__toggle md-toggle " type = "checkbox" id = "__nav_15_4" >
< label class = "md-nav__link" for = "__nav_15_4" id = "__nav_15_4_label" tabindex = "0" >
< span class = "md-ellipsis" >
Screen lock
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< nav class = "md-nav" data-md-level = "2" aria-labelledby = "__nav_15_4_label" aria-expanded = "false" >
< label class = "md-nav__title" for = "__nav_15_4" >
< span class = "md-nav__icon md-icon" ></ span >
Screen lock
</ label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "../../solo_features/screen_lock/screen_lock/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Screen lock
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item md-nav__item--nested" >
< input class = "md-nav__toggle md-toggle " type = "checkbox" id = "__nav_15_5" >
< label class = "md-nav__link" for = "__nav_15_5" id = "__nav_15_5_label" tabindex = "0" >
< span class = "md-ellipsis" >
Settings screen
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< nav class = "md-nav" data-md-level = "2" aria-labelledby = "__nav_15_5_label" aria-expanded = "false" >
< label class = "md-nav__title" for = "__nav_15_5" >
< span class = "md-nav__icon md-icon" ></ span >
Settings screen
</ label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "../../solo_features/settings_screen/settings_screen/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Settings screen
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item md-nav__item--nested" >
< input class = "md-nav__toggle md-toggle " type = "checkbox" id = "__nav_15_6" >
< label class = "md-nav__link" for = "__nav_15_6" id = "__nav_15_6_label" tabindex = "0" >
< span class = "md-ellipsis" >
Tools screen
</ span >
< span class = "md-nav__icon md-icon" ></ span >
</ label >
< nav class = "md-nav" data-md-level = "2" aria-labelledby = "__nav_15_6_label" aria-expanded = "false" >
< label class = "md-nav__title" for = "__nav_15_6" >
< span class = "md-nav__icon md-icon" ></ span >
Tools screen
</ label >
< ul class = "md-nav__list" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "../../solo_features/tools_screen/tools_screen/" class = "md-nav__link" >
< span class = "md-ellipsis" >
Tools screen
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
</ ul >
</ nav >
</ li >
</ ul >
</ nav >
</ div >
</ div >
</ div >
< div class = "md-sidebar md-sidebar--secondary" data-md-component = "sidebar" data-md-type = "toc" >
< div class = "md-sidebar__scrollwrap" >
< div class = "md-sidebar__inner" >
< nav class = "md-nav md-nav--secondary" aria-label = "Table of contents" >
< label class = "md-nav__title" for = "__toc" >
< span class = "md-nav__icon md-icon" ></ span >
Table of contents
</ label >
< ul class = "md-nav__list" data-md-component = "toc" data-md-scrollfix >
< li class = "md-nav__item" >
< a href = "#1-jak-ekran-jest-zbudowany-dzisiaj" class = "md-nav__link" >
< span class = "md-ellipsis" >
1. Jak ekran jest zbudowany dzisiaj
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#2-co-jest-nieuporzadkowane" class = "md-nav__link" >
< span class = "md-ellipsis" >
2. Co jest nieuporządkowane
</ span >
</ a >
< nav class = "md-nav" aria-label = "2. Co jest nieuporządkowane" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#21-popup-akcji-to-jedna-paska-lista-12-pozycji-z-mieszanymi-rolami" class = "md-nav__link" >
< span class = "md-ellipsis" >
2.1 Popup akcji to jedna płaska lista 12 pozycji z mieszanymi rolami
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#22-rendergrid-dostaje-11-skalarnych-parametrow-brak-wspolnej-projekcji" class = "md-nav__link" >
< span class = "md-ellipsis" >
2.2 renderGrid dostaje 11 skalarnych parametrów — brak wspólnej projekcji
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#23-wybor-kroku-siatki-wielostopniowa-heurystyka-z-nieaktualnym-komentarzem" class = "md-nav__link" >
< span class = "md-ellipsis" >
2.3 Wybór kroku siatki — wielostopniowa heurystyka z nieaktualnym komentarzem
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#24-drobne" class = "md-nav__link" >
< span class = "md-ellipsis" >
2.4 Drobne
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item" >
< a href = "#3-propozycja-uporzadkowania" class = "md-nav__link" >
< span class = "md-ellipsis" >
3. Propozycja uporządkowania
</ span >
</ a >
< nav class = "md-nav" aria-label = "3. Propozycja uporządkowania" >
< ul class = "md-nav__list" >
< li class = "md-nav__item" >
< a href = "#31-popup-dwa-poziomy-zamiast-jednej-paskiej-listy" class = "md-nav__link" >
< span class = "md-ellipsis" >
3.1 Popup: dwa poziomy zamiast jednej płaskiej listy
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#32-mapa-wspolny-obiekt-projekcji" class = "md-nav__link" >
< span class = "md-ellipsis" >
3.2 Mapa: wspólny obiekt projekcji
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#33-siatka-uproszczenie-i-naprawa-komentarza" class = "md-nav__link" >
< span class = "md-ellipsis" >
3.3 Siatka: uproszczenie i naprawa komentarza
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ li >
< li class = "md-nav__item" >
< a href = "#4-proponowany-zakres-etapami" class = "md-nav__link" >
< span class = "md-ellipsis" >
4. Proponowany zakres (etapami)
</ span >
</ a >
</ li >
< li class = "md-nav__item" >
< a href = "#5-decyzje-zatwierdzone-2026-06-14" class = "md-nav__link" >
< span class = "md-ellipsis" >
5. Decyzje (zatwierdzone 2026-06-14)
</ span >
</ a >
</ li >
</ ul >
</ nav >
</ div >
</ div >
</ div >
< div class = "md-content" data-md-component = "content" >
< article class = "md-content__inner md-typeset" >
< a href = "https://github.com/meshcore-dev/meshcore/edit/main/docs/design/trail_redesign.md" title = "Edit this page" class = "md-content__button md-icon" rel = "edit" >
< svg xmlns = "http://www.w3.org/2000/svg" viewBox = "0 0 24 24" >< path d = "M10 20H6V4h7v5h5v3.1l2-2V8l-6-6H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h4zm10.2-7c.1 0 .3.1.4.2l1.3 1.3c.2.2.2.6 0 .8l-1 1-2.1-2.1 1-1c.1-.1.2-.2.4-.2m0 3.9L14.1 23H12v-2.1l6.1-6.1z" /></ svg >
</ a >
< h1 id = "trail-tools-trail-analiza-i-propozycja-uporzadkowania" > Trail (Tools › Trail) — analiza i propozycja uporządkowania</ h1 >
< blockquote >
2026-06-15 07:51:36 +00:00
< p > Branch: < code > refactor/trail-screen</ code > (zmergowany do < code > main</ code > )
Plik źródłowy: < a href = "../../examples/companion_radio/ui-new/TrailScreen.h" > TrailScreen.h</ a >
Status: < strong > zaimplementowane</ strong > — dokument zachowany jako zapis analizy/decyzji.
Aktualny opis funkcji od strony użytkownika: < a href = "../../solo_features/tools_screen/tools_screen/" > tools_screen.md › GPS Trail</ a > .</ p >
2026-06-14 22:06:34 +00:00
</ blockquote >
< hr />
< h2 id = "1-jak-ekran-jest-zbudowany-dzisiaj" > 1. Jak ekran jest zbudowany dzisiaj</ h2 >
< pre >< code > TrailScreen
├── 3 widoki (LEFT/RIGHT): Summary · Map · List
├── popup akcji (Hold Enter) — JEDNA płaska lista, do 12 pozycji
│ ├── ustawienia (LEFT/RIGHT cykluje w miejscu): Min dist · Readout · Grid
│ ├── toggle: Start/Stop tracking
│ ├── waypointy: Mark here · Waypoints · Clear waypoints
│ └── trail: Save · Load · Export(live) · Export(saved) · Reset
├── pod-ekrany waypointów (nakładane na widoki):
│ ├── WP_LIST (lista + dystanse; Trail-start + „+ Add by coords" )
│ ├── WP_NAV (navview)
│ ├── WP_ADD (formularz lat/lon/label)
│ └── _wp_ctx popup: Rename · Delete · Send
└── KeyboardWidget (label / lat / lon) — nakładka pełnoekranowa
</ code ></ pre >
< p > Renderowanie mapy: < code > renderMap()</ code > (≈140 linii) + < code > renderGrid()</ code > (≈130 linii)
+ 7 funkcji rysujących markery.</ p >
< hr />
< h2 id = "2-co-jest-nieuporzadkowane" > 2. Co jest nieuporządkowane</ h2 >
< h3 id = "21-popup-akcji-to-jedna-paska-lista-12-pozycji-z-mieszanymi-rolami" > 2.1 Popup akcji to jedna płaska lista 12 pozycji z mieszanymi rolami</ h3 >
< p >< code > openActionMenu()</ code > (< code > TrailScreen.h:363</ code > ) buduje jedno menu, które miesza
< strong > cztery różne klasy</ strong > pozycji:</ p >
< table >
< thead >
< tr >
< th > Klasa</ th >
< th > Pozycje</ th >
< th > Interakcja</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td > Ustawienia</ td >
< td > Min dist, Readout, Grid</ td >
< td > LEFT/RIGHT (w miejscu)</ td >
</ tr >
< tr >
< td > Stan nagrywania</ td >
< td > Start/Stop tracking</ td >
< td > Enter</ td >
</ tr >
< tr >
< td > Waypointy</ td >
< td > Mark here, Waypoints, Clear waypoints</ td >
< td > Enter</ td >
</ tr >
< tr >
< td > Plik trasy</ td >
< td > Save, Load, Export(live), Export(saved), Reset</ td >
< td > Enter</ td >
</ tr >
</ tbody >
</ table >
< p > Problemy:
- < strong > Długi scroll</ strong > — na OLED widać ~4 wiersze naraz, więc do „Reset trail"
trzeba przewinąć przez całą listę;
- < strong > Dwa wzorce interakcji w jednym menu</ strong > — część pozycji reaguje na
LEFT/RIGHT (ustawienia), część na Enter (akcje). Enter na wierszu
ustawień nic sensownego nie robi — tylko zamyka i otwiera menu od nowa
(< code > reopenAt</ code > , < code > TrailScreen.h:581</ code > );
- < strong > Brak kontekstu widoku</ strong > — < code > Grid</ code > (dotyczy tylko mapy) i < code > Readout</ code >
(dotyczy tylko Summary) są widoczne zawsze, też tam, gdzie nie mają
efektu;
- < strong >< code > Grid</ code > ma dwie ścieżki</ strong > — i LEFT/RIGHT (< code > :221</ code > ) i Enter (< code > :234</ code > )
robią to samo; lekko myli.</ p >
< h3 id = "22-rendergrid-dostaje-11-skalarnych-parametrow-brak-wspolnej-projekcji" > 2.2 < code > renderGrid</ code > dostaje 11 skalarnych parametrów — brak wspólnej projekcji</ h3 >
< p >< code > renderMap</ code > liczy projekcję (lokalne lambdy < code > projectLL</ code > /< code > project</ code > ,
< code > :816</ code > ), a < code > renderGrid</ code > (< code > :876</ code > ) dostaje < strong > 11 osobnych liczb</ strong >
(< code > area_*</ code > , < code > min/max_lat</ code > , < code > min_lon</ code > , < code > lon_scale_geo</ code > , < code > scale</ code > , < code > off_*</ code > ) i
< strong > powtarza tę samą matematykę projekcji</ strong > ręcznie w pętli (< code > :988</ code > ,
< code > :992</ code > ). To samo równanie żyje w trzech miejscach. Każda zmiana modelu
mapy wymaga edycji w kilku miejscach naraz.</ p >
< h3 id = "23-wybor-kroku-siatki-wielostopniowa-heurystyka-z-nieaktualnym-komentarzem" > 2.3 Wybór kroku siatki — wielostopniowa heurystyka z nieaktualnym komentarzem</ h3 >
< p >< code > renderGrid</ code > wybiera krok siatki w < strong > czterech</ strong > następujących po sobie
korektach (< code > :912</ code > – < code > :952</ code > ):
1. największy krok ≤ < code > target_m</ code > ,
2. zwiększaj aż odstęp pikseli ≥ < code > MIN_GRID_PX</ code > (22 px),
3. zmniejszaj aż zmieszczą się ≥2 interwały,
4. zwiększaj aż liczba linii ≤ < code > MAX_GRID_LINES</ code > (40).</ p >
< p > Uwagi:
- Komentarz przy kroku 4 (< code > :937</ code > ) mówi o „static buffers (40× 40 = ~1600
intersections)" — < strong > takich buforów już nie ma</ strong > ; pętla rysuje na bieżąco
z < code > continue</ code > -guardami (< code > :986</ code > – < code > 1002</ code > ). Cap 40 ogranicza dziś tylko
liczbę iteracji pętli (wydajność), nie chroni żadnego bufora. Komentarz
wprowadza w błąd.
- Kroki 2 i 3 mogą sobie przeczyć na bardzo małych ekranach
(< code > MIN_GRID_PX = 22</ code > vs < code > shorter_px/2</ code > , gdy < code > shorter_px < 44</ code > ).
Nie powoduje błędu, ale „ostateczny" krok bywa wtedy przypadkowy.</ p >
< h3 id = "24-drobne" > 2.4 Drobne</ h3 >
< ul >
< li >< code > _act_map[16]</ code > z komentarzem „12 used today; pad" — ręczne pilnowanie
rozmiaru; < code > pushAction</ code > już to zabezpiecza, więc magiczna 16 jest zbędna.</ li >
< li > Bounding-box mapy i markery mają sporo powtarzalnego clamp-to-edge
(< code > :852</ code > , < code > :1011</ code > ).</ li >
</ ul >
< hr />
< h2 id = "3-propozycja-uporzadkowania" > 3. Propozycja uporządkowania</ h2 >
< h3 id = "31-popup-dwa-poziomy-zamiast-jednej-paskiej-listy" > 3.1 Popup: dwa poziomy zamiast jednej płaskiej listy</ h3 >
< p > Górne menu krótkie (akcje), ustawienia i operacje na pliku w podmenu:</ p >
< pre >< code > Hold Enter → Trail
• Start / Stop tracking
• Mark here
• Waypoints… → istniejący WP_LIST
• Trail file… → Save / Load / Export (live) / Export (saved) / Reset
• Settings… → Min dist · Readout · Grid (LEFT/RIGHT w miejscu)
</ code ></ pre >
< p > Korzyści:
- górne menu to < strong > ~5 pozycji, bez scrolla</ strong > na OLED;
- < strong > jeden wzorzec na poziom</ strong > : górny i „Trail file" = Enter-akcje;
„Settings" = wartości cyklowane LEFT/RIGHT — bez mieszania w jednym
widoku;
- destrukcyjny < code > Reset</ code > przeniesiony do „Trail file…", dalej od przypadkowego
Entera;
- (opcjonalnie) < code > Grid</ code > pokazywać tylko gdy aktywny jest widok Map, a
< code > Readout</ code > tylko przy Summary — menu zależne od kontekstu widoku.</ p >
< blockquote >
< p > Wariant minimalny (mniej kodu): zostać przy jednej liście, ale
< strong > pogrupować</ strong > (ustawienia → akcje → plik), < code > Reset</ code > na sam dół, usunąć
podwójną ścieżkę < code > Grid</ code > . Mniej porządku niż podmenu, ale tańsze.</ p >
</ blockquote >
< h3 id = "32-mapa-wspolny-obiekt-projekcji" > 3.2 Mapa: wspólny obiekt projekcji</ h3 >
< p > Wydzielić mały < code > MapProjection</ code > liczony raz w < code > renderMap</ code > i przekazywany
do < code > renderGrid</ code > oraz markerów:</ p >
< pre >< code class = "language-cpp" > struct MapProjection {
int32_t min_lat, max_lat, min_lon;
float lon_scale_geo, scale;
int off_x, off_y, area_x, area_y, area_w, area_h;
void project(int32_t lat, int32_t lon, int& px, int& py) const;
};
</ code ></ pre >
< ul >
< li >< code > renderGrid(display, proj)</ code > zamiast 11 parametrów;</ li >
< li > jedno równanie projekcji (dziś powielone 3× );</ li >
< li > markery/waypointy też przez < code > proj.project(...)</ code > .</ li >
</ ul >
< p > Czysto refaktoryzacyjne — bez zmiany wyglądu mapy.</ p >
< h3 id = "33-siatka-uproszczenie-i-naprawa-komentarza" > 3.3 Siatka: uproszczenie i naprawa komentarza</ h3 >
< ul >
< li > poprawić/skasować komentarz o „static buffers" (już nieaktualny);</ li >
< li > scalić wybór kroku w jedną pętlę „znajdź najmniejszy krok, który daje
odstęp ≥ MIN_GRID_PX i ≤ MAX_GRID_LINES linii" zamiast czterech
następujących korekt;</ li >
< li > bbox etykiety/strzałki północy liczyć z jednej funkcji pomocniczej.</ li >
</ ul >
< p > Wynik wizualnie identyczny, logika krótsza i łatwiejsza do utrzymania.</ p >
< hr />
< h2 id = "4-proponowany-zakres-etapami" > 4. Proponowany zakres (etapami)</ h2 >
< table >
< thead >
< tr >
< th > Etap</ th >
< th > Zmiana</ th >
< th style = "text-align: center;" > Ryzyko</ th >
</ tr >
</ thead >
< tbody >
< tr >
< td > 1</ td >
< td > Popup → dwa poziomy (Trail file…, Settings…); Reset głębiej; usuń podwójny Grid</ td >
< td style = "text-align: center;" > niskie</ td >
</ tr >
< tr >
< td > 2</ td >
< td > Wydziel < code > MapProjection</ code > ; < code > renderGrid</ code > i markery przez projekcję</ td >
< td style = "text-align: center;" > średnie (czysty refactor)</ td >
</ tr >
< tr >
< td > 3</ td >
< td > Uprość wybór kroku siatki; popraw nieaktualne komentarze; sprzątnij < code > _act_map</ code ></ td >
< td style = "text-align: center;" > niskie</ td >
</ tr >
</ tbody >
</ table >
< p > Etap 1 = największa poprawa „uporządkowania popupu" (główna prośba).
Etapy 2– 3 = czyszczenie logiki mapy/siatki bez zmiany wyglądu.</ p >
< hr />
< h2 id = "5-decyzje-zatwierdzone-2026-06-14" > 5. Decyzje (zatwierdzone 2026-06-14)</ h2 >
< ol >
< li >< strong > Popup — pełne podmenu.</ strong > Górne menu krótkie; < code > Trail file…</ code > i
< code > Settings…</ code > jako podmenu.</ li >
< li >< strong > Menu zależne od widoku — tak.</ strong > < code > Grid</ code > widoczny w Settings tylko na
widoku Map, < code > Readout</ code > tylko na Summary.</ li >
< li >< strong > Mapa — < code > MapProjection</ code > + uproszczenie siatki</ strong > (etap 2 i 3 razem).</ li >
< li >< strong > Siatka — kwadratowe oczka, dociągnięte do krótszego boku.</ strong > Krok w
przestrzeni pikseli (skala izotropiczna). Krótszy bok dzielony na
całkowitą liczbę równych kwadratów (siatka dotyka tej pary krawędzi —
na poziomym OLED: góra/dół), na dłuższym boku mieści się całkowita
liczba tych samych kwadratów, wyśrodkowana. Dzięki temu oczka są
< strong > kwadratowe</ strong > , siatka wpisana w ramkę i symetryczna (brak
jednostronnego przesunięcia). Etykieta skali = < strong > nominalna</ strong > okrągła
wartość. (Kwadraty + linie na wszystkich 4 krawędziach są
geometrycznie niemożliwe dla dowolnego prostokąta — wybrano kwadraty +
2 krawędzie + symetria.)</ li >
</ ol >
</ article >
</ div >
< script > var target = document . getElementById ( location . hash . slice ( 1 )); target && target . name && ( target . checked = target . name . startsWith ( "__tabbed_" ))</ script >
</ div >
</ main >
< footer class = "md-footer" >
< div class = "md-footer-meta md-typeset" >
< div class = "md-footer-meta__inner md-grid" >
< div class = "md-copyright" >
Made with
< a href = "https://squidfunk.github.io/mkdocs-material/" target = "_blank" rel = "noopener" >
Material for MkDocs
</ a >
</ div >
</ div >
</ div >
</ footer >
</ div >
< div class = "md-dialog" data-md-component = "dialog" >
< div class = "md-dialog__inner md-typeset" ></ div >
</ div >
< script id = "__config" type = "application/json" >{ "annotate" : null , "base" : "../.." , "features" : [ "content.action.edit" , "content.code.copy" , "search.highlight" , "search.suggest" ], "search" : "../../assets/javascripts/workers/search.2c215733.min.js" , "tags" : null , "translations" : { "clipboard.copied" : "Copied to clipboard" , "clipboard.copy" : "Copy to clipboard" , "search.result.more.one" : "1 more on this page" , "search.result.more.other" : "# more on this page" , "search.result.none" : "No matching documents" , "search.result.one" : "1 matching document" , "search.result.other" : "# matching documents" , "search.result.placeholder" : "Type to start searching" , "search.result.term.missing" : "Missing" , "select.version" : "Select version" }, "version" : null }</ script >
2026-07-18 08:11:35 +00:00
< script src = "../../assets/javascripts/bundle.d7400e89.min.js" ></ script >
2026-06-14 22:06:34 +00:00
</ body >
</ html >