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>
This commit is contained in:
MarekWo
2026-01-05 21:26:26 +01:00
parent 964d88a14a
commit 4bd6a681db
10 changed files with 2834 additions and 14 deletions

View File

@@ -41,8 +41,8 @@ A lightweight web interface for meshcore-cli, providing browser-based access to
- 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
- Bootstrap CSS/JS and icons hosted locally (no CDN dependency)
- Service Worker caches all UI assets automatically
- 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

View File

@@ -1254,6 +1254,8 @@ function setupEmojiPicker() {
// Create emoji-picker element
const picker = document.createElement('emoji-picker');
// Use local emoji data instead of CDN
picker.dataSource = '/static/vendor/emoji-picker-element-data/en/emojibase/data.json';
emojiPickerPopup.appendChild(picker);
// Toggle emoji picker on button click

View File

@@ -579,6 +579,8 @@ function setupEmojiPicker() {
// Create emoji-picker element
const picker = document.createElement('emoji-picker');
// Use local emoji data instead of CDN
picker.dataSource = '/static/vendor/emoji-picker-element-data/en/emojibase/data.json';
emojiPickerPopup.appendChild(picker);
// Toggle emoji picker on button click

View File

@@ -1,4 +1,4 @@
const CACHE_NAME = 'mc-webui-v2';
const CACHE_NAME = 'mc-webui-v3';
const ASSETS_TO_CACHE = [
'/',
'/static/css/style.css',
@@ -14,7 +14,12 @@ const ASSETS_TO_CACHE = [
// Bootstrap Icons 1.11.2 (local)
'/static/vendor/bootstrap-icons/bootstrap-icons.css',
'/static/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2',
'/static/vendor/bootstrap-icons/fonts/bootstrap-icons.woff'
'/static/vendor/bootstrap-icons/fonts/bootstrap-icons.woff',
// Emoji Picker Element 1.28.1 (local)
'/static/vendor/emoji-picker-element/index.js',
'/static/vendor/emoji-picker-element/picker.js',
'/static/vendor/emoji-picker-element/database.js',
'/static/vendor/emoji-picker-element-data/en/emojibase/data.json'
];
// Install event - cache core assets

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
import Picker from './picker.js'
import Database from './database.js'
export { Picker, Database }

File diff suppressed because one or more lines are too long

View File

@@ -12,16 +12,16 @@
<link rel="manifest" href="{{ url_for('static', filename='manifest.json') }}">
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap Icons -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.css">
<!-- Bootstrap 5 CSS (local) -->
<link href="{{ url_for('static', filename='vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
<!-- Bootstrap Icons (local) -->
<link rel="stylesheet" href="{{ url_for('static', filename='vendor/bootstrap-icons/bootstrap-icons.css') }}">
<!-- Custom CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<!-- Emoji Picker -->
<script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js"></script>
<!-- Emoji Picker (local) -->
<script type="module" src="{{ url_for('static', filename='vendor/emoji-picker-element/index.js') }}"></script>
<style>
emoji-picker {
--emoji-size: 1.5rem;
@@ -144,8 +144,8 @@
</div>
</div>
<!-- Bootstrap 5 JS Bundle -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<!-- Bootstrap 5 JS Bundle (local) -->
<script src="{{ url_for('static', filename='vendor/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<!-- Message Content Processing Utilities (must load before dm.js) -->
<script src="{{ url_for('static', filename='js/message-utils.js') }}"></script>

View File

@@ -3,8 +3,8 @@
{% block title %}Chat - mc-webui{% endblock %}
{% block extra_head %}
<!-- Emoji Picker -->
<script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js"></script>
<!-- Emoji Picker (local) -->
<script type="module" src="{{ url_for('static', filename='vendor/emoji-picker-element/index.js') }}"></script>
<style>
emoji-picker {
--emoji-size: 1.5rem;