- Add -u flag to Python for unbuffered logging to journald
- Configure git safe.directory automatically during install
- Revert test marker from base.html
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds webhook-based update system that allows triggering updates
directly from the mc-webui menu. Includes:
- Webhook server (updater.py) on port 5050
- Systemd service and install script
- API proxy endpoints for container-to-host communication
- Update modal with progress tracking and auto-reload
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- version.py now captures and exports GIT_BRANCH
- Display branch badge next to version in menu (e.g., "2026.01.20+abc1234 [dev]")
- /api/version now returns branch field
- /api/check-update uses frozen branch instead of hardcoded "dev"
- Allows proper update checking for both dev and main branches
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>
- Rename Settings to Device Info with new cpu icon
- Display device parameters in readable table format
- Add copy-to-clipboard buttons for Name and Public Key
- Add map button for device location coordinates
- Show human-readable parameter names and values
- Hide telemetry parameters (not commonly needed)
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>
- Add Leaflet CSS/JS and map modal to contacts_base.html
- Add showContactOnMap function to contacts.js (contacts page has separate template)
- Load contactsGeoCache before messages to ensure Map buttons appear on bubbles
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>
Browser blocks mixed content (HTTPS page -> HTTP WebSocket on port 5001).
Solution: Route WebSocket through main Flask app which goes through
existing HTTPS reverse proxy.
- Add Flask-SocketIO to main mc-webui app
- WebSocket handler proxies commands to bridge via HTTP
- Remove port 5001 external exposure (no longer needed)
- Remove duplicate title from console header
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Flask-SocketIO backend with gevent for real-time communication
- Create chat-style console UI showing only user's command responses
- WebSocket commands tracked separately from HTTP API (ws_ prefix)
- Console accessible from main menu as fullscreen modal
- Command history navigation with arrow keys
- Auto-reconnection on disconnect
- Update service worker cache for offline support
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>
Implement complete offline functionality by hosting Bootstrap CSS/JS and icons locally, eliminating dependency on external CDNs. This ensures the application works reliably in internet-free environments, perfect for mesh networks in remote or emergency scenarios.
Changes:
- Download and host Bootstrap 5.3.2 CSS/JS locally (~307 KB total)
- Download and host Bootstrap Icons 1.11.2 CSS and fonts (~300 KB)
- Update base.html to use local library paths instead of CDN URLs
- Enhance Service Worker with hybrid caching strategy:
- Cache-first for vendor libraries (static, unchanging)
- Network-first for app code (dynamic, needs updates)
- Bump Service Worker cache version to v2
- Add vendor libraries to pre-cache list for instant offline availability
- Update README.md with offline support documentation
- Update project structure documentation
Benefits:
- Works without internet connection (no CDN dependency)
- Faster initial page load (no external requests)
- Reliable operation during internet outages
- Perfect for air-gapped and remote mesh network deployments
File sizes:
- Bootstrap CSS: ~227 KB
- Bootstrap JS: ~80 KB
- Bootstrap Icons CSS: ~98 KB
- Bootstrap Icons Fonts: ~300 KB (woff2 + woff)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changes:
- Convert all Polish UI text to English (buttons, labels, messages)
- Menu: "Powiadomienia" → "Notifications"
- Status badges: "Włączone/Wyłączone/Zablokowane" → "Enabled/Disabled/Blocked"
- Toast messages: all notification messages translated to English
- Notification bodies: "Nowe: X kanały" → "New: X channels"
- Fix notification toggle UI bug
- Badge now correctly shows "Disabled" when user turns off notifications
- Previously showed "Enabled" whenever permission was granted (ignoring localStorage)
- Now checks both permission AND localStorage state
This ensures the UI respects the international nature of the project
and fixes the toggle state display issue found during Android testing.
Files modified:
- app/templates/base.html
- app/static/js/app.js
- app/static/js/dm.js
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 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>
- 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>
Removed Node Discovery feature that was experiencing persistent timeout
issues. Feature attempted to scan mesh network for nearby repeaters but
consistently failed due to bridge timing constraints.
Changes:
- Remove node_discover() function from cli.py
- Remove 'node_discover' from SPECIAL_COMMANDS in api.py
- Remove Discover Nodes button and modal from base.html
- Remove discoverNodes() and displayNodeDiscoveryResults() from app.js
- Remove Discover Nodes documentation from README.md
IMPORTANT: Advert message cleanup ("Advert sent") is preserved and
working correctly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Integrate pending contacts refactoring with JSON format
- Resolve conflict in special commands handler
- Keep node_discover functionality from main
- Add filtering and batch approval from dev
- Change backend from 'pending_contacts' to '.pending_contacts' command
- Parse JSON response with enriched contact data (type, GPS, timestamps)
- Add type badges (CLI/REP/ROOM/SENS) with color coding
- Add Map button for contacts with GPS coordinates
- Add type filter (checkboxes, default: CLI only) and name search
- Add batch approval with confirmation modal
- Follow existing contacts UI pattern for consistency
- Mobile-first design with touch-friendly controls
Breaking change: /api/contacts/pending response format changed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implemented new "Discover Nodes" feature in Network Commands menu:
- Added .node_discover command to meshcli wrapper (cli.py)
- Created interactive modal with sortable table showing nearby repeaters
- Displays SNR, RSSI, path length, and signal quality indicators
- Added refresh functionality to rescan for nodes
Fixed advert notification to show clean "Advert sent" message
instead of full meshcli output.
Technical changes:
- app/meshcore/cli.py: Added node_discover() function with JSON parsing
- app/routes/api.py: Updated SPECIAL_COMMANDS and execute_special_command()
to handle node_discover return type and clean advert message
- app/templates/base.html: Added "Discover Nodes" menu button and modal
- app/static/js/app.js: Added discoverNodes() and displayNodeDiscoveryResults()
- README.md: Added documentation for Discover Nodes feature
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed viewport fix approach to be less invasive:
- Removed document.body.style.height modification
- Use document.documentElement.offsetHeight instead
- Trigger resize event instead of modifying DOM
- Increased delay from 100ms to 150ms for better stability
This should prevent potential conflicts with channel loading and
other page initialization code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Two critical fixes:
1. DM Badge Sync Issue:
- After closing DM modal, badge showed correct count for 10 seconds
- Then auto-refresh (running every 10s) used stale dmLastSeenTimestamps
- Solution: Call loadDmLastSeenTimestampsFromServer() before updating badge
- This ensures app.js auto-refresh uses current server state
2. Android PWA Viewport Corruption:
- Viewport corrupted on F5 refresh in Android PWA mode
- Status bar content hidden under system UI
- Solution: Force viewport recalculation on page load
- Scrolls to top and forces reflow after 100ms delay
Testing needed on Android PWA to verify both fixes work correctly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed DM badge update logic to use /api/dm/conversations endpoint
instead of /api/dm/updates?last_seen={} which was causing incorrect
unread counts (showing 99+, then 2, when there should be 0).
The new approach:
- Fetches all conversations with their unread counts
- Sums up unread messages across all conversations
- Updates badge without full page reload (avoiding viewport corruption)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Replace full page reload with targeted badge update when DM modal closes.
This prevents the viewport corruption issue that was reintroduced by
window.location.reload() in the previous commit.
Problem:
- Previous solution used window.location.reload() to update badges
- This caused viewport corruption (status bar hidden under system UI)
- Same issue we solved by using modals instead of navigation
New solution:
- Fetch latest unread counts from /api/dm/updates when modal closes
- Update only the green DM badge (notification-badge-dm) on notification bell
- No page reload = no viewport corruption
- Keeps modal solution benefits intact
Changes:
- Remove window.location.reload() from hidden.bs.modal event listener
- Add async fetch to /api/dm/updates endpoint
- Update notification-badge-dm element directly using DOM manipulation
- Handle badge creation/update/hiding based on unread count
Result:
- DM badges update correctly after closing modal
- No viewport corruption
- Fast, smooth user experience
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add event listener for DM modal close event that reloads the main page.
This ensures that unread DM badges are properly updated after user reads
messages in the DM modal.
Previously, when using the "Home" button, the page would reload via navigateTo('/').
Now with the "Close" button, the modal just closes without reloading, leaving
stale unread counts in the notification badges.
Changes:
- Add 'hidden.bs.modal' event listener to dmModal
- Call window.location.reload() when DM modal is closed
- This updates all unread badges on the main page
Note: This should not cause viewport corruption issues because:
1. Modal is fully closed before reload
2. No offcanvas or other Bootstrap components are active
3. Regular page reload, not navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
After removing navbars from modal embedded pages, add proper page headers
and optimize button layout for better mobile UX.
Changes to Pending Contacts page:
- Add H4 page header "Pending Contacts" with badge counter
- Replace two large buttons (Contact Management + Home) with smaller ones
- Change Home button to Refresh button (more useful in modal context)
- Use btn-sm for compact button sizes
- Replace back-buttons class with d-flex gap-2 for simpler layout
Changes to Existing Contacts page:
- Add H4 page header "Existing Contacts" with counter badge
- Same button improvements as Pending Contacts
- Replace Home button with Refresh button
Changes to Contact Management settings:
- Set default "Days of Inactivity" value to 0 (ignore) instead of 2
- This is safer default as 0 means "do not filter by inactivity"
Result:
- Clear page headers indicate current location in modal
- Smaller, more compact buttons save screen space
- Refresh buttons are more useful than Home (which is Close in modal)
- Safer default value for cleanup prevents accidental bulk deletions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add custom CSS overrides to ensure fullscreen modals fill the entire viewport
without any gaps on top, left, right, or bottom edges.
Changes:
- Force modal-dialog to use 0 margin and 100vw/100vh dimensions
- Remove border and border-radius from modal-content
- Set overflow hidden on modal-body to prevent scrollbars
- Use !important to override Bootstrap default styles
This fixes the issue where modals had visible gaps on the top and left sides
while content was slightly cut off on the right and bottom edges.
🤖 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>
Implement modal dialogs to resolve PWA viewport corruption issues on Android.
When navigating between pages using window.location.href, the viewport height
calculation becomes corrupted, causing the status bar to be hidden under system UI.
Changes:
- Add fullscreen modals for Direct Messages and Contact Management in index.html
- Configure FAB buttons to open modals instead of navigating to new pages
- Add JavaScript to reload iframe content when modals are opened (ensures fresh data)
- Remove DM and Contact Management from offcanvas menu to avoid duplication
- Both modals use iframes to embed existing /dm and /contacts/manage pages
- Modal headers styled with appropriate colors (green for DM, blue for Contacts)
This approach bypasses the viewport corruption issue since modals don't trigger
the problematic navigation flow that occurs with page changes in PWA mode.
🤖 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>
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>
Remove impractical path length filter from contact cleanup feature.
The out_path_len parameter is rarely useful as most contacts have
value -1 (no route), making this filter unpractical for real-world use.
Changes:
- Remove path_len parameter from backend API endpoints
- Remove path length input field from HTML template
- Remove path_len collection from JavaScript code
- Update documentation (CLAUDE.md, README.md)
- Simplify cleanup filter to: name, types, date field, and days
Backend changes:
- Update _filter_contacts_by_criteria() to remove path_len logic
- Remove path_len validation from both endpoints
- Update API documentation in docstrings
Frontend changes:
- Remove Path Length input section from contacts-manage.html
- Remove path_len from collectCleanupCriteria() function
Documentation changes:
- Update API endpoint descriptions in CLAUDE.md
- Update cleanup instructions in README.md
- Remove path_len from example use cases
🤖 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>
Problem: #pendingList had max-height: 200px showing only 1-2 contacts
with huge unused whitespace below.
Solution:
- Desktop: height calc(100vh - 280px) - slightly more than existingList
due to extra description text
- Mobile: height calc(100vh - 320px) - adjusted for mobile layout
- Changed from max-height to height for consistent behavior
- Added min-height: 300px for safety
Now pending contacts list properly utilizes available screen space.
- 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>
Problem: List was too tall causing the entire page to scroll,
hiding navigation buttons at the top when scrolling to bottom.
Solution:
- Changed from max-height to height for #existingList
- Desktop: calc(100vh - 260px) - slightly smaller to fit all elements
- Mobile: calc(100vh - 300px) - adjusted for mobile layout
Now only the contact list scrolls internally, while navigation
buttons remain visible at the top.
Problem: #existingList ID selector had higher specificity than
.contacts-list-fullscreen class, and max-height values were limiting
the list height regardless of the class height setting.
Changes:
- Desktop: #existingList max-height calc(100vh - 400px) → calc(100vh - 240px)
- Mobile: #existingList max-height calc(100vh - 450px) → calc(100vh - 280px)
This should now properly utilize available screen space.
Changed height calculation:
- Desktop: calc(100vh - 300px) → calc(100vh - 240px)
- Mobile: calc(100vh - 340px) → calc(100vh - 280px)
This should eliminate the ~20% unused whitespace at the bottom
of the contact lists.
Adjusted .contacts-list-fullscreen height to better utilize available
screen space by increasing the subtracted value from 200px to 300px
on desktop and from 150px to 340px on mobile.
This accounts for:
- Navbar (~56px)
- Main container padding (~48px)
- Back buttons (~60px)
- Search toolbar (~50px)
- Filter/sort toolbar (~60px)
- Margins between elements (~26px)
Fixes blank space at bottom of Existing Contacts and Pending Contacts pages.
- Add CSS override to enable scrolling on Contact Management pages
(override global overflow: hidden from style.css)
- Move cleanup description to tooltip on info icon for consistency
with Manual approval toggle pattern
- Add flexbox layout to cleanup section h6 for proper icon alignment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Compact Manual Approval and Pending Contacts sections to give more
space for Existing Contacts list, which is the primary focus.
Changes to Manual Approval section:
- Convert from full section to single-line compact control
- Replace description text with tooltip icon (hover for info)
- Reduce vertical space by ~70px
Changes to Pending Contacts section:
- Reduce header size from h5 to h6
- Compact empty state (1rem padding vs 3rem)
- Reduce icon size (1.5rem vs 3rem)
- Limit list height to 200px (was 600px)
- Remove "Refresh" text from button (icon only)
Changes to Existing Contacts section:
- Dynamic height: calc(100vh - 400px) with 300px minimum
- Adapts to viewport height automatically
- On mobile: calc(100vh - 450px) for better fit
- More contacts visible without scrolling
Other improvements:
- Initialize Bootstrap tooltips in contacts.js
- Smaller fonts and margins throughout
- Better vertical space distribution
Result: ~150px more space for main contacts list on desktop,
~200px more on mobile. Tooltip provides same info without clutter.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fix scrolling issue where contact lists with many items (263/350)
couldn't be scrolled on desktop or mobile devices.
Changes:
- Add max-height: 600px to #existingList and #pendingList
- Enable vertical scrolling with overflow-y: auto
- Add smooth scrolling for mobile with -webkit-overflow-scrolling
- Style custom scrollbar (8px, rounded, gray) for better UX
Tested: Lists now show ~8-10 contact cards at once with scrollbar
appearing when needed. Works with mouse wheel and touch gestures.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>