Skip to content

Commit b7dca8c

Browse files
committed
feat: make the modal resizable
1 parent 3761cc1 commit b7dca8c

File tree

6 files changed

+184
-43
lines changed

6 files changed

+184
-43
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
/**
3+
*
4+
* THIS SCRIPT IS AUTOMATICALLY GENERATED, NO CHANGES WILL APPLY
5+
*
6+
* @package modai
7+
* @subpackage build
8+
*
9+
* @var \xPDO\Transport\xPDOTransport $transport
10+
* @var array $object
11+
* @var array $options
12+
*/
13+
14+
15+
return (function () {
16+
return new class() {
17+
/**
18+
* @var \MODX\Revolution\modX
19+
*/
20+
private $modx;
21+
22+
/**
23+
* @var int
24+
*/
25+
private $action;
26+
27+
/**
28+
* @param \MODX\Revolution\modX $modx
29+
* @param int $action
30+
* @return bool
31+
*/
32+
public function __invoke(&$modx, $action)
33+
{
34+
$this->modx =& $modx;
35+
$this->action = $action;
36+
37+
if ($this->action === \xPDO\Transport\xPDOTransport::ACTION_UNINSTALL) {
38+
return true;
39+
}
40+
41+
/** @var class-string<\modAI\Tools\ToolInterface>[] $tools */
42+
$tools = [
43+
\modAI\Tools\GetWeather::class,
44+
45+
\modAI\Tools\GetCategories::class,
46+
\modAI\Tools\CreateCategory::class,
47+
48+
\modAI\Tools\GetChunks::class,
49+
\modAI\Tools\CreateChunk::class,
50+
\modAI\Tools\EditChunk::class,
51+
52+
\modAI\Tools\GetTemplates::class,
53+
\modAI\Tools\CreateTemplate::class,
54+
\modAI\Tools\EditTemplate::class,
55+
56+
\modAI\Tools\CreateResource::class,
57+
\modAI\Tools\GetResources::class,
58+
\modAI\Tools\GetResourceDetail::class,
59+
];
60+
61+
foreach ($tools as $tool) {
62+
$exists = $this->modx->getCount(\modAI\Model\Tool::class, ['name' => $tool::getSuggestedName()]);
63+
if ($exists > 0) {
64+
continue;
65+
}
66+
67+
$toolObjects = $this->modx->newObject(\modAI\Model\Tool::class, [
68+
'class' => $tool,
69+
'name' => $tool::getSuggestedName(),
70+
'description' => $tool::getDescription(),
71+
'prompt' => null,
72+
'config' => null,
73+
'default' => false,
74+
'enabled' => true,
75+
]);
76+
77+
$toolObjects->save();
78+
}
79+
80+
81+
return true;
82+
}
83+
};
84+
})()($transport->xpdo, $options[xPDOTransport::PACKAGE_ACTION]);

_build/js/src/chatHistory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type AssistantMessageContentType = 'text' | 'image';
1212

1313
export type UpdatableHTMLElement<M extends Message = Message> = HTMLElement & {
1414
update?: (msg: M) => void;
15+
syncHeight?: () => void;
1516
};
1617

1718
export type UserMessageContext = {

_build/js/src/ui/localChat/messageHandlers.ts

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,23 @@ export const addUserMessage = (msg: UserMessage) => {
158158
};
159159

160160
messageWrapper.appendChild(messageElement);
161+
const lastMsg = globalState.modal.chatMessages.lastElementChild;
161162
globalState.modal.chatMessages.appendChild(messageWrapper);
162163

163-
const userMsgHeight = messageWrapper.firstElementChild?.clientHeight ?? 0;
164-
const msgHeight = userMsgHeight < 100 ? -10 : -1 * (userMsgHeight - 62);
165-
messageWrapper.style.setProperty('--user-msg-height', `${msgHeight}px`);
164+
if (lastMsg) {
165+
lastMsg.classList.remove('new');
166+
}
167+
168+
messageWrapper.syncHeight = () => {
169+
const userMsgHeight = messageElement.clientHeight;
170+
const msgHeight = userMsgHeight < 100 ? -10 : -1 * (userMsgHeight - 62);
171+
messageWrapper.style.setProperty(
172+
'--user-msg-height',
173+
`${globalState.modal.chatContainer.clientHeight - msgHeight - 50}px`,
174+
);
175+
};
176+
177+
messageWrapper.syncHeight?.();
166178

167179
return messageWrapper;
168180
};
@@ -192,16 +204,6 @@ export const addAssistantMessage = (msg: AssistantMessage, config: LocalChatConf
192204
`message-wrapper ai ${msg.init ? '' : 'new'}`,
193205
);
194206

