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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "watercooler",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "A beautiful 3D visualization of your mailbox messages as a village of coworkers",
5
5
  "type": "module",
6
6
  "main": "server.ts",
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, isUnread) {
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: isUnread ? 0xff6b6b : 0x4CAF50,
251
- opacity: isUnread ? 0.8 : 0.3,
253
+ color: 0xff6b6b,
254
+ opacity: 0.8,
252
255
  transparent: true,
253
- linewidth: isUnread ? 3 : 1
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 based on messages
311
- messages.forEach(msg => {
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="">To: Select agent...</option>' +
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-color: #ff6b6b;
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-color: #ff6b6b;
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 involving the user (for house dialogs)
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(user!.toLowerCase(), user!.toLowerCase()));
103
+ res.json(stmt.all());
105
104
  } catch (err: any) {
106
105
  res.status(500).json({ error: err.message });
107
106
  }