watercooler 0.0.1 → 0.0.2
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/package.json +1 -1
- package/public/app.js +44 -16
- package/public/index.html +65 -6
- package/server.ts +2 -3
package/package.json
CHANGED
package/public/app.js
CHANGED
|
@@ -245,18 +245,18 @@ function createMessageParticle(fromPos, toPos) {
|
|
|
245
245
|
animateParticle();
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
function createConnectionLine(fromPos, toPos
|
|
248
|
+
function createConnectionLine(fromPos, toPos) {
|
|
249
|
+
const startPos = new THREE.Vector3(fromPos.x, fromPos.y + 5, fromPos.z);
|
|
250
|
+
const endPos = new THREE.Vector3(toPos.x, toPos.y + 5, toPos.z);
|
|
251
|
+
|
|
249
252
|
const material = new THREE.LineBasicMaterial({
|
|
250
|
-
color:
|
|
251
|
-
opacity:
|
|
253
|
+
color: 0xff6b6b,
|
|
254
|
+
opacity: 0.8,
|
|
252
255
|
transparent: true,
|
|
253
|
-
linewidth:
|
|
256
|
+
linewidth: 3
|
|
254
257
|
});
|
|
255
258
|
|
|
256
|
-
const points = [
|
|
257
|
-
new THREE.Vector3(fromPos.x, fromPos.y + 5, fromPos.z),
|
|
258
|
-
new THREE.Vector3(toPos.x, toPos.y + 5, toPos.z)
|
|
259
|
-
];
|
|
259
|
+
const points = [startPos, endPos];
|
|
260
260
|
|
|
261
261
|
const geometry = new THREE.BufferGeometry().setFromPoints(points);
|
|
262
262
|
const line = new THREE.Line(geometry, material);
|
|
@@ -264,6 +264,29 @@ function createConnectionLine(fromPos, toPos, isUnread) {
|
|
|
264
264
|
scene.add(line);
|
|
265
265
|
connectionLines.push(line);
|
|
266
266
|
|
|
267
|
+
// Add arrowhead for directionality
|
|
268
|
+
const direction = new THREE.Vector3().subVectors(endPos, startPos).normalize();
|
|
269
|
+
const arrowPos = endPos.clone().sub(direction.clone().multiplyScalar(5));
|
|
270
|
+
|
|
271
|
+
const arrowGeometry = new THREE.ConeGeometry(0.5, 1.5, 8);
|
|
272
|
+
const arrowMaterial = new THREE.MeshStandardMaterial({
|
|
273
|
+
color: 0xff6b6b,
|
|
274
|
+
emissive: 0xff6b6b,
|
|
275
|
+
emissiveIntensity: 0.3
|
|
276
|
+
});
|
|
277
|
+
const arrowhead = new THREE.Mesh(arrowGeometry, arrowMaterial);
|
|
278
|
+
|
|
279
|
+
arrowhead.position.copy(arrowPos);
|
|
280
|
+
|
|
281
|
+
// Orient arrow to point along the line
|
|
282
|
+
const up = new THREE.Vector3(0, 1, 0);
|
|
283
|
+
const quaternion = new THREE.Quaternion();
|
|
284
|
+
quaternion.setFromUnitVectors(up, direction);
|
|
285
|
+
arrowhead.setRotationFromQuaternion(quaternion);
|
|
286
|
+
|
|
287
|
+
scene.add(arrowhead);
|
|
288
|
+
connectionLines.push(arrowhead);
|
|
289
|
+
|
|
267
290
|
// Send particle
|
|
268
291
|
setTimeout(() => {
|
|
269
292
|
createMessageParticle(fromPos, toPos);
|
|
@@ -307,16 +330,15 @@ function updateVillage() {
|
|
|
307
330
|
}
|
|
308
331
|
});
|
|
309
332
|
|
|
310
|
-
// Create connections
|
|
311
|
-
|
|
333
|
+
// Create connections for unread messages only
|
|
334
|
+
allMessages.forEach(msg => {
|
|
312
335
|
const fromHouse = agentMeshes.get(msg.sender.toLowerCase());
|
|
313
336
|
const toHouse = agentMeshes.get(msg.recipient.toLowerCase());
|
|
314
337
|
|
|
315
|
-
if (fromHouse && toHouse) {
|
|
338
|
+
if (fromHouse && toHouse && !msg.read) {
|
|
316
339
|
createConnectionLine(
|
|
317
340
|
fromHouse.position,
|
|
318
|
-
toHouse.position
|
|
319
|
-
!msg.read && msg.recipient.toLowerCase() === config.user.toLowerCase()
|
|
341
|
+
toHouse.position
|
|
320
342
|
);
|
|
321
343
|
}
|
|
322
344
|
});
|
|
@@ -387,7 +409,7 @@ function updateUI() {
|
|
|
387
409
|
// Update recipient select (send panel) - only from coworkers.db
|
|
388
410
|
const select = document.getElementById('recipient-select');
|
|
389
411
|
const currentVal = select.value;
|
|
390
|
-
select.innerHTML = '<option value="">
|
|
412
|
+
select.innerHTML = '<option value="">Coworker...</option>' +
|
|
391
413
|
recipients.sort().map(r =>
|
|
392
414
|
`<option value="${r}" ${r === currentVal ? 'selected' : ''}>${r}</option>`
|
|
393
415
|
).join('');
|
|
@@ -408,7 +430,7 @@ function updateUI() {
|
|
|
408
430
|
<span class="message-sender">${msg.sender} → ${msg.recipient}</span>
|
|
409
431
|
<span class="message-time">${new Date(msg.timestamp).toLocaleString()}</span>
|
|
410
432
|
</div>
|
|
411
|
-
<div class="message-text">${msg.message}</div>
|
|
433
|
+
<div class="message-text">${marked.parse(msg.message)}</div>
|
|
412
434
|
</div>
|
|
413
435
|
`).join('');
|
|
414
436
|
|
|
@@ -434,6 +456,12 @@ function updateUI() {
|
|
|
434
456
|
// Mark as read
|
|
435
457
|
markAsRead(msgId);
|
|
436
458
|
|
|
459
|
+
// Expand send panel if collapsed
|
|
460
|
+
const sendPanel = document.getElementById('send-panel');
|
|
461
|
+
if (sendPanel && sendPanel.classList.contains('collapsed')) {
|
|
462
|
+
toggleSendPanel();
|
|
463
|
+
}
|
|
464
|
+
|
|
437
465
|
// Focus the message input for typing
|
|
438
466
|
const messageInput = document.getElementById('message-input');
|
|
439
467
|
if (messageInput) {
|
|
@@ -621,7 +649,7 @@ function updateHouseDialogContent() {
|
|
|
621
649
|
<span class="message-sender">${msg.sender} → ${msg.recipient}</span>
|
|
622
650
|
<span class="message-time">${new Date(msg.timestamp).toLocaleString()}</span>
|
|
623
651
|
</div>
|
|
624
|
-
<div class="message-text">${msg.message}</div>
|
|
652
|
+
<div class="message-text">${marked.parse(msg.message)}</div>
|
|
625
653
|
</div>
|
|
626
654
|
`).join('');
|
|
627
655
|
}
|
package/public/index.html
CHANGED
|
@@ -208,9 +208,8 @@
|
|
|
208
208
|
.message-card {
|
|
209
209
|
background: rgba(255, 255, 255, 0.1);
|
|
210
210
|
border-radius: 12px;
|
|
211
|
-
padding: 12px;
|
|
211
|
+
padding: 12px 12px 12px 20px;
|
|
212
212
|
margin-bottom: 10px;
|
|
213
|
-
border-left: 3px solid #4CAF50;
|
|
214
213
|
transition: all 0.3s ease;
|
|
215
214
|
cursor: pointer;
|
|
216
215
|
}
|
|
@@ -220,7 +219,7 @@
|
|
|
220
219
|
}
|
|
221
220
|
|
|
222
221
|
.message-card.unread {
|
|
223
|
-
border-left
|
|
222
|
+
border-left: 3px solid #ff6b6b;
|
|
224
223
|
background: rgba(255, 107, 107, 0.15);
|
|
225
224
|
}
|
|
226
225
|
|
|
@@ -246,6 +245,65 @@
|
|
|
246
245
|
color: rgba(255, 255, 255, 0.9);
|
|
247
246
|
font-size: 0.85rem;
|
|
248
247
|
line-height: 1.4;
|
|
248
|
+
white-space: pre-wrap;
|
|
249
|
+
word-wrap: break-word;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.message-text h1, .message-text h2, .message-text h3 {
|
|
253
|
+
margin: 8px 0;
|
|
254
|
+
color: white;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.message-text h1 { font-size: 1.2rem; }
|
|
258
|
+
.message-text h2 { font-size: 1.1rem; }
|
|
259
|
+
.message-text h3 { font-size: 1rem; }
|
|
260
|
+
|
|
261
|
+
.message-text strong {
|
|
262
|
+
color: white;
|
|
263
|
+
font-weight: 700;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.message-text code {
|
|
267
|
+
background: rgba(0, 0, 0, 0.3);
|
|
268
|
+
padding: 2px 6px;
|
|
269
|
+
border-radius: 4px;
|
|
270
|
+
font-family: 'Monaco', 'Menlo', monospace;
|
|
271
|
+
font-size: 0.8rem;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.message-text pre {
|
|
275
|
+
background: rgba(0, 0, 0, 0.3);
|
|
276
|
+
padding: 10px;
|
|
277
|
+
border-radius: 8px;
|
|
278
|
+
overflow-x: auto;
|
|
279
|
+
margin: 8px 0;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.message-text pre code {
|
|
283
|
+
background: transparent;
|
|
284
|
+
padding: 0;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.message-text hr {
|
|
288
|
+
border: none;
|
|
289
|
+
border-top: 1px solid rgba(255, 255, 255, 0.2);
|
|
290
|
+
margin: 12px 0;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.message-text blockquote {
|
|
294
|
+
border-left: 3px solid rgba(255, 255, 255, 0.4);
|
|
295
|
+
margin: 8px 0;
|
|
296
|
+
padding-left: 12px;
|
|
297
|
+
color: rgba(255, 255, 255, 0.7);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.message-text ul, .message-text ol {
|
|
301
|
+
margin: 8px 0;
|
|
302
|
+
padding-left: 24px;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.message-text li {
|
|
306
|
+
margin: 4px 0;
|
|
249
307
|
}
|
|
250
308
|
|
|
251
309
|
/* Toggle Messages Button */
|
|
@@ -378,13 +436,12 @@
|
|
|
378
436
|
.house-dialog-body .message-card {
|
|
379
437
|
background: rgba(255, 255, 255, 0.1);
|
|
380
438
|
border-radius: 12px;
|
|
381
|
-
padding: 12px;
|
|
439
|
+
padding: 12px 12px 12px 20px;
|
|
382
440
|
margin-bottom: 10px;
|
|
383
|
-
border-left: 3px solid #4CAF50;
|
|
384
441
|
}
|
|
385
442
|
|
|
386
443
|
.house-dialog-body .message-card.unread {
|
|
387
|
-
border-left
|
|
444
|
+
border-left: 3px solid #ff6b6b;
|
|
388
445
|
background: rgba(255, 107, 107, 0.15);
|
|
389
446
|
}
|
|
390
447
|
|
|
@@ -442,6 +499,8 @@
|
|
|
442
499
|
display: none;
|
|
443
500
|
}
|
|
444
501
|
</style>
|
|
502
|
+
<!-- Markdown parser -->
|
|
503
|
+
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
445
504
|
</head>
|
|
446
505
|
<body>
|
|
447
506
|
<div id="canvas-container"></div>
|
package/server.ts
CHANGED
|
@@ -92,16 +92,15 @@ app.get('/api/messages/sent', (req, res) => {
|
|
|
92
92
|
}
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
// API: Get ALL messages
|
|
95
|
+
// API: Get ALL messages between ALL agents
|
|
96
96
|
app.get('/api/messages/all', (req, res) => {
|
|
97
97
|
try {
|
|
98
98
|
if (!db) throw new Error('Database not connected');
|
|
99
99
|
const stmt = db.prepare(`
|
|
100
100
|
SELECT * FROM messages
|
|
101
|
-
WHERE recipient = ? OR sender = ?
|
|
102
101
|
ORDER BY timestamp DESC
|
|
103
102
|
`);
|
|
104
|
-
res.json(stmt.all(
|
|
103
|
+
res.json(stmt.all());
|
|
105
104
|
} catch (err: any) {
|
|
106
105
|
res.status(500).json({ error: err.message });
|
|
107
106
|
}
|