diff --git a/lib/I18n/translations/english.yaml b/lib/I18n/translations/english.yaml index a868933c..c30e04b0 100644 --- a/lib/I18n/translations/english.yaml +++ b/lib/I18n/translations/english.yaml @@ -110,6 +110,7 @@ STR_TIME_TO_SLEEP: "Time to Sleep" STR_SHOW_HIDDEN_FILES: "Show Hidden Files" STR_SHOW_FILE_EXTENSIONS: "Show File Extensions" STR_USE_CLOCK: "Use Clock" +STR_USE_WEATHER: "Use Weather" STR_CLOCK_SETTINGS: "Clock Settings" STR_CLOCK_SETTINGS_WARNING: "Uses more battery; clock may drift" STR_CLOCK: "Clock" @@ -379,6 +380,7 @@ STR_AUTO_TURN_ENABLED: "Auto Turn Enabled: " STR_AUTO_TURN_PAGES_PER_MIN: "Auto Turn (Pages Per Minute)" STR_WEATHER: "Weather" STR_WEATHER_LOCATION: "Location" +STR_WEATHER_UNITS: "Units" STR_WEATHER_NO_LOCATION: "No location set for weather" STR_WEATHER_FETCH_FAILED: "Failed to fetch weather" STR_WEATHER_SETTINGS: "Weather Settings" diff --git a/lib/I18n/translations/french.yaml b/lib/I18n/translations/french.yaml index 640e940f..d8721b2a 100644 --- a/lib/I18n/translations/french.yaml +++ b/lib/I18n/translations/french.yaml @@ -44,6 +44,18 @@ STR_CONNECT_WIFI_HINT: "Connectez un appareil à ce WiFi" STR_OPEN_URL_HINT: "Ouvrez cette URL dans un navigateur" STR_OR_HTTP_PREFIX: "ou http://" STR_SCAN_QR_HINT: "ou scannez le QR code :" +STR_KEYBOARD_HELP_URL_LINE_1: "Mode URL : Espace bascule les snippets URL." +STR_KEYBOARD_HELP_URL_LINE_2: "Utilisez une grille 3×3 pour protocoles, hôtes et domaines." +STR_KEYBOARD_HELP_URL_LINE_3: "Appuyez sur ABC pour quitter le mode URL." +STR_KEYBOARD_HELP_CURSOR_LINE_1: "Mode curseur : appui long Haut, court Bas pour quitter." +STR_KEYBOARD_HELP_CURSOR_LINE_2: "Gauche/Droite déplace le curseur ; Confirmer bascule [abc]/[***]." +STR_KEYBOARD_HELP_CURSOR_LINE_3: "Le curseur bloc met en surbrillance le caractère sélectionné." +STR_KEYBOARD_HELP_PASSWORD_LINE_1: "Mode mot de passe masque le texte avec * et révèle un caractère." +STR_KEYBOARD_HELP_PASSWORD_LINE_2: "Utilisez le mode curseur au-delà de la fin pour basculer [abc]/[***]." +STR_KEYBOARD_HELP_PASSWORD_LINE_3: "Appui long sur Suppr efface tout le texte." +STR_KEYBOARD_HELP_DEFAULT_LINE_1: "Appui long sur Haut pour le mode curseur ; Gauche/Droite déplace le curseur." +STR_KEYBOARD_HELP_DEFAULT_LINE_2: "Maintenez Confirmer pour des caractères alternatifs en mode ABC." +STR_KEYBOARD_HELP_DEFAULT_LINE_3: "Shift change la casse ; Espace insère un espace normal." STR_RSSI: "RSSI" STR_NO_SIGNAL: "Pas de signal" STR_SIGNAL_QUALITY_POOR: "Faible" @@ -340,6 +352,7 @@ STR_OVERLAY_READING_PROGRESS: "Progression : Page %lu/%u - %.0f%%" STR_OVERLAY_READING_PROGRESS_NO_TOTAL: "Progression : Page %lu" STR_OVERLAY_CHAPTER_PAGE_SUFFIX: " - Page %d/%d - %.0f%%" STR_USE_CLOCK: "Afficher l'horloge" +STR_USE_WEATHER: "Afficher la météo" STR_CLOCK_SETTINGS: "Réglages horloge" STR_CLOCK_SETTINGS_WARNING: "Consomme plus de batterie ; l'heure peut dériver" STR_CLOCK: "Horloge" @@ -377,6 +390,16 @@ STR_DST_ACTIVE: "Heure d'été : active" STR_DST_INACTIVE: "Heure d'été : inactive" STR_DST_UNKNOWN: "Heure d'été : inconnue" STR_SYSTEM_INFO: "Informations système" +STR_APP_PARTITION: "Partition de l'application" +STR_DEVICE: "Appareil" +STR_FLASH_TOTAL: "Flash total" +STR_MEM_COMBINED: "Libre / Min / Max" +STR_SEC_VERSION: "Version" +STR_SEC_CHIP: "Chip" +STR_SEC_FLASH: "Flash" +STR_SEC_MEMORY: "Mémoire" +STR_SEC_RUNTIME: "Exécution" +STR_SEC_STORAGE: "Stockage" STR_LOAD_XTC_FAILED: "Échec du chargement XTC" STR_LOAD_EPUB_FAILED: "Échec du chargement EPUB" STR_FW_VERSION: "Version FW" @@ -393,6 +416,7 @@ STR_GATHERING_DATA: "Collecte des données…" STR_SD_UPDATE_PROMPT: "Appuyez sur mise à jour" STR_WEATHER: "Météo" STR_WEATHER_LOCATION: "Lieu" +STR_WEATHER_UNITS: "Unités" STR_WEATHER_NO_LOCATION: "Aucun lieu défini pour la météo" STR_WEATHER_FETCH_FAILED: "Échec du chargement météo" STR_WEATHER_SETTINGS: "Réglages météo" @@ -483,6 +507,8 @@ STR_SLEEP_SCREEN_SET: "Écran de veille mis à jour !" STR_IMAGE_DISPLAY_BW: ">> N/B" STR_IMAGE_DISPLAY_GRAYSCALE: ">> Niveaux de gris" STR_READER_BOOKMARKS: "Signets & notes de bas de page" +STR_GLOBAL_BOOKMARKS: "Signets" +STR_NO_GLOBAL_BOOKMARKS: "Aucun signet pour l'instant" STR_READER_UTILS: "Utilitaire" STR_STARRED_PAGES: "Pages marquées" STR_STAR_PAGE: "Marquer la page" diff --git a/lib/I18n/translations/german.yaml b/lib/I18n/translations/german.yaml index 39e60ec0..5eb0b6d4 100644 --- a/lib/I18n/translations/german.yaml +++ b/lib/I18n/translations/german.yaml @@ -358,6 +358,8 @@ STR_SLEEP_SCREEN_SET: "Standby-Bild aktualisiert!" STR_IMAGE_DISPLAY_BW: ">> S/W" STR_IMAGE_DISPLAY_GRAYSCALE: ">> Grau" STR_READER_BOOKMARKS: "Lesezeichen & Fußnoten" +STR_GLOBAL_BOOKMARKS: "Lesezeichen" +STR_NO_GLOBAL_BOOKMARKS: "Noch keine Lesezeichen" STR_READER_UTILS: "Hilfsfunktionen" STR_STARRED_PAGES: "Markierte Seiten" STR_STAR_PAGE: "Seite markieren" @@ -384,6 +386,7 @@ STR_MENU_KOSYNC_AUTH: "Anmelden / Registrieren" STR_WEATHER: "Wetter" STR_WEATHER_LOCATION: "Ort" +STR_WEATHER_UNITS: "Einheiten" STR_WEATHER_NO_LOCATION: "Kein Ort für Wetter festgelegt" STR_WEATHER_FETCH_FAILED: "Wetterdaten konnten nicht geladen werden" STR_WEATHER_SETTINGS: "Wettereinstellungen" @@ -466,6 +469,7 @@ STR_WEATHER_DESC_THUNDERSTORM_HEAVY_HAIL: "Gewitter mit starkem Hagel" STR_WEATHER_DESC_UNKNOWN: "Unbekannt" STR_CREATE_FALLBACK_FOR_INVALID_TOC: "Ersatz für ungültiges Inhaltsverzeichnis erstellen" STR_USE_CLOCK: "Uhr anzeigen" +STR_USE_WEATHER: "Wetter verwenden" STR_CLOCK_SETTINGS: "Uhr-Einstellungen" STR_CLOCK_SETTINGS_WARNING: "Verbraucht mehr Akku; Uhr kann abweichen" STR_CLOCK: "Uhr" @@ -509,3 +513,25 @@ STR_OVERLAY_OFF: "Aus" STR_OVERLAY_READING_PROGRESS: "Lesefortschritt: Seite %lu/%u - %.0f%%" STR_OVERLAY_READING_PROGRESS_NO_TOTAL: "Lesefortschritt: Seite %lu" STR_OVERLAY_CHAPTER_PAGE_SUFFIX: " - Seite %d/%d - %.0f%%" +STR_APP_PARTITION: "App-Partition" +STR_DEVICE: "Gerät" +STR_FLASH_TOTAL: "Gesamter Flash" +STR_MEM_COMBINED: "Frei / Min / Max" +STR_SEC_VERSION: "Version" +STR_SEC_CHIP: "Chip" +STR_SEC_FLASH: "Flash" +STR_SEC_MEMORY: "Speicher" +STR_SEC_RUNTIME: "Laufzeit" +STR_SEC_STORAGE: "Speicherplatz" +STR_KEYBOARD_HELP_URL_LINE_1: "URL-Modus: Leer schaltet URL-Snippets um." +STR_KEYBOARD_HELP_URL_LINE_2: "Nutzt 3×3-Raster für Protokolle, Hosts und Domains." +STR_KEYBOARD_HELP_URL_LINE_3: "Drücke ABC, um den URL-Modus zu verlassen." +STR_KEYBOARD_HELP_CURSOR_LINE_1: "Cursor-Modus: Hoch lange drücken, Ende mit Runter." +STR_KEYBOARD_HELP_CURSOR_LINE_2: "Links/Rechts bewegt Cursor; Bestätigen schaltet [abc]/[***] um." +STR_KEYBOARD_HELP_CURSOR_LINE_3: "Der Blockcursor markiert das ausgewählte Zeichen." +STR_KEYBOARD_HELP_PASSWORD_LINE_1: "Passwortmodus versteckt Text mit * und zeigt ein Zeichen an." +STR_KEYBOARD_HELP_PASSWORD_LINE_2: "Am Textende rechts drücken für [abc] bzw. [***]." +STR_KEYBOARD_HELP_PASSWORD_LINE_3: "Entf lang drücken löscht alles." +STR_KEYBOARD_HELP_DEFAULT_LINE_1: "Hoch lang drücken für Cursor-Modus; <- -> bewegt den Cursor." +STR_KEYBOARD_HELP_DEFAULT_LINE_2: "Lange Bestätigen drücken für alternative Zeichen." +STR_KEYBOARD_HELP_DEFAULT_LINE_3: "umsch für Groß-/Kleinschreibung" diff --git a/lib/I18n/translations/italian.yaml b/lib/I18n/translations/italian.yaml index 3c1fd1e7..35d52909 100644 --- a/lib/I18n/translations/italian.yaml +++ b/lib/I18n/translations/italian.yaml @@ -44,6 +44,18 @@ STR_CONNECT_WIFI_HINT: "Connettere il dispositivo a questa rete WiFi" STR_OPEN_URL_HINT: "Aprire questo URL nel browser" STR_OR_HTTP_PREFIX: "o http://" STR_SCAN_QR_HINT: "oppure scansionare il codice QR col telefono:" +STR_KEYBOARD_HELP_URL_LINE_1: "Modalità URL: Spazio alterna gli snippet URL." +STR_KEYBOARD_HELP_URL_LINE_2: "Usa una griglia 3×3 per protocolli, host e domini." +STR_KEYBOARD_HELP_URL_LINE_3: "Premi ABC per uscire dalla modalità URL." +STR_KEYBOARD_HELP_CURSOR_LINE_1: "Modalità cursore: tieni premuto Su, breve Giù per uscire." +STR_KEYBOARD_HELP_CURSOR_LINE_2: "Sinistra/Destra sposta il cursore; Conferma alterna [abc]/[***]." +STR_KEYBOARD_HELP_CURSOR_LINE_3: "Il cursore blocco evidenzia il carattere selezionato." +STR_KEYBOARD_HELP_PASSWORD_LINE_1: "Modalità password nasconde il testo con * e mostra un carattere." +STR_KEYBOARD_HELP_PASSWORD_LINE_2: "Usa la modalità cursore oltre la fine per alternare [abc]/[***]." +STR_KEYBOARD_HELP_PASSWORD_LINE_3: "Tieni premuto Canc per cancellare tutto il testo." +STR_KEYBOARD_HELP_DEFAULT_LINE_1: "Tieni premuto Su per la modalità cursore; Sinistra/Destra sposta il cursore." +STR_KEYBOARD_HELP_DEFAULT_LINE_2: "Tieni premuto Conferma per caratteri alternativi in modalità ABC." +STR_KEYBOARD_HELP_DEFAULT_LINE_3: "Shift cambia maiuscole/minuscole; Spazio inserisce uno spazio normale." STR_RSSI: "RSSI" STR_NO_SIGNAL: "Nessun segnale" STR_SIGNAL_QUALITY_POOR: "Scarso" @@ -322,6 +334,7 @@ STR_IMAGE_DITHER_ATKINSON: "Atkinson" STR_IMAGE_DITHER_DIFFUSED_BAYER: "Bayer diffuso" STR_CREATE_FALLBACK_FOR_INVALID_TOC: "Crea fallback per TOC non valido" STR_USE_CLOCK: "Mostra orologio" +STR_USE_WEATHER: "Usa meteo" STR_CLOCK_SETTINGS: "Impostazioni orologio" STR_CLOCK_SETTINGS_WARNING: "Consuma più batteria; l'orologio può scorrere" STR_CLOCK: "Orologio" @@ -370,6 +383,7 @@ STR_MAPPING_REMOTE: "Mappatura posizione remota..." STR_MAPPING_LOCAL: "Calcolo posizione locale..." STR_WEATHER: "Meteo" STR_WEATHER_LOCATION: "Località" +STR_WEATHER_UNITS: "Unità" STR_WEATHER_NO_LOCATION: "Nessuna località impostata" STR_WEATHER_FETCH_FAILED: "Impossibile recuperare il meteo" STR_WEATHER_SETTINGS: "Impostazioni meteo" @@ -458,6 +472,16 @@ STR_OVERLAY_READING_PROGRESS: "Avanzamento lettura: Pagina %lu/%u - %.0f%%" STR_OVERLAY_READING_PROGRESS_NO_TOTAL: "Avanzamento lettura: Pagina %lu" STR_OVERLAY_CHAPTER_PAGE_SUFFIX: " - Pagina %d/%d - %.0f%%" STR_SYSTEM_INFO: "Informazioni di sistema" +STR_APP_PARTITION: "Partizione app" +STR_DEVICE: "Dispositivo" +STR_FLASH_TOTAL: "Flash totale" +STR_MEM_COMBINED: "Libero / Min / Max" +STR_SEC_VERSION: "Versione" +STR_SEC_CHIP: "Chip" +STR_SEC_FLASH: "Flash" +STR_SEC_MEMORY: "Memoria" +STR_SEC_RUNTIME: "Runtime" +STR_SEC_STORAGE: "Archiviazione" STR_LOAD_XTC_FAILED: "Impossibile caricare file XTC" STR_LOAD_EPUB_FAILED: "Impossibile caricare file EPUB" STR_FW_VERSION: "Versione FW" @@ -481,6 +505,8 @@ STR_SLEEP_SCREEN_SET: "Schermo standby aggiornato!" STR_IMAGE_DISPLAY_BW: ">> B/N" STR_IMAGE_DISPLAY_GRAYSCALE: ">> Gradazioni di grigio" STR_READER_BOOKMARKS: "Segnalibri e note" +STR_GLOBAL_BOOKMARKS: "Segnalibri" +STR_NO_GLOBAL_BOOKMARKS: "Ancora nessun segnalibro" STR_READER_UTILS: "Utilità" STR_STARRED_PAGES: "Pagine contrassegnate" STR_STAR_PAGE: "Contrassegna pagina" diff --git a/lib/I18n/translations/russian.yaml b/lib/I18n/translations/russian.yaml index 155301bc..3d32b1f6 100644 --- a/lib/I18n/translations/russian.yaml +++ b/lib/I18n/translations/russian.yaml @@ -44,6 +44,18 @@ STR_CONNECT_WIFI_HINT: "Подключите устройство к этой с STR_OPEN_URL_HINT: "Откройте этот адрес в браузере" STR_OR_HTTP_PREFIX: "или http://" STR_SCAN_QR_HINT: "или отсканируйте QR-код:" +STR_KEYBOARD_HELP_URL_LINE_1: "Режим URL: пробел переключает фрагменты URL." +STR_KEYBOARD_HELP_URL_LINE_2: "Используйте сетку 3×3 для протоколов, хостов и доменов." +STR_KEYBOARD_HELP_URL_LINE_3: "Нажмите ABC, чтобы выйти из режима URL." +STR_KEYBOARD_HELP_CURSOR_LINE_1: "Режим курсора: длинное нажатие Вверх, короткое Вниз для выхода." +STR_KEYBOARD_HELP_CURSOR_LINE_2: "Влево/Вправо перемещает курсор; Подтвердить переключает [abc]/[***]." +STR_KEYBOARD_HELP_CURSOR_LINE_3: "Блочный курсор выделяет выбранный символ." +STR_KEYBOARD_HELP_PASSWORD_LINE_1: "Режим пароля скрывает текст * и показывает один символ." +STR_KEYBOARD_HELP_PASSWORD_LINE_2: "Используйте режим курсора за концом, чтобы переключить [abc]/[***]." +STR_KEYBOARD_HELP_PASSWORD_LINE_3: "Долгое нажатие Del удаляет весь текст." +STR_KEYBOARD_HELP_DEFAULT_LINE_1: "Долгое нажатие Вверх для режима курсора; Влево/Вправо перемещает курсор." +STR_KEYBOARD_HELP_DEFAULT_LINE_2: "Удерживайте Подтвердить для альтернативного ввода в режиме ABC." +STR_KEYBOARD_HELP_DEFAULT_LINE_3: "Shift переключает регистр; Пробел вставляет обычный пробел." STR_RSSI: "RSSI" STR_NO_SIGNAL: "Нет сигнала" STR_SIGNAL_QUALITY_POOR: "Плохо" @@ -337,6 +349,7 @@ STR_OVERLAY_READING_PROGRESS: "Прогресс: Стр. %lu/%u - %.0f%%" STR_OVERLAY_READING_PROGRESS_NO_TOTAL: "Прогресс: Стр. %lu" STR_OVERLAY_CHAPTER_PAGE_SUFFIX: " - Стр. %d/%d - %.0f%%" STR_USE_CLOCK: "Показывать часы" +STR_USE_WEATHER: "Использовать погоду" STR_CLOCK_SETTINGS: "Настройки часов" STR_CLOCK_SETTINGS_WARNING: "Расходует больше батареи; часы могут отставать" STR_CLOCK: "Часы" @@ -374,6 +387,16 @@ STR_DST_ACTIVE: "Летнее время: вкл" STR_DST_INACTIVE: "Летнее время: выкл" STR_DST_UNKNOWN: "Летнее время: неизвестно" STR_SYSTEM_INFO: "Информация о системе" +STR_APP_PARTITION: "Раздел приложения" +STR_DEVICE: "Устройство" +STR_FLASH_TOTAL: "Всего Flash" +STR_MEM_COMBINED: "Свободно / Мин / Макс" +STR_SEC_VERSION: "Версия" +STR_SEC_CHIP: "Чип" +STR_SEC_FLASH: "Flash" +STR_SEC_MEMORY: "Память" +STR_SEC_RUNTIME: "Время работы" +STR_SEC_STORAGE: "Хранилище" STR_LOAD_XTC_FAILED: "Ошибка загрузки файла XTC" STR_LOAD_EPUB_FAILED: "Ошибка загрузки файла EPUB" STR_FW_VERSION: "Версия ПО" @@ -390,6 +413,7 @@ STR_GATHERING_DATA: "Сбор данных..." STR_SD_UPDATE_PROMPT: "Нажмите обновить" STR_WEATHER: "Погода" STR_WEATHER_LOCATION: "Местоположение" +STR_WEATHER_UNITS: "Единицы" STR_WEATHER_NO_LOCATION: "Местоположение не задано" STR_WEATHER_FETCH_FAILED: "Ошибка загрузки погоды" STR_WEATHER_SETTINGS: "Настройки погоды" @@ -483,6 +507,8 @@ STR_SLEEP_SCREEN_SET: "Экран сна обновлён!" STR_IMAGE_DISPLAY_BW: ">> Ч/Б" STR_IMAGE_DISPLAY_GRAYSCALE: ">> Оттенки серого" STR_READER_BOOKMARKS: "Закладки и сноски" +STR_GLOBAL_BOOKMARKS: "Закладки" +STR_NO_GLOBAL_BOOKMARKS: "Пока нет закладок" STR_READER_UTILS: "Утилиты" STR_STARRED_PAGES: "Отмеченные страницы" STR_STAR_PAGE: "Отметить страницу" diff --git a/lib/I18n/translations/spanish.yaml b/lib/I18n/translations/spanish.yaml index 45e0ead0..2f04f2b6 100644 --- a/lib/I18n/translations/spanish.yaml +++ b/lib/I18n/translations/spanish.yaml @@ -44,6 +44,18 @@ STR_CONNECT_WIFI_HINT: "Conecte su dispositivo a esta red Wi-Fi" STR_OPEN_URL_HINT: "Abra esta dirección en su navegador" STR_OR_HTTP_PREFIX: "o http://" STR_SCAN_QR_HINT: "o escanee el código QR con su móvil:" +STR_KEYBOARD_HELP_URL_LINE_1: "Modo URL: Espacio cambia fragmentos de URL." +STR_KEYBOARD_HELP_URL_LINE_2: "Use una cuadrícula 3×3 para protocolos, hosts y dominios." +STR_KEYBOARD_HELP_URL_LINE_3: "Presione ABC para salir del modo URL." +STR_KEYBOARD_HELP_CURSOR_LINE_1: "Modo cursor: presione largo Arriba, corto Abajo para salir." +STR_KEYBOARD_HELP_CURSOR_LINE_2: "Izquierda/Derecha mueve el cursor; Confirmar alterna [abc]/[***]." +STR_KEYBOARD_HELP_CURSOR_LINE_3: "El cursor bloque resalta el carácter seleccionado." +STR_KEYBOARD_HELP_PASSWORD_LINE_1: "Modo contraseña oculta texto con * y muestra un carácter." +STR_KEYBOARD_HELP_PASSWORD_LINE_2: "Use el modo cursor más allá del final para alternar [abc]/[***]." +STR_KEYBOARD_HELP_PASSWORD_LINE_3: "Presione largo Supr para borrar todo el texto." +STR_KEYBOARD_HELP_DEFAULT_LINE_1: "Presione largo Arriba para modo cursor; Izquierda/Derecha mueve el cursor." +STR_KEYBOARD_HELP_DEFAULT_LINE_2: "Mantenga pulsado Confirmar para caracteres alternativos en modo ABC." +STR_KEYBOARD_HELP_DEFAULT_LINE_3: "Shift cambia mayúsculas/minúsculas; Espacio inserta un espacio normal." STR_CALIBRE_WIRELESS: "Calibre inalámbrico" STR_CALIBRE_WEB_URL: "OPDS URL" STR_NETWORK_LEGEND: "* (Cifrado) | + (Guardado)" @@ -334,6 +346,7 @@ STR_OVERLAY_READING_PROGRESS: "Progreso: Página %lu/%u - %.0f%%" STR_OVERLAY_READING_PROGRESS_NO_TOTAL: "Progreso: Página %lu" STR_OVERLAY_CHAPTER_PAGE_SUFFIX: " - Página %d/%d - %.0f%%" STR_USE_CLOCK: "Mostrar reloj" +STR_USE_WEATHER: "Usar clima" STR_CLOCK_SETTINGS: "Ajustes de reloj" STR_CLOCK_SETTINGS_WARNING: "Consume más batería; el reloj puede desviarse" STR_CLOCK: "Reloj" @@ -371,6 +384,16 @@ STR_DST_ACTIVE: "Horario de verano: activo" STR_DST_INACTIVE: "Horario de verano: inactivo" STR_DST_UNKNOWN: "Horario de verano: desconocido" STR_SYSTEM_INFO: "Información del sistema" +STR_APP_PARTITION: "Partición de la app" +STR_DEVICE: "Dispositivo" +STR_FLASH_TOTAL: "Flash total" +STR_MEM_COMBINED: "Libre / Min / Máx" +STR_SEC_VERSION: "Versión" +STR_SEC_CHIP: "Chip" +STR_SEC_FLASH: "Flash" +STR_SEC_MEMORY: "Memoria" +STR_SEC_RUNTIME: "Tiempo de ejecución" +STR_SEC_STORAGE: "Almacenamiento" STR_LOAD_XTC_FAILED: "Error al cargar archivo XTC" STR_LOAD_EPUB_FAILED: "Error al cargar archivo EPUB" STR_FW_VERSION: "Versión FW" @@ -387,6 +410,7 @@ STR_GATHERING_DATA: "Recopilando datos..." STR_SD_UPDATE_PROMPT: "Presiona actualizar" STR_WEATHER: "Clima" STR_WEATHER_LOCATION: "Ubicación" +STR_WEATHER_UNITS: "Unidades" STR_WEATHER_NO_LOCATION: "No se ha configurado ubicación" STR_WEATHER_FETCH_FAILED: "Error al obtener datos del clima" STR_WEATHER_SETTINGS: "Ajustes del clima" @@ -483,6 +507,8 @@ STR_SLEEP_SCREEN_SET: "Pantalla de suspensión actualizada!" STR_IMAGE_DISPLAY_BW: ">> N/B" STR_IMAGE_DISPLAY_GRAYSCALE: ">> Escala de grises" STR_READER_BOOKMARKS: "Marcadores y notas" +STR_GLOBAL_BOOKMARKS: "Marcadores" +STR_NO_GLOBAL_BOOKMARKS: "Aún no hay marcadores" STR_READER_UTILS: "Utilidades" STR_STARRED_PAGES: "Páginas marcadas" STR_STAR_PAGE: "Marcar página" diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index 8a788d98..7334ca71 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -271,6 +271,8 @@ class CrossPointSettings { // Use clock and keep the LP timer running during deep sleep (GPIO13 HIGH) // so time can be accurately restored on wake. Increases sleep current by ~3-4 mA. uint8_t useClock = 0; + // Show the Weather home screen menu item (1 = enabled, 0 = hidden) + uint8_t useWeather = 1; ~CrossPointSettings() = default; diff --git a/src/SettingsList.h b/src/SettingsList.h index b7643590..f108e2ec 100644 --- a/src/SettingsList.h +++ b/src/SettingsList.h @@ -143,6 +143,7 @@ inline const std::vector list = { StrId::STR_TZ_EST, StrId::STR_TZ_CST, StrId::STR_TZ_MST, StrId::STR_TZ_PST}, "timeZone", StrId::STR_CAT_SYSTEM), SettingInfo::Toggle(StrId::STR_USE_CLOCK, &CrossPointSettings::useClock, "useClock", StrId::STR_CAT_SYSTEM), + SettingInfo::Toggle(StrId::STR_USE_WEATHER, &CrossPointSettings::useWeather, "useWeather", StrId::STR_CAT_SYSTEM), // --- KOReader Sync (web-only, uses KOReaderCredentialStore) --- SettingInfo::DynamicString( diff --git a/src/activities/home/HomeActivity.cpp b/src/activities/home/HomeActivity.cpp index f3bade9c..a010c778 100644 --- a/src/activities/home/HomeActivity.cpp +++ b/src/activities/home/HomeActivity.cpp @@ -100,7 +100,10 @@ int getHomeCoverRenderHeight(const HomeScreenLayout& layout) { } // namespace int HomeActivity::getMenuItemCount() const { - int count = 5; // File Browser, Recents, File transfer, Weather, Settings + int count = 4; // File Browser, Recents, File transfer, Settings + if (SETTINGS.useWeather) { + count++; + } if (!recentBooks.empty()) { count += recentBooks.size(); } @@ -283,12 +286,13 @@ void HomeActivity::loop() { int idx = 0; int menuSelectedIndex = selectorIndex - static_cast(recentBooks.size()); const bool hasGlobalBookmarks = !GLOBAL_BOOKMARKS.isEmpty(); + const bool hasWeather = SETTINGS.useWeather; const int fileBrowserIdx = idx++; const int recentsIdx = idx++; const int globalBookmarksIdx = hasGlobalBookmarks ? idx++ : -1; const int opdsLibraryIdx = hasOpdsUrl ? idx++ : -1; const int fileTransferIdx = idx++; - const int weatherIdx = idx++; + const int weatherIdx = hasWeather ? idx++ : -1; const int settingsIdx = idx; if (selectorIndex < recentBooks.size()) { @@ -321,9 +325,17 @@ void HomeActivity::render(RenderLock&&) { GUI.drawHeader(renderer, Rect{contentRect.x, metrics.topPadding, contentRect.width, metrics.homeTopPadding}, nullptr); // Build menu items dynamically + const char* weatherMenuLabel = SETTINGS.useWeather ? tr(STR_WEATHER) : tr(STR_SETTINGS_TITLE); + const UIIcon weatherMenuIcon = SETTINGS.useWeather ? Weather : Settings; + std::vector menuItems = {tr(STR_BROWSE_FILES), tr(STR_MENU_RECENT_BOOKS), tr(STR_FILE_TRANSFER), - tr(STR_WEATHER), tr(STR_SETTINGS_TITLE)}; - std::vector menuIcons = {Folder, Recent, Transfer, Weather, Settings}; + weatherMenuLabel, tr(STR_SETTINGS_TITLE)}; + std::vector menuIcons = {Folder, Recent, Transfer, weatherMenuIcon, Settings}; + + if (!SETTINGS.useWeather) { + menuItems.erase(menuItems.begin() + 3); + menuIcons.erase(menuIcons.begin() + 3); + } int insertAfterRecents = 2; if (!GLOBAL_BOOKMARKS.isEmpty()) { diff --git a/src/activities/settings/ClockSettingsActivity.cpp b/src/activities/settings/ClockSettingsActivity.cpp index 0137b77a..854b2347 100644 --- a/src/activities/settings/ClockSettingsActivity.cpp +++ b/src/activities/settings/ClockSettingsActivity.cpp @@ -6,7 +6,6 @@ #include "CrossPointSettings.h" #include "DetectTimezoneActivity.h" -#include "MappedInputManager.h" #include "SyncTimeActivity.h" #include "components/UITheme.h" #include "fontIds.h" @@ -19,94 +18,48 @@ const StrId timeZoneNames[CrossPointSettings::TIMEZONE_COUNT] = { StrId::STR_TZ_EST, StrId::STR_TZ_CST, StrId::STR_TZ_MST, StrId::STR_TZ_PST}; } // namespace -std::string ClockSettingsActivity::MenuItem::getTitle() const { - const auto t = I18N.get(labelId); - return isSeparator ? UITheme::makeSeparatorTitle(t) : t; +void ClockSettingsActivity::buildMenuItems() { + menuItems.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_TITLE)); + menuItems.push_back( + SettingInfo::Toggle(StrId::STR_USE_CLOCK, &CrossPointSettings::useClock, "useClock", StrId::STR_CAT_SYSTEM)); + menuItems.push_back(SettingInfo::Enum(StrId::STR_CLOCK_FORMAT, &CrossPointSettings::clockFormat12h, + {StrId::STR_24H, StrId::STR_12H}, "clockFormat12h", StrId::STR_CAT_SYSTEM)); + menuItems.push_back( + SettingInfo::Enum(StrId::STR_TIMEZONE, &CrossPointSettings::timeZone, + {StrId::STR_TZ_UTC, StrId::STR_TZ_CET, StrId::STR_TZ_EET, StrId::STR_TZ_MSK, + StrId::STR_TZ_UTC_PLUS4, StrId::STR_TZ_IST, StrId::STR_TZ_UTC_PLUS7, StrId::STR_TZ_UTC_PLUS8, + StrId::STR_TZ_UTC_PLUS9, StrId::STR_TZ_AEST, StrId::STR_TZ_NZST, StrId::STR_TZ_UTC_MINUS3, + StrId::STR_TZ_EST, StrId::STR_TZ_CST, StrId::STR_TZ_MST, StrId::STR_TZ_PST}, + "timeZone", StrId::STR_CAT_SYSTEM)); + + menuItems.push_back(SettingInfo::Action(StrId::STR_DETECT_TIMEZONE, SettingAction::DetectTimezone) + .withSubcategory(StrId::STR_READER_TOOLS)); + menuItems.push_back(SettingInfo::Action(StrId::STR_SYNC_TIME, SettingAction::SyncTime)); } -std::vector ClockSettingsActivity::buildMenuItems() { - std::vector items; - items.reserve(7); - // Settings - items.push_back(MenuItem::separator(StrId::STR_SETTINGS_TITLE)); - items.push_back({Action::USE_CLOCK, StrId::STR_USE_CLOCK}); - items.push_back({Action::CLOCK_FORMAT, StrId::STR_CLOCK_FORMAT}); - items.push_back({Action::TIMEZONE, StrId::STR_TIMEZONE}); - - // Tools - items.push_back(MenuItem::separator(StrId::STR_READER_TOOLS)); - items.push_back({Action::DETECT_TIMEZONE, StrId::STR_DETECT_TIMEZONE}); - items.push_back({Action::SYNC_TIME, StrId::STR_SYNC_TIME}); - return items; -} - -void ClockSettingsActivity::onEnter() { - Activity::onEnter(); - const auto pred = UITheme::makeSelectablePredicate(static_cast(menuItems.size()), - [this](int i) { return menuItems[i].getTitle(); }); - buttonNavigator.setSelectablePredicate(pred, static_cast(menuItems.size())); - if (!pred(selectedIndex)) { - selectedIndex = buttonNavigator.nextIndex(selectedIndex); +void ClockSettingsActivity::onActionSelected(int index) { + const auto& item = menuItems[index]; + if (item.nameId == StrId::STR_DETECT_TIMEZONE) { + auto resultHandler = [](const ActivityResult&) { SETTINGS.saveToFile(); }; + startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); + } else if (item.nameId == StrId::STR_SYNC_TIME) { + auto resultHandler = [](const ActivityResult&) { SETTINGS.saveToFile(); }; + startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); } - requestUpdate(); } -void ClockSettingsActivity::onExit() { Activity::onExit(); } - -void ClockSettingsActivity::loop() { - if (mappedInput.wasPressed(MappedInputManager::Button::Back)) { - finish(); - return; - } - - if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) { - handleSelection(); - requestUpdate(); - return; - } - - buttonNavigator.onNextRelease([this] { - selectedIndex = buttonNavigator.nextIndex(selectedIndex); - requestUpdate(); - }); - - buttonNavigator.onPreviousRelease([this] { - selectedIndex = buttonNavigator.previousIndex(selectedIndex); - requestUpdate(); - }); - - buttonNavigator.onNextContinuous([this] { - selectedIndex = buttonNavigator.nextIndex(selectedIndex); - requestUpdate(); - }); - - buttonNavigator.onPreviousContinuous([this] { - selectedIndex = buttonNavigator.previousIndex(selectedIndex); - requestUpdate(); - }); -} - -void ClockSettingsActivity::handleSelection() { - const auto action = menuItems[selectedIndex].action; - if (action == Action::USE_CLOCK) { - SETTINGS.useClock = (SETTINGS.useClock + 1) % 2; +void ClockSettingsActivity::onSettingToggled(int index) { + const auto& item = menuItems[index]; + if (item.nameId == StrId::STR_USE_CLOCK) { if (!SETTINGS.useClock) { SETTINGS.statusBarClock = 0; } SETTINGS.saveToFile(); - } else if (action == Action::CLOCK_FORMAT) { - SETTINGS.clockFormat12h = (SETTINGS.clockFormat12h + 1) % 2; - SETTINGS.saveToFile(); - } else if (action == Action::TIMEZONE) { - SETTINGS.timeZone = (SETTINGS.timeZone + 1) % CrossPointSettings::TIMEZONE_COUNT; + } else if (item.nameId == StrId::STR_TIMEZONE) { HalClock::applyTimezone(SETTINGS.timeZone); SETTINGS.saveToFile(); - } else if (action == Action::SYNC_TIME) { - auto resultHandler = [](const ActivityResult&) { SETTINGS.saveToFile(); }; - startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); - } else if (action == Action::DETECT_TIMEZONE) { - auto resultHandler = [](const ActivityResult&) { SETTINGS.saveToFile(); }; - startActivityForResult(std::make_unique(renderer, mappedInput), resultHandler); + } else if (item.nameId == StrId::STR_CLOCK_FORMAT) { + SETTINGS.saveToFile(); } } @@ -129,28 +82,7 @@ void ClockSettingsActivity::render(RenderLock&&) { const int contentHeight = contentRect.height - (metrics.topPadding + metrics.headerHeight + metrics.tabBarHeight + metrics.verticalSpacing * 2); - GUI.drawList( - renderer, Rect(contentRect.x, contentTop, contentRect.width, contentHeight), static_cast(menuItems.size()), - selectedIndex, [this](int index) { return menuItems[index].getTitle(); }, nullptr, nullptr, - [this](int index) { - const auto action = menuItems[index].action; - switch (action) { - case Action::USE_CLOCK: - return std::string(SETTINGS.useClock ? tr(STR_STATE_ON) : tr(STR_STATE_OFF)); - case Action::CLOCK_FORMAT: - return std::string(SETTINGS.clockFormat12h ? tr(STR_12H) : tr(STR_24H)); - case Action::TIMEZONE: { - const auto tzIndex = static_cast(SETTINGS.timeZone); - if (tzIndex < (sizeof(timeZoneNames) / sizeof(timeZoneNames[0]))) { - return std::string(I18N.get(timeZoneNames[tzIndex])); - } - return std::string(tr(STR_TZ_UTC)); - } - default: - return std::string(""); - } - }, - true); + drawMenuList(Rect{contentRect.x, contentTop, contentRect.width, contentHeight}); const auto labels = mappedInput.mapLabels(tr(STR_BACK), tr(STR_SELECT), tr(STR_DIR_UP), tr(STR_DIR_DOWN)); GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4); diff --git a/src/activities/settings/ClockSettingsActivity.h b/src/activities/settings/ClockSettingsActivity.h index 54a4196b..0486014b 100644 --- a/src/activities/settings/ClockSettingsActivity.h +++ b/src/activities/settings/ClockSettingsActivity.h @@ -1,35 +1,18 @@ #pragma once -#include -#include -#include - -#include "activities/Activity.h" -#include "util/ButtonNavigator.h" - -class ClockSettingsActivity final : public Activity { - enum class Action { USE_CLOCK, CLOCK_FORMAT, TIMEZONE, SYNC_TIME, DETECT_TIMEZONE, NONE }; - - struct MenuItem { - Action action; - StrId labelId; - bool isSeparator = false; - static MenuItem separator(StrId label) { return {Action::NONE, label, true}; } - [[nodiscard]] std::string getTitle() const; - }; - - ButtonNavigator buttonNavigator; - int selectedIndex = 0; - const std::vector menuItems; - - static std::vector buildMenuItems(); - void handleSelection(); +#include "../MenuListActivity.h" +class ClockSettingsActivity final : public MenuListActivity { public: explicit ClockSettingsActivity(GfxRenderer& renderer, MappedInputManager& mappedInput) - : Activity("ClockSettings", renderer, mappedInput), menuItems(buildMenuItems()) {} - void onEnter() override; - void onExit() override; - void loop() override; + : MenuListActivity("ClockSettings", renderer, mappedInput) { + buildMenuItems(); + } + void render(RenderLock&&) override; + + private: + void buildMenuItems(); + void onActionSelected(int index) override; + void onSettingToggled(int index) override; }; diff --git a/src/activities/weather/WeatherSettingsActivity.cpp b/src/activities/weather/WeatherSettingsActivity.cpp index b3b69664..32e938a4 100644 --- a/src/activities/weather/WeatherSettingsActivity.cpp +++ b/src/activities/weather/WeatherSettingsActivity.cpp @@ -13,29 +13,29 @@ #include "components/UITheme.h" #include "fontIds.h" -namespace { -const StrId menuNames[] = { - StrId::STR_WEATHER_LOCATION, // 0: Search city - StrId::STR_WEATHER_LATITUDE, // 1: Manual latitude - StrId::STR_WEATHER_LONGITUDE, // 2: Manual longitude - StrId::STR_WEATHER_TEMP_UNIT, // 3: Temperature unit - StrId::STR_WEATHER_WIND_UNIT, // 4: Wind speed unit - StrId::STR_WEATHER_PRECIP_UNIT, // 5: Precipitation unit -}; -} // namespace +void WeatherSettingsActivity::buildMenuItems() { + menuItems.push_back(SettingInfo::Separator(StrId::STR_SETTINGS_TITLE)); + menuItems.push_back(SettingInfo::Toggle(StrId::STR_USE_WEATHER, &CrossPointSettings::useWeather, "useWeather", + StrId::STR_CAT_SYSTEM)); -void WeatherSettingsActivity::onEnter() { - Activity::onEnter(); - selectedIndex = 0; - showingSearchResults = false; - requestUpdate(); + menuItems.push_back(SettingInfo::Separator(StrId::STR_WEATHER_LOCATION)); + menuItems.push_back(SettingInfo::Action(StrId::STR_WEATHER_LOCATION, SettingAction::None)); + menuItems.push_back(SettingInfo::Action(StrId::STR_WEATHER_LATITUDE, SettingAction::None)); + menuItems.push_back(SettingInfo::Action(StrId::STR_WEATHER_LONGITUDE, SettingAction::None)); + + menuItems.push_back(SettingInfo::Separator(StrId::STR_WEATHER_UNITS)); + menuItems.push_back(SettingInfo::Action(StrId::STR_WEATHER_TEMP_UNIT, SettingAction::None)); + menuItems.push_back(SettingInfo::Action(StrId::STR_WEATHER_WIND_UNIT, SettingAction::None)); + menuItems.push_back(SettingInfo::Action(StrId::STR_WEATHER_PRECIP_UNIT, SettingAction::None)); } -void WeatherSettingsActivity::onExit() { Activity::onExit(); } +void WeatherSettingsActivity::onEnter() { + MenuListActivity::onEnter(); + showingSearchResults = false; +} void WeatherSettingsActivity::loop() { if (showingSearchResults) { - // Handle search results navigation if (mappedInput.wasPressed(MappedInputManager::Button::Back)) { showingSearchResults = false; requestUpdate(); @@ -43,7 +43,7 @@ void WeatherSettingsActivity::loop() { } if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) { - if (!searchResults.empty() && selectedIndex < searchResults.size()) { + if (!searchResults.empty() && selectedIndex < static_cast(searchResults.size())) { const auto& result = searchResults[selectedIndex]; WEATHER_SETTINGS.setLocation(result.latitude, result.longitude, result.name + ", " + result.country); WEATHER_SETTINGS.saveToFile(); @@ -69,50 +69,89 @@ void WeatherSettingsActivity::loop() { return; } - if (mappedInput.wasPressed(MappedInputManager::Button::Back)) { - finish(); - return; - } - - if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) { - handleSelection(); - return; - } - - buttonNavigator.onNext([this] { - selectedIndex = (selectedIndex + 1) % MENU_ITEMS; - requestUpdate(); - }); - - buttonNavigator.onPrevious([this] { - selectedIndex = (selectedIndex + MENU_ITEMS - 1) % MENU_ITEMS; - requestUpdate(); - }); + MenuListActivity::loop(); } -void WeatherSettingsActivity::handleSelection() { - switch (selectedIndex) { - case 0: - launchCitySearch(); - break; - case 1: - launchLatitudeEntry(); - break; - case 2: - launchLongitudeEntry(); - break; - case 3: - toggleTempUnit(); - break; - case 4: - toggleWindUnit(); - break; - case 5: - togglePrecipUnit(); - break; +std::string WeatherSettingsActivity::getItemValueString(int index) const { + const auto& item = menuItems[index]; + switch (item.nameId) { + case StrId::STR_WEATHER_LOCATION: { + auto name = WEATHER_SETTINGS.getLocationName(); + return name.empty() ? std::string(tr(STR_NOT_SET)) : name; + } + case StrId::STR_WEATHER_LATITUDE: { + char buf[16]; + snprintf(buf, sizeof(buf), "%.4f", WEATHER_SETTINGS.getLatitude()); + return std::string(buf); + } + case StrId::STR_WEATHER_LONGITUDE: { + char buf[16]; + snprintf(buf, sizeof(buf), "%.4f", WEATHER_SETTINGS.getLongitude()); + return std::string(buf); + } + case StrId::STR_WEATHER_TEMP_UNIT: + return WEATHER_SETTINGS.getTempUnit() == WeatherTempUnit::CELSIUS ? "C" : "F"; + case StrId::STR_WEATHER_WIND_UNIT: + switch (WEATHER_SETTINGS.getWindUnit()) { + case WeatherWindUnit::KMH: + return "km/h"; + case WeatherWindUnit::MS: + return "m/s"; + case WeatherWindUnit::MPH: + return "mph"; + case WeatherWindUnit::KNOTS: + return "kn"; + } + return "km/h"; + case StrId::STR_WEATHER_PRECIP_UNIT: + return WEATHER_SETTINGS.getPrecipUnit() == WeatherPrecipUnit::MM ? "mm" : "in"; + default: + return MenuListActivity::getItemValueString(index); } } +void WeatherSettingsActivity::onActionSelected(int index) { + const auto& item = menuItems[index]; + if (item.nameId == StrId::STR_WEATHER_LOCATION) { + launchCitySearch(); + } else if (item.nameId == StrId::STR_WEATHER_LATITUDE) { + launchLatitudeEntry(); + } else if (item.nameId == StrId::STR_WEATHER_LONGITUDE) { + launchLongitudeEntry(); + } else if (item.nameId == StrId::STR_WEATHER_TEMP_UNIT) { + auto current = WEATHER_SETTINGS.getTempUnit(); + WEATHER_SETTINGS.setTempUnit(current == WeatherTempUnit::CELSIUS ? WeatherTempUnit::FAHRENHEIT + : WeatherTempUnit::CELSIUS); + WEATHER_SETTINGS.saveToFile(); + requestUpdate(); + } else if (item.nameId == StrId::STR_WEATHER_WIND_UNIT) { + auto current = static_cast(WEATHER_SETTINGS.getWindUnit()); + WEATHER_SETTINGS.setWindUnit(static_cast((current + 1) % 4)); + WEATHER_SETTINGS.saveToFile(); + requestUpdate(); + } else if (item.nameId == StrId::STR_WEATHER_PRECIP_UNIT) { + auto current = WEATHER_SETTINGS.getPrecipUnit(); + WEATHER_SETTINGS.setPrecipUnit(current == WeatherPrecipUnit::MM ? WeatherPrecipUnit::INCH : WeatherPrecipUnit::MM); + WEATHER_SETTINGS.saveToFile(); + requestUpdate(); + } +} + +void WeatherSettingsActivity::onSettingToggled(int index) { + if (menuItems[index].nameId == StrId::STR_USE_WEATHER) { + SETTINGS.saveToFile(); + } +} + +void WeatherSettingsActivity::onBackPressed() { + if (showingSearchResults) { + showingSearchResults = false; + requestUpdate(); + return; + } + finish(); +} + void WeatherSettingsActivity::launchCitySearch() { startActivityForResult(std::make_unique(renderer, mappedInput, tr(STR_WEATHER_SEARCH_CITY), "", 64, InputType::Text), @@ -122,7 +161,6 @@ void WeatherSettingsActivity::launchCitySearch() { const auto& kb = std::get(result.data); if (kb.text.empty()) return; - // Need WiFi for geocoding if (WiFi.status() != WL_CONNECTED || WiFi.localIP() == IPAddress(0, 0, 0, 0)) { startActivityForResult(std::make_unique(renderer, mappedInput), [this, query = kb.text](const ActivityResult& wifiResult) { @@ -181,28 +219,6 @@ void WeatherSettingsActivity::launchLongitudeEntry() { }); } -void WeatherSettingsActivity::toggleTempUnit() { - auto current = WEATHER_SETTINGS.getTempUnit(); - WEATHER_SETTINGS.setTempUnit(current == WeatherTempUnit::CELSIUS ? WeatherTempUnit::FAHRENHEIT - : WeatherTempUnit::CELSIUS); - WEATHER_SETTINGS.saveToFile(); - requestUpdate(); -} - -void WeatherSettingsActivity::toggleWindUnit() { - auto current = static_cast(WEATHER_SETTINGS.getWindUnit()); - WEATHER_SETTINGS.setWindUnit(static_cast((current + 1) % 4)); - WEATHER_SETTINGS.saveToFile(); - requestUpdate(); -} - -void WeatherSettingsActivity::togglePrecipUnit() { - auto current = WEATHER_SETTINGS.getPrecipUnit(); - WEATHER_SETTINGS.setPrecipUnit(current == WeatherPrecipUnit::MM ? WeatherPrecipUnit::INCH : WeatherPrecipUnit::MM); - WEATHER_SETTINGS.saveToFile(); - requestUpdate(); -} - void WeatherSettingsActivity::render(RenderLock&&) { renderer.clearScreen(); @@ -210,7 +226,6 @@ void WeatherSettingsActivity::render(RenderLock&&) { const Rect contentRect = UITheme::getContentRect(renderer, true, false); if (showingSearchResults) { - // Display search results GUI.drawHeader(renderer, Rect(contentRect.x, contentRect.y + metrics.topPadding, contentRect.width, metrics.headerHeight), tr(STR_WEATHER_SEARCH_RESULTS)); @@ -241,7 +256,6 @@ void WeatherSettingsActivity::render(RenderLock&&) { return; } - // Main settings menu GUI.drawHeader(renderer, Rect(contentRect.x, contentRect.y + metrics.topPadding, contentRect.width, metrics.headerHeight), tr(STR_WEATHER_SETTINGS)); @@ -250,46 +264,7 @@ void WeatherSettingsActivity::render(RenderLock&&) { const int contentHeight = contentRect.height - (metrics.topPadding + metrics.headerHeight + metrics.verticalSpacing * 2); - GUI.drawList( - renderer, Rect(contentRect.x, contentTop, contentRect.width, contentHeight), MENU_ITEMS, - static_cast(selectedIndex), [](int index) { return std::string(I18N.get(menuNames[index])); }, nullptr, - nullptr, - [this](int index) -> std::string { - switch (index) { - case 0: { - auto name = WEATHER_SETTINGS.getLocationName(); - return name.empty() ? std::string(tr(STR_NOT_SET)) : name; - } - case 1: { - char buf[16]; - snprintf(buf, sizeof(buf), "%.4f", WEATHER_SETTINGS.getLatitude()); - return std::string(buf); - } - case 2: { - char buf[16]; - snprintf(buf, sizeof(buf), "%.4f", WEATHER_SETTINGS.getLongitude()); - return std::string(buf); - } - case 3: - return WEATHER_SETTINGS.getTempUnit() == WeatherTempUnit::CELSIUS ? "C" : "F"; - case 4: - switch (WEATHER_SETTINGS.getWindUnit()) { - case WeatherWindUnit::KMH: - return "km/h"; - case WeatherWindUnit::MS: - return "m/s"; - case WeatherWindUnit::MPH: - return "mph"; - case WeatherWindUnit::KNOTS: - return "kn"; - } - return "km/h"; - case 5: - return WEATHER_SETTINGS.getPrecipUnit() == WeatherPrecipUnit::MM ? "mm" : "in"; - } - return ""; - }, - true); + drawMenuList(Rect{contentRect.x, contentTop, contentRect.width, contentHeight}); const auto labels = mappedInput.mapLabels(tr(STR_BACK), tr(STR_SELECT), tr(STR_DIR_UP), tr(STR_DIR_DOWN)); GUI.drawButtonHints(renderer, labels.btn1, labels.btn2, labels.btn3, labels.btn4); diff --git a/src/activities/weather/WeatherSettingsActivity.h b/src/activities/weather/WeatherSettingsActivity.h index b112c315..b83fd22e 100644 --- a/src/activities/weather/WeatherSettingsActivity.h +++ b/src/activities/weather/WeatherSettingsActivity.h @@ -5,42 +5,35 @@ #include #include -#include "../Activity.h" -#include "util/ButtonNavigator.h" +#include "../MenuListActivity.h" /** * Settings submenu for weather configuration. * Supports city search via geocoding, manual lat/lon entry, and unit selection. */ -class WeatherSettingsActivity final : public Activity { +class WeatherSettingsActivity final : public MenuListActivity { public: explicit WeatherSettingsActivity(GfxRenderer& renderer, MappedInputManager& mappedInput) - : Activity("WeatherSettings", renderer, mappedInput) {} + : MenuListActivity("WeatherSettings", renderer, mappedInput) { + buildMenuItems(); + } void onEnter() override; - void onExit() override; void loop() override; void render(RenderLock&&) override; private: - ButtonNavigator buttonNavigator; - int selectedIndex = 0; - - // City search results (populated when user searches) std::vector searchResults; bool showingSearchResults = false; - bool searchInProgress = false; std::string searchQuery; - static constexpr int MENU_ITEMS = 6; // Location, Lat, Lon, TempUnit, WindUnit, PrecipUnit + void buildMenuItems(); + void onActionSelected(int index) override; + std::string getItemValueString(int index) const override; + void onBackPressed() override; + void onSettingToggled(int index) override; - void handleSelection(); void launchCitySearch(); void launchLatitudeEntry(); void launchLongitudeEntry(); - void toggleTempUnit(); - void toggleWindUnit(); - void togglePrecipUnit(); - - bool preventAutoSleep() override { return true; } };