From 8c3db305ca72b6e15073a648870cac35e8538baa Mon Sep 17 00:00:00 2001 From: Fovway Date: Mon, 3 Nov 2025 01:00:52 +0700 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D1=8B=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D0=BD=D0=B0?= =?UTF-8?q?=D1=81=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B8=20=D0=BF=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8F:=20?= =?UTF-8?q?=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BE=D1=82=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D0=B4=D0=B0=D1=82=D1=8B=20=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B0=D0=BA=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=B8=20=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=86=D0=B2=D0=B5=D1=82?= =?UTF-8?q?=D0=BD=D1=8B=D1=85=20=D0=B8=D0=BA=D0=BE=D0=BD=D0=BE=D0=BA.=20?= =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20=D1=81?= =?UTF-8?q?=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D1=83?= =?UTF-8?q?=D1=8E=D1=89=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BE=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D1=82=D1=8B=20=D0=B8=20=D1=81=D1=82=D0=B8=D0=BB?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D0=BE=D0=B4=D0=B4=D0=B5?= =?UTF-8?q?=D1=80=D0=B6=D0=BA=D0=B8=20=D0=BD=D0=BE=D0=B2=D1=8B=D1=85=20?= =?UTF-8?q?=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=B9.=20=D0=A0=D0=B5?= =?UTF-8?q?=D0=B0=D0=BB=D0=B8=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B0=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BB=D0=BE=D0=BD?= =?UTF-8?q?=D0=BE=D0=BA=20=D0=B2=20=D0=B1=D0=B0=D0=B7=D1=83=20=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D1=85=20=D0=BF=D1=80=D0=B8=20=D0=BE=D1=82?= =?UTF-8?q?=D1=81=D1=83=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8.=20=D0=9E?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D1=8B=20API=20=D0=B8?= =?UTF-8?q?=20=D0=B8=D0=BD=D1=82=D0=B5=D1=80=D1=84=D0=B5=D0=B9=D1=81=D1=8B?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B=20?= =?UTF-8?q?=D1=81=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=BC=D0=B8=20=D0=BF=D0=B0?= =?UTF-8?q?=D1=80=D0=B0=D0=BC=D0=B5=D1=82=D1=80=D0=B0=D0=BC=D0=B8.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/server.js | 52 +++++- dev-dist/sw.js | 2 +- src/api/userApi.ts | 2 + src/components/layout/Header.tsx | 8 + src/components/notes/NoteItem.tsx | 37 ++-- src/pages/SettingsPage.tsx | 71 ++++++- src/styles/style.css | 295 +++++++++++++++++++----------- src/types/user.ts | 2 + 8 files changed, 343 insertions(+), 126 deletions(-) diff --git a/backend/server.js b/backend/server.js index d35a9f8..600852e 100644 --- a/backend/server.js +++ b/backend/server.js @@ -464,6 +464,42 @@ function runMigrations() { }); } + // Проверяем существование колонки show_edit_date + const hasShowEditDate = columns.some((col) => col.name === "show_edit_date"); + if (!hasShowEditDate) { + db.run( + "ALTER TABLE users ADD COLUMN show_edit_date INTEGER DEFAULT 1", + (err) => { + if (err) { + console.error( + "Ошибка добавления колонки show_edit_date:", + err.message + ); + } else { + console.log("Колонка show_edit_date добавлена в таблицу users"); + } + } + ); + } + + // Проверяем существование колонки colored_icons + const hasColoredIcons = columns.some((col) => col.name === "colored_icons"); + if (!hasColoredIcons) { + db.run( + "ALTER TABLE users ADD COLUMN colored_icons INTEGER DEFAULT 1", + (err) => { + if (err) { + console.error( + "Ошибка добавления колонки colored_icons:", + err.message + ); + } else { + console.log("Колонка colored_icons добавлена в таблицу users"); + } + } + ); + } + // Проверяем существование колонки ai_enabled const hasAiEnabled = columns.some((col) => col.name === "ai_enabled"); if (!hasAiEnabled) { @@ -733,7 +769,7 @@ app.get("/api/user", requireApiAuth, (req, res) => { } const sql = - "SELECT username, email, avatar, accent_color FROM users WHERE id = ?"; + "SELECT username, email, avatar, accent_color, show_edit_date, colored_icons FROM users WHERE id = ?"; db.get(sql, [req.session.userId], (err, user) => { if (err) { console.error("Ошибка получения данных пользователя:", err.message); @@ -1528,7 +1564,7 @@ app.get("/profile", requireAuth, (req, res) => { // API для обновления профиля app.put("/api/user/profile", requireApiAuth, async (req, res) => { - const { username, email, currentPassword, newPassword, accent_color } = + const { username, email, currentPassword, newPassword, accent_color, show_edit_date, colored_icons } = req.body; const userId = req.session.userId; @@ -1594,6 +1630,16 @@ app.put("/api/user/profile", requireApiAuth, async (req, res) => { params.push(accent_color || "#007bff"); } + if (show_edit_date !== undefined) { + updateFields.push("show_edit_date = ?"); + params.push(show_edit_date ? 1 : 0); + } + + if (colored_icons !== undefined) { + updateFields.push("colored_icons = ?"); + params.push(colored_icons ? 1 : 0); + } + if (newPassword) { const hashedPassword = await bcrypt.hash(newPassword, 10); updateFields.push("password = ?"); @@ -1628,6 +1674,8 @@ app.put("/api/user/profile", requireApiAuth, async (req, res) => { if (username && username !== user.username) changes.push("логин"); if (email !== undefined) changes.push("email"); if (accent_color !== undefined) changes.push("цвет темы"); + if (show_edit_date !== undefined) changes.push("настройка показа даты редактирования"); + if (colored_icons !== undefined) changes.push("цветные иконки"); if (newPassword) changes.push("пароль"); const details = `Обновлен профиль: ${changes.join(", ")}`; logAction(userId, "profile_update", details); diff --git a/dev-dist/sw.js b/dev-dist/sw.js index 0786127..9adc105 100644 --- a/dev-dist/sw.js +++ b/dev-dist/sw.js @@ -85,7 +85,7 @@ define(['./workbox-8cfb3eb5'], (function (workbox) { 'use strict'; "revision": "3ca0b8505b4bec776b69afdba2768812" }, { "url": "index.html", - "revision": "0.tihabijh3s" + "revision": "0.8irmmrfvp3g" }], {}); workbox.cleanupOutdatedCaches(); workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { diff --git a/src/api/userApi.ts b/src/api/userApi.ts index 62f47fc..3655742 100644 --- a/src/api/userApi.ts +++ b/src/api/userApi.ts @@ -12,6 +12,8 @@ export const userApi = { currentPassword?: string; newPassword?: string; accent_color?: string; + show_edit_date?: boolean; + colored_icons?: boolean; } ) => { const { data } = await axiosClient.put("/user/profile", profile); diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index a16cb67..5fb6966 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -43,6 +43,14 @@ export const Header: React.FC = ({ dispatch(setAccentColorAction(accent)); setAccentColor(accent); + // Применяем настройку цветных иконок + const coloredIcons = userData.colored_icons !== undefined ? userData.colored_icons === 1 : true; + if (coloredIcons) { + document.body.classList.add("colored-icons"); + } else { + document.body.classList.remove("colored-icons"); + } + // Загружаем AI настройки try { const aiSettings = await userApi.getAiSettings(); diff --git a/src/components/notes/NoteItem.tsx b/src/components/notes/NoteItem.tsx index 09b57f0..01fedb5 100644 --- a/src/components/notes/NoteItem.tsx +++ b/src/components/notes/NoteItem.tsx @@ -62,6 +62,7 @@ export const NoteItem: React.FC = ({ const searchQuery = useAppSelector((state) => state.notes.searchQuery); const isPreviewMode = useAppSelector((state) => state.ui.isPreviewMode); const aiEnabled = useAppSelector((state) => state.profile.aiEnabled); + const user = useAppSelector((state) => state.profile.user); const { showNotification } = useNotification(); const dispatch = useAppDispatch(); useMarkdown({ onNoteUpdate: onReload }); // Инициализируем обработчики спойлеров, внешних ссылок и чекбоксов @@ -914,6 +915,7 @@ export const NoteItem: React.FC = ({ ); if (note.updated_at && note.created_at !== note.updated_at) { + const showEditDate = user?.show_edit_date !== undefined ? user.show_edit_date === 1 : true; const updated = parseSQLiteUtc(note.updated_at); const updatedStr = formatLocalDateTime(updated); // Убеждаемся, что строка не содержит лишних символов @@ -921,17 +923,30 @@ export const NoteItem: React.FC = ({ /(\d{2}\.\d{2}\.\d{4} \d{2}:\d{2})\d*.*/, "$1" ); - return ( - <> - {cleanCreatedStr} - | - - {cleanUpdatedStr} - - ); + + if (showEditDate) { + return ( + <> + {cleanCreatedStr} + | + + {cleanUpdatedStr} + + ); + } else { + return ( + <> + {cleanCreatedStr} + + + ); + } } else { return cleanCreatedStr; } diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index a7b8842..6679387 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -29,6 +29,8 @@ const SettingsPage: React.FC = () => { // Appearance settings const [selectedAccentColor, setSelectedAccentColor] = useState("#007bff"); + const [showEditDate, setShowEditDate] = useState(true); + const [coloredIcons, setColoredIcons] = useState(true); // AI settings const [apiKey, setApiKey] = useState(""); @@ -84,6 +86,10 @@ const SettingsPage: React.FC = () => { setSelectedAccentColor(accent); dispatch(setAccentColorAction(accent)); setAccentColor(accent); + setShowEditDate(userData.show_edit_date !== undefined ? userData.show_edit_date === 1 : true); + const coloredIconsValue = userData.colored_icons !== undefined ? userData.colored_icons === 1 : true; + setColoredIcons(coloredIconsValue); + updateColoredIconsClass(coloredIconsValue); // Загружаем AI настройки try { @@ -114,13 +120,17 @@ const SettingsPage: React.FC = () => { try { await userApi.updateProfile({ accent_color: selectedAccentColor, + show_edit_date: showEditDate, + colored_icons: coloredIcons, }); dispatch(setAccentColorAction(selectedAccentColor)); setAccentColor(selectedAccentColor); await loadUserInfo(); - showNotification("Цветовой акцент успешно обновлен", "success"); + // Обновляем класс на body для управления цветными иконками + updateColoredIconsClass(coloredIcons); + showNotification("Настройки внешнего вида успешно обновлены", "success"); } catch (error: any) { - console.error("Ошибка обновления цветового акцента:", error); + console.error("Ошибка обновления настроек внешнего вида:", error); showNotification( error.response?.data?.error || "Ошибка обновления", "error" @@ -128,6 +138,14 @@ const SettingsPage: React.FC = () => { } }; + const updateColoredIconsClass = (enabled: boolean) => { + if (enabled) { + document.body.classList.add("colored-icons"); + } else { + document.body.classList.remove("colored-icons"); + } + }; + const handleUpdateAiSettings = async () => { if (!apiKey.trim()) { showNotification("API ключ обязателен", "error"); @@ -420,6 +438,55 @@ const SettingsPage: React.FC = () => { +
+ +
+ +
+ +
+ diff --git a/src/styles/style.css b/src/styles/style.css index 985bbaf..b1049ab 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -179,26 +179,178 @@ header .iconify { margin-right: 6px; } -/* Цветные иконки */ -/* Иконка поиска - синий */ -.search-title .iconify[data-icon="mdi:magnify"] { - color: var(--icon-search); +/* Цветные иконки - для кнопок заметок и заголовков страниц */ +.colored-icons .iconify svg, +.colored-icons iconify-icon svg { + fill: currentColor !important; } -/* Иконка тегов - зеленый */ -.tags-title .iconify[data-icon="mdi:tag"] { - color: var(--icon-tags); +/* Универсальное правило для всех SVG в заголовках */ +.colored-icons header svg, +.colored-icons header img[role="img"] svg { + fill: currentColor !important; } -/* Иконка заметок - оранжевый */ -header .iconify[data-icon="mdi:note-text"] { - color: var(--icon-notes); +/* Иконки в заголовках страниц */ +/* Мои заметки - оранжевый */ +.colored-icons .notes-header-left .iconify, +.colored-icons .notes-header-left iconify-icon, +.colored-icons header .notes-header-left .iconify, +.colored-icons header .notes-header-left iconify-icon, +.colored-icons header .notes-header-left svg, +.colored-icons header .notes-header span .iconify, +.colored-icons header .notes-header span iconify-icon, +.colored-icons header .notes-header span svg, +.colored-icons .notes-header-left img[src*="data:image/svg"], +.colored-icons header .notes-header-left img[src*="data:image/svg"], +.colored-icons header .notes-header span img[src*="data:image/svg"] { + color: #ff9800 !important; + fill: #ff9800 !important; } -/* Иконка пользователя - фиолетовый */ -header .iconify[data-icon="mdi:account"], -.username-clickable .iconify[data-icon="mdi:account"] { - color: var(--icon-user); +.colored-icons .notes-header-left svg, +.colored-icons header .notes-header-left svg, +.colored-icons header .notes-header span svg, +.colored-icons .notes-header-left img svg, +.colored-icons header .notes-header-left img svg { + fill: #ff9800 !important; +} + +/* Все SVG внутри notes-header-left */ +.colored-icons .notes-header-left svg path, +.colored-icons header .notes-header-left svg path { + fill: #ff9800 !important; +} + +/* Настройки - серый/синий */ +.colored-icons .settings-icon-btn .iconify, +.colored-icons .settings-icon-btn iconify-icon, +.colored-icons header button.settings-icon-btn .iconify, +.colored-icons header button.settings-icon-btn iconify-icon, +.colored-icons .settings-icon-btn svg, +.colored-icons header button.settings-icon-btn svg, +.colored-icons .settings-icon-btn svg path, +.colored-icons header button.settings-icon-btn svg path { + color: #607d8b !important; + fill: #607d8b !important; +} + +/* Профиль - фиолетовый */ +.colored-icons .user-avatar-placeholder-mini .iconify, +.colored-icons .user-avatar-placeholder-mini iconify-icon, +.colored-icons header .user-avatar-placeholder-mini .iconify, +.colored-icons header .user-avatar-placeholder-mini iconify-icon, +.colored-icons .user-avatar-placeholder-mini svg, +.colored-icons header .user-avatar-placeholder-mini svg, +.colored-icons .user-avatar-placeholder-mini svg path, +.colored-icons header .user-avatar-placeholder-mini svg path { + color: #9c27b0 !important; + fill: #9c27b0 !important; +} + +/* Выйти - красный */ +.colored-icons .logout-btn .iconify, +.colored-icons .logout-btn iconify-icon, +.colored-icons header button.logout-btn .iconify, +.colored-icons header button.logout-btn iconify-icon, +.colored-icons .logout-btn svg, +.colored-icons header button.logout-btn svg, +.colored-icons .logout-btn svg path, +.colored-icons header button.logout-btn svg path { + color: #f44336 !important; + fill: #f44336 !important; +} + +/* Вход - синий */ +.colored-icons header .iconify[data-icon="mdi:login"], +.colored-icons header iconify-icon[icon="mdi:login"] { + color: #2196f3 !important; + fill: #2196f3 !important; +} + +/* Регистрация - зеленый */ +.colored-icons header .iconify[data-icon="mdi:account-plus"], +.colored-icons header iconify-icon[icon="mdi:account-plus"] { + color: #4caf50 !important; + fill: #4caf50 !important; +} + +/* Заголовок Настройки - серый/синий */ +.colored-icons header.notes-header span:first-child .iconify, +.colored-icons header.notes-header span:first-child iconify-icon, +.colored-icons header.notes-header span:first-child svg, +.colored-icons header.notes-header span:first-child svg path { + color: #607d8b !important; + fill: #607d8b !important; +} + +/* Кнопки в заголовке настроек */ +.colored-icons header .notes-btn .iconify, +.colored-icons header .notes-btn iconify-icon, +.colored-icons header button.notes-btn .iconify, +.colored-icons header button.notes-btn iconify-icon, +.colored-icons header .notes-btn svg, +.colored-icons header button.notes-btn svg, +.colored-icons header .notes-btn svg path, +.colored-icons header button.notes-btn svg path { + color: #ff9800 !important; + fill: #ff9800 !important; +} + +.colored-icons header .profile-btn .iconify, +.colored-icons header .profile-btn iconify-icon, +.colored-icons header button.profile-btn .iconify, +.colored-icons header button.profile-btn iconify-icon, +.colored-icons header .profile-btn svg, +.colored-icons header button.profile-btn svg, +.colored-icons header .profile-btn svg path, +.colored-icons header button.profile-btn svg path { + color: #9c27b0 !important; + fill: #9c27b0 !important; +} + +/* Табы в настройках */ +.colored-icons .settings-tab .iconify[data-icon="mdi:palette"], +.colored-icons .settings-tab iconify-icon[icon="mdi:palette"] { + color: #e91e63 !important; + fill: #e91e63 !important; +} + +.colored-icons .settings-tab .iconify[data-icon="mdi:robot"], +.colored-icons .settings-tab iconify-icon[icon="mdi:robot"] { + color: #ff6f00 !important; + fill: #ff6f00 !important; +} + +.colored-icons .settings-tab .iconify[data-icon="mdi:archive"], +.colored-icons .settings-tab iconify-icon[icon="mdi:archive"] { + color: #ff9800 !important; + fill: #ff9800 !important; +} + +.colored-icons .settings-tab .iconify[data-icon="mdi:history"], +.colored-icons .settings-tab iconify-icon[icon="mdi:history"] { + color: #9c27b0 !important; + fill: #9c27b0 !important; +} + +/* Иконки кнопок заметок - цветные при включенной настройке */ +.colored-icons .note-actions .notesHeaderBtn:nth-child(1) .iconify, +.colored-icons .note-actions .notesHeaderBtn:nth-child(1) iconify-icon { + color: #ff9800 !important; + fill: #ff9800 !important; +} + +.colored-icons .note-actions .notesHeaderBtn:nth-child(2) .iconify, +.colored-icons .note-actions .notesHeaderBtn:nth-child(2) iconify-icon { + color: #2196f3 !important; + fill: #2196f3 !important; +} + +.colored-icons .note-actions .notesHeaderBtn:nth-child(3) .iconify, +.colored-icons .note-actions .notesHeaderBtn:nth-child(3) iconify-icon { + color: #dc3545 !important; + fill: #dc3545 !important; } /* Переключатель темы */ @@ -235,97 +387,6 @@ header .iconify[data-icon="mdi:account"], color: white; } -/* Иконка входа - синий */ -header .iconify[data-icon="mdi:login"] { - color: #2196f3; -} - -/* Иконка регистрации - зеленый */ -header .iconify[data-icon="mdi:account-plus"] { - color: #4caf50; -} - -/* Markdown кнопки - разные цвета */ -.btnMarkdown .iconify[data-icon="mdi:format-bold"] { - color: #d32f2f; -} - -.btnMarkdown .iconify[data-icon="mdi:format-italic"] { - color: #f57c00; -} - -.btnMarkdown .iconify[data-icon="mdi:palette"] { - color: #e91e63; -} - -.btnMarkdown .iconify[data-icon="mdi:format-header-1"] { - color: #1976d2; -} - -.btnMarkdown .iconify[data-icon="mdi:format-header-pound"] { - color: #1976d2; -} - -.btnMarkdown .iconify[data-icon="mdi:format-list-bulleted"] { - color: #388e3c; -} - -.btnMarkdown .iconify[data-icon="mdi:format-quote-close"] { - color: #f57c00; -} - -.btnMarkdown .iconify[data-icon="mdi:code-tags"] { - color: #7b1fa2; -} - -.btnMarkdown .iconify[data-icon="mdi:link"] { - color: #0288d1; -} - -.btnMarkdown .iconify[data-icon="mdi:format-strikethrough"] { - color: #ff6f00; -} - -.btnMarkdown .iconify[data-icon="mdi:format-list-numbered"] { - color: #4caf50; -} - -.btnMarkdown .iconify[data-icon="mdi:checkbox-marked-outline"] { - color: #ff9800; -} - -.btnMarkdown .iconify[data-icon="mdi:image-plus"] { - color: #2196f3; -} - -.btnMarkdown .iconify[data-icon="mdi:eye"] { - color: #607d8b; -} - -.btnMarkdown .iconify[data-icon="mdi:file-plus"] { - color: #9c27b0; -} - -.btnMarkdown .iconify[data-icon="mdi:eye-off"] { - color: #e91e63; -} - -.btnMarkdown .iconify[data-icon="mdi:robot"] { - color: #ff6f00; -} - -.btnMarkdown .iconify[data-icon="mdi:menu-down"] { - color: #1976d2; -} - -.notesHeaderBtn .iconify[data-icon="mdi:pencil"] { - color: #2196f3; -} - -.notesHeaderBtn .iconify[data-icon="mdi:delete"] { - color: #dc3545; -} - header { font-size: 20px; font-weight: bold; @@ -1534,18 +1595,33 @@ textarea:focus { font-size: 18px; } -.floating-toolbar-btn .iconify[data-icon="mdi:format-bold"] { +.colored-icons .floating-toolbar-btn .iconify[data-icon="mdi:format-bold"], +.colored-icons .floating-toolbar-btn iconify-icon[icon="mdi:format-bold"] { color: #1976d2; } -.floating-toolbar-btn .iconify[data-icon="mdi:format-italic"] { +.colored-icons .floating-toolbar-btn .iconify[data-icon="mdi:format-italic"], +.colored-icons .floating-toolbar-btn iconify-icon[icon="mdi:format-italic"] { color: #7b1fa2; } -.floating-toolbar-btn .iconify[data-icon="mdi:format-strikethrough"] { +.colored-icons + .floating-toolbar-btn + .iconify[data-icon="mdi:format-strikethrough"], +.colored-icons + .floating-toolbar-btn + iconify-icon[icon="mdi:format-strikethrough"] { color: #ff6f00; } +/* Универсальный стиль для всех цветных иконок через SVG */ +.colored-icons .iconify svg, +.colored-icons iconify-icon svg { + fill: currentColor; +} + +/* Монохромные иконки для плавающей панели уже покрыты универсальным селектором */ + .floating-toolbar-btn.active { background-color: var(--bg-quaternary); box-shadow: 0 0 0 2px var(--border-focus); @@ -4847,8 +4923,7 @@ textarea:focus { } /* Очень маленькие экраны */ - - +@media (max-width: 480px) { .mobile-menu-btn .iconify { font-size: 20px; } diff --git a/src/types/user.ts b/src/types/user.ts index 2873fd8..8033656 100644 --- a/src/types/user.ts +++ b/src/types/user.ts @@ -3,6 +3,8 @@ export interface User { email?: string; avatar?: string; accent_color: string; + show_edit_date?: number; + colored_icons?: number; } export interface AuthResponse {