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 +9 -12
- package/lib/public/modules/sticky-notes.js +19 -1
- package/lib/server.js +1 -1
- package/lib/users.js +2 -0
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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)
|
|
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;
|