- Create theme.css with CSS custom properties for light/dark themes
- Dark theme inspired by demo landing page (deep navy palette)
- Update style.css: replace ~145 hardcoded colors with CSS variables
- Extract inline styles from index.html, contacts.html, dm.html to style.css
- Add Appearance tab in Settings modal with theme selector
- Bootstrap 5.3 data-bs-theme integration for native dark mode
- Theme persisted in localStorage, applied before CSS loads (no FOUC)
- Console and System Log panels unchanged (already dark themed)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On screens >= 992px (lg breakpoint), show a persistent sidebar panel:
- Group chat: channel list with unread badges, active highlight, muted state
- DM: conversation/contact list with search, unread dots, type badges
- Desktop contact header with info button replaces mobile selector
- Mobile/narrow screens unchanged (dropdown/top selector still used)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
'No Flood' was confusing next to the 'Reset to FLOOD' button.
'Keep path' better describes the behavior: don't auto-reset
the path to FLOOD after failed direct retries.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reset to FLOOD now only resets the device path without deleting
configured paths from the database. New Clear Paths button deletes
all configured paths from DB without touching the device. This lets
users reset to FLOOD to discover new paths while keeping their
configured alternatives intact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The path creation form is now a separate modal (z-index 1070) that
opens above Contact Info with its own backdrop, making the UI layers
clearly distinguishable. Map picker modal bumped to z-index 1080 so
it stacks correctly above both Contact Info and Add Path modals.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Raises the z-index of the map modal (1070) and its backdrop (1060)
so the Contact Info modal behind is visually grayed out, making it
clear which modal is active.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Map modal no longer closes on Add - resets selection instead so user
can pick multiple repeaters in sequence. Cancel button renamed to Close.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a map button (geo icon) next to the list picker in the path form.
Clicking it opens a modal with a Leaflet map showing repeater locations.
User clicks a repeater marker, then clicks Add to append its ID prefix
to the path hex. Includes Cached toggle to show all DB repeaters vs
only device-known ones. Respects current hash size setting (1B/2B/3B).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ID mode searches by first N hex chars of public key (2/4/6 chars
depending on selected hash size). Placeholder updates dynamically.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New `contact_paths` table for storing multiple user-configured paths per contact
- New `no_auto_flood` column on contacts to prevent automatic DIRECT→FLOOD reset
- Path rotation during DM retry: cycles through configured paths before optional flood fallback
- REST API for path CRUD, reorder, reset-to-flood, repeater listing
- Path management UI in Contact Info modal: add/delete/reorder paths, repeater picker with uniqueness warnings, hash size selector (1B/2B/3B)
- "No Flood" per-contact toggle in modal footer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows an X button when a conversation is selected, allowing quick
clearing of the search field to find another contact.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Redesign DM chat contact selector:
- Replace <select> dropdown with searchable text input + filtered dropdown
- Show only device contacts (from /api/contacts/detailed), not all cached
- Sort contacts alphabetically, conversations by recency
- Type badge (CLI/REP/ROOM/SENS) shown in dropdown items
- Keyboard support: Enter selects first match, Escape closes
Add Contact Info modal (replaces Retry toggle in header):
- Shows contact name, type, public key, last advert, path/route, GPS
- Auto Retry toggle moved into modal footer
- Designed for future extensibility (manual path setting etc.)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add SocketIO /chat client to dm.js for real-time DM and ACK updates
- Listen for new_message (dm), ack, device_status events
- Remove 5x cascading refresh after send (replaced by SocketIO ACK)
- Reduce polling interval from 10s to 60s (fallback only)
- Add data-ack attribute to status icons for real-time ACK updates
- Enrich ACK emission with snr/rssi/route_type (device_manager.py)
- Include socket.io.min.js in dm.html template
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement automatic retry for DM messages when ACK is not received,
similar to the MeshCore mobile app's Auto Retry feature. The bridge
monitors for ACK after each send and retries up to 3 times, switching
to flood routing after 2 failed direct attempts via reset_path.
- Bridge: background retry engine with configurable max_attempts,
flood_after; retry group tracking to prevent duplicate messages
- Bridge: enhanced ACK status checks retry groups so delivery is
detected even if only a retry attempt's ACK arrives
- Backend: filter retry SENT_MSG duplicates from message list
- Frontend: extended ACK polling window, auto-retry toggle in DM bar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add person icon button in filter bar that inserts the current device
name into the search field, for filtering own messages
- DM filter bar already benefits from the CSS sibling push-down rule
added in previous commit (same class names used)
- Add collapsible FAB toggle to DM view, same pattern as channel chat
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add filter-utils.js with diacritic-insensitive search and text highlighting
- Add FAB filter button (gray funnel icon) to channel chat and DM
- Filter bar slides in as overlay at top of chat area
- Real-time filtering with debounce (150ms) as user types
- Matched text highlighted with yellow background
- Support for Polish characters (wol matches wół)
- Keyboard shortcuts: Ctrl+F to open, Escape to close
- Match counter shows X / Y filtered messages
- Filter persists during auto-refresh
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Resend button under own messages in channel chat and DM
(allows easy re-sending of failed messages)
- Change channel chat limit from 140 to 135 bytes
- Change DM limit from 140 to 150 bytes
(experimentally verified Meshcore limits)
- Remove misleading Hops info from DM message bubbles
- Update README with new byte limits
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Complete the offline support implementation by hosting emoji-picker-element locally, eliminating the last external CDN dependency. Application now works 100% offline without any internet connection.
Changes:
- Download and host emoji-picker-element 1.28.1 locally (~100 KB)
- index.js, picker.js, database.js
- Download and host emoji data JSON (~429 KB)
- en/emojibase/data.json with full emoji database
- Update index.html and dm.html:
- Replace CDN emoji picker import with local version
- Also migrate Bootstrap CSS/JS to local in dm.html (was missed before)
- Configure emoji picker to use local data source in app.js and dm.js
- Set picker.dataSource to local JSON path
- Update Service Worker (v2 → v3):
- Add emoji picker files to pre-cache list
- Total offline cache size: ~1.2 MB
- Update documentation:
- README.md: Add emoji picker to offline support features
- CLAUDE.md: Document emoji picker implementation and file structure
Total offline package breakdown:
- Bootstrap CSS/JS: ~307 KB
- Bootstrap Icons: ~398 KB
- Emoji Picker: ~100 KB
- Emoji Data: ~429 KB
- Total: ~1.2 MB
Benefits:
- Zero external dependencies (no CDN calls)
- Full emoji picker functionality offline
- Faster page load (no external requests)
- Perfect for air-gapped mesh network deployments
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
After testing the modal implementation on Android PWA, removed duplicate
navigation elements and optimized layout to maximize screen real estate.
Changes to DM modal:
- Removed navbar with back button and "DM" title (duplicates modal header)
- Moved conversation selector to top of content as clean dropdown bar
- Changed main container from dynamic height to fixed 100vh
Changes to Contact Management modals:
- Removed navbar with home button from contacts_base.html
- Removed navbar_content blocks from all contact pages (manage, pending, existing)
- Removed padding/margins from base container (px-3 py-4 → p-0)
- Removed row gutters (added g-0 class)
- Removed col width constraint (col-lg-8 mx-auto → col-12)
- Added padding back to individual page content (p-3) for readability
Changes to modal close buttons:
- Replaced small X icon (btn-close) with proper button
- Added "Close" text with X icon for better visibility on mobile
- Used btn-outline-light styling for consistency with green/blue headers
Result:
- Modals now fill entire available screen space without margins
- No duplicate headers or navigation elements
- Clearer, more intuitive close action with labeled button
- Better mobile experience with larger touch targets
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Root cause: Bootstrap offcanvas leaves backdrop/body classes in DOM
when navigating via window.location.href, causing viewport issues.
Changes:
- Remove hamburger menu button from DM navbar (caused overflow)
- Reduce menu button icon size on channels (remove font-size override)
- Add global navigateTo() function in app.js and contacts.js
- Function closes offcanvas, removes backdrops, clears body classes
- Replace all window.location.href calls with navigateTo()
- Updated navigation in: base.html, contacts*.html templates
- Add 100ms delay before navigation to ensure cleanup completes
This fixes the issue where:
1. Opening offcanvas menu on main page
2. Navigating to DM or Contact Management
3. Returning to main page
Results in corrupted viewport with hidden status bar
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Unify navbar:
- Add menu button to DM navbar (same icon as channels) for consistent height
- Both navbars now have 3 elements: back/brand, dropdown, menu button
Unify message input area:
- Disable textarea resize on both pages (resize: none)
- Unify input font-size on mobile (0.9rem)
- Unify form padding on mobile (0.5rem)
- Unify border-radius for send buttons
Unify message bubbles:
- Set DM message max-width to 70% (same as channels)
- Unify padding: 0.75rem 1rem (same as channels)
- Unify max-width on mobile: 85% for both
- Remove explicit font-size from DM bubbles (inherit default)
- Unify animation duration: 0.3s
Unify selectors:
- Apply same mobile styles to both #channelSelector and #dmConversationSelector
PWA fixes:
- Move safe-area handling from inline styles to main CSS
- Apply safe-area-inset-bottom globally for both pages
- Remove duplicate inline styles from dm.html
This should fix the Android PWA viewport issue where the bottom bar
gets hidden under system navigation after navigating to DM page.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Change DM message input from input to textarea (rows=2) for consistency
- Increase DM form padding (p-2 → p-3) to match channel view
- Increase DM status bar padding (p-1 → p-2) with larger font
- Replace "Last refresh:" with "Updated:" in both views
- Update DM status to show connection states (Connected/Connecting/Disconnected) instead of "Ready"
- Add loadStatus() function to DM page for proper connection monitoring
- Unify message input area height and status bar appearance across both pages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented comprehensive message content enhancements for both channel messages and DMs:
- **Mention badges**: @[Username] mentions now display as styled badges similar to Android Meshcore app
- **Clickable URLs**: http:// and https:// URLs are automatically converted to clickable links that open in new tabs
- **Image thumbnails**: URLs ending in .jpg, .jpeg, .png, .gif, .webp display as thumbnails with click-to-expand modal preview
- **Mobile responsive**: Image thumbnails adapt size for mobile screens
- **Security**: Proper XSS protection with HTML escaping and attribute sanitization
Technical implementation:
- Created shared message-utils.js module for content processing
- Added CSS styles for badges, links, images, and modal preview
- Updated both app.js and dm.js to use new content processor
- Used event delegation for image click handlers to support dynamic content
- Responsive design with mobile-optimized image sizes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Move toast container from bottom-right to top-left corner
- Reduce notification display time from 3-5s to 1.5s
- Prevents notifications from blocking message input area
- Applied consistently across all pages (main, DM, contacts)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Change DM menu link from <a> to <button> with onclick for better
mobile compatibility (fixes link not working on some devices)
- Add proper flexbox layout styles for DM page viewport height
- Use 100dvh (dynamic viewport height) for mobile browsers
- Add flex-shrink: 0 to form and status bar to prevent overflow
- Reduce padding in form and status bar for more compact mobile view
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix duplicate conversations in dropdown by merging pk_ and name_ IDs
- Add intelligent refresh (only reload when new messages arrive)
- Fix message alignment (own messages right, others left)
- Change sent message status from 'timeout' to 'pending'
- Add emoji picker button to DM page
- Change message limit from 200 to 140 bytes (consistent with channels)
- Update README.md with corrected DM documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace DM modal with full-page view at /dm route for better mobile UX
- Add workaround for meshcore-cli bug where SENT_MSG contains sender's
name instead of recipient - now saving sent DMs to separate log file
- Fix DM button styling to match Reply button (btn-outline-secondary)
- Add dm.js for DM page functionality
- Add dm.html template with green navbar for visual distinction
- Update menu link to navigate to /dm instead of opening modal
- Remove unused DM modal functions from app.js
- Update documentation with new DM workflow
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>