@lvce-editor/chat-view 1.0.0 → 1.2.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.
@@ -486,7 +486,7 @@ const execute = (command, ...args) => {
486
486
 
487
487
  const Two$1 = '2.0';
488
488
  const callbacks = Object.create(null);
489
- const get$3 = id => {
489
+ const get$2 = id => {
490
490
  return callbacks[id];
491
491
  };
492
492
  const remove$1 = id => {
@@ -635,7 +635,7 @@ const warn = (...args) => {
635
635
  console.warn(...args);
636
636
  };
637
637
  const resolve = (id, response) => {
638
- const fn = get$3(id);
638
+ const fn = get$2(id);
639
639
  if (!fn) {
640
640
  console.log(response);
641
641
  warn(`callback ${id} may already be disposed`);
@@ -964,18 +964,21 @@ const create$3 = async ({
964
964
  return rpc;
965
965
  };
966
966
 
967
- const Button$1 = 'button';
968
- const Status = 'status';
969
-
970
- const MaskIcon = 'MaskIcon';
967
+ const Button$2 = 'button';
971
968
 
972
- const Button = 1;
969
+ const Button$1 = 1;
973
970
  const Div = 4;
974
971
  const Span = 8;
975
972
  const Text = 12;
973
+ const P = 50;
974
+ const TextArea = 62;
975
+ const Strong = 70;
976
976
  const Reference = 100;
977
977
 
978
+ const Key = 'event.key';
979
+ const ShiftKey = 'event.shiftKey';
978
980
  const TargetName = 'event.target.name';
981
+ const TargetValue = 'event.target.value';
979
982
 
980
983
  const ExtensionHostWorker = 44;
981
984
  const RendererWorker = 1;
@@ -1007,7 +1010,7 @@ const rpcs = Object.create(null);
1007
1010
  const set$3 = (id, rpc) => {
1008
1011
  rpcs[id] = rpc;
1009
1012
  };
1010
- const get$2 = id => {
1013
+ const get$1 = id => {
1011
1014
  return rpcs[id];
1012
1015
  };
1013
1016
  const remove = id => {
@@ -1018,18 +1021,18 @@ const remove = id => {
1018
1021
  const create$2 = rpcId => {
1019
1022
  return {
1020
1023
  async dispose() {
1021
- const rpc = get$2(rpcId);
1024
+ const rpc = get$1(rpcId);
1022
1025
  await rpc.dispose();
1023
1026
  },
1024
1027
  // @ts-ignore
1025
1028
  invoke(method, ...params) {
1026
- const rpc = get$2(rpcId);
1029
+ const rpc = get$1(rpcId);
1027
1030
  // @ts-ignore
1028
1031
  return rpc.invoke(method, ...params);
1029
1032
  },
1030
1033
  // @ts-ignore
1031
1034
  invokeAndTransfer(method, ...params) {
1032
- const rpc = get$2(rpcId);
1035
+ const rpc = get$1(rpcId);
1033
1036
  // @ts-ignore
1034
1037
  return rpc.invokeAndTransfer(method, ...params);
1035
1038
  },
@@ -1052,12 +1055,10 @@ const create$2 = rpcId => {
1052
1055
  };
1053
1056
 
1054
1057
  const {
1055
- invoke: invoke$1,
1056
1058
  set: set$2
1057
1059
  } = create$2(ExtensionHostWorker);
1058
1060
 
1059
1061
  const {
1060
- invoke,
1061
1062
  invokeAndTransfer,
1062
1063
  set: set$1
1063
1064
  } = create$2(RendererWorker);
@@ -1065,12 +1066,6 @@ const sendMessagePortToExtensionHostWorker$1 = async (port, rpcId = 0) => {
1065
1066
  const command = 'HandleMessagePort.handleMessagePort2';
1066
1067
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, rpcId);
1067
1068
  };
1068
- const activateByEvent$1 = (event, assetDir, platform) => {
1069
- return invoke('ExtensionHostManagement.activateByEvent', event, assetDir, platform);
1070
- };
1071
- const getPreference = async key => {
1072
- return await invoke('Preferences.get', key);
1073
- };
1074
1069
 
1075
1070
  const toCommandId = key => {
1076
1071
  const dotIndex = key.indexOf('.');
@@ -1192,8 +1187,32 @@ const terminate = () => {
1192
1187
  globalThis.close();
1193
1188
  };
1194
1189
 
1190
+ const createDefaultState = () => {
1191
+ const defaultSessionId = 'session-1';
1192
+ return {
1193
+ assetDir: '',
1194
+ composerValue: '',
1195
+ errorCount: 0,
1196
+ ignoreNextInput: false,
1197
+ initial: true,
1198
+ lastSubmittedSessionId: '',
1199
+ nextMessageId: 1,
1200
+ nextSessionId: 2,
1201
+ platform: 0,
1202
+ renamingSessionId: '',
1203
+ selectedSessionId: defaultSessionId,
1204
+ sessions: [{
1205
+ id: defaultSessionId,
1206
+ messages: [],
1207
+ title: 'Chat 1'
1208
+ }],
1209
+ uid: 0,
1210
+ warningCount: 0
1211
+ };
1212
+ };
1213
+
1195
1214
  const {
1196
- get: get$1,
1215
+ get,
1197
1216
  getCommandIds,
1198
1217
  registerCommands,
1199
1218
  set,
@@ -1203,20 +1222,16 @@ const {
1203
1222
 
1204
1223
  const create = (uid, uri, x, y, width, height, platform, assetDir) => {
1205
1224
  const state = {
1225
+ ...createDefaultState(),
1206
1226
  assetDir,
1207
- errorCount: 0,
1208
- initial: true,
1209
1227
  platform,
1210
- statusBarItemsLeft: [],
1211
- statusBarItemsRight: [],
1212
- uid,
1213
- warningCount: 0
1228
+ uid
1214
1229
  };
1215
1230
  set(uid, state, state);
1216
1231
  };
1217
1232
 
1218
1233
  const isEqual = (oldState, newState) => {
1219
- return oldState.statusBarItemsLeft === newState.statusBarItemsLeft && oldState.statusBarItemsRight === newState.statusBarItemsRight;
1234
+ 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;
1220
1235
  };
1221
1236
 
1222
1237
  const RenderItems = 4;
@@ -1240,325 +1255,252 @@ const diff2 = uid => {
1240
1255
  const {
1241
1256
  newState,
1242
1257
  oldState
1243
- } = get$1(uid);
1258
+ } = get(uid);
1244
1259
  const result = diff(oldState, newState);
1245
1260
  return result;
1246
1261
  };
1247
1262
 
1248
- const getMatchingItem = (itemsLeft, itemsRight, name) => {
1249
- for (const item of itemsLeft) {
1250
- if (item.name === name) {
1251
- return item;
1252
- }
1263
+ const getKeyBindings = () => {
1264
+ return [];
1265
+ };
1266
+
1267
+ const CREATE_SESSION = 'create-session';
1268
+ const SESSION_PREFIX = 'session:';
1269
+ const RENAME_PREFIX = 'session-rename:';
1270
+ const DELETE_PREFIX = 'session-delete:';
1271
+ const getNextSelectedSessionId = (sessions, deletedId) => {
1272
+ if (sessions.length === 0) {
1273
+ return '';
1253
1274
  }
1254
- for (const item of itemsRight) {
1255
- if (item.name === name) {
1256
- return item;
1257
- }
1275
+ const index = sessions.findIndex(session => session.id === deletedId);
1276
+ if (index === -1) {
1277
+ return sessions[0].id;
1258
1278
  }
1259
- return undefined;
1279
+ const nextIndex = Math.min(index, sessions.length - 1);
1280
+ return sessions[nextIndex].id;
1260
1281
  };
1261
-
1262
- const handleClickExtensionStatusBarItem = async name => {
1263
- // @ts-ignore
1264
- await invoke$1(`ExtensionHostStatusBar.executeCommand`, name);
1282
+ const createSession = state => {
1283
+ const id = `session-${state.nextSessionId}`;
1284
+ const session = {
1285
+ id,
1286
+ messages: [],
1287
+ title: `Chat ${state.nextSessionId}`
1288
+ };
1289
+ return {
1290
+ ...state,
1291
+ nextSessionId: state.nextSessionId + 1,
1292
+ renamingSessionId: '',
1293
+ selectedSessionId: id,
1294
+ sessions: [...state.sessions, session]
1295
+ };
1265
1296
  };
1266
-
1267
- const handleClickNotification = async () => {
1268
- // TODO toggle notifications
1297
+ const selectSession = (state, id) => {
1298
+ const exists = state.sessions.some(session => session.id === id);
1299
+ if (!exists) {
1300
+ return state;
1301
+ }
1302
+ return {
1303
+ ...state,
1304
+ renamingSessionId: '',
1305
+ selectedSessionId: id
1306
+ };
1269
1307
  };
1270
-
1271
- const handleClickProblems = async () => {
1272
- // @ts-ignore
1273
- await invoke('Layout.showPanel');
1274
- // @ts-ignore
1275
- await invoke('Panel.toggleView', 'Problems');
1308
+ const startRename = (state, id) => {
1309
+ const session = state.sessions.find(item => item.id === id);
1310
+ if (!session) {
1311
+ return state;
1312
+ }
1313
+ return {
1314
+ ...state,
1315
+ composerValue: session.title,
1316
+ renamingSessionId: id,
1317
+ selectedSessionId: id
1318
+ };
1319
+ };
1320
+ const deleteSession = (state, id) => {
1321
+ const filtered = state.sessions.filter(session => session.id !== id);
1322
+ if (filtered.length === state.sessions.length) {
1323
+ return state;
1324
+ }
1325
+ if (filtered.length === 0) {
1326
+ const fallbackId = `session-${state.nextSessionId}`;
1327
+ const fallback = {
1328
+ id: fallbackId,
1329
+ messages: [],
1330
+ title: `Chat ${state.nextSessionId}`
1331
+ };
1332
+ return {
1333
+ ...state,
1334
+ nextSessionId: state.nextSessionId + 1,
1335
+ renamingSessionId: '',
1336
+ selectedSessionId: fallbackId,
1337
+ sessions: [fallback]
1338
+ };
1339
+ }
1340
+ return {
1341
+ ...state,
1342
+ renamingSessionId: state.renamingSessionId === id ? '' : state.renamingSessionId,
1343
+ selectedSessionId: getNextSelectedSessionId(filtered, id),
1344
+ sessions: filtered
1345
+ };
1276
1346
  };
1277
-
1278
- const Notifications = 'Notifications';
1279
- const Problems = 'Problems';
1280
-
1281
1347
  const handleClick = async (state, name) => {
1282
1348
  if (!name) {
1283
1349
  return state;
1284
1350
  }
1285
- const {
1286
- statusBarItemsLeft,
1287
- statusBarItemsRight
1288
- } = state;
1289
- const item = getMatchingItem(statusBarItemsLeft, statusBarItemsRight, name);
1290
- if (!item) {
1291
- return state;
1351
+ if (name === CREATE_SESSION) {
1352
+ return createSession(state);
1292
1353
  }
1293
- if (item.name === Notifications) {
1294
- await handleClickNotification();
1295
- } else if (item.name === Problems) {
1296
- await handleClickProblems();
1297
- } else {
1298
- await handleClickExtensionStatusBarItem(name);
1354
+ if (name.startsWith(SESSION_PREFIX)) {
1355
+ const id = name.slice(SESSION_PREFIX.length);
1356
+ return selectSession(state, id);
1299
1357
  }
1300
- // TODO
1301
- // sendExtensionWorker([/* statusBarItemHandleClick */ 7657, /* name */ name])
1302
- return state;
1303
- };
1304
-
1305
- const id = 7201;
1306
- const sendMessagePortToExtensionHostWorker = async port => {
1307
- await sendMessagePortToExtensionHostWorker$1(port, id);
1308
- };
1309
-
1310
- const createExtensionHostRpc = async () => {
1311
- try {
1312
- const rpc = await create$4({
1313
- commandMap: {},
1314
- send: sendMessagePortToExtensionHostWorker
1315
- });
1316
- return rpc;
1317
- } catch (error) {
1318
- throw new VError(error, `Failed to create extension host rpc`);
1358
+ if (name.startsWith(RENAME_PREFIX)) {
1359
+ const id = name.slice(RENAME_PREFIX.length);
1360
+ return startRename(state, id);
1319
1361
  }
1320
- };
1321
-
1322
- const initialize = async () => {
1323
- const rpc = await createExtensionHostRpc();
1324
- set$2(rpc);
1325
- };
1326
-
1327
- const getIndex = (items, item) => {
1328
- for (let i = 0; i < items.length; i++) {
1329
- if (items[i].name === item.name) {
1330
- return i;
1331
- }
1362
+ if (name.startsWith(DELETE_PREFIX)) {
1363
+ const id = name.slice(DELETE_PREFIX.length);
1364
+ return deleteSession(state, id);
1332
1365
  }
1333
- return -1;
1334
- };
1335
-
1336
- const updateArray = (items, newItem) => {
1337
- const index = getIndex(items, newItem);
1338
- const before = items.slice(0, index);
1339
- const after = items.slice(index + 1);
1340
- return [...before, newItem, ...after];
1366
+ return state;
1341
1367
  };
1342
1368
 
1343
- const itemLeftUpdate = (state, newItem) => {
1369
+ const handleInput = async (state, value) => {
1370
+ if (state.ignoreNextInput) {
1371
+ return {
1372
+ ...state,
1373
+ ignoreNextInput: false
1374
+ };
1375
+ }
1344
1376
  return {
1345
1377
  ...state,
1346
- statusBarItemsLeft: updateArray([...state.statusBarItemsLeft], newItem)
1378
+ composerValue: value
1347
1379
  };
1348
1380
  };
1349
1381
 
1350
- const itemRightCreate = (state, newItem) => {
1382
+ const submitRename = state => {
1351
1383
  const {
1352
- statusBarItemsRight
1384
+ composerValue,
1385
+ renamingSessionId,
1386
+ sessions
1353
1387
  } = state;
1354
- const newStatusBarItemsRight = [...statusBarItemsRight, newItem];
1388
+ const title = composerValue.trim();
1389
+ if (!renamingSessionId || !title) {
1390
+ return {
1391
+ ...state,
1392
+ renamingSessionId: ''
1393
+ };
1394
+ }
1395
+ const updatedSessions = sessions.map(session => {
1396
+ if (session.id !== renamingSessionId) {
1397
+ return session;
1398
+ }
1399
+ return {
1400
+ ...session,
1401
+ title
1402
+ };
1403
+ });
1355
1404
  return {
1356
1405
  ...state,
1357
- statusBarItemsRight: newStatusBarItemsRight
1406
+ composerValue: '',
1407
+ ignoreNextInput: true,
1408
+ renamingSessionId: '',
1409
+ sessions: updatedSessions
1358
1410
  };
1359
1411
  };
1360
-
1361
- const itemRightUpdate = (state, newItem) => {
1412
+ const submitMessage = state => {
1362
1413
  const {
1363
- statusBarItemsRight
1414
+ composerValue,
1415
+ nextMessageId,
1416
+ selectedSessionId,
1417
+ sessions
1364
1418
  } = state;
1365
- const newStatusBarItemsRight = updateArray([...statusBarItemsRight], newItem);
1419
+ const text = composerValue.trim();
1420
+ if (!text) {
1421
+ return {
1422
+ ...state,
1423
+ ignoreNextInput: true
1424
+ };
1425
+ }
1426
+ const updatedSessions = sessions.map(session => {
1427
+ if (session.id !== selectedSessionId) {
1428
+ return session;
1429
+ }
1430
+ const message = {
1431
+ id: `message-${nextMessageId}`,
1432
+ role: 'user',
1433
+ text
1434
+ };
1435
+ return {
1436
+ ...session,
1437
+ messages: [...session.messages, message]
1438
+ };
1439
+ });
1366
1440
  return {
1367
1441
  ...state,
1368
- statusBarItemsRight: newStatusBarItemsRight
1442
+ composerValue: '',
1443
+ ignoreNextInput: true,
1444
+ lastSubmittedSessionId: selectedSessionId,
1445
+ nextMessageId: nextMessageId + 1,
1446
+ sessions: updatedSessions
1369
1447
  };
1370
1448
  };
1371
-
1372
- const OnStatusBarItem = 'onStatusBarItem';
1373
-
1374
- const GetStatusBarItems = 'ExtensionHost.getStatusBarItems2';
1375
-
1376
- const activateByEvent = (event, assetDir, platform) => {
1377
- // @ts-ignore
1378
- return activateByEvent$1(event, assetDir, platform);
1379
- };
1380
-
1381
- const executeProviders = async ({
1382
- assetDir,
1383
- combineResults,
1384
- event,
1385
- method,
1386
- noProviderFoundMessage = 'No provider found',
1387
- noProviderFoundResult,
1388
- params,
1389
- platform
1390
- }) => {
1391
- await activateByEvent(event, assetDir, platform);
1392
- // @ts-ignore
1393
- const result = await invoke$1(method, ...params);
1394
- return result;
1395
- };
1396
-
1397
- const combineResults = results => {
1398
- return results.flat();
1399
- };
1400
- const getStatusBarItems$1 = (assetDir, platform) => {
1401
- return executeProviders({
1402
- assetDir,
1403
- combineResults,
1404
- event: OnStatusBarItem,
1405
- method: GetStatusBarItems,
1406
- noProviderFoundMessage: 'No status bar item provider found',
1407
- noProviderFoundResult: [],
1408
- params: [],
1409
- platform
1410
- });
1411
- };
1412
-
1413
- const ProblemsErrorIcon = 'ProblemsErrorIcon';
1414
- const ProblemsWarningIcon = 'ProblemsWarningIcon';
1415
- const StatusBarItem = 'StatusBarItem';
1416
- const StatusBarItemsLeft = 'StatusBarItemsLeft';
1417
- const StatusBarItemsRight = 'StatusBarItemsRight';
1418
-
1419
- const getProblemsAriaLabel = (errorCount, warningCount) => {
1420
- const parts = [];
1421
- if (errorCount > 0) {
1422
- parts.push(`${errorCount} ${errorCount === 1 ? 'Problem' : 'Problems'}`);
1423
- }
1424
- if (warningCount > 0) {
1425
- parts.push(`${warningCount} ${warningCount === 1 ? 'Warning' : 'Warnings'}`);
1449
+ const handleKeyDown = async (state, key, shiftKey) => {
1450
+ if (key !== 'Enter' || shiftKey) {
1451
+ return state;
1426
1452
  }
1427
- if (parts.length === 0) {
1428
- return 'No Problems';
1453
+ if (state.renamingSessionId) {
1454
+ return submitRename(state);
1429
1455
  }
1430
- return parts.join(', ');
1431
- };
1432
- const getBuiltinStatusBarItems = async (errorCount, warningCount) => {
1433
- const extraItems = [{
1434
- ariaLabel: 'Notifications',
1435
- command: '',
1436
- // TODO should show notifications center
1437
- elements: [{
1438
- type: 'text',
1439
- value: 'Notifications'
1440
- }],
1441
- name: Notifications,
1442
- tooltip: 'Notifications'
1443
- }, {
1444
- ariaLabel: getProblemsAriaLabel(errorCount, warningCount),
1445
- command: '',
1446
- // TODO should show problems view
1447
- elements: [{
1448
- type: 'icon',
1449
- value: ProblemsErrorIcon
1450
- }, {
1451
- type: 'text',
1452
- value: `${errorCount}`
1453
- }, {
1454
- type: 'icon',
1455
- value: ProblemsWarningIcon
1456
- }, {
1457
- type: 'text',
1458
- value: `${warningCount}`
1459
- }],
1460
- name: Problems,
1461
- tooltip: 'Problems'
1462
- }];
1463
- return extraItems;
1456
+ return submitMessage(state);
1464
1457
  };
1465
1458
 
1466
- const toStatusBarItem = uiStatusBarItem => {
1467
- const elements = [];
1468
- if (uiStatusBarItem.icon) {
1469
- elements.push({
1470
- type: 'icon',
1471
- value: uiStatusBarItem.icon
1472
- });
1473
- }
1474
- if (uiStatusBarItem.text) {
1475
- elements.push({
1476
- type: 'text',
1477
- value: uiStatusBarItem.text
1478
- });
1479
- }
1480
- if (elements.length === 0) {
1481
- elements.push({
1482
- type: 'text',
1483
- value: ''
1484
- });
1485
- }
1486
- const ariaLabel = uiStatusBarItem.text || uiStatusBarItem.tooltip || uiStatusBarItem.name;
1487
- return {
1488
- ariaLabel,
1489
- command: uiStatusBarItem.command || undefined,
1490
- elements,
1491
- name: uiStatusBarItem.name,
1492
- tooltip: uiStatusBarItem.tooltip
1493
- };
1459
+ const id = 7201;
1460
+ const sendMessagePortToExtensionHostWorker = async port => {
1461
+ await sendMessagePortToExtensionHostWorker$1(port, id);
1494
1462
  };
1495
1463
 
1496
- const getActualIcon = extensionHostStatusBarItem => {
1497
- if (extensionHostStatusBarItem.icon === 'branch') {
1498
- return 'Branch';
1464
+ const createExtensionHostRpc = async () => {
1465
+ try {
1466
+ const rpc = await create$4({
1467
+ commandMap: {},
1468
+ send: sendMessagePortToExtensionHostWorker
1469
+ });
1470
+ return rpc;
1471
+ } catch (error) {
1472
+ throw new VError(error, `Failed to create extension host rpc`);
1499
1473
  }
1500
- return extensionHostStatusBarItem.icon || '';
1501
- };
1502
- const toUiStatusBarItem = extensionHostStatusBarItem => {
1503
- return {
1504
- command: extensionHostStatusBarItem.command || '',
1505
- icon: getActualIcon(extensionHostStatusBarItem),
1506
- name: extensionHostStatusBarItem.id || extensionHostStatusBarItem.name || '',
1507
- text: extensionHostStatusBarItem.text || '',
1508
- tooltip: extensionHostStatusBarItem.tooltip || ''
1509
- };
1510
1474
  };
1511
1475
 
1512
- const toUiStatusBarItems = statusBarItems => {
1513
- if (!statusBarItems) {
1514
- return [];
1515
- }
1516
- return statusBarItems.map(toUiStatusBarItem);
1476
+ const initialize = async () => {
1477
+ const rpc = await createExtensionHostRpc();
1478
+ set$2(rpc);
1517
1479
  };
1518
1480
 
1519
- const getStatusBarItems = async (showItems, assetDir, platform, errorCount, warningCount) => {
1520
- if (!showItems) {
1521
- return [];
1481
+ const ensureSessions = state => {
1482
+ if (state.sessions.length > 0) {
1483
+ return state.sessions;
1522
1484
  }
1523
- await activateByEvent('onSourceControl', assetDir, platform);
1524
- const extensionStatusBarItems = await getStatusBarItems$1(assetDir, platform);
1525
- const uiStatusBarItems = toUiStatusBarItems(extensionStatusBarItems);
1526
- const extraItems = await getBuiltinStatusBarItems(errorCount, warningCount);
1527
- return [...uiStatusBarItems.map(toStatusBarItem), ...extraItems];
1528
- };
1529
-
1530
- const get = async key => {
1531
- return getPreference(key);
1532
- };
1533
-
1534
- const itemsVisible = async () => {
1535
- const statusBarItemsPreference = (await get('statusBar.itemsVisible')) ?? true;
1536
- return statusBarItemsPreference;
1485
+ const id = `session-${state.nextSessionId}`;
1486
+ return [{
1487
+ id,
1488
+ messages: [],
1489
+ title: `Chat ${state.nextSessionId}`
1490
+ }];
1537
1491
  };
1538
-
1539
1492
  const loadContent = async state => {
1540
- const {
1541
- assetDir,
1542
- errorCount,
1543
- platform,
1544
- warningCount
1545
- } = state;
1546
- const statusBarItemsPreference = await itemsVisible();
1547
- const statusBarItems = await getStatusBarItems(statusBarItemsPreference, assetDir, platform, errorCount, warningCount);
1493
+ const sessions = ensureSessions(state);
1494
+ const selectedSessionId = sessions.some(session => session.id === state.selectedSessionId) ? state.selectedSessionId : sessions[0].id;
1548
1495
  return {
1549
1496
  ...state,
1550
- errorCount: 0,
1551
1497
  initial: false,
1552
- statusBarItemsLeft: [...statusBarItems],
1553
- statusBarItemsRight: [],
1554
- warningCount: 0
1498
+ nextSessionId: state.sessions.length === 0 ? state.nextSessionId + 1 : state.nextSessionId,
1499
+ selectedSessionId,
1500
+ sessions
1555
1501
  };
1556
1502
  };
1557
1503
 
1558
- const mergeClassNames = (...classNames) => {
1559
- return classNames.filter(Boolean).join(' ');
1560
- };
1561
-
1562
1504
  const text = data => {
1563
1505
  return {
1564
1506
  childCount: 0,
@@ -1855,104 +1797,158 @@ const diffTree = (oldNodes, newNodes) => {
1855
1797
  return removeTrailingNavigationPatches(patches);
1856
1798
  };
1857
1799
 
1800
+ const Actions = 'Actions';
1801
+ const TestActive = 'TestActive';
1802
+ const SideBarLocation = 'SideBarLocation';
1803
+ const Button = 'Button';
1804
+ const Editor = 'Editor';
1805
+ const EditorContent = 'EditorContent';
1806
+ const IconButton = 'IconButton';
1807
+ const Label = 'Label';
1808
+ const List = 'List';
1809
+ const ListItems = 'ListItems';
1810
+ const Markdown = 'Markdown';
1811
+ const Message = 'Message';
1812
+ const MultilineInputBox = 'MultilineInputBox';
1813
+ const Viewlet = 'Viewlet';
1814
+ const WelcomeMessage = 'WelcomeMessage';
1815
+
1816
+ const HandleInput = 4;
1858
1817
  const HandleClick = 11;
1818
+ const HandleKeyDown = 12;
1859
1819
 
1860
- const getTextVirtualDom = element => {
1820
+ const getSessionDom = (session, selectedSessionId) => {
1821
+ const selected = session.id === selectedSessionId;
1822
+ const sessionClassName = selected ? `${List} ${TestActive}` : List;
1861
1823
  return [{
1862
- childCount: 1,
1863
- className: 'StatusBarItemLabel',
1864
- type: Span
1865
- }, text(element.value)];
1866
- };
1867
- const getIconVirtualDom = element => {
1868
- return [{
1869
- childCount: 0,
1870
- className: mergeClassNames(MaskIcon, element.value),
1824
+ childCount: 2,
1825
+ className: sessionClassName,
1871
1826
  type: Div
1872
- }];
1873
- };
1874
- const getStatusBarItemElementVirtualDom = element => {
1875
- if (element.type === 'text') {
1876
- return getTextVirtualDom(element);
1877
- }
1878
- if (element.type === 'icon') {
1879
- return getIconVirtualDom(element);
1880
- }
1881
- return [];
1882
- };
1883
-
1884
- const getStatusBarItemVirtualDom = statusBarItem => {
1885
- const {
1886
- ariaLabel,
1887
- elements,
1888
- name,
1889
- tooltip
1890
- } = statusBarItem;
1891
- const elementNodes = elements.flatMap(getStatusBarItemElementVirtualDom);
1892
- const buttonNode = {
1893
- ariaLabel,
1894
- childCount: elements.length,
1895
- className: StatusBarItem,
1896
- name,
1897
- role: Button$1,
1898
- tabIndex: -1,
1899
- title: tooltip,
1900
- type: Button
1901
- };
1902
- return [buttonNode, ...elementNodes];
1903
- };
1904
-
1905
- const getStatusBarItemsVirtualDom = (items, className) => {
1906
- if (items.length === 0) {
1907
- return [];
1908
- }
1909
- return [{
1910
- childCount: items.length,
1911
- className,
1827
+ }, {
1828
+ childCount: 1,
1829
+ className: Button,
1830
+ name: `session:${session.id}`,
1831
+ role: Button$2,
1832
+ tabIndex: 0,
1833
+ type: Button$1
1834
+ }, text(session.title), {
1835
+ childCount: 2,
1836
+ className: Actions,
1912
1837
  type: Div
1913
- }, ...items.flatMap(getStatusBarItemVirtualDom)];
1914
- };
1915
-
1916
- const getStatusBarItemsLeftDom = statusBarItemsLeft => {
1917
- return getStatusBarItemsVirtualDom(statusBarItemsLeft, StatusBarItemsLeft);
1918
- };
1919
-
1920
- const getStatusBarItemsRightDom = statusBarItemsRight => {
1921
- return getStatusBarItemsVirtualDom(statusBarItemsRight, StatusBarItemsRight);
1922
- };
1923
-
1924
- const getChildCount = (leftCount, rightCount) => {
1925
- let count = 0;
1926
- if (leftCount > 0) {
1927
- count++;
1928
- }
1929
- if (rightCount > 0) {
1930
- count++;
1931
- }
1932
- return count;
1838
+ }, {
1839
+ childCount: 1,
1840
+ className: IconButton,
1841
+ name: `session-rename:${session.id}`,
1842
+ role: Button$2,
1843
+ tabIndex: 0,
1844
+ title: 'Rename chat session',
1845
+ type: Button$1
1846
+ }, text('Rename'), {
1847
+ childCount: 1,
1848
+ className: IconButton,
1849
+ name: `session-delete:${session.id}`,
1850
+ role: Button$2,
1851
+ tabIndex: 0,
1852
+ title: 'Delete chat session',
1853
+ type: Button$1
1854
+ }, text('Delete')];
1855
+ };
1856
+ const getMessagesDom = messages => {
1857
+ if (messages.length === 0) {
1858
+ return [{
1859
+ childCount: 1,
1860
+ className: WelcomeMessage,
1861
+ type: Div
1862
+ }, text('Start a conversation by typing below.')];
1863
+ }
1864
+ return messages.flatMap(message => {
1865
+ return [{
1866
+ childCount: 2,
1867
+ className: Message,
1868
+ type: Div
1869
+ }, {
1870
+ childCount: 1,
1871
+ className: Label,
1872
+ type: Strong
1873
+ }, text(message.role === 'user' ? 'You' : 'Assistant'), {
1874
+ childCount: 1,
1875
+ className: Markdown,
1876
+ type: P
1877
+ }, text(message.text)];
1878
+ });
1933
1879
  };
1934
- const getStatusBarVirtualDom = (statusBarItemsLeft, statusBarItemsRight) => {
1880
+ const getStatusBarVirtualDom = (sessions, selectedSessionId, composerValue) => {
1881
+ const selectedSession = sessions.find(session => session.id === selectedSessionId);
1882
+ const messages = selectedSession ? selectedSession.messages : [];
1883
+ const sessionNodes = sessions.flatMap(session => getSessionDom(session, selectedSessionId));
1884
+ const messagesNodes = getMessagesDom(messages);
1935
1885
  const dom = [{
1936
- childCount: getChildCount(statusBarItemsLeft.length, statusBarItemsRight.length),
1937
- className: 'StatusBar',
1886
+ childCount: 3,
1887
+ className: Viewlet,
1938
1888
  onClick: HandleClick,
1939
- role: Status,
1889
+ onInput: HandleInput,
1890
+ onKeyDown: HandleKeyDown,
1891
+ type: Div
1892
+ }, {
1893
+ childCount: 2,
1894
+ className: SideBarLocation,
1895
+ type: Div
1896
+ }, {
1897
+ childCount: 2,
1898
+ className: Actions,
1899
+ type: Div
1900
+ }, {
1901
+ childCount: 1,
1902
+ className: Label,
1903
+ type: Span
1904
+ }, text('Chats'), {
1905
+ childCount: 1,
1906
+ className: IconButton,
1907
+ name: 'create-session',
1908
+ role: Button$2,
1909
+ tabIndex: 0,
1910
+ title: 'New Chat',
1911
+ type: Button$1
1912
+ }, text('+'), {
1913
+ childCount: sessions.length,
1914
+ className: ListItems,
1915
+ type: Div
1916
+ }, ...sessionNodes, {
1917
+ childCount: 2,
1918
+ className: Editor,
1919
+ type: Div
1920
+ }, {
1921
+ childCount: Math.max(messagesNodes.length, 0),
1922
+ className: EditorContent,
1940
1923
  type: Div
1941
- }, ...getStatusBarItemsLeftDom(statusBarItemsLeft), ...getStatusBarItemsRightDom(statusBarItemsRight)];
1924
+ }, ...messagesNodes, {
1925
+ childCount: 1,
1926
+ className: Actions,
1927
+ type: Div
1928
+ }, {
1929
+ childCount: 0,
1930
+ className: MultilineInputBox,
1931
+ name: 'composer',
1932
+ placeholder: 'Type your message. Enter to send, Shift+Enter for newline.',
1933
+ rows: 4,
1934
+ type: TextArea,
1935
+ value: composerValue
1936
+ }];
1942
1937
  return dom;
1943
1938
  };
1944
1939
 
1945
1940
  const renderItems = (oldState, newState) => {
1946
1941
  const {
1942
+ composerValue,
1947
1943
  initial,
1948
- statusBarItemsLeft,
1949
- statusBarItemsRight,
1944
+ selectedSessionId,
1945
+ sessions,
1950
1946
  uid
1951
1947
  } = newState;
1952
1948
  if (initial) {
1953
1949
  return [SetDom2, uid, []];
1954
1950
  }
1955
- const dom = getStatusBarVirtualDom(statusBarItemsLeft, statusBarItemsRight);
1951
+ const dom = getStatusBarVirtualDom(sessions, selectedSessionId, composerValue);
1956
1952
  return [SetDom2, uid, dom];
1957
1953
  };
1958
1954
 
@@ -1990,7 +1986,7 @@ const render2 = (uid, diffResult) => {
1990
1986
  const {
1991
1987
  newState,
1992
1988
  oldState
1993
- } = get$1(uid);
1989
+ } = get(uid);
1994
1990
  set(uid, newState, newState);
1995
1991
  const commands = applyRender(oldState, newState, diffResult);
1996
1992
  return commands;
@@ -2000,6 +1996,12 @@ const renderEventListeners = () => {
2000
1996
  return [{
2001
1997
  name: HandleClick,
2002
1998
  params: ['handleClick', TargetName]
1999
+ }, {
2000
+ name: HandleInput,
2001
+ params: ['handleInput', TargetValue]
2002
+ }, {
2003
+ name: HandleKeyDown,
2004
+ params: ['handleKeyDown', Key, ShiftKey]
2003
2005
  }];
2004
2006
  };
2005
2007
 
@@ -2012,30 +2014,39 @@ const resize = (state, dimensions) => {
2012
2014
 
2013
2015
  const saveState = state => {
2014
2016
  const {
2015
- statusBarItemsLeft,
2016
- statusBarItemsRight
2017
+ composerValue,
2018
+ nextMessageId,
2019
+ nextSessionId,
2020
+ renamingSessionId,
2021
+ selectedSessionId,
2022
+ sessions
2017
2023
  } = state;
2018
2024
  return {
2019
- itemsLeft: statusBarItemsLeft,
2020
- itemsRight: statusBarItemsRight
2025
+ composerValue,
2026
+ nextMessageId,
2027
+ nextSessionId,
2028
+ renamingSessionId,
2029
+ selectedSessionId,
2030
+ sessions
2021
2031
  };
2022
2032
  };
2023
2033
 
2024
2034
  const commandMap = {
2025
- 'StatusBar.create': create,
2026
- 'StatusBar.diff2': diff2,
2027
- 'StatusBar.getCommandIds': getCommandIds,
2028
- 'StatusBar.handleClick': wrapCommand(handleClick),
2029
- 'StatusBar.initialize': initialize,
2030
- 'StatusBar.itemLeftUpdate': wrapCommand(itemLeftUpdate),
2031
- 'StatusBar.itemRightCreate': wrapCommand(itemRightCreate),
2032
- 'StatusBar.itemRightUpdate': wrapCommand(itemRightUpdate),
2033
- 'StatusBar.loadContent': wrapCommand(loadContent),
2034
- 'StatusBar.render2': render2,
2035
- 'StatusBar.renderEventListeners': renderEventListeners,
2036
- 'StatusBar.resize': wrapCommand(resize),
2037
- 'StatusBar.saveState': wrapGetter(saveState),
2038
- 'StatusBar.terminate': terminate
2035
+ 'Chat.create': create,
2036
+ 'Chat.diff2': diff2,
2037
+ 'Chat.getCommandIds': getCommandIds,
2038
+ 'Chat.getKeyBindings': getKeyBindings,
2039
+ 'Chat.handleClick': wrapCommand(handleClick),
2040
+ 'Chat.handleInput': wrapCommand(handleInput),
2041
+ 'Chat.handleKeyDown': wrapCommand(handleKeyDown),
2042
+ 'Chat.initialize': initialize,
2043
+ 'Chat.loadContent': wrapCommand(loadContent),
2044
+ 'Chat.loadContent2': wrapCommand(loadContent),
2045
+ 'Chat.render2': render2,
2046
+ 'Chat.renderEventListeners': renderEventListeners,
2047
+ 'Chat.resize': wrapCommand(resize),
2048
+ 'Chat.saveState': wrapGetter(saveState),
2049
+ 'Chat.terminate': terminate
2039
2050
  };
2040
2051
 
2041
2052
  const listen = async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/chat-view",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "description": "Chat View Worker",
5
5
  "repository": {
6
6
  "type": "git",