@lvce-editor/chat-view 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chatViewWorkerMain.js +381 -174
- package/package.json +2 -1
|
@@ -975,6 +975,8 @@ const TextArea = 62;
|
|
|
975
975
|
const Strong = 70;
|
|
976
976
|
const Reference = 100;
|
|
977
977
|
|
|
978
|
+
const ClientX = 'event.clientX';
|
|
979
|
+
const ClientY = 'event.clientY';
|
|
978
980
|
const Key = 'event.key';
|
|
979
981
|
const ShiftKey = 'event.shiftKey';
|
|
980
982
|
const TargetName = 'event.target.name';
|
|
@@ -1189,6 +1191,37 @@ const terminate = () => {
|
|
|
1189
1191
|
globalThis.close();
|
|
1190
1192
|
};
|
|
1191
1193
|
|
|
1194
|
+
const emptyObject = {};
|
|
1195
|
+
const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
|
|
1196
|
+
const i18nString = (key, placeholders = emptyObject) => {
|
|
1197
|
+
if (placeholders === emptyObject) {
|
|
1198
|
+
return key;
|
|
1199
|
+
}
|
|
1200
|
+
const replacer = (match, rest) => {
|
|
1201
|
+
return placeholders[rest];
|
|
1202
|
+
};
|
|
1203
|
+
return key.replaceAll(RE_PLACEHOLDER, replacer);
|
|
1204
|
+
};
|
|
1205
|
+
|
|
1206
|
+
const chatTitle = i18nString('Chat');
|
|
1207
|
+
const chats = i18nString('Chats');
|
|
1208
|
+
const newChat = i18nString('New Chat');
|
|
1209
|
+
const backToChats = i18nString('Back to chats');
|
|
1210
|
+
const settings = i18nString('Settings');
|
|
1211
|
+
const closeChat = i18nString('Close Chat');
|
|
1212
|
+
const clickToOpenNewChat = i18nString('Click the + button to open a new chat.');
|
|
1213
|
+
const startConversation = i18nString('Start a conversation by typing below.');
|
|
1214
|
+
const you = i18nString('You');
|
|
1215
|
+
const assistant = i18nString('Assistant');
|
|
1216
|
+
const composePlaceholder = i18nString('Type your message. Enter to send, Shift+Enter for newline.');
|
|
1217
|
+
const sendMessage = i18nString('Send message');
|
|
1218
|
+
const send = i18nString('Send');
|
|
1219
|
+
const deleteChatSession = i18nString('Delete chat session');
|
|
1220
|
+
const defaultSessionTitle = i18nString('Chat 1');
|
|
1221
|
+
const dummyChatA = i18nString('Dummy Chat A');
|
|
1222
|
+
const dummyChatB = i18nString('Dummy Chat B');
|
|
1223
|
+
const dummyChatC = i18nString('Dummy Chat C');
|
|
1224
|
+
|
|
1192
1225
|
const createDefaultState = () => {
|
|
1193
1226
|
const defaultSessionId = 'session-1';
|
|
1194
1227
|
return {
|
|
@@ -1199,16 +1232,16 @@ const createDefaultState = () => {
|
|
|
1199
1232
|
initial: true,
|
|
1200
1233
|
lastSubmittedSessionId: '',
|
|
1201
1234
|
nextMessageId: 1,
|
|
1202
|
-
nextSessionId: 2,
|
|
1203
1235
|
platform: 0,
|
|
1204
1236
|
renamingSessionId: '',
|
|
1205
1237
|
selectedSessionId: defaultSessionId,
|
|
1206
1238
|
sessions: [{
|
|
1207
1239
|
id: defaultSessionId,
|
|
1208
1240
|
messages: [],
|
|
1209
|
-
title:
|
|
1241
|
+
title: defaultSessionTitle
|
|
1210
1242
|
}],
|
|
1211
1243
|
uid: 0,
|
|
1244
|
+
viewMode: 'list',
|
|
1212
1245
|
warningCount: 0
|
|
1213
1246
|
};
|
|
1214
1247
|
};
|
|
@@ -1237,7 +1270,7 @@ const isEqual$1 = (oldState, newState) => {
|
|
|
1237
1270
|
};
|
|
1238
1271
|
|
|
1239
1272
|
const isEqual = (oldState, newState) => {
|
|
1240
|
-
return oldState.composerValue === newState.composerValue && oldState.ignoreNextInput === newState.ignoreNextInput && oldState.initial === newState.initial && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions;
|
|
1273
|
+
return oldState.composerValue === newState.composerValue && oldState.ignoreNextInput === newState.ignoreNextInput && oldState.initial === newState.initial && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.viewMode === newState.viewMode;
|
|
1241
1274
|
};
|
|
1242
1275
|
|
|
1243
1276
|
const RenderItems = 4;
|
|
@@ -1271,10 +1304,73 @@ const getKeyBindings = () => {
|
|
|
1271
1304
|
return [];
|
|
1272
1305
|
};
|
|
1273
1306
|
|
|
1307
|
+
const SESSION_PREFIX$1 = 'session:';
|
|
1308
|
+
const CHAT_LIST_ITEM_CONTEXT_MENU = 'ChatListItemContextMenu';
|
|
1309
|
+
const handleChatListContextMenu = async (name, x, y) => {
|
|
1310
|
+
if (!name || !name.startsWith(SESSION_PREFIX$1)) {
|
|
1311
|
+
return;
|
|
1312
|
+
}
|
|
1313
|
+
const sessionId = name.slice(SESSION_PREFIX$1.length);
|
|
1314
|
+
// @ts-ignore
|
|
1315
|
+
await invoke('ContextMenu.show', x, y, CHAT_LIST_ITEM_CONTEXT_MENU, sessionId);
|
|
1316
|
+
};
|
|
1317
|
+
|
|
1318
|
+
const generateSessionId = () => {
|
|
1319
|
+
return crypto.randomUUID();
|
|
1320
|
+
};
|
|
1321
|
+
|
|
1322
|
+
const handleSubmit = async state => {
|
|
1323
|
+
const {
|
|
1324
|
+
composerValue,
|
|
1325
|
+
nextMessageId,
|
|
1326
|
+
selectedSessionId,
|
|
1327
|
+
sessions
|
|
1328
|
+
} = state;
|
|
1329
|
+
const text = composerValue.trim();
|
|
1330
|
+
const time = new Date().toLocaleTimeString([], {
|
|
1331
|
+
hour: '2-digit',
|
|
1332
|
+
minute: '2-digit'
|
|
1333
|
+
});
|
|
1334
|
+
if (!text) {
|
|
1335
|
+
return {
|
|
1336
|
+
...state,
|
|
1337
|
+
ignoreNextInput: true
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
const updatedSessions = sessions.map(session => {
|
|
1341
|
+
if (session.id !== selectedSessionId) {
|
|
1342
|
+
return session;
|
|
1343
|
+
}
|
|
1344
|
+
const message = {
|
|
1345
|
+
id: `message-${nextMessageId}`,
|
|
1346
|
+
role: 'user',
|
|
1347
|
+
text,
|
|
1348
|
+
time
|
|
1349
|
+
};
|
|
1350
|
+
return {
|
|
1351
|
+
...session,
|
|
1352
|
+
messages: [...session.messages, message]
|
|
1353
|
+
};
|
|
1354
|
+
});
|
|
1355
|
+
return {
|
|
1356
|
+
...state,
|
|
1357
|
+
composerValue: '',
|
|
1358
|
+
ignoreNextInput: true,
|
|
1359
|
+
lastSubmittedSessionId: selectedSessionId,
|
|
1360
|
+
nextMessageId: nextMessageId + 1,
|
|
1361
|
+
sessions: updatedSessions
|
|
1362
|
+
};
|
|
1363
|
+
};
|
|
1364
|
+
|
|
1274
1365
|
const CREATE_SESSION = 'create-session';
|
|
1275
1366
|
const SESSION_PREFIX = 'session:';
|
|
1276
1367
|
const RENAME_PREFIX = 'session-rename:';
|
|
1277
1368
|
const DELETE_PREFIX = 'session-delete:';
|
|
1369
|
+
const SEND = 'send';
|
|
1370
|
+
const BACK = 'back';
|
|
1371
|
+
const handleClickSend = async state => {
|
|
1372
|
+
return handleSubmit(state);
|
|
1373
|
+
};
|
|
1278
1374
|
const getNextSelectedSessionId = (sessions, deletedId) => {
|
|
1279
1375
|
if (sessions.length === 0) {
|
|
1280
1376
|
return '';
|
|
@@ -1287,15 +1383,14 @@ const getNextSelectedSessionId = (sessions, deletedId) => {
|
|
|
1287
1383
|
return sessions[nextIndex].id;
|
|
1288
1384
|
};
|
|
1289
1385
|
const createSession = state => {
|
|
1290
|
-
const id =
|
|
1386
|
+
const id = generateSessionId();
|
|
1291
1387
|
const session = {
|
|
1292
1388
|
id,
|
|
1293
1389
|
messages: [],
|
|
1294
|
-
title: `Chat ${state.
|
|
1390
|
+
title: `Chat ${state.sessions.length + 1}`
|
|
1295
1391
|
};
|
|
1296
1392
|
return {
|
|
1297
1393
|
...state,
|
|
1298
|
-
nextSessionId: state.nextSessionId + 1,
|
|
1299
1394
|
renamingSessionId: '',
|
|
1300
1395
|
selectedSessionId: id,
|
|
1301
1396
|
sessions: [...state.sessions, session]
|
|
@@ -1309,7 +1404,8 @@ const selectSession = (state, id) => {
|
|
|
1309
1404
|
return {
|
|
1310
1405
|
...state,
|
|
1311
1406
|
renamingSessionId: '',
|
|
1312
|
-
selectedSessionId: id
|
|
1407
|
+
selectedSessionId: id,
|
|
1408
|
+
viewMode: 'detail'
|
|
1313
1409
|
};
|
|
1314
1410
|
};
|
|
1315
1411
|
const startRename = (state, id) => {
|
|
@@ -1330,18 +1426,12 @@ const deleteSession = (state, id) => {
|
|
|
1330
1426
|
return state;
|
|
1331
1427
|
}
|
|
1332
1428
|
if (filtered.length === 0) {
|
|
1333
|
-
const fallbackId = `session-${state.nextSessionId}`;
|
|
1334
|
-
const fallback = {
|
|
1335
|
-
id: fallbackId,
|
|
1336
|
-
messages: [],
|
|
1337
|
-
title: `Chat ${state.nextSessionId}`
|
|
1338
|
-
};
|
|
1339
1429
|
return {
|
|
1340
1430
|
...state,
|
|
1341
|
-
nextSessionId: state.nextSessionId + 1,
|
|
1342
1431
|
renamingSessionId: '',
|
|
1343
|
-
selectedSessionId:
|
|
1344
|
-
sessions: [
|
|
1432
|
+
selectedSessionId: '',
|
|
1433
|
+
sessions: [],
|
|
1434
|
+
viewMode: 'list'
|
|
1345
1435
|
};
|
|
1346
1436
|
}
|
|
1347
1437
|
return {
|
|
@@ -1370,6 +1460,16 @@ const handleClick = async (state, name) => {
|
|
|
1370
1460
|
const id = name.slice(DELETE_PREFIX.length);
|
|
1371
1461
|
return deleteSession(state, id);
|
|
1372
1462
|
}
|
|
1463
|
+
if (name === SEND) {
|
|
1464
|
+
return handleClickSend(state);
|
|
1465
|
+
}
|
|
1466
|
+
if (name === BACK) {
|
|
1467
|
+
return {
|
|
1468
|
+
...state,
|
|
1469
|
+
renamingSessionId: '',
|
|
1470
|
+
viewMode: 'list'
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1373
1473
|
return state;
|
|
1374
1474
|
};
|
|
1375
1475
|
|
|
@@ -1378,6 +1478,8 @@ const handleClickClose = async () => {
|
|
|
1378
1478
|
await invoke('Chat.terminate');
|
|
1379
1479
|
};
|
|
1380
1480
|
|
|
1481
|
+
const handleClickSettings = async () => {};
|
|
1482
|
+
|
|
1381
1483
|
const handleInput = async (state, value) => {
|
|
1382
1484
|
if (state.ignoreNextInput) {
|
|
1383
1485
|
return {
|
|
@@ -1421,43 +1523,6 @@ const submitRename = state => {
|
|
|
1421
1523
|
sessions: updatedSessions
|
|
1422
1524
|
};
|
|
1423
1525
|
};
|
|
1424
|
-
const submitMessage = state => {
|
|
1425
|
-
const {
|
|
1426
|
-
composerValue,
|
|
1427
|
-
nextMessageId,
|
|
1428
|
-
selectedSessionId,
|
|
1429
|
-
sessions
|
|
1430
|
-
} = state;
|
|
1431
|
-
const text = composerValue.trim();
|
|
1432
|
-
if (!text) {
|
|
1433
|
-
return {
|
|
1434
|
-
...state,
|
|
1435
|
-
ignoreNextInput: true
|
|
1436
|
-
};
|
|
1437
|
-
}
|
|
1438
|
-
const updatedSessions = sessions.map(session => {
|
|
1439
|
-
if (session.id !== selectedSessionId) {
|
|
1440
|
-
return session;
|
|
1441
|
-
}
|
|
1442
|
-
const message = {
|
|
1443
|
-
id: `message-${nextMessageId}`,
|
|
1444
|
-
role: 'user',
|
|
1445
|
-
text
|
|
1446
|
-
};
|
|
1447
|
-
return {
|
|
1448
|
-
...session,
|
|
1449
|
-
messages: [...session.messages, message]
|
|
1450
|
-
};
|
|
1451
|
-
});
|
|
1452
|
-
return {
|
|
1453
|
-
...state,
|
|
1454
|
-
composerValue: '',
|
|
1455
|
-
ignoreNextInput: true,
|
|
1456
|
-
lastSubmittedSessionId: selectedSessionId,
|
|
1457
|
-
nextMessageId: nextMessageId + 1,
|
|
1458
|
-
sessions: updatedSessions
|
|
1459
|
-
};
|
|
1460
|
-
};
|
|
1461
1526
|
const handleKeyDown = async (state, key, shiftKey) => {
|
|
1462
1527
|
if (key !== 'Enter' || shiftKey) {
|
|
1463
1528
|
return state;
|
|
@@ -1465,7 +1530,7 @@ const handleKeyDown = async (state, key, shiftKey) => {
|
|
|
1465
1530
|
if (state.renamingSessionId) {
|
|
1466
1531
|
return submitRename(state);
|
|
1467
1532
|
}
|
|
1468
|
-
return
|
|
1533
|
+
return handleSubmit(state);
|
|
1469
1534
|
};
|
|
1470
1535
|
|
|
1471
1536
|
const id = 7201;
|
|
@@ -1490,69 +1555,62 @@ const initialize = async () => {
|
|
|
1490
1555
|
set$2(rpc);
|
|
1491
1556
|
};
|
|
1492
1557
|
|
|
1493
|
-
const
|
|
1494
|
-
|
|
1495
|
-
|
|
1558
|
+
const isObject = value => {
|
|
1559
|
+
return typeof value === 'object' && value !== null;
|
|
1560
|
+
};
|
|
1561
|
+
|
|
1562
|
+
const getSavedSelectedSessionId = savedState => {
|
|
1563
|
+
if (!isObject(savedState)) {
|
|
1564
|
+
return undefined;
|
|
1496
1565
|
}
|
|
1497
|
-
const
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
}
|
|
1566
|
+
const {
|
|
1567
|
+
selectedSessionId
|
|
1568
|
+
} = savedState;
|
|
1569
|
+
if (typeof selectedSessionId !== 'string') {
|
|
1570
|
+
return undefined;
|
|
1571
|
+
}
|
|
1572
|
+
return selectedSessionId;
|
|
1573
|
+
};
|
|
1574
|
+
|
|
1575
|
+
const getSavedSessions = savedState => {
|
|
1576
|
+
if (!isObject(savedState)) {
|
|
1577
|
+
return undefined;
|
|
1578
|
+
}
|
|
1579
|
+
const {
|
|
1580
|
+
sessions
|
|
1581
|
+
} = savedState;
|
|
1582
|
+
if (!Array.isArray(sessions)) {
|
|
1583
|
+
return undefined;
|
|
1584
|
+
}
|
|
1585
|
+
return sessions;
|
|
1503
1586
|
};
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
const
|
|
1587
|
+
|
|
1588
|
+
const loadContent = async (state, savedState) => {
|
|
1589
|
+
const sessions = getSavedSessions(savedState) || state.sessions;
|
|
1590
|
+
const preferredSessionId = getSavedSelectedSessionId(savedState) || state.selectedSessionId;
|
|
1591
|
+
const selectedSessionId = sessions.some(session => session.id === preferredSessionId) ? preferredSessionId : sessions[0]?.id || '';
|
|
1592
|
+
const viewMode = sessions.length === 0 ? 'list' : state.viewMode === 'detail' ? 'detail' : 'list';
|
|
1507
1593
|
return {
|
|
1508
1594
|
...state,
|
|
1509
1595
|
initial: false,
|
|
1510
|
-
nextSessionId: state.sessions.length === 0 ? state.nextSessionId + 1 : state.nextSessionId,
|
|
1511
1596
|
selectedSessionId,
|
|
1512
|
-
sessions
|
|
1597
|
+
sessions,
|
|
1598
|
+
viewMode
|
|
1513
1599
|
};
|
|
1514
1600
|
};
|
|
1515
1601
|
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
grid-template-rows: auto 1fr auto;
|
|
1520
|
-
height: 100%;
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
.ChatHeader {
|
|
1524
|
-
align-items: center;
|
|
1525
|
-
display: flex;
|
|
1526
|
-
gap: 8px;
|
|
1527
|
-
justify-content: space-between;
|
|
1528
|
-
padding: 8px;
|
|
1529
|
-
}
|
|
1530
|
-
|
|
1531
|
-
.ChatList {
|
|
1532
|
-
border-right: 1px solid var(--Widget-border);
|
|
1533
|
-
overflow: auto;
|
|
1534
|
-
}
|
|
1535
|
-
|
|
1536
|
-
.ChatDetails {
|
|
1537
|
-
display: flex;
|
|
1538
|
-
flex-direction: column;
|
|
1539
|
-
min-height: 0;
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
.ChatDetailsContent {
|
|
1543
|
-
flex: 1;
|
|
1544
|
-
overflow: auto;
|
|
1545
|
-
padding: 8px;
|
|
1546
|
-
}
|
|
1547
|
-
|
|
1548
|
-
.MultilineInputBox {
|
|
1549
|
-
width: 100%;
|
|
1550
|
-
}
|
|
1602
|
+
// TODO render things like scrollbar height,scrollbar offset, textarea height,
|
|
1603
|
+
// list height
|
|
1604
|
+
const css = `
|
|
1551
1605
|
`;
|
|
1552
1606
|
const renderCss = (oldState, newState) => {
|
|
1553
1607
|
return [SetCss, newState.uid, css];
|
|
1554
1608
|
};
|
|
1555
1609
|
|
|
1610
|
+
const mergeClassNames = (...classNames) => {
|
|
1611
|
+
return classNames.filter(Boolean).join(' ');
|
|
1612
|
+
};
|
|
1613
|
+
|
|
1556
1614
|
const text = data => {
|
|
1557
1615
|
return {
|
|
1558
1616
|
childCount: 0,
|
|
@@ -1850,152 +1908,264 @@ const diffTree = (oldNodes, newNodes) => {
|
|
|
1850
1908
|
};
|
|
1851
1909
|
|
|
1852
1910
|
const ChatActions = 'ChatActions';
|
|
1911
|
+
const ChatName = 'ChatName';
|
|
1912
|
+
const ChatSendArea = 'ChatSendArea';
|
|
1913
|
+
const Chat = 'Chat';
|
|
1853
1914
|
const ChatHeader = 'ChatHeader';
|
|
1854
1915
|
const Button = 'Button';
|
|
1916
|
+
const ButtonPrimary = 'ButtonPrimary';
|
|
1855
1917
|
const ChatDetails = 'ChatDetails';
|
|
1856
1918
|
const ChatDetailsContent = 'ChatDetailsContent';
|
|
1857
1919
|
const IconButton = 'IconButton';
|
|
1858
1920
|
const Label = 'Label';
|
|
1859
1921
|
const ChatList = 'ChatList';
|
|
1922
|
+
const ChatListItem = 'ChatListItem';
|
|
1860
1923
|
const Markdown = 'Markdown';
|
|
1861
1924
|
const Message = 'Message';
|
|
1862
1925
|
const MultilineInputBox = 'MultilineInputBox';
|
|
1863
1926
|
const Viewlet = 'Viewlet';
|
|
1864
1927
|
const ChatWelcomeMessage = 'ChatWelcomeMessage';
|
|
1865
1928
|
|
|
1929
|
+
const HandleContextMenu = 2;
|
|
1866
1930
|
const HandleInput = 4;
|
|
1867
1931
|
const HandleClick = 11;
|
|
1868
1932
|
const HandleKeyDown = 12;
|
|
1933
|
+
const HandleClickClose = 13;
|
|
1934
|
+
const HandleClickSettings = 14;
|
|
1935
|
+
|
|
1936
|
+
const getChatHeaderActionsDom = () => {
|
|
1937
|
+
const items = [{
|
|
1938
|
+
icon: '+',
|
|
1939
|
+
name: 'create-session',
|
|
1940
|
+
title: newChat
|
|
1941
|
+
}, {
|
|
1942
|
+
icon: '⚙',
|
|
1943
|
+
onClick: HandleClickSettings,
|
|
1944
|
+
title: settings
|
|
1945
|
+
}, {
|
|
1946
|
+
icon: '×',
|
|
1947
|
+
onClick: HandleClickClose,
|
|
1948
|
+
title: closeChat
|
|
1949
|
+
}];
|
|
1950
|
+
return [{
|
|
1951
|
+
childCount: items.length,
|
|
1952
|
+
className: ChatActions,
|
|
1953
|
+
type: Div
|
|
1954
|
+
}, ...items.flatMap(item => {
|
|
1955
|
+
const name = 'name' in item ? item.name : undefined;
|
|
1956
|
+
const onClick = 'onClick' in item ? item.onClick : undefined;
|
|
1957
|
+
return [{
|
|
1958
|
+
childCount: 1,
|
|
1959
|
+
className: IconButton,
|
|
1960
|
+
...(name ? {
|
|
1961
|
+
name
|
|
1962
|
+
} : {}),
|
|
1963
|
+
...(onClick ? {
|
|
1964
|
+
onClick
|
|
1965
|
+
} : {}),
|
|
1966
|
+
role: Button$2,
|
|
1967
|
+
tabIndex: 0,
|
|
1968
|
+
title: item.title,
|
|
1969
|
+
type: Button$1
|
|
1970
|
+
}, text(item.icon)];
|
|
1971
|
+
})];
|
|
1972
|
+
};
|
|
1973
|
+
|
|
1974
|
+
const getChatHeaderBackButtonVirtualDom = () => {
|
|
1975
|
+
return [{
|
|
1976
|
+
childCount: 1,
|
|
1977
|
+
className: IconButton,
|
|
1978
|
+
name: 'back',
|
|
1979
|
+
role: Button$2,
|
|
1980
|
+
tabIndex: 0,
|
|
1981
|
+
title: backToChats,
|
|
1982
|
+
type: Button$1
|
|
1983
|
+
}, text('←')];
|
|
1984
|
+
};
|
|
1869
1985
|
|
|
1870
|
-
const
|
|
1986
|
+
const getChatHeaderDomDetailMode = selectedSessionTitle => {
|
|
1871
1987
|
return [{
|
|
1872
1988
|
childCount: 2,
|
|
1989
|
+
className: ChatHeader,
|
|
1990
|
+
type: Div
|
|
1991
|
+
}, {
|
|
1992
|
+
childCount: 2,
|
|
1993
|
+
className: ChatName,
|
|
1994
|
+
type: Div
|
|
1995
|
+
}, ...getChatHeaderBackButtonVirtualDom(), {
|
|
1996
|
+
childCount: 1,
|
|
1997
|
+
className: Label,
|
|
1998
|
+
type: Span
|
|
1999
|
+
}, text(selectedSessionTitle), ...getChatHeaderActionsDom()];
|
|
2000
|
+
};
|
|
2001
|
+
|
|
2002
|
+
const getChatDetailsDom = (selectedSessionTitle, messagesNodes, composerValue) => {
|
|
2003
|
+
return [{
|
|
2004
|
+
childCount: 3,
|
|
1873
2005
|
className: ChatDetails,
|
|
1874
2006
|
type: Div
|
|
1875
2007
|
}, {
|
|
2008
|
+
childCount: 1,
|
|
2009
|
+
className: Label,
|
|
2010
|
+
type: Span
|
|
2011
|
+
}, text(selectedSessionTitle), {
|
|
1876
2012
|
childCount: Math.max(messagesNodes.length, 0),
|
|
1877
2013
|
className: ChatDetailsContent,
|
|
1878
2014
|
type: Div
|
|
1879
2015
|
}, ...messagesNodes, {
|
|
1880
|
-
childCount:
|
|
1881
|
-
className:
|
|
2016
|
+
childCount: 2,
|
|
2017
|
+
className: ChatSendArea,
|
|
1882
2018
|
type: Div
|
|
1883
2019
|
}, {
|
|
1884
2020
|
childCount: 0,
|
|
1885
2021
|
className: MultilineInputBox,
|
|
1886
2022
|
name: 'composer',
|
|
1887
|
-
placeholder:
|
|
2023
|
+
placeholder: composePlaceholder,
|
|
1888
2024
|
rows: 4,
|
|
1889
2025
|
type: TextArea,
|
|
1890
2026
|
value: composerValue
|
|
1891
|
-
}
|
|
2027
|
+
}, {
|
|
2028
|
+
childCount: 1,
|
|
2029
|
+
className: Button + ' ' + ButtonPrimary,
|
|
2030
|
+
name: 'send',
|
|
2031
|
+
role: Button$2,
|
|
2032
|
+
tabIndex: 0,
|
|
2033
|
+
title: sendMessage,
|
|
2034
|
+
type: Button$1
|
|
2035
|
+
}, text(send)];
|
|
2036
|
+
};
|
|
2037
|
+
|
|
2038
|
+
const getChatContentDom = (viewMode, sessionsLength, emptyStateNodes, sessionNodes, selectedSessionTitle, messagesNodes, composerValue) => {
|
|
2039
|
+
return getChatDetailsDom(selectedSessionTitle, messagesNodes, composerValue);
|
|
1892
2040
|
};
|
|
1893
2041
|
|
|
1894
|
-
const
|
|
2042
|
+
const getChatMessageDom = message => {
|
|
1895
2043
|
return [{
|
|
1896
2044
|
childCount: 2,
|
|
1897
|
-
className:
|
|
1898
|
-
type: Div
|
|
1899
|
-
}, {
|
|
1900
|
-
childCount: 2,
|
|
1901
|
-
className: ChatActions,
|
|
2045
|
+
className: Message,
|
|
1902
2046
|
type: Div
|
|
1903
2047
|
}, {
|
|
1904
2048
|
childCount: 1,
|
|
1905
2049
|
className: Label,
|
|
1906
|
-
type:
|
|
1907
|
-
}, text('
|
|
2050
|
+
type: Strong
|
|
2051
|
+
}, text(`${message.role === 'user' ? you : assistant} · ${message.time}`), {
|
|
1908
2052
|
childCount: 1,
|
|
1909
|
-
className:
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
tabIndex: 0,
|
|
1913
|
-
title: 'New Chat',
|
|
1914
|
-
type: Button$1
|
|
1915
|
-
}, text('+'), {
|
|
1916
|
-
childCount: sessionsLength,
|
|
1917
|
-
className: ChatList,
|
|
1918
|
-
type: Div
|
|
1919
|
-
}];
|
|
2053
|
+
className: Markdown,
|
|
2054
|
+
type: P
|
|
2055
|
+
}, text(message.text)];
|
|
1920
2056
|
};
|
|
1921
|
-
|
|
1922
2057
|
const getMessagesDom = messages => {
|
|
1923
2058
|
if (messages.length === 0) {
|
|
1924
2059
|
return [{
|
|
1925
2060
|
childCount: 1,
|
|
1926
2061
|
className: ChatWelcomeMessage,
|
|
1927
2062
|
type: Div
|
|
1928
|
-
}, text(
|
|
2063
|
+
}, text(startConversation)];
|
|
1929
2064
|
}
|
|
1930
2065
|
return messages.flatMap(message => {
|
|
1931
|
-
return
|
|
1932
|
-
childCount: 2,
|
|
1933
|
-
className: Message,
|
|
1934
|
-
type: Div
|
|
1935
|
-
}, {
|
|
1936
|
-
childCount: 1,
|
|
1937
|
-
className: Label,
|
|
1938
|
-
type: Strong
|
|
1939
|
-
}, text(message.role === 'user' ? 'You' : 'Assistant'), {
|
|
1940
|
-
childCount: 1,
|
|
1941
|
-
className: Markdown,
|
|
1942
|
-
type: P
|
|
1943
|
-
}, text(message.text)];
|
|
2066
|
+
return getChatMessageDom(message);
|
|
1944
2067
|
});
|
|
1945
2068
|
};
|
|
1946
2069
|
|
|
2070
|
+
const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue) => {
|
|
2071
|
+
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
2072
|
+
const selectedSessionTitle = selectedSession?.title || chatTitle;
|
|
2073
|
+
const messages = selectedSession ? selectedSession.messages : [];
|
|
2074
|
+
const messagesNodes = getMessagesDom(messages);
|
|
2075
|
+
const contentNodes = getChatContentDom('detail', sessions.length, [], [], selectedSessionTitle, messagesNodes, composerValue);
|
|
2076
|
+
return [{
|
|
2077
|
+
childCount: 2,
|
|
2078
|
+
className: Viewlet + ' Chat',
|
|
2079
|
+
onClick: HandleClick,
|
|
2080
|
+
onInput: HandleInput,
|
|
2081
|
+
onKeyDown: HandleKeyDown,
|
|
2082
|
+
type: Div
|
|
2083
|
+
}, ...getChatHeaderDomDetailMode(selectedSessionTitle), ...contentNodes];
|
|
2084
|
+
};
|
|
2085
|
+
|
|
2086
|
+
const getChatHeaderListModeDom = () => {
|
|
2087
|
+
return [{
|
|
2088
|
+
childCount: 2,
|
|
2089
|
+
className: ChatHeader,
|
|
2090
|
+
type: Div
|
|
2091
|
+
}, {
|
|
2092
|
+
childCount: 1,
|
|
2093
|
+
className: Label,
|
|
2094
|
+
type: Span
|
|
2095
|
+
}, text(chats), ...getChatHeaderActionsDom()];
|
|
2096
|
+
};
|
|
2097
|
+
|
|
2098
|
+
const getEmptyChatSessionsDom = sessionsLength => {
|
|
2099
|
+
if (sessionsLength !== 0) {
|
|
2100
|
+
return [];
|
|
2101
|
+
}
|
|
2102
|
+
return [{
|
|
2103
|
+
childCount: 1,
|
|
2104
|
+
className: Label,
|
|
2105
|
+
type: Div
|
|
2106
|
+
}, text(clickToOpenNewChat)];
|
|
2107
|
+
};
|
|
2108
|
+
|
|
1947
2109
|
const getSessionDom = (session, _selectedSessionId) => {
|
|
1948
|
-
const sessionClassName =
|
|
2110
|
+
const sessionClassName = ChatListItem;
|
|
1949
2111
|
return [{
|
|
1950
2112
|
childCount: 2,
|
|
1951
2113
|
className: sessionClassName,
|
|
1952
2114
|
type: Div
|
|
1953
2115
|
}, {
|
|
1954
2116
|
childCount: 1,
|
|
1955
|
-
className:
|
|
2117
|
+
className: ChatName,
|
|
1956
2118
|
name: `session:${session.id}`,
|
|
1957
|
-
|
|
2119
|
+
onContextMenu: HandleContextMenu,
|
|
1958
2120
|
tabIndex: 0,
|
|
1959
|
-
type:
|
|
2121
|
+
type: Div
|
|
1960
2122
|
}, text(session.title), {
|
|
1961
|
-
childCount:
|
|
2123
|
+
childCount: 1,
|
|
1962
2124
|
className: ChatActions,
|
|
1963
2125
|
type: Div
|
|
1964
2126
|
}, {
|
|
1965
|
-
childCount: 1,
|
|
1966
|
-
className: IconButton,
|
|
1967
|
-
name: `session-rename:${session.id}`,
|
|
1968
|
-
role: Button$2,
|
|
1969
|
-
tabIndex: 0,
|
|
1970
|
-
title: 'Rename chat session',
|
|
1971
|
-
type: Button$1
|
|
1972
|
-
}, text('Rename'), {
|
|
1973
2127
|
childCount: 1,
|
|
1974
2128
|
className: IconButton,
|
|
1975
2129
|
name: `session-delete:${session.id}`,
|
|
1976
2130
|
role: Button$2,
|
|
1977
2131
|
tabIndex: 0,
|
|
1978
|
-
title:
|
|
2132
|
+
title: deleteChatSession,
|
|
1979
2133
|
type: Button$1
|
|
1980
|
-
}, text('
|
|
2134
|
+
}, text('🗑')];
|
|
1981
2135
|
};
|
|
1982
2136
|
|
|
1983
|
-
const
|
|
1984
|
-
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
1985
|
-
const messages = selectedSession ? selectedSession.messages : [];
|
|
1986
|
-
const chatHeaderDom = getChatHeaderDom(sessions.length);
|
|
2137
|
+
const getChatModeListVirtualDom = (sessions, selectedSessionId) => {
|
|
1987
2138
|
const sessionNodes = sessions.flatMap(session => getSessionDom(session));
|
|
1988
|
-
const
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
className: Viewlet + ' Chat',
|
|
2139
|
+
const emptyStateNodes = getEmptyChatSessionsDom(sessions.length);
|
|
2140
|
+
return [{
|
|
2141
|
+
childCount: 2,
|
|
2142
|
+
className: mergeClassNames(Viewlet, Chat),
|
|
1993
2143
|
onClick: HandleClick,
|
|
1994
2144
|
onInput: HandleInput,
|
|
1995
2145
|
onKeyDown: HandleKeyDown,
|
|
1996
2146
|
type: Div
|
|
1997
|
-
}, ...
|
|
1998
|
-
|
|
2147
|
+
}, ...getChatHeaderListModeDom(), {
|
|
2148
|
+
childCount: sessions.length === 0 ? 1 : sessions.length,
|
|
2149
|
+
className: ChatList,
|
|
2150
|
+
type: Div
|
|
2151
|
+
}, ...(sessions.length === 0 ? emptyStateNodes : sessionNodes)];
|
|
2152
|
+
};
|
|
2153
|
+
|
|
2154
|
+
const getChatModeUnsupportedVirtualDom = () => {
|
|
2155
|
+
return [{
|
|
2156
|
+
childCount: 1,
|
|
2157
|
+
type: Div
|
|
2158
|
+
}, text('Unknown view mode')];
|
|
2159
|
+
};
|
|
2160
|
+
const getChatVirtualDom = (sessions, selectedSessionId, composerValue, viewMode) => {
|
|
2161
|
+
switch (viewMode) {
|
|
2162
|
+
case 'detail':
|
|
2163
|
+
return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue);
|
|
2164
|
+
case 'list':
|
|
2165
|
+
return getChatModeListVirtualDom(sessions);
|
|
2166
|
+
default:
|
|
2167
|
+
return getChatModeUnsupportedVirtualDom();
|
|
2168
|
+
}
|
|
1999
2169
|
};
|
|
2000
2170
|
|
|
2001
2171
|
const renderItems = (oldState, newState) => {
|
|
@@ -2004,12 +2174,13 @@ const renderItems = (oldState, newState) => {
|
|
|
2004
2174
|
initial,
|
|
2005
2175
|
selectedSessionId,
|
|
2006
2176
|
sessions,
|
|
2007
|
-
uid
|
|
2177
|
+
uid,
|
|
2178
|
+
viewMode
|
|
2008
2179
|
} = newState;
|
|
2009
2180
|
if (initial) {
|
|
2010
2181
|
return [SetDom2, uid, []];
|
|
2011
2182
|
}
|
|
2012
|
-
const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue);
|
|
2183
|
+
const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, viewMode);
|
|
2013
2184
|
return [SetDom2, uid, dom];
|
|
2014
2185
|
};
|
|
2015
2186
|
|
|
@@ -2057,8 +2228,18 @@ const render2 = (uid, diffResult) => {
|
|
|
2057
2228
|
|
|
2058
2229
|
const renderEventListeners = () => {
|
|
2059
2230
|
return [{
|
|
2231
|
+
name: HandleContextMenu,
|
|
2232
|
+
params: ['handleChatListContextMenu', TargetName, ClientX, ClientY],
|
|
2233
|
+
preventDefault: true
|
|
2234
|
+
}, {
|
|
2060
2235
|
name: HandleClick,
|
|
2061
2236
|
params: ['handleClick', TargetName]
|
|
2237
|
+
}, {
|
|
2238
|
+
name: HandleClickClose,
|
|
2239
|
+
params: ['handleClickClose']
|
|
2240
|
+
}, {
|
|
2241
|
+
name: HandleClickSettings,
|
|
2242
|
+
params: ['handleClickSettings']
|
|
2062
2243
|
}, {
|
|
2063
2244
|
name: HandleInput,
|
|
2064
2245
|
params: ['handleInput', TargetValue]
|
|
@@ -2079,18 +2260,40 @@ const saveState = state => {
|
|
|
2079
2260
|
const {
|
|
2080
2261
|
composerValue,
|
|
2081
2262
|
nextMessageId,
|
|
2082
|
-
nextSessionId,
|
|
2083
2263
|
renamingSessionId,
|
|
2084
2264
|
selectedSessionId,
|
|
2085
|
-
sessions
|
|
2265
|
+
sessions,
|
|
2266
|
+
viewMode
|
|
2086
2267
|
} = state;
|
|
2087
2268
|
return {
|
|
2088
2269
|
composerValue,
|
|
2089
2270
|
nextMessageId,
|
|
2090
|
-
nextSessionId,
|
|
2091
2271
|
renamingSessionId,
|
|
2092
2272
|
selectedSessionId,
|
|
2093
|
-
sessions
|
|
2273
|
+
sessions,
|
|
2274
|
+
viewMode
|
|
2275
|
+
};
|
|
2276
|
+
};
|
|
2277
|
+
|
|
2278
|
+
const dummySessions = [{
|
|
2279
|
+
id: 'session-a',
|
|
2280
|
+
messages: [],
|
|
2281
|
+
title: dummyChatA
|
|
2282
|
+
}, {
|
|
2283
|
+
id: 'session-b',
|
|
2284
|
+
messages: [],
|
|
2285
|
+
title: dummyChatB
|
|
2286
|
+
}, {
|
|
2287
|
+
id: 'session-c',
|
|
2288
|
+
messages: [],
|
|
2289
|
+
title: dummyChatC
|
|
2290
|
+
}];
|
|
2291
|
+
const setChatList = state => {
|
|
2292
|
+
return {
|
|
2293
|
+
...state,
|
|
2294
|
+
selectedSessionId: dummySessions[0].id,
|
|
2295
|
+
sessions: dummySessions,
|
|
2296
|
+
viewMode: 'detail'
|
|
2094
2297
|
};
|
|
2095
2298
|
};
|
|
2096
2299
|
|
|
@@ -2099,10 +2302,13 @@ const commandMap = {
|
|
|
2099
2302
|
'Chat.diff2': diff2,
|
|
2100
2303
|
'Chat.getCommandIds': getCommandIds,
|
|
2101
2304
|
'Chat.getKeyBindings': getKeyBindings,
|
|
2305
|
+
'Chat.handleChatListContextMenu': handleChatListContextMenu,
|
|
2102
2306
|
'Chat.handleClick': wrapCommand(handleClick),
|
|
2103
2307
|
'Chat.handleClickClose': handleClickClose,
|
|
2308
|
+
'Chat.handleClickSettings': handleClickSettings,
|
|
2104
2309
|
'Chat.handleInput': wrapCommand(handleInput),
|
|
2105
2310
|
'Chat.handleKeyDown': wrapCommand(handleKeyDown),
|
|
2311
|
+
'Chat.handleSubmit': wrapCommand(handleSubmit),
|
|
2106
2312
|
'Chat.initialize': initialize,
|
|
2107
2313
|
'Chat.loadContent': wrapCommand(loadContent),
|
|
2108
2314
|
'Chat.loadContent2': wrapCommand(loadContent),
|
|
@@ -2110,6 +2316,7 @@ const commandMap = {
|
|
|
2110
2316
|
'Chat.renderEventListeners': renderEventListeners,
|
|
2111
2317
|
'Chat.resize': wrapCommand(resize),
|
|
2112
2318
|
'Chat.saveState': wrapGetter(saveState),
|
|
2319
|
+
'Chat.setChatList': wrapCommand(setChatList),
|
|
2113
2320
|
'Chat.terminate': terminate
|
|
2114
2321
|
};
|
|
2115
2322
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lvce-editor/chat-view",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Chat View Worker",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"type": "module",
|
|
12
12
|
"main": "dist/chatViewWorkerMain.js",
|
|
13
13
|
"dependencies": {
|
|
14
|
+
"@lvce-editor/i18n": "^2.1.0",
|
|
14
15
|
"@lvce-editor/virtual-dom-worker": "^8.9.0"
|
|
15
16
|
}
|
|
16
17
|
}
|