Commit Graph

79 Commits

Author SHA1 Message Date
MarekWo a4ef0fd497 feat: Use local timezone for scheduled cleanup instead of UTC
The scheduler now uses the timezone configured in .env (TZ variable)
instead of hardcoded UTC:
- Add get_local_timezone_name() helper to manager.py
- BackgroundScheduler uses system local timezone
- API returns timezone field in cleanup-settings response
- Frontend displays timezone next to hour selector and in status text
- Updated documentation to reflect timezone behavior

This makes the cleanup hour more intuitive for users in non-UTC timezones.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 10:46:08 +01:00
MarekWo da31ab8794 feat: Add configurable hour for scheduled contact cleanup
Allow users to select the hour (0-23 UTC) when automatic contact
cleanup runs:
- Add hour selector dropdown in Advanced Filters (disabled until enabled)
- Hour field saved to .webui_settings.json with cleanup_settings
- API validates hour (0-23), scheduler uses CronTrigger with hour param
- Status text shows configured hour (e.g., "Enabled (runs daily at 03:00 UTC)")
- Documentation updated in user-guide.md

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 10:22:02 +01:00
MarekWo a23eb2a5f4 feat: Add automatic scheduled contact cleanup
Add auto-cleanup feature that runs daily at 01:00 UTC using APScheduler:
- New cleanup settings stored in .webui_settings.json (enabled, types, date_field, days, name_filter)
- API endpoints: GET/POST /api/contacts/cleanup-settings
- Scheduler functions: _cleanup_job(), schedule_cleanup(), init_cleanup_schedule()
- UI toggle in Advanced Filters with validation (requires days > 0)
- Debounced auto-save for filter criteria changes
- Protected contacts are excluded from auto-cleanup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 21:49:27 +01:00
MarekWo bbc8b1db25 ui: Replace Copy Key button with clickable key
- Remove separate "Copy Key" button
- Make public key prefix clickable to copy
- Add fallback for HTTP contexts (execCommand)
- Add hover and copied state styling

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 20:16:12 +01:00
MarekWo 51c05f7794 feat: Add contact protection feature
Add ability to protect contacts from accidental deletion via Contact
Cleanup tool. Protected contacts are stored locally in settings file.

Changes:
- Add GET /api/contacts/protected endpoint
- Add POST /api/contacts/<key>/protect toggle endpoint
- Add is_protected field to /api/contacts/detailed response
- Exclude protected contacts from cleanup preview and deletion
- Add Protect toggle button to Existing Contacts list
- Show lock icon for protected contacts
- Disable Delete button for protected contacts

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 14:30:38 +01:00
MarekWo d0f1aae963 ui: Replace map filter checkboxes with clickable badges
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>
2026-01-23 08:58:32 +01:00
MarekWo a9dd31b86e ui: Optimize Contact Management for mobile screens
- Replace type filter checkboxes with clickable toggle badges in Pending
  Contacts (CLI/REP/ROOM/SENS) - more compact and better mobile UX
- Make Pending Contacts buttons (Approve, Map, Copy Key) smaller and
  uniform, matching Existing Contacts button style
- Optimize Existing Contacts filter toolbar to fit in one row on mobile
  (narrower dropdown, more compact sort buttons)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 08:44:55 +01:00
MarekWo a764c66070 fix: Improve update UI and install script
- Add sudo to journalctl command in install.sh help text
- Move "Update now" link below version number to prevent line wrap
- Add "What's new?" link in update modal pointing to GitHub commits

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 08:18:14 +01:00
MarekWo df852a1a80 feat: Add remote update capability from web GUI
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>
2026-01-21 16:58:05 +01:00
MarekWo f36c2eb3c8 feat: Add update checker to verify new versions on GitHub
- 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>
2026-01-20 17:14:59 +01:00
MarekWo 07de51e56a fix: Use colored border instead of fill for emoji avatars
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>
2026-01-20 07:56:12 +01:00
MarekWo 5582f85ad0 feat: Add avatar circles to channel messages
- 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>
2026-01-20 07:38:15 +01:00
MarekWo 731d4a9d9b refactor: Remove colon from quote format
Format changed from @[User]: »text« to @[User] »text«
Guillemets alone are sufficient to separate the quote.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 11:01:50 +01:00
MarekWo 5d01f90ba1 refactor: Hide guillemets and add line break after quote
- Guillemets (» «) no longer displayed - styling is sufficient
- Added line break after quoted text for better readability
- Raw message still contains guillemets for compatibility

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:43:45 +01:00
MarekWo b2418a50d3 feat: Improve quote format with guillemets and styling
- 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>
2026-01-19 10:29:59 +01:00
MarekWo 936698ca46 feat: Add Quote button to chat messages
Adds a Quote button next to Reply that allows quoting a message.
- Messages ≤20 bytes are quoted in full
- Longer messages are truncated with "..."
- Format: @[Username] "quoted text"
- Uses UTF-8 byte counting for accurate truncation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 10:15:35 +01:00
MarekWo ffbcd8eead fix: Remove whitespace from image thumbnail template literal
The template literal had newlines and spaces that were preserved by
white-space: pre-wrap CSS, causing unwanted gaps before and after
image previews in chat messages.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:48:17 +01:00
MarekWo 039433a8a2 fix: Remove extra spacing before image preview in group chat
Changed message content container from <p> to <div> to fix invalid HTML
when image previews are embedded. The <p> tag cannot contain block-level
elements like <div>, causing browsers to auto-close the paragraph and
create unwanted spacing between text and image preview.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 09:40:14 +01:00
MarekWo b5cdce18f2 feat: Replace Settings with Device Info modal
- 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>
2026-01-18 17:02:42 +01:00
MarekWo 9bc27042da fix: Re-render messages after geo cache loads to show Map buttons
Messages are now displayed immediately, then re-rendered once geo cache
is ready so Map buttons appear for contacts with GPS coordinates.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 16:28:30 +01:00
MarekWo 7d0fb61533 perf: Don't block UI on geo cache loading
Geo cache now loads fully in background without blocking setupAutoRefresh().
UI is ready as soon as messages are displayed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 13:25:01 +01:00
MarekWo 9e36c17f77 perf: Optimize channel chat loading time
- Add 60s cache for /api/contacts/detailed (reduces 4 USB calls to 0)
- Optimize /api/messages/updates to read file once instead of N×2 times
- Parallelize initialization: timestamps loaded together, messages and
  geo cache loaded in parallel
