Skip to content

feat: Messages UI redesign, telemetry fixes, and emoji support#7

Merged
Yeraze merged 6 commits into
mainfrom
feat/messages-ui-and-telemetry-improvements
Sep 28, 2025
Merged

feat: Messages UI redesign, telemetry fixes, and emoji support#7
Yeraze merged 6 commits into
mainfrom
feat/messages-ui-and-telemetry-improvements

Conversation

@Yeraze

@Yeraze Yeraze commented Sep 28, 2025

Copy link
Copy Markdown
Owner

Summary

  • Redesigned Messages tab with split-view layout matching Nodes tab
  • Fixed environment telemetry storage (null value handling)
  • Implemented hop count display with fallback calculations
  • Added emoji/tapback message support with database schema
  • Disabled frequent notification chime
  • Cleaned up debug logging from protobuf investigation

Changes

  • UI/UX: Split-view Messages tab with sortable node list and unread indicators
  • Telemetry: Fixed null checks for temperature, humidity, and pressure storage
  • Hop Counts: Extract and display hop counts with snake_case fallback support
  • Emoji Support: Database migration, protobuf field extraction, and UI rendering
  • API: Include hopStart, hopLimit, replyId, and emoji in message responses
  • Notifications: Disabled auto-play chime (TODO: user-configurable settings)

Test plan

  • Verify Messages tab displays split-view layout correctly
  • Confirm environment telemetry saves properly
  • Check hop count calculations display accurately
  • Test emoji/tapback message display (note: device firmware may not send these fields)
  • Verify notification chime is disabled
  • Ensure no excessive debug logging in production

🤖 Generated with Claude Code

Yeraze and others added 6 commits September 27, 2025 20:55
- Implement split-view layout matching Nodes tab design
- Add sortable node list with unread message indicators
- Filter traceroute messages from direct message counts
- Reorder layout to show messages above telemetry charts
- Improve message container sizing with flexible height
- Add proper spacing and padding to conversation panel

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add null checks for environment telemetry (temperature, humidity, pressure) to prevent storing null values
- Fix hop field extraction to check both camelCase and snake_case variants
- Change database insertion to use nullish coalescing (??) instead of logical OR (||) to properly handle 0 values
- Improve hop count display in UI with fallback calculation when hopStart is missing, assuming common max hopLimit of 7

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Disable notification sound that was playing too frequently
- Remove debug logging from hop field extraction
- Add TODO for user-configurable notification settings
- Simplify hop field extraction code

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add missing hopStart and hopLimit fields to getRecentMessages() mapping
- This enables frontend to calculate and display hop counts for messages

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Add emoji field to database schema with migration
- Extract emoji field from incoming mesh packets
- Store emoji Unicode code point in database
- Convert emoji code point to character and display in UI
- Include emoji and replyId in API message responses

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Removed extensive debug logging used to investigate protobuf field parsing.
Added snake_case fallback for reply_id field detection.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude

claude Bot commented Sep 28, 2025

Copy link
Copy Markdown
Contributor

Claude finished @Yeraze's task —— View job


PR Review Complete ✅

I've conducted a thorough review of this pull request covering code quality, potential bugs, performance, security, and test coverage.

Summary

This PR implements significant UI improvements and important bug fixes. The code quality is generally excellent with proper error handling, good separation of concerns, and thoughtful implementation details.

🟢 Strengths

Code Quality & Best Practices

  • Excellent CSS Architecture: Comprehensive Catppuccin theme with well-organized CSS variables and responsive design (App.css:1-2370)
  • Proper Error Handling: Robust null checks for telemetry data (meshtasticManager.ts:898-915)
  • Clean Database Migrations: Well-implemented schema changes with proper error handling (database.ts:242-322)
  • Good State Management: Proper React hooks usage and state isolation in the split-view implementation

Bug Fixes

  • Fixed Telemetry Storage: Critical fix for null temperature/humidity/pressure values (meshtasticManager.ts:898-915)
  • Enhanced Message Support: Proper emoji and reply message handling with fallback support for both camelCase and snake_case fields (meshtasticManager.ts:706-715)
  • Robust Hop Count Display: Intelligent fallback calculation when hopStart is missing (App.tsx:1512-1527)

Performance Optimizations

  • Efficient Database Queries: Proper indexing and normalized BigInt handling (database.ts:325-340, database.ts:585-604)
  • Smart UI Updates: Split-view design reduces re-renders and improves UX
  • Optimized CSS: Well-structured selectors and efficient animations

🟡 Areas for Improvement

Code Organization

  • Large File Size: App.tsx is quite large and could benefit from component extraction for better maintainability
  • Complex State Logic: Message filtering and display logic could be extracted into custom hooks

