hand raised
This commit is contained in:
@@ -2,8 +2,11 @@ local st = require "util.stanza";
|
|||||||
local http = require "net.http";
|
local http = require "net.http";
|
||||||
local jid = require "util.jid";
|
local jid = require "util.jid";
|
||||||
local json = require "util.json";
|
local json = require "util.json";
|
||||||
|
local array = require "util.array";
|
||||||
local util = module:require "util";
|
local util = module:require "util";
|
||||||
local is_admin = util.is_admin;
|
local is_admin = util.is_admin;
|
||||||
|
local is_focus = util.is_focus;
|
||||||
|
local internal_room_jid_match_rewrite = util.internal_room_jid_match_rewrite;
|
||||||
|
|
||||||
local ROLE_JOINING = module:shared("politictalk/roles/joining");
|
local ROLE_JOINING = module:shared("politictalk/roles/joining");
|
||||||
local ROOM_INACTIVE_CALLBACK_URL = module:get_option_string(
|
local ROOM_INACTIVE_CALLBACK_URL = module:get_option_string(
|
||||||
@@ -144,13 +147,48 @@ local function ensure_room_data(room)
|
|||||||
room._data.politictalk_host_jids = room._data.politictalk_host_jids or {};
|
room._data.politictalk_host_jids = room._data.politictalk_host_jids or {};
|
||||||
room._data.politictalk_participant_jids = room._data.politictalk_participant_jids or {};
|
room._data.politictalk_participant_jids = room._data.politictalk_participant_jids or {};
|
||||||
room._data.politictalk_jid_user_ids = room._data.politictalk_jid_user_ids or {};
|
room._data.politictalk_jid_user_ids = room._data.politictalk_jid_user_ids or {};
|
||||||
-- Enables Jitsi AV moderation automatically: hosts can speak, participants
|
|
||||||
-- must be explicitly allowed by a host before they can unmute.
|
|
||||||
room._data.av_can_unmute = false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function enable_audio_moderation_only(room, actor_occupant)
|
||||||
|
if not room or not actor_occupant then
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Avoid Jitsi's av_can_unmute shortcut because it enables audio, video, and desktop moderation together.
|
||||||
|
room.av_moderation = room.av_moderation or {};
|
||||||
|
room.av_moderation_actors = room.av_moderation_actors or {};
|
||||||
|
|
||||||
|
if room.av_moderation.audio then
|
||||||
|
room.av_moderation.video = nil;
|
||||||
|
room.av_moderation.desktop = nil;
|
||||||
|
room.av_moderation_actors.video = nil;
|
||||||
|
room.av_moderation_actors.desktop = nil;
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
room.av_moderation.audio = array();
|
||||||
|
room.av_moderation.video = nil;
|
||||||
|
room.av_moderation.desktop = nil;
|
||||||
|
|
||||||
|
for _, room_occupant in room:each_occupant() do
|
||||||
|
if room:get_role(room_occupant.nick) == "moderator" and not is_focus(room_occupant.nick) then
|
||||||
|
room.av_moderation.audio:push(internal_room_jid_match_rewrite(room_occupant.nick));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
room.jitsiMetadata = room.jitsiMetadata or {};
|
||||||
|
room.jitsiMetadata.startMuted = room.jitsiMetadata.startMuted or {};
|
||||||
|
room.av_moderation_startMuted_restore = room.av_moderation_startMuted_restore or {};
|
||||||
|
room.av_moderation_startMuted_restore.audio = room.jitsiMetadata.startMuted.audio;
|
||||||
|
room.jitsiMetadata.startMuted.audio = true;
|
||||||
|
|
||||||
|
room.av_moderation_actors.audio = actor_occupant.nick;
|
||||||
|
room.av_moderation_actors.video = nil;
|
||||||
|
room.av_moderation_actors.desktop = nil;
|
||||||
|
end
|
||||||
|
|
||||||
local function update_room_role_lists(room, user_id, is_moderator)
|
local function update_room_role_lists(room, user_id, is_moderator)
|
||||||
if not room or not user_id then
|
if not room or not user_id then
|
||||||
return;
|
return;
|
||||||
@@ -613,10 +651,11 @@ module:hook("muc-occupant-joined", function(event)
|
|||||||
mark_host(room, occupant, role.user_id);
|
mark_host(room, occupant, role.user_id);
|
||||||
update_room_role_lists(room, role.user_id, true);
|
update_room_role_lists(room, role.user_id, true);
|
||||||
room:set_affiliation(true, occupant.bare_jid, "owner");
|
room:set_affiliation(true, occupant.bare_jid, "owner");
|
||||||
|
enable_audio_moderation_only(room, occupant);
|
||||||
remove_duplicate_user_occupants(room, occupant, role.user_id);
|
remove_duplicate_user_occupants(room, occupant, role.user_id);
|
||||||
module:log(
|
module:log(
|
||||||
"info",
|
"info",
|
||||||
"PoliticTalk host joined as moderator with AV moderation: %s room=%s",
|
"PoliticTalk host joined as moderator with audio moderation: %s room=%s",
|
||||||
tostring(role.user_id),
|
tostring(role.user_id),
|
||||||
tostring(room.jid)
|
tostring(room.jid)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -466,6 +466,10 @@
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.politictalk-hidden-av-request {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
html:not(.politictalk-direct-access-blocked),
|
html:not(.politictalk-direct-access-blocked),
|
||||||
html:not(.politictalk-direct-access-blocked) body,
|
html:not(.politictalk-direct-access-blocked) body,
|
||||||
@@ -1144,6 +1148,141 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizePoliticTalkText(value) {
|
||||||
|
return String(value || '').replace(/\s+/g, ' ').trim().toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPoliticTalkModerationAction(text) {
|
||||||
|
return text.indexOf('allow audio') !== -1
|
||||||
|
|| text.indexOf('allow video') !== -1
|
||||||
|
|| text.indexOf('allow screen sharing') !== -1
|
||||||
|
|| text.indexOf('allow all') !== -1
|
||||||
|
|| text.indexOf('unmute audio') !== -1
|
||||||
|
|| text.indexOf('unmute video') !== -1
|
||||||
|
|| text.indexOf('start screen sharing') !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findPoliticTalkNotificationCard(element) {
|
||||||
|
var current = element;
|
||||||
|
|
||||||
|
while (current && current !== document.body) {
|
||||||
|
if (isPoliticTalkRaisedHandCard(current)) {
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPoliticTalkRaisedHandCard(element) {
|
||||||
|
if (!element || element === document.body) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var text = normalizePoliticTalkText(element.textContent);
|
||||||
|
var rect = element.getBoundingClientRect();
|
||||||
|
|
||||||
|
return text.indexOf('would like to participate') !== -1
|
||||||
|
&& rect.width > 120
|
||||||
|
&& rect.width < 560
|
||||||
|
&& rect.height > 40
|
||||||
|
&& rect.height < 280;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyPoliticTalkModerationNotificationPolicy() {
|
||||||
|
if (directAccessBlocked || !document.body) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var isHost = isPoliticTalkHost();
|
||||||
|
var controls = document.querySelectorAll('button, [role="button"], a');
|
||||||
|
var handledCards = [];
|
||||||
|
|
||||||
|
controls.forEach(function(control) {
|
||||||
|
var actionText = normalizePoliticTalkText([
|
||||||
|
control.getAttribute('aria-label'),
|
||||||
|
control.getAttribute('title'),
|
||||||
|
control.textContent
|
||||||
|
].join(' '));
|
||||||
|
|
||||||
|
if (!isPoliticTalkModerationAction(actionText)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var card = findPoliticTalkNotificationCard(control);
|
||||||
|
|
||||||
|
if (!card || handledCards.indexOf(card) !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handledCards.push(card);
|
||||||
|
|
||||||
|
var cardText = normalizePoliticTalkText(card.textContent);
|
||||||
|
var isAudioCard = cardText.indexOf('allow audio') !== -1
|
||||||
|
|| cardText.indexOf('unmute audio') !== -1;
|
||||||
|
var isVideoOrDesktopCard = cardText.indexOf('allow video') !== -1
|
||||||
|
|| cardText.indexOf('allow screen sharing') !== -1
|
||||||
|
|| cardText.indexOf('unmute video') !== -1
|
||||||
|
|| cardText.indexOf('start screen sharing') !== -1;
|
||||||
|
|
||||||
|
card.classList.toggle('politictalk-hidden-av-request', !isHost || isVideoOrDesktopCard || !isAudioCard);
|
||||||
|
card.setAttribute('aria-hidden', (!isHost || isVideoOrDesktopCard || !isAudioCard) ? 'true' : 'false');
|
||||||
|
|
||||||
|
card.querySelectorAll('button, [role="button"], a').forEach(function(cardControl) {
|
||||||
|
var cardControlText = normalizePoliticTalkText([
|
||||||
|
cardControl.getAttribute('aria-label'),
|
||||||
|
cardControl.getAttribute('title'),
|
||||||
|
cardControl.textContent
|
||||||
|
].join(' '));
|
||||||
|
|
||||||
|
if (cardControlText.indexOf('allow all') !== -1) {
|
||||||
|
cardControl.classList.add('politictalk-hidden-av-request');
|
||||||
|
cardControl.setAttribute('aria-hidden', 'true');
|
||||||
|
cardControl.setAttribute('tabindex', '-1');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isHost) {
|
||||||
|
document.querySelectorAll('[role="alert"], [class*="notification"], [class*="Notification"], div')
|
||||||
|
.forEach(function(candidate) {
|
||||||
|
if (isPoliticTalkRaisedHandCard(candidate)) {
|
||||||
|
candidate.classList.add('politictalk-hidden-av-request');
|
||||||
|
candidate.setAttribute('aria-hidden', 'true');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mountPoliticTalkModerationNotificationPolicy() {
|
||||||
|
applyPoliticTalkModerationNotificationPolicy();
|
||||||
|
|
||||||
|
if (window.politicTalkModerationNotificationObserver || !document.body) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.politicTalkModerationNotificationObserver = new MutationObserver(function() {
|
||||||
|
window.cancelAnimationFrame(window.politicTalkModerationNotificationFrame);
|
||||||
|
window.politicTalkModerationNotificationFrame = window.requestAnimationFrame(
|
||||||
|
applyPoliticTalkModerationNotificationPolicy
|
||||||
|
);
|
||||||
|
});
|
||||||
|
window.politicTalkModerationNotificationObserver.observe(document.body, {
|
||||||
|
attributes: true,
|
||||||
|
attributeFilter: [ 'aria-label', 'class', 'style', 'title' ],
|
||||||
|
childList: true,
|
||||||
|
characterData: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
|
||||||
|
window.clearInterval(window.politicTalkModerationNotificationInterval);
|
||||||
|
window.politicTalkModerationNotificationInterval = window.setInterval(function() {
|
||||||
|
applyPoliticTalkModerationNotificationPolicy();
|
||||||
|
}, 800);
|
||||||
|
}
|
||||||
|
|
||||||
function mountPoliticTalkLogo() {
|
function mountPoliticTalkLogo() {
|
||||||
if (!document.body || document.getElementById('politictalk-room-logo')) {
|
if (!document.body || document.getElementById('politictalk-room-logo')) {
|
||||||
return;
|
return;
|
||||||
@@ -1222,6 +1361,7 @@
|
|||||||
mountHostHangupPolicy();
|
mountHostHangupPolicy();
|
||||||
mountMobileToolbarPositioning();
|
mountMobileToolbarPositioning();
|
||||||
mountPoliticTalkStageBrandInset();
|
mountPoliticTalkStageBrandInset();
|
||||||
|
mountPoliticTalkModerationNotificationPolicy();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
mountPoliticTalkDocumentTitle();
|
mountPoliticTalkDocumentTitle();
|
||||||
@@ -1230,6 +1370,7 @@
|
|||||||
mountHostHangupPolicy();
|
mountHostHangupPolicy();
|
||||||
mountMobileToolbarPositioning();
|
mountMobileToolbarPositioning();
|
||||||
mountPoliticTalkStageBrandInset();
|
mountPoliticTalkStageBrandInset();
|
||||||
|
mountPoliticTalkModerationNotificationPolicy();
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user