Commit Graph

9 Commits

Author SHA1 Message Date
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
MarekWo a53879df97 fix(ui): Move notifications to top-left corner and reduce display time
- 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>
2025-12-30 12:30:47 +01:00
MarekWo c0d61650a1 fix(contacts): Use contact name for deletion instead of public key
Testing revealed that meshcli's remove_contact command only works
with contact names, not with public keys (neither prefix nor full key).

Example test results:
- remove_contact bd030a71e091 → Unknown contact
- remove_contact bd030a71e091b14e...f7a → Unknown contact
- remove_contact "Progres-SLU-Lubsza-test" → SUCCESS

Changed frontend to send contact name as selector.
2025-12-30 09:56:58 +01:00
MarekWo 0d9fe53e53 fix(contacts): Use full public key for contact deletion
Problem:
- meshcli's remove_contact command requires full public key
- We were sending only 12-char prefix, causing 'Unknown contact' errors
- Contacts appeared in list but couldn't be deleted

Solution:
- API now includes full_public_key in /api/contacts/detailed response
- Frontend uses full_public_key when available, falls back to prefix
- Added detailed logging to track deletion attempts

This fixes the issue where contacts (especially with last_seen=4)
could not be removed from the device.
2025-12-30 09:44:09 +01:00
MarekWo cdc8be9eb4 refactor(contacts): Implement multi-page Contact Management with advanced sorting
Split Contact Management into 3 dedicated pages for improved mobile usability:
- /contacts/manage - Settings & navigation hub (manual approval + cleanup)
- /contacts/pending - Full-screen pending contacts view
- /contacts/existing - Full-screen existing contacts with search/filter/sort

New Features:
- Advanced sorting: Name (A-Z/Z-A) & Last advert (newest/oldest)
- URL-based sort state (?sort=name&order=asc)
- Activity indicators: 🟢 active, 🟡 recent, 🔴 inactive
- Changed terminology: "Last seen" → "Last advert" (more accurate)
- Cleanup tool moved from Settings modal to Contact Management page

Technical Changes:
- Created contacts_base.html standalone template
- Split contacts.html into 3 specialized templates
- Refactored contacts.js for multi-page support with page detection
- Added 2 new Flask routes: /contacts/pending, /contacts/existing
- Removed cleanup section from base.html Settings modal

Mobile-first design: Each page has full-screen space with touch-friendly
navigation and back buttons.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-30 08:40:22 +01:00
MarekWo 7f819b63c7 feat(contacts): Add 'Last Seen' timestamp display with activity indicators
Add comprehensive "last seen" tracking for all contact types:

Backend (cli.py):
- New function get_contacts_with_last_seen() using 'apply_to t=1,t=2,t=3,t=4 contact_info'
- Fetches detailed contact metadata including last_advert timestamps
- Returns dictionary indexed by full public_key for efficient lookup

API (api.py):
- Enhanced /api/contacts/detailed endpoint to merge last_seen data
- Matches contacts by public_key_prefix (first 12 chars)
- Graceful fallback if detailed fetch fails (contacts still displayed without last_seen)

Frontend (contacts.js):
- formatRelativeTime() - converts Unix timestamps to human-readable format
  ("5 minutes ago", "2 hours ago", "3 days ago")
- getActivityStatus() - returns status indicator based on recency:
  🟢 Active (< 5 min), 🟡 Recent (< 1 hour), 🔴 Inactive (> 1 hour)
- Contact cards now display "Last seen" with status icon and relative time
- Clean handling of missing last_seen data (shows "Unknown")

This feature helps users identify active vs. inactive contacts at a glance,
using the last_advert field from meshcli's contact_info command.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-29 13:03:15 +01:00
MarekWo 3e524bb0d2 refactor(ui): Optimize Contact Management layout for better space usage
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>
2025-12-29 12:34:35 +01:00
MarekWo 8b709b9136 feat(ui): Contact Management v2 - existing contacts display and delete
Implements MVP v2 requirements from docs/UI-Contact-Management-MVP-v2.md:
- Display all contact types (CLI, REP, ROOM, SENS)
- Delete contacts with confirmation modal
- Capacity counter with color-coded warnings (green/yellow/red)
- Search by name or public key
- Filter by contact type
- Mobile-first responsive design

Backend changes:
- Add get_all_contacts_detailed() parser for meshcli contacts output
  - Handles Unicode characters, emoji, spaces in names
  - Backward parsing strategy using public_key_prefix as anchor
  - Returns detailed metadata for all contact types
- Add delete_contact() wrapper for remove_contact command
- Add GET /api/contacts/detailed endpoint
- Add POST /api/contacts/delete endpoint

Frontend changes:
- Add Existing Contacts section to contacts.html
  - Real-time search input
  - Type filter dropdown (All/CLI/REP/ROOM/SENS)
  - Color-coded type badges
  - Capacity counter with pulse animation for critical levels
- Add delete confirmation modal with danger styling
- Add complete contact management logic to contacts.js
  - loadExistingContacts(), applyFilters(), confirmDelete()
  - Copy public key to clipboard functionality

Documentation:
- Update README.md with usage instructions
- Add technotes/UI-Contact-Management-MVP-v2-completed.md
- Add docs/UI-Contact-Management-MVP-v2.md (specification)
- Add technotes/UI-Contact-Management-MVP-v1-completed.md (retroactive)

Tested with 263 real contacts including Unicode and edge cases.

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-29 11:45:47 +01:00
MarekWo 77c72ba62e feat: add contact management MVP (manual approval + pending)
Implements Contact Management UI with manual contact approval and pending contacts list.

**Backend changes (meshcore-bridge/bridge.py):**
- Remove forced manual_add_contacts on session init (was for testing only)
- Add _load_webui_settings() to read .webui_settings.json from MC_CONFIG_DIR
- Add /set_manual_add_contacts endpoint for persistent settings management
- Settings now persist across container restarts via .webui_settings.json

**Backend changes (app/meshcore/cli.py):**
- Add get_pending_contacts() - proxy to bridge /pending_contacts
- Add approve_pending_contact() - proxy to bridge /add_pending (always uses full public_key)
- Add get_device_settings() - read .webui_settings.json
- Add set_manual_add_contacts() - proxy to bridge /set_manual_add_contacts

**API changes (app/routes/api.py):**
- Add GET /api/contacts/pending - list pending contacts
- Add POST /api/contacts/pending/approve - approve contact by public_key
- Add GET /api/device/settings - get persistent settings
- Add POST /api/device/settings - update manual_add_contacts setting

**Frontend (app/routes/views.py, templates, js):**
- Add /contacts/manage route rendering contacts.html
- Add contacts.html template with mobile-first design
- Add contacts.js with settings toggle and pending list UI
- Add "Contact Management" menu item in base.html
- Features: manual approval toggle, pending list, approve/copy actions, toast notifications

**Documentation (README.md):**
- Add Contact Management section in Usage
- Add to Key Features list
- Add debugging instructions

**Key features:**
- Manual approval toggle (persists across restarts)
- Pending contacts list with name and public_key
- Approve button (always sends full public_key for compatibility)
- Copy full key button (clipboard API)
- Auto-refresh on page load
- Mobile-first responsive design
- Info badge when manual approval is disabled
- Toast notifications for user feedback

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-29 09:52:09 +01:00