Type Safety

// Consider strengthening type safety:
const decodedReplyId = (meshPacket.decoded as any)?.replyId ?? (meshPacket.decoded as any)?.reply_id;

Location: meshtasticManager.ts:707

Could benefit from proper TypeScript interfaces instead of any casting.

Performance Considerations

  • Emoji Regex: The emoji detection regex runs frequently (App.tsx:943-944) - consider memoization for better performance
  • Large Message Lists: Consider virtualization for very large message histories

🔒 Security

  • No Security Concerns: Code follows secure practices with proper input validation and no exposed credentials
  • Safe Database Operations: Prepared statements used throughout preventing SQL injection

🧪 Test Coverage

  • Test Plan Completed: Author has manually tested all functionality
  • Consider Adding: Unit tests for the hop count calculation logic and emoji detection functions would improve confidence

📋 Specific Recommendations

  1. Component Extraction: Consider breaking down the large App.tsx file:

    // Extract these into separate components:
    - MessagesBubbleView
    - NodesList 
    - TracerouteDisplay
  2. Type Safety Enhancement: Define proper interfaces for protobuf message types instead of using any

  3. Performance Optimization: Memoize the emoji regex for better performance:

    const emojiRegex = useMemo(() => /^(\p{Emoji_Presentation}|\p{Extended_Pictographic})$/u, []);
  4. Error Boundary: Consider adding React error boundaries around the new split-view components

Approval Recommendation

This PR demonstrates excellent engineering practices with:

  • Critical bug fixes for telemetry storage
  • Well-designed UI improvements
  • Proper database schema evolution
  • Good error handling and edge case management

The code is production-ready with only minor suggestions for future improvements. The author has clearly thought through the implementation details and edge cases.

Recommended Action: ✅ Approve and Merge


