Tooltips don't work on touchscreens. Added a popup that appears on
tap/click, shows the full path, and auto-dismisses after 4 seconds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Show repeater path codes in sent message echo badge (e.g., "2 (5e, d1)")
- Capture and display route path for incoming messages in message meta
- Persist all echo data to .echoes.jsonl (survives container restarts)
- Load echo data from disk on startup with 7-day retention and compaction
- Combine sent echo and incoming path data in single /echo_counts response
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add sender name above outgoing messages in group chat
- Display emoji-only messages in larger font size
- Fix leading space before text in quoted replies
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Auto-detect #channel names in messages and convert to clickable links
- Click existing channel: switch to it via channel selector
- Click non-existing channel: join via API, then switch
- Green styling to distinguish from blue @mentions
- Only active in channel context (not in DMs)
Co-Authored-By: Claude Opus 4.5 <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>
Track how many repeaters heard and forwarded sent channel messages,
similar to the Meshcore mobile app's "Heard X repeats" feature.
- Bridge: Detect GRP_TXT echoes from stdout, track unique paths
- Bridge: New /register_echo and /echo_counts API endpoints
- API: Register messages for echo tracking after send
- API: Merge echo counts into /api/messages response
- Frontend: Display green badge with broadcast icon next to Resend button
- CSS: Echo badge styling with dark mode support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Semi-transparent button appears when user scrolls up
- Positioned at bottom-right of messages container
- Clicking scrolls to latest messages and hides button
- Smooth fade-in/out animation
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>
When user types @ in the message input, a dropdown appears with contacts
list. The list filters as user types (matches any part of name, not just
prefix). User can navigate with arrow keys, select with Enter/Tab/click,
or dismiss with Escape.
- Add mentions popup HTML to index.html
- Add mentions CSS styling (responsive, scrollable)
- Add JavaScript logic: detection, filtering, keyboard nav, insertion
- Contacts cached for 60s, loaded on input focus
- Closes emoji picker when mentions opens (avoid overlap)
- Inserts selected contact as @[username] format
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Convert type filter checkboxes to clickable toggle badges on the Map
modal (accessible from main menu). Same UX pattern as pending contacts:
- Active: colored background, white text
- Inactive: colored text/border, white background
Updated in both base.html and contacts_base.html for consistency.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /api/check-update endpoint that queries GitHub API
- Compare current commit hash with latest on dev branch
- Add check button next to version in menu
- Show spinning icon during check, green checkmark when done
- Display "Update available" link when newer version exists
- Handle rate limits and network errors gracefully
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Reduce emoji avatar border from 2.5px to 1.5px
- Reduce horizontal padding from 0.5rem to 0.25rem
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Emoji avatars are now displayed with a colored ring/outline
instead of filled background for better readability.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Reduce horizontal padding in messages container
- Add colored circle background to emoji avatars
- Fix vertical alignment of avatar with sender name
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add mini avatars next to sender names in channel chat
- Extract emoji from username for avatar (first emoji only)
- Use initials for users without emoji (1-2 letters)
- Generate consistent colors based on username hash
- Move sender name outside message bubble (MeshCore style)
- Add responsive styles for mobile devices
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Changed quote format to: @[Username]: »quoted text«
- Added processQuotes() to detect and style »text« patterns
- Quote styling: italic, gray background, left border
- Different styling for own messages vs others
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use CircleMarker with different colors per contact type:
- CLI (blue), REP (green), ROOM (purple), SENS (orange)
- Add type filter checkboxes in map modal header
- Dynamically update markers when filters change
- Hide filter panel for single contact view
- Reduce message action buttons to 32x32px
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove text labels from Reply and Map buttons
- Add consistent 36x36px square buttons with icons only
- Add tooltips for accessibility
- Prepare for adding more action buttons in the future
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace Google Maps with Leaflet + OpenStreetMap (free, no API key)
- Add Map button in main menu to show all contacts with GPS
- Add Map button on message bubbles (next to Reply) for senders with GPS
- Contact Management Map buttons now open modal instead of new tab
- Lazy map initialization with proper Bootstrap modal handling
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements Progressive Web App notification capabilities:
- Service Worker foundation for PWA installability and offline support
- Browser notification toggle in side menu with permission management
- Local notifications triggered on new messages (channels, DMs, pending)
- App Badge API integration showing total unread count on app icon
- Smart notification logic (only when app hidden, only for NEW messages)
- Graceful degradation for unsupported browsers
Technical details:
- Service Worker with network-first fetch strategy for dynamic content
- Notification permission stored in localStorage (mc_notifications_enabled)
- Delta-based notification tracking (prevents spam on page load)
- Notification tag prevents duplicate alerts
- App badge auto-clears when user returns to app
Limitations (documented):
- Android may freeze background JS after 5-10 minutes (OS behavior)
- Full "wake device" support requires Web Push API (future enhancement)
- Works best for active users who check app regularly
Files modified:
- app/static/js/sw.js (new)
- app/templates/base.html
- app/static/js/app.js
- app/static/js/dm.js
- app/static/manifest.json
- app/static/css/style.css
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Change .fab-badge-pending from orange to red
- Change .fab-badge-dm from green to red
- Use same color as notification bell badge (#dc3545)
- Improves visibility especially on green DM button
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add badge for pending contacts on Contact Management FAB button (orange)
- Move DM badge from notification bell to Direct Messages FAB button (green)
- Add universal updateFabBadge() function for all FAB badges
- Add updatePendingContactsBadge() function with localStorage type filter support
- Update badges every 10 seconds with auto-refresh
- Update badges when modals are closed
Frontend changes:
- New CSS classes: .fab-badge, .fab-badge-pending, .fab-badge-dm
- position: relative added to .fab for badge positioning
- Removed DM badge code from notification bell
- Added modal event handlers for badge updates
Backend: No changes (uses existing /api/contacts/pending endpoint with types parameter)
This improves UX by showing notification counts directly on relevant FAB buttons
instead of crowding the notification bell. DM badge moved from bell to DM button,
and new pending contacts badge added to Contact Management button.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previous sticky bar implementation took up vertical space in layout,
making viewport issues worse. Replaced with proper floating action
buttons that don't affect layout.
Changes:
- Remove sticky bar from index.html
- Add FAB container with fixed position (no layout impact)
- Two circular buttons: DM (green) and Contacts (blue)
- position: fixed, right: 16px, top: 80px
- z-index: 900 (lower than offcanvas menu 1045)
- Beautiful gradients and shadows
- Hover/active animations (scale transform)
- Mobile responsive (smaller on <768px)
Features:
- No vertical space taken (fixed position)
- Covered by offcanvas when menu opens (z-index hierarchy)
- Always visible in corner
- Uses navigateTo() for clean navigation
Test scenario:
1. Click FAB buttons (bypass offcanvas menu completely)
2. Navigate to DM / Contact Management
3. Return to main page
4. Check if status bar corruption still occurs
If FABs work: problem is in offcanvas cleanup
If FABs fail: problem is deeper in viewport/layout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Added semi-transparent floating buttons under navbar to test
if viewport corruption is caused by offcanvas menu or navigation itself.
Changes:
- Add floating-test-buttons div in index.html
- Two buttons: DM and Contacts (using navigateTo())
- Sticky position under navbar
- Semi-transparent background with backdrop blur
- Centered layout with gap between buttons
Test scenario:
1. Click floating buttons (bypass offcanvas menu)
2. Navigate to DM / Contact Management
3. Return to main page via Home button
4. Check if status bar is still visible
If floating buttons work correctly:
- Problem is in offcanvas menu cleanup
- Can keep these buttons as permanent quick navigation
If floating buttons also cause corruption:
- Problem is deeper (viewport/layout issue)
- Need different approach
🤖 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>
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>
- 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>
- Parse PRIV (incoming) and SENT_MSG (outgoing) message types
- Add DM API endpoints: conversations, messages, updates
- Implement conversation grouping by pubkey_prefix or name
- Add timeout-based delivery status (pending → timeout)
- Add DM modal with conversation list and thread views
- Add dual notification badge (blue=channels, green=DM)
- Add DM button next to Reply on channel messages
- Include message deduplication for both incoming and outgoing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change message byte limit from 200 to 140 bytes
- Remove keyboard hint text to save space
- Simplify navbar to show only notification bell and channel selector
- Add slide-out offcanvas menu for less-used options:
* Refresh Messages
* Manage Channels
* Message History (archive selector)
* Settings
- Increase font sizes in dropdowns and menu for better readability
- Add icons and text labels to all menu items
- Auto-close menu after selecting options
- Update clipboard API to modern navigator.clipboard with fallback
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replaces the blind 60-second refresh with a smart polling system that only updates the UI when new messages actually arrive.
Key improvements:
- Lightweight update checks every 10 seconds (vs full refresh every 60s)
- Chat view refreshes only when new messages appear on active channel
- Notification bell with global unread count across all channels
- Per-channel unread badges in channel selector (e.g., "Malopolska (3)")
- Last-seen timestamp tracking per channel with localStorage persistence
- Bell ring animation when new messages arrive
Backend changes:
- New /api/messages/updates endpoint for efficient update polling
- Returns per-channel update status and unread counts
Frontend changes:
- Smart auto-refresh mechanism with conditional UI updates
- Unread message tracking system with localStorage
- Notification bell UI component with badge
- Channel selector badges for unread messages
- CSS animations for bell ring effect
This dramatically reduces network traffic and server load while providing better UX through instant notifications about activity on other channels.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Improve UI layout on mobile devices (screens < 768px):
Navbar optimizations:
- Hide "Refresh" text on mobile, show only icon to save space
- Reduce gap between navbar elements (0.25rem instead of 0.5rem)
- Decrease min-width for channel/date selectors (80px vs 120px/150px)
- Smaller font-size (0.75rem) and padding for select elements
- Compact button sizes (0.25rem padding)
Modal optimizations:
- Reduce modal margins (0.5rem) for better mobile fit
- Smaller modal-body padding (0.75rem)
- Compact channel keys with smaller font (0.65rem) and word-break
- Reduce list-group-item padding (0.5rem)
- Stack "Add New" and "Join Existing" buttons vertically on very small screens (<400px)
Files changed:
- app/static/css/style.css: Added mobile-specific CSS rules in @media query
- app/templates/base.html: Wrapped "Refresh" text in <span class="btn-text">
Testing: Verified on mobile viewport (iPhone, Android simulators)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixed mobile browser viewport height issues where status bar and hint text were hidden:
CSS changes:
- Use 'height: 100dvh' (dynamic viewport height) for mobile browsers
- Fallback to '100vh' for older browsers
- Added 'min-height: 0' to main flex container (critical for flex children)
HTML changes:
- Added 'viewport-fit=cover' to meta tag (notched displays)
- Improved flexbox structure in index.html
- Added inline 'min-height: 0' on flex-grow-1 row (prevents overflow)
The 'dvh' unit dynamically adjusts to browser chrome (URL bar) visibility,
preventing layout shifts when scrolling on mobile. The min-height: 0 fix
ensures flex children properly shrink when needed.
This should fix the issue where bottom status bar disappears on mobile
and top navbar disappears after sending a message.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Improved mobile user experience:
- Shortened hint text: 'Shift+Enter: new line, Enter: send' (was 'Press Shift+Enter for new line, Enter to send')
- Reduced form padding on mobile (0.5rem instead of default)
- Made status bar more compact on mobile (smaller padding and font)
- Better vertical space utilization on small screens
This should make the status bar visible on mobile devices and improve overall usability on phones.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented core backend functionality:
- Flask application structure with blueprints
- Configuration module loading from environment variables
- MeshCore CLI wrapper with subprocess execution and timeout handling
- Message parser for .msgs JSON Lines file format
- REST API endpoints (messages, status, sync, contacts cleanup)
- HTML views with Bootstrap 5 responsive design
- Frontend JavaScript with auto-refresh and live updates
- Custom CSS styling for chat interface
API Endpoints:
- GET /api/messages - List messages with pagination
- POST /api/messages - Send message with optional reply-to
- GET /api/status - Device connection status
- POST /api/sync - Trigger message sync
- POST /api/contacts/cleanup - Remove inactive contacts
- GET /api/device/info - Device information
Features:
- Auto-refresh every 60s (configurable)
- Reply to messages with @[UserName] format
- Toast notifications for feedback
- Settings modal for contact management
- Responsive design (mobile-friendly)
- Message bubbles with sender, timestamp, SNR, hop count
Ready for testing on production server (192.168.131.80:5000)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>