From b96f20140f64b71071f68d0deb71fab486691810 Mon Sep 17 00:00:00 2001 From: Strycher Date: Thu, 30 Jul 2026 00:48:44 -0400 Subject: [PATCH] chore(#457): remove em-dash characters from source Ben's style rule: no em-dash character in copy, docs, or code comments (it reads as an AI tell), and the repo is going public. Replaced the em-dashes in code comments and English UI strings with commas, colons, or periods, whichever reads best. User-facing strings were hand-tuned for natural punctuation rather than a blanket comma. Preserved the lone "no data" glyph placeholders (a standalone dash used as a not-available indicator in status displays); those are a design element, not prose. Regenerated app_localizations*.dart from app_en.arb (the English fallback for untranslated keys propagates to every locale's generated file). Non-English ARB translations left untouched. Co-Authored-By: Claude Opus 4.8 --- lib/connector/caplog_reassembler.dart | 4 +- lib/connector/meshcore_connector.dart | 88 +++++++++---------- lib/connector/meshcore_protocol.dart | 33 ++++--- lib/connector/observer_config_client.dart | 12 +-- lib/helpers/config_profile_diff.dart | 8 +- lib/helpers/config_profile_parser.dart | 2 +- lib/helpers/config_profile_writes.dart | 12 +-- lib/helpers/emoji_shortcodes.dart | 2 +- lib/helpers/gif_helper.dart | 2 +- lib/helpers/path_helper.dart | 2 +- lib/helpers/settings_persist.dart | 2 +- lib/l10n/app_en.arb | 20 ++--- lib/l10n/app_localizations.dart | 20 ++--- lib/l10n/app_localizations_bg.dart | 14 +-- lib/l10n/app_localizations_de.dart | 14 +-- lib/l10n/app_localizations_en.dart | 20 ++--- lib/l10n/app_localizations_es.dart | 14 +-- lib/l10n/app_localizations_fr.dart | 14 +-- lib/l10n/app_localizations_hu.dart | 14 +-- lib/l10n/app_localizations_it.dart | 14 +-- lib/l10n/app_localizations_ja.dart | 14 +-- lib/l10n/app_localizations_ko.dart | 14 +-- lib/l10n/app_localizations_nl.dart | 14 +-- lib/l10n/app_localizations_pl.dart | 14 +-- lib/l10n/app_localizations_pt.dart | 14 +-- lib/l10n/app_localizations_ru.dart | 14 +-- lib/l10n/app_localizations_sk.dart | 14 +-- lib/l10n/app_localizations_sl.dart | 14 +-- lib/l10n/app_localizations_sv.dart | 14 +-- lib/l10n/app_localizations_uk.dart | 14 +-- lib/l10n/app_localizations_zh.dart | 14 +-- lib/main.dart | 4 +- lib/models/app_settings.dart | 2 +- lib/models/channel_message.dart | 4 +- lib/models/config_catalog.dart | 6 +- lib/models/config_profile.dart | 10 +-- lib/models/contact.dart | 2 +- lib/models/message.dart | 6 +- lib/models/observer_config.dart | 30 +++---- lib/models/offband_gps_status.dart | 4 +- lib/screens/channel_chat_screen.dart | 4 +- lib/screens/chat_screen.dart | 2 +- lib/screens/companion_radio_stats_screen.dart | 2 +- lib/screens/contacts_screen.dart | 2 +- lib/screens/map_screen.dart | 10 +-- lib/screens/path_trace_map.dart | 6 +- lib/screens/repeater_settings_screen.dart | 4 +- lib/screens/serial_capture_screen.dart | 4 +- .../settings/broker_editor_screen.dart | 18 ++-- .../config_profile_preview_screen.dart | 6 +- lib/screens/settings/mqtt_brokers_screen.dart | 12 ++- .../settings/observer_settings_view.dart | 14 +-- lib/screens/settings/settings_shell.dart | 2 +- lib/screens/settings_screen.dart | 8 +- lib/screens/topology_debug_screen.dart | 8 +- lib/screens/usb_screen.dart | 2 +- lib/services/block_service.dart | 10 +-- lib/services/config_source_service.dart | 8 +- lib/services/linux_ble_pairing_service.dart | 2 +- lib/services/mesh_topology_service.dart | 16 ++-- lib/services/message_retry_service.dart | 12 +-- lib/services/observer_apply_service.dart | 4 +- lib/services/observer_config_service.dart | 26 +++--- lib/services/queue_sync_file_log_io.dart | 2 +- lib/services/storage_health_service.dart | 4 +- lib/services/timeout_prediction_service.dart | 2 +- lib/services/usb_serial_frame_codec.dart | 2 +- lib/services/usb_serial_service_native.dart | 16 ++-- lib/services/windows_taskbar_service.dart | 2 +- lib/storage/block_store.dart | 2 +- lib/storage/channel_message_store.dart | 6 +- lib/storage/client_id_store.dart | 2 +- lib/storage/drift/blob_store.dart | 2 +- lib/storage/drift/offband_database.dart | 2 +- lib/theme/mesh_theme.dart | 8 +- lib/utils/build_info.dart | 2 +- lib/utils/file_log_writer.dart | 2 +- lib/utils/macos_usb_device_names.dart | 2 +- lib/utils/usb_vid.dart | 4 +- lib/widgets/app_shell.dart | 8 +- lib/widgets/battery_optimization_banner.dart | 4 +- lib/widgets/blocked_badge.dart | 2 +- lib/widgets/gif_picker.dart | 2 +- lib/widgets/keep_screen_awake.dart | 2 +- lib/widgets/mention_autocomplete.dart | 4 +- lib/widgets/path_selection_dialog.dart | 2 +- lib/widgets/storage_unavailable_banner.dart | 2 +- lib/widgets/translated_message_content.dart | 2 +- test/models/broker_status_test.dart | 2 +- 89 files changed, 401 insertions(+), 404 deletions(-) diff --git a/lib/connector/caplog_reassembler.dart b/lib/connector/caplog_reassembler.dart index 6d9ed25..1bcb447 100644 --- a/lib/connector/caplog_reassembler.dart +++ b/lib/connector/caplog_reassembler.dart @@ -68,7 +68,7 @@ class CaplogBusyException implements Exception { const CaplogBusyException(); @override String toString() => - 'CaplogBusyException: device busy — another stream is in flight'; + 'CaplogBusyException: device busy, another stream is in flight'; } /// Thrown when the reassembled caplog byte count doesn't match the length the @@ -82,7 +82,7 @@ class CaplogTruncatedException implements Exception { final int received; final int expected; - /// Number of CHUNK frames the client accumulated before END — a diagnostic to + /// Number of CHUNK frames the client accumulated before END, a diagnostic to /// tell client/transport frame loss apart from the firmware streaming short. final int? chunks; diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index ab5abd4..472896d 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -81,7 +81,7 @@ class DirectRepeater { pubkeyPrefix.map((b) => b.toRadixString(16).padLeft(2, '0')).join(); /// True if [pathBytes] begins with this repeater's full configured-width - /// prefix — the width-aware replacement for a 1-byte first-hop match. (#156) + /// prefix, the width-aware replacement for a 1-byte first-hop match. (#156) bool matchesPathStart(List pathBytes) { if (pathBytes.length < pubkeyPrefix.length) return false; for (var i = 0; i < pubkeyPrefix.length; i++) { @@ -118,7 +118,7 @@ class DirectRepeater { const Duration(minutes: maxAgeMinutes); } - /// Records a directly-heard hop [prefix] at [snr] into [list] — the SNR-ranked + /// Records a directly-heard hop [prefix] at [snr] into [list], the SNR-ranked /// set of nearest direct repeaters, capped at [cap]. Updates an existing /// entry's SNR + timestamp, or adds a new one, evicting the weakest by SNR /// only when the newcomer is stronger. Returns true when the change is worth a @@ -442,7 +442,7 @@ class MeshCoreConnector extends ChangeNotifier { } final mtu = _device?.mtuNow ?? 0; // ATT_MTU 23 is the BLE minimum; a single write then carries 23 - 3 = 20 - // bytes. An unknown MTU must fall back to that floor, never [maxFrameSize] — + // bytes. An unknown MTU must fall back to that floor, never [maxFrameSize], // defaulting an unknown link to the largest size would authorize an // oversized write (#395 review). const minWritable = 20; @@ -610,7 +610,7 @@ class MeshCoreConnector extends ChangeNotifier { /// null on older firmware that sends a shorter frame. int? get offbandCaps => _offbandCaps; - /// Whether the connected firmware speaks the `0xC1` GPS extension — i.e. it + /// Whether the connected firmware speaks the `0xC1` GPS extension, i.e. it /// advertised the Offband-fork `offband_caps` byte. Stock MeshCore omits it, /// so 0xC1 is suppressed there rather than pinged blindly. (#144) bool get supportsOffbandGps => firmwareSupportsOffbandGps(_offbandCaps); @@ -626,7 +626,7 @@ class MeshCoreConnector extends ChangeNotifier { /// Whether this specific radio can control its external FEM LNA (#304). /// - /// Gated on the capability BIT alone — firmware derives it from a runtime FEM + /// Gated on the capability BIT alone, firmware derives it from a runtime FEM /// probe, so it is a per-unit answer: two Heltec V4s can legitimately disagree /// depending on the fitted chip, and `rak3401` reports false by design (its /// SKY66122 gates LNA and PA off one line, so a toggle would kill TX). @@ -654,7 +654,7 @@ class MeshCoreConnector extends ChangeNotifier { await sendFrame(buildOffbandFemLnaGetFrame()); } - /// `[0xC3][sub][value]` — the value is the post-apply hardware state, so it is + /// `[0xC3][sub][value]`, the value is the post-apply hardware state, so it is /// adopted verbatim rather than assuming a SET took effect (#304). void _handleOffbandFemLnaReply(Uint8List frame) { final reply = parseOffbandFemLnaReply(frame); @@ -1015,7 +1015,7 @@ class MeshCoreConnector extends ChangeNotifier { } void setChannelUnreadCount(int channelIndex, int count) { - // Don't persist channel state after disconnect — the store scope still + // Don't persist channel state after disconnect, the store scope still // points at the last radio, so a stale write can mis-scope (#23). if (!isConnected) return; final channel = _findChannelByIndex(channelIndex); @@ -1036,7 +1036,7 @@ class MeshCoreConnector extends ChangeNotifier { } void markChannelRead(int channelIndex) { - // Don't persist channel state after disconnect — the store scope still + // Don't persist channel state after disconnect, the store scope still // points at the last radio, so a stale write can mis-scope (#23). if (!isConnected) return; final channel = _findChannelByIndex(channelIndex); @@ -1345,7 +1345,7 @@ class MeshCoreConnector extends ChangeNotifier { int timestampSeconds, ) async { if (!isConnected || text.isEmpty) return; - // Automatic retries route here without passing sendMessage — stop them + // Automatic retries route here without passing sendMessage, stop them // too once the contact is blocked (#252). if (_blockService?.isBlocked(contact.publicKeyHex) ?? false) { appLogger.info( @@ -1673,8 +1673,8 @@ class MeshCoreConnector extends ChangeNotifier { await Future.delayed(const Duration(milliseconds: 300)); } - // Surface radios already connected to the OS — by us or by another app such - // as MeshCore — so we can attach to them. A connected BLE radio stops + // Surface radios already connected to the OS, by us or by another app such + // as MeshCore, so we can attach to them. A connected BLE radio stops // advertising, so a scan alone never finds it; systemDevices does. Supported // on every native platform (Android/iOS/macOS/Linux), not web. if (!PlatformInfo.isWeb) { @@ -2616,7 +2616,7 @@ class MeshCoreConnector extends ChangeNotifier { } /// Keep [BlockService]'s notion of "me" in sync with the connected node, so - /// it can refuse a self-block and self-heal one that already exists — the + /// it can refuse a self-block and self-heal one that already exists, the /// union pull can land before self-info arrives, so healing matters (#250). void _applySelfKeyToBlockService() { final service = _blockService; @@ -2897,7 +2897,7 @@ class MeshCoreConnector extends ChangeNotifier { /// Poll the radio's own GPS position every [_gpsLocationPollInterval] without /// resetting the session (the old `CMD_APP_START` poll re-inited the device - /// and broke contact/channel sync on gps=1 radios — #110/#140). Mechanism is + /// and broke contact/channel sync on gps=1 radios, #110/#140). Mechanism is /// firmware-aware: the Offband `0xC1` query where supported (#135, richer /// state), else standard MeshCore self-telemetry (`CMD_SEND_TELEMETRY_REQ` /// len==4 → `PUSH_CODE_TELEMETRY_RESPONSE`, decoded in [_handleSelfTelemetry]) @@ -2933,7 +2933,7 @@ class MeshCoreConnector extends ChangeNotifier { } /// Start or stop the GPS poll based on state: run whenever the radio reports - /// `gps=1` — the poll itself picks 0xC1 vs self-telemetry by firmware, so + /// `gps=1`, the poll itself picks 0xC1 vs self-telemetry by firmware, so /// stock-fw radios get the non-destructive self-telemetry refresh too (#123). /// Called from every input that can change `gps` or `offband_caps` (custom-var /// frames, the enable toggle, the device-info reply that delivers @@ -2948,7 +2948,7 @@ class MeshCoreConnector extends ChangeNotifier { /// Decode a self-telemetry reply /// (`[0x8B][reserved][self-pubkey 6][CayenneLPP]`) and update the radio's own - /// position from its GPS — the non-destructive replacement for the APP_START + /// position from its GPS, the non-destructive replacement for the APP_START /// GPS poll (#110). Contact telemetry (a different pubkey) is ignored here; /// the telemetry screen handles those. void _handleSelfTelemetry(List frame) { @@ -2956,7 +2956,7 @@ class MeshCoreConnector extends ChangeNotifier { if (selfKey == null || selfKey.length < 6) return; if (frame.length < 8) return; // code + reserved + 6-byte pubkey prefix if (!listEquals(frame.sublist(2, 8), selfKey.sublist(0, 6))) { - return; // not the self node — a contact telemetry reply + return; // not the self node, a contact telemetry reply } // Guard the parse: a malformed CayenneLPP payload from an external radio // must not throw out of the RX dispatch and stall the receive loop. (#123) @@ -3100,7 +3100,7 @@ class MeshCoreConnector extends ChangeNotifier { /// and awaiting SELF_INFO, and never while an initial sync is in flight (the /// Web-path guard, so the retry doesn't contend with the contact/channel /// sync). The timer keeps rescheduling, so the skip is per-tick, not - /// permanent — once a sync settles, the next tick sends. (#88) + /// permanent, once a sync settles, the next tick sends. (#88) static bool shouldSendAppStartRetry({ required bool connected, required bool awaitingSelfInfo, @@ -3135,7 +3135,7 @@ class MeshCoreConnector extends ChangeNotifier { } // BLE/USB: bounded backoff -> slow keep-alive (was an unbounded 3.5s // hammer). A slow handshake no longer churns the connect or contends with - // the initial sync, but the retry never hard-stops — a slow/recovering + // the initial sync, but the retry never hard-stops, a slow/recovering // device still gets prompted (#88). _appStartRetryAttempt = 0; _armAppStartRetry(); @@ -3216,7 +3216,7 @@ class MeshCoreConnector extends ChangeNotifier { }) async { if (!isConnected || text.isEmpty) return; // Outgoing DMs (incl. reactions and retries) to a blocked contact are - // dropped — mirrors the incoming DM-drop so a block is symmetric (#252). + // dropped, mirrors the incoming DM-drop so a block is symmetric (#252). if (_blockService?.isBlocked(contact.publicKeyHex) ?? false) { appLogger.info( 'Dropped outgoing DM to blocked contact', @@ -3242,7 +3242,7 @@ class MeshCoreConnector extends ChangeNotifier { notifyListeners(); // Route through retry service (same as normal messages) - // Don't use auto-rotation for reactions — just send directly + // Don't use auto-rotation for reactions, just send directly if (_retryService != null) { await _retryService!.sendMessageWithRetry(contact: contact, text: text); } else { @@ -3785,7 +3785,7 @@ class MeshCoreConnector extends ChangeNotifier { ); if (existingIndex >= 0) { final existing = _contacts[existingIndex]; - // Preserve pathOverride and pathOverrideBytes — only reset device path + // Preserve pathOverride and pathOverrideBytes, only reset device path _contacts[existingIndex] = existing.copyWith( pathLength: -1, path: Uint8List(0), @@ -4181,7 +4181,7 @@ class MeshCoreConnector extends ChangeNotifier { // than the one whose history is stored here, clear the stale history so a // previous occupant's messages (e.g. #echo) don't surface under the newly // added channel. Preserve only when the slot already holds the SAME channel - // (same PSK) — e.g. a rename. (#193) + // (same PSK), e.g. a rename. (#193) final existing = _findChannelByIndex(index); final sameChannel = existing != null && listEquals(existing.psk, psk); @@ -4227,7 +4227,7 @@ class MeshCoreConnector extends ChangeNotifier { if (!supportsOffbandGps) return null; final existing = _offbandGpsCompleter; if (existing != null && !existing.isCompleted) { - // A query is already in flight — share it rather than orphaning it. + // A query is already in flight, share it rather than orphaning it. return existing.future.timeout(timeout, onTimeout: () => null); } final completer = Completer(); @@ -4253,7 +4253,7 @@ class MeshCoreConnector extends ChangeNotifier { final completer = _offbandGpsCompleter; _offbandGpsCompleter = null; _latestOffbandGpsStatus = status; - // A live fix is the device's real position — keep self-lat/lon (and the + // A live fix is the device's real position, keep self-lat/lon (and the // map) fresh from it, replacing what the old APP_START GPS poll did. (#140) if (status.hasLiveFix) { _selfLatitude = status.latitude; @@ -4483,10 +4483,10 @@ class MeshCoreConnector extends ChangeNotifier { }); return; } - // Complete dump — UNION. Exclude any key the user block/unblocked WHILE the + // Complete dump, UNION. Exclude any key the user block/unblocked WHILE the // dump was in flight: _pushBlockChange already sent the right ADD/REMOVE and // the local state is authoritative, so the stale dump must NOT override it - // (prevents re-importing an unblock — data loss — and redundant re-pushes). + // (prevents re-importing an unblock, data loss, and redundant re-pushes). final blockService = _blockService; if (blockService == null) { _blockDumpInFlight = false; @@ -4811,7 +4811,7 @@ class MeshCoreConnector extends ChangeNotifier { // generic RESP_CODE_ERR when another stream (block-list / contacts / // observer config) is already in flight. Fail the download fast with a // typed error instead of waiting out the timeout. Falling through to the - // normal handling below is harmless — it no-ops unless a channel sync is + // normal handling below is harmless, it no-ops unless a channel sync is // active. (#430) if (_caplogAwaitingStart) { _caplogAwaitingStart = false; @@ -4838,7 +4838,7 @@ class MeshCoreConnector extends ChangeNotifier { tag: 'Protocol', ); - // An in-flight channel GET that draws an ERR means that slot is empty — + // An in-flight channel GET that draws an ERR means that slot is empty, // advance to the next index the instant the ERR lands instead of waiting // out the timeout + retry budget (mirrors the CHANNEL_INFO success path // minus adding a channel). This is the whole sync-slowness fix (#82). @@ -4943,7 +4943,7 @@ class MeshCoreConnector extends ChangeNotifier { } // GPS poll responses arrive as RESP_CODE_SELF_INFO but are not the real - // handshake — only update location and notify, skip store reloads and + // handshake, only update location and notify, skip store reloads and // contact sync which would clear and re-fetch contacts every minute. if (!wasAwaitingSelfInfo) { notifyListeners(); @@ -5001,7 +5001,7 @@ class MeshCoreConnector extends ChangeNotifier { /// Extract the additive `offband_caps` byte from a device-info reply. /// /// Offset verified against firmware MyMesh.cpp: the reply tail is three - /// consecutive `out_frame[i++]` writes — client_repeat (byte 80, v9+), + /// consecutive `out_frame[i++]` writes, client_repeat (byte 80, v9+), /// path_hash_mode (byte 81, v10+), offband_caps (byte 82, v14+). Bytes 80/81 /// are shipping/working (path-hash feature), so byte 82 is the adjacent next /// byte by construction. Pre-v14 firmware sends a shorter frame -> null. @@ -5010,8 +5010,8 @@ class MeshCoreConnector extends ChangeNotifier { frame.length >= 83 ? frame[82] : null; /// FEM LNA state byte, appended immediately after the caps byte in device-info - /// v16+ (firmware #298). Appended **unconditionally** — including on - /// non-capable boards, where it reads 0 — so the byte's presence indicates + /// v16+ (firmware #298). Appended **unconditionally**, including on + /// non-capable boards, where it reads 0, so the byte's presence indicates /// firmware version, not capability. The capability BIT is what decides /// whether to render the control. Null on v15 and older (shorter frame). static bool? parseFemLnaState(Uint8List frame) => @@ -5024,7 +5024,7 @@ class MeshCoreConnector extends ChangeNotifier { } _firmwareVerCode = frame[1]; - // Readable build date / model / firmware version — NUL-terminated strings + // Readable build date / model / firmware version, NUL-terminated strings // after the 8-byte header, before the binary config block. (#134) final infoStrings = parseDeviceInfoStrings(frame); final info = deviceInfoFields(infoStrings); @@ -5065,7 +5065,7 @@ class MeshCoreConnector extends ChangeNotifier { // testable helper; offset verified against firmware (see parseOffbandCaps). _offbandCaps = parseOffbandCaps(frame); // FEM LNA state rides one byte past the caps byte on v16+ (#304). Primary - // read on connect — a 0xC3 GET is only the fallback. + // read on connect, a 0xC3 GET is only the fallback. _femLnaEnabled = parseFemLnaState(frame); // Capability-gated features are invisible when a bit is clear, which looks // identical to a bug. Log the raw inputs so "the toggle didn't appear" can @@ -5080,7 +5080,7 @@ class MeshCoreConnector extends ChangeNotifier { // Caps just landed; (re)evaluate GPS polling in case a `gps=1` custom-var // frame arrived before this device-info reply set support. (#144) _reconcileGpsPolling(); - // Caps landed — if the radio speaks block, pull its list and union-reconcile. + // Caps landed, if the radio speaks block, pull its list and union-reconcile. _reconcileFirmwareBlock(); // Firmware reports MAX_CONTACTS / 2 for v3+ device info. @@ -5297,7 +5297,7 @@ class MeshCoreConnector extends ChangeNotifier { int _physicsMinTimeout(int pathLength, int airtime) { if (pathLength < 0) { - // Same as max for flood — firmware uses a single formula + // Same as max for flood, firmware uses a single formula return 500 + (16 * airtime); } else { return airtime * (pathLength + 1); @@ -5333,7 +5333,7 @@ class MeshCoreConnector extends ChangeNotifier { return mlTimeout.clamp(physicsMin, physicsMax); } - // No ML data — use firmware formula + // No ML data, use firmware formula return physicsMax; } @@ -5697,7 +5697,7 @@ class MeshCoreConnector extends ChangeNotifier { 'claimed=${claimed.toIso8601String()} ' 'delta=${formatRxTimeDelta(arrival, claimed)} path=$path'; // Direct service call (not appLogger): the file trail must not depend on - // the in-app debug-log toggle — the service always writes to disk and the + // the in-app debug-log toggle, the service always writes to disk and the // toggle only gates the in-app ring buffer. if (isRxTimeAnomaly(arrival, claimed)) { _appDebugLogService?.warn('$line ** TIME ANOMALY **', tag: 'Ingest'); @@ -5759,7 +5759,7 @@ class MeshCoreConnector extends ChangeNotifier { return; } - // Blocked sender: drop the DM entirely — no thread entry, no unread, no + // Blocked sender: drop the DM entirely, no thread entry, no unread, no // notification, no lastMessage bump. Adverts still flow for name self-heal. if (!message.isOutgoing && (_blockService?.isBlocked(message.senderKeyHex) ?? false)) { @@ -5887,7 +5887,7 @@ class MeshCoreConnector extends ChangeNotifier { // snr: (int8)(snr_dB * 4), so dB = byte / 4.0 (MyMesh.cpp:512). // res1 bit0 = device-composed outgoing flag (#429). // res2 = RX RSSI as clamped int8 dBm, or 0 when unset (older firmware or - // no-RX text) — gate on != 0 (MyMesh.cpp:550-551, #465). RSSI is always + // no-RX text). Gate on != 0 (MyMesh.cpp:550-551, #465). RSSI is always // negative for a real RX, so 0 unambiguously means "no data". double? snr; bool isOutgoing = false; @@ -5970,7 +5970,7 @@ class MeshCoreConnector extends ChangeNotifier { pathBytes: Uint8List(0), fourByteRoomContactKey: roomAuthorPrefix, // A device-composed outgoing message has no real RX frame, so its SNR / - // path-type / rxTime are meaningless — null them like rxTime (#429/#438). + // path-type / rxTime are meaningless, null them like rxTime (#429/#438). rxTime: isOutgoing ? null : DateTime.now(), snr: isOutgoing ? null : snr, rssi: isOutgoing ? null : rssi, @@ -6677,7 +6677,7 @@ class MeshCoreConnector extends ChangeNotifier { } Future setChannelOrder(List order) async { - // Don't persist channel state after disconnect — the store scope still + // Don't persist channel state after disconnect, the store scope still // points at the last radio, so a stale write can mis-scope (#23). if (!isConnected) return; _channelOrder = List.from(order); @@ -7443,7 +7443,7 @@ class MeshCoreConnector extends ChangeNotifier { /// reported clock. Frame layout (firmware companion_radio/MyMesh.cpp:678+): /// [0]=0x85, [1]=permissions, [2..7]=pubkey prefix (6 bytes), /// [8..11]=repeater RTC unix seconds (LE), [12]=ACL perms, [13]=fw level - /// The timestamp is only present in the v7+ "new login response" — older + /// The timestamp is only present in the v7+ "new login response", older /// firmware emits a shorter frame that we silently skip. void _handleLoginSuccess(Uint8List frame) { if (frame.length < 12) return; @@ -7554,7 +7554,7 @@ class MeshCoreConnector extends ChangeNotifier { final pathBytes = packet.readBytes(pathByteLen); final payload = packet.readBytes(packet.remaining); - // #186: feed the passive topology map from every routed packet's path — + // #186: feed the passive topology map from every routed packet's path, // the same firehose that feeds nearest-repeater detection. Cheap: the // path is already parsed here. Guarded so a topology-side fault can never // stall the RX dispatch that also drives message handling. diff --git a/lib/connector/meshcore_protocol.dart b/lib/connector/meshcore_protocol.dart index e2e5ff7..09d5901 100644 --- a/lib/connector/meshcore_protocol.dart +++ b/lib/connector/meshcore_protocol.dart @@ -256,15 +256,15 @@ const int respCodeCustomVars = 21; const int respCodeAutoAddConfig = 25; const int respCodeStats = 24; -/// Offband fork-only extension space (0xC0+) — never collides with upstream, +/// Offband fork-only extension space (0xC0+), never collides with upstream, /// never submitted upstream. Request and reply share the code. (#135) const int cmdOffbandGps = 0xC1; const int respCodeOffbandGps = 0xC1; -/// Request frame for [cmdOffbandGps] — a bare 1-byte command, no payload. (#135) +/// Request frame for [cmdOffbandGps], a bare 1-byte command, no payload. (#135) Uint8List buildOffbandGpsRequestFrame() => Uint8List.fromList([cmdOffbandGps]); -// --- Offband FEM LNA command (0xC3) — capability-gated. Heltec V4 external +// --- Offband FEM LNA command (0xC3), capability-gated. Heltec V4 external // FEM LNA control; firmware counterpart OffbandMesh/meshcore-firmware#298. // // Deliberately a fork-private command rather than an extra byte on the stock @@ -312,11 +312,11 @@ OffbandFemLnaReply? parseOffbandFemLnaReply(Uint8List frame) { return OffbandFemLnaReply(frame[1], frame[2]); } -// --- Offband caplog serial-capture download (0xC4) — companion-API only; NEVER +// --- Offband caplog serial-capture download (0xC4), companion-API only; NEVER // on the mesh. Firmware counterpart OffbandMesh/meshcore-firmware#406. // // 0xC4, NOT 0xC3: the firmware first merged this on 0xC3, which collides with -// cmdOffbandFemLna (0xC3, #298) — the caplog handler swallowed every 0xC3 frame +// cmdOffbandFemLna (0xC3, #298), the caplog handler swallowed every 0xC3 frame // before FEM/LNA dispatch. Reassigned to 0xC4, the next free code in the 0xC0+ // space (0xC0 config, 0xC1 GPS, 0xC2 block, 0xC3 FEM LNA). // @@ -334,8 +334,7 @@ const int caplogSubEnd = 0x03; // Caplog request sub-codes in cmd_frame[1]. A bare [0xC4] (len 1) is DOWNLOAD // for back-compat. Firmware #417/#408. (#430) const int caplogReqDownload = 0x01; -const int caplogReqEnable = - 0x02; // [0xC4,0x02,(level)] — omit level for default +const int caplogReqEnable = 0x02; // [0xC4,0x02,(level)], omit level for default const int caplogReqDisable = 0x03; const int caplogReqErase = 0x04; const int caplogReqStatus = 0x05; @@ -346,7 +345,7 @@ const int caplogRespAck = 0x10; // [0xC4,0x10, req_op, ok(0|1)] const int caplogRespStatus = 0x11; // [0xC4,0x11, enabled, level, used(4B LE), cap(4B LE)] -/// Request frame to download the device's serial-capture buffer — a bare 1-byte +/// Request frame to download the device's serial-capture buffer, a bare 1-byte /// command, no payload (firmware treats bare [0xC4] as DOWNLOAD). (#430) Uint8List buildOffbandCaplogRequestFrame() => Uint8List.fromList([cmdOffbandCaplog]); @@ -414,7 +413,7 @@ CaplogDeviceStatus? parseCaplogStatus(Uint8List frame) { ); } -// --- Offband block command (0xC2) — capability-gated; see +// --- Offband block command (0xC2), capability-gated; see // docs/architecture/block-contract-as-built.md §8. Firmware as-built PR #247. --- const int cmdOffbandBlock = 0xC2; const int offbandBlockAdd = 0x01; @@ -423,11 +422,11 @@ const int offbandBlockList = 0x03; const int offbandBlockClear = 0x04; /// Result of a malformed 0xC2 request: firmware replies with the GENERIC error -/// frame `[respCodeErr(1)][errCodeIllegalArg(6)]` — NOT 0xC2-prefixed, so the +/// frame `[respCodeErr(1)][errCodeIllegalArg(6)]`, NOT 0xC2-prefixed, so the /// app must recognise the 2-byte error frame and not wait for a 0xC2 echo. const int errCodeIllegalArg = 6; -/// `ERR_CODE_UNSUPPORTED_CMD` — returned for an Offband command the connected +/// `ERR_CODE_UNSUPPORTED_CMD`, returned for an Offband command the connected /// board can't service (e.g. a `0xC3` FEM LNA request to a board without FEM /// control). Unreachable when the capability bit is respected; firmware answers /// it defensively against a stale or mis-gated client. (#304) @@ -461,7 +460,7 @@ OffbandBlockReply? parseOffbandBlockReply(Uint8List frame) { /// True iff the connected firmware understands the `0xC1` GPS extension. Gated /// on the `offband_caps` byte being present: that byte is an Offband-fork /// addition (device-info v14+) which stock/upstream MeshCore never emits, so a -/// null caps value means non-Offband firmware that couldn't answer `0xC1` — and +/// null caps value means non-Offband firmware that couldn't answer `0xC1`, and /// must not be pinged with it. (#144) /// /// Interim presence-gate: a dedicated `OFFBAND_CAP_GPS` bit (firmware @@ -479,12 +478,12 @@ const int offbandCapBlock = 0x02; /// `OFFBAND_CAP_FEM_LNA` bit (bit 2) in the `offband_caps` byte: this radio can /// control its external FEM LNA (firmware #298). /// -/// PROVISIONAL — firmware owns the caps byte and has not yet confirmed 0x04 as +/// PROVISIONAL, firmware owns the caps byte and has not yet confirmed 0x04 as /// free. Do not ship against this without that confirmation (#304). /// /// Gate on the BIT ONLY, never on model or version: firmware derives it at /// runtime from the auto-detected FEM chip (KCT8103L vs GC1109), so it is a -/// per-unit answer — two Heltec V4s can legitimately disagree, and other +/// per-unit answer, two Heltec V4s can legitimately disagree, and other /// FEM-bearing boards report false today. const int offbandCapFemLna = 0x04; @@ -497,7 +496,7 @@ bool firmwareSupportsOffbandBlock(int? offbandCaps, int? firmwareVerCode) => (firmwareVerCode ?? 0) >= 15; /// Caplog serial-capture capability (firmware #427). The bit is compile-time -/// static in device-info, so it's reliable across reboots — the client re-reads +/// static in device-info, so it's reliable across reboots, the client re-reads /// it on reconnect and never has to race a STATUS probe. Bit 5 (0x08/0x10 are /// reserved for WiFi-companion #365 / display-config); requires FIRMWARE_VER_CODE /// >= 17, the version that introduced it. @@ -711,7 +710,7 @@ int readInt32LE(Uint8List data, int offset) { } // Path-length byte from the firmware. This is a PACKED field, and both halves -// are authoritative — the path is self-describing on the wire: +// are authoritative, the path is self-describing on the wire: // // high 2 bits = hash size - 1 (0..2 -> 1..3 bytes per hop hash) // low 6 bits = hash COUNT (the number of HOPS, 0-63) @@ -1066,7 +1065,7 @@ Uint8List buildResetPathFrame(Uint8List pubKey) { // [hopCount] is a HOP count and [hashWidth] the bytes per hop hash; the two are // packed into the single wire path_len byte via encodePathLen(). // -// This previously wrote the count raw, leaving the mode bits 00 — which tells +// This previously wrote the count raw, leaving the mode bits 00, which tells // the radio "1-byte hashes". On a 2-byte net that handed the firmware 2-byte // hash data labelled as 1-byte hops, so it routed to nodes that were never on // the route. That is the send-side half of #240's misrouting. (#309) diff --git a/lib/connector/observer_config_client.dart b/lib/connector/observer_config_client.dart index 8934946..39a460d 100644 --- a/lib/connector/observer_config_client.dart +++ b/lib/connector/observer_config_client.dart @@ -3,7 +3,7 @@ // Mirrors the firmware contract in the firmware repo's // `examples/companion_radio/OffbandConfigProtocol.h` + `MyMesh::handleOffbandConfigCmd` // (Epic F #160-#163) byte-for-byte. This is a PURE codec: it builds request -// frames and parses response frames. It never touches BLE/USB/TCP — the +// frames and parses response frames. It never touches BLE/USB/TCP, the // connector sends the Uint8Lists and feeds received frames back to [parse]. // // Frame layout (both directions): byte[0] = code (0xC0), byte[1] = sub-type, @@ -97,13 +97,13 @@ class ObserverConfigClient { /// Bit 0 of the `offband_caps` byte appended to the device-info reply. static const int capWifiObserver = 0x01; - // Request sub-type — byte[1]. + // Request sub-type, byte[1]. static const int opSet = 0x00; static const int opGet = 0x01; static const int opView = 0x02; static const int opBrokers = 0x03; - // Response sub-type — byte[1]. + // Response sub-type, byte[1]. static const int rAck = 0x00; static const int rErr = 0x01; static const int rValue = 0x02; @@ -141,7 +141,7 @@ class ObserverConfigClient { return builder.toBytes(); } - /// SET ` ` — firmware splits on the FIRST space; [value] is the + /// SET ` `, firmware splits on the FIRST space; [value] is the /// verbatim remainder and may contain spaces. static Uint8List buildSet(String key, String value) => _frame(opSet, '$key $value'); @@ -166,7 +166,7 @@ class ObserverConfigClient { /// NOTE: `enabled` is intentionally NOT here. The firmware /// `handleSetBrokerField` has no `enabled` branch and the VIEW allowlist /// blocks `mqtt enable/disable/clear`, so activation + clear have no wire - /// path in this firmware (TODO: firmware F-task — see observer_config docs). + /// path in this firmware (TODO: firmware F-task, see observer_config docs). /// The activation guard still holds: any field SET on a live slot /// auto-disables it firmware-side. static List> brokerFieldSets( @@ -264,7 +264,7 @@ class ObserverConfigClient { /// [BrokerConfig]s. Feed each parsed [ConfigResponse]; [add] returns the /// decoded list once END arrives (or `[]` for an empty pool), else null. class BrokerListDecoder { - /// Hard cap on total key/value lines retained across the whole dump — a + /// Hard cap on total key/value lines retained across the whole dump, a /// hostile device cannot grow memory without bound (Gemini BLOCKER: DoS). /// Generous for the 10-slot contract (~16 fields each). static const int _maxFields = ObserverConfigClient.brokerSlotCount * 32; diff --git a/lib/helpers/config_profile_diff.dart b/lib/helpers/config_profile_diff.dart index d5229a7..8df667e 100644 --- a/lib/helpers/config_profile_diff.dart +++ b/lib/helpers/config_profile_diff.dart @@ -4,7 +4,7 @@ import 'config_profile_writes.dart'; /// Builds the human-facing diff for a profile apply (#406): current → new, per /// field, categorized so the preview can render its two-tier confirm. /// -/// Pure — the screen fetches current device values and passes them in, so this +/// Pure, the screen fetches current device values and passes them in, so this /// is unit-testable without a device. enum DiffKind { @@ -25,7 +25,7 @@ class DiffRow { required this.secret, }); - /// Firmware key (flat) or `broker N.` — never a value, safe to show. + /// Firmware key (flat) or `broker N.`, never a value, safe to show. final String label; /// Current on-device value, or null if unknown/unreadable (e.g. write-only @@ -34,10 +34,10 @@ class DiffRow { final String newValue; final DiffKind kind; - /// In the credential/identity danger set — routed to the red gate. + /// In the credential/identity danger set, routed to the red gate. final bool danger; - /// A true secret (password / wifi.pwd) — the UI must mask both values. + /// A true secret (password / wifi.pwd), the UI must mask both values. final bool secret; } diff --git a/lib/helpers/config_profile_parser.dart b/lib/helpers/config_profile_parser.dart index f8b27aa..a84b93f 100644 --- a/lib/helpers/config_profile_parser.dart +++ b/lib/helpers/config_profile_parser.dart @@ -15,7 +15,7 @@ class ConfigProfileFormatException implements Exception { /// Parse a YAML config profile into a [ConfigProfile] (#402 model). /// -/// Strict by design — profiles are untrusted input (#139 trust note), so an +/// Strict by design, profiles are untrusted input (#139 trust note), so an /// unknown key, a wrong type, or an out-of-range value is an error, not a silent /// skip. Only keys present in the document appear in the model; everything else /// stays null so the apply engines touch only what the profile sets. diff --git a/lib/helpers/config_profile_writes.dart b/lib/helpers/config_profile_writes.dart index ab23d83..67a66ee 100644 --- a/lib/helpers/config_profile_writes.dart +++ b/lib/helpers/config_profile_writes.dart @@ -3,10 +3,10 @@ import '../models/config_profile.dart'; /// Enumerates the device writes a [ConfigProfile] implies (#405), device-agnostic /// so observer / repeater / companion executors share the same rules: /// -/// - **Skip null or empty** — a profile only touches keys it actually sets; a +/// - **Skip null or empty**, a profile only touches keys it actually sets; a /// blank never clobbers a configured value. Clearing is a separate explicit op. -/// - **Skip `jwt_token`** — it's live-minted by firmware at connect, never config. -/// - **`enabled` is written last** (the executor's activation guard) — so it is +/// - **Skip `jwt_token`**, it's live-minted by firmware at connect, never config. +/// - **`enabled` is written last** (the executor's activation guard), so it is /// returned separately from [BrokerWrites.fields]. /// - **Danger fields** (owner/identity/credentials) are flagged so the preview /// (#406) can gate them: broker `username`/`password`/`jwt_owner`/`jwt_email`, @@ -65,7 +65,7 @@ class ProfileWrites { /// Partition writes into (safe, danger) so the preview's two buttons each apply /// their own set: the normal Apply writes safe changes; the red gate writes the -/// credential/identity ones. A broker with both is split across both — its +/// credential/identity ones. A broker with both is split across both, its /// `enabled` toggle rides with the safe half only. ({ProfileWrites safe, ProfileWrites danger}) splitProfileWrites( ProfileWrites w, @@ -117,7 +117,7 @@ bool _blank(String? v) => v == null || v.isEmpty; ProfileWrites enumerateProfileWrites(ConfigProfile p) { final flats = []; - // WiFi — ssid/pwd first, enabled last (activation guard). + // WiFi, ssid/pwd first, enabled last (activation guard). final wifi = p.wifi; if (wifi != null) { if (!_blank(wifi.ssid)) { @@ -157,7 +157,7 @@ ProfileWrites enumerateProfileWrites(ConfigProfile p) { } put(ConfigKeys.brokerUsername, b.username); put(ConfigKeys.brokerPassword, b.password); - // jwt_token deliberately omitted — live-minted at connect, never config. + // jwt_token deliberately omitted, live-minted at connect, never config. put(ConfigKeys.brokerJwtAudience, b.jwtAudience); if (b.jwtRefresh != null) { fields[ConfigKeys.brokerJwtRefresh] = '${b.jwtRefresh}'; diff --git a/lib/helpers/emoji_shortcodes.dart b/lib/helpers/emoji_shortcodes.dart index ec399b9..52c83e9 100644 --- a/lib/helpers/emoji_shortcodes.dart +++ b/lib/helpers/emoji_shortcodes.dart @@ -1925,7 +1925,7 @@ const Map _emojiAliases = { 'tick': '✅', }; -/// gemoji shortcodes plus [_emojiAliases] — what composers use. +/// gemoji shortcodes plus [_emojiAliases], what composers use. final Map emojiShortcodesWithAliases = { ...emojiShortcodes, ..._emojiAliases, diff --git a/lib/helpers/gif_helper.dart b/lib/helpers/gif_helper.dart index 5cbf244..8d2f65f 100644 --- a/lib/helpers/gif_helper.dart +++ b/lib/helpers/gif_helper.dart @@ -12,7 +12,7 @@ class GifHelper { static String? parseGif(String text) { // A reply prepends a leading `@[Name] ` mention; ignore it so a reply-gif // still resolves to the gif rather than plain text. Only a reply mention is - // stripped — arbitrary text before a gif is left as text. (#232) + // stripped, arbitrary text before a gif is left as text. (#232) final trimmed = text.trim().replaceFirst(RegExp(r'^@\[[^\]]+\]\s+'), ''); final match = RegExp(r'^g:([A-Za-z0-9_-]+)$').firstMatch(trimmed); if (match != null) { diff --git a/lib/helpers/path_helper.dart b/lib/helpers/path_helper.dart index c4a2337..5455b06 100644 --- a/lib/helpers/path_helper.dart +++ b/lib/helpers/path_helper.dart @@ -58,7 +58,7 @@ class PathHelper { } /// Trace `path_sz` flag for a configured hash width: floor(log2(width)), so - /// width 1→0, 2→1, 3→1, 4→2. The wire hop size is `1 << path_sz` bytes — the + /// width 1→0, 2→1, 3→1, 4→2. The wire hop size is `1 << path_sz` bytes, the /// firmware's trace widths are powers of two, so this is the largest power of /// two ≤ the configured width (width 3 sends the leading 2 bytes per hop). (#150) static int tracePathSz(int hashWidth) { diff --git a/lib/helpers/settings_persist.dart b/lib/helpers/settings_persist.dart index 7c0da55..05fc7fb 100644 --- a/lib/helpers/settings_persist.dart +++ b/lib/helpers/settings_persist.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; /// Runs a settings-persist [action] and surfaces a dismissible error SnackBar if /// it throws, instead of dropping the returned Future and swallowing the error -/// (no silent failures — #28). +/// (no silent failures, #28). /// /// Call sites intentionally don't await the returned Future: this function never /// rethrows (it catches internally), so dropping it is safe. The diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 811ce0b..97c4383 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -170,13 +170,13 @@ "settings_gpsStatusTitle": "GPS status", "settings_gpsStatusRefresh": "Query GPS", "settings_gpsStatusLiveFix": "Live GPS fix", - "settings_gpsStatusNoFix": "No fix — using stored/last position", + "settings_gpsStatusNoFix": "No fix: using stored/last position", "settings_gpsStatusCoords": "Coordinates", "settings_gpsStatusSats": "Satellites", "settings_gpsStatusAltitude": "Altitude", "settings_gpsStatusTime": "Fix time", "settings_gpsStatusTapRefresh": "Tap Query GPS to read the current GPS state", - "settings_gpsStatusNoResponse": "No response — device may need the GPS-query firmware build", + "settings_gpsStatusNoResponse": "No response: device may need the GPS-query firmware build", "settings_locationIntervalInvalid": "Interval must be at least 60 seconds, and less than 86400 seconds.", "settings_latitude": "Latitude", "settings_longitude": "Longitude", @@ -1427,13 +1427,13 @@ "repeater_advancedSettings": "Advanced", "repeater_advancedSettingsSubtitle": "Tuning knobs for experienced operators", "repeater_pathHashMode": "Path hash mode", - "repeater_pathHashModeHelper": "Bytes used to encode this repeater's ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.", + "repeater_pathHashModeHelper": "Bytes used to encode this repeater's ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths. Only raise once your network is on v1.14+.", "repeater_txDelay": "Flood TX delay", "repeater_txDelayHelper": "Retransmit spacing for flood traffic, as a multiplier of the packet's airtime (0-2, default 0.5). Higher = fewer collisions but slower delivery.", "repeater_directTxDelay": "Direct TX delay", "repeater_directTxDelayHelper": "Retransmit spacing for direct (non-flood) traffic, as a multiplier of the packet's airtime (0-2, default 0.3).", "repeater_intThresh": "Interference threshold", - "repeater_intThreshHelper": "Threshold passed to the radio's noise-floor calibration so it rejects interference above this level. 0 disables — only raise if you see RX errors in a noisy band.", + "repeater_intThreshHelper": "Threshold passed to the radio's noise-floor calibration so it rejects interference above this level. 0 disables. Only raise if you see RX errors in a noisy band.", "repeater_agcResetInterval": "AGC reset interval", "repeater_agcResetIntervalHelper": "How often to reset the radio's automatic gain control to recover from a stuck gain state. Seconds, snapped down to a multiple of 4. 0 disables periodic resets.", "repeater_actionsTitle": "Actions", @@ -1462,7 +1462,7 @@ } } }, - "repeater_settingsSavedRebootNeeded": "Settings saved — reboot the repeater to apply", + "repeater_settingsSavedRebootNeeded": "Settings saved. Reboot the repeater to apply", "repeater_settingsPartialFailure": "Some settings failed: {failures}", "@repeater_settingsPartialFailure": { "placeholders": { @@ -2450,7 +2450,7 @@ "settings_gpxExportShareText": "Map data exported from meshcore-open", "settings_gpxExportShareSubject": "meshcore-open GPX map data export", "snrIndicator_nearByRepeaters": "Nearby Repeaters", - "snrIndicator_noNeighbors": "No neighbors heard currently — messages still broadcast and route.", + "snrIndicator_noNeighbors": "No neighbors heard currently. Messages still broadcast and route.", "snrIndicator_lastSeen": "Last seen", "contactsSettings_title": "Contacts settings", "contactsSettings_autoAddTitle": "Automatic Discovery", @@ -2643,7 +2643,7 @@ } } }, - "block_blockedNameOnly": "Blocked \"{name}\" across all channels — name only until we learn their key", + "block_blockedNameOnly": "Blocked \"{name}\" across all channels. Name only until we learn their key", "@block_blockedNameOnly": { "placeholders": { "name": { @@ -2656,9 +2656,9 @@ "block_none": "No blocked users", "block_keysSection": "Blocked contacts", "block_namesSection": "Blocked names", - "block_namesHint": "Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.", - "block_offloadActive": "Firmware offload active — blocks sync to this radio", - "block_offloadStoreFull": "Radio block list full (32) — extra blocks stay app-only", + "block_namesHint": "Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.", + "block_offloadActive": "Firmware offload active: blocks sync to this radio", + "block_offloadStoreFull": "Radio block list full (32): extra blocks stay app-only", "block_composerNotice": "You've blocked this contact", "storageUnavailableTitle": "Message storage unavailable", "storageUnavailableBody": "Your history is not lost, but the app can't open its database, so new messages are NOT being saved. Restart the app after fixing the problem. See the app log for details.", diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 83862ef..eda069c 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -823,7 +823,7 @@ abstract class AppLocalizations { /// No description provided for @settings_gpsStatusNoFix. /// /// In en, this message translates to: - /// **'No fix — using stored/last position'** + /// **'No fix: using stored/last position'** String get settings_gpsStatusNoFix; /// No description provided for @settings_gpsStatusCoords. @@ -859,7 +859,7 @@ abstract class AppLocalizations { /// No description provided for @settings_gpsStatusNoResponse. /// /// In en, this message translates to: - /// **'No response — device may need the GPS-query firmware build'** + /// **'No response: device may need the GPS-query firmware build'** String get settings_gpsStatusNoResponse; /// No description provided for @settings_locationIntervalInvalid. @@ -4751,7 +4751,7 @@ abstract class AppLocalizations { /// No description provided for @repeater_pathHashModeHelper. /// /// In en, this message translates to: - /// **'Bytes used to encode this repeater\'s ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.'** + /// **'Bytes used to encode this repeater\'s ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths. Only raise once your network is on v1.14+.'** String get repeater_pathHashModeHelper; /// No description provided for @repeater_txDelay. @@ -4787,7 +4787,7 @@ abstract class AppLocalizations { /// No description provided for @repeater_intThreshHelper. /// /// In en, this message translates to: - /// **'Threshold passed to the radio\'s noise-floor calibration so it rejects interference above this level. 0 disables — only raise if you see RX errors in a noisy band.'** + /// **'Threshold passed to the radio\'s noise-floor calibration so it rejects interference above this level. 0 disables. Only raise if you see RX errors in a noisy band.'** String get repeater_intThreshHelper; /// No description provided for @repeater_agcResetInterval. @@ -4859,7 +4859,7 @@ abstract class AppLocalizations { /// No description provided for @repeater_settingsSavedRebootNeeded. /// /// In en, this message translates to: - /// **'Settings saved — reboot the repeater to apply'** + /// **'Settings saved. Reboot the repeater to apply'** String get repeater_settingsSavedRebootNeeded; /// No description provided for @repeater_settingsPartialFailure. @@ -7417,7 +7417,7 @@ abstract class AppLocalizations { /// No description provided for @snrIndicator_noNeighbors. /// /// In en, this message translates to: - /// **'No neighbors heard currently — messages still broadcast and route.'** + /// **'No neighbors heard currently. Messages still broadcast and route.'** String get snrIndicator_noNeighbors; /// No description provided for @snrIndicator_lastSeen. @@ -7987,7 +7987,7 @@ abstract class AppLocalizations { /// No description provided for @block_blockedNameOnly. /// /// In en, this message translates to: - /// **'Blocked \"{name}\" across all channels — name only until we learn their key'** + /// **'Blocked \"{name}\" across all channels. Name only until we learn their key'** String block_blockedNameOnly(String name); /// No description provided for @block_settingsTitle. @@ -8023,19 +8023,19 @@ abstract class AppLocalizations { /// No description provided for @block_namesHint. /// /// In en, this message translates to: - /// **'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'** + /// **'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'** String get block_namesHint; /// No description provided for @block_offloadActive. /// /// In en, this message translates to: - /// **'Firmware offload active — blocks sync to this radio'** + /// **'Firmware offload active: blocks sync to this radio'** String get block_offloadActive; /// No description provided for @block_offloadStoreFull. /// /// In en, this message translates to: - /// **'Radio block list full (32) — extra blocks stay app-only'** + /// **'Radio block list full (32): extra blocks stay app-only'** String get block_offloadStoreFull; /// No description provided for @block_composerNotice. diff --git a/lib/l10n/app_localizations_bg.dart b/lib/l10n/app_localizations_bg.dart index ffc9bc6..a73400e 100644 --- a/lib/l10n/app_localizations_bg.dart +++ b/lib/l10n/app_localizations_bg.dart @@ -388,7 +388,7 @@ class AppLocalizationsBg extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -408,7 +408,7 @@ class AppLocalizationsBg extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4332,7 +4332,7 @@ class AppLocalizationsBg extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Последно видян'; @@ -4674,7 +4674,7 @@ class AppLocalizationsBg extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4694,15 +4694,15 @@ class AppLocalizationsBg extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index a07c13a..1b209c5 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -390,7 +390,7 @@ class AppLocalizationsDe extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -410,7 +410,7 @@ class AppLocalizationsDe extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4345,7 +4345,7 @@ class AppLocalizationsDe extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Zuletzt gesehen'; @@ -4691,7 +4691,7 @@ class AppLocalizationsDe extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4711,15 +4711,15 @@ class AppLocalizationsDe extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 075d136..8ad3bf9 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -384,7 +384,7 @@ class AppLocalizationsEn extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -404,7 +404,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -2613,7 +2613,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get repeater_pathHashModeHelper => - 'Bytes used to encode this repeater\'s ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths — only raise once your network is on v1.14+.'; + 'Bytes used to encode this repeater\'s ID in flood path/loop-detect tags. 0=1 byte (256 IDs, up to 64 hops), 1=2 bytes (65K IDs, up to 32 hops), 2=3 bytes (16M IDs, up to 21 hops). v1.13 and older firmware drops multi-byte paths. Only raise once your network is on v1.14+.'; @override String get repeater_txDelay => 'Flood TX delay'; @@ -2634,7 +2634,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get repeater_intThreshHelper => - 'Threshold passed to the radio\'s noise-floor calibration so it rejects interference above this level. 0 disables — only raise if you see RX errors in a noisy band.'; + 'Threshold passed to the radio\'s noise-floor calibration so it rejects interference above this level. 0 disables. Only raise if you see RX errors in a noisy band.'; @override String get repeater_agcResetInterval => 'AGC reset interval'; @@ -2679,7 +2679,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get repeater_settingsSavedRebootNeeded => - 'Settings saved — reboot the repeater to apply'; + 'Settings saved. Reboot the repeater to apply'; @override String repeater_settingsPartialFailure(String failures) { @@ -4262,7 +4262,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Last seen'; @@ -4596,7 +4596,7 @@ class AppLocalizationsEn extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4616,15 +4616,15 @@ class AppLocalizationsEn extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_es.dart b/lib/l10n/app_localizations_es.dart index 421c4c2..9ba54d3 100644 --- a/lib/l10n/app_localizations_es.dart +++ b/lib/l10n/app_localizations_es.dart @@ -388,7 +388,7 @@ class AppLocalizationsEs extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -408,7 +408,7 @@ class AppLocalizationsEs extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4332,7 +4332,7 @@ class AppLocalizationsEs extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Visto por última vez'; @@ -4679,7 +4679,7 @@ class AppLocalizationsEs extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4699,15 +4699,15 @@ class AppLocalizationsEs extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_fr.dart b/lib/l10n/app_localizations_fr.dart index 801e065..8ba78ec 100644 --- a/lib/l10n/app_localizations_fr.dart +++ b/lib/l10n/app_localizations_fr.dart @@ -391,7 +391,7 @@ class AppLocalizationsFr extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -411,7 +411,7 @@ class AppLocalizationsFr extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4360,7 +4360,7 @@ class AppLocalizationsFr extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Dernière fois vu'; @@ -4707,7 +4707,7 @@ class AppLocalizationsFr extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4727,15 +4727,15 @@ class AppLocalizationsFr extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_hu.dart b/lib/l10n/app_localizations_hu.dart index b1d7a1a..8bab96a 100644 --- a/lib/l10n/app_localizations_hu.dart +++ b/lib/l10n/app_localizations_hu.dart @@ -390,7 +390,7 @@ class AppLocalizationsHu extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -410,7 +410,7 @@ class AppLocalizationsHu extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4352,7 +4352,7 @@ class AppLocalizationsHu extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Utoljára, amikor látták'; @@ -4696,7 +4696,7 @@ class AppLocalizationsHu extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4716,15 +4716,15 @@ class AppLocalizationsHu extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_it.dart b/lib/l10n/app_localizations_it.dart index 8c4f29b..e2b0d0d 100644 --- a/lib/l10n/app_localizations_it.dart +++ b/lib/l10n/app_localizations_it.dart @@ -390,7 +390,7 @@ class AppLocalizationsIt extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -410,7 +410,7 @@ class AppLocalizationsIt extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4340,7 +4340,7 @@ class AppLocalizationsIt extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Ultimo accesso'; @@ -4684,7 +4684,7 @@ class AppLocalizationsIt extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4704,15 +4704,15 @@ class AppLocalizationsIt extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 42d5f4c..4065395 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -373,7 +373,7 @@ class AppLocalizationsJa extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -393,7 +393,7 @@ class AppLocalizationsJa extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4127,7 +4127,7 @@ class AppLocalizationsJa extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => '最後に確認された場所'; @@ -4450,7 +4450,7 @@ class AppLocalizationsJa extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4470,15 +4470,15 @@ class AppLocalizationsJa extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index fe553db..2469343 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -373,7 +373,7 @@ class AppLocalizationsKo extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -393,7 +393,7 @@ class AppLocalizationsKo extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4128,7 +4128,7 @@ class AppLocalizationsKo extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => '마지막으로 목격'; @@ -4451,7 +4451,7 @@ class AppLocalizationsKo extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4471,15 +4471,15 @@ class AppLocalizationsKo extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_nl.dart b/lib/l10n/app_localizations_nl.dart index 77ed752..ebbe9ae 100644 --- a/lib/l10n/app_localizations_nl.dart +++ b/lib/l10n/app_localizations_nl.dart @@ -387,7 +387,7 @@ class AppLocalizationsNl extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -407,7 +407,7 @@ class AppLocalizationsNl extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4318,7 +4318,7 @@ class AppLocalizationsNl extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Laatst gezien'; @@ -4659,7 +4659,7 @@ class AppLocalizationsNl extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4679,15 +4679,15 @@ class AppLocalizationsNl extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_pl.dart b/lib/l10n/app_localizations_pl.dart index 902380c..75b3bef 100644 --- a/lib/l10n/app_localizations_pl.dart +++ b/lib/l10n/app_localizations_pl.dart @@ -393,7 +393,7 @@ class AppLocalizationsPl extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -413,7 +413,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4356,7 +4356,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Ostatnio widziany'; @@ -4696,7 +4696,7 @@ class AppLocalizationsPl extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4716,15 +4716,15 @@ class AppLocalizationsPl extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_pt.dart b/lib/l10n/app_localizations_pt.dart index ff2f5fb..52cd3d3 100644 --- a/lib/l10n/app_localizations_pt.dart +++ b/lib/l10n/app_localizations_pt.dart @@ -390,7 +390,7 @@ class AppLocalizationsPt extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -410,7 +410,7 @@ class AppLocalizationsPt extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4329,7 +4329,7 @@ class AppLocalizationsPt extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Visto pela última vez'; @@ -4672,7 +4672,7 @@ class AppLocalizationsPt extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4692,15 +4692,15 @@ class AppLocalizationsPt extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_ru.dart b/lib/l10n/app_localizations_ru.dart index 435b8a8..ff61747 100644 --- a/lib/l10n/app_localizations_ru.dart +++ b/lib/l10n/app_localizations_ru.dart @@ -389,7 +389,7 @@ class AppLocalizationsRu extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -409,7 +409,7 @@ class AppLocalizationsRu extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4347,7 +4347,7 @@ class AppLocalizationsRu extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Последний раз видели'; @@ -4690,7 +4690,7 @@ class AppLocalizationsRu extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4710,15 +4710,15 @@ class AppLocalizationsRu extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_sk.dart b/lib/l10n/app_localizations_sk.dart index 241c175..479c060 100644 --- a/lib/l10n/app_localizations_sk.dart +++ b/lib/l10n/app_localizations_sk.dart @@ -388,7 +388,7 @@ class AppLocalizationsSk extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -408,7 +408,7 @@ class AppLocalizationsSk extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4316,7 +4316,7 @@ class AppLocalizationsSk extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Naposledy videný'; @@ -4656,7 +4656,7 @@ class AppLocalizationsSk extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4676,15 +4676,15 @@ class AppLocalizationsSk extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_sl.dart b/lib/l10n/app_localizations_sl.dart index 5c2cea4..0942f71 100644 --- a/lib/l10n/app_localizations_sl.dart +++ b/lib/l10n/app_localizations_sl.dart @@ -386,7 +386,7 @@ class AppLocalizationsSl extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -406,7 +406,7 @@ class AppLocalizationsSl extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4313,7 +4313,7 @@ class AppLocalizationsSl extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Zadnjič videno'; @@ -4654,7 +4654,7 @@ class AppLocalizationsSl extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4674,15 +4674,15 @@ class AppLocalizationsSl extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_sv.dart b/lib/l10n/app_localizations_sv.dart index 140e4d6..7a79520 100644 --- a/lib/l10n/app_localizations_sv.dart +++ b/lib/l10n/app_localizations_sv.dart @@ -385,7 +385,7 @@ class AppLocalizationsSv extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -405,7 +405,7 @@ class AppLocalizationsSv extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4286,7 +4286,7 @@ class AppLocalizationsSv extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Senast sedd'; @@ -4629,7 +4629,7 @@ class AppLocalizationsSv extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4649,15 +4649,15 @@ class AppLocalizationsSv extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_uk.dart b/lib/l10n/app_localizations_uk.dart index 6475e37..388858a 100644 --- a/lib/l10n/app_localizations_uk.dart +++ b/lib/l10n/app_localizations_uk.dart @@ -387,7 +387,7 @@ class AppLocalizationsUk extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -407,7 +407,7 @@ class AppLocalizationsUk extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => @@ -4346,7 +4346,7 @@ class AppLocalizationsUk extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => 'Останній раз бачили'; @@ -4691,7 +4691,7 @@ class AppLocalizationsUk extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4711,15 +4711,15 @@ class AppLocalizationsUk extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 4183304..a1fea72 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -370,7 +370,7 @@ class AppLocalizationsZh extends AppLocalizations { String get settings_gpsStatusLiveFix => 'Live GPS fix'; @override - String get settings_gpsStatusNoFix => 'No fix — using stored/last position'; + String get settings_gpsStatusNoFix => 'No fix: using stored/last position'; @override String get settings_gpsStatusCoords => 'Coordinates'; @@ -390,7 +390,7 @@ class AppLocalizationsZh extends AppLocalizations { @override String get settings_gpsStatusNoResponse => - 'No response — device may need the GPS-query firmware build'; + 'No response: device may need the GPS-query firmware build'; @override String get settings_locationIntervalInvalid => '间隔时间必须至少为 60 秒,但不超过 86400 秒。'; @@ -4008,7 +4008,7 @@ class AppLocalizationsZh extends AppLocalizations { @override String get snrIndicator_noNeighbors => - 'No neighbors heard currently — messages still broadcast and route.'; + 'No neighbors heard currently. Messages still broadcast and route.'; @override String get snrIndicator_lastSeen => '最近访问'; @@ -4324,7 +4324,7 @@ class AppLocalizationsZh extends AppLocalizations { @override String block_blockedNameOnly(String name) { - return 'Blocked \"$name\" across all channels — name only until we learn their key'; + return 'Blocked \"$name\" across all channels. Name only until we learn their key'; } @override @@ -4344,15 +4344,15 @@ class AppLocalizationsZh extends AppLocalizations { @override String get block_namesHint => - 'Name-only blocks (channel senders) — each upgrades to a full block once we learn their key.'; + 'Name-only blocks (channel senders). Each upgrades to a full block once we learn their key.'; @override String get block_offloadActive => - 'Firmware offload active — blocks sync to this radio'; + 'Firmware offload active: blocks sync to this radio'; @override String get block_offloadStoreFull => - 'Radio block list full (32) — extra blocks stay app-only'; + 'Radio block list full (32): extra blocks stay app-only'; @override String get block_composerNotice => 'You\'ve blocked this contact'; diff --git a/lib/main.dart b/lib/main.dart index 34a3a8e..c9e76ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -42,8 +42,8 @@ void main() async { // Initialize SharedPreferences cache await PrefsManager.initialize(); - // Probe the storage layer up front (#385). If the database can't open — e.g. - // the native sqlite library fails to load — every read/write silently fails + // Probe the storage layer up front (#385). If the database can't open, e.g. + // the native sqlite library fails to load, every read/write silently fails // and the app looks wiped. Capture that here so the UI can warn loudly // instead of showing an empty, normal-looking screen (SAFELANE §6). final storageHealth = StorageHealthService(); diff --git a/lib/models/app_settings.dart b/lib/models/app_settings.dart index 70d4222..4997403 100644 --- a/lib/models/app_settings.dart +++ b/lib/models/app_settings.dart @@ -148,7 +148,7 @@ class AppSettings { /// written, so an older build can be rolled back to without losing mutes. final Set mutedChannels; - /// Per-channel notification level, keyed by [channelNotifyKey] — the PSK + /// Per-channel notification level, keyed by [channelNotifyKey], the PSK /// identity when known, else the slot index. Keying by PSK (not by display /// name, and not by slot) means the setting survives a rename and does not /// bleed across a slot reassignment (#193/#194). diff --git a/lib/models/channel_message.dart b/lib/models/channel_message.dart index 51602b3..092f00a 100644 --- a/lib/models/channel_message.dart +++ b/lib/models/channel_message.dart @@ -60,7 +60,7 @@ class ChannelMessage { final Map> reactionSenders; /// Local wall-clock time this message's frame arrived, set at ingest. - /// Null for outgoing messages and records stored before #285 — never + /// Null for outgoing messages and records stored before #285, never /// fabricated. [timestamp] is the SENDER's claimed time; this is ours. final DateTime? rxTime; @@ -106,7 +106,7 @@ class ChannelMessage { /// Hop count decoded from the firmware path-length byte (low 6 bits). /// The raw byte also packs hash width in its high 2 bits, so the stored - /// pathLength is NOT the hop count — use this getter for display. + /// pathLength is NOT the hop count, use this getter for display. /// Returns null when unknown; a negative (flood) sentinel is preserved. int? get hopCount { final pl = pathLength; diff --git a/lib/models/config_catalog.dart b/lib/models/config_catalog.dart index 6e5d982..b7de366 100644 --- a/lib/models/config_catalog.dart +++ b/lib/models/config_catalog.dart @@ -3,8 +3,8 @@ import 'dart:convert'; // Catalog manifest model (#404): the `profiles.json` a source publishes. // // Schema is documented in the `OffbandMesh/config-profiles` repo (SCHEMA.md). -// Parsing is resilient — a single malformed entry is skipped rather than -// failing the whole catalog — but a manifest that isn't JSON, or declares a +// Parsing is resilient, a single malformed entry is skipped rather than +// failing the whole catalog, but a manifest that isn't JSON, or declares a // newer `manifest_version` than we support, is rejected outright. /// Highest manifest_version this build understands. @@ -67,7 +67,7 @@ class ConfigCatalog { final int manifestVersion; final List entries; - /// Count of malformed entries skipped during parse — surfaced so a partly-bad + /// Count of malformed entries skipped during parse, surfaced so a partly-bad /// catalog doesn't look complete (no silent truncation). final int skippedEntries; diff --git a/lib/models/config_profile.dart b/lib/models/config_profile.dart index 7f9287c..94b13ce 100644 --- a/lib/models/config_profile.dart +++ b/lib/models/config_profile.dart @@ -2,7 +2,7 @@ /// /// A profile is a portable set of config values a user applies to a device /// (observer #139, repeater #137, companion #138) instead of baked defaults. -/// This file defines only the schema and typed model — parsing (#403) and the +/// This file defines only the schema and typed model, parsing (#403) and the /// per-device apply engines live elsewhere. /// /// Every field is nullable: a profile carries only the keys it wants to set, so @@ -20,7 +20,7 @@ const int kConfigProfileSchemaVersion = 1; /// Number of broker slots the firmware exposes (`mqtt_b0`..`mqtt_b5`). const int kMaxBrokerSlots = 6; -/// MQTT transport — wire value is the name (`tcp`/`tls`/`wss`), not the ordinal. +/// MQTT transport, wire value is the name (`tcp`/`tls`/`wss`), not the ordinal. enum MqttTransport { tcp, tls, @@ -37,7 +37,7 @@ enum MqttTransport { } } -/// MQTT auth type — wire value is the name (`none`/`basic`/`jwt`). +/// MQTT auth type, wire value is the name (`none`/`basic`/`jwt`). enum MqttAuthType { none, basic, @@ -123,10 +123,10 @@ class ConfigProfile { final int schemaVersion; final WifiConfig? wifi; - /// `mqtt.iata` — the region/IATA code applied globally. + /// `mqtt.iata`, the region/IATA code applied globally. final String? regionIata; - /// `mqtt.status_interval` — seconds between status publishes. + /// `mqtt.status_interval`, seconds between status publishes. final int? statusInterval; /// Populated broker slots only (may be sparse; each carries its [BrokerConfig.slot]). diff --git a/lib/models/contact.dart b/lib/models/contact.dart index 07e2d1c..972c04f 100644 --- a/lib/models/contact.dart +++ b/lib/models/contact.dart @@ -188,7 +188,7 @@ class Contact { // (`src/Packet.h:79-84`). 0xFF stays the flood sentinel. // // This previously read `count` BYTES, so at 2-byte width it kept half of - // every path and discarded the rest — the truncation behind #240's failed + // every path and discarded the rest, the truncation behind #240's failed // repeater logins. The width is taken from the path itself rather than the // connector's global width, so a path is always sliced at the width it was // captured at. (#309) diff --git a/lib/models/message.dart b/lib/models/message.dart index 2535962..71281c7 100644 --- a/lib/models/message.dart +++ b/lib/models/message.dart @@ -43,16 +43,16 @@ class Message { final Uint8List fourByteRoomContactKey; /// Local wall-clock time this message's frame arrived, set at ingest. - /// Null for outgoing messages and records stored before #285 — never + /// Null for outgoing messages and records stored before #285, never /// fabricated. [timestamp] is the SENDER's claimed time; this is ours. final DateTime? rxTime; /// RX signal-to-noise in dB for the received frame, captured from the v3 /// contact-msg-recv frame. Null for outgoing messages, pre-v3 firmware, and - /// records stored before #438 — never fabricated. (#438) + /// records stored before #438, never fabricated. (#438) final double? snr; - /// RX signal strength in dBm. Null until firmware populates it — the wire + /// RX signal strength in dBm. Null until firmware populates it, the wire /// currently sends a reserved 0 byte here, so we do NOT read it yet (#439). final int? rssi; diff --git a/lib/models/observer_config.dart b/lib/models/observer_config.dart index e22d2c9..db1452b 100644 --- a/lib/models/observer_config.dart +++ b/lib/models/observer_config.dart @@ -3,7 +3,7 @@ // These mirror the firmware wire contract in the firmware repo's // `examples/companion_radio/OffbandConfigProtocol.h` (CMD_OFFBAND_CONFIG 0xC0, // Epic F #160-#163). The device NVS is the single source of truth: the client -// holds no local copy — it reads via ObserverConfigClient and writes +// holds no local copy, it reads via ObserverConfigClient and writes // field-at-a-time. Secrets (password / wifi.pwd) are write-only on the wire. /// MQTT broker transport. On the wire this is the string name @@ -77,13 +77,13 @@ enum WifiStatus { sealed class SecretField { const SecretField(); - /// Leave the stored secret untouched — the codec sends nothing. + /// Leave the stored secret untouched, the codec sends nothing. const factory SecretField.unchanged() = SecretUnchanged; - /// Clear the stored secret — the codec sends an empty value. + /// Clear the stored secret, the codec sends an empty value. const factory SecretField.clear() = SecretClear; - /// Replace the stored secret — the codec sends [value]. + /// Replace the stored secret, the codec sends [value]. const factory SecretField.set(String value) = SecretSet; } @@ -103,16 +103,16 @@ class SecretSet extends SecretField { /// Outcome of verifying that a broker enable/disable actually took effect, by /// re-reading the slot after the SET (#89). A firmware build can ACK a toggle as /// success without applying it (meshcore-firmware#179), so the UI never trusts -/// the ACK alone — it re-reads and reports what the device actually says. +/// the ACK alone, it re-reads and reports what the device actually says. enum BrokerApplyOutcome { /// Re-read confirms the device is in the intended enabled state. applied, - /// The device ACKed success but the re-read shows the unchanged state — it did + /// The device ACKed success but the re-read shows the unchanged state, it did /// not apply the toggle. Surfaced as a warning, never a false success. notApplied, - /// The re-read itself failed (timeout/disconnect — e.g. an enable that rebooted + /// The re-read itself failed (timeout/disconnect, e.g. an enable that rebooted /// the device), so the result can't be confirmed either way. unverified, } @@ -174,7 +174,7 @@ enum BrokerLastError { } } -/// Display category for a broker's status line — drives the label colour/icon. +/// Display category for a broker's status line, drives the label colour/icon. enum BrokerStatusKind { connected, connecting, failed, held, idle, disabled } /// A broker's human-facing status: a [label] plus a [kind] the UI colours. @@ -185,7 +185,7 @@ class BrokerStatus { } /// One MQTT broker slot (0-9), as read back from the `OCFG_BROKERS` dump. -/// Non-secret fields only — `password` is reported as presence ([passwordSet]), +/// Non-secret fields only, `password` is reported as presence ([passwordSet]), /// `jwt_token` is never a config key. class BrokerConfig { const BrokerConfig({ @@ -218,7 +218,7 @@ class BrokerConfig { final BrokerAuthType authType; final String username; - /// Whether a password is stored — from the wire `(set)` / `(unset)` token. + /// Whether a password is stored, from the wire `(set)` / `(unset)` token. /// The value itself is never returned. final bool passwordSet; final String topicPrefix; @@ -237,7 +237,7 @@ class BrokerConfig { final BrokerLastError lastError; /// Resolved defaults shown as greyed hints when the raw key is blank (#173). - /// Never written back — the blank raw key stays the source of truth. + /// Never written back, the blank raw key stays the source of truth. final String jwtOwnerResolved; final String iataResolved; @@ -251,7 +251,7 @@ class BrokerConfig { if (url.isEmpty) return 'URL is required'; if (port < 1 || port > 65535) return 'Port must be between 1 and 65535'; // JWT owner (device pubkey), IATA override, etc. are firmware-defaulted, so - // the client does NOT gate them — the firmware enforces with its defaults. + // the client does NOT gate them, the firmware enforces with its defaults. return null; } @@ -272,7 +272,7 @@ class BrokerConfig { /// Human-facing status, derived from [enabled] + [runtimeState] + [lastError] /// (#172). When the device doesn't report runtime state ([runtimeState] is /// [BrokerRuntimeState.unknown], e.g. older firmware) this is the plain - /// enabled/disabled the UI showed before — so absent fields read as today. + /// enabled/disabled the UI showed before, so absent fields read as today. BrokerStatus get status { if (!enabled) { return const BrokerStatus('Disabled', BrokerStatusKind.disabled); @@ -288,9 +288,9 @@ class BrokerConfig { : ' (${lastError.name})'; return BrokerStatus('Failed$reason', BrokerStatusKind.failed); case BrokerRuntimeState.heldNoClock: - return const BrokerStatus('Held — no clock', BrokerStatusKind.held); + return const BrokerStatus('Held, no clock', BrokerStatusKind.held); case BrokerRuntimeState.heldNoHeap: - return const BrokerStatus('Held — low heap', BrokerStatusKind.held); + return const BrokerStatus('Held, low heap', BrokerStatusKind.held); case BrokerRuntimeState.down: case BrokerRuntimeState.unknown: return const BrokerStatus('Enabled', BrokerStatusKind.idle); diff --git a/lib/models/offband_gps_status.dart b/lib/models/offband_gps_status.dart index b21886d..904102e 100644 --- a/lib/models/offband_gps_status.dart +++ b/lib/models/offband_gps_status.dart @@ -1,4 +1,4 @@ -/// Parsed payload of a `RESP_CODE_OFFBAND_GPS` (0xC1) reply — the on-demand GPS +/// Parsed payload of a `RESP_CODE_OFFBAND_GPS` (0xC1) reply, the on-demand GPS /// state from an Offband-fork companion radio. (#135) /// /// Wire format is one ASCII string of space-separated `key=value` tokens, e.g. @@ -27,7 +27,7 @@ class OffbandGpsStatus { this.timestampUtc, }); - /// True when the radio reports a live satellite fix with usable coordinates — + /// True when the radio reports a live satellite fix with usable coordinates, /// i.e. position is GPS-driven, not a stored/manual location. (#135) bool get hasLiveFix => fix && latitude != null && longitude != null; diff --git a/lib/screens/channel_chat_screen.dart b/lib/screens/channel_chat_screen.dart index 78dfdf2..651bbc4 100644 --- a/lib/screens/channel_chat_screen.dart +++ b/lib/screens/channel_chat_screen.dart @@ -635,7 +635,7 @@ class _ChannelChatScreenState extends State { /// Block the sender of a channel post. Resolves the claimed name to known /// pubkey(s) and blocks each (full block: DM + adverts + all channels); if it /// resolves to nothing, blocks the name globally across all channels (promotes - /// to a pubkey block later, once the identity is learned — #174). + /// to a pubkey block later, once the identity is learned, #174). Future _blockChannelSender(ChannelMessage message) async { final connector = context.read(); final blockService = context.read(); @@ -1423,7 +1423,7 @@ class _ChannelChatScreenState extends State { ); } - /// One-click reply quoting the route a message took — hop count + path, + /// One-click reply quoting the route a message took, hop count + path, /// truncated with … to fit the channel byte budget, fired directly. (#106) void _sendRouteReply(ChannelMessage message) { final connector = context.read(); diff --git a/lib/screens/chat_screen.dart b/lib/screens/chat_screen.dart index 773e8df..791a24c 100644 --- a/lib/screens/chat_screen.dart +++ b/lib/screens/chat_screen.dart @@ -1439,7 +1439,7 @@ class _ChatScreenState extends State { ); if (result == null) { - return; // Cancelled — keep existing path + return; // Cancelled, keep existing path } if (!mounted) { diff --git a/lib/screens/companion_radio_stats_screen.dart b/lib/screens/companion_radio_stats_screen.dart index b17bd8b..5bc00da 100644 --- a/lib/screens/companion_radio_stats_screen.dart +++ b/lib/screens/companion_radio_stats_screen.dart @@ -20,7 +20,7 @@ class CompanionRadioStatsScreen extends StatelessWidget { } } -/// Embeddable Radio Stats content (no Scaffold) — used by both +/// Embeddable Radio Stats content (no Scaffold), used by both /// [CompanionRadioStatsScreen] and the settings shell's Radio Stats pane. /// Acquires 1 s radio-stats polling while mounted and releases it on dispose. class CompanionRadioStatsBody extends StatefulWidget { diff --git a/lib/screens/contacts_screen.dart b/lib/screens/contacts_screen.dart index d9ad000..3934973 100644 --- a/lib/screens/contacts_screen.dart +++ b/lib/screens/contacts_screen.dart @@ -1335,7 +1335,7 @@ class _ContactsScreenState extends State } else { // Confirm-first: pre-fill the route builder with the // inferred route when we have one, else an empty builder. - // The user always confirms — we never fire a silent guess. + // The user always confirms, we never fire a silent guess. // (#186; replaces the old strongest-repeater guess.) final suggested = (inferred != null && inferred.isNotEmpty) diff --git a/lib/screens/map_screen.dart b/lib/screens/map_screen.dart index 7c5752d..200efa2 100644 --- a/lib/screens/map_screen.dart +++ b/lib/screens/map_screen.dart @@ -136,7 +136,7 @@ class _MapScreenState extends State { sumSquaredDiff += diff * diff; } - // Sample standard deviation (n-1) — most appropriate here + // Sample standard deviation (n-1), most appropriate here final variance = sumSquaredDiff / (values.length - 1); return sqrt(variance); @@ -251,7 +251,7 @@ class _MapScreenState extends State { return c.hasLocation; }).toList(); - // All contacts with a known location — used as anchors regardless of + // All contacts with a known location, used as anchors regardless of // time/key-prefix filters so that repeaters are always available. final allContactsWithLocation = allContacts .where((c) => c.hasLocation) @@ -710,7 +710,7 @@ class _MapScreenState extends State { // Collect the contact-side (last-hop) repeater from every known path. // path = [device-side hop, ..., contact-side hop] - // Only path.last is actually within radio range of the contact — using + // Only path.last is actually within radio range of the contact, using // earlier bytes would anchor against our own side of the network. final pathSets = >[ contact.path.toList(), @@ -722,7 +722,7 @@ class _MapScreenState extends State { if (pathBytes.length < w) continue; // Anchor on the contact-side hop. Paths are stored device-side-first // (Contact.path is the reversed wire path), so the contact-side repeater - // is the trailing w bytes — the same hop the 1-byte code read via + // is the trailing w bytes, the same hop the 1-byte code read via // pathBytes.last, just widened to the configured width. final r = repeaterByHash[packPrefix(pathBytes, pathBytes.length - w)]; if (r != null) anchorSet.add(LatLng(r.latitude!, r.longitude!)); @@ -1010,7 +1010,7 @@ class _MapScreenState extends State { return filtered; } - /// True if two contacts share their first [width] public-key bytes — the + /// True if two contacts share their first [width] public-key bytes, the /// width-aware replacement for a 1-byte first-byte comparison. (#156) bool _samePubkeyPrefix(Contact a, Contact b, int width) { if (a.publicKey.length < width || b.publicKey.length < width) return false; diff --git a/lib/screens/path_trace_map.dart b/lib/screens/path_trace_map.dart index faaf0a8..a4dc3fb 100644 --- a/lib/screens/path_trace_map.dart +++ b/lib/screens/path_trace_map.dart @@ -195,7 +195,7 @@ class _PathTraceMapScreenState extends State { // Per the firmware trace contract, the route must EXCLUDE our own origin // prefix (it is implicit at both ends). Drop a leading self hop if the - // stored path includes it — otherwise route[0] matches no forwarding node + // stored path includes it, otherwise route[0] matches no forwarding node // (we are the sender) and the packet never advances → silent timeout. (#150) var route = pathBytes; final self = context.read().selfPublicKey; @@ -210,7 +210,7 @@ class _PathTraceMapScreenState extends State { if (isSelf) route = Uint8List.fromList(route.sublist(hopBytes)); } - // Empty path, or an all-zero "flood" marker, means no real route — trace + // Empty path, or an all-zero "flood" marker, means no real route, trace // the target's own width prefix directly. Never return an empty payload: // the firmware rejects an empty trace with error 1. (#150) if (route.isEmpty || route.every((b) => b == 0)) { @@ -256,7 +256,7 @@ class _PathTraceMapScreenState extends State { final path = widget.flipPathAround ? buildPath(pathTmp) : pathTmp; if (path.isEmpty) { - // No route to trace — don't send an empty payload (firmware error 1); + // No route to trace, don't send an empty payload (firmware error 1); // surface "not available" instead. (#150) appLogger.info( 'Path trace skipped: no route to trace', diff --git a/lib/screens/repeater_settings_screen.dart b/lib/screens/repeater_settings_screen.dart index 7072395..8e5c892 100644 --- a/lib/screens/repeater_settings_screen.dart +++ b/lib/screens/repeater_settings_screen.dart @@ -397,7 +397,7 @@ class _RepeaterSettingsScreenState extends State { /// /// Response/command pairing is guaranteed by the prefix-matching layer in /// RepeaterCommandService (firmware echoes the `XX|` token from MyMesh.cpp), - /// so no shape-based validation is needed here — `tryParse` handles any + /// so no shape-based validation is needed here, `tryParse` handles any /// malformed value by leaving state untouched. bool _handleGetResponse(String command, String response) { final normalized = command.trim().toLowerCase(); @@ -924,7 +924,7 @@ class _RepeaterSettingsScreenState extends State { await Future.delayed(const Duration(milliseconds: 200)); } - // Only clear password fields if every password command succeeded — + // Only clear password fields if every password command succeeded, // otherwise the user keeps their typed value to retry. if (!passwordsFailed) { _passwordController.clear(); diff --git a/lib/screens/serial_capture_screen.dart b/lib/screens/serial_capture_screen.dart index b462367..f5a749d 100644 --- a/lib/screens/serial_capture_screen.dart +++ b/lib/screens/serial_capture_screen.dart @@ -205,7 +205,7 @@ class _SerialCaptureScreenState extends State { title: const Text('Start capture & reboot?'), content: const Text( 'Enables serial capture, then reboots the radio so the boot log is ' - 'captured from power-on. There is no timer — capture runs until you ' + 'captured from power-on. There is no timer. Capture runs until you ' 'Stop it. The connection drops during the reboot; when it reconnects, ' 'capture is still running and you can Stop and download here.', ), @@ -254,7 +254,7 @@ class _SerialCaptureScreenState extends State { if (bytes.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( - content: Text('Buffer is empty — nothing to download.'), + content: Text('Buffer is empty, nothing to download.'), ), ); return; diff --git a/lib/screens/settings/broker_editor_screen.dart b/lib/screens/settings/broker_editor_screen.dart index e152e29..2dc78ab 100644 --- a/lib/screens/settings/broker_editor_screen.dart +++ b/lib/screens/settings/broker_editor_screen.dart @@ -114,7 +114,7 @@ class _BrokerEditorScreenState extends State { /// Pre-enable validation, shared with the list's quick Enable via /// [BrokerConfig.enableError]. Only structural fields (URL, port) gate a save - /// — the firmware enforces the rest via its own defaults. + ///, the firmware enforces the rest via its own defaults. String? _validate() => BrokerConfig( slot: _baseline.slot, url: _url.text.trim(), @@ -122,7 +122,7 @@ class _BrokerEditorScreenState extends State { ).enableError; /// Greyed placeholder showing the firmware-resolved default for a field whose - /// raw value is blank (#173). The blank raw key stays the source of truth — + /// raw value is blank (#173). The blank raw key stays the source of truth, /// this is hint text only, never written back. Null when nothing to resolve. String? _resolvedHint(String resolved, {bool shortenKey = false}) { if (resolved.isEmpty) return null; @@ -142,7 +142,7 @@ class _BrokerEditorScreenState extends State { } Future _save() async { - // Validation only gates ENABLING — disabling a slot with blank/partial + // Validation only gates ENABLING, disabling a slot with blank/partial // fields is fine; it won't be active. if (_enabled) { final err = _validate(); @@ -169,7 +169,7 @@ class _BrokerEditorScreenState extends State { messenger.showSnackBar( SnackBar( content: Text( - 'Save failed at "${result.failedField ?? 'a field'}" — the slot ' + 'Save failed at "${result.failedField ?? 'a field'}", the slot ' 'was left disabled. Re-read and retry.', ), backgroundColor: errorColor, @@ -177,7 +177,7 @@ class _BrokerEditorScreenState extends State { ); return; } - // The writes were ACKed — but a firmware build can ACK without applying the + // The writes were ACKed, but a firmware build can ACK without applying the // enabled state (meshcore-firmware#179). Settle, re-read, and only claim // success if the device actually matches what we asked for. await Future.delayed(ObserverConfigService.applySettleDelay); @@ -195,14 +195,14 @@ class _BrokerEditorScreenState extends State { ); navigator.pop(true); case BrokerApplyOutcome.notApplied: - // Stay on the editor, re-seed to the device's true state, and warn — the + // Stay on the editor, re-seed to the device's true state, and warn, the // fields were written but the device didn't honor the enable/disable. if (fresh != null) _seedFrom(fresh); messenger.showSnackBar( SnackBar( content: Text( 'Saved, but the device did not ${intended ? 'enable' : 'disable'} ' - 'broker ${_baseline.slot} — possible firmware issue', + 'broker ${_baseline.slot}, possible firmware issue', ), backgroundColor: errorColor, ), @@ -211,7 +211,7 @@ class _BrokerEditorScreenState extends State { messenger.showSnackBar( SnackBar( content: Text( - 'Broker ${_baseline.slot} saved — could not confirm enabled ' + 'Broker ${_baseline.slot} saved. Could not confirm enabled ' 'state (device may be rebooting)', ), ), @@ -429,7 +429,7 @@ class _BrokerEditorScreenState extends State { obscureText: true, decoration: InputDecoration( labelText: _baseline.passwordSet - ? 'Password (set — leave blank to keep)' + ? 'Password (set, leave blank to keep)' : 'Password', border: const OutlineInputBorder(), ), diff --git a/lib/screens/settings/config_profile_preview_screen.dart b/lib/screens/settings/config_profile_preview_screen.dart index 58e4ea3..a790fc7 100644 --- a/lib/screens/settings/config_profile_preview_screen.dart +++ b/lib/screens/settings/config_profile_preview_screen.dart @@ -7,7 +7,7 @@ import '../../services/observer_apply_service.dart'; import '../../services/observer_config_service.dart'; /// Full sub-screen preview of a config-profile apply (#406): shows the current -/// -> new diff, then a two-tier confirm — a normal Apply for plain config, and a +/// -> new diff, then a two-tier confirm, a normal Apply for plain config, and a /// separate red gate for credential/identity changes. class ConfigProfilePreviewScreen extends StatefulWidget { const ConfigProfilePreviewScreen({ @@ -117,7 +117,7 @@ class _ConfigProfilePreviewScreenState child: Padding( padding: EdgeInsets.all(24), child: Text( - 'No changes — the device already matches this profile.', + 'No changes: the device already matches this profile.', textAlign: TextAlign.center, ), ), @@ -290,7 +290,7 @@ class _DangerHeader extends StatelessWidget { const SizedBox(width: 8), Expanded( child: Text( - 'Credential / identity changes ($count) — require the red button', + 'Credential / identity changes ($count), require the red button', style: theme.textTheme.titleSmall?.copyWith( color: theme.colorScheme.error, ), diff --git a/lib/screens/settings/mqtt_brokers_screen.dart b/lib/screens/settings/mqtt_brokers_screen.dart index 367b227..f948dfa 100644 --- a/lib/screens/settings/mqtt_brokers_screen.dart +++ b/lib/screens/settings/mqtt_brokers_screen.dart @@ -8,7 +8,7 @@ import 'broker_editor_screen.dart'; /// The MQTT broker pool as its own screen (#80), reached from the Observer /// settings pane. Tap a broker to edit it; long-press for Enable / Disable / -/// Edit / Clear; the `+` FAB adds the next empty slot — matching the FAB-add +/// Edit / Clear; the `+` FAB adds the next empty slot, matching the FAB-add /// pattern of channels_screen. Single-slot re-GET keeps it off the 84-frame /// pool dump after each action. class MqttBrokersScreen extends StatefulWidget { @@ -90,7 +90,7 @@ class _MqttBrokersScreenState extends State { ); return; } - // The SET was ACKed — but a firmware build can ACK without applying it + // The SET was ACKed, but a firmware build can ACK without applying it // (meshcore-firmware#179). Settle, re-read the slot, and report what the // device ACTUALLY did rather than trusting the ACK. await Future.delayed(ObserverConfigService.applySettleDelay); @@ -123,7 +123,7 @@ class _MqttBrokersScreenState extends State { SnackBar( content: Text( 'Device reported success but broker ${b.slot} is still ' - '${fresh!.enabled ? 'enabled' : 'disabled'} — possible firmware ' + '${fresh!.enabled ? 'enabled' : 'disabled'}, possible firmware ' 'issue', ), backgroundColor: errorColor, @@ -133,7 +133,7 @@ class _MqttBrokersScreenState extends State { messenger.showSnackBar( SnackBar( content: Text( - 'Broker ${b.slot} ${enable ? 'enable' : 'disable'} sent — could ' + 'Broker ${b.slot} ${enable ? 'enable' : 'disable'} sent. Could ' 'not confirm (device may be rebooting). Tap Refresh to re-check.', ), ), @@ -266,9 +266,7 @@ class _MqttBrokersScreenState extends State { child: const Icon(Icons.add), ), body: _brokers.isEmpty - ? const Center( - child: Text('No brokers configured — tap + to add one'), - ) + ? const Center(child: Text('No brokers configured. Tap + to add one')) : ListView( children: [ for (final b in _brokers) diff --git a/lib/screens/settings/observer_settings_view.dart b/lib/screens/settings/observer_settings_view.dart index ed952e3..64297a6 100644 --- a/lib/screens/settings/observer_settings_view.dart +++ b/lib/screens/settings/observer_settings_view.dart @@ -14,10 +14,10 @@ import 'mqtt_brokers_screen.dart'; /// Staged-save model: every control edits LOCAL state; nothing reaches the /// device until "Save", which sends only the changed keys (the firmware has no /// transaction, so each is an individual SET awaiting its ACK). Device NVS is -/// the source of truth — Refresh re-reads it. +/// the source of truth, Refresh re-reads it. /// /// TODO(l10n): strings are English-only pending ARB keys. -/// The broker pool opens as its own screen (MqttBrokersScreen, #80) — tap to +/// The broker pool opens as its own screen (MqttBrokersScreen, #80), tap to /// edit, long-press for Enable/Disable/Edit/Clear, + FAB to add. class ObserverSettingsView extends StatefulWidget { const ObserverSettingsView({super.key}); @@ -47,7 +47,7 @@ class _ObserverSettingsViewState extends State { WidgetsBinding.instance.addPostFrameCallback((_) => _refreshWhenIdle()); } - /// Defer the initial read until the device's channel/contact sync settles — + /// Defer the initial read until the device's channel/contact sync settles, /// observer config traffic must not compete with (and slow) that sync (#81). void _refreshWhenIdle() { final conn = context.read(); @@ -171,7 +171,7 @@ class _ObserverSettingsViewState extends State { : ok ? 'Observer settings saved' : (svc.lastError ?? - 'Some changes failed — re-read from the device'), + 'Some changes failed. Re-read from the device'), ), backgroundColor: ok ? null : Theme.of(context).colorScheme.error, ), @@ -201,7 +201,7 @@ class _ObserverSettingsViewState extends State { if (svc.stale) _banner( Icons.warning_amber, - 'Showing the last read — the device did not answer the latest refresh.', + 'Showing the last read, the device did not answer the latest refresh.', ), if (svc.lastError != null) _banner(Icons.error_outline, svc.lastError!), _actionRow(), @@ -283,7 +283,7 @@ class _ObserverSettingsViewState extends State { if (svc.brokersUnavailable) _banner( Icons.cloud_off, - 'Broker pool unavailable — the device did not finish sending it.', + 'Broker pool unavailable. The device did not finish sending it.', ) else ListTile( @@ -369,7 +369,7 @@ class _ObserverSettingsViewState extends State { String _brokerSummary(List brokers) { final populated = brokers.where((b) => b.isPopulated).toList(); - if (populated.isEmpty) return 'None configured — tap to add'; + if (populated.isEmpty) return 'None configured. Tap to add'; final enabled = populated.where((b) => b.enabled).length; return '${populated.length} configured · $enabled enabled'; } diff --git a/lib/screens/settings/settings_shell.dart b/lib/screens/settings/settings_shell.dart index 02ceb57..75779fe 100644 --- a/lib/screens/settings/settings_shell.dart +++ b/lib/screens/settings/settings_shell.dart @@ -21,7 +21,7 @@ class SettingsCategory { /// Wide layouts (>= [_wideBreakpoint] logical pixels) show a pinned category /// rail beside the selected detail pane. Narrow layouts show the category list /// and push the detail onto the navigator. Same categories, same code, every -/// platform — the layout is chosen from the available width, not the OS. +/// platform, the layout is chosen from the available width, not the OS. class SettingsShell extends StatefulWidget { final String title; final List categories; diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 263923c..81177da 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -80,7 +80,7 @@ class _SettingsScreenState extends State { List _categories(BuildContext context) { final l10n = context.l10n; - // Rebuild ONLY when the observer gate flips — NOT on every connector update. + // Rebuild ONLY when the observer gate flips, NOT on every connector update. // A blanket context.watch here rebuilt the whole settings screen on every // sync frame, thrashing the UI thread and slowing the channel sync (#81). final showObserver = context.select( @@ -720,7 +720,7 @@ class _SettingsScreenState extends State { leading: const Icon(Icons.sync_problem_outlined), title: const Text('Sync queued messages now'), subtitle: const Text( - 'Force-pull messages the radio is holding — diagnostic for #51 ' + 'Force-pull messages the radio is holding, diagnostic for #51 ' '(radio reports a count but the app shows none). Logs the flow ' 'for diagnostics.', ), @@ -2290,7 +2290,7 @@ class _RadioSettingsFormState extends State<_RadioSettingsForm> { contentPadding: EdgeInsets.zero, ), ], - // Only this radio's own FEM probe decides whether this appears — never + // Only this radio's own FEM probe decides whether this appears, never // model or version (#304). Deliberately not mirrored into local state: // firmware returns post-apply hardware truth, so the switch renders // what the radio reports rather than what we asked for. @@ -2336,7 +2336,7 @@ class _RadioSettingsSnapshot { required this.txPowerDbm, }); - /// Frequency in integer Hz — avoids floating-point comparison issues. + /// Frequency in integer Hz, avoids floating-point comparison issues. int get frequencyHz => (frequencyMHz * 1000).round(); /// Convert from the connector's raw-int snapshot to UI-enum snapshot. diff --git a/lib/screens/topology_debug_screen.dart b/lib/screens/topology_debug_screen.dart index cc3a1dd..3b2f569 100644 --- a/lib/screens/topology_debug_screen.dart +++ b/lib/screens/topology_debug_screen.dart @@ -13,7 +13,7 @@ import '../widgets/adaptive_app_bar_title.dart'; /// epic #186). It answers one question on real hardware: is /// [MeshTopologyService] actually ingesting? Node/edge counts climb as routed /// packets arrive; stuck at zero while traffic flows means the RX ingestion -/// wiring is dead. Strings are hardcoded EN on purpose — this is a dev-facing +/// wiring is dead. Strings are hardcoded EN on purpose, this is a dev-facing /// diagnostic, deliberately not part of the localized UX surface. class TopologyDebugScreen extends StatelessWidget { const TopologyDebugScreen({super.key}); @@ -85,7 +85,7 @@ class TopologyDebugScreen extends StatelessWidget { List contacts, ) { final selfLabel = self == null - ? 'not set yet — waiting for first packet' + ? 'not set yet, waiting for first packet' : (_nameOf(self, contacts) == null ? _hex(self) : '${_nameOf(self, contacts)} (${_hex(self)})'); @@ -229,7 +229,7 @@ class TopologyDebugScreen extends StatelessWidget { ), const SizedBox(height: 6), Text( - 'Listening — this fills as routed packets arrive from the mesh. ' + 'Listening. This fills as routed packets arrive from the mesh. ' 'Leave it connected a few minutes.', textAlign: TextAlign.center, style: TextStyle(fontSize: 12, color: Colors.grey[500]), @@ -282,7 +282,7 @@ class TopologyDebugScreen extends StatelessWidget { final self = topo.self; final buf = StringBuffer() ..writeln( - 'Mesh topology — ${topo.nodeCount} nodes, ${topo.edgeCount} edges', + 'Mesh topology: ${topo.nodeCount} nodes, ${topo.edgeCount} edges', ) ..writeln('self: ${self == null ? "(unset)" : _hex(self)}') ..writeln('freshness: ${topo.freshnessSeconds ~/ 86400}d') diff --git a/lib/screens/usb_screen.dart b/lib/screens/usb_screen.dart index 25992de..d426546 100644 --- a/lib/screens/usb_screen.dart +++ b/lib/screens/usb_screen.dart @@ -329,7 +329,7 @@ class _UsbScreenState extends State { ..addAll(ports); }); } catch (_) { - // Silent — hot-plug failures are non-critical. + // Silent, hot-plug failures are non-critical. } } diff --git a/lib/services/block_service.dart b/lib/services/block_service.dart index 0b27747..9c9b081 100644 --- a/lib/services/block_service.dart +++ b/lib/services/block_service.dart @@ -35,14 +35,14 @@ class BlockService extends ChangeNotifier { } /// Called by the connector when the self key is learned (or cleared). If the - /// self key is already stored — blocked before this guard existed, or pulled - /// in from the radio's list — drop it here and tell the radio to remove it. + /// self key is already stored, blocked before this guard existed, or pulled + /// in from the radio's list, drop it here and tell the radio to remove it. Future setSelfKey(String? publicKeyHex) async { final key = publicKeyHex?.toLowerCase(); final normalized = (key == null || key.isEmpty) ? null : key; final changed = normalized != _selfKeyHex; _selfKeyHex = normalized; - // Heal even when the key is unchanged — a self-block can appear after the + // Heal even when the key is unchanged, a self-block can appear after the // key is already known (a union pull racing self-info, or a stale store), // and an unchanged-key early return would strand it. final healed = normalized != null && _blockedKeys.remove(normalized); @@ -93,7 +93,7 @@ class BlockService extends ChangeNotifier { /// Merge keys learned from the firmware block list into the local set WITHOUT /// echoing them back to the radio (used by the connect-time union pull). - /// Never removes — the union only adds. + /// Never removes, the union only adds. Future importKeys(Iterable keysHex) async { var changed = false; for (final k in keysHex) { @@ -134,7 +134,7 @@ class BlockService extends ChangeNotifier { final key = publicKeyHex.toLowerCase(); _blockedNames.remove(n); // Your own name resolving to your own key must not promote into a - // self-block — drop the name block and stop (#250). + // self-block, drop the name block and stop (#250). if (isSelf(key)) { await _store.saveNames(_blockedNames); notifyListeners(); diff --git a/lib/services/config_source_service.dart b/lib/services/config_source_service.dart index 6837ccd..0ea976d 100644 --- a/lib/services/config_source_service.dart +++ b/lib/services/config_source_service.dart @@ -7,7 +7,7 @@ import '../models/config_profile.dart'; /// Fetches config profiles from a remote source (#404): the curated Offband /// catalog, or any region's self-hosted catalog / single profile. /// -/// Device-agnostic — observer (#139), repeater (#137), and companion (#138) +/// Device-agnostic, observer (#139), repeater (#137), and companion (#138) /// share this. Only the apply step differs per device. /// Default curated catalog (repo: OffbandMesh/config-profiles). @@ -21,7 +21,7 @@ class ResolvedSource { const ResolvedSource(this.kind, this.url); final SourceKind kind; - /// The URL to actually fetch (may differ from the input — a directory URL + /// The URL to actually fetch (may differ from the input, a directory URL /// resolves to `/profiles.json`). final String url; } @@ -81,8 +81,8 @@ class ConfigSourceService { try { // Cache-bust for federated catalogs on normal servers/CDNs: a unique // query param + no-cache headers get them to serve fresh content. - // KNOWN LIMITATION (#452): raw.githubusercontent — the DEFAULT catalog - // host — ignores BOTH (verified: X-Cache HIT on a unique-query request) + // KNOWN LIMITATION (#452): raw.githubusercontent, the DEFAULT catalog + // host, ignores BOTH (verified: X-Cache HIT on a unique-query request) // and serves its cached copy for up to max-age=300 (~5 min). So the // default catalog can lag up to 5 min after an edit; this does not defeat // that. Kept because region-hosted catalogs elsewhere do honor it. diff --git a/lib/services/linux_ble_pairing_service.dart b/lib/services/linux_ble_pairing_service.dart index 8ed52f6..e95d67f 100644 --- a/lib/services/linux_ble_pairing_service.dart +++ b/lib/services/linux_ble_pairing_service.dart @@ -154,7 +154,7 @@ class LinuxBlePairingService { return false; } - // Timeout path — pairing neither succeeded nor failed. + // Timeout path, pairing neither succeeded nor failed. onLog?.call('Pairing did not complete before timeout'); if (!result.pinSent && !proactivePinRetryUsed && diff --git a/lib/services/mesh_topology_service.dart b/lib/services/mesh_topology_service.dart index 1a42e23..00d672f 100644 --- a/lib/services/mesh_topology_service.dart +++ b/lib/services/mesh_topology_service.dart @@ -3,7 +3,7 @@ import 'dart:collection'; import 'package:flutter/foundation.dart'; /// A node (repeater/relay) in the passively-observed mesh topology, keyed by its -/// width-byte path-hash prefix. (#186 Phase B — see docs/trace-topology-spec.md) +/// width-byte path-hash prefix. (#186 Phase B, see docs/trace-topology-spec.md) class TopoNode { final Uint8List prefix; int lastSeen; // unix seconds @@ -29,7 +29,7 @@ class TopoEdge { int lastSeen; int count; - /// Set when a trace routed over this link timed out — inference deprioritises + /// Set when a trace routed over this link timed out, inference deprioritises /// it so the graph self-heals as topology drifts. int? lastFailed; @@ -43,13 +43,13 @@ class TopoEdge { } /// Accumulates the routing paths of received packets into a topology graph and -/// infers trace routes from it — the thing the firmware can't do (it only walks +/// infers trace routes from it, the thing the firmware can't do (it only walks /// a caller-supplied route) and the reference apps push onto the user (manual /// build). Deliberately SEPARATE from PathHistoryService (Ben, 2026-07-05): /// PathHistory weights message routing; this is the trace oracle. /// /// Storage is bounded by design: the graph is deduplicated (a node/edge stored -/// once, refreshed), pruned by freshness, and hard-capped by node count — so it +/// once, refreshed), pruned by freshness, and hard-capped by node count, so it /// scales with mesh size, not hop depth or packet volume. (#186) class MeshTopologyService extends ChangeNotifier { static const int defaultFreshnessSeconds = 7 * 24 * 3600; // 7 days @@ -98,7 +98,7 @@ class MeshTopologyService extends ChangeNotifier { double? neighbourSnrOf(List prefix) => _nodes[_hex(prefix)]?.neighbourSnr; - /// Our own node prefix — the BFS origin for inference and the anchor for the + /// Our own node prefix, the BFS origin for inference and the anchor for the /// `us ~ direct-neighbour` edges. void setSelf(List prefix, int width) { final w = width < 1 ? 1 : width; @@ -117,7 +117,7 @@ class MeshTopologyService extends ChangeNotifier { /// `origin → h1 → … → hk → us`, so `hk` = `path`'s last hop = our direct /// neighbour). [lastHopSnr] is the SNR of our reception (attributed to `hk`). /// Returns true on a notify-worthy STRUCTURAL change (new node/edge). Cheap: - /// O(path length ≤ 64) map writes — the path was already parsed upstream. + /// O(path length ≤ 64) map writes, the path was already parsed upstream. bool observePath( List path, { required int width, @@ -193,7 +193,7 @@ class MeshTopologyService extends ChangeNotifier { } /// The ordered intermediate hops from us to [target], EXCLUDING both us and - /// the target — feed straight into + /// the target, feed straight into /// `PathHelper.buildTraceRoundTrip(routingPath: result, targetPrefix: target)`. /// /// - `[]` → target is a direct neighbour (a one-hop ping is correct). @@ -287,7 +287,7 @@ class MeshTopologyService extends ChangeNotifier { } } - /// Drops nodes/edges not heard within the freshness window — for persistence + /// Drops nodes/edges not heard within the freshness window, for persistence /// bounds (Phase D). Inference already ignores stale links at query time. void pruneStale([int? nowTs]) { final now = nowTs ?? _now(); diff --git a/lib/services/message_retry_service.dart b/lib/services/message_retry_service.dart index ae81a68..8d048ed 100644 --- a/lib/services/message_retry_service.dart +++ b/lib/services/message_retry_service.dart @@ -21,7 +21,7 @@ class _AckHistoryEntry { }); } -/// (messageId, timestamp, attemptIndex, pathSelection) — stored per ACK hash +/// (messageId, timestamp, attemptIndex, pathSelection), stored per ACK hash /// for O(1) lookup. [pathSelection] snapshots the route used for this /// specific attempt so that a late PUSH_CODE_SEND_CONFIRMED credits the /// correct path even when the message has since been retried on a different @@ -174,7 +174,7 @@ class MessageRetryService extends ChangeNotifier { _config?.addMessage(contact.publicKeyHex, message); - // Queue per contact — only one message in-flight at a time to avoid + // Queue per contact, only one message in-flight at a time to avoid // overflowing the firmware's 8-entry expected_ack_table. final contactKey = contact.publicKeyHex; _sendQueue[contactKey] ??= []; @@ -267,7 +267,7 @@ class MessageRetryService extends ChangeNotifier { ); _pendingMessages[messageId] = updatedMessage; } else if (message.retryCount > 0) { - // No schedule entry for this retry — re-resolve path from current contact + // No schedule entry for this retry, re-resolve path from current contact // state so user's path override changes are picked up between retries. final resolved = resolvePathSelection(contact); final updatedMessage = message.copyWith( @@ -304,7 +304,7 @@ class MessageRetryService extends ChangeNotifier { } } - // Re-validate after async gap — a timer or ACK could have resolved/retried + // Re-validate after async gap, a timer or ACK could have resolved/retried // this message while we were awaiting the path callback. final currentMessage = _pendingMessages[messageId]; if (currentMessage == null || _resolvedMessages.contains(messageId)) { @@ -384,7 +384,7 @@ class MessageRetryService extends ChangeNotifier { _pendingMessages[messageId] = failed; _config?.updateMessage(failed); _config?.debugLogService?.warn( - 'No RESP_CODE_SENT within ${_sentConfirmationTimeoutMs}ms — marking send failed', + 'No RESP_CODE_SENT within ${_sentConfirmationTimeoutMs}ms, marking send failed', tag: 'AckHash', ); notifyListeners(); @@ -464,7 +464,7 @@ class MessageRetryService extends ChangeNotifier { _pendingMessages[messageId] = updatedMessage; config.updateMessage(updatedMessage); - // Radio confirmed the send — the delivery-ack timer takes over from here. + // Radio confirmed the send, the delivery-ack timer takes over from here. _sentConfirmationTimers.remove(messageId)?.cancel(); _startTimeoutTimer(messageId, actualTimeout); return true; diff --git a/lib/services/observer_apply_service.dart b/lib/services/observer_apply_service.dart index 23bd243..74c8ff3 100644 --- a/lib/services/observer_apply_service.dart +++ b/lib/services/observer_apply_service.dart @@ -1,7 +1,7 @@ import '../helpers/config_profile_writes.dart'; import 'observer_config_service.dart'; -/// Result of applying one write (or one broker slot). [label] is safe to show — +/// Result of applying one write (or one broker slot). [label] is safe to show, /// it names the key/slot, never a value, so secrets never leak into UI or logs. class ApplyItemResult { const ApplyItemResult(this.label, this.ok, [this.error]); @@ -56,7 +56,7 @@ class ObserverApplyService { : ApplyItemResult( 'broker ${b.slot}', false, - 'field "${res.failedField}" failed — slot left disabled', + 'field "${res.failedField}" failed, slot left disabled', ), ); } diff --git a/lib/services/observer_config_service.dart b/lib/services/observer_config_service.dart index 35ed00f..5b7af48 100644 --- a/lib/services/observer_config_service.dart +++ b/lib/services/observer_config_service.dart @@ -2,7 +2,7 @@ // [ObserverConfigClient], sends them over the active transport, awaits and // parses the response, and holds the parsed [ObserverConfig]. // -// Device NVS is the source of truth — this service caches the last read but +// Device NVS is the source of truth, this service caches the last read but // never persists locally. The firmware protocol has no request id, so // responses are correlated by ORDER: keep ONE request in flight at a time // (the settings UI sends staged changes sequentially, awaiting each). @@ -32,22 +32,22 @@ class ObserverConfigService extends ChangeNotifier { ObserverConfig? _config; ObserverConfig? get config => _config; - /// True after a refresh failed to complete — the UI shows stale data warning + /// True after a refresh failed to complete, the UI shows stale data warning /// rather than silently presenting an out-of-date snapshot. bool _stale = false; bool get stale => _stale; - /// Last error surfaced (SAFELANE §6 — every failure is visible). The UI shows + /// Last error surfaced (SAFELANE §6, every failure is visible). The UI shows /// it; cleared on the next success. String? _lastError; String? get lastError => _lastError; - /// True when the broker-pool dump failed but the flat settings read OK — the + /// True when the broker-pool dump failed but the flat settings read OK, the /// UI shows the broker section as unavailable instead of blanking the pane. bool _brokersUnavailable = false; bool get brokersUnavailable => _brokersUnavailable; - /// Whether the connected device supports the config command — the version + /// Whether the connected device supports the config command, the version /// gate AND the capability bit, read live from the connector's device-info /// parse. The settings UI watches the connector, so the Observer category /// appears/hides as this flips on connect/disconnect. @@ -140,7 +140,7 @@ class ObserverConfigService extends ChangeNotifier { /// Save a broker [slot] field-at-a-time per the firmware contract: a live slot /// is disabled first, each changed [fields] entry is written, then `enabled` /// is written LAST (when [enable]). Stops at the first ERR/timeout and reports - /// the failed field — a partial save therefore leaves the slot disabled, never + /// the failed field, a partial save therefore leaves the slot disabled, never /// live-corrupt (#80). The caller re-GETs the slot to show true state + offer /// retry/clear. Future saveBroker( @@ -167,10 +167,10 @@ class ObserverConfigService extends ChangeNotifier { return const BrokerSaveResult.ok(); } - /// Definitively wipe a broker slot — `mqtt.broker..clear` (#80). + /// Definitively wipe a broker slot, `mqtt.broker..clear` (#80). Future clearBroker(int slot) => setBrokerField(slot, 'clear', '1'); - /// Re-read a single broker [slot] field-by-field — the post-save / recovery + /// Re-read a single broker [slot] field-by-field, the post-save / recovery /// re-GET. Cheaper than the whole pool: 14 scalar GETs for one slot, not the /// 84-frame OCFG_BROKERS dump (#80). Returns null if any field GET fails. Future getBroker(int slot) async { @@ -194,7 +194,7 @@ class ObserverConfigService extends ChangeNotifier { for (final f in fields) { final v = await getFlat('mqtt.broker.$slot.$f'); if (v == null) { - // password is write-only — a missing read is its presence, not a slot + // password is write-only, a missing read is its presence, not a slot // failure; any other missing field means the re-GET is incomplete. if (f == 'password') continue; return null; @@ -210,7 +210,7 @@ class ObserverConfigService extends ChangeNotifier { /// Read the broker pool (paginated START → KV → END). Null on a stall or /// error. The completion deadline is an INACTIVITY watchdog re-armed on every - /// frame — a large pool streams field-by-field and outlasts any single fixed + /// frame, a large pool streams field-by-field and outlasts any single fixed /// deadline, so only a genuine stall (no frame for [timeout]) fails (#103). /// The fetch lifecycle is logged to the shared file log (#108) so a tester's /// Share-logs capture shows in plain text where a pool load succeeds or fails. @@ -239,7 +239,7 @@ class ObserverConfigService extends ChangeNotifier { final r = ObserverConfigClient.parse(f); if (r is ConfigBrokersStart) { expected = r.count; - _logBroker('pool GET: header — ${r.count} brokers'); + _logBroker('pool GET: header, ${r.count} brokers'); } frames++; final list = decoder.add(r); @@ -260,7 +260,7 @@ class ObserverConfigService extends ChangeNotifier { _logBroker( 'pool GET: FAILED after ' '${DateTime.now().difference(started).inMilliseconds}ms ' - '($frames frames, header said ${expected ?? "?"}) — $e', + '($frames frames, header said ${expected ?? "?"}), $e', ); _setError('broker list failed: $e'); return null; @@ -285,7 +285,7 @@ class ObserverConfigService extends ChangeNotifier { final alwaysOn = await getFlat('display.always_on'); final rotation = await getFlat('display.rotation'); // Skip the heavy broker dump (84 frames) when only flat settings changed - // (e.g. after a flat Save) — it must not re-flood BLE for a toggle (#81). + // (e.g. after a flat Save), it must not re-flood BLE for a toggle (#81). final brokers = includeBrokers ? await getBrokers() : null; final keptBrokers = _config?.brokers ?? const []; diff --git a/lib/services/queue_sync_file_log_io.dart b/lib/services/queue_sync_file_log_io.dart index 4dd2d8d..205e753 100644 --- a/lib/services/queue_sync_file_log_io.dart +++ b/lib/services/queue_sync_file_log_io.dart @@ -11,7 +11,7 @@ import 'package:path_provider/path_provider.dart'; // The IOSink is intentionally held open for the app's lifetime (append-only, // low-frequency) rather than open/close per line; the OS closes the handle on // process exit. `_sinkFuture ??= _openSink()` assigns synchronously before the -// await, so concurrent callers share one sink — no double-open on the event +// await, so concurrent callers share one sink, no double-open on the event // loop. Future? _sinkFuture; diff --git a/lib/services/storage_health_service.dart b/lib/services/storage_health_service.dart index ce62c9a..1a36ffe 100644 --- a/lib/services/storage_health_service.dart +++ b/lib/services/storage_health_service.dart @@ -3,8 +3,8 @@ import 'package:flutter/foundation.dart'; /// Tracks whether the app's storage layer (drift/SQLite) opened successfully at /// startup (#385). /// -/// When the database can't open — e.g. the native `sqlite3` library fails to -/// load — every read and write silently fails and the app looks wiped. This +/// When the database can't open, e.g. the native `sqlite3` library fails to +/// load, every read and write silently fails and the app looks wiped. This /// holds that state so the UI can show a loud, persistent warning instead of an /// empty, normal-looking screen (SAFELANE §6: no silent failures). class StorageHealthService extends ChangeNotifier { diff --git a/lib/services/timeout_prediction_service.dart b/lib/services/timeout_prediction_service.dart index d92ca64..679c777 100644 --- a/lib/services/timeout_prediction_service.dart +++ b/lib/services/timeout_prediction_service.dart @@ -24,7 +24,7 @@ class TimeoutPredictionService extends ChangeNotifier { static const int maxObservations = 100; static const int _retrainInterval = 5; // 1.5x multiplier on raw prediction to account for variance in delivery - // times — tight enough to improve on worst-case physics, loose enough + // times, tight enough to improve on worst-case physics, loose enough // to avoid premature timeouts from model noise. static const double _safetyMargin = 1.5; static const int _minContactObservations = 10; diff --git a/lib/services/usb_serial_frame_codec.dart b/lib/services/usb_serial_frame_codec.dart index e62e082..0b7b39a 100644 --- a/lib/services/usb_serial_frame_codec.dart +++ b/lib/services/usb_serial_frame_codec.dart @@ -5,7 +5,7 @@ const int usbSerialRxFrameStart = 0x3e; const int usbSerialHeaderLength = 3; // Max companion frame the decoder will accept, matching the firmware's // MAX_FRAME_SIZE (BaseSerialInterface.h = 176, "+4 for transport codes"). This -// was 172, which silently rejected full-size frames — exposed by caplog chunks +// was 172, which silently rejected full-size frames, exposed by caplog chunks // (176 B), the first feature to use the full frame. Normal traffic stays <=172. const int usbSerialMaxPayloadLength = 176; diff --git a/lib/services/usb_serial_service_native.dart b/lib/services/usb_serial_service_native.dart index 05655bb..4405919 100644 --- a/lib/services/usb_serial_service_native.dart +++ b/lib/services/usb_serial_service_native.dart @@ -104,7 +104,7 @@ class UsbSerialService { } /// Best-effort USB vendor ID for [portName] from the flserial port - /// enumeration, or null if it can't be determined. Enumeration only — it does + /// enumeration, or null if it can't be determined. Enumeration only, it does /// NOT open the port, so it can't trigger the reset the gate exists to avoid. /// Used to gate the DTR open pulse. (#244/#245) int? _lookupPortVid(String portName) { @@ -194,7 +194,7 @@ class UsbSerialService { bool opened = false; for (final candidate in candidates) { - // Always create a fresh FlSerial instance — a cached instance retains + // Always create a fresh FlSerial instance, a cached instance retains // a stale flh handle from prior failed opens, which causes the native // fl_open() to mis-route the request and report port-not-exist even // when the device node is physically present. @@ -206,7 +206,7 @@ class UsbSerialService { final msg = 'Failed to open USB port $candidate (status: $openStatus)'; _debugLogService?.error(msg, tag: 'USB Serial'); - // Not a FlSerialException — treat as terminal failure + // Not a FlSerialException, treat as terminal failure _status = UsbSerialStatus.disconnected; throw StateError(msg); } @@ -224,8 +224,8 @@ class UsbSerialService { } else { // ESP32 USB-Serial/JTAG (VID 303A) maps DTR/RTS onto EN/BOOT, so a // DTR-low window resets the chip into ROM download mode mid-open and - // wedges it. Any non-nRF52 device — including an unknown/unparseable - // VID — opens with DTR asserted and no pulse (a stale DTR is safer + // wedges it. Any non-nRF52 device, including an unknown/unparseable + // VID, opens with DTR asserted and no pulse (a stale DTR is safer // than wedging the device). (#244/#245) serial.setDTR(true); } @@ -370,7 +370,7 @@ class UsbSerialService { // state for all ports. The global reset is done in connect() instead, // before the next open, which is the safer place to do it. - // Now it is safe to cancel the Dart subscription — the native thread has + // Now it is safe to cancel the Dart subscription, the native thread has // already seen the port close and will not fire any more callbacks. await _dataSubscription?.cancel(); _dataSubscription = null; @@ -404,7 +404,7 @@ class UsbSerialService { void dispose() { // Synchronously close the native port so the SerialThread exits before // the Dart isolate is torn down (e.g. on hot restart). The async - // disconnect() path via unawaited() offers no ordering guarantee — the + // disconnect() path via unawaited() offers no ordering guarantee, the // isolate may die before the Future resolves, leaving the thread alive // with a dangling NativeCallable pointer. if (_useDesktopFlSerial) { @@ -412,7 +412,7 @@ class UsbSerialService { try { if (serial?.isOpen() == FlOpenStatus.open) { serial?.setDTR(false); - serial?.closePort(); // synchronous C call — kills the SerialThread + serial?.closePort(); // synchronous C call, kills the SerialThread } } catch (_) {} } diff --git a/lib/services/windows_taskbar_service.dart b/lib/services/windows_taskbar_service.dart index 648fd15..4b26845 100644 --- a/lib/services/windows_taskbar_service.dart +++ b/lib/services/windows_taskbar_service.dart @@ -3,7 +3,7 @@ import 'dart:io' show Platform; import 'package:flutter/foundation.dart' show debugPrint; import 'package:flutter/services.dart'; -/// Flashes the Windows taskbar button to draw attention — e.g. a new message +/// Flashes the Windows taskbar button to draw attention, e.g. a new message /// arriving while the app window is not in the foreground. /// /// The native side (`windows/runner/flutter_window.cpp`) only flashes when the diff --git a/lib/storage/block_store.dart b/lib/storage/block_store.dart index 22c892b..0ca7e9d 100644 --- a/lib/storage/block_store.dart +++ b/lib/storage/block_store.dart @@ -5,7 +5,7 @@ import 'prefs_manager.dart'; /// Persistence for the app-global block list. /// -/// Deliberately **global** — unlike the other stores it is NOT scoped by the +/// Deliberately **global**, unlike the other stores it is NOT scoped by the /// connected device key. A block is "I don't want to see this person," keyed by /// their public key, and must hold regardless of which radio is connected. /// See `docs/architecture/block-contract-as-built.md`. diff --git a/lib/storage/channel_message_store.dart b/lib/storage/channel_message_store.dart index 8077d23..831a579 100644 --- a/lib/storage/channel_message_store.dart +++ b/lib/storage/channel_message_store.dart @@ -19,7 +19,7 @@ class ChannelMessageStore { set setPublicKeyHex(String value) => publicKeyHex = value.length >= 10 ? value.substring(0, 10) : ''; - /// Resolves a channel slot index to its channel's PSK hex — a stable identity + /// Resolves a channel slot index to its channel's PSK hex, a stable identity /// that does not change when the channel moves slots. Set by the connector. /// When it yields a non-empty hex, history is keyed by PSK so reusing a slot /// can never surface a previous occupant's messages. Falls back to the slot @@ -166,8 +166,8 @@ class ChannelMessageStore { String? jsonString = await blobs.readWithPrefsFallback(key); // One-time migration into the PSK-identity key. Only runs when the PSK is - // known (key != index key). Adopts pre-#194 history keyed by slot index — - // device-scoped first, then the oldest unscoped key — and drops the source. + // known (key != index key). Adopts pre-#194 history keyed by slot index, + // device-scoped first, then the oldest unscoped key, and drops the source. // Build-B (#193) clears a slot's index history on mismatched reuse, so a // live slot's index data is the channel's own by the time we read here. if ((jsonString == null || jsonString.isEmpty) && diff --git a/lib/storage/client_id_store.dart b/lib/storage/client_id_store.dart index 742c27e..2aecfd3 100644 --- a/lib/storage/client_id_store.dart +++ b/lib/storage/client_id_store.dart @@ -20,7 +20,7 @@ import 'prefs_manager.dart'; class ClientIdStore { static const String _key = 'client_install_id'; - /// Byte length of the id. Do not change without re-checking both firmwares — + /// Byte length of the id. Do not change without re-checking both firmwares, /// 6 is what keeps the app-name offset agreeing at 8. static const int length = 6; diff --git a/lib/storage/drift/blob_store.dart b/lib/storage/drift/blob_store.dart index 8b8243c..ea75b9f 100644 --- a/lib/storage/drift/blob_store.dart +++ b/lib/storage/drift/blob_store.dart @@ -98,7 +98,7 @@ class BlobStore { } /// Proves the database opens and round-trips a write. Throws (or returns - /// false) if storage is unusable — e.g. the native sqlite library can't load + /// false) if storage is unusable, e.g. the native sqlite library can't load /// (#385). Used by the startup health probe. Future verifyReadWrite() => _db.verifyReadWrite(); diff --git a/lib/storage/drift/offband_database.dart b/lib/storage/drift/offband_database.dart index 1b2e028..0c91e57 100644 --- a/lib/storage/drift/offband_database.dart +++ b/lib/storage/drift/offband_database.dart @@ -52,7 +52,7 @@ class OffbandDatabase extends _$OffbandDatabase { web: DriftWebOptions( sqlite3Wasm: Uri.parse('sqlite3.wasm'), // Filename matches the asset published by the drift release, which is - // `drift_worker.js` — not the `drift_worker.dart.js` the older docs + // `drift_worker.js`, not the `drift_worker.dart.js` the older docs // name. Both assets are taken from the SAME drift release so they are // built against each other. driftWorker: Uri.parse('drift_worker.js'), diff --git a/lib/theme/mesh_theme.dart b/lib/theme/mesh_theme.dart index 7c35d57..978eb9a 100644 --- a/lib/theme/mesh_theme.dart +++ b/lib/theme/mesh_theme.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -/// MeshCore redesign palette — warm field-journal dark theme with +/// MeshCore redesign palette, warm field-journal dark theme with /// phosphor-green signal accents. Mirrors values from the redesign spec. class MeshPalette { MeshPalette._(); @@ -67,7 +67,7 @@ class MeshPalette { static const lightSignal = Color(0xFF1A7A44); } -/// Named font stacks — Flutter falls back to system fonts when the named +/// Named font stacks, Flutter falls back to system fonts when the named /// family isn't installed, keeping things working without bundled assets. class MeshFonts { MeshFonts._(); @@ -389,7 +389,7 @@ class MeshTheme { ); } - /// Mono text style — sizes default to the body size Inter is using. + /// Mono text style, sizes default to the body size Inter is using. static TextStyle mono({ double? fontSize, FontWeight? fontWeight, @@ -424,7 +424,7 @@ class MeshTheme { ); } - /// Small-caps mono label — used for section accents and chip labels. + /// Small-caps mono label, used for section accents and chip labels. static TextStyle accentLabel({Color? color, double? fontSize}) { return TextStyle( fontFamily: MeshFonts.mono, diff --git a/lib/utils/build_info.dart b/lib/utils/build_info.dart index 00d5b34..db1f9cd 100644 --- a/lib/utils/build_info.dart +++ b/lib/utils/build_info.dart @@ -1,6 +1,6 @@ /// Identity of the running binary, injected at build time (#397). /// -/// Set via `--dart-define` so every build — debug or release, dev or prod — +/// Set via `--dart-define` so every build, debug or release, dev or prod, /// carries its own identity, independent of the pubspec marketing version: /// /// ``` diff --git a/lib/utils/file_log_writer.dart b/lib/utils/file_log_writer.dart index 63a7209..625222f 100644 --- a/lib/utils/file_log_writer.dart +++ b/lib/utils/file_log_writer.dart @@ -6,7 +6,7 @@ import 'dart:io'; /// [maxBytes], it rotates: `.log` -> `.1.log` -> `.2.log` …, keeping /// at most [maxFiles] files total (oldest dropped). Platform-agnostic: the /// caller resolves [dir] (e.g. `getApplicationSupportDirectory()`) and only -/// constructs this where a filesystem exists — never on web. Writes are appended +/// constructs this where a filesystem exists, never on web. Writes are appended /// and flushed so logs survive a crash. class FileLogWriter { FileLogWriter({ diff --git a/lib/utils/macos_usb_device_names.dart b/lib/utils/macos_usb_device_names.dart index ad521f8..25ccf00 100644 --- a/lib/utils/macos_usb_device_names.dart +++ b/lib/utils/macos_usb_device_names.dart @@ -74,7 +74,7 @@ Map _parseIoregOutput(String output) { currentVendor = vendorMatch.group(1)?.trim(); continue; } - // IOCalloutDevice — the /dev/cu.xxx path our app uses + // IOCalloutDevice, the /dev/cu.xxx path our app uses final calloutMatch = _kCalloutDevice.firstMatch(line); if (calloutMatch != null) { final port = calloutMatch.group(1)?.trim(); diff --git a/lib/utils/usb_vid.dart b/lib/utils/usb_vid.dart index d43e350..1ca7a59 100644 --- a/lib/utils/usb_vid.dart +++ b/lib/utils/usb_vid.dart @@ -7,10 +7,10 @@ /// wedges it until a physical reset. We gate the pulse by vendor ID. (#244/#245) library; -/// Adafruit — nRF52 boards (RAK4631 etc.). Needs the DTR edge to reconnect. +/// Adafruit, nRF52 boards (RAK4631 etc.). Needs the DTR edge to reconnect. const int usbVidAdafruitNrf52 = 0x239A; -/// Espressif — ESP32 USB-Serial/JTAG. The DTR pulse resets it into ROM. +/// Espressif, ESP32 USB-Serial/JTAG. The DTR pulse resets it into ROM. const int usbVidEspressif = 0x303A; final RegExp _vidWindows = RegExp(r'VID_([0-9A-Fa-f]{4})'); diff --git a/lib/widgets/app_shell.dart b/lib/widgets/app_shell.dart index 1225393..2517ac2 100644 --- a/lib/widgets/app_shell.dart +++ b/lib/widgets/app_shell.dart @@ -21,11 +21,11 @@ class AppShell extends StatefulWidget { static const double _drawerWidth = 300; /// Bottom bar tab to highlight. A pushed detail screen (a channel chat) still - /// sets this so the bar stays visible; it is NOT what decides Back behavior — + /// sets this so the bar stays visible; it is NOT what decides Back behavior, /// [isTopLevel] is. Null renders no bottom bar. final int? selectedIndex; - /// Whether this is a genuine top-level landing screen — a bottom-bar tab + /// Whether this is a genuine top-level landing screen, a bottom-bar tab /// (Contacts/Channels/Map). On a top-level screen, Back sends the app to the /// background; on a pushed detail screen (a channel chat, the LOS map) Back /// pops to the list it came from. Kept separate from [selectedIndex] so a @@ -74,8 +74,8 @@ class AppShell extends StatefulWidget { /// Pure back-button decision (#389), extracted so it is testable without the /// widget tree. An open drawer closes first; a pushed detail ([isTopLevel] - /// false) that has a route below pops to its list; anything else — a - /// top-level tab, or a detail with nothing to pop — backgrounds the app. A + /// false) that has a route below pops to its list; anything else, a + /// top-level tab, or a detail with nothing to pop, backgrounds the app. A /// top-level tab CAN pop (the scanner sits below it) but must not, or Back /// would strand the user on the radio-connect screen. @visibleForTesting diff --git a/lib/widgets/battery_optimization_banner.dart b/lib/widgets/battery_optimization_banner.dart index c6e54ec..4f34e38 100644 --- a/lib/widgets/battery_optimization_banner.dart +++ b/lib/widgets/battery_optimization_banner.dart @@ -12,7 +12,7 @@ import '../utils/platform_info.dart'; /// exempt gets put to sleep on screen-off, dropping the radio connection. The /// app can't force the exemption without the Play-restricted /// `REQUEST_IGNORE_BATTERY_OPTIMIZATIONS` permission, so it only reads its own -/// status and deep-links to the settings screen — no restricted permission, +/// status and deep-links to the settings screen: no restricted permission, /// no Play-policy impact. /// /// Mirrors [StorageUnavailableBanner]'s wrap-child shape: when there is nothing @@ -65,7 +65,7 @@ class _BatteryOptimizationBannerState extends State if (!mounted) return; setState(() => _ignoring = ignoring); } catch (e) { - // Can't confirm the status — leave the banner hidden rather than risk a + // Can't confirm the status, leave the banner hidden rather than risk a // false warning, but surface the failure to the log (SAFELANE §6). appLogger.warn( 'Battery-optimization status check failed: $e', diff --git a/lib/widgets/blocked_badge.dart b/lib/widgets/blocked_badge.dart index 6dca699..7edfcca 100644 --- a/lib/widgets/blocked_badge.dart +++ b/lib/widgets/blocked_badge.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; /// Small red "blocked" indicator (circle-with-slash) shown next to a blocked /// entry's name in the contacts/discovery lists. Blocked entries stay visible -/// (not hidden) — see `docs/architecture/block-contract-as-built.md`. +/// (not hidden), see `docs/architecture/block-contract-as-built.md`. class BlockedBadge extends StatelessWidget { final double size; const BlockedBadge({super.key, this.size = 16}); diff --git a/lib/widgets/gif_picker.dart b/lib/widgets/gif_picker.dart index fcae16e..e71253b 100644 --- a/lib/widgets/gif_picker.dart +++ b/lib/widgets/gif_picker.dart @@ -19,7 +19,7 @@ class _GifPickerState extends State { bool _isLoading = false; String? _error; - // Giphy API key — injected at build time, never hardcoded. Provide it via: + // Giphy API key, injected at build time, never hardcoded. Provide it via: // flutter build ... --dart-define-from-file=dart_defines.json // (or --dart-define=GIPHY_API_KEY=). Empty when unset → the picker shows a hint. static const String _giphyApiKey = String.fromEnvironment('GIPHY_API_KEY'); diff --git a/lib/widgets/keep_screen_awake.dart b/lib/widgets/keep_screen_awake.dart index 4a98167..538bb09 100644 --- a/lib/widgets/keep_screen_awake.dart +++ b/lib/widgets/keep_screen_awake.dart @@ -8,7 +8,7 @@ import '../services/app_settings_service.dart'; /// the app is foregrounded (#269). /// /// The lock is released when the setting is turned off, when the app leaves the -/// foreground, and on dispose — so normal display sleep resumes and the +/// foreground, and on dispose, so normal display sleep resumes and the /// background foreground-service behaviour is untouched. class KeepScreenAwake extends StatefulWidget { const KeepScreenAwake({super.key, required this.child}); diff --git a/lib/widgets/mention_autocomplete.dart b/lib/widgets/mention_autocomplete.dart index 5302d98..e7cfc25 100644 --- a/lib/widgets/mention_autocomplete.dart +++ b/lib/widgets/mention_autocomplete.dart @@ -128,7 +128,7 @@ class _MentionAutocompleteFieldState extends State { void _onChanged() { // Cursor-driven trigger detection (same shape as multi_trigger_autocomplete's - // invokingTrigger). It does not special-case the IME composing region — + // invokingTrigger). It does not special-case the IME composing region, // fine for hardware keyboards; a known limitation for CJK/IME input, which // the reference package doesn't handle either. final value = widget.controller.value; @@ -352,7 +352,7 @@ class _MentionAutocompleteFieldState extends State { if (key == LogicalKeyboardKey.enter || key == LogicalKeyboardKey.numpadEnter) { // Enter accepts the highlighted item (emoji or mention) like Tab, then - // sends — so `:shrug` + Enter ships the highlighted glyph, and `@Bob` + + // sends, so `:shrug` + Enter ships the highlighted glyph, and `@Bob` + // Enter inserts the mention. Tab accepts without sending; Esc dismisses // the dropdown to send literal text. (#231) if (_highlighted >= 0 && _highlighted < _matches.length) { diff --git a/lib/widgets/path_selection_dialog.dart b/lib/widgets/path_selection_dialog.dart index 62a2c6b..4dfaf62 100644 --- a/lib/widgets/path_selection_dialog.dart +++ b/lib/widgets/path_selection_dialog.dart @@ -59,7 +59,7 @@ class PathSelectionDialog extends StatefulWidget { /// Parses comma-separated hex hop prefixes, each exactly [hashWidth] bytes /// wide (clamped >= 1). Wrong-length or malformed entries go to [invalid] and - /// are skipped — never silently truncated. (#155) + /// are skipped, never silently truncated. (#155) static List parsePathPrefixes( String text, int hashWidth, diff --git a/lib/widgets/storage_unavailable_banner.dart b/lib/widgets/storage_unavailable_banner.dart index db53efd..8f0c2e6 100644 --- a/lib/widgets/storage_unavailable_banner.dart +++ b/lib/widgets/storage_unavailable_banner.dart @@ -5,7 +5,7 @@ import '../l10n/l10n.dart'; /// A persistent, non-dismissable banner shown above the whole app when the /// storage layer failed to open (#385). /// -/// SAFELANE §6: a storage failure must be loud and stay visible — not a 4s +/// SAFELANE §6: a storage failure must be loud and stay visible, not a 4s /// toast, and never a silent empty screen. When [show] is false this is a /// transparent pass-through and adds no layout. class StorageUnavailableBanner extends StatelessWidget { diff --git a/lib/widgets/translated_message_content.dart b/lib/widgets/translated_message_content.dart index e4b751e..96b8917 100644 --- a/lib/widgets/translated_message_content.dart +++ b/lib/widgets/translated_message_content.dart @@ -59,7 +59,7 @@ class TranslatedMessageContent extends StatelessWidget { } // Mentions can't be interleaved with the Linkify widget, so a message that // contains a mention renders as rich text with chip spans (links inside a - // mention message are not tappable — same as the prior leading-mention + // mention message are not tappable, same as the prior leading-mention // path). Messages without a mention keep full link support above. final spans = []; var last = 0; diff --git a/test/models/broker_status_test.dart b/test/models/broker_status_test.dart index 52478b7..c28f0f8 100644 --- a/test/models/broker_status_test.dart +++ b/test/models/broker_status_test.dart @@ -62,7 +62,7 @@ void main() { ); expect( _broker(state: BrokerRuntimeState.heldNoHeap).status.label, - 'Held — low heap', + 'Held, low heap', ); });