Add image attachment pills
This commit is contained in:
@@ -95,7 +95,7 @@ body {
|
|||||||
/* ==================== */
|
/* ==================== */
|
||||||
|
|
||||||
.chat {
|
.chat {
|
||||||
flex: 1 1 0;
|
flex: 1 1 100%;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overscroll-behavior: contain;
|
overscroll-behavior: contain;
|
||||||
@@ -1242,3 +1242,32 @@ body {
|
|||||||
.message__placeholder {
|
.message__placeholder {
|
||||||
color: var(--color-text-muted);
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Image attachment pills in user messages */
|
||||||
|
.message__image-pills {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: var(--s-2);
|
||||||
|
padding: 0 var(--s-1) var(--s-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message__image-pill {
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 100%;
|
||||||
|
min-width: 0;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25rem;
|
||||||
|
padding: 0.125rem 0.375rem;
|
||||||
|
font-size: var(--s-1);
|
||||||
|
background: var(--color-gray1);
|
||||||
|
border-radius: var(--radius);
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.message__image-pill-name {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|||||||
@@ -959,6 +959,7 @@ class Odidere {
|
|||||||
imageParts.push({
|
imageParts.push({
|
||||||
type: ContentTypeImageURL,
|
type: ContentTypeImageURL,
|
||||||
image_url: { url: dataURL },
|
image_url: { url: dataURL },
|
||||||
|
filename: file.name,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const content = await file.text();
|
const content = await file.text();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export class Renderer {
|
|||||||
'tpl-assistant-message',
|
'tpl-assistant-message',
|
||||||
);
|
);
|
||||||
this.$tplAttachmentChip = document.getElementById('tpl-attachment-chip');
|
this.$tplAttachmentChip = document.getElementById('tpl-attachment-chip');
|
||||||
|
this.$tplImagePill = document.getElementById('tpl-image-pill');
|
||||||
this.$tplDebugRow = document.getElementById('tpl-debug-row');
|
this.$tplDebugRow = document.getElementById('tpl-debug-row');
|
||||||
this.$tplErrorMessage = document.getElementById('tpl-error-message');
|
this.$tplErrorMessage = document.getElementById('tpl-error-message');
|
||||||
this.$tplUserMessage = document.getElementById('tpl-user-message');
|
this.$tplUserMessage = document.getElementById('tpl-user-message');
|
||||||
@@ -132,6 +133,8 @@ export class Renderer {
|
|||||||
const content = extractText(message.content);
|
const content = extractText(message.content);
|
||||||
$msg.querySelector('.message__content').textContent = content;
|
$msg.querySelector('.message__content').textContent = content;
|
||||||
|
|
||||||
|
this._renderImagePills($msg, message);
|
||||||
|
|
||||||
const $dl = $msg.querySelector('.message__debug-list');
|
const $dl = $msg.querySelector('.message__debug-list');
|
||||||
if (message.meta?.language)
|
if (message.meta?.language)
|
||||||
this._appendDebugRow($dl, 'Language', message.meta.language);
|
this._appendDebugRow($dl, 'Language', message.meta.language);
|
||||||
@@ -512,6 +515,8 @@ export class Renderer {
|
|||||||
$msg.querySelector('.message__content').textContent = content;
|
$msg.querySelector('.message__content').textContent = content;
|
||||||
$msg.dataset.copyText = content;
|
$msg.dataset.copyText = content;
|
||||||
|
|
||||||
|
this._renderImagePills($msg, message);
|
||||||
|
|
||||||
const $dl = $msg.querySelector('.message__debug-list');
|
const $dl = $msg.querySelector('.message__debug-list');
|
||||||
if (meta?.language) this._appendDebugRow($dl, 'Language', meta.language);
|
if (meta?.language) this._appendDebugRow($dl, 'Language', meta.language);
|
||||||
if (meta?.voice) this._appendDebugRow($dl, 'Voice', meta.voice);
|
if (meta?.voice) this._appendDebugRow($dl, 'Voice', meta.voice);
|
||||||
@@ -670,6 +675,24 @@ export class Renderer {
|
|||||||
this.$chat.insertBefore($msg, this.$chatLoading);
|
this.$chat.insertBefore($msg, this.$chatLoading);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_renderImagePills($msg, message) {
|
||||||
|
if (!Array.isArray(message.content)) return;
|
||||||
|
const imageParts = message.content.filter((p) => p.type === 'image_url');
|
||||||
|
if (imageParts.length === 0) return;
|
||||||
|
|
||||||
|
const $wrapper = document.createElement('div');
|
||||||
|
$wrapper.className = 'message__image-pills';
|
||||||
|
for (const part of imageParts) {
|
||||||
|
const $pill = this.$tplImagePill.content.cloneNode(true);
|
||||||
|
$pill.querySelector('.message__image-pill-name').textContent =
|
||||||
|
part.filename || 'Image';
|
||||||
|
$wrapper.appendChild($pill.firstElementChild);
|
||||||
|
}
|
||||||
|
$msg
|
||||||
|
.querySelector('.message__body')
|
||||||
|
.insertBefore($wrapper, $msg.querySelector('.message__actions'));
|
||||||
|
}
|
||||||
|
|
||||||
_populateDebugPanel($dl, meta) {
|
_populateDebugPanel($dl, meta) {
|
||||||
if (meta?.voice) this._appendDebugRow($dl, 'Voice', meta.voice);
|
if (meta?.voice) this._appendDebugRow($dl, 'Voice', meta.voice);
|
||||||
if (meta?.usage) {
|
if (meta?.usage) {
|
||||||
|
|||||||
@@ -152,6 +152,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template id="tpl-image-pill">
|
||||||
|
<span class="message__image-pill">
|
||||||
|
<span class="message__image-pill-name"></span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template id="tpl-debug-row">
|
<template id="tpl-debug-row">
|
||||||
<dt></dt>
|
<dt></dt>
|
||||||
<dd></dd>
|
<dd></dd>
|
||||||
|
|||||||
Reference in New Issue
Block a user