@lvce-editor/chat-view 1.4.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 +361 -177
- 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,37 +1304,22 @@ const getKeyBindings = () => {
|
|
|
1271
1304
|
return [];
|
|
1272
1305
|
};
|
|
1273
1306
|
|
|
1274
|
-
const
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
} = state;
|
|
1280
|
-
const title = composerValue.trim();
|
|
1281
|
-
if (!renamingSessionId || !title) {
|
|
1282
|
-
return {
|
|
1283
|
-
...state,
|
|
1284
|
-
renamingSessionId: ''
|
|
1285
|
-
};
|
|
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;
|
|
1286
1312
|
}
|
|
1287
|
-
const
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
};
|
|
1295
|
-
});
|
|
1296
|
-
return {
|
|
1297
|
-
...state,
|
|
1298
|
-
composerValue: '',
|
|
1299
|
-
ignoreNextInput: true,
|
|
1300
|
-
renamingSessionId: '',
|
|
1301
|
-
sessions: updatedSessions
|
|
1302
|
-
};
|
|
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();
|
|
1303
1320
|
};
|
|
1304
|
-
|
|
1321
|
+
|
|
1322
|
+
const handleSubmit = async state => {
|
|
1305
1323
|
const {
|
|
1306
1324
|
composerValue,
|
|
1307
1325
|
nextMessageId,
|
|
@@ -1309,6 +1327,10 @@ const submitMessage = state => {
|
|
|
1309
1327
|
sessions
|
|
1310
1328
|
} = state;
|
|
1311
1329
|
const text = composerValue.trim();
|
|
1330
|
+
const time = new Date().toLocaleTimeString([], {
|
|
1331
|
+
hour: '2-digit',
|
|
1332
|
+
minute: '2-digit'
|
|
1333
|
+
});
|
|
1312
1334
|
if (!text) {
|
|
1313
1335
|
return {
|
|
1314
1336
|
...state,
|
|
@@ -1322,7 +1344,8 @@ const submitMessage = state => {
|
|
|
1322
1344
|
const message = {
|
|
1323
1345
|
id: `message-${nextMessageId}`,
|
|
1324
1346
|
role: 'user',
|
|
1325
|
-
text
|
|
1347
|
+
text,
|
|
1348
|
+
time
|
|
1326
1349
|
};
|
|
1327
1350
|
return {
|
|
1328
1351
|
...session,
|
|
@@ -1338,23 +1361,15 @@ const submitMessage = state => {
|
|
|
1338
1361
|
sessions: updatedSessions
|
|
1339
1362
|
};
|
|
1340
1363
|
};
|
|
1341
|
-
const handleKeyDown = async (state, key, shiftKey) => {
|
|
1342
|
-
if (key !== 'Enter' || shiftKey) {
|
|
1343
|
-
return state;
|
|
1344
|
-
}
|
|
1345
|
-
if (state.renamingSessionId) {
|
|
1346
|
-
return submitRename(state);
|
|
1347
|
-
}
|
|
1348
|
-
return submitMessage(state);
|
|
1349
|
-
};
|
|
1350
1364
|
|
|
1351
1365
|
const CREATE_SESSION = 'create-session';
|
|
1352
1366
|
const SESSION_PREFIX = 'session:';
|
|
1353
1367
|
const RENAME_PREFIX = 'session-rename:';
|
|
1354
1368
|
const DELETE_PREFIX = 'session-delete:';
|
|
1355
1369
|
const SEND = 'send';
|
|
1370
|
+
const BACK = 'back';
|
|
1356
1371
|
const handleClickSend = async state => {
|
|
1357
|
-
return
|
|
1372
|
+
return handleSubmit(state);
|
|
1358
1373
|
};
|
|
1359
1374
|
const getNextSelectedSessionId = (sessions, deletedId) => {
|
|
1360
1375
|
if (sessions.length === 0) {
|
|
@@ -1368,15 +1383,14 @@ const getNextSelectedSessionId = (sessions, deletedId) => {
|
|
|
1368
1383
|
return sessions[nextIndex].id;
|
|
1369
1384
|
};
|
|
1370
1385
|
const createSession = state => {
|
|
1371
|
-
const id =
|
|
1386
|
+
const id = generateSessionId();
|
|
1372
1387
|
const session = {
|
|
1373
1388
|
id,
|
|
1374
1389
|
messages: [],
|
|
1375
|
-
title: `Chat ${state.
|
|
1390
|
+
title: `Chat ${state.sessions.length + 1}`
|
|
1376
1391
|
};
|
|
1377
1392
|
return {
|
|
1378
1393
|
...state,
|
|
1379
|
-
nextSessionId: state.nextSessionId + 1,
|
|
1380
1394
|
renamingSessionId: '',
|
|
1381
1395
|
selectedSessionId: id,
|
|
1382
1396
|
sessions: [...state.sessions, session]
|
|
@@ -1390,7 +1404,8 @@ const selectSession = (state, id) => {
|
|
|
1390
1404
|
return {
|
|
1391
1405
|
...state,
|
|
1392
1406
|
renamingSessionId: '',
|
|
1393
|
-
selectedSessionId: id
|
|
1407
|
+
selectedSessionId: id,
|
|
1408
|
+
viewMode: 'detail'
|
|
1394
1409
|
};
|
|
1395
1410
|
};
|
|
1396
1411
|
const startRename = (state, id) => {
|
|
@@ -1411,18 +1426,12 @@ const deleteSession = (state, id) => {
|
|
|
1411
1426
|
return state;
|
|
1412
1427
|
}
|
|
1413
1428
|
if (filtered.length === 0) {
|
|
1414
|
-
const fallbackId = `session-${state.nextSessionId}`;
|
|
1415
|
-
const fallback = {
|
|
1416
|
-
id: fallbackId,
|
|
1417
|
-
messages: [],
|
|
1418
|
-
title: `Chat ${state.nextSessionId}`
|
|
1419
|
-
};
|
|
1420
1429
|
return {
|
|
1421
1430
|
...state,
|
|
1422
|
-
nextSessionId: state.nextSessionId + 1,
|
|
1423
1431
|
renamingSessionId: '',
|
|
1424
|
-
selectedSessionId:
|
|
1425
|
-
sessions: [
|
|
1432
|
+
selectedSessionId: '',
|
|
1433
|
+
sessions: [],
|
|
1434
|
+
viewMode: 'list'
|
|
1426
1435
|
};
|
|
1427
1436
|
}
|
|
1428
1437
|
return {
|
|
@@ -1454,6 +1463,13 @@ const handleClick = async (state, name) => {
|
|
|
1454
1463
|
if (name === SEND) {
|
|
1455
1464
|
return handleClickSend(state);
|
|
1456
1465
|
}
|
|
1466
|
+
if (name === BACK) {
|
|
1467
|
+
return {
|
|
1468
|
+
...state,
|
|
1469
|
+
renamingSessionId: '',
|
|
1470
|
+
viewMode: 'list'
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1457
1473
|
return state;
|
|
1458
1474
|
};
|
|
1459
1475
|
|
|
@@ -1477,6 +1493,46 @@ const handleInput = async (state, value) => {
|
|
|
1477
1493
|
};
|
|
1478
1494
|
};
|
|
1479
1495
|
|
|
1496
|
+
const submitRename = state => {
|
|
1497
|
+
const {
|
|
1498
|
+
composerValue,
|
|
1499
|
+
renamingSessionId,
|
|
1500
|
+
sessions
|
|
1501
|
+
} = state;
|
|
1502
|
+
const title = composerValue.trim();
|
|
1503
|
+
if (!renamingSessionId || !title) {
|
|
1504
|
+
return {
|
|
1505
|
+
...state,
|
|
1506
|
+
renamingSessionId: ''
|
|
1507
|
+
};
|
|
1508
|
+
}
|
|
1509
|
+
const updatedSessions = sessions.map(session => {
|
|
1510
|
+
if (session.id !== renamingSessionId) {
|
|
1511
|
+
return session;
|
|
1512
|
+
}
|
|
1513
|
+
return {
|
|
1514
|
+
...session,
|
|
1515
|
+
title
|
|
1516
|
+
};
|
|
1517
|
+
});
|
|
1518
|
+
return {
|
|
1519
|
+
...state,
|
|
1520
|
+
composerValue: '',
|
|
1521
|
+
ignoreNextInput: true,
|
|
1522
|
+
renamingSessionId: '',
|
|
1523
|
+
sessions: updatedSessions
|
|
1524
|
+
};
|
|
1525
|
+
};
|
|
1526
|
+
const handleKeyDown = async (state, key, shiftKey) => {
|
|
1527
|
+
if (key !== 'Enter' || shiftKey) {
|
|
1528
|
+
return state;
|
|
1529
|
+
}
|
|
1530
|
+
if (state.renamingSessionId) {
|
|
1531
|
+
return submitRename(state);
|
|
1532
|
+
}
|
|
1533
|
+
return handleSubmit(state);
|
|
1534
|
+
};
|
|
1535
|
+
|
|
1480
1536
|
const id = 7201;
|
|
1481
1537
|
const sendMessagePortToExtensionHostWorker = async port => {
|
|
1482
1538
|
await sendMessagePortToExtensionHostWorker$1(port, id);
|
|
@@ -1499,26 +1555,47 @@ const initialize = async () => {
|
|
|
1499
1555
|
set$2(rpc);
|
|
1500
1556
|
};
|
|
1501
1557
|
|
|
1502
|
-
const
|
|
1503
|
-
|
|
1504
|
-
|
|
1558
|
+
const isObject = value => {
|
|
1559
|
+
return typeof value === 'object' && value !== null;
|
|
1560
|
+
};
|
|
1561
|
+
|
|
1562
|
+
const getSavedSelectedSessionId = savedState => {
|
|
1563
|
+
if (!isObject(savedState)) {
|
|
1564
|
+
return undefined;
|
|
1505
1565
|
}
|
|
1506
|
-
const
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
}
|
|
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;
|
|
1512
1586
|
};
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
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';
|
|
1516
1593
|
return {
|
|
1517
1594
|
...state,
|
|
1518
1595
|
initial: false,
|
|
1519
|
-
nextSessionId: state.sessions.length === 0 ? state.nextSessionId + 1 : state.nextSessionId,
|
|
1520
1596
|
selectedSessionId,
|
|
1521
|
-
sessions
|
|
1597
|
+
sessions,
|
|
1598
|
+
viewMode
|
|
1522
1599
|
};
|
|
1523
1600
|
};
|
|
1524
1601
|
|
|
@@ -1530,6 +1607,10 @@ const renderCss = (oldState, newState) => {
|
|
|
1530
1607
|
return [SetCss, newState.uid, css];
|
|
1531
1608
|
};
|
|
1532
1609
|
|
|
1610
|
+
const mergeClassNames = (...classNames) => {
|
|
1611
|
+
return classNames.filter(Boolean).join(' ');
|
|
1612
|
+
};
|
|
1613
|
+
|
|
1533
1614
|
const text = data => {
|
|
1534
1615
|
return {
|
|
1535
1616
|
childCount: 0,
|
|
@@ -1827,168 +1908,264 @@ const diffTree = (oldNodes, newNodes) => {
|
|
|
1827
1908
|
};
|
|
1828
1909
|
|
|
1829
1910
|
const ChatActions = 'ChatActions';
|
|
1911
|
+
const ChatName = 'ChatName';
|
|
1912
|
+
const ChatSendArea = 'ChatSendArea';
|
|
1913
|
+
const Chat = 'Chat';
|
|
1830
1914
|
const ChatHeader = 'ChatHeader';
|
|
1831
1915
|
const Button = 'Button';
|
|
1916
|
+
const ButtonPrimary = 'ButtonPrimary';
|
|
1832
1917
|
const ChatDetails = 'ChatDetails';
|
|
1833
1918
|
const ChatDetailsContent = 'ChatDetailsContent';
|
|
1834
1919
|
const IconButton = 'IconButton';
|
|
1835
1920
|
const Label = 'Label';
|
|
1836
1921
|
const ChatList = 'ChatList';
|
|
1922
|
+
const ChatListItem = 'ChatListItem';
|
|
1837
1923
|
const Markdown = 'Markdown';
|
|
1838
1924
|
const Message = 'Message';
|
|
1839
1925
|
const MultilineInputBox = 'MultilineInputBox';
|
|
1840
1926
|
const Viewlet = 'Viewlet';
|
|
1841
1927
|
const ChatWelcomeMessage = 'ChatWelcomeMessage';
|
|
1842
1928
|
|
|
1929
|
+
const HandleContextMenu = 2;
|
|
1843
1930
|
const HandleInput = 4;
|
|
1844
1931
|
const HandleClick = 11;
|
|
1845
1932
|
const HandleKeyDown = 12;
|
|
1846
1933
|
const HandleClickClose = 13;
|
|
1847
1934
|
const HandleClickSettings = 14;
|
|
1848
1935
|
|
|
1849
|
-
const
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
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;
|
|
1858
1957
|
return [{
|
|
1859
|
-
childCount: 2,
|
|
1860
|
-
className: Message,
|
|
1861
|
-
type: Div
|
|
1862
|
-
}, {
|
|
1863
|
-
childCount: 1,
|
|
1864
|
-
className: Label,
|
|
1865
|
-
type: Strong
|
|
1866
|
-
}, text(message.role === 'user' ? 'You' : 'Assistant'), {
|
|
1867
1958
|
childCount: 1,
|
|
1868
|
-
className:
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
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('←')];
|
|
1872
1984
|
};
|
|
1873
1985
|
|
|
1874
|
-
const
|
|
1875
|
-
const sessionClassName = ChatList;
|
|
1986
|
+
const getChatHeaderDomDetailMode = selectedSessionTitle => {
|
|
1876
1987
|
return [{
|
|
1877
1988
|
childCount: 2,
|
|
1878
|
-
className:
|
|
1989
|
+
className: ChatHeader,
|
|
1879
1990
|
type: Div
|
|
1880
1991
|
}, {
|
|
1992
|
+
childCount: 2,
|
|
1993
|
+
className: ChatName,
|
|
1994
|
+
type: Div
|
|
1995
|
+
}, ...getChatHeaderBackButtonVirtualDom(), {
|
|
1881
1996
|
childCount: 1,
|
|
1882
|
-
className:
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1997
|
+
className: Label,
|
|
1998
|
+
type: Span
|
|
1999
|
+
}, text(selectedSessionTitle), ...getChatHeaderActionsDom()];
|
|
2000
|
+
};
|
|
2001
|
+
|
|
2002
|
+
const getChatDetailsDom = (selectedSessionTitle, messagesNodes, composerValue) => {
|
|
2003
|
+
return [{
|
|
2004
|
+
childCount: 3,
|
|
2005
|
+
className: ChatDetails,
|
|
2006
|
+
type: Div
|
|
2007
|
+
}, {
|
|
2008
|
+
childCount: 1,
|
|
2009
|
+
className: Label,
|
|
2010
|
+
type: Span
|
|
2011
|
+
}, text(selectedSessionTitle), {
|
|
2012
|
+
childCount: Math.max(messagesNodes.length, 0),
|
|
2013
|
+
className: ChatDetailsContent,
|
|
2014
|
+
type: Div
|
|
2015
|
+
}, ...messagesNodes, {
|
|
1888
2016
|
childCount: 2,
|
|
1889
|
-
className:
|
|
2017
|
+
className: ChatSendArea,
|
|
1890
2018
|
type: Div
|
|
2019
|
+
}, {
|
|
2020
|
+
childCount: 0,
|
|
2021
|
+
className: MultilineInputBox,
|
|
2022
|
+
name: 'composer',
|
|
2023
|
+
placeholder: composePlaceholder,
|
|
2024
|
+
rows: 4,
|
|
2025
|
+
type: TextArea,
|
|
2026
|
+
value: composerValue
|
|
1891
2027
|
}, {
|
|
1892
2028
|
childCount: 1,
|
|
1893
|
-
className:
|
|
1894
|
-
name:
|
|
2029
|
+
className: Button + ' ' + ButtonPrimary,
|
|
2030
|
+
name: 'send',
|
|
1895
2031
|
role: Button$2,
|
|
1896
2032
|
tabIndex: 0,
|
|
1897
|
-
title:
|
|
2033
|
+
title: sendMessage,
|
|
1898
2034
|
type: Button$1
|
|
1899
|
-
}, text(
|
|
2035
|
+
}, text(send)];
|
|
2036
|
+
};
|
|
2037
|
+
|
|
2038
|
+
const getChatContentDom = (viewMode, sessionsLength, emptyStateNodes, sessionNodes, selectedSessionTitle, messagesNodes, composerValue) => {
|
|
2039
|
+
return getChatDetailsDom(selectedSessionTitle, messagesNodes, composerValue);
|
|
2040
|
+
};
|
|
2041
|
+
|
|
2042
|
+
const getChatMessageDom = message => {
|
|
2043
|
+
return [{
|
|
2044
|
+
childCount: 2,
|
|
2045
|
+
className: Message,
|
|
2046
|
+
type: Div
|
|
2047
|
+
}, {
|
|
1900
2048
|
childCount: 1,
|
|
1901
|
-
className:
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
type:
|
|
1907
|
-
}, text(
|
|
2049
|
+
className: Label,
|
|
2050
|
+
type: Strong
|
|
2051
|
+
}, text(`${message.role === 'user' ? you : assistant} · ${message.time}`), {
|
|
2052
|
+
childCount: 1,
|
|
2053
|
+
className: Markdown,
|
|
2054
|
+
type: P
|
|
2055
|
+
}, text(message.text)];
|
|
2056
|
+
};
|
|
2057
|
+
const getMessagesDom = messages => {
|
|
2058
|
+
if (messages.length === 0) {
|
|
2059
|
+
return [{
|
|
2060
|
+
childCount: 1,
|
|
2061
|
+
className: ChatWelcomeMessage,
|
|
2062
|
+
type: Div
|
|
2063
|
+
}, text(startConversation)];
|
|
2064
|
+
}
|
|
2065
|
+
return messages.flatMap(message => {
|
|
2066
|
+
return getChatMessageDom(message);
|
|
2067
|
+
});
|
|
1908
2068
|
};
|
|
1909
2069
|
|
|
1910
|
-
const
|
|
2070
|
+
const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue) => {
|
|
1911
2071
|
const selectedSession = sessions.find(session => session.id === selectedSessionId);
|
|
2072
|
+
const selectedSessionTitle = selectedSession?.title || chatTitle;
|
|
1912
2073
|
const messages = selectedSession ? selectedSession.messages : [];
|
|
1913
|
-
const sessionNodes = sessions.flatMap(session => getSessionDom(session));
|
|
1914
2074
|
const messagesNodes = getMessagesDom(messages);
|
|
1915
|
-
const
|
|
1916
|
-
|
|
2075
|
+
const contentNodes = getChatContentDom('detail', sessions.length, [], [], selectedSessionTitle, messagesNodes, composerValue);
|
|
2076
|
+
return [{
|
|
2077
|
+
childCount: 2,
|
|
1917
2078
|
className: Viewlet + ' Chat',
|
|
1918
2079
|
onClick: HandleClick,
|
|
1919
2080
|
onInput: HandleInput,
|
|
1920
2081
|
onKeyDown: HandleKeyDown,
|
|
1921
2082
|
type: Div
|
|
1922
|
-
},
|
|
2083
|
+
}, ...getChatHeaderDomDetailMode(selectedSessionTitle), ...contentNodes];
|
|
2084
|
+
};
|
|
2085
|
+
|
|
2086
|
+
const getChatHeaderListModeDom = () => {
|
|
2087
|
+
return [{
|
|
1923
2088
|
childCount: 2,
|
|
1924
2089
|
className: ChatHeader,
|
|
1925
2090
|
type: Div
|
|
1926
|
-
}, {
|
|
1927
|
-
childCount: 4,
|
|
1928
|
-
className: ChatActions,
|
|
1929
|
-
type: Div
|
|
1930
2091
|
}, {
|
|
1931
2092
|
childCount: 1,
|
|
1932
2093
|
className: Label,
|
|
1933
2094
|
type: Span
|
|
1934
|
-
}, text(
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
}, text('+'), {
|
|
1943
|
-
childCount: 1,
|
|
1944
|
-
className: IconButton,
|
|
1945
|
-
onClick: HandleClickSettings,
|
|
1946
|
-
role: Button$2,
|
|
1947
|
-
tabIndex: 0,
|
|
1948
|
-
title: 'Settings',
|
|
1949
|
-
type: Button$1
|
|
1950
|
-
}, text('⚙'), {
|
|
2095
|
+
}, text(chats), ...getChatHeaderActionsDom()];
|
|
2096
|
+
};
|
|
2097
|
+
|
|
2098
|
+
const getEmptyChatSessionsDom = sessionsLength => {
|
|
2099
|
+
if (sessionsLength !== 0) {
|
|
2100
|
+
return [];
|
|
2101
|
+
}
|
|
2102
|
+
return [{
|
|
1951
2103
|
childCount: 1,
|
|
1952
|
-
className:
|
|
1953
|
-
onClick: HandleClickClose,
|
|
1954
|
-
role: Button$2,
|
|
1955
|
-
tabIndex: 0,
|
|
1956
|
-
title: 'Close Chat',
|
|
1957
|
-
type: Button$1
|
|
1958
|
-
}, text('×'), {
|
|
1959
|
-
childCount: sessions.length,
|
|
1960
|
-
className: ChatList,
|
|
2104
|
+
className: Label,
|
|
1961
2105
|
type: Div
|
|
1962
|
-
},
|
|
2106
|
+
}, text(clickToOpenNewChat)];
|
|
2107
|
+
};
|
|
2108
|
+
|
|
2109
|
+
const getSessionDom = (session, _selectedSessionId) => {
|
|
2110
|
+
const sessionClassName = ChatListItem;
|
|
2111
|
+
return [{
|
|
1963
2112
|
childCount: 2,
|
|
1964
|
-
className:
|
|
2113
|
+
className: sessionClassName,
|
|
1965
2114
|
type: Div
|
|
1966
2115
|
}, {
|
|
1967
|
-
childCount:
|
|
1968
|
-
className:
|
|
2116
|
+
childCount: 1,
|
|
2117
|
+
className: ChatName,
|
|
2118
|
+
name: `session:${session.id}`,
|
|
2119
|
+
onContextMenu: HandleContextMenu,
|
|
2120
|
+
tabIndex: 0,
|
|
1969
2121
|
type: Div
|
|
1970
|
-
},
|
|
1971
|
-
childCount:
|
|
2122
|
+
}, text(session.title), {
|
|
2123
|
+
childCount: 1,
|
|
1972
2124
|
className: ChatActions,
|
|
1973
2125
|
type: Div
|
|
1974
|
-
}, {
|
|
1975
|
-
childCount: 0,
|
|
1976
|
-
className: MultilineInputBox,
|
|
1977
|
-
name: 'composer',
|
|
1978
|
-
placeholder: 'Type your message. Enter to send, Shift+Enter for newline.',
|
|
1979
|
-
rows: 4,
|
|
1980
|
-
type: TextArea,
|
|
1981
|
-
value: composerValue
|
|
1982
2126
|
}, {
|
|
1983
2127
|
childCount: 1,
|
|
1984
|
-
className:
|
|
1985
|
-
name:
|
|
2128
|
+
className: IconButton,
|
|
2129
|
+
name: `session-delete:${session.id}`,
|
|
1986
2130
|
role: Button$2,
|
|
1987
2131
|
tabIndex: 0,
|
|
1988
|
-
title:
|
|
2132
|
+
title: deleteChatSession,
|
|
1989
2133
|
type: Button$1
|
|
1990
|
-
}, text('
|
|
1991
|
-
|
|
2134
|
+
}, text('🗑')];
|
|
2135
|
+
};
|
|
2136
|
+
|
|
2137
|
+
const getChatModeListVirtualDom = (sessions, selectedSessionId) => {
|
|
2138
|
+
const sessionNodes = sessions.flatMap(session => getSessionDom(session));
|
|
2139
|
+
const emptyStateNodes = getEmptyChatSessionsDom(sessions.length);
|
|
2140
|
+
return [{
|
|
2141
|
+
childCount: 2,
|
|
2142
|
+
className: mergeClassNames(Viewlet, Chat),
|
|
2143
|
+
onClick: HandleClick,
|
|
2144
|
+
onInput: HandleInput,
|
|
2145
|
+
onKeyDown: HandleKeyDown,
|
|
2146
|
+
type: Div
|
|
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
|
+
}
|
|
1992
2169
|
};
|
|
1993
2170
|
|
|
1994
2171
|
const renderItems = (oldState, newState) => {
|
|
@@ -1997,12 +2174,13 @@ const renderItems = (oldState, newState) => {
|
|
|
1997
2174
|
initial,
|
|
1998
2175
|
selectedSessionId,
|
|
1999
2176
|
sessions,
|
|
2000
|
-
uid
|
|
2177
|
+
uid,
|
|
2178
|
+
viewMode
|
|
2001
2179
|
} = newState;
|
|
2002
2180
|
if (initial) {
|
|
2003
2181
|
return [SetDom2, uid, []];
|
|
2004
2182
|
}
|
|
2005
|
-
const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue);
|
|
2183
|
+
const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, viewMode);
|
|
2006
2184
|
return [SetDom2, uid, dom];
|
|
2007
2185
|
};
|
|
2008
2186
|
|
|
@@ -2050,6 +2228,10 @@ const render2 = (uid, diffResult) => {
|
|
|
2050
2228
|
|
|
2051
2229
|
const renderEventListeners = () => {
|
|
2052
2230
|
return [{
|
|
2231
|
+
name: HandleContextMenu,
|
|
2232
|
+
params: ['handleChatListContextMenu', TargetName, ClientX, ClientY],
|
|
2233
|
+
preventDefault: true
|
|
2234
|
+
}, {
|
|
2053
2235
|
name: HandleClick,
|
|
2054
2236
|
params: ['handleClick', TargetName]
|
|
2055
2237
|
}, {
|
|
@@ -2078,40 +2260,40 @@ const saveState = state => {
|
|
|
2078
2260
|
const {
|
|
2079
2261
|
composerValue,
|
|
2080
2262
|
nextMessageId,
|
|
2081
|
-
nextSessionId,
|
|
2082
2263
|
renamingSessionId,
|
|
2083
2264
|
selectedSessionId,
|
|
2084
|
-
sessions
|
|
2265
|
+
sessions,
|
|
2266
|
+
viewMode
|
|
2085
2267
|
} = state;
|
|
2086
2268
|
return {
|
|
2087
2269
|
composerValue,
|
|
2088
2270
|
nextMessageId,
|
|
2089
|
-
nextSessionId,
|
|
2090
2271
|
renamingSessionId,
|
|
2091
2272
|
selectedSessionId,
|
|
2092
|
-
sessions
|
|
2273
|
+
sessions,
|
|
2274
|
+
viewMode
|
|
2093
2275
|
};
|
|
2094
2276
|
};
|
|
2095
2277
|
|
|
2096
2278
|
const dummySessions = [{
|
|
2097
2279
|
id: 'session-a',
|
|
2098
2280
|
messages: [],
|
|
2099
|
-
title:
|
|
2281
|
+
title: dummyChatA
|
|
2100
2282
|
}, {
|
|
2101
2283
|
id: 'session-b',
|
|
2102
2284
|
messages: [],
|
|
2103
|
-
title:
|
|
2285
|
+
title: dummyChatB
|
|
2104
2286
|
}, {
|
|
2105
2287
|
id: 'session-c',
|
|
2106
2288
|
messages: [],
|
|
2107
|
-
title:
|
|
2289
|
+
title: dummyChatC
|
|
2108
2290
|
}];
|
|
2109
2291
|
const setChatList = state => {
|
|
2110
2292
|
return {
|
|
2111
2293
|
...state,
|
|
2112
|
-
nextSessionId: dummySessions.length + 1,
|
|
2113
2294
|
selectedSessionId: dummySessions[0].id,
|
|
2114
|
-
sessions: dummySessions
|
|
2295
|
+
sessions: dummySessions,
|
|
2296
|
+
viewMode: 'detail'
|
|
2115
2297
|
};
|
|
2116
2298
|
};
|
|
2117
2299
|
|
|
@@ -2120,11 +2302,13 @@ const commandMap = {
|
|
|
2120
2302
|
'Chat.diff2': diff2,
|
|
2121
2303
|
'Chat.getCommandIds': getCommandIds,
|
|
2122
2304
|
'Chat.getKeyBindings': getKeyBindings,
|
|
2305
|
+
'Chat.handleChatListContextMenu': handleChatListContextMenu,
|
|
2123
2306
|
'Chat.handleClick': wrapCommand(handleClick),
|
|
2124
2307
|
'Chat.handleClickClose': handleClickClose,
|
|
2125
2308
|
'Chat.handleClickSettings': handleClickSettings,
|
|
2126
2309
|
'Chat.handleInput': wrapCommand(handleInput),
|
|
2127
2310
|
'Chat.handleKeyDown': wrapCommand(handleKeyDown),
|
|
2311
|
+
'Chat.handleSubmit': wrapCommand(handleSubmit),
|
|
2128
2312
|
'Chat.initialize': initialize,
|
|
2129
2313
|
'Chat.loadContent': wrapCommand(loadContent),
|
|
2130
2314
|
'Chat.loadContent2': wrapCommand(loadContent),
|
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
|
}
|