@lvce-editor/chat-view 1.4.0 → 1.6.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.
@@ -972,9 +972,10 @@ const Span = 8;
972
972
  const Text = 12;
973
973
  const P = 50;
974
974
  const TextArea = 62;
975
- const Strong = 70;
976
975
  const Reference = 100;
977
976
 
977
+ const ClientX = 'event.clientX';
978
+ const ClientY = 'event.clientY';
978
979
  const Key = 'event.key';
979
980
  const ShiftKey = 'event.shiftKey';
980
981
  const TargetName = 'event.target.name';
@@ -983,8 +984,10 @@ const TargetValue = 'event.target.value';
983
984
  const ExtensionHostWorker = 44;
984
985
  const RendererWorker = 1;
985
986
 
987
+ const FocusSelector = 'Viewlet.focusSelector';
986
988
  const SetCss = 'Viewlet.setCss';
987
989
  const SetDom2 = 'Viewlet.setDom2';
990
+ const SetValueByName = 'Viewlet.setValueByName';
988
991
  const SetPatches = 'Viewlet.setPatches';
989
992
 
990
993
  const createMockRpc = ({
@@ -1189,27 +1192,72 @@ const terminate = () => {
1189
1192
  globalThis.close();
1190
1193
  };
1191
1194
 
1195
+ const clearInput = async state => {
1196
+ return {
1197
+ ...state,
1198
+ composerValue: ''
1199
+ };
1200
+ };
1201
+
1202
+ const emptyObject = {};
1203
+ const RE_PLACEHOLDER = /\{(PH\d+)\}/g;
1204
+ const i18nString = (key, placeholders = emptyObject) => {
1205
+ if (placeholders === emptyObject) {
1206
+ return key;
1207
+ }
1208
+ const replacer = (match, rest) => {
1209
+ return placeholders[rest];
1210
+ };
1211
+ return key.replaceAll(RE_PLACEHOLDER, replacer);
1212
+ };
1213
+
1214
+ const chatTitle = i18nString('Chat');
1215
+ const chats = i18nString('Chats');
1216
+ const newChat = i18nString('New Chat');
1217
+ const backToChats = i18nString('Back to chats');
1218
+ const settings = i18nString('Settings');
1219
+ const closeChat = i18nString('Close Chat');
1220
+ const clickToOpenNewChat = i18nString('Click the + button to open a new chat.');
1221
+ const startConversation = i18nString('Start a conversation by typing below.');
1222
+ const you = i18nString('You');
1223
+ const assistant = i18nString('Assistant');
1224
+ const composePlaceholder = i18nString('Type your message. Enter to send, Shift+Enter for newline.');
1225
+ const sendMessage = i18nString('Send message');
1226
+ const send = i18nString('Send');
1227
+ const deleteChatSession = i18nString('Delete chat session');
1228
+ const defaultSessionTitle = i18nString('Chat 1');
1229
+ const dummyChatA = i18nString('Dummy Chat A');
1230
+ const dummyChatB = i18nString('Dummy Chat B');
1231
+ const dummyChatC = i18nString('Dummy Chat C');
1232
+
1192
1233
  const createDefaultState = () => {
1193
1234
  const defaultSessionId = 'session-1';
1194
1235
  return {
1195
1236
  assetDir: '',
1196
1237
  composerValue: '',
1197
1238
  errorCount: 0,
1198
- ignoreNextInput: false,
1239
+ focus: 'composer',
1240
+ focused: false,
1241
+ height: 0,
1199
1242
  initial: true,
1243
+ inputSource: 'script',
1200
1244
  lastSubmittedSessionId: '',
1245
+ listItemHeight: 40,
1201
1246
  nextMessageId: 1,
1202
- nextSessionId: 2,
1203
1247
  platform: 0,
1204
1248
  renamingSessionId: '',
1205
1249
  selectedSessionId: defaultSessionId,
1206
1250
  sessions: [{
1207
1251
  id: defaultSessionId,
1208
1252
  messages: [],
1209
- title: 'Chat 1'
1253
+ title: defaultSessionTitle
1210
1254
  }],
1211
1255
  uid: 0,
1212
- warningCount: 0
1256
+ viewMode: 'list',
1257
+ warningCount: 0,
1258
+ width: 0,
1259
+ x: 0,
1260
+ y: 0
1213
1261
  };
1214
1262
  };
1215
1263
 
@@ -1222,12 +1270,16 @@ const {
1222
1270
  wrapGetter
1223
1271
  } = create$1();
1224
1272
 
1225
- const create = (uid, uri, x, y, width, height, platform, assetDir) => {
1273
+ const create = (uid, _uri, x, y, width, height, platform, assetDir) => {
1226
1274
  const state = {
1227
1275
  ...createDefaultState(),
1228
1276
  assetDir,
1277
+ height,
1229
1278
  platform,
1230
- uid
1279
+ uid,
1280
+ width,
1281
+ x,
1282
+ y
1231
1283
  };
1232
1284
  set(uid, state, state);
1233
1285
  };
@@ -1236,16 +1288,32 @@ const isEqual$1 = (oldState, newState) => {
1236
1288
  return oldState.initial === newState.initial;
1237
1289
  };
1238
1290
 
1291
+ const diffFocus = (oldState, newState) => {
1292
+ if (!newState.focused) {
1293
+ return true;
1294
+ }
1295
+ return oldState.focus === newState.focus && oldState.focused === newState.focused;
1296
+ };
1297
+
1239
1298
  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;
1299
+ return oldState.composerValue === newState.composerValue && oldState.initial === newState.initial && oldState.renamingSessionId === newState.renamingSessionId && oldState.selectedSessionId === newState.selectedSessionId && oldState.sessions === newState.sessions && oldState.viewMode === newState.viewMode;
1241
1300
  };
1242
1301
 
1243
1302
  const RenderItems = 4;
1303
+ const RenderFocus = 6;
1304
+ const RenderValue = 8;
1244
1305
  const RenderCss = 10;
1245
1306
  const RenderIncremental = 11;
1246
1307
 
1247
- const modules = [isEqual, isEqual$1];
1248
- const numbers = [RenderIncremental, RenderCss];
1308
+ const diffValue = (oldState, newState) => {
1309
+ if (oldState.composerValue === newState.composerValue) {
1310
+ return true;
1311
+ }
1312
+ return newState.inputSource !== 'script';
1313
+ };
1314
+
1315
+ const modules = [isEqual, diffValue, diffFocus, isEqual$1];
1316
+ const numbers = [RenderIncremental, RenderValue, RenderFocus, RenderCss];
1249
1317
 
1250
1318
  const diff = (oldState, newState) => {
1251
1319
  const diffResult = [];
@@ -1271,117 +1339,186 @@ const getKeyBindings = () => {
1271
1339
  return [];
1272
1340
  };
1273
1341
 
1274
- const submitRename = state => {
1342
+ const SESSION_PREFIX$1 = 'session:';
1343
+ const CHAT_LIST_ITEM_CONTEXT_MENU = 'ChatListItemContextMenu';
1344
+ const handleChatListContextMenu = async (name, x, y) => {
1345
+ if (!name || !name.startsWith(SESSION_PREFIX$1)) {
1346
+ return;
1347
+ }
1348
+ const sessionId = name.slice(SESSION_PREFIX$1.length);
1349
+ // @ts-ignore
1350
+ await invoke('ContextMenu.show', x, y, CHAT_LIST_ITEM_CONTEXT_MENU, sessionId);
1351
+ };
1352
+
1353
+ const generateSessionId = () => {
1354
+ return crypto.randomUUID();
1355
+ };
1356
+
1357
+ const createSession = state => {
1358
+ const id = generateSessionId();
1359
+ const session = {
1360
+ id,
1361
+ messages: [],
1362
+ title: `Chat ${state.sessions.length + 1}`
1363
+ };
1364
+ return {
1365
+ ...state,
1366
+ renamingSessionId: '',
1367
+ selectedSessionId: id,
1368
+ sessions: [...state.sessions, session]
1369
+ };
1370
+ };
1371
+
1372
+ const getNextSelectedSessionId = (sessions, deletedId) => {
1373
+ if (sessions.length === 0) {
1374
+ return '';
1375
+ }
1376
+ const index = sessions.findIndex(session => session.id === deletedId);
1377
+ if (index === -1) {
1378
+ return sessions[0].id;
1379
+ }
1380
+ const nextIndex = Math.min(index, sessions.length - 1);
1381
+ return sessions[nextIndex].id;
1382
+ };
1383
+
1384
+ const deleteSession = (state, id) => {
1275
1385
  const {
1276
- composerValue,
1277
1386
  renamingSessionId,
1278
1387
  sessions
1279
1388
  } = state;
1280
- const title = composerValue.trim();
1281
- if (!renamingSessionId || !title) {
1389
+ const filtered = sessions.filter(session => session.id !== id);
1390
+ if (filtered.length === sessions.length) {
1391
+ return state;
1392
+ }
1393
+ if (filtered.length === 0) {
1282
1394
  return {
1283
1395
  ...state,
1284
- renamingSessionId: ''
1396
+ renamingSessionId: '',
1397
+ selectedSessionId: '',
1398
+ sessions: [],
1399
+ viewMode: 'list'
1285
1400
  };
1286
1401
  }
1287
- const updatedSessions = sessions.map(session => {
1288
- if (session.id !== renamingSessionId) {
1289
- return session;
1290
- }
1291
- return {
1292
- ...session,
1293
- title
1294
- };
1295
- });
1296
1402
  return {
1297
1403
  ...state,
1298
- composerValue: '',
1299
- ignoreNextInput: true,
1300
- renamingSessionId: '',
1301
- sessions: updatedSessions
1404
+ renamingSessionId: renamingSessionId === id ? '' : renamingSessionId,
1405
+ selectedSessionId: getNextSelectedSessionId(filtered, id),
1406
+ sessions: filtered
1302
1407
  };
1303
1408
  };
1304
- const submitMessage = state => {
1409
+
1410
+ const focusInput = state => {
1411
+ return {
1412
+ ...state,
1413
+ focus: 'composer',
1414
+ focused: true
1415
+ };
1416
+ };
1417
+
1418
+ const delay = async ms => {
1419
+ await new Promise(resolve => setTimeout(resolve, ms));
1420
+ };
1421
+ const getMockAiResponse = userMessage => {
1422
+ return `Mock AI response: I received "${userMessage}".`;
1423
+ };
1424
+ const handleSubmit = async state => {
1305
1425
  const {
1306
1426
  composerValue,
1307
1427
  nextMessageId,
1308
1428
  selectedSessionId,
1309
- sessions
1429
+ sessions,
1430
+ viewMode
1310
1431
  } = state;
1311
- const text = composerValue.trim();
1312
- if (!text) {
1313
- return {
1314
- ...state,
1315
- ignoreNextInput: true
1432
+ const userText = composerValue.trim();
1433
+ if (!userText) {
1434
+ return state;
1435
+ }
1436
+ const userTime = new Date().toLocaleTimeString([], {
1437
+ hour: '2-digit',
1438
+ minute: '2-digit'
1439
+ });
1440
+ const userMessage = {
1441
+ id: `message-${nextMessageId}`,
1442
+ role: 'user',
1443
+ text: userText,
1444
+ time: userTime
1445
+ };
1446
+ let optimisticState;
1447
+ if (viewMode === 'list') {
1448
+ const newSessionId = generateSessionId();
1449
+ const newSession = {
1450
+ id: newSessionId,
1451
+ messages: [userMessage],
1452
+ title: `Chat ${sessions.length + 1}`
1316
1453
  };
1454
+ optimisticState = focusInput({
1455
+ ...state,
1456
+ composerValue: '',
1457
+ inputSource: 'script',
1458
+ lastSubmittedSessionId: newSessionId,
1459
+ nextMessageId: nextMessageId + 1,
1460
+ selectedSessionId: newSessionId,
1461
+ sessions: [...sessions, newSession],
1462
+ viewMode: 'detail'
1463
+ });
1464
+ } else {
1465
+ const updatedSessions = sessions.map(session => {
1466
+ if (session.id !== selectedSessionId) {
1467
+ return session;
1468
+ }
1469
+ return {
1470
+ ...session,
1471
+ messages: [...session.messages, userMessage]
1472
+ };
1473
+ });
1474
+ optimisticState = focusInput({
1475
+ ...state,
1476
+ composerValue: '',
1477
+ inputSource: 'script',
1478
+ lastSubmittedSessionId: selectedSessionId,
1479
+ nextMessageId: nextMessageId + 1,
1480
+ sessions: updatedSessions
1481
+ });
1317
1482
  }
1318
- const updatedSessions = sessions.map(session => {
1319
- if (session.id !== selectedSessionId) {
1483
+ set(state.uid, state, optimisticState);
1484
+ // @ts-ignore
1485
+ await invoke('Chat.rerender');
1486
+ await delay(800);
1487
+ const assistantTime = new Date().toLocaleTimeString([], {
1488
+ hour: '2-digit',
1489
+ minute: '2-digit'
1490
+ });
1491
+ const assistantMessage = {
1492
+ id: `message-${optimisticState.nextMessageId}`,
1493
+ role: 'assistant',
1494
+ text: getMockAiResponse(userText),
1495
+ time: assistantTime
1496
+ };
1497
+ const updatedSessions = optimisticState.sessions.map(session => {
1498
+ if (session.id !== optimisticState.selectedSessionId) {
1320
1499
  return session;
1321
1500
  }
1322
- const message = {
1323
- id: `message-${nextMessageId}`,
1324
- role: 'user',
1325
- text
1326
- };
1327
1501
  return {
1328
1502
  ...session,
1329
- messages: [...session.messages, message]
1503
+ messages: [...session.messages, assistantMessage]
1330
1504
  };
1331
1505
  });
1332
- return {
1333
- ...state,
1334
- composerValue: '',
1335
- ignoreNextInput: true,
1336
- lastSubmittedSessionId: selectedSessionId,
1337
- nextMessageId: nextMessageId + 1,
1506
+ return focusInput({
1507
+ ...optimisticState,
1508
+ nextMessageId: optimisticState.nextMessageId + 1,
1338
1509
  sessions: updatedSessions
1339
- };
1340
- };
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);
1510
+ });
1349
1511
  };
1350
1512
 
1351
- const CREATE_SESSION = 'create-session';
1352
- const SESSION_PREFIX = 'session:';
1353
- const RENAME_PREFIX = 'session-rename:';
1354
- const DELETE_PREFIX = 'session-delete:';
1355
- const SEND = 'send';
1356
1513
  const handleClickSend = async state => {
1357
- return handleKeyDown(state, 'Enter', false);
1358
- };
1359
- const getNextSelectedSessionId = (sessions, deletedId) => {
1360
- if (sessions.length === 0) {
1361
- return '';
1362
- }
1363
- const index = sessions.findIndex(session => session.id === deletedId);
1364
- if (index === -1) {
1365
- return sessions[0].id;
1366
- }
1367
- const nextIndex = Math.min(index, sessions.length - 1);
1368
- return sessions[nextIndex].id;
1369
- };
1370
- const createSession = state => {
1371
- const id = `session-${state.nextSessionId}`;
1372
- const session = {
1373
- id,
1374
- messages: [],
1375
- title: `Chat ${state.nextSessionId}`
1376
- };
1377
- return {
1514
+ const hasSelectedSession = state.sessions.some(session => session.id === state.selectedSessionId);
1515
+ const submitState = state.viewMode === 'list' && hasSelectedSession ? {
1378
1516
  ...state,
1379
- nextSessionId: state.nextSessionId + 1,
1380
- renamingSessionId: '',
1381
- selectedSessionId: id,
1382
- sessions: [...state.sessions, session]
1383
- };
1517
+ viewMode: 'detail'
1518
+ } : state;
1519
+ return handleSubmit(submitState);
1384
1520
  };
1521
+
1385
1522
  const selectSession = (state, id) => {
1386
1523
  const exists = state.sessions.some(session => session.id === id);
1387
1524
  if (!exists) {
@@ -1390,9 +1527,11 @@ const selectSession = (state, id) => {
1390
1527
  return {
1391
1528
  ...state,
1392
1529
  renamingSessionId: '',
1393
- selectedSessionId: id
1530
+ selectedSessionId: id,
1531
+ viewMode: 'detail'
1394
1532
  };
1395
1533
  };
1534
+
1396
1535
  const startRename = (state, id) => {
1397
1536
  const session = state.sessions.find(item => item.id === id);
1398
1537
  if (!session) {
@@ -1401,38 +1540,47 @@ const startRename = (state, id) => {
1401
1540
  return {
1402
1541
  ...state,
1403
1542
  composerValue: session.title,
1543
+ inputSource: 'script',
1404
1544
  renamingSessionId: id,
1405
1545
  selectedSessionId: id
1406
1546
  };
1407
1547
  };
1408
- const deleteSession = (state, id) => {
1409
- const filtered = state.sessions.filter(session => session.id !== id);
1410
- if (filtered.length === state.sessions.length) {
1548
+
1549
+ const HEADER_HEIGHT = 40;
1550
+ const handleClickList = async (state, eventX, eventY) => {
1551
+ const {
1552
+ height,
1553
+ listItemHeight,
1554
+ sessions,
1555
+ width,
1556
+ x,
1557
+ y
1558
+ } = state;
1559
+ if (eventX < x || eventY < y) {
1411
1560
  return state;
1412
1561
  }
1413
- 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
- return {
1421
- ...state,
1422
- nextSessionId: state.nextSessionId + 1,
1423
- renamingSessionId: '',
1424
- selectedSessionId: fallbackId,
1425
- sessions: [fallback]
1426
- };
1562
+ if (eventX >= x + width || eventY >= y + height) {
1563
+ return state;
1427
1564
  }
1428
- return {
1429
- ...state,
1430
- renamingSessionId: state.renamingSessionId === id ? '' : state.renamingSessionId,
1431
- selectedSessionId: getNextSelectedSessionId(filtered, id),
1432
- sessions: filtered
1433
- };
1565
+ const listY = eventY - y - HEADER_HEIGHT;
1566
+ if (listY < 0) {
1567
+ return state;
1568
+ }
1569
+ const itemHeight = listItemHeight > 0 ? listItemHeight : 40;
1570
+ const index = Math.floor(listY / itemHeight);
1571
+ const session = sessions[index];
1572
+ if (!session) {
1573
+ return state;
1574
+ }
1575
+ return selectSession(state, session.id);
1434
1576
  };
1435
- const handleClick = async (state, name) => {
1577
+
1578
+ const CREATE_SESSION = 'create-session';
1579
+ const SESSION_PREFIX = 'session:';
1580
+ const RENAME_PREFIX = 'session-rename:';
1581
+ const SESSION_DELETE = 'SessionDelete';
1582
+ const SEND = 'send';
1583
+ const handleClick = async (state, name, id = '') => {
1436
1584
  if (!name) {
1437
1585
  return state;
1438
1586
  }
@@ -1447,8 +1595,7 @@ const handleClick = async (state, name) => {
1447
1595
  const id = name.slice(RENAME_PREFIX.length);
1448
1596
  return startRename(state, id);
1449
1597
  }
1450
- if (name.startsWith(DELETE_PREFIX)) {
1451
- const id = name.slice(DELETE_PREFIX.length);
1598
+ if (name === SESSION_DELETE) {
1452
1599
  return deleteSession(state, id);
1453
1600
  }
1454
1601
  if (name === SEND) {
@@ -1457,26 +1604,124 @@ const handleClick = async (state, name) => {
1457
1604
  return state;
1458
1605
  };
1459
1606
 
1607
+ const handleClickBack = async state => {
1608
+ return {
1609
+ ...state,
1610
+ renamingSessionId: '',
1611
+ viewMode: 'list'
1612
+ };
1613
+ };
1614
+
1460
1615
  const handleClickClose = async () => {
1461
1616
  // @ts-ignore
1462
- await invoke('Chat.terminate');
1617
+ await invoke('Layout.hideSecondarySideBar');
1618
+ };
1619
+
1620
+ const handleClickDelete = async (state, sessionId = '') => {
1621
+ return deleteSession(state, sessionId);
1622
+ };
1623
+
1624
+ const handleClickNew = async state => {
1625
+ return createSession(state);
1626
+ };
1627
+
1628
+ const handleClickSettings = async () => {
1629
+ // TODO
1630
+ };
1631
+
1632
+ const handleInput = async (state, value, inputSource = 'user') => {
1633
+ return {
1634
+ ...state,
1635
+ composerValue: value,
1636
+ inputSource
1637
+ };
1463
1638
  };
1464
1639
 
1465
- const handleClickSettings = async () => {};
1640
+ const handleInputFocus = async (state, name) => {
1641
+ if (name === 'composer') {
1642
+ return focusInput(state);
1643
+ }
1644
+ if (name === 'send') {
1645
+ return {
1646
+ ...state,
1647
+ focus: 'send-button',
1648
+ focused: true
1649
+ };
1650
+ }
1651
+ if (name.startsWith('session:') || name === 'SessionDelete') {
1652
+ return {
1653
+ ...state,
1654
+ focus: 'list',
1655
+ focused: true
1656
+ };
1657
+ }
1658
+ if (name === 'create-session' || name === 'settings' || name === 'close-chat' || name === 'back') {
1659
+ return {
1660
+ ...state,
1661
+ focus: 'header',
1662
+ focused: true
1663
+ };
1664
+ }
1665
+ return {
1666
+ ...state,
1667
+ focused: false
1668
+ };
1669
+ };
1466
1670
 
1467
- const handleInput = async (state, value) => {
1468
- if (state.ignoreNextInput) {
1671
+ const submitRename = state => {
1672
+ const {
1673
+ composerValue,
1674
+ renamingSessionId,
1675
+ sessions
1676
+ } = state;
1677
+ const title = composerValue.trim();
1678
+ if (!renamingSessionId || !title) {
1469
1679
  return {
1470
1680
  ...state,
1471
- ignoreNextInput: false
1681
+ renamingSessionId: ''
1472
1682
  };
1473
1683
  }
1684
+ const updatedSessions = sessions.map(session => {
1685
+ if (session.id !== renamingSessionId) {
1686
+ return session;
1687
+ }
1688
+ return {
1689
+ ...session,
1690
+ title
1691
+ };
1692
+ });
1474
1693
  return {
1475
1694
  ...state,
1476
- composerValue: value
1695
+ composerValue: '',
1696
+ inputSource: 'script',
1697
+ renamingSessionId: '',
1698
+ sessions: updatedSessions
1477
1699
  };
1478
1700
  };
1479
1701
 
1702
+ const handleKeyDown = async (state, key, shiftKey) => {
1703
+ const {
1704
+ composerValue,
1705
+ renamingSessionId,
1706
+ selectedSessionId,
1707
+ sessions,
1708
+ viewMode
1709
+ } = state;
1710
+ if (key !== 'Enter' || shiftKey) {
1711
+ return state;
1712
+ }
1713
+ if (renamingSessionId) {
1714
+ return submitRename(state);
1715
+ }
1716
+ const hasInput = composerValue.trim().length > 0;
1717
+ const hasSelectedSession = sessions.some(session => session.id === selectedSessionId);
1718
+ const submitState = viewMode === 'list' && hasInput && hasSelectedSession ? {
1719
+ ...state,
1720
+ viewMode: 'detail'
1721
+ } : state;
1722
+ return handleSubmit(submitState);
1723
+ };
1724
+
1480
1725
  const id = 7201;
1481
1726
  const sendMessagePortToExtensionHostWorker = async port => {
1482
1727
  await sendMessagePortToExtensionHostWorker$1(port, id);
@@ -1499,26 +1744,79 @@ const initialize = async () => {
1499
1744
  set$2(rpc);
1500
1745
  };
1501
1746
 
1502
- const ensureSessions = state => {
1503
- if (state.sessions.length > 0) {
1504
- return state.sessions;
1747
+ const isObject = value => {
1748
+ return typeof value === 'object' && value !== null;
1749
+ };
1750
+
1751
+ const getSavedBounds = savedState => {
1752
+ if (!isObject(savedState)) {
1753
+ return undefined;
1505
1754
  }
1506
- const id = `session-${state.nextSessionId}`;
1507
- return [{
1508
- id,
1509
- messages: [],
1510
- title: `Chat ${state.nextSessionId}`
1511
- }];
1755
+ const {
1756
+ height,
1757
+ width,
1758
+ x,
1759
+ y
1760
+ } = savedState;
1761
+ if (typeof x !== 'number') {
1762
+ return undefined;
1763
+ }
1764
+ if (typeof y !== 'number') {
1765
+ return undefined;
1766
+ }
1767
+ if (typeof width !== 'number') {
1768
+ return undefined;
1769
+ }
1770
+ if (typeof height !== 'number') {
1771
+ return undefined;
1772
+ }
1773
+ return {
1774
+ height,
1775
+ width,
1776
+ x,
1777
+ y
1778
+ };
1512
1779
  };
1513
- const loadContent = async state => {
1514
- const sessions = ensureSessions(state);
1515
- const selectedSessionId = sessions.some(session => session.id === state.selectedSessionId) ? state.selectedSessionId : sessions[0].id;
1780
+
1781
+ const getSavedSelectedSessionId = savedState => {
1782
+ if (!isObject(savedState)) {
1783
+ return undefined;
1784
+ }
1785
+ const {
1786
+ selectedSessionId
1787
+ } = savedState;
1788
+ if (typeof selectedSessionId !== 'string') {
1789
+ return undefined;
1790
+ }
1791
+ return selectedSessionId;
1792
+ };
1793
+
1794
+ const getSavedSessions = savedState => {
1795
+ if (!isObject(savedState)) {
1796
+ return undefined;
1797
+ }
1798
+ const {
1799
+ sessions
1800
+ } = savedState;
1801
+ if (!Array.isArray(sessions)) {
1802
+ return undefined;
1803
+ }
1804
+ return sessions;
1805
+ };
1806
+
1807
+ const loadContent = async (state, savedState) => {
1808
+ const savedBounds = getSavedBounds(savedState);
1809
+ const sessions = getSavedSessions(savedState) || state.sessions;
1810
+ const preferredSessionId = getSavedSelectedSessionId(savedState) || state.selectedSessionId;
1811
+ const selectedSessionId = sessions.some(session => session.id === preferredSessionId) ? preferredSessionId : sessions[0]?.id || '';
1812
+ const viewMode = sessions.length === 0 ? 'list' : state.viewMode === 'detail' ? 'detail' : 'list';
1516
1813
  return {
1517
1814
  ...state,
1815
+ ...savedBounds,
1518
1816
  initial: false,
1519
- nextSessionId: state.sessions.length === 0 ? state.nextSessionId + 1 : state.nextSessionId,
1520
1817
  selectedSessionId,
1521
- sessions
1818
+ sessions,
1819
+ viewMode
1522
1820
  };
1523
1821
  };
1524
1822
 
@@ -1530,6 +1828,30 @@ const renderCss = (oldState, newState) => {
1530
1828
  return [SetCss, newState.uid, css];
1531
1829
  };
1532
1830
 
1831
+ const getFocusSelector = focus => {
1832
+ switch (focus) {
1833
+ case 'composer':
1834
+ case 'input':
1835
+ return '[name="composer"]';
1836
+ case 'header':
1837
+ return '[name="create-session"]';
1838
+ case 'list':
1839
+ return '[name^="session:"]';
1840
+ case 'send-button':
1841
+ return '[name="send"]';
1842
+ default:
1843
+ return '[name="composer"]';
1844
+ }
1845
+ };
1846
+ const renderFocus = (oldState, newState) => {
1847
+ const selector = getFocusSelector(newState.focus);
1848
+ return [FocusSelector, selector];
1849
+ };
1850
+
1851
+ const mergeClassNames = (...classNames) => {
1852
+ return classNames.filter(Boolean).join(' ');
1853
+ };
1854
+
1533
1855
  const text = data => {
1534
1856
  return {
1535
1857
  childCount: 0,
@@ -1827,168 +2149,261 @@ const diffTree = (oldNodes, newNodes) => {
1827
2149
  };
1828
2150
 
1829
2151
  const ChatActions = 'ChatActions';
2152
+ const ChatName = 'ChatName';
2153
+ const ChatSendArea = 'ChatSendArea';
2154
+ const Chat = 'Chat';
1830
2155
  const ChatHeader = 'ChatHeader';
1831
2156
  const Button = 'Button';
1832
- const ChatDetails = 'ChatDetails';
1833
- const ChatDetailsContent = 'ChatDetailsContent';
2157
+ const ButtonDisabled = 'ButtonDisabled';
2158
+ const ButtonPrimary = 'ButtonPrimary';
1834
2159
  const IconButton = 'IconButton';
1835
2160
  const Label = 'Label';
1836
2161
  const ChatList = 'ChatList';
2162
+ const ChatListItem = 'ChatListItem';
2163
+ const ChatListItemLabel = 'ChatListItemLabel';
1837
2164
  const Markdown = 'Markdown';
1838
2165
  const Message = 'Message';
1839
2166
  const MultilineInputBox = 'MultilineInputBox';
1840
2167
  const Viewlet = 'Viewlet';
1841
2168
  const ChatWelcomeMessage = 'ChatWelcomeMessage';
1842
2169
 
2170
+ const HandleContextMenu = 2;
2171
+ const HandleFocus = 3;
1843
2172
  const HandleInput = 4;
1844
2173
  const HandleClick = 11;
1845
2174
  const HandleKeyDown = 12;
1846
2175
  const HandleClickClose = 13;
1847
2176
  const HandleClickSettings = 14;
1848
-
1849
- const getMessagesDom = messages => {
1850
- if (messages.length === 0) {
1851
- return [{
1852
- childCount: 1,
1853
- className: ChatWelcomeMessage,
1854
- type: Div
1855
- }, text('Start a conversation by typing below.')];
1856
- }
1857
- return messages.flatMap(message => {
1858
- 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
- childCount: 1,
1868
- className: Markdown,
1869
- type: P
1870
- }, text(message.text)];
1871
- });
1872
- };
1873
-
1874
- const getSessionDom = (session, _selectedSessionId) => {
1875
- const sessionClassName = ChatList;
2177
+ const HandleClickNew = 15;
2178
+ const HandleClickBack = 16;
2179
+ const HandleClickList = 17;
2180
+ const HandleClickDelete = 18;
2181
+ const HandleSubmit = 19;
2182
+
2183
+ const getChatSendAreaDom = composerValue => {
2184
+ const isSendDisabled = composerValue.trim() === '';
2185
+ const sendButtonClassName = isSendDisabled ? `${Button} ${ButtonPrimary} ${ButtonDisabled}` : `${Button} ${ButtonPrimary}`;
1876
2186
  return [{
1877
2187
  childCount: 2,
1878
- className: sessionClassName,
2188
+ className: ChatSendArea,
1879
2189
  type: Div
2190
+ }, {
2191
+ childCount: 0,
2192
+ className: MultilineInputBox,
2193
+ name: 'composer',
2194
+ onInput: HandleInput,
2195
+ placeholder: composePlaceholder,
2196
+ rows: 4,
2197
+ type: TextArea,
2198
+ value: composerValue
1880
2199
  }, {
1881
2200
  childCount: 1,
1882
- className: Button,
1883
- name: `session:${session.id}`,
2201
+ className: sendButtonClassName,
2202
+ disabled: isSendDisabled,
2203
+ name: 'send',
2204
+ onClick: HandleSubmit,
1884
2205
  role: Button$2,
1885
- tabIndex: 0,
2206
+ title: sendMessage,
1886
2207
  type: Button$1
1887
- }, text(session.title), {
1888
- childCount: 2,
1889
- className: ChatActions,
1890
- type: Div
1891
- }, {
2208
+ }, text(send)];
2209
+ };
2210
+
2211
+ const getHeaderActionVirtualDom = item => {
2212
+ return [{
1892
2213
  childCount: 1,
1893
2214
  className: IconButton,
1894
- name: `session-rename:${session.id}`,
2215
+ name: item.name,
2216
+ onClick: item.onClick,
1895
2217
  role: Button$2,
1896
- tabIndex: 0,
1897
- title: 'Rename chat session',
2218
+ title: item.title,
1898
2219
  type: Button$1
1899
- }, text('Rename'), {
2220
+ }, text(item.icon)];
2221
+ };
2222
+
2223
+ const getChatHeaderActionsDom = () => {
2224
+ const items = [{
2225
+ icon: '+',
2226
+ name: 'create-session',
2227
+ onClick: HandleClickNew,
2228
+ title: newChat
2229
+ }, {
2230
+ icon: '⚙',
2231
+ name: 'settings',
2232
+ onClick: HandleClickSettings,
2233
+ title: settings
2234
+ }, {
2235
+ icon: '×',
2236
+ name: 'close-chat',
2237
+ onClick: HandleClickClose,
2238
+ title: closeChat
2239
+ }];
2240
+ return [{
2241
+ childCount: items.length,
2242
+ className: ChatActions,
2243
+ type: Div
2244
+ }, ...items.flatMap(getHeaderActionVirtualDom)];
2245
+ };
2246
+
2247
+ const getChatHeaderBackButtonVirtualDom = () => {
2248
+ return [{
1900
2249
  childCount: 1,
1901
2250
  className: IconButton,
1902
- name: `session-delete:${session.id}`,
2251
+ name: 'back',
2252
+ onClick: HandleClickBack,
1903
2253
  role: Button$2,
1904
- tabIndex: 0,
1905
- title: 'Delete chat session',
2254
+ title: backToChats,
1906
2255
  type: Button$1
1907
- }, text('Delete')];
2256
+ }, text('')];
2257
+ };
2258
+
2259
+ const getChatHeaderDomDetailMode = selectedSessionTitle => {
2260
+ return [{
2261
+ childCount: 2,
2262
+ className: ChatHeader,
2263
+ type: Div
2264
+ }, {
2265
+ childCount: 2,
2266
+ className: ChatName,
2267
+ type: Div
2268
+ }, ...getChatHeaderBackButtonVirtualDom(), {
2269
+ childCount: 1,
2270
+ className: Label,
2271
+ type: Span
2272
+ }, text(selectedSessionTitle), ...getChatHeaderActionsDom()];
2273
+ };
2274
+
2275
+ const getChatMessageDom = message => {
2276
+ return [{
2277
+ childCount: 2,
2278
+ className: Message,
2279
+ type: Div
2280
+ }, {
2281
+ childCount: 1,
2282
+ className: Label,
2283
+ type: Div
2284
+ }, text(`${message.role === 'user' ? you : assistant} · ${message.time}`), {
2285
+ childCount: 1,
2286
+ className: Markdown,
2287
+ type: P
2288
+ }, text(message.text)];
1908
2289
  };
1909
2290
 
1910
- const getChatVirtualDom = (sessions, selectedSessionId, composerValue) => {
2291
+ const getMessagesDom = messages => {
2292
+ if (messages.length === 0) {
2293
+ return [{
2294
+ childCount: 1,
2295
+ className: ChatWelcomeMessage,
2296
+ type: Div
2297
+ }, text(startConversation)];
2298
+ }
2299
+ return [{
2300
+ childCount: messages.length,
2301
+ className: 'ChatMessages',
2302
+ type: Div
2303
+ }, ...messages.flatMap(getChatMessageDom)];
2304
+ };
2305
+
2306
+ const getChatModeDetailVirtualDom = (sessions, selectedSessionId, composerValue) => {
1911
2307
  const selectedSession = sessions.find(session => session.id === selectedSessionId);
2308
+ const selectedSessionTitle = selectedSession?.title || chatTitle;
1912
2309
  const messages = selectedSession ? selectedSession.messages : [];
1913
- const sessionNodes = sessions.flatMap(session => getSessionDom(session));
1914
- const messagesNodes = getMessagesDom(messages);
1915
- const dom = [{
2310
+ return [{
1916
2311
  childCount: 3,
1917
- className: Viewlet + ' Chat',
1918
- onClick: HandleClick,
1919
- onInput: HandleInput,
1920
- onKeyDown: HandleKeyDown,
2312
+ className: mergeClassNames(Viewlet, Chat),
1921
2313
  type: Div
1922
- }, {
2314
+ }, ...getChatHeaderDomDetailMode(selectedSessionTitle), ...getMessagesDom(messages), ...getChatSendAreaDom(composerValue)];
2315
+ };
2316
+
2317
+ const getChatHeaderListModeDom = () => {
2318
+ return [{
1923
2319
  childCount: 2,
1924
2320
  className: ChatHeader,
1925
2321
  type: Div
1926
- }, {
1927
- childCount: 4,
1928
- className: ChatActions,
1929
- type: Div
1930
2322
  }, {
1931
2323
  childCount: 1,
1932
2324
  className: Label,
1933
2325
  type: Span
1934
- }, text('Chats'), {
1935
- childCount: 1,
1936
- className: IconButton,
1937
- name: 'create-session',
1938
- role: Button$2,
1939
- tabIndex: 0,
1940
- title: 'New Chat',
1941
- type: Button$1
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('⚙'), {
2326
+ }, text(chats), ...getChatHeaderActionsDom()];
2327
+ };
2328
+
2329
+ const getEmptyChatSessionsDom = () => {
2330
+ return [{
1951
2331
  childCount: 1,
1952
- className: IconButton,
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
2332
  className: ChatList,
1961
2333
  type: Div
1962
- }, ...sessionNodes, {
2334
+ }, {
2335
+ childCount: 1,
2336
+ className: Label,
2337
+ type: Div
2338
+ }, text(clickToOpenNewChat)];
2339
+ };
2340
+
2341
+ const getSessionDom = session => {
2342
+ const sessionClassName = ChatListItem;
2343
+ return [{
1963
2344
  childCount: 2,
1964
- className: ChatDetails,
2345
+ className: sessionClassName,
1965
2346
  type: Div
1966
2347
  }, {
1967
- childCount: Math.max(messagesNodes.length, 0),
1968
- className: ChatDetailsContent,
2348
+ childCount: 1,
2349
+ className: ChatListItemLabel,
2350
+ name: `session:${session.id}`,
2351
+ onContextMenu: HandleContextMenu,
2352
+ tabIndex: 0,
1969
2353
  type: Div
1970
- }, ...messagesNodes, {
1971
- childCount: 2,
2354
+ }, text(session.title), {
2355
+ childCount: 1,
1972
2356
  className: ChatActions,
1973
2357
  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
2358
  }, {
1983
2359
  childCount: 1,
1984
- className: Button,
1985
- name: 'send',
2360
+ className: IconButton,
2361
+ 'data-id': session.id,
2362
+ name: 'SessionDelete',
2363
+ onClick: HandleClickDelete,
1986
2364
  role: Button$2,
1987
2365
  tabIndex: 0,
1988
- title: 'Send message',
2366
+ title: deleteChatSession,
1989
2367
  type: Button$1
1990
- }, text('Send')];
1991
- return dom;
2368
+ }, text('🗑')];
2369
+ };
2370
+
2371
+ const getChatListDom = (sessions, selectedSessionId) => {
2372
+ if (sessions.length === 0) {
2373
+ return getEmptyChatSessionsDom();
2374
+ }
2375
+ return [{
2376
+ childCount: sessions.length,
2377
+ className: ChatList,
2378
+ onClick: HandleClickList,
2379
+ type: Div
2380
+ }, ...sessions.flatMap(getSessionDom)];
2381
+ };
2382
+
2383
+ const getChatModeListVirtualDom = (sessions, selectedSessionId, composerValue) => {
2384
+ return [{
2385
+ childCount: 3,
2386
+ className: mergeClassNames(Viewlet, Chat),
2387
+ type: Div
2388
+ }, ...getChatHeaderListModeDom(), ...getChatListDom(sessions), ...getChatSendAreaDom(composerValue)];
2389
+ };
2390
+
2391
+ const getChatModeUnsupportedVirtualDom = () => {
2392
+ return [{
2393
+ childCount: 1,
2394
+ type: Div
2395
+ }, text('Unknown view mode')];
2396
+ };
2397
+
2398
+ const getChatVirtualDom = (sessions, selectedSessionId, composerValue, viewMode) => {
2399
+ switch (viewMode) {
2400
+ case 'detail':
2401
+ return getChatModeDetailVirtualDom(sessions, selectedSessionId, composerValue);
2402
+ case 'list':
2403
+ return getChatModeListVirtualDom(sessions, selectedSessionId, composerValue);
2404
+ default:
2405
+ return getChatModeUnsupportedVirtualDom();
2406
+ }
1992
2407
  };
1993
2408
 
1994
2409
  const renderItems = (oldState, newState) => {
@@ -1997,12 +2412,13 @@ const renderItems = (oldState, newState) => {
1997
2412
  initial,
1998
2413
  selectedSessionId,
1999
2414
  sessions,
2000
- uid
2415
+ uid,
2416
+ viewMode
2001
2417
  } = newState;
2002
2418
  if (initial) {
2003
2419
  return [SetDom2, uid, []];
2004
2420
  }
2005
- const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue);
2421
+ const dom = getChatVirtualDom(sessions, selectedSessionId, composerValue, viewMode);
2006
2422
  return [SetDom2, uid, dom];
2007
2423
  };
2008
2424
 
@@ -2013,14 +2429,25 @@ const renderIncremental = (oldState, newState) => {
2013
2429
  return [SetPatches, newState.uid, patches];
2014
2430
  };
2015
2431
 
2432
+ const renderValue = (oldState, newState) => {
2433
+ const {
2434
+ composerValue
2435
+ } = newState;
2436
+ return [SetValueByName, newState.uid, 'composer', composerValue];
2437
+ };
2438
+
2016
2439
  const getRenderer = diffType => {
2017
2440
  switch (diffType) {
2018
2441
  case RenderCss:
2019
2442
  return renderCss;
2443
+ case RenderFocus:
2444
+ return renderFocus;
2020
2445
  case RenderIncremental:
2021
2446
  return renderIncremental;
2022
2447
  case RenderItems:
2023
2448
  return renderItems;
2449
+ case RenderValue:
2450
+ return renderValue;
2024
2451
  default:
2025
2452
  throw new Error('unknown renderer');
2026
2453
  }
@@ -2050,23 +2477,55 @@ const render2 = (uid, diffResult) => {
2050
2477
 
2051
2478
  const renderEventListeners = () => {
2052
2479
  return [{
2480
+ name: HandleContextMenu,
2481
+ params: ['handleChatListContextMenu', TargetName, ClientX, ClientY],
2482
+ preventDefault: true
2483
+ }, {
2053
2484
  name: HandleClick,
2054
- params: ['handleClick', TargetName]
2485
+ params: ['handleClick', TargetName, 'event.target.dataset.id']
2486
+ }, {
2487
+ name: HandleClickDelete,
2488
+ params: ['handleClickDelete', 'event.target.dataset.id']
2055
2489
  }, {
2056
2490
  name: HandleClickClose,
2057
2491
  params: ['handleClickClose']
2058
2492
  }, {
2059
2493
  name: HandleClickSettings,
2060
2494
  params: ['handleClickSettings']
2495
+ }, {
2496
+ name: HandleClickNew,
2497
+ params: ['handleClickNew']
2498
+ }, {
2499
+ name: HandleClickBack,
2500
+ params: ['handleClickBack']
2501
+ }, {
2502
+ name: HandleClickList,
2503
+ params: ['handleClickList', ClientX, ClientY]
2061
2504
  }, {
2062
2505
  name: HandleInput,
2063
2506
  params: ['handleInput', TargetValue]
2507
+ }, {
2508
+ name: HandleFocus,
2509
+ params: ['handleInputFocus', TargetName]
2064
2510
  }, {
2065
2511
  name: HandleKeyDown,
2066
2512
  params: ['handleKeyDown', Key, ShiftKey]
2513
+ }, {
2514
+ name: HandleSubmit,
2515
+ params: ['handleSubmit']
2067
2516
  }];
2068
2517
  };
2069
2518
 
2519
+ const reset = async state => {
2520
+ return {
2521
+ ...state,
2522
+ composerValue: '',
2523
+ selectedSessionId: '',
2524
+ sessions: [],
2525
+ viewMode: 'list'
2526
+ };
2527
+ };
2528
+
2070
2529
  const resize = (state, dimensions) => {
2071
2530
  return {
2072
2531
  ...state,
@@ -2077,59 +2536,76 @@ const resize = (state, dimensions) => {
2077
2536
  const saveState = state => {
2078
2537
  const {
2079
2538
  composerValue,
2539
+ height,
2080
2540
  nextMessageId,
2081
- nextSessionId,
2082
2541
  renamingSessionId,
2083
2542
  selectedSessionId,
2084
- sessions
2543
+ sessions,
2544
+ viewMode,
2545
+ width,
2546
+ x,
2547
+ y
2085
2548
  } = state;
2086
2549
  return {
2087
2550
  composerValue,
2551
+ height,
2088
2552
  nextMessageId,
2089
- nextSessionId,
2090
2553
  renamingSessionId,
2091
2554
  selectedSessionId,
2092
- sessions
2555
+ sessions,
2556
+ viewMode,
2557
+ width,
2558
+ x,
2559
+ y
2093
2560
  };
2094
2561
  };
2095
2562
 
2096
2563
  const dummySessions = [{
2097
2564
  id: 'session-a',
2098
2565
  messages: [],
2099
- title: 'Dummy Chat A'
2566
+ title: dummyChatA
2100
2567
  }, {
2101
2568
  id: 'session-b',
2102
2569
  messages: [],
2103
- title: 'Dummy Chat B'
2570
+ title: dummyChatB
2104
2571
  }, {
2105
2572
  id: 'session-c',
2106
2573
  messages: [],
2107
- title: 'Dummy Chat C'
2574
+ title: dummyChatC
2108
2575
  }];
2109
2576
  const setChatList = state => {
2110
2577
  return {
2111
2578
  ...state,
2112
- nextSessionId: dummySessions.length + 1,
2113
2579
  selectedSessionId: dummySessions[0].id,
2114
- sessions: dummySessions
2580
+ sessions: dummySessions,
2581
+ viewMode: 'detail'
2115
2582
  };
2116
2583
  };
2117
2584
 
2118
2585
  const commandMap = {
2586
+ 'Chat.clearInput': wrapCommand(clearInput),
2119
2587
  'Chat.create': create,
2120
2588
  'Chat.diff2': diff2,
2121
2589
  'Chat.getCommandIds': getCommandIds,
2122
2590
  'Chat.getKeyBindings': getKeyBindings,
2591
+ 'Chat.handleChatListContextMenu': handleChatListContextMenu,
2123
2592
  'Chat.handleClick': wrapCommand(handleClick),
2593
+ 'Chat.handleClickBack': wrapCommand(handleClickBack),
2124
2594
  'Chat.handleClickClose': handleClickClose,
2595
+ 'Chat.handleClickDelete': wrapCommand(handleClickDelete),
2596
+ 'Chat.handleClickList': wrapCommand(handleClickList),
2597
+ 'Chat.handleClickNew': wrapCommand(handleClickNew),
2125
2598
  'Chat.handleClickSettings': handleClickSettings,
2126
2599
  'Chat.handleInput': wrapCommand(handleInput),
2600
+ 'Chat.handleInputFocus': wrapCommand(handleInputFocus),
2127
2601
  'Chat.handleKeyDown': wrapCommand(handleKeyDown),
2602
+ 'Chat.handleSubmit': wrapCommand(handleSubmit),
2128
2603
  'Chat.initialize': initialize,
2129
2604
  'Chat.loadContent': wrapCommand(loadContent),
2130
2605
  'Chat.loadContent2': wrapCommand(loadContent),
2131
2606
  'Chat.render2': render2,
2132
2607
  'Chat.renderEventListeners': renderEventListeners,
2608
+ 'Chat.reset': wrapCommand(reset),
2133
2609
  'Chat.resize': wrapCommand(resize),
2134
2610
  'Chat.saveState': wrapGetter(saveState),
2135
2611
  'Chat.setChatList': wrapCommand(setChatList),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "1.4.0",
3
+ "version": "1.6.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
  }