195-
if (globalState.modal.chatMessages.lastElementChild?.firstElementChild) {
196-
const msgHeight =
197-
globalState.modal.chatMessages.lastElementChild.firstElementChild.clientHeight < 100
198-
? globalState.modal.chatMessages.lastElementChild.firstElementChild.clientHeight
199-
: globalState.modal.chatMessages.lastElementChild.firstElementChild.clientHeight -
200-
(globalState.modal.chatMessages.lastElementChild.firstElementChild.clientHeight - 62) +
201-
10;
202-
messageWrapper.style.setProperty('--user-msg-height', `${msgHeight}px`);
203-
}
204-
205207
const messageElement = createElement('div', 'message ai');
206208
messageElement.dataset.id = msg.id;
207209
const md = markdownit({
@@ -353,14 +355,38 @@ export const addAssistantMessage = (msg: AssistantMessage, config: LocalChatConf
353355

354356
messageWrapper.appendChild(messageElement);
355357

358+
const lastMsg = globalState.modal.chatMessages.lastElementChild;
359+
356360
globalState.modal.chatMessages.appendChild(messageWrapper);
357361

362+
if (lastMsg) {
363+
lastMsg.classList.remove('new');
364+
}
365+
366+
messageWrapper.syncHeight = () => {
367+
if (lastMsg?.firstElementChild) {
368+
const msgHeight = lastMsg.classList.contains('user')
369+
? lastMsg.firstElementChild.clientHeight < 100
370+
? lastMsg.firstElementChild.clientHeight
371+
: lastMsg.firstElementChild.clientHeight -
372+
(lastMsg.firstElementChild.clientHeight - 62) +
373+
10
374+
: -10;
375+
messageWrapper.style.setProperty(
376+
'--user-msg-height',
377+
`${globalState.modal.chatContainer.clientHeight - msgHeight - 50}px`,
378+
);
379+
}
380+
};
381+
358382
messageWrapper.update = (msg) => {
359383
const content =
360384
msg.contentType === 'image' ? `<img src="${textContent}" />` : md.render(msg.content ?? '');
361385
shadow.updateContent(content);
362386
};
363387

388+
messageWrapper.syncHeight?.();
389+
364390
return messageWrapper;
365391
};
366392

@@ -379,7 +405,12 @@ export const renderMessage = (msg: Message, config: LocalChatConfig) => {
379405
}
380406

381407
if (msg.__type === 'AssistantMessage') {
382-
return addAssistantMessage(msg, config);
408+
const el = addAssistantMessage(msg, config);
409+
if (!msg.init && !el.previousElementSibling?.classList.contains('user')) {
410+
scrollToBottom('smooth');
411+
}
412+
413+
return el;
383414
}
384415

385416
return;

_build/js/src/ui/localChat/modalBuilder.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ export const buildModal = (config: LocalChatConfig) => {
2222
ariaLabel: lng('modai.ui.modai_assistant_chat_dialog'),
2323
});
2424

25+
const resizeObserver = new ResizeObserver(() => {
26+
const msg = globalState.modal.chatMessages.lastElementChild as UpdatableHTMLElement | null;
27+
28+
if (msg) {
29+
msg.syncHeight?.();
30+
}
31+
});
32+
33+
resizeObserver.observe(chatModal);
34+
2535
shadow.modal = chatModal;
2636
globalState.modal = shadow;
2737

assets/components/modai/css/modai.css

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,34 @@
6464
}
6565
}
6666

67+
68+
::-webkit-resizer {
69+
display: none;
70+
z-index: 1;
71+
background: rgba(0,0,0,0);
72+
left: -20px;
73+
}
74+
6775
.chat-modal {
68-
width: 90%;
69-
max-width: 800px;
70-
background-color: var(--bg-light);
71-
border-radius: var(--border-radius);
72-
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2);
73-
display: flex;
74-
flex-direction: column;
75-
height: 80vh;
76-
max-height: 700px;
76+
padding-bottom: 20px; /* webkit fix for resizer */
77+
width: clamp(374px,800px,90%);
78+
height: clamp(500px,80vh,90%);
79+
min-width: 374px;
80+
min-height: 500px;
81+
max-width: 90%;
82+
max-height: 90%;
83+
resize: both;
84+
overflow: auto;
7785
position: fixed;
7886
z-index: 101;
7987
top: 50%;
8088
left: 50%;
8189
transform: translate(-50%, -50%);
90+
background-color: var(--bg-light);
91+
border-radius: var(--border-radius);
92+
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2);
93+
display: flex;
94+
flex-direction: column;
8295

8396
.disclaimer {
8497
font-size: 11px;
@@ -141,11 +154,13 @@
141154
transition: opacity 0.5s ease-out, height 0.5s ease-out;
142155

143156
.greeting {
144-
font-size: 24px;
145-
color: var(--text-dark);
146-
opacity: 0.7;
157+
font-size: 30px;
158+
font-weight: bold;
147159
margin-block: var(--spacing-sm);
148-
font-weight: 400;
160+
color: transparent;
161+
background: linear-gradient(90deg, #FF5529 0%, #00B5DE 50%, #00DECC 100%);
162+
background-clip: text;
163+
display: inline-block;
149164
}
150165

151166
.msg {
@@ -168,7 +183,7 @@
168183

169184
&.new {
170185
&:last-of-type {
171-
min-height: calc(472px - var(--user-msg-height) - 50px)
186+
min-height: var(--user-msg-height)
172187
}
173188
}
174189

0 commit comments

Comments
 (0)