diff --git a/cmd/creator-web/static/assets/chat.css b/cmd/creator-web/static/assets/chat.css index ff5687b..063b21d 100644 --- a/cmd/creator-web/static/assets/chat.css +++ b/cmd/creator-web/static/assets/chat.css @@ -102,13 +102,10 @@ textarea { resize: vertical; min-height: 84px; max-height: 240px; padding: 13px; .composer button[aria-busy="true"] { color: #384529; background: #a6ca7a; } .composer button span:last-child { opacity: .65; font: 15px/1 var(--mono); } .composer button:disabled { cursor: wait; filter: saturate(.35); } -.media-tools, .conversation-starters { width: min(100%, 900px); margin: 0 auto; padding: 0 22px 9px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; color: var(--muted); font: 9px/1 var(--mono); letter-spacing: .03em; text-transform: uppercase; } +.media-tools { width: min(100%, 900px); margin: 0 auto; padding: 0 22px 9px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; color: var(--muted); font: 9px/1 var(--mono); letter-spacing: .03em; text-transform: uppercase; } .media-tools label { display: inline-flex; align-items: center; gap: 5px; min-height: 28px; margin: 0; padding: 0 7px; border: 1px solid var(--line); border-radius: 6px; color: var(--muted); cursor: pointer; } .media-tools input { max-width: 125px; font: 9px var(--mono); } .media-tools span { color: var(--yellow); } -.conversation-starters { margin-top: -2px; padding-bottom: 15px; } -.conversation-starters button { min-height: 29px; padding: 0 9px; border: 1px solid var(--line); border-radius: 6px; color: var(--muted); background: transparent; font: 9px/1 var(--mono); } -.conversation-starters button:hover, .conversation-starters button:focus-visible { border-color: var(--lime); color: var(--lime); outline: none; } .insight-grid { display: grid; gap: 7px; margin-top: 19px; } .insight-card { padding: 11px; border: 1px solid var(--line); border-radius: 8px; background: var(--panel-soft); } .insight-card strong { display: block; margin-top: 7px; color: var(--ink); font-size: 12px; font-weight: 650; line-height: 1.3; } @@ -153,8 +150,7 @@ textarea { resize: vertical; min-height: 84px; max-height: 240px; padding: 13px; .composer { grid-template-columns: 1fr; padding-inline: 12px; } .composer button { width: 100%; } .composer-hint { font-size: 8px; } - .media-tools, .conversation-starters { padding-inline: 12px; } - .conversation-starters span { width: 100%; } + .media-tools { padding-inline: 12px; } .side-build { display: none; } } @media (max-width: 640px) { @@ -194,8 +190,6 @@ textarea { resize: vertical; min-height: 84px; max-height: 240px; padding: 13px; .message-role { font-size: 10px; } .message-time { font-size: 10px; } .message small { font-size: 10px; } -.conversation-starters { width: min(100%, 1040px); padding: 0 30px 10px; } -.conversation-starters span { display: none; } .composer { width: min(100%, 1040px); padding-inline: 30px; } .composer-input-wrap { min-height: 64px; padding: 0 12px 36px; border-radius: 14px; } .composer textarea { min-height: 56px; max-height: 180px; padding: 13px 0 8px; font-size: 15px; } @@ -232,8 +226,6 @@ textarea { resize: vertical; min-height: 84px; max-height: 240px; padding: 13px; .messages { padding: 22px 12px 16px; } .message { max-width: 94%; } .message-content { font-size: 14px; } - .conversation-starters { width: 100%; padding: 0 12px 8px; overflow-x: auto; flex-wrap: nowrap; } - .conversation-starters button { flex: 0 0 auto; } .composer { width: 100%; padding-inline: 12px; } .composer-input-wrap { padding-right: 10px; } .composer-hint { display: none; } @@ -244,16 +236,14 @@ textarea { resize: vertical; min-height: 84px; max-height: 240px; padding: 13px; /* Focused composer: one calm surface, with compact controls kept together. */ .active-panel { grid-template-rows: minmax(0, 1fr) auto auto auto; } -.conversation-starters { width: min(100%, 900px); margin: 0 auto; padding: 0 22px 8px; gap: 6px; align-items: center; } -.conversation-starters span { color: var(--faint); font: 9px/1 var(--mono); letter-spacing: .03em; text-transform: uppercase; } -.conversation-starters button { min-height: 27px; padding: 0 9px; border: 1px solid var(--line); border-radius: 999px; color: var(--muted); background: transparent; font: 9px/1 var(--mono); } -.conversation-starters button:hover, .conversation-starters button:focus-visible { border-color: var(--blue); color: var(--blue); outline: none; } .composer { width: min(100%, 900px); margin: 0 auto; padding: 0 22px 7px; display: block; border-top: 0; background: transparent; } .composer-input-wrap { position: relative; min-height: 62px; padding: 0 58px 32px 12px; border: 1px solid var(--line-strong); border-radius: 12px; background: var(--panel); } .composer textarea { display: block; min-height: 54px; max-height: 178px; height: 54px; padding: 12px 0 8px; overflow-y: hidden; line-height: 1.4; } .composer-actions { position: absolute; right: 8px; bottom: 7px; left: 8px; height: 27px; display: flex; align-items: center; gap: 8px; } .composer-hint { order: 3; padding: 0; color: var(--faint); font: 9px/1 var(--mono); } .composer-tool { width: 27px; height: 27px; flex: 0 0 27px; border: 1px solid var(--line-strong); border-radius: 7px; color: var(--muted); background: transparent; font-size: 18px; line-height: 1; } +.composer-tool:has(.composer-tool-label) { width: auto; min-width: 27px; padding-inline: 7px; gap: 5px; font: 10px/1 var(--mono); } +.composer-tool-label { font-size: 10px; } .composer-tool:hover, .composer-tool:focus-visible { border-color: var(--blue); color: var(--blue); outline: none; } .context-indicator { display: inline-flex; align-items: center; gap: 5px; color: var(--faint); font: 9px/1 var(--mono); white-space: nowrap; } .context-indicator output { color: var(--muted); } @@ -270,13 +260,12 @@ textarea { resize: vertical; min-height: 84px; max-height: 240px; padding: 13px; .attachment-menu button:hover, .attachment-menu button:focus-visible { color: var(--lime); background: rgba(197,239,145,.1); outline: none; } .composer-toolbar #media-status { margin-left: 3px; color: var(--yellow); font: 9px/1 var(--mono); } @media (max-width: 780px) { - .conversation-starters { width: 100%; padding-inline: 12px; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: thin; } - .conversation-starters span { flex: 0 0 auto; width: auto; } - .conversation-starters button { flex: 0 0 auto; } .composer { width: 100%; padding-inline: 12px; } .composer-input-wrap { padding-right: 50px; } .composer-toolbar { width: 100%; padding-inline: 12px; } .attachment-menu { left: 12px; } .composer-hint { display: none; } + .composer-tool:has(.composer-tool-label) { padding-inline: 5px; } + .composer-tool-label { font-size: 9px; } .context-indicator { font-size: 8px; } } diff --git a/cmd/creator-web/static/assets/chat.js b/cmd/creator-web/static/assets/chat.js index 10f1f2d..2f86143 100644 --- a/cmd/creator-web/static/assets/chat.js +++ b/cmd/creator-web/static/assets/chat.js @@ -25,12 +25,12 @@ const todayList = document.querySelector("#today-list"); const refreshToday = document.querySelector("#refresh-today"); const historyList = document.querySelector("#history-list"); const navTabs = Array.from(document.querySelectorAll(".nav-tab")); -const conversationStarters = Array.from(document.querySelectorAll("[data-starter]")); const aiDataForm = document.querySelector("#ai-data-form"); const aiDataInput = document.querySelector("#ai-data"); const aiDataError = document.querySelector("#ai-data-error"); const attachToggle = document.querySelector("#attach-toggle"); const attachmentMenu = document.querySelector("#attachment-menu"); +const photoTrigger = document.querySelector("#photo-trigger"); const micTrigger = document.querySelector("#mic-trigger"); const sendIcon = document.querySelector("#send-icon"); const stopIcon = document.querySelector("#stop-icon"); @@ -65,11 +65,6 @@ function setChatBusy(busy) { if (stopIcon) stopIcon.hidden = !busy; } -function setSuggestionsVisible(visible) { - const suggestions = document.querySelector(".conversation-starters"); - if (suggestions) suggestions.hidden = !visible; -} - class ChatApiError extends Error { constructor(status, detail = "") { super(detail || `chat api returned ${status}`); @@ -136,9 +131,6 @@ function stopCognitiveStatusPolling() { function showChat() { loginView.hidden = true; chatView.hidden = false; - if (!messages.children.length) { - appendMessage("assistant", "Я рядом. Напишите обычное сообщение, без внутренних идентификаторов."); - } startCognitiveStatusPolling(); messageInput.focus(); resizeComposerInput(); @@ -184,7 +176,6 @@ function appendMessage(kind, text, meta = "", media = null) { messages.appendChild(node); messages.scrollTop = messages.scrollHeight; localHistory.push({kind, text, meta, at: new Date()}); - setSuggestionsVisible(!localHistory.some((item) => item.kind === "user")); renderHistory(); } @@ -495,6 +486,7 @@ for (const option of document.querySelectorAll("[data-input]")) { if (input) input.click(); }); } +if (photoTrigger && imageInput) photoTrigger.addEventListener("click", () => imageInput.click()); if (micTrigger && audioInput) micTrigger.addEventListener("click", () => audioInput.click()); document.addEventListener("click", (event) => { if (attachmentMenu && !attachmentMenu.hidden && !attachmentMenu.contains(event.target) && !attachToggle?.contains(event.target)) toggleAttachmentMenu(false); @@ -511,15 +503,6 @@ for (const tab of navTabs) { tab.addEventListener("click", () => activateTab(tab.dataset.tab)); } -for (const starter of conversationStarters) { - starter.addEventListener("click", async () => { - const text = starter.dataset.starter || ""; - if (!text || isChatBusy()) return; - messageInput.value = ""; - await sendChatMessage(text); - }); -} - if (refreshToday) refreshToday.addEventListener("click", loadToday); if (cognitiveStatus) cognitiveStatus.addEventListener("click", loadCognitiveStatus); if (aiDataForm) { diff --git a/cmd/creator-web/static/chat.html b/cmd/creator-web/static/chat.html index 6485967..0fca577 100644 --- a/cmd/creator-web/static/chat.html +++ b/cmd/creator-web/static/chat.html @@ -56,17 +56,14 @@
-
- - - -
+
- - + + + Enter — отправить · Shift+Enter — новая строка