feat: donation banner, About tab, settings UI improvements
Some checks failed
Lint & Test / test (push) Has been cancelled

- Dismissible donation/open-source banner after 3+ sessions (30-day snooze)
- New About tab in Settings: version, repo link, license info
- Centralize project URLs (REPO_URL, DONATE_URL) in __init__.py, served via /health
- Center settings tab bar, reduce tab padding for 6-tab fit
- External URL save button: icon button instead of full-width text button
- Remove redundant settings footer close button
- Footer "Source Code" link replaced with "About" opening settings
- i18n keys for en/ru/zh
This commit is contained in:
2026-03-27 21:09:34 +03:00
parent f61a0206d4
commit f3d07fc47f
18 changed files with 442 additions and 49 deletions

View File

@@ -8,7 +8,7 @@ import { Modal } from './core/modal.ts';
import { queryEl } from './core/dom-utils.ts';
// Layer 1: api, i18n
import { loadServerInfo, loadDisplays, configureApiKey, startConnectionMonitor, stopConnectionMonitor } from './core/api.ts';
import { loadServerInfo, loadDisplays, configureApiKey, startConnectionMonitor, stopConnectionMonitor, serverRepoUrl, serverDonateUrl } from './core/api.ts';
import { t, initLocale, changeLocale } from './core/i18n.ts';
// Layer 1.5: visual effects
@@ -205,6 +205,9 @@ import {
initUpdateSettingsPanel, applyUpdate,
openReleaseNotes, closeReleaseNotes,
} from './features/update.ts';
import {
initDonationBanner, dismissDonation, snoozeDonation, renderAboutPanel, setProjectUrls,
} from './features/donation.ts';
// ─── Register all HTML onclick / onchange / onfocus globals ───
@@ -576,6 +579,11 @@ Object.assign(window, {
openReleaseNotes,
closeReleaseNotes,
// donation
dismissDonation,
snoozeDonation,
renderAboutPanel,
// appearance
applyStylePreset,
applyBgEffect,
@@ -723,6 +731,10 @@ document.addEventListener('DOMContentLoaded', async () => {
initUpdateListener();
loadUpdateStatus();
// Show donation banner (after a few sessions)
setProjectUrls(serverRepoUrl, serverDonateUrl);
initDonationBanner();
// Show getting-started tutorial on first visit
if (!localStorage.getItem('tour_completed')) {
setTimeout(() => startGettingStartedTutorial(), 600);