- Defer checkForUpdates() to after messages are displayed
- Remove blocking checkForUpdates() from loadChannels()
- Add cache invalidation for contacts on add/delete operations
- Add performance timing logs to browser console

Expected improvement: ~10-20s → ~2-3s initial load time

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 13:05:03 +01:00
MarekWo d395656445 feat: Add colored markers and type filtering on contact map
- 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>
2026-01-16 08:21:11 +01:00
MarekWo f00234af88 style: Make message action buttons icon-only with uniform size
- 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>
2026-01-16 07:59:18 +01:00
MarekWo 6cb777e90c fix: Map buttons not working in contacts page and message bubbles
- 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>
2026-01-16 07:51:00 +01:00
MarekWo 72da96e647 feat: Add Leaflet map for contact locations
- 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>
2026-01-15 22:46:36 +01:00
MarekWo b00419ce25 fix: Update filtered count badge when type filter returns empty results
The filteredCountBadge in "Add Filtered" button was not updating when
unchecking type filter checkboxes resulted in zero matching contacts.
Now resets badge to '0' and clears filteredPendingContacts array.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 19:23:40 +01:00
MarekWo c376ecff30 fix: Proxy console WebSocket through main app for HTTPS compatibility
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>
2026-01-09 13:18:56 +01:00
MarekWo a5f7fd59e6 feat: Add interactive meshcli console with WebSocket support
- 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>
2026-01-09 08:27:42 +01:00
MarekWo 783a00c798 feat: Increase channel limit to 40 with soft warning at 7+
- Changed hard limit from 8 to 40 channels (most LoRa devices support up to 40)
- Added soft warning when exceeding 7 channels (some devices may have lower limits)
- Warning displayed in UI after successful channel creation/join
- Updated error message to reflect new 40-channel maximum

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 10:39:52 +01:00
MarekWo 4bd6a681db feat: Add local emoji picker for complete offline independence
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>
2026-01-05 21:26:26 +01:00
MarekWo 964d88a14a feat: Add full offline support with local Bootstrap libraries
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>
2026-01-05 20:46:27 +01:00
MarekWo a74ed136ce fix: Implement proper toggle logic for notification enable/disable
Previous implementation always disabled notifications when permission
was granted, regardless of current state. This made it impossible to
re-enable notifications after disabling them.

Now properly checks localStorage state and toggles:
- If currently enabled → disable (show "Notifications disabled")
- If currently disabled → enable (show "Notifications enabled")

This fixes the issue where clicking the toggle when disabled would
show "Notifications disabled" instead of enabling them.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-05 15:05:48 +01:00
MarekWo 77c0a33da6 fix: Change UI language to English and fix notification toggle bug
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>
2026-01-05 14:45:38 +01:00
MarekWo ecb3618da7 feat: Add PWA notification support with badge counters
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>
2026-01-05 12:29:17 +01:00
MarekWo 34ab437390 feat: Remember last selected DM conversation
Add localStorage persistence for Direct Messages page to remember and restore the last selected conversation when user returns to the page.

Changes:
- Save selected conversation to localStorage when user selects a conversation
- Restore last conversation on page load (if no URL parameter provided)
- Clear localStorage when user returns to empty state
- Updated README.md with persistence documentation
- Priority: URL parameter > localStorage > empty state

This improves UX by maintaining conversation context across page navigation, similar to how the main page remembers the selected channel.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-04 13:29:04 +01:00
MarekWo 7cee262971 feat: Add notification badges to FAB buttons
- 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>
2026-01-04 11:51:07 +01:00
MarekWo 009d3254b8 feat: Add persistent type filter for pending contacts
- Add query parameter 'types' to GET /api/contacts/pending endpoint
- Save user's type filter selection to localStorage (pendingContactsTypeFilter)
- Restore filter on page reload (Pending Contacts page)
- Contact Management badge shows count based on saved filter
- Default filter: CLI only (type=1)

