Merge pull request #235 from gamosoft/features/autosave-delay-config

configurable autosave
This commit is contained in:
Guillermo Villar 2026-06-08 11:02:28 +02:00 committed by GitHub
commit e715639a43
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 51 additions and 4 deletions

View File

@ -230,6 +230,16 @@ UPLOAD_MAX_AUDIO_MB = int(os.getenv('UPLOAD_MAX_AUDIO_MB', '50'))
UPLOAD_MAX_VIDEO_MB = int(os.getenv('UPLOAD_MAX_VIDEO_MB', '100'))
UPLOAD_MAX_PDF_MB = int(os.getenv('UPLOAD_MAX_PDF_MB', '20'))
# Autosave debounce in milliseconds (applies to note typing AND drawing PNG autosave).
try:
_autosave_raw = int(os.getenv(
'AUTOSAVE_DELAY_MS',
str(config.get('ui', {}).get('autosave_delay_ms', 1000))
))
except (TypeError, ValueError):
_autosave_raw = 1000
AUTOSAVE_DELAY_MS = max(250, min(60000, _autosave_raw))
if DEMO_MODE:
# Enable rate limiting for demo deployments
limiter = Limiter(key_func=get_remote_address, default_limits=["200/hour"])
@ -488,6 +498,7 @@ async def get_config():
"searchEnabled": config['search']['enabled'],
"demoMode": DEMO_MODE, # Expose demo mode flag to frontend
"alreadyDonated": ALREADY_DONATED, # Hide support buttons if true
"autosaveDelayMs": AUTOSAVE_DELAY_MS, # Debounce for note/drawing autosave
"authentication": {
"enabled": config.get('authentication', {}).get('enabled', False)
}

View File

@ -23,6 +23,13 @@ storage:
search:
enabled: true
# User interface behavior
ui:
# Autosave debounce in milliseconds (applies to note typing and drawing autosave).
# Lower = saves more often (more disk writes); higher = saves less often.
# Override via the AUTOSAVE_DELAY_MS env var. Server clamps to 250-60000ms.
autosave_delay_ms: 1000
authentication:
# Authentication settings
# Set enabled to true to require login

View File

@ -67,6 +67,30 @@ environment:
- UPLOAD_MAX_VIDEO_MB=500
```
### User Interface
| Variable | Type | Default | Description |
|----------|------|---------|-------------|
| `AUTOSAVE_DELAY_MS` | integer | `1000` | Autosave debounce in milliseconds (applies to note typing and drawing autosave). Server-clamped to 25060000ms. |
#### Example: Slower autosave for very large notes
```bash
# Docker
docker run -e AUTOSAVE_DELAY_MS=5000 ...
# Docker Compose
environment:
- AUTOSAVE_DELAY_MS=5000
```
Equivalent in `config.yaml`:
```yaml
ui:
autosave_delay_ms: 5000
```
## 🎯 Configuration Priority
Configuration is loaded in this order (later overrides earlier):

View File

@ -2,7 +2,7 @@
// Configuration constants
const CONFIG = {
AUTOSAVE_DELAY: 1000, // ms - Debounce before note save (autoSave) and drawing PNG autosave (_drawingScheduleAutosave)
AUTOSAVE_DELAY: 1000, // ms - Fallback only; runtime value lives on this.autosaveDelayMs (hydrated from /api/config). Used by autoSave() and _drawingScheduleAutosave().
/** Must match drawingRedraw() fill and eraser stroke color (opaque “whiteboard”). */
DRAWING_BACKGROUND: '#ffffff',
/**
@ -260,6 +260,7 @@ function noteApp() {
authEnabled: false,
demoMode: false,
alreadyDonated: false,
autosaveDelayMs: CONFIG.AUTOSAVE_DELAY, // hydrated from /api/config in loadConfig()
notes: [],
currentNote: '',
currentNoteName: '',
@ -959,6 +960,10 @@ function noteApp() {
this.authEnabled = config.authentication?.enabled || false;
this.demoMode = config.demoMode || false;
this.alreadyDonated = config.alreadyDonated || false;
// Server already clamps autosaveDelayMs to a sane range; we just sanity-check the type.
if (Number.isFinite(config.autosaveDelayMs) && config.autosaveDelayMs > 0) {
this.autosaveDelayMs = config.autosaveDelayMs;
}
} catch (error) {
console.error('Failed to load config:', error);
}
@ -3253,7 +3258,7 @@ function noteApp() {
this._drawingAutosaveTimeout = null;
this.drawingSave();
};
this._drawingAutosaveTimeout = setTimeout(attemptSave, CONFIG.AUTOSAVE_DELAY);
this._drawingAutosaveTimeout = setTimeout(attemptSave, this.autosaveDelayMs);
},
/**
@ -5064,7 +5069,7 @@ function noteApp() {
this.commitToHistory();
}
this.saveNote();
}, CONFIG.AUTOSAVE_DELAY);
}, this.autosaveDelayMs);
},
// Mark that we have pending changes (called on each keystroke)