Spaces:
Runtime error
Runtime error
| <html lang="ru"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"> | |
| <title>SalGram</title> | |
| <link rel="stylesheet" href="style.css"> | |
| <!-- PWA: установка на телефон/десктоп + уведомления --> | |
| <link rel="manifest" href="manifest.webmanifest"> | |
| <meta name="theme-color" content="#17212b"> | |
| <meta name="apple-mobile-web-app-capable" content="yes"> | |
| <meta name="apple-mobile-web-app-title" content="SalGram"> | |
| <link rel="apple-touch-icon" href="icon-192.png"> | |
| <link rel="icon" type="image/x-icon" href="favicon.ico"> | |
| <link rel="icon" type="image/png" href="icon-192.png"> | |
| </head> | |
| <body> | |
| <!-- ===== Экран авторизации ===== --> | |
| <main id="auth" class="screen" hidden> | |
| <section class="card"> | |
| <h1 class="logo">SalGram</h1> | |
| <p class="tagline">Безопасный мессенджер</p> | |
| <!-- Форма регистрации (по умолчанию) --> | |
| <form id="register-form" class="form"> | |
| <input name="display_name" placeholder="Отображаемый ник" maxlength="50" required> | |
| <input name="username" placeholder="Юзернейм" maxlength="32" | |
| autocomplete="username" required> | |
| <input name="password" type="password" placeholder="Пароль (мин. 8 символов)" | |
| minlength="8" autocomplete="new-password" required> | |
| <label class="tos-row"> | |
| <input type="checkbox" name="tos" required> | |
| <span>Я принимаю <button type="button" class="link" id="tos-open">условия использования</button></span> | |
| </label> | |
| <p class="error" hidden></p> | |
| <button class="primary">Создать аккаунт</button> | |
| <button type="button" class="link switch" data-target="login-form">Уже есть аккаунт</button> | |
| </form> | |
| <!-- Форма входа --> | |
| <form id="login-form" class="form" hidden> | |
| <input name="username" placeholder="Юзернейм" maxlength="32" | |
| autocomplete="username" required> | |
| <input name="password" type="password" placeholder="Пароль" | |
| autocomplete="current-password" required> | |
| <p class="error" hidden></p> | |
| <button class="primary">Войти</button> | |
| <button type="button" class="link switch" data-target="register-form">Нет аккаунта</button> | |
| </form> | |
| </section> | |
| </main> | |
| <!-- ===== Основной экран мессенджера ===== --> | |
| <main id="app" class="app-layout" hidden> | |
| <!-- Левая панель --> | |
| <aside class="sidebar"> | |
| <header class="sidebar-head">SalGram | |
| <button class="icon-btn" id="group-create" title="Создать группу или канал"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><line x1="19" y1="8" x2="19" y2="14"/><line x1="22" y1="11" x2="16" y2="11"/></svg> | |
| </button> | |
| </header> | |
| <!-- Поиск: пользователи или сообщения, частичное/точное совпадение. | |
| У заблокированного аккаунта вместо поиска — красная надпись. --> | |
| <div class="search-box"> | |
| <p id="banned-banner" class="banned-banner" hidden>Ваш аккаунт заблокирован!</p> | |
| <input id="search-input" placeholder="Поиск" autocomplete="off"> | |
| <div class="search-opts" id="search-opts" hidden> | |
| <select id="search-type"> | |
| <option value="users">Пользователи</option> | |
| <option value="groups">Группы</option> | |
| <option value="messages">Сообщения</option> | |
| </select> | |
| <select id="search-mode"> | |
| <option value="partial">Частичное</option> | |
| <option value="exact">Точное</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div id="chat-list" class="chat-list"></div> | |
| <div id="search-results" class="chat-list" hidden></div> | |
| <nav class="toolbar"> | |
| <button id="nav-settings" title="Настройки"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09a1.65 1.65 0 0 0-1-1.51 1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33h.08a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h.08a1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82v.08a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg> | |
| </button> | |
| <button id="nav-profile" title="Профиль"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> | |
| </button> | |
| <button id="nav-logout" title="Выйти"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg> | |
| </button> | |
| </nav> | |
| </aside> | |
| <!-- Правая область --> | |
| <section class="main"> | |
| <!-- Заглушка --> | |
| <div id="view-empty" class="view view-center"> | |
| <p class="stub">Выберите чат</p> | |
| </div> | |
| <!-- Чат --> | |
| <div id="view-chat" class="view view-chat" hidden> | |
| <header class="chat-head" id="chat-head" title="Открыть профиль"> | |
| <button class="icon-btn mobile-back" id="chat-back" title="Назад"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| </button> | |
| <div class="ava" id="chat-ava"></div> | |
| <div class="chat-head-info"> | |
| <span id="chat-name"></span> | |
| <span id="chat-status" class="muted small"></span> | |
| </div> | |
| <button class="icon-btn chat-del" id="chat-delete" title="Удалить переписку"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg> | |
| </button> | |
| </header> | |
| <!-- Обои чата: фото или видео фоном под сообщениями --> | |
| <div id="chat-bg" class="chat-bg"></div> | |
| <!-- Закреплённое сообщение (последнее из закреплённых) --> | |
| <div id="pinned-bar" class="pinned-bar" hidden> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="17" x2="12" y2="22"/><path d="M5 17h14v-1.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V6h1a2 2 0 0 0 0-4H8a2 2 0 0 0 0 4h1v4.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24Z"/></svg> | |
| <div class="pinned-info"> | |
| <small>Закреплённое сообщение</small> | |
| <span id="pinned-text"></span> | |
| </div> | |
| <button class="icon-btn" id="pinned-unpin" title="Открепить"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg> | |
| </button> | |
| </div> | |
| <div id="messages" class="messages"></div> | |
| <p class="error chat-error" id="chat-error" hidden></p> | |
| <p class="chat-blocked" id="chat-blocked" hidden></p> | |
| <!-- Панель ответа: цитата сообщения, на которое отвечаем (над полем ввода) --> | |
| <div id="reply-bar" class="reply-bar" hidden> | |
| <svg class="reply-bar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 17 4 12 9 7"/><path d="M20 18v-2a4 4 0 0 0-4-4H4"/></svg> | |
| <div class="reply-bar-info"> | |
| <small id="reply-bar-name"></small> | |
| <span id="reply-bar-text"></span> | |
| </div> | |
| <button type="button" class="icon-btn" id="reply-cancel" title="Отменить ответ"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg> | |
| </button> | |
| </div> | |
| <!-- Панель правки: показывается, когда сообщение редактируется в поле ввода --> | |
| <div id="edit-bar" class="reply-bar" hidden> | |
| <svg class="reply-bar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z"/></svg> | |
| <div class="reply-bar-info"> | |
| <small>Редактирование</small> | |
| <span>Enter — сохранить, Esc — отменить</span> | |
| </div> | |
| <button type="button" class="icon-btn" id="edit-cancel" title="Отменить редактирование"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg> | |
| </button> | |
| </div> | |
| <form id="msg-form" class="msg-form"> | |
| <button type="button" class="icon-btn big" id="attach-btn" title="Прикрепить фото или файл (до 25 МБ)"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> | |
| </button> | |
| <button type="button" class="icon-btn big gif-btn" id="gif-btn" title="Отправить GIF">GIF</button> | |
| <div id="msg-input" class="msg-input" contenteditable="true" role="textbox" | |
| aria-multiline="true" data-placeholder="Сообщение"></div> | |
| <input type="color" id="fmt-color" hidden> | |
| <button type="button" class="icon-btn big" id="mic-btn" title="Записать голосовое сообщение"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg> | |
| </button> | |
| <button class="icon-btn big" title="Отправить"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg> | |
| </button> | |
| <input type="file" id="photo-input" hidden> | |
| </form> | |
| <!-- Панель записи голосового: показывается во время записи вместо ввода --> | |
| <div id="rec-bar" class="rec-bar" hidden> | |
| <button type="button" class="icon-btn big rec-cancel" id="rec-cancel" title="Отменить"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg> | |
| </button> | |
| <span class="rec-dot"></span> | |
| <span class="rec-time" id="rec-time">0:00</span> | |
| <span class="rec-hint">Идёт запись…</span> | |
| <button type="button" class="icon-btn big rec-send" id="rec-send" title="Отправить голосовое"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg> | |
| </button> | |
| </div> | |
| <!-- Панель чата с ботом @addgif: вместо ввода — добавление GIF в библиотеку --> | |
| <div id="addgif-bar" class="addgif-bar" hidden> | |
| <button type="button" class="primary" id="addgif-add">Добавить GIF в библиотеку</button> | |
| </div> | |
| <!-- Панель канала для подписчика: открыть обсуждение (слева) и отписаться (справа) --> | |
| <div id="channel-bar" class="channel-bar" hidden> | |
| <button type="button" class="primary" id="channel-open-chat">Открыть чат</button> | |
| <button type="button" class="primary danger-btn" id="channel-unsub">Отписаться</button> | |
| </div> | |
| </div> | |
| <!-- Профиль другого пользователя --> | |
| <div id="view-user" class="view" hidden> | |
| <div class="panel profile"> | |
| <button class="panel-back mobile-back" data-back> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <div class="avatar readonly"> | |
| <img id="user-ava" alt="Аватарка" hidden> | |
| <svg id="user-ava-stub" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> | |
| </div> | |
| <div class="profile-row"> | |
| <h2 id="user-name"></h2> | |
| <span id="user-status" class="muted small"></span> | |
| </div> | |
| <div class="profile-actions"> | |
| <button class="primary small-btn" id="user-add-contact">Добавить в контакты</button> | |
| <button class="primary small-btn danger-btn" id="user-block">Заблокировать</button> | |
| </div> | |
| <span id="user-username" class="muted"></span> | |
| <button class="primary write-btn" id="user-write">Написать</button> | |
| <p id="user-desc" class="desc"></p> | |
| <section class="contacts" id="user-contacts-sec" hidden> | |
| <div class="profile-row"><h3>Контакты</h3></div> | |
| <ul id="user-contact-list"></ul> | |
| </section> | |
| <div class="profile-actions bottom"> | |
| <button class="link" id="user-report">Пожаловаться</button> | |
| <button class="link danger-link" id="user-delete" hidden>Удалить аккаунт</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Профиль группы --> | |
| <div id="view-group" class="view" hidden> | |
| <div class="panel profile"> | |
| <button class="panel-back mobile-back" data-back> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <div class="ava big" id="group-ava"></div> | |
| <input type="file" id="group-avatar-input" accept="image/*" hidden> | |
| <div class="profile-row"><h2 id="group-title"></h2></div> | |
| <span id="group-meta" class="muted"></span> | |
| <button class="primary write-btn" id="group-open">Открыть чат</button> | |
| <button class="primary write-btn" id="group-join">Вступить</button> | |
| <!-- Пригласительная ссылка (видна участникам) --> | |
| <div class="invite-row" id="group-invite-row" hidden> | |
| <span id="group-invite" class="invite-link"></span> | |
| <button class="link" id="group-invite-copy">Копировать</button> | |
| </div> | |
| <!-- Управление комментариями канала (открыть / привязать / отвязать группу) --> | |
| <div id="group-channel-extra" class="group-channel-extra"></div> | |
| <!-- Настройки модерации (для владельца/админов группы) --> | |
| <div id="group-mod-row" class="group-mod-row"></div> | |
| <section class="contacts" id="group-members-sec" hidden> | |
| <div class="profile-row"> | |
| <h3 id="group-members-title">Участники</h3> | |
| <button class="icon-btn" id="group-add-member" title="Добавить участника" hidden> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> | |
| </button> | |
| </div> | |
| <ul id="group-member-list"></ul> | |
| </section> | |
| <div class="profile-actions bottom"> | |
| <button class="link danger-link" id="group-leave" hidden>Выйти из группы</button> | |
| <button class="link danger-link" id="group-delete" hidden>Удалить группу</button> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Настройки --> | |
| <div id="view-settings" class="view" hidden> | |
| <div class="panel"> | |
| <!-- Корень настроек --> | |
| <div id="page-root" class="settings-page"> | |
| <button class="panel-back mobile-back" data-back> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <h2>Настройки</h2> | |
| <button class="settings-item" data-page="page-account">Аккаунт | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg> | |
| </button> | |
| <button class="settings-item" data-page="page-privacy">Приватность | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg> | |
| </button> | |
| <button class="settings-item" data-page="page-chats">Чаты | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg> | |
| </button> | |
| <button class="settings-item" id="root-appearance" data-page="page-appearance">Оформление | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg> | |
| </button> | |
| <!-- Только в ПК-приложении: кэш, оформление, уведомления и автозапуск в одном месте --> | |
| <button class="settings-item" id="root-app" data-page="page-app" hidden>Приложение | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg> | |
| </button> | |
| <button class="settings-item" data-page="page-misc">Прочее | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg> | |
| </button> | |
| </div> | |
| <!-- Аккаунт --> | |
| <div id="page-account" class="settings-page" hidden> | |
| <button class="settings-back" data-page="page-root"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <h2>Аккаунт</h2> | |
| <button class="settings-item" id="opt-nick">Изменить ник</button> | |
| <button class="settings-item" id="opt-username">Изменить юзернейм</button> | |
| <button class="settings-item" id="opt-password">Изменить пароль</button> | |
| <button class="settings-item danger" id="opt-delete">Удалить аккаунт</button> | |
| </div> | |
| <!-- Приватность --> | |
| <div id="page-privacy" class="settings-page" hidden> | |
| <button class="settings-back" data-page="page-root"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <h2>Приватность</h2> | |
| <label class="settings-row">Кому видна аватарка | |
| <select id="privacy-avatar"> | |
| <option value="everyone">Всем</option> | |
| <option value="contacts">Только контактам</option> | |
| <option value="nobody">Никому</option> | |
| </select> | |
| </label> | |
| <label class="settings-row">Кому виден список контактов | |
| <select id="privacy-contacts"> | |
| <option value="everyone">Всем</option> | |
| <option value="contacts">Только контактам</option> | |
| <option value="nobody">Никому</option> | |
| </select> | |
| </label> | |
| <label class="settings-row">Кто может добавлять меня в группы | |
| <select id="privacy-group-invite"> | |
| <option value="everyone">Все</option> | |
| <option value="contacts">Только мои контакты</option> | |
| <option value="nobody">Никто</option> | |
| </select> | |
| </label> | |
| </div> | |
| <!-- Чаты: медленный режим --> | |
| <div id="page-chats" class="settings-page" hidden> | |
| <button class="settings-back" data-page="page-root"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <h2>Чаты</h2> | |
| <label class="settings-row">Медленный режим: интервал (сек) | |
| <input type="number" id="slow-seconds" min="0" max="3600" class="num"> | |
| </label> | |
| <label class="settings-row">Действует на | |
| <select id="slow-scope"> | |
| <option value="nobody">Ни на кого</option> | |
| <option value="noncontacts">Всех, кроме контактов</option> | |
| <option value="everyone">Всех</option> | |
| </select> | |
| </label> | |
| <p class="hint">Ограничивает, как часто вам могут отправлять сообщения.</p> | |
| <div class="settings-row" id="row-cache">Кэш сообщений | |
| <span class="cache-row"> | |
| <span id="cache-size" class="muted">пусто</span> | |
| <button type="button" class="link" id="cache-clear">Очистить</button> | |
| </span> | |
| </div> | |
| <p class="hint" id="hint-cache">Переписки сохраняются на этом устройстве, чтобы чаты открывались | |
| мгновенно. Удалённые сообщения удаляются и из кэша. Кэш очищается при выходе | |
| из аккаунта.</p> | |
| </div> | |
| <!-- Оформление: тема и обои --> | |
| <div id="page-appearance" class="settings-page" hidden> | |
| <button class="settings-back" data-page="page-root"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <h2>Оформление</h2> | |
| <label class="settings-row" id="row-theme">Цветовая тема | |
| <select id="theme-select"> | |
| <option value="dark">Тёмная</option> | |
| <option value="light">Светлая</option> | |
| <option value="oled">Чёрная (OLED)</option> | |
| <option value="blue">Синяя</option> | |
| </select> | |
| </label> | |
| <div class="settings-row" id="row-wallpaper">Обои чата | |
| <span class="cache-row"> | |
| <button type="button" class="link" id="wallpaper-upload">Загрузить</button> | |
| <button type="button" class="link" id="wallpaper-remove" hidden>Удалить</button> | |
| </span> | |
| </div> | |
| <p class="hint" id="hint-wallpaper">Обои — фото или видео (до 25 МБ), показываются фоном в переписке. | |
| Тема сохраняется на этом устройстве.</p> | |
| <input type="file" id="wallpaper-input" accept="image/*,video/*" hidden> | |
| </div> | |
| <!-- Приложение: только для ПК-версии. Сюда переносятся оформление, | |
| кэш и уведомления; автозапуск существует только здесь. --> | |
| <div id="page-app" class="settings-page" hidden> | |
| <button class="settings-back" data-page="page-root"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <h2>Приложение</h2> | |
| <!-- Блоки «Оформление», «Кэш» и «Уведомления» переносятся сюда из своих | |
| разделов скриптом applyDesktopUI(). Здесь — только автозапуск. --> | |
| <h3 class="settings-sub" id="sub-autostart">Автозапуск</h3> | |
| <label class="settings-row" id="row-autostart">Запускать при старте системы | |
| <input type="checkbox" id="autostart-toggle"> | |
| </label> | |
| <p class="hint" id="hint-autostart">При включении SalGram будет автоматически | |
| запускаться при входе в Windows. По умолчанию выключено.</p> | |
| </div> | |
| <!-- Прочее: часовой пояс --> | |
| <div id="page-misc" class="settings-page" hidden> | |
| <button class="settings-back" data-page="page-root"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <h2>Прочее</h2> | |
| <label class="settings-row" id="row-notify">Уведомления о сообщениях | |
| <input type="checkbox" id="notify-toggle"> | |
| </label> | |
| <p class="hint" id="notify-hint">Показывать системные уведомления о новых сообщениях | |
| (в том числе когда приложение свёрнуто). Настройка для этого устройства.</p> | |
| <label class="settings-row">Часовой пояс | |
| <select id="tz-offset"></select> | |
| </label> | |
| <p class="hint">Определяется автоматически и сохраняется на этом устройстве (в cookie). | |
| Время сообщений и статусов «был(а) в сети» показывается в этом поясе.</p> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Собственный профиль --> | |
| <div id="view-profile" class="view" hidden> | |
| <div class="panel profile"> | |
| <button class="panel-back mobile-back" data-back> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg> | |
| Назад | |
| </button> | |
| <label class="avatar" title="Изменить аватарку"> | |
| <img id="avatar-img" alt="Аватарка" hidden> | |
| <svg id="avatar-stub" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"/><circle cx="12" cy="13" r="4"/></svg> | |
| <input type="file" id="avatar-input" accept="image/*,video/*" hidden> | |
| </label> | |
| <div class="profile-row"> | |
| <h2 id="profile-name"></h2> | |
| <button class="icon-btn" id="edit-nick" title="Изменить ник"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/></svg> | |
| </button> | |
| </div> | |
| <div class="profile-row"> | |
| <span id="profile-username" class="muted"></span> | |
| <button class="icon-btn" id="edit-username" title="Изменить юзернейм"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/></svg> | |
| </button> | |
| </div> | |
| <div class="profile-row"> | |
| <p id="profile-desc" class="desc"></p> | |
| <button class="icon-btn" id="edit-desc" title="Изменить описание"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"/></svg> | |
| </button> | |
| </div> | |
| <section class="contacts"> | |
| <div class="profile-row"> | |
| <button class="contacts-toggle" id="contacts-toggle" aria-expanded="false"> | |
| <svg class="contacts-chevron" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg> | |
| <h3>Контакты</h3> | |
| </button> | |
| <button class="icon-btn" id="contact-add" title="Добавить контакт"> | |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg> | |
| </button> | |
| </div> | |
| <ul id="contact-list" hidden></ul> | |
| </section> | |
| </div> | |
| </div> | |
| </section> | |
| </main> | |
| <!-- ===== Модальное окно с условиями использования ===== --> | |
| <div id="tos-modal" class="modal" hidden> | |
| <div class="modal-card"> | |
| <h2>Условия использования сервиса SalGram</h2> | |
| <ol> | |
| <li><b>Изменение условий.</b> Администрация Сервиса вправе в одностороннем | |
| порядке изменять настоящее Соглашение в любой момент без предварительного | |
| уведомления. Продолжение использования Сервиса после внесения изменений | |
| означает согласие Пользователя с новой редакцией Соглашения.</li> | |
| <li><b>Предоставление сервиса.</b> Сервис предоставляется на условиях | |
| «как есть» (as is). Администрация не гарантирует бесперебойную, | |
| своевременную и безошибочную работу Сервиса: он может быть недоступен | |
| или работать нестабильно.</li> | |
| <li><b>Ограничение ответственности.</b> Разработчик не несёт ответственности | |
| за действия Пользователей, а также за любую информацию и контент, | |
| передаваемые или размещаемые внутри Сервиса.</li> | |
| <li><b>Конфиденциальность переписок.</b> Все переписки Пользователей | |
| хранятся исключительно в зашифрованном виде.</li> | |
| <li><b>Персональные данные.</b> Персональные данные Пользователя | |
| используются исключительно для аутентификации (входа в аккаунт) | |
| и не применяются в каких-либо иных целях.</li> | |
| </ol> | |
| <button type="button" class="primary" id="tos-close">Закрыть</button> | |
| </div> | |
| </div> | |
| <script src="app.js"></script> | |
| </body> | |
| </html> | |