Modernize application to v0.9.0 with PySide6, FastAPI, and PWA support
## Major Changes
### Build System
- Replace requirements.txt with pyproject.toml for modern dependency management
- Support for uv package manager alongside pip
- Update PyInstaller spec files for new dependencies and structure
### Desktop GUI (Tkinter → PySide6)
- Complete rewrite of UI using PySide6/Qt6
- New modular structure in gui/ directory:
- main_window.py: Main application window
- macro_editor.py: Macro creation/editing dialog
- command_builder.py: Visual command sequence builder
- Modern dark theme with consistent styling
- System tray integration
### Web Server (Flask → FastAPI)
- Migrate from Flask/Waitress to FastAPI/Uvicorn
- Add WebSocket support for real-time updates
- Full CRUD API for macro management
- Image upload endpoint
### Web Interface → PWA
- New web/ directory with standalone static files
- PWA manifest and service worker for installability
- Offline caching support
- Full macro editing from web interface
- Responsive mobile-first design
- Command builder UI matching desktop functionality
### Macro System Enhancement
- New command sequence model replacing simple text/app types
- Command types: text, key, hotkey, wait, app
- Support for delays between commands (wait in ms)
- Support for key presses between commands (enter, tab, etc.)
- Automatic migration of existing macros to new format
- Backward compatibility maintained
### Files Added
- pyproject.toml
- gui/__init__.py, main_window.py, macro_editor.py, command_builder.py
- gui/widgets/__init__.py
- web/index.html, manifest.json, service-worker.js
- web/css/styles.css, web/js/app.js
- web/icons/icon-192.png, icon-512.png
### Files Removed
- requirements.txt (replaced by pyproject.toml)
- ui_components.py (replaced by gui/ modules)
- web_templates.py (replaced by web/ static files)
- main.spec (consolidated into platform-specific specs)
### Files Modified
- main.py: Simplified entry point for PySide6
- macro_manager.py: Command sequence model and migration
- web_server.py: FastAPI implementation
- config.py: Version bump to 0.9.0
- All .spec files: Updated for PySide6 and new structure
- README.md: Complete rewrite for v0.9.0
- .gitea/workflows/release.yml: Disabled pending build testing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 16:57:14 -08:00
|
|
|
// MacroPad PWA Service Worker
|
2026-01-03 18:34:56 -08:00
|
|
|
const CACHE_NAME = 'macropad-v3';
|
Modernize application to v0.9.0 with PySide6, FastAPI, and PWA support
## Major Changes
### Build System
- Replace requirements.txt with pyproject.toml for modern dependency management
- Support for uv package manager alongside pip
- Update PyInstaller spec files for new dependencies and structure
### Desktop GUI (Tkinter → PySide6)
- Complete rewrite of UI using PySide6/Qt6
- New modular structure in gui/ directory:
- main_window.py: Main application window
- macro_editor.py: Macro creation/editing dialog
- command_builder.py: Visual command sequence builder
- Modern dark theme with consistent styling
- System tray integration
### Web Server (Flask → FastAPI)
- Migrate from Flask/Waitress to FastAPI/Uvicorn
- Add WebSocket support for real-time updates
- Full CRUD API for macro management
- Image upload endpoint
### Web Interface → PWA
- New web/ directory with standalone static files
- PWA manifest and service worker for installability
- Offline caching support
- Full macro editing from web interface
- Responsive mobile-first design
- Command builder UI matching desktop functionality
### Macro System Enhancement
- New command sequence model replacing simple text/app types
- Command types: text, key, hotkey, wait, app
- Support for delays between commands (wait in ms)
- Support for key presses between commands (enter, tab, etc.)
- Automatic migration of existing macros to new format
- Backward compatibility maintained
### Files Added
- pyproject.toml
- gui/__init__.py, main_window.py, macro_editor.py, command_builder.py
- gui/widgets/__init__.py
- web/index.html, manifest.json, service-worker.js
- web/css/styles.css, web/js/app.js
- web/icons/icon-192.png, icon-512.png
### Files Removed
- requirements.txt (replaced by pyproject.toml)
- ui_components.py (replaced by gui/ modules)
- web_templates.py (replaced by web/ static files)
- main.spec (consolidated into platform-specific specs)
### Files Modified
- main.py: Simplified entry point for PySide6
- macro_manager.py: Command sequence model and migration
- web_server.py: FastAPI implementation
- config.py: Version bump to 0.9.0
- All .spec files: Updated for PySide6 and new structure
- README.md: Complete rewrite for v0.9.0
- .gitea/workflows/release.yml: Disabled pending build testing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 16:57:14 -08:00
|
|
|
const ASSETS_TO_CACHE = [
|
|
|
|
|
'/',
|
|
|
|
|
'/static/css/styles.css',
|
|
|
|
|
'/static/js/app.js',
|
|
|
|
|
'/static/icons/icon-192.png',
|
|
|
|
|
'/static/icons/icon-512.png',
|
|
|
|
|
'/manifest.json'
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
// Install event - cache assets
|
|
|
|
|
self.addEventListener('install', (event) => {
|
|
|
|
|
event.waitUntil(
|
|
|
|
|
caches.open(CACHE_NAME)
|
|
|
|
|
.then((cache) => {
|
|
|
|
|
console.log('Caching app assets');
|
|
|
|
|
return cache.addAll(ASSETS_TO_CACHE);
|
|
|
|
|
})
|
|
|
|
|
.then(() => self.skipWaiting())
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Activate event - clean old caches
|
|
|
|
|
self.addEventListener('activate', (event) => {
|
|
|
|
|
event.waitUntil(
|
|
|
|
|
caches.keys().then((cacheNames) => {
|
|
|
|
|
return Promise.all(
|
|
|
|
|
cacheNames
|
|
|
|
|
.filter((name) => name !== CACHE_NAME)
|
|
|
|
|
.map((name) => caches.delete(name))
|
|
|
|
|
);
|
|
|
|
|
}).then(() => self.clients.claim())
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Fetch event - serve from cache, fallback to network
|
|
|
|
|
self.addEventListener('fetch', (event) => {
|
|
|
|
|
const url = new URL(event.request.url);
|
|
|
|
|
|
|
|
|
|
// Always fetch API requests from network
|
|
|
|
|
if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/ws')) {
|
|
|
|
|
event.respondWith(fetch(event.request));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For other requests, try cache first, then network
|
|
|
|
|
event.respondWith(
|
|
|
|
|
caches.match(event.request)
|
|
|
|
|
.then((response) => {
|
|
|
|
|
if (response) {
|
|
|
|
|
return response;
|
|
|
|
|
}
|
|
|
|
|
return fetch(event.request).then((networkResponse) => {
|
|
|
|
|
// Cache successful responses
|
|
|
|
|
if (networkResponse && networkResponse.status === 200) {
|
|
|
|
|
const responseClone = networkResponse.clone();
|
|
|
|
|
caches.open(CACHE_NAME).then((cache) => {
|
|
|
|
|
cache.put(event.request, responseClone);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return networkResponse;
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {
|
|
|
|
|
// Return offline fallback for navigation requests
|
|
|
|
|
if (event.request.mode === 'navigate') {
|
|
|
|
|
return caches.match('/');
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
});
|