<commit_before>/* global $, APP, interfaceConfig */

import ConnectionIndicator from './ConnectionIndicator';

import SmallVideo from "./SmallVideo";
import UIUtils from "../util/UIUtil";
import UIEvents from '../../../service/UI/UIEvents';
import JitsiPopover from "../util/JitsiPopover";

const MUTED_DIALOG_BUTTON_VALUES = {
    cancel: 0,
    muted: 1
};

/**
 * Creates new instance of the <tt>RemoteVideo</tt>.
 * @param user {JitsiParticipant} the user for whom remote video instance will
 * be created.
 * @param {VideoLayout} VideoLayout the video layout instance.
 * @param {EventEmitter} emitter the event emitter which will be used by
 * the new instance to emit events.
 * @constructor
 */
function RemoteVideo(user, VideoLayout, emitter) {
    this.user = user;
    this.id = user.getId();
    this.emitter = emitter;
    this.videoSpanId = `participant_${this.id}`;
    SmallVideo.call(this, VideoLayout);
    this.hasRemoteVideoMenu = false;
    this.addRemoteVideoContainer();
    this.connectionIndicator = new ConnectionIndicator(this, this.id);
    this.setDisplayName();
    this.bindHoverHandler();
    this.flipX = false;
    this.isLocal = false;
    this.popupMenuIsHovered = false;
    /**
     * The flag is set to <tt>true</tt> after the 'onplay' event has been
     * triggered on the current video element. It goes back to <tt>false</tt>
     * when the stream is removed. It is used to determine whether the video
     * playback has ever started.
     * @type {boolean}
     */
    this.wasVideoPlayed = false;
    /**
     * The flag is set to <tt>true</tt> if remote participant's video gets muted
     * during his media connection disruption. This is to prevent black video
     * being render on the thumbnail, because even though once the video has
     * been played the image usually remains on the video element it seems that
     * after longer period of the video element being hidden this image can be
     * lost.
     * @type {boolean}
     */
    this.mutedWhileDisconnected = false;
}

RemoteVideo.prototype = Object.create(SmallVideo.prototype);
RemoteVideo.prototype.constructor = RemoteVideo;

RemoteVideo.prototype.addRemoteVideoContainer = function() {
    this.container = RemoteVideo.createContainer(this.videoSpanId);

    this.initBrowserSpecificProperties();

    if (APP.conference.isModerator) {
        this.addRemoteVideoMenu();
    }

    this.VideoLayout.resizeThumbnails(false, true);

    this.addAudioLevelIndicator();

    return this.container;
};

/**
 * Initializes the remote participant popup menu, by specifying previously
 * constructed popupMenuElement, containing all the menu items.
 *
 * @param popupMenuElement a pre-constructed element, containing the menu items
 * to display in the popup
 */
RemoteVideo.prototype._initPopupMenu = function (popupMenuElement) {
    let options = {
        content: popupMenuElement.outerHTML,
        skin: "black",
        hasArrow: false,
        onBeforePosition: el => APP.translation.translateElement(el)
    };
    let element = $("#" + this.videoSpanId + " .remotevideomenu");
    this.popover = new JitsiPopover(element, options);
    this.popover.addOnHoverPopover(isHovered => {
        this.popupMenuIsHovered = isHovered;
        this.updateView();
    });

    // override popover show method to make sure we will update the content
    // before showing the popover
    let origShowFunc = this.popover.show;
    this.popover.show = function () {
        // update content by forcing it, to finish even if popover
        // is not visible
        this.updateRemoteVideoMenu(this.isAudioMuted, true);
        // call the original show, passing its actual this
        origShowFunc.call(this.popover);
    }.bind(this);
};

/**<commit_msg>Removes click handlers when popup is hidden.<commit_after>/* global $, APP, interfaceConfig */

import ConnectionIndicator from './ConnectionIndicator';

import SmallVideo from "./SmallVideo";
import UIUtils from "../util/UIUtil";
import UIEvents from '../../../service/UI/UIEvents';
import JitsiPopover from "../util/JitsiPopover";

