Почтовый кабинет: регистрация, папки, черновики, вложения, грид @jambotron/aria-grid, интерфейс по synthwave-шаблону
Бэкенд: регистрация со входом сразу и /api/config, профиль и смена пароля, свои папки, PATCH письма (прочитано, флажок, перенос; Спам ставит отметку), корзина и очистка, черновики, несколько адресатов и копия, вложения черновика уходят с письмом, вложения и заголовки To/Cc входящих сохраняются, письма заблокированных — в Спам. Исправлено: загрузка файла (415), колонка content_id (500 на любых вложениях), SPA-маршрут с точкой. Фронтенд переписан: все таблицы — грид, оформление — шаблон synthwave-design-showcase.html. α Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
import { Injectable, effect, signal } from '@angular/core';
|
||||
|
||||
export const THEMES = [
|
||||
{ value: 'theme-cyber-magenta', label: 'Cyber Magenta' },
|
||||
{ value: 'theme-neon-cyan', label: 'Neon Cyan' },
|
||||
{ value: 'theme-sunset-orange', label: 'Sunset Orange' },
|
||||
{ value: 'theme-matrix-green', label: 'Matrix Green' }
|
||||
];
|
||||
|
||||
/** Palette, high contrast and background motion — on <html>, remembered in this browser. */
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ThemeService {
|
||||
readonly theme = signal(load('theme', THEMES[0].value));
|
||||
readonly highContrast = signal(load('contrast', 'off') === 'on');
|
||||
readonly animation = signal(load('animation', 'on') === 'on');
|
||||
|
||||
constructor() {
|
||||
effect(() => {
|
||||
const root = document.documentElement;
|
||||
THEMES.forEach(t => root.classList.toggle(t.value, t.value === this.theme()));
|
||||
root.classList.toggle('high-contrast', this.highContrast());
|
||||
root.classList.toggle('no-anim', !this.animation());
|
||||
save('theme', this.theme());
|
||||
save('contrast', this.highContrast() ? 'on' : 'off');
|
||||
save('animation', this.animation() ? 'on' : 'off');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function load(key: string, fallback: string): string {
|
||||
try { return localStorage.getItem('ui.' + key) ?? fallback; } catch { return fallback; }
|
||||
}
|
||||
|
||||
function save(key: string, value: string): void {
|
||||
try { localStorage.setItem('ui.' + key, value); } catch { /* storage blocked */ }
|
||||
}
|
||||
Reference in New Issue
Block a user