@Yeraze Yeraze merged commit dedfda1 into main Sep 28, 2025
1 check passed
@Yeraze Yeraze deleted the feat/messages-ui-and-telemetry-improvements branch September 28, 2025 02:13
Yeraze added a commit that referenced this pull request Oct 12, 2025
TheWISPRer pushed a commit to TheWISPRer/meshmonitor that referenced this pull request Jun 20, 2026
- Mark messages played from the delivery-success callback, not at enqueue:
  handleCommand returns { responses, playOnDelivery }; a dropped body DM now
  leaves the message pending instead of losing it. (Yeraze#1)
- Wire purgeExpired into databaseMaintenanceService so expired rows are
  reclaimed daily (purgeExpired returns a count). (Yeraze#2)
- Count the per-recipient cap across the recipient's identity forms via an
  injected node resolver, so it can't be bypassed by addressing one node by
  several name forms. (Yeraze#3)
- Mailbox bypasses the per-node cooldown (interactive flow). (Yeraze#4)
- inbox play <sender> filter matches !hex/node-num forms too. (Yeraze#5)
- Non-DM commands return [] (no unsolicited DM). (Yeraze#6)
- inbox delete returns the same response for not-yours vs non-existent ids
  (no id enumeration). (Yeraze#7)
- Wrap the mailbox dispatch in try/catch like the script branch. (Yeraze#8)
- Remove the command-prefix tolerance: canonical msg/inbox only. (Yeraze#9)
- Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (Yeraze#10)

Docs + tests updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TheWISPRer pushed a commit to TheWISPRer/meshmonitor that referenced this pull request Jun 21, 2026
- Mark messages played from the delivery-success callback, not at enqueue:
  handleCommand returns { responses, playOnDelivery }; a dropped body DM now
  leaves the message pending instead of losing it. (Yeraze#1)
- Wire purgeExpired into databaseMaintenanceService so expired rows are
  reclaimed daily (purgeExpired returns a count). (Yeraze#2)
- Count the per-recipient cap across the recipient's identity forms via an
  injected node resolver, so it can't be bypassed by addressing one node by
  several name forms. (Yeraze#3)
- Mailbox bypasses the per-node cooldown (interactive flow). (Yeraze#4)
- inbox play <sender> filter matches !hex/node-num forms too. (Yeraze#5)
- Non-DM commands return [] (no unsolicited DM). (Yeraze#6)
- inbox delete returns the same response for not-yours vs non-existent ids
  (no id enumeration). (Yeraze#7)
- Wrap the mailbox dispatch in try/catch like the script branch. (Yeraze#8)
- Remove the command-prefix tolerance: canonical msg/inbox only. (Yeraze#9)
- Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (Yeraze#10)

Docs + tests updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Yeraze added a commit that referenced this pull request Jun 21, 2026
…ore) (#3538)

* feat: add Dead Drop / Mailbox auto-responder (async message store)

A per-source 'mesh voicemail': a node DMs the radio `msg <name> <text>`
and the message is held until the named recipient retrieves it via
`inbox` / `inbox play`. Implemented as a new auto-responder
responseType ('mailbox'), reusing the existing DM-gating, per-node
cooldown, param extraction, and per-source scoping.

- DB: dead_drop_messages table (SQLite/PostgreSQL/MySQL) + migration 092
- Repository (Drizzle-only) + DatabaseService.deadDrop accessor
- DeadDropService: command brain (store/inbox/play[/sender]/delete/clear,
  180-byte cap, per-recipient & per-sender caps, 7-day expiry, batch play)
- meshtasticManager: 'mailbox' responseType dispatch branch
- UI: 'Mailbox' response type option + guidance in the auto-responder editor
- Tests: 34 (migration registry, repository perSource, service)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): add Mailbox option to the Add-Trigger form select

The Mailbox response type was only added to the per-trigger edit view
(TriggerItem); the separate Add-Trigger form in AutoResponderSection had
its own type <select> (Text/HTTP/Script) that was missed, so new mailbox
triggers couldn't be created from the UI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): don't require response text to add a Mailbox trigger

The Add button's disabled gate required a non-empty response field for
all types; Mailbox has no response, so the button stayed greyed out.
Exempt mailbox from the response-required check (matches validateResponse).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): accept mailbox responseType in settings save validation

The settings-save validator required a non-empty response for every
trigger and only allowed text/http/script responseTypes, so saving a
Mailbox trigger failed with a generic 400. Exempt mailbox from the
response-required check and add it to the responseType allowlist.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(dead-drop): settings-save accepts mailbox triggers without response text

Regression coverage for the mailbox responseType in the autoResponderTriggers
validator: a mailbox trigger with empty response now saves (200), while
non-mailbox empty responses and unknown responseTypes still 400.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(dead-drop): tolerate optional command keyword prefix

The mailbox service parsed hardcoded msg/inbox, but a trigger configured with
prefixed keywords (e.g. betamsg/betainbox, to coexist with another responder
already using msg/inbox) would fire the handler yet fall through to help. Strip
an optional non-space prefix from the leading verb so prefixed keywords parse
correctly; no-op for plain msg/inbox. Caught by live over-the-air testing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(dead-drop): add Mailbox feature docs + live testing brief

- automation.md: Mailbox response type + 'Mailbox (Dead Drop)' section
  (commands, recipient matching, delivery format, limits, command-prefix
  coexistence, configuration).
- dev-notes/DEAD_DROP_TESTING.md: architecture, automated coverage, and the
  over-the-air validation results (ALTO MF / ALTO LF / ZN Office).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): register dead_drop_messages in migrate-db table lists

The cross-database migrate-db CLI tracks every schema table in TABLE_ORDER /
SKIP_TABLES; migrationTables.test.ts fails if a new schema table isn't listed.
Add dead_drop_messages to TABLE_ORDER and SOURCE_SCOPED_TABLES (it carries a
sourceId, like auto_favorite_targets). Caught by the full Vitest suite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(dead-drop): address PR review feedback

- Mark messages played from the delivery-success callback, not at enqueue:
  handleCommand returns { responses, playOnDelivery }; a dropped body DM now
  leaves the message pending instead of losing it. (#1)
- Wire purgeExpired into databaseMaintenanceService so expired rows are
  reclaimed daily (purgeExpired returns a count). (#2)
- Count the per-recipient cap across the recipient's identity forms via an
  injected node resolver, so it can't be bypassed by addressing one node by
  several name forms. (#3)
- Mailbox bypasses the per-node cooldown (interactive flow). (#4)
- inbox play <sender> filter matches !hex/node-num forms too. (#5)
- Non-DM commands return [] (no unsolicited DM). (#6)
- inbox delete returns the same response for not-yours vs non-existent ids
  (no id enumeration). (#7)
- Wrap the mailbox dispatch in try/catch like the script branch. (#8)
- Remove the command-prefix tolerance: canonical msg/inbox only. (#9)
- Use shared nodeIdHex (unsigned coerce) for the mailbox log target. (#10)

Docs + tests updated to match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(dead-drop): recommend enabling Verify response on the mailbox trigger

Played-state is committed from the delivery-success callback; with Verify
response off (maxAttempts=1) a single unacked send could mark a voicemail
played on transmit. Document enabling Verify response so undelivered bodies
resurface. (PR #3538 review follow-up)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: chrisn <chrisn@DebDev1.corp.tlclocal.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Randall Hand <randall.hand@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant