clay-server 2.11.0-beta.22 → 2.11.0-beta.23

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/lib/public/app.js CHANGED
@@ -55,6 +55,7 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
55
55
  var dmTargetUser = null;
56
56
  var dmUnread = {}; // { otherUserId: count }
57
57
  var cachedAllUsers = [];
58
+ var cachedOnlineIds = [];
58
59
  var cachedDmFavorites = [];
59
60
  var cachedDmConversations = [];
60
61
  var dmRemovedUsers = {}; // { userId: true } - users explicitly removed from favorites
@@ -850,15 +851,19 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
850
851
  }
851
852
  // Update topbar with server-wide presence
852
853
  if (msg.serverUsers) {
854
+ cachedOnlineIds = msg.serverUsers.map(function (u) { return u.id; });
853
855
  renderTopbarPresence(msg.serverUsers);
856
+ // Re-render user strip online dots even without allUsers update
857
+ if (!msg.allUsers && cachedAllUsers.length > 0) {
858
+ renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers);
859
+ }
854
860
  }
855
861
  // Update user strip (DM targets) in icon strip
856
862
  if (msg.allUsers) {
857
863
  cachedAllUsers = msg.allUsers;
858
864
  if (msg.dmFavorites) cachedDmFavorites = msg.dmFavorites;
859
865
  if (msg.dmConversations) cachedDmConversations = msg.dmConversations;
860
- var onlineIds = (msg.serverUsers || []).map(function (u) { return u.id; });
861
- renderUserStrip(msg.allUsers, onlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers);
866
+ renderUserStrip(msg.allUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers);
862
867
  // Render my avatar (always present, hidden behind user-island)
863
868
  var meEl = document.getElementById("icon-strip-me");
864
869
  if (meEl && !meEl.hasChildNodes()) {
@@ -3665,11 +3670,7 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
3665
3670
  if (fromId && fromId !== myUserId) {
3666
3671
  dmUnread[fromId] = (dmUnread[fromId] || 0) + 1;
3667
3672
  // Re-render strip so non-favorited sender appears
3668
- var onlineIdsForDm = (cachedAllUsers || []).filter(function (u) {
3669
- var el = document.querySelector('.icon-strip-user[data-user-id="' + u.id + '"]');
3670
- return el && el.classList.contains("online");
3671
- }).map(function (u) { return u.id; });
3672
- renderUserStrip(cachedAllUsers, onlineIdsForDm, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers);
3673
+ renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers);
3673
3674
  updateDmBadge(fromId, dmUnread[fromId]);
3674
3675
  }
3675
3676
  }
@@ -3701,11 +3702,7 @@ import { initAdmin, checkAdminAccess } from './modules/admin.js';
3701
3702
  }
3702
3703
  }
3703
3704
  cachedDmFavorites = msg.dmFavorites || [];
3704
- var onlineIds2 = (cachedAllUsers || []).filter(function (u) {
3705
- var el = document.querySelector('.icon-strip-user[data-user-id="' + u.id + '"]');
3706
- return el && el.classList.contains("online");
3707
- }).map(function (u) { return u.id; });
3708
- renderUserStrip(cachedAllUsers, onlineIds2, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers);
3705
+ renderUserStrip(cachedAllUsers, cachedOnlineIds, myUserId, cachedDmFavorites, cachedDmConversations, dmUnread, dmRemovedUsers);
3709
3706
  break;
3710
3707
 
3711
3708
  case "daemon_config":
@@ -644,7 +644,25 @@ function showFormatToolbar(rendered) {
644
644
  if (!sel.toString().trim()) return;
645
645
 
646
646
  var range = sel.getRangeAt(0);
647
- if (!rendered.contains(range.commonAncestorContainer)) return;
647
+ // When dragging outside the note, commonAncestorContainer may be a parent
648
+ // of rendered. Clamp the range to the rendered element so the toolbar shows.
649
+ if (!rendered.contains(range.commonAncestorContainer)) {
650
+ try {
651
+ var clampedRange = range.cloneRange();
652
+ if (range.startContainer === rendered || rendered.contains(range.startContainer)) {
653
+ clampedRange.selectNodeContents(rendered);
654
+ clampedRange.setStart(range.startContainer, range.startOffset);
655
+ } else if (range.endContainer === rendered || rendered.contains(range.endContainer)) {
656
+ clampedRange.selectNodeContents(rendered);
657
+ clampedRange.setEnd(range.endContainer, range.endOffset);
658
+ } else {
659
+ return;
660
+ }
661
+ range = clampedRange;
662
+ } catch (e) {
663
+ return;
664
+ }
665
+ }
648
666
 
649
667
  var toolbar = document.createElement("div");
650
668
  toolbar.className = "sn-format-toolbar";
package/lib/server.js CHANGED
@@ -2416,7 +2416,7 @@ function createServer(opts) {
2416
2416
  // Sends per-user filtered project lists + server-wide user list
2417
2417
  var presenceTimer = null;
2418
2418
  function broadcastPresenceChange() {
2419
- if (presenceTimer) return;
2419
+ if (presenceTimer) clearTimeout(presenceTimer);
2420
2420
  presenceTimer = setTimeout(function () {
2421
2421
  presenceTimer = null;
2422
2422
  if (!users.isMultiUser()) {
package/lib/users.js CHANGED
@@ -548,6 +548,8 @@ function canAccessProject(userId, project) {
548
548
  // Admin always has access
549
549
  var user = findUserById(userId);
550
550
  if (user && user.role === "admin") return true;
551
+ // Owner always has access to their own project
552
+ if (project.ownerId && project.ownerId === userId) return true;
551
553
  // Private project — check allowedUsers
552
554
  var allowed = project.allowedUsers || [];
553
555
  return allowed.indexOf(userId) >= 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clay-server",
3
- "version": "2.11.0-beta.22",
3
+ "version": "2.11.0-beta.23",
4
4
  "description": "Web UI for Claude Code. Any device. Push notifications.",
5
5
  "bin": {
6
6
  "clay-server": "./bin/cli.js",