- Restore the if($bringEnabled) block that was accidentally removed in fa0442e
- Check is skipped entirely when SHOPPING_MODE != bring or credentials not set
- Missing token file = first launch, auto-created on next shopping open → ok:true
- Warning shown only if token file exists but access_token field is missing (corrupt)
- Expired tokens are OK (refreshed automatically)
Fixes spurious 'Token Bring!' warning on installs without Bring! configured
- PHP (all 3 recipe endpoints): conf products with weight/volume package_unit
(e.g., 300g/conf) now keep qty_number in sub-units (grams/ml) instead of
converting to fractional conf. Post-normalisation block converts any AI-
returned fractional conf values to grams automatically.
- JS submitRecipeUse: vacuum state now read from actual inventory item at the
used location (_recipeUseContext.items), not from recipe ingredient data.
- JS showRecipeMoveModal: now uses _prefMoveLocCache preference system —
after 2 consistent choices the modal is skipped automatically. 'Stay' button
records the choice. Added _recipeMoveCancelStay() helper.
- JS confirmRecipeMove: records move choice via _recordMoveLocChoice();
accepts optional forcedVacuum param for preference-triggered auto-moves.
Closes#108 (duplicate of #107 — data dir permissions)
- getSettings() no longer reads from localStorage; uses _settingsCache only
- saveSettingsToStorage() no longer writes to localStorage
- _applySyncedSettings() no longer writes to localStorage
- syncSettingsFromDB() meal_plan/tts_voice blocks no longer write to localStorage
- loadSettingsUI() server-merge block no longer writes to localStorage
- flipCamera() saves camera_facing directly to server via _saveSettingToServer()
- New helper _saveSettingToServer(data): calls save_settings API for partial updates
- onShoppingEnabledChange() / onShoppingModeChange() now immediately persist to
server .env via _saveSettingToServer() — no wait for Save button
- Early-theme IIFE: reads dedicated evershelf_dark_mode key (falls back to old
evershelf_settings for backward compat) — only dark_mode kept in localStorage
as a technical necessity for pre-render theme application
- New shopping_list SQLite table (migration in migrateDB)
- shoppingGetList/Add/Remove — delegates to Bring! or internal DB
based on SHOPPING_MODE env var (default: internal)
- isShoppingBringMode() guard: requires mode=bring + BRING credentials
- bringQuickSyncProduct updated to support both modes
- All bring_* JS calls replaced with shopping_* (bring_migrate_names kept)
- New settings tab 'Lista spesa' (tab-bring) with:
- Enable/disable shopping list toggle
- Provider radio: internal vs Bring!
- Bring! sub-section (shown only when mode=bring)
- AI smart suggestions toggle
- Forecast toggle
- Auto-add threshold (qty slider)
- Price estimation section
- _applyShoppingSettingsUI, onShoppingEnabledChange, onShoppingModeChange
- SHOPPING_* env vars documented in .env.example
- cron_smart_shopping respects SHOPPING_MODE and SHOPPING_SMART_SUGGESTIONS
- Translations: 12 new keys in all 5 languages (it/en/de/fr/es)
- DB busy_timeout=5000ms + WAL pragma in getDB() (fixes#95)
- New '🤝 Contributing' section with translation table, skill matrix,
and links to good first issues and help wanted labels
- New '💬 Community' section linking to GitHub Discussions
- Visible call-to-action for translators pointing to issue #93
- Switch redirect URI from server IP to http://localhost (works everywhere)
- Add manual code exchange flow: user copies URL from browser, pastes in app
- New PHP action gdrive_oauth_exchange to exchange auth code for refresh token
- Fix null bug in gdrive_oauth_exchange (was read before initialization)
- Add #gdrive-code-section UI with input + submit button in index.html
- Update _gdriveAuthorize() to show code section and store redirect_uri
- Add _gdriveSubmitCode() JS function for manual code submission
- Update setup wizard and backup tab to show http://localhost as redirect URI
- Add 5 new translation keys (gdrive_redirect_uri_hint, gdrive_code_title,
gdrive_code_hint, gdrive_code_submit, gdrive_code_empty) in all 5 languages
- Update gdrive_oauth_steps in all translations to reflect new flow
- Document Google Drive OAuth setup in README.md
- Dark mode: comprehensive fix for 30+ components with hardcoded light colors