Frontend changes:
- Add localStorage functions (save/load/set checkboxes)
- Modify loadPendingContacts() to use types from checkboxes
- Modify loadContactCounts() to use filter from localStorage
- Checkbox changes trigger save to localStorage + API reload

Backend changes:
- Add 'types' query parameter to GET /api/contacts/pending
- Filter pending contacts by type before returning
- Validate types parameter (must be 1-4)

This allows users to customize which contact types they want to see
in pending contacts list, and the selection persists across sessions.
The same filter is used consistently across all pages (Pending Contacts
page and Contact Management page).

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-04 11:07:31 +01:00
MarekWo 66f16609e5 fix: Remove non-functional Node Discovery feature
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>
2026-01-03 10:46:05 +01:00
MarekWo df26b44df0 Merge branch 'dev' into main
- 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
2026-01-03 10:27:54 +01:00
MarekWo fd2b9b1592 feat: Refactor pending contacts to JSON format with filtering and batch approval
- 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>
2026-01-03 09:56:56 +01:00
MarekWo 75ec789fba feat: Add node discovery feature and improve advert notification
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>
2026-01-02 14:34:02 +01:00
MarekWo bc4d29e369 fix: Add viewport recalculation on main page load (PWA fix)
The main page (app.js) was missing viewport recalculation logic
that was already present in dm.js, causing layout corruption when
returning from other pages in PWA mode.

Changes:
- Add viewport recalculation in DOMContentLoaded:
  - window.scrollTo(0, 0) - reset scroll position
  - window.dispatchEvent(new Event('resize')) - trigger reflow
  - document.body.offsetHeight - force layout recalculation

- Add pageshow event listener:
  - Handles page restoration from browser cache (Back button)
  - Recalculates viewport when event.persisted is true

- Add visibilitychange event listener:
  - Handles PWA returning from background
  - 100ms delay to ensure proper timing

This fixes the issue where:
1. User opens menu on main page
2. Navigates to Contact Management
3. Clicks Home button to return
4. Status bar is hidden under Android system buttons

The viewport wasn't being recalculated after navigation,
leaving the layout with incorrect heights from cached state.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 18:12:08 +01:00
MarekWo 11935d419a fix: Resolve PWA viewport corruption on page navigation
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>
2026-01-01 17:31:44 +01:00
MarekWo ca2e2178c9 refactor: Unify channel and DM interface styling
- 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>
2026-01-01 16:35:59 +01:00
MarekWo 5518c622bc feat: Implement server-side read status for cross-device synchronization
Replace localStorage-based message read tracking with server-side storage
to enable unread badge synchronization across all devices and browsers.

Changes:
- Add read_status.py module for server-side read status management
- Add GET /api/read_status endpoint to fetch read status
- Add POST /api/read_status/mark_read endpoint to update read status
- Update app.js to load/save read status from server instead of localStorage
- Update dm.js to load/save DM read status from server instead of localStorage
- Read status stored in MC_CONFIG_DIR/.read_status.json for persistence

Benefits:
- Unread badges sync across all devices (phone, computer, tablet)
- Read status persists across browser sessions
- No more duplicate unread notifications when switching devices

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 15:41:41 +01:00
MarekWo 4345456db7 refactor(contacts): Remove path_len filter from cleanup tool
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>
2026-01-01 15:18:40 +01:00
MarekWo cd65125b40 feat(contacts): Redesign cleanup tool with advanced filtering
Replace hours-based cleanup with multi-criteria contact filtering system:
- Add name filter (partial match, case-insensitive)
- Add contact type selection (CLI, REP, ROOM, SENS)
- Add date field selector (last_advert vs lastmod)
- Add days of inactivity filter (0 = ignore)
- Add path length filter (> X, 0 = ignore)
- Implement preview modal before deletion
- Support all contact types (CLI, REP, ROOM, SENS)

Backend changes:
- Add POST /api/contacts/preview-cleanup endpoint
- Refactor POST /api/contacts/cleanup with new filter logic
- Implement _filter_contacts_by_criteria helper function
- Use last_advert (reliable) instead of lastmod (unreliable)

Frontend changes:
- Move cleanup section below Existing Contacts
- Add collapsible Advanced Filters section
- Replace handleCleanupInactive with handleCleanupPreview/Confirm
- Add confirmation modal with contact list preview
- Display deletion results (success/failure counts)

Documentation updates:
- Update API endpoints in CLAUDE.md
- Update README.md with new cleanup instructions
- Remove deprecated MC_INACTIVE_HOURS from docs

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-01 14:25:29 +01:00
MarekWo 5fc1c5b779 feat: Add mention badges, clickable URLs, and image previews to messages
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>
2025-12-31 17:21:23 +01:00
MarekWo f8aedc5899 feat(contacts): Add Map button to open GPS location in Google Maps
Add Map button between Copy Key and Delete buttons on existing contacts cards.
Button appears only when contact has GPS coordinates (adv_lat/adv_lon != 0).
Opens contact location in Google Maps in new tab.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 12:43:50 +01:00