diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfdb8b7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf diff --git a/.gitignore b/.gitignore index 6fb67f7..223d757 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ local/docker-jitsi-meet/ local/.jitsi-meet-cfg/ local/*.zip local/.release +WINDOWS_LOCAL_SETUP.md # Local-only shell/environment files. local/.env diff --git a/scripts/local-jitsi-env.sh b/scripts/local-jitsi-env.sh new file mode 100644 index 0000000..67f8536 --- /dev/null +++ b/scripts/local-jitsi-env.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +local_jitsi_config_dir() { + local root_dir="$1" + local local_dir="$root_dir/local" + + if [[ -n "${POLITICTALK_LOCAL_JITSI_CONFIG_DIR:-}" ]]; then + printf '%s\n' "$POLITICTALK_LOCAL_JITSI_CONFIG_DIR" + return + fi + + if grep -qi microsoft /proc/version 2>/dev/null && [[ "$root_dir" == /mnt/* ]]; then + printf '%s\n' "$HOME/politictalk-jitsi-cfg" + return + fi + + printf '%s\n' "$local_dir/.jitsi-meet-cfg" +} + +local_jitsi_set_env() { + local key="$1" + local value="$2" + local file="$3" + + if grep -qE "^#?${key}=" "$file"; then + perl -0pi -e "s|^#?${key}=.*|${key}=${value}|m" "$file" + else + printf '%s=%s\n' "$key" "$value" >> "$file" + fi +} diff --git a/scripts/local-jitsi-setup.sh b/scripts/local-jitsi-setup.sh index 1e3b9e1..bf728ce 100755 --- a/scripts/local-jitsi-setup.sh +++ b/scripts/local-jitsi-setup.sh @@ -5,9 +5,12 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" LOCAL_DIR="$ROOT_DIR/local" STACK_DIR="$LOCAL_DIR/docker-jitsi-meet" -CONFIG_DIR="$LOCAL_DIR/.jitsi-meet-cfg" RELEASE_FILE="$LOCAL_DIR/.release" +source "$SCRIPT_DIR/local-jitsi-env.sh" + +CONFIG_DIR="$(local_jitsi_config_dir "$ROOT_DIR")" + HTTP_PORT="${HTTP_PORT:-8000}" HTTPS_PORT="${HTTPS_PORT:-8443}" PUBLIC_URL="${PUBLIC_URL:-https://localhost:${HTTPS_PORT}}" @@ -18,11 +21,7 @@ set_env() { local value="$2" local file="$STACK_DIR/.env" - if grep -qE "^#?${key}=" "$file"; then - perl -0pi -e "s|^#?${key}=.*|${key}=${value}|m" "$file" - else - printf '%s=%s\n' "$key" "$value" >> "$file" - fi + local_jitsi_set_env "$key" "$value" "$file" } mkdir -p "$LOCAL_DIR" diff --git a/scripts/local-jitsi-sync.sh b/scripts/local-jitsi-sync.sh index e27860d..ea86cd1 100755 --- a/scripts/local-jitsi-sync.sh +++ b/scripts/local-jitsi-sync.sh @@ -5,7 +5,10 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" LOCAL_DIR="$ROOT_DIR/local" STACK_DIR="$LOCAL_DIR/docker-jitsi-meet" -CONFIG_DIR="$LOCAL_DIR/.jitsi-meet-cfg" + +source "$SCRIPT_DIR/local-jitsi-env.sh" + +CONFIG_DIR="$(local_jitsi_config_dir "$ROOT_DIR")" if [[ ! -d "$STACK_DIR" ]]; then echo "Missing $STACK_DIR. Run ./scripts/local-jitsi-setup.sh first." @@ -14,6 +17,10 @@ fi mkdir -p "$CONFIG_DIR"/{web,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri} +if [[ -f "$STACK_DIR/.env" ]]; then + local_jitsi_set_env CONFIG "$CONFIG_DIR" "$STACK_DIR/.env" +fi + cp "$LOCAL_DIR/custom-config.js" "$CONFIG_DIR/web/custom-config.js" cp "$LOCAL_DIR/custom-interface_config.js" "$CONFIG_DIR/web/custom-interface_config.js" cp "$LOCAL_DIR/docker-compose.override.yml" "$STACK_DIR/docker-compose.override.yml" @@ -23,3 +30,4 @@ find "$ROOT_DIR/prosody-plugins" -maxdepth 1 -name 'mod_politictalk_*.lua' -type done echo "Synced PoliticTalk local overrides into Docker Jitsi runtime." +echo "Using Docker Jitsi config: $CONFIG_DIR" diff --git a/web/plugin.head.html b/web/plugin.head.html index f6603b7..aeca798 100644 --- a/web/plugin.head.html +++ b/web/plugin.head.html @@ -273,7 +273,15 @@ background: var(--politictalk-avatar-background, #63477a) !important; background-color: var(--politictalk-avatar-background, #63477a) !important; border-radius: 50% !important; + color: #fff !important; overflow: hidden !important; + text-shadow: none !important; + } + + html:not(.politictalk-direct-access-blocked) #participants-pane .politictalk-avatar-themed *:not(img):not(picture):not(svg), + html:not(.politictalk-direct-access-blocked) [class*="participantsPane"] .politictalk-avatar-themed *:not(img):not(picture):not(svg) { + color: #fff !important; + text-shadow: none !important; } html:not(.politictalk-direct-access-blocked) #participants-pane .politictalk-avatar-themed > img, @@ -1955,6 +1963,28 @@ }) || null; } + function getPoliticTalkInitialsTextTargets(element) { + if (!element) { + return []; + } + + var targets = [element]; + + Array.prototype.slice.call(element.querySelectorAll('*')).forEach(function(candidate) { + if (candidate.querySelector('img, canvas, video, picture, svg')) { + return; + } + + var text = String(candidate.textContent || '').replace(/\s+/g, '').trim(); + + if (text && text.length <= 4) { + targets.push(candidate); + } + }); + + return targets; + } + function isPoliticTalkTransparentTileLayer(element, tile) { if (!element || element === tile || element.classList.contains('politictalk-avatar-shell')) { return false; @@ -1983,6 +2013,97 @@ && backgroundColor !== 'transparent'; } + function getPoliticTalkTileAvatarMaxSize(tile) { + if (!tile) { + return null; + } + + var tileRect = tile.getBoundingClientRect(); + + if (!tileRect.width || !tileRect.height) { + return null; + } + + var maxByHeight = Math.max(40, tileRect.height * 0.48); + var maxByWidth = Math.max(40, tileRect.width * 0.48); + var responsiveCap = tileRect.width <= 480 ? 132 : 180; + + return Math.floor(Math.min(maxByWidth, maxByHeight, responsiveCap)); + } + + function clampPoliticTalkTileAvatarSize(tile, avatarContainer) { + var maxSize = getPoliticTalkTileAvatarMaxSize(tile); + + if (!maxSize || !avatarContainer) { + return; + } + + setPoliticTalkImportantStyle(avatarContainer, 'aspect-ratio', '1 / 1'); + setPoliticTalkImportantStyle(avatarContainer, 'height', maxSize + 'px'); + setPoliticTalkImportantStyle(avatarContainer, 'max-height', maxSize + 'px'); + setPoliticTalkImportantStyle(avatarContainer, 'max-width', maxSize + 'px'); + setPoliticTalkImportantStyle(avatarContainer, 'width', maxSize + 'px'); + + Array.prototype.slice.call(avatarContainer.querySelectorAll('img, canvas')).forEach(function(media) { + setPoliticTalkImportantStyle(media, 'height', '100%'); + setPoliticTalkImportantStyle(media, 'max-height', '100%'); + setPoliticTalkImportantStyle(media, 'max-width', '100%'); + setPoliticTalkImportantStyle(media, 'object-fit', 'cover'); + setPoliticTalkImportantStyle(media, 'width', '100%'); + }); + + var initialsTarget = getPoliticTalkInitialsAvatarTarget(avatarContainer); + + if (!initialsTarget) { + return; + } + + var initialsText = String(initialsTarget.textContent || '').replace(/\s+/g, '').trim(); + var maxFontSize = Math.max(18, Math.floor(maxSize * (initialsText.length > 1 ? 0.36 : 0.46))); + + setPoliticTalkImportantStyle(initialsTarget, 'align-items', 'center'); + setPoliticTalkImportantStyle(initialsTarget, 'aspect-ratio', '1 / 1'); + setPoliticTalkImportantStyle(initialsTarget, 'box-sizing', 'border-box'); + setPoliticTalkImportantStyle(initialsTarget, 'color', '#fff'); + setPoliticTalkImportantStyle(initialsTarget, 'display', 'flex'); + setPoliticTalkImportantStyle(initialsTarget, 'height', maxSize + 'px'); + setPoliticTalkImportantStyle(initialsTarget, 'justify-content', 'center'); + setPoliticTalkImportantStyle(initialsTarget, 'line-height', '1'); + setPoliticTalkImportantStyle(initialsTarget, 'max-height', maxSize + 'px'); + setPoliticTalkImportantStyle(initialsTarget, 'max-width', maxSize + 'px'); + setPoliticTalkImportantStyle(initialsTarget, 'padding', '0'); + setPoliticTalkImportantStyle(initialsTarget, 'text-align', 'center'); + setPoliticTalkImportantStyle(initialsTarget, 'text-shadow', 'none'); + setPoliticTalkImportantStyle(initialsTarget, 'width', maxSize + 'px'); + + getPoliticTalkInitialsTextTargets(initialsTarget).forEach(function(textTarget) { + var isRootTarget = textTarget === initialsTarget; + + setPoliticTalkImportantStyle(textTarget, 'align-items', 'center'); + setPoliticTalkImportantStyle(textTarget, 'box-sizing', 'border-box'); + setPoliticTalkImportantStyle(textTarget, 'color', '#fff'); + setPoliticTalkImportantStyle(textTarget, 'display', 'flex'); + setPoliticTalkImportantStyle(textTarget, 'font-size', maxFontSize + 'px'); + setPoliticTalkImportantStyle(textTarget, 'justify-content', 'center'); + setPoliticTalkImportantStyle(textTarget, 'letter-spacing', '0'); + setPoliticTalkImportantStyle(textTarget, 'line-height', '1'); + setPoliticTalkImportantStyle(textTarget, 'margin', '0'); + setPoliticTalkImportantStyle(textTarget, 'padding', '0'); + setPoliticTalkImportantStyle(textTarget, 'text-align', 'center'); + setPoliticTalkImportantStyle(textTarget, 'text-shadow', 'none'); + setPoliticTalkImportantStyle(textTarget, 'white-space', 'nowrap'); + + if (!isRootTarget) { + setPoliticTalkImportantStyle(textTarget, 'height', '100%'); + setPoliticTalkImportantStyle(textTarget, 'left', 'auto'); + setPoliticTalkImportantStyle(textTarget, 'position', 'static'); + setPoliticTalkImportantStyle(textTarget, 'top', 'auto'); + setPoliticTalkImportantStyle(textTarget, 'transform', 'none'); + setPoliticTalkImportantStyle(textTarget, 'width', '100%'); + } + }); + } + function centerPoliticTalkTileAvatar(tile) { if (!tile) { return; @@ -2005,6 +2126,7 @@ setPoliticTalkImportantStyle(candidate, 'right', 'auto'); setPoliticTalkImportantStyle(candidate, 'top', '50%'); setPoliticTalkImportantStyle(candidate, 'transform', 'translate(-50%, -50%)'); + clampPoliticTalkTileAvatarSize(tile, candidate); }); }