diff --git a/COMMON_ISSUES.md b/COMMON_ISSUES.md deleted file mode 100644 index 6f5fd4a..0000000 --- a/COMMON_ISSUES.md +++ /dev/null @@ -1,163 +0,0 @@ -## Common Issues and Solutions - -### Issue: Container won't start - -**Check logs:** -```bash -docker compose logs meshcore-bridge -docker compose logs mc-webui -``` - -**Common causes:** -- Serial port not found โ†’ Verify MC_SERIAL_PORT in .env -- Permission denied โ†’ Add user to dialout group (Step 4) -- Port 5000 already in use โ†’ Change FLASK_PORT in .env - -### Issue: Cannot access web interface - -**Check if port is open:** -```bash -sudo netstat -tulpn | grep 5000 -``` - -**Check firewall:** -```bash -# Allow port 5000 (if using UFW) -sudo ufw allow 5000/tcp -``` - -**Check container is running:** -```bash -docker compose ps -``` - -### Issue: No messages appearing - -**Verify meshcli is working:** -```bash -# Test meshcli directly in bridge container -docker compose exec meshcore-bridge meshcli -s /dev/ttyUSB0 infos -``` - -**Check .msgs file:** -```bash -docker compose exec mc-webui cat /root/.config/meshcore/YourDeviceName.msgs -``` - -Replace `YourDeviceName` with your MC_DEVICE_NAME. - -### Issue: USB device errors - -**Check device connection:** -```bash -ls -l /dev/serial/by-id/ -``` - -**Restart bridge container:** -```bash -docker compose restart meshcore-bridge -``` - -**Check device permissions:** -```bash -ls -l /dev/serial/by-id/usb-Espressif* -``` - -Should show `crw-rw----` with group `dialout`. - -## Maintenance Commands - -**View logs:** -```bash -docker compose logs -f # All services -docker compose logs -f mc-webui # Main app only -docker compose logs -f meshcore-bridge # Bridge only -``` - -**Restart services:** -```bash -docker compose restart # Restart both -docker compose restart mc-webui # Restart main app only -docker compose restart meshcore-bridge # Restart bridge only -``` - -**Stop application:** -```bash -docker compose down -``` - -**Update to latest version:** -```bash -git pull origin main -docker compose down -docker compose up -d --build -``` - -**View container status:** -```bash -docker compose ps -``` - -**Access container shell:** -```bash -docker compose exec mc-webui sh -docker compose exec meshcore-bridge sh -``` - -## Backup Your Data - -**All important data is in the `data/` directory:** - -```bash -# Create backup -cd ~/mc-webui -tar -czf ../mc-webui-backup-$(date +%Y%m%d).tar.gz data/ - -# Verify backup -ls -lh ../mc-webui-backup-*.tar.gz -``` - -**Recommended backup schedule:** -- Weekly backups of `data/` directory -- Before major updates -- After significant configuration changes - -**Restore from backup:** -```bash -# Stop application -cd ~/mc-webui -docker compose down - -# Restore data -tar -xzf ../mc-webui-backup-YYYYMMDD.tar.gz - -# Restart -docker compose up -d -``` - -## Next Steps - -After successful installation: - -1. **Join channels** - Create or join encrypted channels with other users -2. **Configure contacts** - Enable manual approval if desired -3. **Test Direct Messages** - Send DM to other CLI contacts -4. **Set up backups** - Schedule regular backups of `data/` directory -5. **Read full documentation** - See [README.md](README.md) for all features - -## Getting Help - -**Documentation:** -- Full README: [README.md](README.md) -- MeshCore docs: https://meshcore.org -- meshcore-cli docs: https://github.com/meshcore-dev/meshcore-cli - -**Issues:** -- GitHub Issues: https://github.com/MarekWo/mc-webui/issues -- Check existing issues before creating new ones -- Include logs when reporting problems - ---- - -**Version:** 2026-01-06 - diff --git a/README.md b/README.md index c5ee278..9bb1b87 100644 --- a/README.md +++ b/README.md @@ -9,72 +9,35 @@ A lightweight web interface for meshcore-cli, providing browser-based access to ![Diagram](images/diagram.jpeg) -### Key Features +## Key Features -- ๐Ÿ“ฑ **Mobile-first design** - Optimized responsive UI with slide-out menu for small screens -- ๐Ÿ’ฌ **View messages** - Display chat history with intelligent auto-refresh -- ๐Ÿ”” **Smart notifications** - Bell icon with unread message counter across all channels -- ๐Ÿ“Š **Per-channel badges** - Unread count displayed on each channel in selector -- ๐Ÿ”„ **Cross-device sync** - Unread message status syncs across all devices (server-side storage) -- โœ‰๏ธ **Send messages** - Publish to any channel (140 byte limit for LoRa) -- ๐Ÿ’Œ **Direct messages (DM)** - Send and receive private messages with delivery status tracking -- ๐Ÿ“ก **Channel management** - Create, join, and switch between encrypted channels -- ๐Ÿ” **Channel sharing** - Share channels via QR code or encrypted keys -- ๐Ÿ”“ **Public channels** - Join public channels (starting with #) without encryption keys -- ๐ŸŽฏ **Reply to users** - Quick reply with `@[UserName]` format -- ๐Ÿท๏ธ **Mention badges** - User mentions displayed as styled badges (like Android Meshcore app) -- ๐Ÿ”— **Clickable URLs** - Automatic URL detection and link conversion -- ๐Ÿ–ผ๏ธ **Image previews** - Inline image thumbnails with click-to-expand modal -- ๐Ÿ‘ฅ **Contact management** - Manual contact approval mode with pending contacts list (persistent settings) - - **Dedicated pages:** Separate full-screen views for pending and existing contacts - - **Advanced sorting:** Sort contacts by name (A-Z/Z-A) or last advertisement time (newest/oldest) - - **Smart filtering:** Search by name/key, filter by contact type (CLI, REP, ROOM, SENS) - - **Activity indicators:** Visual status icons (๐ŸŸข active, ๐ŸŸก recent, ๐Ÿ”ด inactive) based on last advertisement - - **GPS location:** View contact location on Google Maps (when GPS coordinates available) - - **Advanced cleanup tool:** Filter and remove contacts by name, type (CLI/REP/ROOM/SENS), and inactivity period with preview before deletion -- ๐Ÿ“ฆ **Message archiving** - Automatic daily archiving with browse-by-date selector -- โšก **Efficient polling** - Lightweight update checks every 10s, UI refreshes only when needed -- ๐Ÿ“ก **Network commands** - Send advertisement (advert) or flood advertisement (floodadv) for network management -- ๐Ÿ”” **PWA notifications** - Browser notifications for new messages when app is hidden (experimental) - - Desktop notifications with aggregated message counts - - App badge counter on home screen icon (Android/Desktop) - - Service Worker for PWA installability and offline support - - Tested on Windows desktop (Firefox), requires further testing on Android mobile -- ๐Ÿ“ด **Full offline support** - Works without internet connection - - All external libraries hosted locally: Bootstrap CSS/JS, Bootstrap Icons, Emoji Picker - - Service Worker caches all UI assets automatically (~1.2 MB total) - - Hybrid caching strategy: cache-first for libraries, network-first for app updates - - Perfect for mesh networks operating in remote/emergency scenarios +- **Mobile-first design** - Responsive UI optimized for small screens +- **Channel management** - Create, join, share (QR code), and switch between encrypted channels +- **Direct Messages (DM)** - Private messaging with delivery status tracking +- **Smart notifications** - Unread message counters per channel with cross-device sync +- **Contact management** - Manual approval mode, filtering, cleanup tools +- **Message archives** - Automatic daily archiving with browse-by-date selector +- **PWA support** - Browser notifications and installable app (experimental) +- **Full offline support** - Works without internet (local Bootstrap, icons, emoji picker) -## Tech Stack - -- **Backend:** Python 3.11+, Flask -- **Frontend:** HTML5, Bootstrap 5, vanilla JavaScript -- **Deployment:** Docker / Docker Compose (2-container architecture) -- **Communication:** HTTP bridge to meshcore-cli (USB isolation for stability) -- **Data source:** `~/.config/meshcore/.msgs` (JSON Lines) +For detailed feature documentation, see the [User Guide](docs/user-guide.md). ## Quick Start ### Prerequisites -Before starting, ensure you have: - **1. Meshcore Device (tested on Heltec V4)** -- **Flash the device** at [https://flasher.meshcore.co.uk/](https://flasher.meshcore.co.uk/). Choose the `Companion USB` role. -- **Configure the device** with the Meshcore mobile app (from Google Play Store / App Store): - - Name - - Location (optional) - - Preset +- Flash the device at [https://flasher.meshcore.co.uk/](https://flasher.meshcore.co.uk/). Choose the `Companion USB` role. +- Configure the device with the Meshcore mobile app (from Google Play Store / App Store): Name, Location (optional), Preset **2. Linux Server** -- **Git** installed -- **Docker** and **Docker Compose** installed ([installation guide](DOCKER_INSTALL.md)) +- Git installed +- Docker and Docker Compose installed ([installation guide](docs/docker-install.md)) **Important Notes:** -- โœ… **No meshcore-cli installation required on host** - meshcore-cli is automatically installed inside the Docker container -- โœ… **No manual directory setup needed** - all data is stored in `./data/` inside the project directory -- โœ… **meshcore-cli version 1.3.12+** is automatically installed for proper Direct Messages (DM) functionality +- No meshcore-cli installation required on host - automatically installed inside Docker container +- No manual directory setup needed - all data stored in `./data/` inside the project directory +- meshcore-cli version 1.3.12+ is automatically installed for proper DM functionality --- @@ -82,294 +45,117 @@ Before starting, ensure you have: 1. **Clone the repository** ```bash - # Navigate to your preferred directory cd ~ - - # Clone the repository git clone https://github.com/MarekWo/mc-webui cd mc-webui ``` - **Verify:** - ```bash - pwd # Should show: /home//mc-webui - ls # Should show: README.md, docker-compose.yml, app/, etc. - ``` - 2. **Find your serial device ID** ```bash - # List USB serial devices ls /dev/serial/by-id/ ``` You should see a device name starting with `usb-...`. For Heltec V4 may look like: ``` usb-Espressif_Systems_heltec_wifi_lora_32_v4__16_MB_FLASH__2_MB_PSRAM__90706984A000-if00 ``` - For Heltec V3 it may be something similar to: - ``` - usb-Silicon_Labs_CP2102_USB_to_UART_Bridge_Controller_0001-if00-port0 - ``` - **Copy the full device ID** - you'll need it in the next step. -
+ **Copy the full device ID** - you'll need it in the next step. 3. **Configure your environment** ```bash - # Copy example configuration cp .env.example .env - - # Edit configuration - nano .env # or you can use your favorite text editor + nano .env ``` **Required changes in .env:** + - `MC_SERIAL_PORT=/dev/serial/by-id/` + - `MC_DEVICE_NAME=` + - `TZ=Europe/Warsaw` (optional, set your timezone) - - **MC_SERIAL_PORT** - Update with your device from Step 2: - ```bash - MC_SERIAL_PORT=/dev/serial/by-id/ - ``` - - - **MC_DEVICE_NAME** - Set your device name (e.g., your callsign): - ```bash - MC_DEVICE_NAME= - ``` - - - **TZ** - Set your timezone (optional): - ```bash - TZ=Europe/Warsaw # Pick your timezone - ``` - **Leave these as default**: - ```bash - MC_CONFIG_DIR=./data/meshcore # โœ… Correct - inside project - MC_ARCHIVE_DIR=./data/archive # โœ… Correct - inside project - ``` - - **Save and exit:** - - Press `Ctrl+O` to save - - Press `Enter` to confirm - - Press `Ctrl+X` to exit -
+ **Leave these as default:** + ```bash + MC_CONFIG_DIR=./data/meshcore + MC_ARCHIVE_DIR=./data/archive + ``` 4. **Verify Serial Device Permissions** - ```bash - # Check device permissions - ls -l /dev/serial/by-id/usb-* + ls -l /dev/serial/by-id/usb-* ``` - You should get something like this: - ``` - lrwxrwxrwx 1 root root 13 Jan 6 14:07 /dev/serial/by-id/usb- -> ../../ttyUSB0 - ``` -
+ If needed, add your user to dialout group: ```bash - # If needed, add your user to dialout group sudo usermod -aG dialout $USER - - # Log out and log back in for group changes to take effect - # Or use: newgrp dialout + # Log out and log back in for changes to take effect ``` 5. **Build and run** ```bash - # Build and start in detached mode docker compose up -d --build ``` - **This will:** + This will: - Download base images (Python, Alpine Linux) - - Install meshcore-cli inside containers (no host installation needed!) + - Install meshcore-cli inside containers - Create `./data/` directory structure automatically - Start both containers (meshcore-bridge and mc-webui) - **Expected output:** - ``` - [+] Building 45.2s (24/24) FINISHED - [+] Running 3/3 - โœ” Network mc-webui_meshcore-net Created - โœ” Container meshcore-bridge Started - โœ” Container mc-webui Started - ``` - -6. **Verify instalation** - - **Check container status:** +6. **Verify installation** ```bash docker compose ps ``` - **Expected output:** - ``` - NAME IMAGE STATUS PORTS - meshcore-bridge mc-webui-bridge Up 10 seconds - mc-webui mc-webui-app Up 10 seconds 0.0.0.0:5000->5000/tcp - ``` - - Both containers should show `Up` status. - - **Check logs:** + Both containers should show `Up` status. Check logs if needed: ```bash - # View all logs docker compose logs -f - - # Or specific container - docker compose logs -f mc-webui - docker compose logs -f meshcore-bridge ``` - **Look for:** - - โœ… "meshcli process started" (in meshcore-bridge logs) - - โœ… "Running on http://0.0.0.0:5000" (in mc-webui logs) - - โŒ No errors about USB device or permissions - - Press `Ctrl+C` to stop viewing logs. - - **Verify data directory:** - ```bash - ls -la data/ - ``` - - **Expected output:** - ``` - drwxr-xr-x meshcore/ # Configuration directory - drwxr-xr-x archive/ # Archive directory - ``` - - 7. **Access the web interface** - Open your browser and navigate to: + + Open your browser and navigate to: ``` http://:5000 ``` - **To find your server IP:** - ```bash - hostname -I | awk '{print $1}' - ``` + To find your server IP: `hostname -I | awk '{print $1}'` 8. **Initial Configuration (In Web UI)** - - - **Main page loads** โœ… - - You should see the chat interface - - Default channel is "Public" - - - **Wait for initial sync** (can take 1-2 minutes) - - Messages will appear as they arrive - - Check notification bell for updates - - - **Optional but highly recommended: Enable manual contact approval** - - Open menu (โ˜ฐ) - - Select "Contact Management" - - Toggle "Manual Contact Approval" - - - **Test sending a message** - - Type a message in the input field - - Press Enter or click Send - - Message should appear in chat history - - -## Installation Summary - -After completing this guide, you should have: - -- โœ… mc-webui running in Docker containers -- โœ… Web interface accessible at http://YOUR_IP:5000 -- โœ… All data stored in `./data/` directory -- โœ… meshcore-cli integrated (no host installation) -- โœ… Basic understanding of Docker commands -- โœ… Backup strategy in place - -**Congratulations! Your mc-webui installation is complete.** ๐ŸŽ‰ - -You can now use the web interface to chat on the MeshCore network without SSH/terminal access. - -Please also check the Common Issues guide [here](COMMON_ISSUES.md). + - Main page loads with chat interface on "Public" channel + - Wait for initial sync (1-2 minutes) + - Optional: Enable manual contact approval in Contact Management --- -## Architecture -mc-webui uses a **2-container architecture** for improved USB stability: +## Basic Usage -1. **meshcore-bridge** - Lightweight service with exclusive USB device access - - Maintains a **persistent meshcli session** (single long-lived process) - - Multiplexes stdout: JSON adverts โ†’ `.adverts.jsonl` log, CLI commands โ†’ HTTP responses - - Real-time message reception via `msgs_subscribe` (no polling) - - Thread-safe command queue with event-based synchronization - - Watchdog thread for automatic crash recovery - - Exposes HTTP API on port 5001 (internal only) +1. **View messages** - Main page shows chat history with auto-refresh every 10 seconds +2. **Send messages** - Type in the text field and press Enter (140 byte limit) +3. **Switch channels** - Use the dropdown in navbar +4. **Direct Messages** - Access via menu (โ˜ฐ) โ†’ "Direct Messages" +5. **Manage contacts** - Access via menu (โ˜ฐ) โ†’ "Contact Management" -2. **mc-webui** - Main web application - - Flask-based web interface - - Communicates with bridge via HTTP - - No direct USB access (prevents device locking) +For complete usage instructions, see the [User Guide](docs/user-guide.md). -This separation solves USB timeout/deadlock issues common in Docker + VM environments. +--- -### Bridge Session Architecture +## Gallery -The meshcore-bridge maintains a **single persistent meshcli session** instead of spawning new processes per request: +Main Chat Window Unread messages Menu Direct Messages Channel management Message history Contact management Pending contacts Existing contacts -- **Single subprocess.Popen** - One long-lived meshcli process with stdin/stdout pipes -- **Multiplexing** - Intelligently routes output: - - JSON adverts (with `payload_typename: "ADVERT"`) โ†’ logged to `{device_name}.adverts.jsonl` - - CLI command responses โ†’ returned via HTTP API -- **Real-time messages** - `msgs_subscribe` command enables instant message reception without polling -- **Thread-safe queue** - Commands are serialized through a queue.Queue for FIFO execution -- **Timeout-based detection** - Response completion detected when no new lines arrive for 300ms -- **Auto-restart watchdog** - Monitors process health and restarts on crash +--- -This architecture enables advanced features like pending contact management (`manual_add_contacts`) and provides better stability and performance. +## Documentation -## Project Structure +| Document | Description | +|----------|-------------| +| [User Guide](docs/user-guide.md) | Complete feature documentation | +| [Architecture](docs/architecture.md) | Technical details, API reference | +| [Troubleshooting](docs/troubleshooting.md) | Common issues and solutions | +| [Docker Installation](docs/docker-install.md) | How to install Docker on Debian/Ubuntu | -``` -mc-webui/ -โ”œโ”€โ”€ Dockerfile # Main app Docker image -โ”œโ”€โ”€ docker-compose.yml # Multi-container orchestration -โ”œโ”€โ”€ meshcore-bridge/ -โ”‚ โ”œโ”€โ”€ Dockerfile # Bridge service image -โ”‚ โ”œโ”€โ”€ bridge.py # HTTP API wrapper for meshcli -โ”‚ โ””โ”€โ”€ requirements.txt # Bridge dependencies (Flask only) -โ”œโ”€โ”€ app/ -โ”‚ โ”œโ”€โ”€ __init__.py -โ”‚ โ”œโ”€โ”€ main.py # Flask entry point -โ”‚ โ”œโ”€โ”€ config.py # Configuration from env vars -โ”‚ โ”œโ”€โ”€ meshcore/ -โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py -โ”‚ โ”‚ โ”œโ”€โ”€ cli.py # HTTP client for bridge API -โ”‚ โ”‚ โ””โ”€โ”€ parser.py # .msgs file parser -โ”‚ โ”œโ”€โ”€ routes/ -โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py -โ”‚ โ”‚ โ”œโ”€โ”€ api.py # REST API endpoints -โ”‚ โ”‚ โ””โ”€โ”€ views.py # HTML views -โ”‚ โ”œโ”€โ”€ static/ -โ”‚ โ”‚ โ”œโ”€โ”€ css/ -โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ style.css # Custom styles -โ”‚ โ”‚ โ”œโ”€โ”€ js/ -โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ app.js # Main page frontend logic -โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ dm.js # Direct Messages page logic -โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ contacts.js # Contact Management multi-page logic -โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ message-utils.js # Message content processing (mentions, URLs, images) -โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ sw.js # Service Worker for PWA notifications -โ”‚ โ”‚ โ””โ”€โ”€ manifest.json # PWA manifest -โ”‚ โ””โ”€โ”€ templates/ -โ”‚ โ”œโ”€โ”€ base.html # Base template -โ”‚ โ”œโ”€โ”€ index.html # Main chat view -โ”‚ โ”œโ”€โ”€ dm.html # Direct Messages full-page view -โ”‚ โ”œโ”€โ”€ contacts_base.html # Contact pages base template -โ”‚ โ”œโ”€โ”€ contacts-manage.html # Contact Management settings & navigation -โ”‚ โ”œโ”€โ”€ contacts-pending.html # Pending contacts full-screen view -โ”‚ โ”œโ”€โ”€ contacts-existing.html # Existing contacts with sort/filter -โ”‚ โ””โ”€โ”€ components/ # Reusable components -โ”œโ”€โ”€ requirements.txt # Python dependencies -โ”œโ”€โ”€ .env.example # Example environment config -โ”œโ”€โ”€ .gitignore -โ””โ”€โ”€ README.md # This file -``` +--- ## Development Status -๐Ÿš€ **Core Features Complete** โœ… - ### Completed Features - [x] Environment Setup & Docker Architecture @@ -383,10 +169,10 @@ mc-webui/ - [x] Message Archiving (Daily archiving with browse-by-date selector) - [x] Smart Notifications (Unread counters per channel and total) - [x] Direct Messages (DM) - Private messaging with delivery status tracking -- [x] Advanced Contact Management - Multi-page interface with sorting, filtering, and activity tracking -- [x] Message Content Enhancements - Mention badges, clickable URLs, and image previews -- [x] PWA Notifications (Experimental) - Browser notifications and app badge counters (tested on Windows/Firefox, requires testing on Android) -- [x] Full Offline Support - Local Bootstrap libraries and Service Worker caching for internet-free operation +- [x] Advanced Contact Management - Multi-page interface with sorting, filtering +- [x] Message Content Enhancements - Mention badges, clickable URLs, image previews +- [x] PWA Notifications (Experimental) - Browser notifications and app badge counters +- [x] Full Offline Support - Local Bootstrap libraries and Service Worker caching ### Next Steps @@ -394,514 +180,13 @@ mc-webui/ - [ ] Enhanced Testing - Unit and integration tests - [ ] Documentation Polish - API docs and usage guides -## Usage - -### Viewing Messages - -The main page displays chat history from the currently selected channel. The app uses an intelligent refresh system that checks for new messages every 10 seconds and updates the UI only when new messages actually arrive. - -**Unread notifications:** -- **Bell icon** in navbar shows total unread count across all channels -- **Channel badges** display unread count per channel (e.g., "Malopolska (3)") -- Messages are automatically marked as read when you view them -- Read status persists across browser sessions - -By default, the live view shows messages from the last 7 days. Older messages are automatically archived and can be accessed via the date selector. - -### Managing Channels - -Access channel management: -1. Click the menu icon (โ˜ฐ) in the navbar -2. Select "Manage Channels" from the slide-out menu - -#### Creating a New Channel -1. Click "Add New Channel" -2. Enter a channel name (letters, numbers, _ and - only) -3. Click "Create & Auto-generate Key" -4. The channel is created with a secure encryption key - -#### Sharing a Channel -1. In the Channels modal, click the share icon next to any channel -2. Share the QR code (scan with another device) or copy the encryption key -3. Others can join using the "Join Existing" option - -#### Joining a Channel - -**For private channels:** -1. Click "Join Existing" -2. Enter the channel name and encryption key (received from channel creator) -3. Click "Join Channel" -4. The channel will be added to your available channels - -**For public channels (starting with #):** -1. Click "Join Existing" -2. Enter the channel name (e.g., `#test`, `#krakow`) -3. Leave the encryption key field empty (key is auto-generated based on channel name) -4. Click "Join Channel" -5. You can now chat with other users on the same public channel - -#### Deleting a Channel -1. In the Channels modal, click the delete icon (trash) next to any channel -2. Confirm the deletion -3. The channel configuration and **all its messages** will be permanently removed - -**Note:** Deleting a channel removes all message history for that channel from your device to prevent data leakage when reusing channel slots. - -#### Switching Channels -Use the channel selector dropdown in the navbar to switch between channels. Your selection is remembered between sessions. - -### Viewing Message Archives - -Access historical messages using the date selector: - -1. Click the menu icon (โ˜ฐ) in the navbar -2. Under "Message History" select a date to view archived messages for that day -3. Select "Today (Live)" to return to live view - -Archives are created automatically at midnight (00:00 UTC) each day. The live view always shows the most recent messages (last 7 days by default). - -### Sending Messages - -1. Select your target channel using the channel selector -2. Type your message in the text field at the bottom -3. Press Enter or click "Send" -4. Your message will be published to the selected channel - -### Replying to Users - -Click the reply button on any message to insert `@[UserName]` into the text field, then type your reply. - -### Message Content Features - -The application automatically enhances message content with interactive elements: - -#### Mention Badges -User mentions in the format `@[Username]` are displayed as styled blue badges (similar to the Android Meshcore app), making it easier to identify who is being addressed in a conversation. - -**Example:** `@[MarWoj] test w Kielcach` displays with "MarWoj" as a blue badge. - -#### Clickable URLs -URLs starting with `http://` or `https://` are automatically converted to clickable links that open in a new browser tab. - -**Example:** `https://example.com` becomes a clickable blue link. - -#### Image Previews -URLs ending in `.jpg`, `.jpeg`, `.png`, `.gif`, or `.webp` are displayed as: -- **Inline thumbnails** (max 300x200px on desktop, 200x150px on mobile) -- **Click-to-expand** - Click any thumbnail to view the full-size image in a modal preview -- **Lazy loading** - Images load only when needed for better performance -- **Error handling** - Broken images show a placeholder - -**Example:** Sending `https://example.com/photo.jpg` shows a thumbnail of the image that can be clicked to view full-size. - -**Note:** All content enhancements work in both channel messages and Direct Messages (DM). - -### Direct Messages (DM) - -Access the Direct Messages feature: - -**From the menu:** -1. Click the menu icon (โ˜ฐ) in the navbar -2. Select "Direct Messages" from the menu -3. Opens a dedicated full-page DM view - -**Using the DM page:** -1. **Select a recipient** from the dropdown at the top: - - **Existing conversations** are shown first (with message history) - - Separator: "--- Available contacts ---" - - **All client contacts** from your device (only CLI type, no repeaters/rooms) - - You can start a new conversation with anyone in your contacts list -2. Type your message in the input field (max 140 bytes, same as channels) -3. Use the emoji picker button to insert emojis -4. Press Enter or click Send -5. Click "Back" button to return to the main chat view - -**Persistence:** -- The app remembers your last selected conversation -- When you return to the DM page, it automatically opens the last conversation you were viewing -- This works similarly to how the main page remembers your selected channel - -**Note:** Only client contacts (CLI) are shown in the dropdown. Repeaters (REP), rooms (ROOM), and sensors (SENS) are automatically filtered out. - -**Message status indicators:** -- โณ **Pending** (clock icon, yellow) - Message sent, awaiting delivery confirmation -- Note: Due to meshcore-cli limitations, we cannot track actual delivery status - -**Notifications:** -- The bell icon shows a secondary green badge for unread DMs -- Each conversation shows unread indicator (*) in the dropdown -- DM badge in the menu shows total unread DM count - -### Contact Management - -Access the Contact Management feature to control who can connect to your node: - -**From the menu:** -1. Click the menu icon (โ˜ฐ) in the navbar -2. Select "Contact Management" from the menu -3. Opens the contact management page - -#### Manual Contact Approval - -By default, new contacts attempting to connect are automatically added to your contacts list. You can enable manual approval to control who can communicate with your node. - -**Enable manual approval:** -1. On the Contact Management page, toggle the "Manual Contact Approval" switch -2. When enabled, new contact requests will appear in the Pending Contacts list -3. This setting persists across container restarts - -**Security benefits:** -- **Control over network access** - Only approved contacts can communicate with your node -- **Prevention of spam/unwanted contacts** - Filter out random nodes attempting connection -- **Explicit trust model** - You decide who to trust on the mesh network - -#### Pending Contacts - -When manual approval is enabled, new contacts appear in the Pending Contacts list for review with enriched contact information: - -**View contact details:** -- Contact name with emoji (if present) -- Type badge (CLI, REP, ROOM, SENS) with color coding: - - CLI (blue): Regular clients - - REP (green): Repeaters - - ROOM (cyan): Room servers - - SENS (yellow): Sensors -- Public key prefix (first 12 characters) -- Last seen timestamp (when available) -- Map button (when GPS coordinates are available) - -**Filter contacts:** -- By type: Use checkboxes to show only specific contact types (default: CLI only) -- By name or key: Search by partial contact name or public key prefix - -**Approve contacts:** -- **Single approval:** Click "Approve" on individual contacts -- **Batch approval:** Click "Add Filtered" to approve all filtered contacts at once - - Confirmation modal shows list of contacts to be approved - - Progress indicator during batch approval - -**Other actions:** -- Click "Map" button to view contact location on Google Maps (when GPS data available) -- Click "Copy Key" to copy full public key to clipboard -- Click "Refresh" to reload pending contacts list - -**Note:** Always use the full public key for approval (not name or prefix). This ensures compatibility with all contact types. - -#### Existing Contacts - -The Existing Contacts section displays all contacts currently stored on your device (CLI, REP, ROOM, SENS types). - -**Features:** -- **Counter badge** - Shows current contact count vs. 350 limit (MeshCore device max) - - Green: Normal (< 300 contacts) - - Yellow: Warning (300-339 contacts) - - Red (pulsing): Alarm (โ‰ฅ 340 contacts) -- **Search** - Filter contacts by name or public key prefix -- **Type filter** - Show only specific contact types (All / CLI / REP / ROOM / SENS) -- **Contact cards** - Display name, type badge, public key prefix, path info, and last seen timestamp -- **Last Seen** - Shows when each contact was last active with activity indicators: - - ๐ŸŸข **Active** (seen < 5 minutes ago) - - ๐ŸŸก **Recent** (seen < 1 hour ago) - - ๐Ÿ”ด **Inactive** (seen > 1 hour ago) - - โšซ **Unknown** (no timestamp available) - - Relative time format: "5 minutes ago", "2 hours ago", "3 days ago", etc. - -**Managing contacts:** -1. **Search contacts:** - - Type in the search box to filter by name or public key prefix - - Results update instantly as you type - -2. **Filter by type:** - - Use the type dropdown to show only: - - **CLI** - Client devices (blue badge) - - **REP** - Repeaters (green badge) - - **ROOM** - Room servers (cyan badge) - - **SENS** - Sensors (yellow badge) - -3. **Copy public key:** - - Click "Copy Key" button to copy the public key prefix to clipboard - - Useful for sharing or verification - -4. **Delete a contact:** - - Click the "Delete" button (red trash icon) - - Confirm deletion in the modal dialog - - Contact is permanently removed from device - - **Warning:** This action cannot be undone - -**Refresh contacts list:** -- Click the "Refresh" button to reload the contacts list -- The page automatically loads contacts when first opened - -**Monitoring contact capacity:** -- MeshCore devices have a limit of 350 contacts -- The counter badge changes color as you approach the limit: - - **0-299**: Green (plenty of space) - - **300-339**: Yellow warning (nearing limit) - - **340-350**: Red alarm (critical - delete some contacts soon) - -#### Debugging - -If you encounter issues with contact management: - -**Check logs:** -```bash -# mc-webui container logs -docker compose logs -f mc-webui - -# meshcore-bridge container logs (where settings are applied) -docker compose logs -f meshcore-bridge -``` - -**Look for:** -- "Loaded webui settings" - confirms settings file is being read -- "manual_add_contacts set to on/off" - confirms setting is applied to meshcli session -- "Saved manual_add_contacts=..." - confirms setting is persisted to file - -### Managing Contacts (Cleanup) - -The advanced cleanup tool allows you to filter and remove contacts based on multiple criteria: - -1. Navigate to **Contact Management** page (from slide-out menu) -2. Scroll to **Cleanup Contacts** section (below Existing Contacts) -3. Configure filters: - - **Name Filter:** Enter partial contact name to search (optional) - - **Advanced Filters** (collapsible): - - **Contact Types:** Select which types to include (CLI, REP, ROOM, SENS) - - **Date Field:** Choose between "Last Advert" (recommended) or "Last Modified" - - **Days of Inactivity:** Contacts inactive for more than X days (0 = ignore) -4. Click **Preview Cleanup** to see matching contacts -5. Review the list and confirm deletion - -**Example use cases:** -- Remove all REP contacts inactive for 30+ days: Select REP, set days to 30 -- Clean specific contact names: Enter partial name (e.g., "test") - -### Network Commands - -Access network commands from the slide-out menu under "Network Commands" section: - -#### Send Advert (Recommended) -Sends a single advertisement frame to announce your node's presence in the mesh network. This is the normal, energy-efficient way to advertise. - -1. Click the menu icon (โ˜ฐ) in the navbar -2. Click "Send Advert" under Network Commands -3. Wait for confirmation toast - -#### Flood Advert (Use Sparingly!) -Sends advertisement in flooding mode, forcing all nodes to retransmit. **Use only when:** -- Starting a completely new network -- After device reset or firmware change -- When routing is broken and node is not visible -- For debugging/testing purposes - -โš ๏ธ **Warning:** Flood advertisement causes high airtime usage and can destabilize larger LoRa networks. A confirmation dialog will appear before execution. - -1. Click the menu icon (โ˜ฐ) in the navbar -2. Click "Flood Advert" (highlighted in warning color) -3. Confirm you want to proceed -4. Wait for confirmation toast - -### PWA Notifications (Experimental) - -The application supports Progressive Web App (PWA) notifications to alert you of new messages when the app is hidden in the background. - -#### Enabling Notifications - -1. Click the menu icon (โ˜ฐ) in the navbar -2. Click "Notifications" in the menu -3. Browser will request permission - click "Allow" -4. Status badge will change from "Disabled" to "Enabled" (green) - -#### How It Works - -**When you'll receive notifications:** -- App must be running in the background (minimized, not closed) -- New messages arrive in channels, Direct Messages, or pending contacts -- Notification shows aggregated count: "New: 2 channels, 1 private message" - -**What notifications include:** -- Total count of new messages across all categories -- Click notification to bring app back to focus -- App badge counter on home screen icon (if PWA installed) - -**Disabling notifications:** -- Click "Notifications" button again to toggle off -- Status badge will change to "Disabled" (gray) - -#### Platform Support - -**Desktop (Tested):** -- โœ… **Windows** - Firefox (working correctly) -- โœ… Chrome/Edge - Should work (not extensively tested) - -**Mobile (Experimental):** -- โš ๏ธ **Android** - Requires further testing when installed as PWA via Chrome - - Install: Chrome menu โ†’ "Add to Home Screen" - - Known limitation: Android may freeze background JavaScript after 5-10 minutes for battery saving - - Notifications will stop working after app is frozen by the OS - -**Browser Requirements:** -- Chrome/Edge 81+ (desktop), 84+ (Android) -- Firefox 22+ -- Safari 16.4+ (limited support) - -#### Installing as PWA (Android/Desktop) - -To get the full PWA experience with app badge counters: - -**Android:** -1. Open the app in Chrome -2. Menu (โ‹ฎ) โ†’ "Add to Home Screen" -3. Confirm installation -4. App icon will appear on home screen with badge counter support - -**Desktop:** -1. Open the app in Chrome/Edge -2. Look for install prompt in address bar (+ icon) -3. Click "Install" -4. App opens in standalone window - -#### Troubleshooting - -**Notifications not appearing:** -- Verify browser permission granted: Settings โ†’ Site Settings โ†’ Notifications -- Ensure app is running in background (not closed) -- Check that toggle shows "Enabled" (green badge) -- Try refreshing the page - -**Badge counter not showing:** -- Badge API requires PWA to be installed (not just bookmarked) -- Check browser compatibility (Chrome/Edge recommended) - -**Android-specific issues:** -- After 5-10 minutes in background, Android may freeze the app -- This is normal OS behavior for battery saving -- Reopen app to resume notifications -- Full "wake device" support would require Web Push API (not implemented) - -## Docker Commands - -```bash -# Start the application -docker compose up -d - -# View logs -docker compose logs -f - -# Stop the application -docker compose down - -# Rebuild after code changes -docker compose up -d --build - -# Check container status -docker compose ps -``` - -## Testing Bridge API - -The `meshcore-bridge` container exposes HTTP endpoints for pending contact management. - -### Test Pending Contacts Endpoints - -```bash -# List pending contacts (from inside mc-webui container or server) -curl -s http://meshcore-bridge:5001/pending_contacts | jq - -# Add a pending contact -curl -s -X POST http://meshcore-bridge:5001/add_pending \ - -H 'Content-Type: application/json' \ - -d '{"selector":"Skyllancer"}' | jq - -# Example response for GET /pending_contacts: -# { -# "success": true, -# "pending": [ -# { -# "name": "Skyllancer", -# "public_key": "f9ef..." -# }, -# { -# "name": "KRA Reksio mob2๐Ÿ•", -# "public_key": "41d5..." -# } -# ], -# "raw_stdout": "Skyllancer: f9ef...\nKRA Reksio mob2๐Ÿ•: 41d5..." -# } - -# Example response for POST /add_pending: -# { -# "success": true, -# "stdout": "Contact added successfully", -# "stderr": "", -# "returncode": 0 -# } -``` - -**Note:** These endpoints require `manual_add_contacts` mode to be enabled in meshcli: -```bash -# Enable manual contact approval (run in meshcli interactive mode) -set manual_add_contacts on -``` - -## Troubleshooting - -### Device not found -```bash -# Check if device is connected -ls -l /dev/serial/by-id/ - -# Verify device permissions -sudo chmod 666 /dev/serial/by-id/usb-Espressif* -``` - -### Container won't start -```bash -# Check logs for both services -docker compose logs meshcore-bridge -docker compose logs mc-webui - -# Verify .env file exists -ls -la .env - -# Check if ports are available -sudo netstat -tulpn | grep -E '5000|5001' -``` - -### USB Communication Issues -The 2-container architecture resolves common USB timeout/deadlock problems: -- **meshcore-bridge** has exclusive USB access -- **mc-webui** uses HTTP (no direct device access) -- Restarting `mc-webui` **does not** affect USB connection -- If bridge has USB issues, restart only that service: - ```bash - docker compose restart meshcore-bridge - ``` - -### Bridge connection errors -```bash -# Check bridge health -docker compose exec mc-webui curl http://meshcore-bridge:5001/health - -# Bridge logs -docker compose logs -f meshcore-bridge - -# Test meshcli directly in bridge container -docker compose exec meshcore-bridge meshcli -s /dev/ttyUSB0 infos -``` - -### Messages not updating -- Check that `.msgs` file exists in `MC_CONFIG_DIR` -- Verify bridge service is healthy: `docker compose ps` -- Check bridge logs for command errors - -## Gallery - -Main Chat Window Unread messages Menu Direct Messages Channel management Message history Contact management Pending contacts Existing contacts +--- ## Security Notes -โš ๏ธ **Important**: This application is designed for **trusted local networks only** and has **no authentication**. Do not expose it to the internet without implementing proper security measures. +**Important**: This application is designed for **trusted local networks only** and has **no authentication**. Do not expose it to the internet without implementing proper security measures. + +--- ## Contributing @@ -911,14 +196,21 @@ This is an open-source project. Contributions are welcome! - Follow the existing code style - Test your changes with real hardware if possible +--- + ## License [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) +--- + ## References - [MeshCore Documentation](https://meshcore.org) - [meshcore-cli GitHub](https://github.com/meshcore-dev/meshcore-cli) +--- + ## Contact -meshcore://11009cebbd2744d33c94b980b8f2475241fd2ca6165bd623e5ef00ec6982be6a1784a5434566772eccc26723ea5c3a1b6ccf03725b583f60121eb2bbe21ead23ab1bd96b7e83b215bf4379b4722a85de2ef25187e17e0bd5a1bd7c55c4cfbf2599f719629701814d6172576f6a + +meshcore://... diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..92b4062 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,301 @@ +# mc-webui Architecture + +Technical documentation for mc-webui, covering system architecture, project structure, and internal APIs. + +## Table of Contents + +- [Tech Stack](#tech-stack) +- [Container Architecture](#container-architecture) +- [Bridge Session Architecture](#bridge-session-architecture) +- [Project Structure](#project-structure) +- [Message File Format](#message-file-format) +- [API Reference](#api-reference) +- [Offline Support](#offline-support) + +--- + +## Tech Stack + +- **Backend:** Python 3.11+, Flask +- **Frontend:** HTML5, Bootstrap 5, vanilla JavaScript +- **Deployment:** Docker / Docker Compose (2-container architecture) +- **Communication:** HTTP bridge to meshcore-cli (USB isolation for stability) +- **Data source:** `~/.config/meshcore/.msgs` (JSON Lines) + +--- + +## Container Architecture + +mc-webui uses a **2-container architecture** for improved USB stability: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ Docker Network โ”‚ +โ”‚ โ”‚ +โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ +โ”‚ โ”‚ meshcore-bridge โ”‚ โ”‚ mc-webui โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ - USB device accessโ”‚ HTTP โ”‚ - Flask web app โ”‚ โ”‚ +โ”‚ โ”‚ - meshcli process โ”‚โ—„โ”€โ”€โ”€โ”€โ–บโ”‚ - User interface โ”‚ โ”‚ +โ”‚ โ”‚ - Port 5001 โ”‚ โ”‚ - Port 5000 โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ +โ”‚ โ”‚ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ + โ”‚ + โ–ผ + โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” + โ”‚ USB Device โ”‚ + โ”‚ (Heltec V4) โ”‚ + โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +### meshcore-bridge (Port 5001 - internal) + +Lightweight service with exclusive USB device access: + +- Maintains a **persistent meshcli session** (single long-lived process) +- Multiplexes stdout: JSON adverts โ†’ `.adverts.jsonl` log, CLI commands โ†’ HTTP responses +- Real-time message reception via `msgs_subscribe` (no polling) +- Thread-safe command queue with event-based synchronization +- Watchdog thread for automatic crash recovery +- Exposes HTTP API on port 5001 (internal only) + +### mc-webui (Port 5000 - external) + +Main web application: + +- Flask-based web interface +- Communicates with bridge via HTTP +- No direct USB access (prevents device locking) + +This separation solves USB timeout/deadlock issues common in Docker + VM environments. + +--- + +## Bridge Session Architecture + +The meshcore-bridge maintains a **single persistent meshcli session** instead of spawning new processes per request: + +- **Single subprocess.Popen** - One long-lived meshcli process with stdin/stdout pipes +- **Multiplexing** - Intelligently routes output: + - JSON adverts (with `payload_typename: "ADVERT"`) โ†’ logged to `{device_name}.adverts.jsonl` + - CLI command responses โ†’ returned via HTTP API +- **Real-time messages** - `msgs_subscribe` command enables instant message reception without polling +- **Thread-safe queue** - Commands are serialized through a queue.Queue for FIFO execution +- **Timeout-based detection** - Response completion detected when no new lines arrive for 300ms +- **Auto-restart watchdog** - Monitors process health and restarts on crash + +This architecture enables advanced features like pending contact management (`manual_add_contacts`) and provides better stability and performance. + +--- + +## Project Structure + +``` +mc-webui/ +โ”œโ”€โ”€ Dockerfile # Main app Docker image +โ”œโ”€โ”€ docker-compose.yml # Multi-container orchestration +โ”œโ”€โ”€ meshcore-bridge/ +โ”‚ โ”œโ”€โ”€ Dockerfile # Bridge service image +โ”‚ โ”œโ”€โ”€ bridge.py # HTTP API wrapper for meshcli +โ”‚ โ””โ”€โ”€ requirements.txt # Bridge dependencies (Flask only) +โ”œโ”€โ”€ app/ +โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”œโ”€โ”€ main.py # Flask entry point +โ”‚ โ”œโ”€โ”€ config.py # Configuration from env vars +โ”‚ โ”œโ”€โ”€ read_status.py # Server-side read status manager +โ”‚ โ”œโ”€โ”€ meshcore/ +โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”‚ โ”œโ”€โ”€ cli.py # HTTP client for bridge API +โ”‚ โ”‚ โ””โ”€โ”€ parser.py # .msgs file parser +โ”‚ โ”œโ”€โ”€ archiver/ +โ”‚ โ”‚ โ””โ”€โ”€ manager.py # Archive scheduler and management +โ”‚ โ”œโ”€โ”€ routes/ +โ”‚ โ”‚ โ”œโ”€โ”€ __init__.py +โ”‚ โ”‚ โ”œโ”€โ”€ api.py # REST API endpoints +โ”‚ โ”‚ โ””โ”€โ”€ views.py # HTML views +โ”‚ โ”œโ”€โ”€ static/ +โ”‚ โ”‚ โ”œโ”€โ”€ css/ +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ style.css # Custom styles +โ”‚ โ”‚ โ”œโ”€โ”€ js/ +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ app.js # Main page frontend logic +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ dm.js # Direct Messages page logic +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ contacts.js # Contact Management logic +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ message-utils.js # Message content processing +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ sw.js # Service Worker for PWA +โ”‚ โ”‚ โ”œโ”€โ”€ vendor/ # Local vendor libraries (offline) +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ bootstrap/ # Bootstrap CSS/JS +โ”‚ โ”‚ โ”‚ โ”œโ”€โ”€ bootstrap-icons/ # Icon fonts +โ”‚ โ”‚ โ”‚ โ””โ”€โ”€ emoji-picker-element/ +โ”‚ โ”‚ โ””โ”€โ”€ manifest.json # PWA manifest +โ”‚ โ””โ”€โ”€ templates/ +โ”‚ โ”œโ”€โ”€ base.html # Base template +โ”‚ โ”œโ”€โ”€ index.html # Main chat view +โ”‚ โ”œโ”€โ”€ dm.html # Direct Messages view +โ”‚ โ”œโ”€โ”€ contacts_base.html # Contact pages base template +โ”‚ โ”œโ”€โ”€ contacts-manage.html # Contact Management settings +โ”‚ โ”œโ”€โ”€ contacts-pending.html # Pending contacts view +โ”‚ โ””โ”€โ”€ contacts-existing.html # Existing contacts view +โ”œโ”€โ”€ docs/ # Documentation +โ”œโ”€โ”€ images/ # Screenshots and diagrams +โ”œโ”€โ”€ requirements.txt # Python dependencies +โ”œโ”€โ”€ .env.example # Example environment config +โ””โ”€โ”€ README.md +``` + +--- + +## Message File Format + +Location: `~/.config/meshcore/.msgs` (JSON Lines) + +### Message Types + +**Channel messages:** +```json +{"type": "CHAN", "text": "User: message", "timestamp": 1766300846} +{"type": "SENT_CHAN", "text": "my message", "name": "DeviceName", "timestamp": 1766309432} +``` + +**Private messages:** +```json +{"type": "PRIV", "text": "message", "sender_timestamp": 1766300846, "pubkey_prefix": "abc123", "sender": "User"} +{"type": "SENT_MSG", "text": "message", "recipient": "User", "expected_ack": "xyz", "suggested_timeout": 30000} +``` + +**Note on SENT_MSG:** Requires meshcore-cli >= 1.3.12 for correct format with both `recipient` and `sender` fields. + +--- + +## API Reference + +### Main Web UI Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| GET | `/api/messages` | List messages (supports `?archive_date`, `?days`, `?channel_idx`) | +| POST | `/api/messages` | Send message (`{text, channel_idx, reply_to?}`) | +| GET | `/api/messages/updates` | Check for new messages (smart refresh) | +| GET | `/api/status` | Connection status | +| GET | `/api/contacts` | List contacts | +| GET | `/api/contacts/detailed` | Full contact_info data | +| POST | `/api/contacts/delete` | Delete contact by name | +| GET | `/api/contacts/pending` | List pending contacts | +| POST | `/api/contacts/pending/approve` | Approve pending contact | +| POST | `/api/contacts/preview-cleanup` | Preview cleanup matches | +| POST | `/api/contacts/cleanup` | Execute contact cleanup | +| GET | `/api/channels` | List all channels | +| POST | `/api/channels` | Create new channel | +| POST | `/api/channels/join` | Join existing channel | +| DELETE | `/api/channels/` | Remove channel | +| GET | `/api/channels//qr` | Generate QR code | +| GET | `/api/dm/conversations` | List DM conversations | +| GET | `/api/dm/messages` | Get messages for conversation | +| POST | `/api/dm/messages` | Send DM | +| GET | `/api/dm/updates` | Check for new DMs | +| GET | `/api/device/info` | Device information | +| GET | `/api/device/settings` | Get device settings | +| POST | `/api/device/settings` | Update device settings | +| POST | `/api/device/command` | Execute special command | +| GET | `/api/read_status` | Get server-side read status | +| POST | `/api/read_status/mark_read` | Mark messages as read | +| GET | `/api/archives` | List available archives | +| POST | `/api/archive/trigger` | Manually trigger archiving | + +### Bridge Internal API (Port 5001) + +| Method | Endpoint | Description | +|--------|----------|-------------| +| POST | `/cli` | Execute meshcli command | +| GET | `/health` | Bridge health check | +| GET | `/pending_contacts` | List pending contacts | +| POST | `/add_pending` | Approve pending contact | +| GET | `/device/settings` | Get device settings | +| POST | `/device/settings` | Update device settings | + +**Base URL:** `http://meshcore-bridge:5001` (internal Docker network only) + +--- + +## Offline Support + +The application works completely offline without internet connection - perfect for mesh networks in remote or emergency scenarios. + +### Local Vendor Libraries + +| Library | Size | Location | +|---------|------|----------| +| Bootstrap 5.3.2 CSS | ~227 KB | `static/vendor/bootstrap/css/` | +| Bootstrap 5.3.2 JS | ~80 KB | `static/vendor/bootstrap/js/` | +| Bootstrap Icons 1.11.2 | ~398 KB | `static/vendor/bootstrap-icons/` | +| Emoji Picker Element | ~529 KB | `static/vendor/emoji-picker-element/` | + +**Total offline package size:** ~1.2 MB + +### Service Worker Caching + +- **Cache version:** `mc-webui-v3` +- **Strategy:** Hybrid caching + - **Cache-first** for vendor libraries (static, unchanging) + - **Network-first** for app code (dynamic, needs updates) + +### How It Works + +1. On first visit (online), Service Worker installs and caches all assets +2. Vendor libraries (Bootstrap, Icons, Emoji Picker) loaded from cache instantly +3. App code checks network first, falls back to cache if offline +4. Complete UI functionality available offline +5. Only API calls (messages, channels, contacts) require connectivity + +--- + +## Environment Variables + +| Variable | Description | Default | +|----------|-------------|---------| +| `MC_SERIAL_PORT` | Serial device path | - | +| `MC_DEVICE_NAME` | Device name (for files) | - | +| `MC_CONFIG_DIR` | Configuration directory | `./data/meshcore` | +| `MC_ARCHIVE_DIR` | Archive directory | `./data/archive` | +| `MC_ARCHIVE_ENABLED` | Enable automatic archiving | `true` | +| `MC_ARCHIVE_RETENTION_DAYS` | Days to show in live view | `7` | +| `FLASK_HOST` | Listen address | `0.0.0.0` | +| `FLASK_PORT` | Web server port | `5000` | +| `FLASK_DEBUG` | Debug mode | `false` | +| `TZ` | Timezone for logs | `UTC` | + +--- + +## Persistent Settings + +### Settings File + +**Location:** `MC_CONFIG_DIR/.webui_settings.json` + +```json +{ + "manual_add_contacts": false +} +``` + +### Read Status File + +**Location:** `MC_CONFIG_DIR/.read_status.json` + +Stores per-channel and per-conversation read timestamps for cross-device synchronization. + +```json +{ + "channels": {"0": 1735900000, "1": 1735900100}, + "dm": {"name_User1": 1735900200} +} +``` + +--- + +## Related Documentation + +- [User Guide](user-guide.md) - How to use all features +- [Troubleshooting](troubleshooting.md) - Common issues and solutions +- [Docker Installation](docker-install.md) - How to install Docker diff --git a/DOCKER_INSTALL.md b/docs/docker-install.md similarity index 100% rename from DOCKER_INSTALL.md rename to docs/docker-install.md diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..41268f2 --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,317 @@ +# Troubleshooting Guide + +Common issues and solutions for mc-webui. + +## Table of Contents + +- [Common Issues](#common-issues) +- [Docker Commands](#docker-commands) +- [Testing Bridge API](#testing-bridge-api) +- [Backup and Restore](#backup-and-restore) +- [Next Steps](#next-steps) +- [Getting Help](#getting-help) + +--- + +## Common Issues + +### Container won't start + +**Check logs:** +```bash +docker compose logs meshcore-bridge +docker compose logs mc-webui +``` + +**Common causes:** +- Serial port not found โ†’ Verify `MC_SERIAL_PORT` in `.env` +- Permission denied โ†’ Add user to dialout group +- Port 5000 already in use โ†’ Change `FLASK_PORT` in `.env` + +--- + +### Cannot access web interface + +**Check if port is open:** +```bash +sudo netstat -tulpn | grep 5000 +``` + +**Check firewall:** +```bash +# Allow port 5000 (if using UFW) +sudo ufw allow 5000/tcp +``` + +**Check container is running:** +```bash +docker compose ps +``` + +--- + +### No messages appearing + +**Verify meshcli is working:** +```bash +# Test meshcli directly in bridge container +docker compose exec meshcore-bridge meshcli -s /dev/ttyUSB0 infos +``` + +**Check .msgs file:** +```bash +docker compose exec mc-webui cat /root/.config/meshcore/YourDeviceName.msgs +``` + +Replace `YourDeviceName` with your `MC_DEVICE_NAME`. + +--- + +### Device not found + +```bash +# Check if device is connected +ls -l /dev/serial/by-id/ + +# Verify device permissions +sudo chmod 666 /dev/serial/by-id/usb-Espressif* +``` + +--- + +### USB device errors + +**Check device connection:** +```bash +ls -l /dev/serial/by-id/ +``` + +**Restart bridge container:** +```bash +docker compose restart meshcore-bridge +``` + +**Check device permissions:** +```bash +ls -l /dev/serial/by-id/usb-Espressif* +``` + +Should show `crw-rw----` with group `dialout`. + +--- + +### USB Communication Issues + +The 2-container architecture resolves common USB timeout/deadlock problems: + +- **meshcore-bridge** has exclusive USB access +- **mc-webui** uses HTTP (no direct device access) +- Restarting `mc-webui` **does not** affect USB connection +- If bridge has USB issues, restart only that service: + ```bash + docker compose restart meshcore-bridge + ``` + +--- + +### Bridge connection errors + +```bash +# Check bridge health +docker compose exec mc-webui curl http://meshcore-bridge:5001/health + +# Bridge logs +docker compose logs -f meshcore-bridge + +# Test meshcli directly in bridge container +docker compose exec meshcore-bridge meshcli -s /dev/ttyUSB0 infos +``` + +--- + +### Messages not updating + +- Check that `.msgs` file exists in `MC_CONFIG_DIR` +- Verify bridge service is healthy: `docker compose ps` +- Check bridge logs for command errors + +--- + +### Contact Management Issues + +**Check logs:** +```bash +# mc-webui container logs +docker compose logs -f mc-webui + +# meshcore-bridge container logs (where settings are applied) +docker compose logs -f meshcore-bridge +``` + +**Look for:** +- "Loaded webui settings" - confirms settings file is being read +- "manual_add_contacts set to on/off" - confirms setting is applied to meshcli session +- "Saved manual_add_contacts=..." - confirms setting is persisted to file + +--- + +## Docker Commands + +### View logs + +```bash +docker compose logs -f # All services +docker compose logs -f mc-webui # Main app only +docker compose logs -f meshcore-bridge # Bridge only +``` + +### Restart services + +```bash +docker compose restart # Restart both +docker compose restart mc-webui # Restart main app only +docker compose restart meshcore-bridge # Restart bridge only +``` + +### Start / Stop + +```bash +# Start the application +docker compose up -d + +# Stop the application +docker compose down + +# Rebuild after code changes +docker compose up -d --build +``` + +### Check status + +```bash +docker compose ps +``` + +### Access container shell + +```bash +docker compose exec mc-webui sh +docker compose exec meshcore-bridge sh +``` + +--- + +## Testing Bridge API + +The `meshcore-bridge` container exposes HTTP endpoints for diagnostics. + +### Test endpoints + +```bash +# List pending contacts (from inside mc-webui container or server) +curl -s http://meshcore-bridge:5001/pending_contacts | jq + +# Add a pending contact +curl -s -X POST http://meshcore-bridge:5001/add_pending \ + -H 'Content-Type: application/json' \ + -d '{"selector":"Skyllancer"}' | jq + +# Check bridge health +docker compose exec mc-webui curl http://meshcore-bridge:5001/health +``` + +### Example responses + +**GET /pending_contacts:** +```json +{ + "success": true, + "pending": [ + { + "name": "Skyllancer", + "public_key": "f9ef..." + }, + { + "name": "KRA Reksio mob2๐Ÿ•", + "public_key": "41d5..." + } + ], + "raw_stdout": "Skyllancer: f9ef...\nKRA Reksio mob2๐Ÿ•: 41d5..." +} +``` + +**POST /add_pending:** +```json +{ + "success": true, + "stdout": "Contact added successfully", + "stderr": "", + "returncode": 0 +} +``` + +**Note:** These endpoints require `manual_add_contacts` mode to be enabled. + +--- + +## Backup and Restore + +**All important data is in the `data/` directory.** + +### Create backup + +```bash +cd ~/mc-webui +tar -czf ../mc-webui-backup-$(date +%Y%m%d).tar.gz data/ + +# Verify backup +ls -lh ../mc-webui-backup-*.tar.gz +``` + +### Recommended backup schedule + +- Weekly backups of `data/` directory +- Before major updates +- After significant configuration changes + +### Restore from backup + +```bash +# Stop application +cd ~/mc-webui +docker compose down + +# Restore data +tar -xzf ../mc-webui-backup-YYYYMMDD.tar.gz + +# Restart +docker compose up -d +``` + +--- + +## Next Steps + +After successful installation: + +1. **Join channels** - Create or join encrypted channels with other users +2. **Configure contacts** - Enable manual approval if desired +3. **Test Direct Messages** - Send DM to other CLI contacts +4. **Set up backups** - Schedule regular backups of `data/` directory +5. **Read full documentation** - See [User Guide](user-guide.md) for all features + +--- + +## Getting Help + +**Documentation:** +- [User Guide](user-guide.md) - How to use all features +- [Architecture](architecture.md) - Technical documentation +- [README](../README.md) - Installation guide +- MeshCore docs: https://meshcore.org +- meshcore-cli docs: https://github.com/meshcore-dev/meshcore-cli + +**Issues:** +- GitHub Issues: https://github.com/MarekWo/mc-webui/issues +- Check existing issues before creating new ones +- Include logs when reporting problems diff --git a/docs/user-guide.md b/docs/user-guide.md new file mode 100644 index 0000000..cba8a6e --- /dev/null +++ b/docs/user-guide.md @@ -0,0 +1,403 @@ +# mc-webui User Guide + +This guide covers all features and functionality of mc-webui. For installation instructions, see the main [README.md](../README.md). + +## Table of Contents + +- [Viewing Messages](#viewing-messages) +- [Managing Channels](#managing-channels) +- [Message Archives](#message-archives) +- [Sending Messages](#sending-messages) +- [Message Content Features](#message-content-features) +- [Direct Messages (DM)](#direct-messages-dm) +- [Contact Management](#contact-management) +- [Network Commands](#network-commands) +- [PWA Notifications](#pwa-notifications) + +--- + +## Viewing Messages + +The main page displays chat history from the currently selected channel. The app uses an intelligent refresh system that checks for new messages every 10 seconds and updates the UI only when new messages actually arrive. + +### Unread Notifications + +- **Bell icon** in navbar shows total unread count across all channels +- **Channel badges** display unread count per channel (e.g., "Malopolska (3)") +- Messages are automatically marked as read when you view them +- Read status persists across browser sessions and syncs across devices + +By default, the live view shows messages from the last 7 days. Older messages are automatically archived and can be accessed via the date selector. + +--- + +## Managing Channels + +Access channel management: +1. Click the menu icon (โ˜ฐ) in the navbar +2. Select "Manage Channels" from the slide-out menu + +### Creating a New Channel + +1. Click "Add New Channel" +2. Enter a channel name (letters, numbers, _ and - only) +3. Click "Create & Auto-generate Key" +4. The channel is created with a secure encryption key + +### Sharing a Channel + +1. In the Channels modal, click the share icon next to any channel +2. Share the QR code (scan with another device) or copy the encryption key +3. Others can join using the "Join Existing" option + +### Joining a Channel + +**For private channels:** +1. Click "Join Existing" +2. Enter the channel name and encryption key (received from channel creator) +3. Click "Join Channel" +4. The channel will be added to your available channels + +**For public channels (starting with #):** +1. Click "Join Existing" +2. Enter the channel name (e.g., `#test`, `#krakow`) +3. Leave the encryption key field empty (key is auto-generated based on channel name) +4. Click "Join Channel" +5. You can now chat with other users on the same public channel + +### Deleting a Channel + +1. In the Channels modal, click the delete icon (trash) next to any channel +2. Confirm the deletion +3. The channel configuration and **all its messages** will be permanently removed + +**Note:** Deleting a channel removes all message history for that channel from your device to prevent data leakage when reusing channel slots. + +### Switching Channels + +Use the channel selector dropdown in the navbar to switch between channels. Your selection is remembered between sessions. + +--- + +## Message Archives + +Access historical messages using the date selector: + +1. Click the menu icon (โ˜ฐ) in the navbar +2. Under "Message History" select a date to view archived messages for that day +3. Select "Today (Live)" to return to live view + +Archives are created automatically at midnight (00:00 UTC) each day. The live view always shows the most recent messages (last 7 days by default). + +--- + +## Sending Messages + +1. Select your target channel using the channel selector +2. Type your message in the text field at the bottom +3. Press Enter or click "Send" +4. Your message will be published to the selected channel + +**Message limit:** 140 bytes (LoRa limitation) + +### Replying to Users + +Click the reply button on any message to insert `@[UserName]` into the text field, then type your reply. + +--- + +## Message Content Features + +The application automatically enhances message content with interactive elements: + +### Mention Badges + +User mentions in the format `@[Username]` are displayed as styled blue badges (similar to the Android Meshcore app), making it easier to identify who is being addressed in a conversation. + +**Example:** `@[MarWoj] test message` displays with "MarWoj" as a blue badge. + +### Clickable URLs + +URLs starting with `http://` or `https://` are automatically converted to clickable links that open in a new browser tab. + +### Image Previews + +URLs ending in `.jpg`, `.jpeg`, `.png`, `.gif`, or `.webp` are displayed as: +- **Inline thumbnails** (max 300x200px on desktop, 200x150px on mobile) +- **Click-to-expand** - Click any thumbnail to view the full-size image in a modal preview +- **Lazy loading** - Images load only when needed for better performance +- **Error handling** - Broken images show a placeholder + +**Example:** Sending `https://example.com/photo.jpg` shows a thumbnail of the image that can be clicked to view full-size. + +**Note:** All content enhancements work in both channel messages and Direct Messages (DM). + +--- + +## Direct Messages (DM) + +Access the Direct Messages feature: + +### From the Menu + +1. Click the menu icon (โ˜ฐ) in the navbar +2. Select "Direct Messages" from the menu +3. Opens a dedicated full-page DM view + +### Using the DM Page + +1. **Select a recipient** from the dropdown at the top: + - **Existing conversations** are shown first (with message history) + - Separator: "--- Available contacts ---" + - **All client contacts** from your device (only CLI type, no repeaters/rooms) + - You can start a new conversation with anyone in your contacts list +2. Type your message in the input field (max 140 bytes, same as channels) +3. Use the emoji picker button to insert emojis +4. Press Enter or click Send +5. Click "Back" button to return to the main chat view + +### Persistence + +- The app remembers your last selected conversation +- When you return to the DM page, it automatically opens the last conversation you were viewing +- This works similarly to how the main page remembers your selected channel + +**Note:** Only client contacts (CLI) are shown in the dropdown. Repeaters (REP), rooms (ROOM), and sensors (SENS) are automatically filtered out. + +### Message Status Indicators + +- โณ **Pending** (clock icon, yellow) - Message sent, awaiting delivery confirmation +- Note: Due to meshcore-cli limitations, we cannot track actual delivery status + +### DM Notifications + +- The bell icon shows a secondary green badge for unread DMs +- Each conversation shows unread indicator (*) in the dropdown +- DM badge in the menu shows total unread DM count + +--- + +## Contact Management + +Access the Contact Management feature to control who can connect to your node: + +1. Click the menu icon (โ˜ฐ) in the navbar +2. Select "Contact Management" from the menu +3. Opens the contact management page + +### Manual Contact Approval + +By default, new contacts attempting to connect are automatically added to your contacts list. You can enable manual approval to control who can communicate with your node. + +**Enable manual approval:** +1. On the Contact Management page, toggle the "Manual Contact Approval" switch +2. When enabled, new contact requests will appear in the Pending Contacts list +3. This setting persists across container restarts + +**Security benefits:** +- **Control over network access** - Only approved contacts can communicate with your node +- **Prevention of spam/unwanted contacts** - Filter out random nodes attempting connection +- **Explicit trust model** - You decide who to trust on the mesh network + +### Pending Contacts + +When manual approval is enabled, new contacts appear in the Pending Contacts list for review with enriched contact information: + +**View contact details:** +- Contact name with emoji (if present) +- Type badge (CLI, REP, ROOM, SENS) with color coding: + - CLI (blue): Regular clients + - REP (green): Repeaters + - ROOM (cyan): Room servers + - SENS (yellow): Sensors +- Public key prefix (first 12 characters) +- Last seen timestamp (when available) +- Map button (when GPS coordinates are available) + +**Filter contacts:** +- By type: Use checkboxes to show only specific contact types (default: CLI only) +- By name or key: Search by partial contact name or public key prefix + +**Approve contacts:** +- **Single approval:** Click "Approve" on individual contacts +- **Batch approval:** Click "Add Filtered" to approve all filtered contacts at once + - Confirmation modal shows list of contacts to be approved + - Progress indicator during batch approval + +**Other actions:** +- Click "Map" button to view contact location on Google Maps (when GPS data available) +- Click "Copy Key" to copy full public key to clipboard +- Click "Refresh" to reload pending contacts list + +**Note:** Always use the full public key for approval (not name or prefix). This ensures compatibility with all contact types. + +### Existing Contacts + +The Existing Contacts section displays all contacts currently stored on your device (CLI, REP, ROOM, SENS types). + +**Features:** +- **Counter badge** - Shows current contact count vs. 350 limit (MeshCore device max) + - Green: Normal (< 300 contacts) + - Yellow: Warning (300-339 contacts) + - Red (pulsing): Alarm (โ‰ฅ 340 contacts) +- **Search** - Filter contacts by name or public key prefix +- **Type filter** - Show only specific contact types (All / CLI / REP / ROOM / SENS) +- **Contact cards** - Display name, type badge, public key prefix, path info, and last seen timestamp +- **Last Seen** - Shows when each contact was last active with activity indicators: + - ๐ŸŸข **Active** (seen < 5 minutes ago) + - ๐ŸŸก **Recent** (seen < 1 hour ago) + - ๐Ÿ”ด **Inactive** (seen > 1 hour ago) + - โšซ **Unknown** (no timestamp available) + - Relative time format: "5 minutes ago", "2 hours ago", "3 days ago", etc. + +**Managing contacts:** +1. **Search contacts:** Type in the search box to filter by name or public key prefix +2. **Filter by type:** Use the type dropdown to show only CLI, REP, ROOM, or SENS +3. **Copy public key:** Click "Copy Key" button to copy the public key prefix to clipboard +4. **Delete a contact:** Click the "Delete" button (red trash icon) and confirm + +**Contact capacity monitoring:** +- MeshCore devices have a limit of 350 contacts +- The counter badge changes color as you approach the limit: + - **0-299**: Green (plenty of space) + - **300-339**: Yellow warning (nearing limit) + - **340-350**: Red alarm (critical - delete some contacts soon) + +### Contact Cleanup Tool + +The advanced cleanup tool allows you to filter and remove contacts based on multiple criteria: + +1. Navigate to **Contact Management** page (from slide-out menu) +2. Scroll to **Cleanup Contacts** section +3. Configure filters: + - **Name Filter:** Enter partial contact name to search (optional) + - **Advanced Filters** (collapsible): + - **Contact Types:** Select which types to include (CLI, REP, ROOM, SENS) + - **Date Field:** Choose between "Last Advert" (recommended) or "Last Modified" + - **Days of Inactivity:** Contacts inactive for more than X days (0 = ignore) +4. Click **Preview Cleanup** to see matching contacts +5. Review the list and confirm deletion + +**Example use cases:** +- Remove all REP contacts inactive for 30+ days: Select REP, set days to 30 +- Clean specific contact names: Enter partial name (e.g., "test") + +--- + +## Network Commands + +Access network commands from the slide-out menu under "Network Commands" section: + +### Send Advert (Recommended) + +Sends a single advertisement frame to announce your node's presence in the mesh network. This is the normal, energy-efficient way to advertise. + +1. Click the menu icon (โ˜ฐ) in the navbar +2. Click "Send Advert" under Network Commands +3. Wait for confirmation toast + +### Flood Advert (Use Sparingly!) + +Sends advertisement in flooding mode, forcing all nodes to retransmit. **Use only when:** +- Starting a completely new network +- After device reset or firmware change +- When routing is broken and node is not visible +- For debugging/testing purposes + +**Warning:** Flood advertisement causes high airtime usage and can destabilize larger LoRa networks. A confirmation dialog will appear before execution. + +1. Click the menu icon (โ˜ฐ) in the navbar +2. Click "Flood Advert" (highlighted in warning color) +3. Confirm you want to proceed +4. Wait for confirmation toast + +--- + +## PWA Notifications + +The application supports Progressive Web App (PWA) notifications to alert you of new messages when the app is hidden in the background. + +### Enabling Notifications + +1. Click the menu icon (โ˜ฐ) in the navbar +2. Click "Notifications" in the menu +3. Browser will request permission - click "Allow" +4. Status badge will change from "Disabled" to "Enabled" (green) + +### How It Works + +**When you'll receive notifications:** +- App must be running in the background (minimized, not closed) +- New messages arrive in channels, Direct Messages, or pending contacts +- Notification shows aggregated count: "New: 2 channels, 1 private message" + +**What notifications include:** +- Total count of new messages across all categories +- Click notification to bring app back to focus +- App badge counter on home screen icon (if PWA installed) + +**Disabling notifications:** +- Click "Notifications" button again to toggle off +- Status badge will change to "Disabled" (gray) + +### Platform Support + +**Desktop (Tested):** +- Windows - Firefox (working correctly) +- Chrome/Edge - Should work (not extensively tested) + +**Mobile (Experimental):** +- **Android** - Requires further testing when installed as PWA via Chrome + - Install: Chrome menu โ†’ "Add to Home Screen" + - Known limitation: Android may freeze background JavaScript after 5-10 minutes for battery saving + - Notifications will stop working after app is frozen by the OS + +**Browser Requirements:** +- Chrome/Edge 81+ (desktop), 84+ (Android) +- Firefox 22+ +- Safari 16.4+ (limited support) + +### Installing as PWA + +To get the full PWA experience with app badge counters: + +**Android:** +1. Open the app in Chrome +2. Menu (โ‹ฎ) โ†’ "Add to Home Screen" +3. Confirm installation +4. App icon will appear on home screen with badge counter support + +**Desktop:** +1. Open the app in Chrome/Edge +2. Look for install prompt in address bar (+ icon) +3. Click "Install" +4. App opens in standalone window + +### Troubleshooting Notifications + +**Notifications not appearing:** +- Verify browser permission granted: Settings โ†’ Site Settings โ†’ Notifications +- Ensure app is running in background (not closed) +- Check that toggle shows "Enabled" (green badge) +- Try refreshing the page + +**Badge counter not showing:** +- Badge API requires PWA to be installed (not just bookmarked) +- Check browser compatibility (Chrome/Edge recommended) + +**Android-specific issues:** +- After 5-10 minutes in background, Android may freeze the app +- This is normal OS behavior for battery saving +- Reopen app to resume notifications +- Full "wake device" support would require Web Push API (not implemented) + +--- + +## Getting Help + +- **Full README:** [README.md](../README.md) +- **Troubleshooting:** [troubleshooting.md](troubleshooting.md) +- **Architecture:** [architecture.md](architecture.md) +- **MeshCore docs:** https://meshcore.org +- **meshcore-cli docs:** https://github.com/meshcore-dev/meshcore-cli +- **GitHub Issues:** https://github.com/MarekWo/mc-webui/issues