const MUTED_DIALOG_BUTTON_VALUES = {
    cancel: 0,
    muted: 1
};

/**
 * Creates new instance of the <tt>RemoteVideo</tt>.
 * @param user {JitsiParticipant} the user for whom remote video instance will
 * be created.
 * @param {VideoLayout} VideoLayout the video layout instance.
 * @param {EventEmitter} emitter the event emitter which will be used by
 * the new instance to emit events.
 * @constructor
 */
function RemoteVideo(user, VideoLayout, emitter) {
    this.user = user;
    this.id = user.getId();
    this.emitter = emitter;
    this.videoSpanId = `participant_${this.id}`;
    SmallVideo.call(this, VideoLayout);
    this.hasRemoteVideoMenu = false;
    this.addRemoteVideoContainer();
    this.connectionIndicator = new ConnectionIndicator(this, this.id);
    this.setDisplayName();
    this.bindHoverHandler();
    this.flipX = false;
    this.isLocal = false;
    this.popupMenuIsHovered = false;
    /**
     * The flag is set to <tt>true</tt> after the 'onplay' event has been
     * triggered on the current video element. It goes back to <tt>false</tt>
     * when the stream is removed. It is used to determine whether the video
     * playback has ever started.
     * @type {boolean}
     */
    this.wasVideoPlayed = false;
    /**
     * The flag is set to <tt>true</tt> if remote participant's video gets muted
     * during his media connection disruption. This is to prevent black video
     * being render on the thumbnail, because even though once the video has
     * been played the image usually remains on the video element it seems that
     * after longer period of the video element being hidden this image can be
     * lost.
     * @type {boolean}
     */
    this.mutedWhileDisconnected = false;
}

RemoteVideo.prototype = Object.create(SmallVideo.prototype);
RemoteVideo.prototype.constructor = RemoteVideo;

RemoteVideo.prototype.addRemoteVideoContainer = function() {
    this.container = RemoteVideo.createContainer(this.videoSpanId);

    this.initBrowserSpecificProperties();

    if (APP.conference.isModerator) {
        this.addRemoteVideoMenu();
    }

    this.VideoLayout.resizeThumbnails(false, true);

    this.addAudioLevelIndicator();

    return this.container;
};

/**
 * Initializes the remote participant popup menu, by specifying previously
 * constructed popupMenuElement, containing all the menu items.
 *
 * @param popupMenuElement a pre-constructed element, containing the menu items
 * to display in the popup
 */
RemoteVideo.prototype._initPopupMenu = function (popupMenuElement) {
    let options = {
        content: popupMenuElement.outerHTML,
        skin: "black",
        hasArrow: false,
        onBeforePosition: el => APP.translation.translateElement(el)
    };
    let element = $("#" + this.videoSpanId + " .remotevideomenu");
    this.popover = new JitsiPopover(element, options);
    this.popover.addOnHoverPopover(isHovered => {
        this.popupMenuIsHovered = isHovered;
        this.updateView();
    });

    // override popover show method to make sure we will update the content
    // before showing the popover
    let origShowFunc = this.popover.show;
    this.popover.show = function () {
        // update content by forcing it, to finish even if popover
        // is not visible
        this.updateRemoteVideoMenu(this.isAudioMuted, true);
        // call the original show, passing its actual this
        origShowFunc.call(this.popover);
    }.bind(this);

    // override popover hide method so we can cleanup click handlers
    let origHideFunc = this.popover.forceHide;
    this.popover.forceHide = function () {
        $(document).off("click", '#mutelink_' + this.id);
        $(document).off("click", '#ejectlink_' + this.id);
        origHideFunc.call(this.popover);
    }.bind(this);
};

/**
{'fraction_non_alphanumeric': 0.10289836729527908, 'fraction_numerical': 0.0005062650297430705, 'mean_word_length': 3.2945652173913045, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3815765', 'n_tokens_mistral': 2253, 'n_tokens_neox': 2205, 'n_words': 693}