Files
photo-editor/public/index.html

300 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta
name="viewport"
content="width=device-width, initial-scale=1"
>
<meta
name="description"
content="Локальный редактор фотографий по текстовому промпту с увеличением разрешения."
>
<title>Кадр — AI-фоторедактор</title>
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='16' fill='%23202321'/%3E%3Ctext x='32' y='45' font-size='38' font-weight='bold' text-anchor='middle' fill='%23ffffff' font-family='sans-serif'%3E%D0%9A%3C/text%3E%3C/svg%3E"
>
<link rel="stylesheet" href="/style.css?v=14">
</head>
<body>
<header class="topbar">
<a class="brand" href="/" aria-label="Кадр, главная">
<span class="brand-mark" aria-hidden="true">К</span>
<span class="brand-name">Кадр</span>
</a>
<div class="topbar-right">
<div
id="health-status"
class="health-status health-loading"
role="status"
aria-live="polite"
>
<span class="health-dot" aria-hidden="true"></span>
<span id="health-text">Проверяем сервер обработки…</span>
</div>
<button id="logout-button" class="logout-button" type="button" hidden>
Выйти
</button>
</div>
</header>
<main class="editor-layout">
<section class="control-panel" aria-labelledby="page-title">
<div class="intro">
<p class="eyebrow">Локальная AI-студия</p>
<h1 id="page-title">Меняйте кадр словами.</h1>
<p class="lead">
Загрузите фотографию, опишите желаемое изменение или увеличьте
разрешение одним нажатием.
</p>
</div>
<div class="control-stack">
<div class="field-group">
<span class="field-label">Фотография</span>
<div
id="drop-zone"
class="drop-zone"
role="button"
tabindex="0"
aria-label="Выбрать или перетащить фотографию"
>
<input
id="photo-input"
type="file"
accept="image/jpeg,image/png,image/webp,image/heic,image/heif,.heic,.heif"
multiple
hidden
>
<span class="upload-symbol" aria-hidden="true"></span>
<span class="drop-copy">
<strong id="drop-title">Перетащите фото сюда</strong>
<span id="file-meta">
или нажмите, чтобы выбрать JPEG, PNG или WebP
</span>
</span>
<span class="choose-chip">Выбрать</span>
</div>
</div>
<div class="field-group">
<span class="field-label">Референс <span class="field-label-hint">(необязательно)</span></span>
<div class="reference-actions">
<button id="reference-upload-button" class="button button-secondary button-small" type="button">Загрузить файл</button>
<select id="reference-history-select" class="reference-select" aria-label="Выбрать референс из истории">
<option value="">— из истории —</option>
</select>
<button id="reference-clear-button" class="button button-secondary button-small" type="button">Очистить</button>
</div>
<input id="reference-file-input" type="file" accept="image/jpeg,image/png,image/webp" hidden>
<div id="reference-preview" class="reference-preview" hidden>
<canvas id="reference-canvas" class="reference-canvas"></canvas>
<div class="reference-preview-foot">
<span id="reference-region-info">Область не выбрана — потяните по превью</span>
<button id="reference-region-reset" class="button button-secondary button-small" type="button">Сбросить область</button>
</div>
</div>
<p id="reference-note" class="reference-note" hidden></p>
</div>
<div class="field-group">
<label class="field-label" for="prompt">Промпт</label>
<textarea
id="prompt"
rows="4"
maxlength="1000"
placeholder="Например: сделай закат, фотореалистично"
></textarea>
<div class="field-foot">
<span>Опишите свет, настроение и нужные детали.</span>
<span id="prompt-counter">0 / 1000</span>
</div>
</div>
<button id="suggest-button" class="button button-secondary button-suggest" type="button" disabled>💡 Предложить промпт</button>
<div id="suggest-panel" class="suggest-panel" hidden>
<p class="suggest-section-title">Из истории</p>
<div id="suggest-history-chips" class="suggest-chips"></div>
<div class="suggest-actions">
<button id="suggest-codex-button" class="button button-secondary button-small" type="button" disabled>Спросить Codex</button>
<span id="suggest-codex-status" class="suggest-status" role="status" aria-live="polite"></span>
</div>
<p class="suggest-section-title">Варианты от Codex</p>
<div id="suggest-codex-chips" class="suggest-chips"></div>
</div>
<div class="actions">
<button
id="edit-button"
class="button button-primary"
type="button"
disabled
>
<span>Редактировать</span>
<span class="button-arrow" aria-hidden="true"></span>
</button>
<button
id="upscale-button"
class="button button-secondary"
type="button"
disabled
>
<span class="spark" aria-hidden="true"></span>
<span>Увеличить разрешение</span>
</button>
</div>
<p class="privacy-note">
Фото передаётся только вашему локальному серверу ComfyUI.
</p>
</div>
</section>
<section
id="workspace"
class="workspace"
aria-labelledby="workspace-title"
>
<div class="workspace-head">
<div>
<p class="workspace-kicker">Предпросмотр</p>
<h2 id="workspace-title">До и после</h2>
</div>
<div class="workspace-head-actions">
<a
id="download-current"
class="download-current"
href="#"
download
hidden
>
Скачать
<span aria-hidden="true"></span>
</a>
<span class="local-badge">LAN · локально</span>
</div>
</div>
<div class="comparison">
<figure class="photo-frame">
<figcaption>Исходник</figcaption>
<div class="image-stage">
<img
id="source-image"
alt="Выбранная исходная фотография"
hidden
>
<div id="source-placeholder" class="placeholder">
<span class="placeholder-frame" aria-hidden="true"></span>
<strong>Здесь появится фотография</strong>
<span>Выберите файл слева, чтобы начать</span>
</div>
</div>
</figure>
<figure class="photo-frame result-frame">
<figcaption>
<span>Результат</span>
<span id="result-label" class="result-kind"></span>
</figcaption>
<div class="image-stage">
<img
id="result-image"
alt="Обработанная фотография"
hidden
>
<div id="result-placeholder" class="placeholder">
<span class="placeholder-spark" aria-hidden="true"></span>
<strong>Результат появится здесь</strong>
<span>Редактирование через Codex — 13 минуты, апскейл — несколько секунд</span>
</div>
</div>
</figure>
</div>
<div
id="job-status"
class="job-status"
role="status"
aria-live="polite"
hidden
>
<div class="status-row">
<span class="status-spinner" aria-hidden="true"></span>
<span id="job-status-text"></span>
</div>
<div class="progress-track" aria-hidden="true">
<span class="progress-bar"></span>
</div>
</div>
<div class="result-actions">
<a
id="download-link"
class="download-link"
href="#"
download
hidden
>
Скачать результат
<span aria-hidden="true"></span>
</a>
</div>
<section class="history-section" aria-labelledby="history-title">
<div class="history-head">
<h2 id="history-title">История версий</h2>
<span class="history-hint">
Нажмите на версию, чтобы вернуться к ней и продолжить правки
</span>
</div>
<div id="history-list" class="history-list">
<div id="history-empty" class="history-empty">
Пока пусто — загрузите фото, и все версии появятся здесь
</div>
</div>
</section>
</section>
</main>
<div id="auth-overlay" class="auth-overlay" role="dialog" aria-modal="true" aria-labelledby="auth-title">
<form id="login-form" class="auth-card" novalidate>
<p class="auth-eyebrow">Закрытый доступ</p>
<h1 id="auth-title">Вход в редактор</h1>
<p class="auth-lead">Редактор доступен только владельцу. Войдите, чтобы продолжить.</p>
<div class="auth-field">
<label class="field-label" for="login-username">Логин</label>
<input id="login-username" name="username" type="text" autocomplete="username" autofocus required>
</div>
<div class="auth-field">
<label class="field-label" for="login-password">Пароль</label>
<input id="login-password" name="password" type="password" autocomplete="current-password" required>
</div>
<p id="login-error" class="auth-error" hidden></p>
<button id="login-submit" class="button button-primary auth-submit" type="submit">
<span>Войти</span>
</button>
</form>
</div>
<noscript>
<div class="noscript">
Для работы редактора необходимо включить JavaScript.
</div>
</noscript>
<script type="module" src="/js/main.js?v=13"></script>
</body>
</html>