turbo_chat 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -1
- data/README.md +178 -190
- data/app/assets/config/turbo_chat_manifest.js +3 -0
- data/app/assets/javascripts/turbo_chat/application.js +3 -0
- data/app/assets/javascripts/turbo_chat/invite_picker.js +19 -392
- data/app/assets/javascripts/turbo_chat/member_sync.js +426 -0
- data/app/assets/javascripts/turbo_chat/mentions.js +366 -0
- data/app/assets/javascripts/turbo_chat/messages.js +18 -370
- data/app/assets/javascripts/turbo_chat/realtime.js +3 -10
- data/app/assets/javascripts/turbo_chat/scroll_proxy.js +379 -0
- data/app/assets/javascripts/turbo_chat/shared.js +7 -383
- data/app/assets/stylesheets/turbo_chat/application.css +9 -1646
- data/app/assets/stylesheets/turbo_chat/base.css +84 -0
- data/app/assets/stylesheets/turbo_chat/components.css +193 -0
- data/app/assets/stylesheets/turbo_chat/composer.css +241 -0
- data/app/assets/stylesheets/turbo_chat/layout.css +307 -0
- data/app/assets/stylesheets/turbo_chat/members.css +264 -0
- data/app/assets/stylesheets/turbo_chat/menus.css +172 -0
- data/app/assets/stylesheets/turbo_chat/messages.css +430 -0
- data/app/controllers/turbo_chat/application_controller.rb +3 -7
- data/app/controllers/turbo_chat/chat_memberships_controller.rb +35 -1
- data/app/controllers/turbo_chat/chat_messages_controller.rb +4 -8
- data/app/controllers/turbo_chat/chats_controller.rb +10 -12
- data/app/helpers/turbo_chat/application_helper/config_support.rb +42 -32
- data/app/helpers/turbo_chat/application_helper/mention_support.rb +3 -3
- data/app/helpers/turbo_chat/application_helper/message_rendering.rb +24 -13
- data/app/models/turbo_chat/chat.rb +43 -20
- data/app/models/turbo_chat/chat_membership.rb +1 -1
- data/app/models/turbo_chat/chat_message/blocked_words_moderation.rb +9 -25
- data/app/models/turbo_chat/chat_message/body_length_validation.rb +1 -1
- data/app/models/turbo_chat/chat_message/broadcasting.rb +2 -6
- data/app/models/turbo_chat/chat_message/formatting.rb +3 -7
- data/app/models/turbo_chat/chat_message/mention_validation.rb +1 -1
- data/app/models/turbo_chat/chat_message/signals.rb +1 -1
- data/app/models/turbo_chat/chat_message.rb +3 -8
- data/app/views/turbo_chat/chat_messages/_form.html.erb +9 -9
- data/app/views/turbo_chat/chat_messages/_message.html.erb +2 -2
- data/app/views/turbo_chat/chat_messages/_signals.html.erb +11 -13
- data/app/views/turbo_chat/chat_messages/_system.html.erb +1 -1
- data/app/views/turbo_chat/chats/_invite_form.html.erb +1 -1
- data/app/views/turbo_chat/chats/_member_entries.html.erb +15 -1
- data/app/views/turbo_chat/chats/index.html.erb +1 -1
- data/app/views/turbo_chat/chats/new.html.erb +4 -7
- data/app/views/turbo_chat/chats/show.html.erb +29 -27
- data/config/routes.rb +6 -1
- data/db/migrate/20260325000016_add_chat_mode_to_turbo_chat_chats.rb +6 -0
- data/lib/generators/turbo_chat/install/templates/turbo_chat.rb +8 -0
- data/lib/turbo_chat/configuration/defaults.rb +21 -0
- data/lib/turbo_chat/configuration.rb +105 -0
- data/lib/turbo_chat/moderation/chat_actions.rb +2 -2
- data/lib/turbo_chat/moderation/member_actions.rb +2 -1
- data/lib/turbo_chat/moderation/support.rb +5 -9
- data/lib/turbo_chat/permission/support.rb +6 -2
- data/lib/turbo_chat/permission.rb +1 -5
- data/lib/turbo_chat/signals.rb +1 -1
- data/lib/turbo_chat/version.rb +1 -1
- metadata +13 -2
|
@@ -113,6 +113,8 @@
|
|
|
113
113
|
var filteredOptions = [];
|
|
114
114
|
var activeIndex = 0;
|
|
115
115
|
var selectedOption = null;
|
|
116
|
+
var submitBtn = form.querySelector("[data-chat-invite-submit]");
|
|
117
|
+
if (submitBtn) submitBtn.disabled = true;
|
|
116
118
|
|
|
117
119
|
function persistOptions() {
|
|
118
120
|
form.dataset.chatInviteOptions = serializeOptions(allOptions);
|
|
@@ -121,6 +123,7 @@
|
|
|
121
123
|
function clearSelection() {
|
|
122
124
|
selectedOption = null;
|
|
123
125
|
participantIdInput.value = "";
|
|
126
|
+
if (submitBtn) submitBtn.disabled = true;
|
|
124
127
|
}
|
|
125
128
|
|
|
126
129
|
function setSelection(optionData) {
|
|
@@ -133,7 +136,9 @@
|
|
|
133
136
|
participantIdInput.value = optionData.participantId;
|
|
134
137
|
queryInput.value = optionData.label;
|
|
135
138
|
queryInput.setCustomValidity("");
|
|
139
|
+
if (submitBtn) submitBtn.disabled = false;
|
|
136
140
|
hideMenu();
|
|
141
|
+
hideHint();
|
|
137
142
|
}
|
|
138
143
|
|
|
139
144
|
function setActiveIndex(index) {
|
|
@@ -202,10 +207,14 @@
|
|
|
202
207
|
if (exactMatch) {
|
|
203
208
|
selectedOption = exactMatch;
|
|
204
209
|
participantIdInput.value = exactMatch.participantId;
|
|
205
|
-
|
|
206
|
-
|
|
210
|
+
if (submitBtn) submitBtn.disabled = false;
|
|
211
|
+
hideMenu();
|
|
212
|
+
hideHint();
|
|
213
|
+
return;
|
|
207
214
|
}
|
|
208
215
|
|
|
216
|
+
clearSelection();
|
|
217
|
+
|
|
209
218
|
if (query.length < MIN_QUERY_LENGTH) {
|
|
210
219
|
hideMenu();
|
|
211
220
|
if (!query.length) {
|
|
@@ -216,6 +225,12 @@
|
|
|
216
225
|
return;
|
|
217
226
|
}
|
|
218
227
|
|
|
228
|
+
if (!allOptions.length && query.length) {
|
|
229
|
+
hideMenu();
|
|
230
|
+
showHint("All eligible participants have been invited.");
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
219
234
|
filteredOptions = matchingOptions(allOptions, query);
|
|
220
235
|
if (!filteredOptions.length) {
|
|
221
236
|
hideMenu();
|
|
@@ -352,6 +367,7 @@
|
|
|
352
367
|
setTimeout(function () {
|
|
353
368
|
clearSelection();
|
|
354
369
|
queryInput.value = "";
|
|
370
|
+
if (submitBtn) submitBtn.disabled = true;
|
|
355
371
|
syncQueryState();
|
|
356
372
|
}, 0);
|
|
357
373
|
});
|
|
@@ -367,401 +383,12 @@
|
|
|
367
383
|
return form.__chatInvitePickerApi;
|
|
368
384
|
}
|
|
369
385
|
|
|
370
|
-
function parseMemberEntry(node) {
|
|
371
|
-
if (!node || !node.dataset || node.dataset.chatMemberEntry !== "true") {
|
|
372
|
-
return null;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
var chatId = String(node.dataset.chatId || "").trim();
|
|
376
|
-
var participantType = String(node.dataset.chatMemberParticipantType || "").trim();
|
|
377
|
-
var participantId = String(node.dataset.chatMemberParticipantId || "").trim();
|
|
378
|
-
var mentionToken = String(node.dataset.chatMemberMentionToken || "").trim();
|
|
379
|
-
var roleKey = String(node.dataset.chatMemberRoleKey || "").trim();
|
|
380
|
-
var roleName = String(node.dataset.chatMemberRoleName || "").trim();
|
|
381
|
-
var roleRank = parseInt(node.dataset.chatMemberRoleRank || "-1", 10);
|
|
382
|
-
var name = String(node.dataset.chatMemberName || "").trim();
|
|
383
|
-
var inviteLabel = String(node.dataset.chatMemberInviteLabel || "").trim();
|
|
384
|
-
var search = normalize(node.dataset.chatMemberSearch || inviteLabel || name);
|
|
385
|
-
|
|
386
|
-
if (!chatId || !participantType || !participantId) {
|
|
387
|
-
return null;
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return {
|
|
391
|
-
identity: participantType + ":" + participantId,
|
|
392
|
-
chatId: chatId,
|
|
393
|
-
participantType: participantType,
|
|
394
|
-
participantId: participantId,
|
|
395
|
-
mentionToken: mentionToken,
|
|
396
|
-
name: name,
|
|
397
|
-
roleKey: roleKey,
|
|
398
|
-
roleName: roleName,
|
|
399
|
-
roleRank: isNaN(roleRank) ? -1 : roleRank,
|
|
400
|
-
inviteOption: {
|
|
401
|
-
label: inviteLabel,
|
|
402
|
-
participantId: participantId,
|
|
403
|
-
search: search
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
function collectMemberEntries(sourceNode, entryMap) {
|
|
409
|
-
if (!sourceNode || sourceNode.nodeType !== 1) {
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
var sourceElement = sourceNode;
|
|
414
|
-
var sourceEntry = parseMemberEntry(sourceElement);
|
|
415
|
-
if (sourceEntry) {
|
|
416
|
-
entryMap[sourceEntry.identity] = sourceEntry;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
if (typeof sourceElement.querySelectorAll !== "function") {
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
|
|
423
|
-
sourceElement.querySelectorAll("[data-chat-member-entry='true']").forEach(function (memberEntryNode) {
|
|
424
|
-
var memberEntry = parseMemberEntry(memberEntryNode);
|
|
425
|
-
if (!memberEntry) {
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
entryMap[memberEntry.identity] = memberEntry;
|
|
430
|
-
});
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
function findInvitePickerApis(chatId) {
|
|
434
|
-
var apis = [];
|
|
435
|
-
var normalizedChatId = String(chatId || "").trim();
|
|
436
|
-
if (!normalizedChatId) {
|
|
437
|
-
return apis;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
document.querySelectorAll("[data-chat-invite-form]").forEach(function (form) {
|
|
441
|
-
if (String(form.dataset.chatId || "").trim() !== normalizedChatId) {
|
|
442
|
-
return;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
var api = setupInvitePicker(form);
|
|
446
|
-
if (api) {
|
|
447
|
-
apis.push(api);
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
return apis;
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
function memberListForChat(chatId) {
|
|
455
|
-
var normalizedChatId = String(chatId || "").trim();
|
|
456
|
-
if (!normalizedChatId) {
|
|
457
|
-
return null;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
var matchedList = null;
|
|
461
|
-
document.querySelectorAll("[data-chat-member-list]").forEach(function (memberList) {
|
|
462
|
-
if (!matchedList && String(memberList.dataset.chatId || "").trim() === normalizedChatId) {
|
|
463
|
-
matchedList = memberList;
|
|
464
|
-
}
|
|
465
|
-
});
|
|
466
|
-
return matchedList;
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
function shellForChat(chatId) {
|
|
470
|
-
var normalizedChatId = String(chatId || "").trim();
|
|
471
|
-
if (!normalizedChatId) {
|
|
472
|
-
return null;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
var matchedShell = null;
|
|
476
|
-
document.querySelectorAll(".chat-shell[data-chat-id]").forEach(function (shell) {
|
|
477
|
-
if (!matchedShell && String(shell.dataset.chatId || "").trim() === normalizedChatId) {
|
|
478
|
-
matchedShell = shell;
|
|
479
|
-
}
|
|
480
|
-
});
|
|
481
|
-
return matchedShell;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
function syncInviteOptionsFromMemberMutations(chatId, mutationRecords) {
|
|
485
|
-
var invitePickerApis = findInvitePickerApis(chatId);
|
|
486
|
-
if (!invitePickerApis.length) {
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
var removedEntries = {};
|
|
491
|
-
var addedEntries = {};
|
|
492
|
-
|
|
493
|
-
mutationRecords.forEach(function (record) {
|
|
494
|
-
if (!record) {
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
record.removedNodes.forEach(function (removedNode) {
|
|
499
|
-
collectMemberEntries(removedNode, removedEntries);
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
record.addedNodes.forEach(function (addedNode) {
|
|
503
|
-
collectMemberEntries(addedNode, addedEntries);
|
|
504
|
-
});
|
|
505
|
-
});
|
|
506
|
-
|
|
507
|
-
Object.keys(removedEntries).forEach(function (entryKey) {
|
|
508
|
-
if (addedEntries[entryKey]) {
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
var removedEntry = removedEntries[entryKey];
|
|
513
|
-
invitePickerApis.forEach(function (invitePickerApi) {
|
|
514
|
-
invitePickerApi.upsertOption(removedEntry.inviteOption);
|
|
515
|
-
});
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
Object.keys(addedEntries).forEach(function (entryKey) {
|
|
519
|
-
var addedEntry = addedEntries[entryKey];
|
|
520
|
-
invitePickerApis.forEach(function (invitePickerApi) {
|
|
521
|
-
invitePickerApi.removeParticipant(addedEntry.participantId);
|
|
522
|
-
});
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
function mentionOptionsForComposer(composer, memberEntries) {
|
|
527
|
-
if (!composer || composer.dataset.chatEnableMentions !== "true") {
|
|
528
|
-
return [];
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
var canMentionMembers = composer.dataset.chatCanMentionMembers === "true";
|
|
532
|
-
var canMentionAll = composer.dataset.chatCanMentionAll === "true";
|
|
533
|
-
var canMentionRoles = composer.dataset.chatCanMentionRoles === "true";
|
|
534
|
-
var hideRoles = composer.dataset.chatMentionFilterHideRoles === "true";
|
|
535
|
-
var excludeSelf = composer.dataset.chatMentionFilterExcludeSelf === "true";
|
|
536
|
-
var selfType = String(composer.dataset.chatSelfParticipantType || "").trim();
|
|
537
|
-
var selfId = String(composer.dataset.chatSelfParticipantId || "").trim();
|
|
538
|
-
var mentionOptions = [];
|
|
539
|
-
var seenTokens = {};
|
|
540
|
-
|
|
541
|
-
function addMentionOption(optionData) {
|
|
542
|
-
if (!optionData || !optionData.token) {
|
|
543
|
-
return;
|
|
544
|
-
}
|
|
545
|
-
|
|
546
|
-
var dedupeToken = normalize(optionData.token);
|
|
547
|
-
if (!dedupeToken || seenTokens[dedupeToken]) {
|
|
548
|
-
return;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
seenTokens[dedupeToken] = true;
|
|
552
|
-
mentionOptions.push(optionData);
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
if (canMentionAll) {
|
|
556
|
-
addMentionOption({ token: "@all", label: "All members", kind: "group" });
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
if (canMentionMembers) {
|
|
560
|
-
memberEntries.forEach(function (memberEntry) {
|
|
561
|
-
if (excludeSelf && memberEntry.participantType === selfType && memberEntry.participantId === selfId) {
|
|
562
|
-
return;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
if (!memberEntry.mentionToken) {
|
|
566
|
-
return;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
addMentionOption({
|
|
570
|
-
token: memberEntry.mentionToken,
|
|
571
|
-
label: memberEntry.name || memberEntry.mentionToken,
|
|
572
|
-
kind: "member",
|
|
573
|
-
participant_type: memberEntry.participantType,
|
|
574
|
-
participant_id: memberEntry.participantId
|
|
575
|
-
});
|
|
576
|
-
});
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
if (canMentionRoles && !hideRoles) {
|
|
580
|
-
memberEntries.forEach(function (memberEntry) {
|
|
581
|
-
if (!memberEntry.roleKey) {
|
|
582
|
-
return;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
var roleToken = "@" + memberEntry.roleKey.toUpperCase();
|
|
586
|
-
var roleLabel = (memberEntry.roleName || memberEntry.roleKey) + " role";
|
|
587
|
-
addMentionOption({
|
|
588
|
-
token: roleToken,
|
|
589
|
-
label: roleLabel,
|
|
590
|
-
kind: "role"
|
|
591
|
-
});
|
|
592
|
-
});
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
return mentionOptions;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
function syncComposerMentionOptionsForChat(chatId) {
|
|
599
|
-
var memberList = memberListForChat(chatId);
|
|
600
|
-
if (!memberList) {
|
|
601
|
-
return;
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
var memberEntries = [];
|
|
605
|
-
memberList.querySelectorAll("[data-chat-member-entry='true']").forEach(function (memberNode) {
|
|
606
|
-
var memberEntry = parseMemberEntry(memberNode);
|
|
607
|
-
if (memberEntry) {
|
|
608
|
-
memberEntries.push(memberEntry);
|
|
609
|
-
}
|
|
610
|
-
});
|
|
611
|
-
|
|
612
|
-
document.querySelectorAll("[data-chat-composer]").forEach(function (composer) {
|
|
613
|
-
if (String(composer.dataset.chatId || "").trim() !== String(chatId).trim()) {
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
if (!composer.__chatComposerApi || typeof composer.__chatComposerApi.setMentionOptions !== "function") {
|
|
618
|
-
return;
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
composer.__chatComposerApi.setMentionOptions(mentionOptionsForComposer(composer, memberEntries));
|
|
622
|
-
});
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
function setupMemberManageControlsForChat(chatId) {
|
|
626
|
-
var memberList = memberListForChat(chatId);
|
|
627
|
-
if (!memberList) {
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
memberList.querySelectorAll("[data-chat-member-entry='true']").forEach(function (memberNode) {
|
|
632
|
-
if (!memberNode || memberNode.dataset.chatMemberManageBound === "true") {
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
var toggle = memberNode.querySelector("[data-chat-member-manage-toggle]");
|
|
637
|
-
var panel = memberNode.querySelector("[data-chat-member-manage-panel]");
|
|
638
|
-
if (!toggle || !panel) {
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
memberNode.dataset.chatMemberManageBound = "true";
|
|
643
|
-
panel.hidden = true;
|
|
644
|
-
toggle.setAttribute("aria-expanded", "false");
|
|
645
|
-
|
|
646
|
-
toggle.addEventListener("click", function () {
|
|
647
|
-
if (toggle.disabled) {
|
|
648
|
-
return;
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
var expanded = toggle.getAttribute("aria-expanded") === "true";
|
|
652
|
-
var parentList = memberNode.closest("[data-chat-member-list]");
|
|
653
|
-
if (parentList) {
|
|
654
|
-
parentList.querySelectorAll("[data-chat-member-manage-toggle]").forEach(function (otherToggle) {
|
|
655
|
-
otherToggle.setAttribute("aria-expanded", "false");
|
|
656
|
-
});
|
|
657
|
-
parentList.querySelectorAll("[data-chat-member-manage-panel]").forEach(function (otherPanel) {
|
|
658
|
-
otherPanel.hidden = true;
|
|
659
|
-
});
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
if (expanded) {
|
|
663
|
-
panel.hidden = true;
|
|
664
|
-
toggle.setAttribute("aria-expanded", "false");
|
|
665
|
-
return;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
panel.hidden = false;
|
|
669
|
-
toggle.setAttribute("aria-expanded", "true");
|
|
670
|
-
var roleInput = panel.querySelector("[data-chat-member-role-input]");
|
|
671
|
-
if (roleInput && !roleInput.disabled) {
|
|
672
|
-
roleInput.focus();
|
|
673
|
-
}
|
|
674
|
-
});
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
function syncRoleFormAccessForChat(chatId) {
|
|
679
|
-
var memberList = memberListForChat(chatId);
|
|
680
|
-
var shell = shellForChat(chatId);
|
|
681
|
-
if (!memberList || !shell) {
|
|
682
|
-
return;
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
var canManage = shell.dataset.chatCanManageMemberPermissions === "true";
|
|
686
|
-
var selfType = String(shell.dataset.chatSelfParticipantType || "").trim();
|
|
687
|
-
var selfId = String(shell.dataset.chatSelfParticipantId || "").trim();
|
|
688
|
-
var selfRoleRank = -1;
|
|
689
|
-
|
|
690
|
-
memberList.querySelectorAll("[data-chat-member-entry='true']").forEach(function (memberNode) {
|
|
691
|
-
if (
|
|
692
|
-
String(memberNode.dataset.chatMemberParticipantType || "").trim() === selfType &&
|
|
693
|
-
String(memberNode.dataset.chatMemberParticipantId || "").trim() === selfId
|
|
694
|
-
) {
|
|
695
|
-
var rank = parseInt(memberNode.dataset.chatMemberRoleRank || "-1", 10);
|
|
696
|
-
selfRoleRank = isNaN(rank) ? -1 : rank;
|
|
697
|
-
}
|
|
698
|
-
});
|
|
699
|
-
|
|
700
|
-
memberList.querySelectorAll("[data-chat-member-entry='true']").forEach(function (memberNode) {
|
|
701
|
-
var targetType = String(memberNode.dataset.chatMemberParticipantType || "").trim();
|
|
702
|
-
var targetId = String(memberNode.dataset.chatMemberParticipantId || "").trim();
|
|
703
|
-
var targetRoleRank = parseInt(memberNode.dataset.chatMemberRoleRank || "-1", 10);
|
|
704
|
-
if (isNaN(targetRoleRank)) {
|
|
705
|
-
targetRoleRank = -1;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
var isSelf = targetType === selfType && targetId === selfId;
|
|
709
|
-
var targetManageableByRank = selfRoleRank < 0 || targetRoleRank < selfRoleRank;
|
|
710
|
-
var controlsEnabled = canManage && !isSelf && targetManageableByRank;
|
|
711
|
-
var toggle = memberNode.querySelector("[data-chat-member-manage-toggle]");
|
|
712
|
-
var panel = memberNode.querySelector("[data-chat-member-manage-panel]");
|
|
713
|
-
|
|
714
|
-
memberNode.querySelectorAll("[data-chat-member-role-input], [data-chat-member-role-submit]").forEach(function (control) {
|
|
715
|
-
control.disabled = !controlsEnabled;
|
|
716
|
-
});
|
|
717
|
-
|
|
718
|
-
if (toggle) {
|
|
719
|
-
toggle.disabled = !controlsEnabled;
|
|
720
|
-
if (!controlsEnabled) {
|
|
721
|
-
toggle.setAttribute("aria-expanded", "false");
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
if (panel && !controlsEnabled) {
|
|
726
|
-
panel.hidden = true;
|
|
727
|
-
}
|
|
728
|
-
});
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
function setupMemberListSync(memberList) {
|
|
732
|
-
if (!memberList || memberList.dataset.chatMemberSyncBound === "true") {
|
|
733
|
-
return;
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
var chatId = String(memberList.dataset.chatId || "").trim();
|
|
737
|
-
if (!chatId) {
|
|
738
|
-
return;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
memberList.dataset.chatMemberSyncBound = "true";
|
|
742
|
-
setupMemberManageControlsForChat(chatId);
|
|
743
|
-
syncComposerMentionOptionsForChat(chatId);
|
|
744
|
-
syncRoleFormAccessForChat(chatId);
|
|
745
|
-
|
|
746
|
-
var observer = new MutationObserver(function (mutationRecords) {
|
|
747
|
-
syncInviteOptionsFromMemberMutations(chatId, mutationRecords);
|
|
748
|
-
setupMemberManageControlsForChat(chatId);
|
|
749
|
-
syncComposerMentionOptionsForChat(chatId);
|
|
750
|
-
syncRoleFormAccessForChat(chatId);
|
|
751
|
-
});
|
|
752
|
-
observer.observe(memberList, { childList: true });
|
|
753
|
-
}
|
|
754
|
-
|
|
755
386
|
function setupAllInvitePickers() {
|
|
756
387
|
document.querySelectorAll("[data-chat-invite-form]").forEach(function (form) {
|
|
757
388
|
setupInvitePicker(form);
|
|
758
389
|
});
|
|
759
390
|
}
|
|
760
391
|
|
|
761
|
-
|
|
762
|
-
document.querySelectorAll("[data-chat-member-list]").forEach(setupMemberListSync);
|
|
763
|
-
}
|
|
764
|
-
|
|
392
|
+
namespace.setupInvitePicker = setupInvitePicker;
|
|
765
393
|
namespace.setupAllInvitePickers = setupAllInvitePickers;
|
|
766
|
-
namespace.setupAllMemberListSync = setupAllMemberListSync;
|
|
767
394
|
})(window.TurboChatUI = window.TurboChatUI || {});
|