diff --git a/analytics.js b/analytics.js deleted file mode 100644 index 07ea7184f..000000000 --- a/analytics.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Google Analytics - */ -(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) - })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); - ga('create', 'UA-319188-14', 'jit.si'); - ga('send', 'pageview'); \ No newline at end of file diff --git a/app.js b/app.js deleted file mode 100644 index 01beff590..000000000 --- a/app.js +++ /dev/null @@ -1,55 +0,0 @@ -/* jshint -W117 */ -/* application specific logic */ - -var APP = -{ - init: function () { - this.UI = require("./modules/UI/UI"); - this.API = require("./modules/API/API"); - this.connectionquality = require("./modules/connectionquality/connectionquality"); - this.statistics = require("./modules/statistics/statistics"); - this.RTC = require("./modules/RTC/RTC"); - this.desktopsharing = require("./modules/desktopsharing/desktopsharing"); - this.xmpp = require("./modules/xmpp/xmpp"); - this.keyboardshortcut = require("./modules/keyboardshortcut/keyboardshortcut"); - this.translation = require("./modules/translation/translation"); - this.settings = require("./modules/settings/Settings"); - this.DTMF = require("./modules/DTMF/DTMF"); - this.members = require("./modules/members/MemberList"); - } -}; - -function init() { - - APP.desktopsharing.init(); - APP.RTC.start(); - APP.xmpp.start(); - APP.statistics.start(); - APP.connectionquality.init(); - APP.keyboardshortcut.init(); - APP.members.start(); -} - - -$(document).ready(function () { - - var URLProcessor = require("./modules/URLProcessor/URLProcessor"); - URLProcessor.setConfigParametersFromUrl(); - APP.init(); - - APP.translation.init(); - - if(APP.API.isEnabled()) - APP.API.init(); - - APP.UI.start(init); - -}); - -$(window).bind('beforeunload', function () { - if(APP.API.isEnabled()) - APP.API.dispose(); -}); - -module.exports = APP; - diff --git a/bump-js-versions.sh b/bump-js-versions.sh deleted file mode 100755 index e7d9aee53..000000000 --- a/bump-js-versions.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -if ! which git > /dev/null 2>&1 ;then - echo "Cannot find git executable, not bumping js versions." - exit -fi -if ! git status > /dev/null 2>&1 ;then - echo "Not a git repository, not bumping js versions." - exit -fi - -# This script finds all js files included from index.html which have been -# modified and bumps their version (the value of the "v" parameter used -# in index.html) - -# contents of index.html at HEAD (excluding not-committed changes) -index=`git show HEAD:index.html` - -# js files included from index.html. The sort needed for comm -jsfiles=.bump-js-versions-jsfiles.tmp -echo "$index" | grep ' -- -+ - - - - - - -- -+ - - - diff --git a/debian/patches/series b/debian/patches/series deleted file mode 100644 index 097ce197d..000000000 --- a/debian/patches/series +++ /dev/null @@ -1 +0,0 @@ -jquery-package diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in deleted file mode 100644 index 3458b92cf..000000000 --- a/debian/po/POTFILES.in +++ /dev/null @@ -1 +0,0 @@ -[type: gettext/rfc822deb] jitsi-meet.templates diff --git a/debian/po/templates.pot b/debian/po/templates.pot deleted file mode 100644 index d3933e730..000000000 --- a/debian/po/templates.pot +++ /dev/null @@ -1,98 +0,0 @@ -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: jitsi-meet\n" -"Report-Msgid-Bugs-To: jitsi-meet@packages.debian.org\n" -"POT-Creation-Date: 2014-09-03 17:26+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: 8bit\n" - -#. Type: select -#. Choices -#: ../jitsi-meet.templates:1001 -msgid "Self-signed certificate will be generated" -msgstr "" - -#. Type: select -#. Choices -#: ../jitsi-meet.templates:1001 -msgid "A certificate is available and the files are uploaded on the server" -msgstr "" - -#. Type: select -#. Description -#: ../jitsi-meet.templates:1002 -msgid "SSL certificate for the Jitsi Meet instance" -msgstr "" - -#. Type: select -#. Description -#: ../jitsi-meet.templates:1002 -msgid "" -"Jitsi Meet is best to be set up with an SSL certificate. Having no " -"certificate, a self-signed one will be generated. Having a certificate " -"signed by a recognised CA, it can be uploaded on the server and point its " -"location. The default filenames will be /etc/ssl/--domain.name--.key for the " -"key and /etc/ssl/--domain.name--.crt for the certificate." -msgstr "" - -#. Type: string -#. Description -#: ../jitsi-meet.templates:2001 -msgid "Full local server path to the SSL key file:" -msgstr "" - -#. Type: string -#. Description -#: ../jitsi-meet.templates:2001 -msgid "" -"The full path to the SSL key file on the server. If it has not been " -"uploaded, now is a good time to do so." -msgstr "" - -#. Type: string -#. Description -#: ../jitsi-meet.templates:3001 -msgid "Full local server path to the SSL certificate file:" -msgstr "" - -#. Type: string -#. Description -#: ../jitsi-meet.templates:3001 -msgid "" -"The full path to the SSL certificate file on the server. If you haven't " -"uploaded it, now is a good time to upload it in another console." -msgstr "" - -#. Type: string -#. Description -#: ../jitsi-meet.templates:4001 -msgid "The hostname of the current installation:" -msgstr "" - -#. Type: string -#. Description -#: ../jitsi-meet.templates:4001 -msgid "" -"The value for the hostname that is set in Jitsi Videobridge installation." -msgstr "" - - -#. Type: string -#. Description -#: ../jitsi-meet.templates:5001 -msgid "for internal use" -msgstr "" - -#. Type: string -#. Description -#: ../jitsi-meet.templates:5001 -msgid "" -"Jitsi Videobridge installation can use its internal jetty to serve static meet pages." -msgstr "" diff --git a/debian/rules b/debian/rules deleted file mode 100755 index 71e2450b9..000000000 --- a/debian/rules +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/make -f - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -%: - dh $@ - -# we skip making Makefile exists for updating browserify modules when developing -override_dh_auto_build: - -override_dh_install: - dh_installdirs - dh_install -X/config.js - yui-compressor -o debian/jitsi-meet/usr/share/jitsi-meet/libs/strophe/strophe.caps.jsonly.min.js \ - debian/missing-source/libs/strophe/strophe.caps.jsonly.js - yui-compressor -o debian/jitsi-meet/usr/share/jitsi-meet/libs/strophe/strophe.disco.min.js \ - debian/missing-source/libs/strophe/sha1.js \ - debian/missing-source/libs/strophe/strophe.disco.js diff --git a/debian/source/format b/debian/source/format deleted file mode 100644 index 163aaf8d8..000000000 --- a/debian/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/debian/watch b/debian/watch deleted file mode 100644 index e33c057c7..000000000 --- a/debian/watch +++ /dev/null @@ -1,2 +0,0 @@ -version=3 -opts="uversionmangle=s/^/1.0./" https://github.com/jitsi/jitsi-meet/releases/ /jitsi/jitsi-meet/archive/(\S+)\.tar\.gz \ No newline at end of file diff --git a/doc/adding-an-icon.md b/doc/adding-an-icon.md deleted file mode 100644 index be19a6b5f..000000000 --- a/doc/adding-an-icon.md +++ /dev/null @@ -1,12 +0,0 @@ -### Adding an icon to the font file (e.g. for the floating menu) -1. Go to https://icomoon.io/app/ -2. Go to "Manage Projects" from the menu on the top left. -3. Use "Import project" and select fonts/selection.json from Jitsi Meet. -4. Import icons (e.g. svg files) using the "import items" button. -5. Go to "generate font" and make sure the identifiers for the new icons are correct. -6. Download the result in a zip file using the "download" button. -7. Copy selection.json and fonts/jitsi.* from the zip file to fonts/ in Jitsi Meet -8. Copy the class for the new icon from style.css in the zip file to css/font.css in Jitsi Meet (do *not* copy the whole file) - -Sample commit: https://github.com/jitsi/jitsi-meet/commit/68bc819b89aec12364fcf07b81efa83a1900eed6 - diff --git a/doc/api.md b/doc/api.md deleted file mode 100644 index 139729904..000000000 --- a/doc/api.md +++ /dev/null @@ -1,174 +0,0 @@ -Jitsi Meet API -============ - -You can use Jitsi Meet API to embed Jitsi Meet in to your application. - -Installation -========== - -To embed Jitsi Meet in your application you need to add Jitsi Meet API library -```javascript - -``` - -The next step for embedding Jitsi Meet is to create the Jitsi Meet API object -```javascript - -``` -You can paste that lines in your html code where you want to be placed the Jitsi Meet conference -or you can specify the parent HTML element for the Jitsi Meet conference in the JitsiMeetExternalAPI -constructor. -```javascript - var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement); -``` -If you don't specify room the user will enter in new conference with random room name. - -You can enable the "film strip only" mode(only the small videos are visible) by setting 6th parameter to ```true```: -```javascript - var api = new JitsiMeetExternalAPI(domain, room, width, height, htmlElement, true); -``` - -Controlling embedded Jitsi Meet Conference -========= - -You can control the embedded Jitsi Meet conference using the JitsiMeetExternalAPI object. - -You can send command to Jitsi Meet conference using ```executeCommand```. -``` -api.executeCommand(command, arguments) -``` -The ```command``` parameter is String object with the name of the command. -The ```arguments``` parameter is array with the arguments required by the command. -If no arguments are required by the command this parameter can be omitted or you can pass empty array. -Currently we support the following commands: - - -* **displayName** - sets the display name of the local participant. This command requires one argument - -the new display name to be set -``` -api.executeCommand('displayName', ['New Nickname']); -``` -* **toggleAudio** - mutes / unmutes the audio for the local participant. No arguments are required. -``` -api.executeCommand('toggleAudio', []) -``` -* **toggleVideo** - mutes / unmutes the video for the local participant. No arguments are required. -``` -api.executeCommand('toggleVideo', []) -``` -* **toggleFilmStrip** - hides / shows the film strip. No arguments are required. -``` -api.executeCommand('filmStrip', []) -``` -* **toggleChat** - hides / shows the chat. No arguments are required. -``` -api.executeCommand('toggleChat', []) -``` -* **toggleContactList** - hides / shows the contact list. No arguments are required. -``` -api.executeCommand('toggleContactList', []) -``` - -You can also execute multiple commands using the method ```executeCommands```. -``` -api.executeCommands(commands) -``` -The ```commands``` parameter is object with keys the names of the commands and values the arguments for the -commands. - -``` -api.executeCommands({displayName: ['nickname'], toggleAudio: []}); -``` - -You can add event listeners to the embedded Jitsi Meet using ```addEventListener``` method. -``` -api.addEventListener(event, listener) -``` -The ```event``` parameter is String object with the name of the event. -The ```listener``` paramenter is Function object with one argument that will be notified when the event occurs -with data related to the event. - -Currently we support the following events: - -* **incomingMessage** - event notifications about incoming -messages. The listener will receive object with the following structure: -``` -{ -"from": from,//JID of the user that sent the message -"nick": nick,//the nickname of the user that sent the message -"message": txt//the text of the message -} -``` -* **outgoingMessage** - event notifications about outgoing -messages. The listener will receive object with the following structure: -``` -{ -"message": txt//the text of the message -} -``` -* **displayNameChanged** - event notifications about display name -change. The listener will receive object with the following structure: -``` -{ -jid: jid,//the JID of the participant that changed his display name -displayname: displayName //the new display name -} -``` -* **participantJoined** - event notifications about new participant. -The listener will receive object with the following structure: -``` -{ -jid: jid //the jid of the participant -} -``` -* **participantLeft** - event notifications about participant that left room. -The listener will receive object with the following structure: -``` -{ -jid: jid //the jid of the participant -} -``` - -You can also add multiple event listeners by using ```addEventListeners```. -This method requires one argument of type Object. The object argument must -have keys with the names of the events and values the listeners of the events. - -``` -function incomingMessageListener(object) -{ -... -} - -function outgoingMessageListener(object) -{ -... -} - -api.addEventListeners({ - incomingMessage: incomingMessageListener, - outgoingMessage: outgoingMessageListener}) -``` - -If you want to remove a listener you can use ```removeEventListener``` method with argument the name of the event. -``` -api.removeEventListener("incomingMessage"); -``` - -If you want to remove more than one event you can use ```removeEventListeners``` method with argument - array with the names of the events. -``` -api.removeEventListeners(["incomingMessage", "outgoingMessageListener"]); -``` - -You can remove the embedded Jitsi Meet Conference with the following code: -``` -api.dispose() -``` - -It is a good practice to remove the conference before the page is unloaded. \ No newline at end of file diff --git a/doc/debian/jitsi-meet-prosody/README b/doc/debian/jitsi-meet-prosody/README deleted file mode 100644 index d141f6b71..000000000 --- a/doc/debian/jitsi-meet-prosody/README +++ /dev/null @@ -1 +0,0 @@ -Prosody configuration for Jitsi Meet diff --git a/doc/debian/jitsi-meet-prosody/prosody.cfg.lua-jvb.example b/doc/debian/jitsi-meet-prosody/prosody.cfg.lua-jvb.example deleted file mode 100644 index 9874f3940..000000000 --- a/doc/debian/jitsi-meet-prosody/prosody.cfg.lua-jvb.example +++ /dev/null @@ -1,28 +0,0 @@ -VirtualHost "jitmeet.example.com" - -- enabled = false -- Remove this line to enable this host - authentication = "anonymous" - -- Assign this host a certificate for TLS, otherwise it would use the one - -- set in the global section (if any). - -- Note that old-style SSL on port 5223 only supports one certificate, and will always - -- use the global one. - ssl = { - key = "/etc/prosody/certs/jitmeet.example.com.key"; - certificate = "/etc/prosody/certs/jitmeet.example.com.crt"; - } - -- we need bosh - modules_enabled = { - "bosh"; - "pubsub"; - } - -Component "conference.jitmeet.example.com" "muc" -admins = { "focusUser@auth.jitmeet.example.com" } - -Component "jitsi-videobridge.jitmeet.example.com" - component_secret = "jitmeetSecret" - -VirtualHost "auth.jitmeet.example.com" - authentication = "internal_plain" - -Component "focus.jitmeet.example.com" - component_secret = "focusSecret" diff --git a/doc/debian/jitsi-meet/README b/doc/debian/jitsi-meet/README deleted file mode 100644 index a198dcae3..000000000 --- a/doc/debian/jitsi-meet/README +++ /dev/null @@ -1,13 +0,0 @@ -Jitsi Meet - -==== - -A WebRTC-powered multi-user videochat. For a live demo, check out either -https://meet.estos.de/ or https://meet.jit.si/. - -Built using colibri.js[0] and strophe.jingle[1], powered by the jitsi-videobridge[2] - - -[0] https://github.com/ESTOS/colibri.js -[1] https://github.com/ESTOS/strophe.jingle -[3] https://github.com/jitsi/jitsi-videobridge diff --git a/doc/debian/jitsi-meet/jitsi-meet.example b/doc/debian/jitsi-meet/jitsi-meet.example deleted file mode 100644 index 0ab36315d..000000000 --- a/doc/debian/jitsi-meet/jitsi-meet.example +++ /dev/null @@ -1,36 +0,0 @@ -server_names_hash_bucket_size 64; - -server { - listen 80; - server_name jitsi-meet.example.com; - return 301 https://$host$request_uri; -} -server { - listen 443 ssl; - server_name jitsi-meet.example.com; - - ssl_certificate /var/lib/prosody/jitsi-meet.example.com.crt; - ssl_certificate_key /var/lib/prosody/jitsi-meet.example.com.key; - - root /usr/share/jitsi-meet; - index index.html index.htm; - - location /config.js { - alias /etc/jitsi/meet/jitsi-meet.example.com-config.js; - } - - location ~ ^/([a-zA-Z0-9=\?]+)$ { - rewrite ^/(.*)$ / break; - } - - location / { - ssi on; - } - - # BOSH - location /http-bind { - proxy_pass http://localhost:5280/http-bind; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Host $http_host; - } -} diff --git a/doc/example-config-files/config.js.example b/doc/example-config-files/config.js.example deleted file mode 100755 index 92f71cfed..000000000 --- a/doc/example-config-files/config.js.example +++ /dev/null @@ -1,9 +0,0 @@ -var config = { - hosts: { - domain: 'jitsi.example.com', - muc: 'conference.jitsi.example.com', // FIXME: use XEP-0030 - bridge: 'jitsi-videobridge.jitsi.example.com' // FIXME: use XEP-0030 - }, - useNicks: false, - bosh: '//jitsi.example.com/http-bind' // FIXME: use xep-0156 for that -}; diff --git a/doc/example-config-files/jitsi.example.com.example b/doc/example-config-files/jitsi.example.com.example deleted file mode 100755 index 96ae864f9..000000000 --- a/doc/example-config-files/jitsi.example.com.example +++ /dev/null @@ -1,33 +0,0 @@ -server { - listen 80; - - server_name jitsi.example.com; - # set the root - root /srv/jitsi.example.com; - index index.html; - - location ~ ^/([a-zA-Z0-9=\?]+)$ { - rewrite ^/(.*)$ / break; - } - - location / { - ssi on; - } - - # BOSH - location /http-bind { - proxy_pass http://localhost:5280/http-bind; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Host $http_host; - } - - # xmpp websockets - location /xmpp-websocket { - proxy_pass http://localhost:5280; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $host; - tcp_nodelay on; - } -} diff --git a/doc/example-config-files/nginx.conf.example b/doc/example-config-files/nginx.conf.example deleted file mode 100755 index 017b34ee6..000000000 --- a/doc/example-config-files/nginx.conf.example +++ /dev/null @@ -1,54 +0,0 @@ -user www-data; -worker_processes 1; - -error_log /var/log/nginx/error.log; -pid /var/run/nginx.pid; - -events { - worker_connections 1024; - # multi_accept on; -} - -http { - include /etc/nginx/mime.types; - - access_log /var/log/nginx/access.log; - - sendfile on; - #tcp_nopush on; - - #keepalive_timeout 0; - keepalive_timeout 65; - tcp_nodelay on; - - tcp_nopush on; - types_hash_max_size 2048; - server_names_hash_bucket_size 64; - - gzip on; - gzip_disable "MSIE [1-6]\.(?!.*SV1)"; - - include /etc/nginx/conf.d/*.conf; - include /etc/nginx/sites-enabled/*; -} - -# mail { -# # See sample authentication script at: -# # http://wiki.nginx.org/NginxImapAuthenticateWithApachePhpScript -# -# # auth_http localhost/auth.php; -# # pop3_capabilities "TOP" "USER"; -# # imap_capabilities "IMAP4rev1" "UIDPLUS"; -# -# server { -# listen localhost:110; -# protocol pop3; -# proxy on; -# } -# -# server { -# listen localhost:143; -# protocol imap; -# proxy on; -# } -# } diff --git a/doc/example-config-files/prosody.cfg.lua.example b/doc/example-config-files/prosody.cfg.lua.example deleted file mode 100755 index 6aca907ff..000000000 --- a/doc/example-config-files/prosody.cfg.lua.example +++ /dev/null @@ -1,205 +0,0 @@ --- Prosody XMPP Server Configuration --- --- Information on configuring Prosody can be found on our --- website at http://prosody.im/doc/configure --- --- Tip: You can check that the syntax of this file is correct --- when you have finished by running: prosodyctl check config --- If there are any errors, it will let you know what and where --- they are, otherwise it will keep quiet. --- --- Good luck, and happy Jabbering! - - ----------- Server-wide settings ---------- --- Settings in this section apply to the whole server and are the default settings --- for any virtual hosts - --- This is a (by default, empty) list of accounts that are admins --- for the server. Note that you must create the accounts separately --- (see http://prosody.im/doc/creating_accounts for info) --- Example: admins = { "user1@example.com", "user2@example.net" } -admins = { } -daemonize = true -cross_domain_bosh = true; -component_ports = { 5347 } ---component_interface = "192.168.0.10" - --- Enable use of libevent for better performance under high load --- For more information see: http://prosody.im/doc/libevent ---use_libevent = true - --- This is the list of modules Prosody will load on startup. --- It looks for mod_modulename.lua in the plugins folder, so make sure that exists too. --- Documentation on modules can be found at: http://prosody.im/doc/modules -modules_enabled = { - - -- Generally required - "roster"; -- Allow users to have a roster. Recommended ;) - "saslauth"; -- Authentication for clients and servers. Recommended if you want to log in. - "tls"; -- Add support for secure TLS on c2s/s2s connections - "dialback"; -- s2s dialback support - "disco"; -- Service discovery - "posix"; -- POSIX functionality, sends server to background, enables syslog, etc. - - -- Not essential, but recommended - "private"; -- Private XML storage (for room bookmarks, etc.) - "vcard"; -- Allow users to set vCards - - -- These are commented by default as they have a performance impact - --"privacy"; -- Support privacy lists - "compression"; -- Stream compression (requires the lua-zlib package installed) - - -- Nice to have - "version"; -- Replies to server version requests - "uptime"; -- Report how long server has been running - "time"; -- Let others know the time here on this server - "ping"; -- Replies to XMPP pings with pongs - "pep"; -- Enables users to publish their mood, activity, playing music and more - "register"; -- Allow users to register on this server using a client and change passwords - - -- Admin interfaces - "admin_adhoc"; -- Allows administration via an XMPP client that supports ad-hoc commands - --"admin_telnet"; -- Opens telnet console interface on localhost port 5582 - - -- HTTP modules - "bosh"; -- Enable BOSH clients, aka "Jabber over HTTP" - --"http_files"; -- Serve static files from a directory over HTTP - - -- Other specific functionality - --"groups"; -- Shared roster support - --"announce"; -- Send announcement to all online users - --"welcome"; -- Welcome users who register accounts - --"watchregistrations"; -- Alert admins of registrations - --"motd"; -- Send a message to users when they log in - --"legacyauth"; -- Legacy authentication. Only used by some old clients and bots. - -- jitsi - "smacks"; - "carbons"; - "mam"; - "lastactivity"; - "offline"; - "pubsub"; - "adhoc"; - "websocket"; - "http_altconnect"; -} - --- These modules are auto-loaded, but should you want --- to disable them then uncomment them here: -modules_disabled = { - -- "offline"; -- Store offline messages - -- "c2s"; -- Handle client connections - -- "s2s"; -- Handle server-to-server connections -} - --- Disable account creation by default, for security --- For more information see http://prosody.im/doc/creating_accounts -allow_registration = false - --- These are the SSL/TLS-related settings. If you don't want --- to use SSL/TLS, you may comment or remove this -ssl = { - key = "/etc/prosody/certs/localhost.key"; - certificate = "/etc/prosody/certs/localhost.crt"; -} - --- Force clients to use encrypted connections? This option will --- prevent clients from authenticating unless they are using encryption. - --- c2s_require_encryption = true - --- Force certificate authentication for server-to-server connections? --- This provides ideal security, but requires servers you communicate --- with to support encryption AND present valid, trusted certificates. --- NOTE: Your version of LuaSec must support certificate verification! --- For more information see http://prosody.im/doc/s2s#security - --- s2s_secure_auth = false - --- Many servers don't support encryption or have invalid or self-signed --- certificates. You can list domains here that will not be required to --- authenticate using certificates. They will be authenticated using DNS. - ---s2s_insecure_domains = { "gmail.com" } - --- Even if you leave s2s_secure_auth disabled, you can still require valid --- certificates for some domains by specifying a list here. - ---s2s_secure_domains = { "jabber.org" } - --- Required for init scripts and prosodyctl -pidfile = "/var/run/prosody/prosody.pid" - --- Select the authentication backend to use. The 'internal' providers --- use Prosody's configured data storage to store the authentication data. --- To allow Prosody to offer secure authentication mechanisms to clients, the --- default provider stores passwords in plaintext. If you do not trust your --- server please see http://prosody.im/doc/modules/mod_auth_internal_hashed --- for information about using the hashed backend. - --- authentication = "internal_plain" -authentication = "internal_hashed" - --- Select the storage backend to use. By default Prosody uses flat files --- in its configured data directory, but it also supports more backends --- through modules. An "sql" backend is included by default, but requires --- additional dependencies. See http://prosody.im/doc/storage for more info. - ---storage = "sql" -- Default is "internal" - --- For the "sql" backend, you can uncomment *one* of the below to configure: ---sql = { driver = "SQLite3", database = "prosody.sqlite" } -- Default. 'database' is the filename. ---sql = { driver = "MySQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" } ---sql = { driver = "PostgreSQL", database = "prosody", username = "prosody", password = "secret", host = "localhost" } - --- Logging configuration --- For advanced logging see http://prosody.im/doc/logging -log = { - info = "/var/log/prosody/prosody.log"; -- Change 'info' to 'debug' for verbose logging - error = "/var/log/prosody/prosody.err"; - "*syslog"; -} - ------------ Virtual hosts ----------- --- You need to add a VirtualHost entry for each domain you wish Prosody to serve. --- Settings under each VirtualHost entry apply *only* to that host. - ---VirtualHost "localhost" - -VirtualHost "jitsi.example.com" - -- enabled = false -- Remove this line to enable this host - authentication = "anonymous" - -- Assign this host a certificate for TLS, otherwise it would use the one - -- set in the global section (if any). - -- Note that old-style SSL on port 5223 only supports one certificate, and will always - -- use the global one. - ssl = { - key = "/var/lib/prosody/jitsi.example.com.key"; - certificate = "/var/lib/prosody/jitsi.example.com.crt"; - } - ------- Components ------ --- You can specify components to add hosts that provide special services, --- like multi-user conferences, and transports. --- For more information on components, see http://prosody.im/doc/components - ----Set up a MUC (multi-user chat) room server on conference.example.com: ---Component "conference.example.com" "muc" - --- Set up a SOCKS5 bytestream proxy for server-proxied file transfers: ---Component "proxy.example.com" "proxy65" - ----Set up an external component (default component port is 5347) --- --- External components allow adding various services, such as gateways/ --- transports to other networks like ICQ, MSN and Yahoo. For more info --- see: http://prosody.im/doc/components#adding_an_external_component --- ---Component "gateway.example.com" --- component_secret = "password" - -Component "conference.jitsi.example.com" "muc" - -Component "jitsi-videobridge.jitsi.example.com" - component_secret = "IfGaish6" diff --git a/doc/influxdb.md b/doc/influxdb.md deleted file mode 100644 index b6cdf5ef3..000000000 --- a/doc/influxdb.md +++ /dev/null @@ -1,29 +0,0 @@ -# Overview -Jitsi Meet supports logging to an [InfluxDB](http://influxdb.com/) database. - -# Configuration -The following needs to be done to enable this functionality. - -## Install InfluxDB -The details are outside the scope of the document, see http://influxdb.com/download/ . - -## Create an InfluxDB database -Use the InfluxDB admin interface (running on port 8083) and create a database. In this example we name it jitsi_database - -## Enable logging for Jitsi Videobridge -Add the following properties to /usr/share/jitsi-videobridge/.sip-communicator/sip-communicator.properties. - -- org.jitsi.videobridge.log.INFLUX_DB_ENABLED=true -- org.jitsi.videobridge.log.INFLUX_URL_BASE=http://influxdb.example.com:8086 -- org.jitsi.videobridge.log.INFLUX_DATABASE=jitsi_database -- org.jitsi.videobridge.log.INFLUX_USER=user -- org.jitsi.videobridge.log.INFLUX_PASS=pass - -## Enable logging for Jicofo -Add the same properties as above to /usr/share/jicofo/.sip-communicator/sip-communicator.properties. - -## Enable logging for Jitsi Meet itself -Change "logStats" to "true" in /etc/jitsi/meet/you-domain.config.js or the config.js file used in your installation. - -# User interface -You can explore the database using the [Jiloin](https://github.com/jitsi/jiloin) web interface. diff --git a/doc/manual-install.md b/doc/manual-install.md deleted file mode 100644 index 782951f7d..000000000 --- a/doc/manual-install.md +++ /dev/null @@ -1,223 +0,0 @@ -# Server Installation for Jitsi Meet - -This describes configuring a server `jitsi.example.com` running Debian or a Debian Derivative. You will need to -change references to that to match your host, and generate some passwords for -`YOURSECRET1`, `YOURSECRET2`, `YOURSECRET3` and `YOURSECRET4`. - -There are also some complete [example config files](https://github.com/jitsi/jitsi-meet/tree/master/doc/example-config-files/) available, mentioned in each section. - -## Install prosody -```sh -apt-get install prosody -``` - -## Configure prosody -Add config file in `/etc/prosody/conf.avail/jitsi.example.com.cfg.lua` : - -- add your domain virtual host section: - -``` -VirtualHost "jitsi.example.com" - authentication = "anonymous" - ssl = { - key = "/var/lib/prosody/jitsi.example.com.key"; - certificate = "/var/lib/prosody/jitsi.example.com.crt"; - } - modules_enabled = { - "bosh"; - "pubsub"; - } -``` -- add domain with authentication for conference focus user: -``` -VirtualHost "auth.jitsi.example.com" - authentication = "internal_plain" -``` -- add focus user to server admins: -``` -admins = { "focus@auth.jitsi.example.com" } -``` -- and finally configure components: -``` -Component "conference.jitsi.example.com" "muc" -Component "jitsi-videobridge.jitsi.example.com" - component_secret = "YOURSECRET1" -Component "focus.jitsi.example.com" - component_secret = "YOURSECRET2" -``` - -Add link for the added configuration -```sh -ln -s /etc/prosody/conf.avail/jitsi.example.com.cfg.lua /etc/prosody/conf.d/jitsi.example.com.cfg.lua -``` - -Generate certs for the domain: -```sh -prosodyctl cert generate jitsi.example.com -``` - -Create conference focus user: -```sh -prosodyctl register focus auth.jitsi.example.com YOURSECRET3 -``` - -Restart prosody XMPP server with the new config -```sh -prosodyctl restart -``` - -## Install nginx -```sh -apt-get install nginx -``` - -Add a new file `jitsi.example.com` in `/etc/nginx/sites-available` (see also the example config file): -``` -server_names_hash_bucket_size 64; - -server { - listen 80; - server_name jitsi.example.com; - # set the root - root /srv/jitsi.example.com; - index index.html; - location ~ ^/([a-zA-Z0-9=\?]+)$ { - rewrite ^/(.*)$ / break; - } - location / { - ssi on; - } - # BOSH - location /http-bind { - proxy_pass http://localhost:5280/http-bind; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Host $http_host; - } -} -``` - -Add link for the added configuration -```sh -cd /etc/nginx/sites-enabled -ln -s ../sites-available/jitsi.example.com jitsi.example.com -``` - -## Install Jitsi Videobridge -```sh -wget https://download.jitsi.org/jitsi-videobridge/linux/jitsi-videobridge-linux-{arch-buildnum}.zip -unzip jitsi-videobridge-linux-{arch-buildnum}.zip -``` - -Install JRE if missing: -``` -apt-get install default-jre -``` - -_NOTE: When installing on older Debian releases keep in mind that you need JRE >= 1.7._ - -In the user home that will be starting Jitsi Videobridge create `.sip-communicator` folder and add the file `sip-communicator.properties` with one line in it: -``` -org.jitsi.impl.neomedia.transform.srtp.SRTPCryptoContext.checkReplay=false -``` - -Start the videobridge with: -```sh -./jvb.sh --host=localhost --domain=jitsi.example.com --port=5347 --secret=YOURSECRET1 & -``` -Or autostart it by adding the line in `/etc/rc.local`: -```sh -/bin/bash /root/jitsi-videobridge-linux-{arch-buildnum}/jvb.sh --host=localhost --domain=jitsi.example.com --port=5347 --secret=YOURSECRET1 > /var/log/jvb.log 2>&1 -``` - -## Install Jitsi Conference Focus (jicofo) - -Install JDK and Ant if missing: -``` -apt-get install default-jdk ant -``` - -_NOTE: When installing on older Debian releases keep in mind that you need JDK >= 1.7._ - -Clone source from Github repo: -```sh -git clone https://github.com/jitsi/jicofo.git -``` -Build distribution package. Replace {os-name} with one of: 'lin', 'lin64', 'macosx', 'win', 'win64'. -```sh -cd jicofo -ant dist.{os-name} -``` -Run jicofo: -```sh -cd dist/{os-name}' -./jicofo.sh --domain=jitsi.example.com --secret=YOURSECRET2 --user_domain=auth.jitsi.example.com --user_name=focus --user_password=YOURSECRET3 -``` - -## Deploy Jitsi Meet -Checkout and configure Jitsi Meet: -```sh -cd /srv -git clone https://github.com/jitsi/jitsi-meet.git -mv jitsi-meet/ jitsi.example.com -``` - -Edit host names in `/srv/jitsi.example.com/config.js` (see also the example config file): -``` -var config = { - hosts: { - domain: 'jitsi.example.com', - muc: 'conference.jitsi.example.com', - bridge: 'jitsi-videobridge.jitsi.example.com' - }, - useNicks: false, - bosh: '//jitsi.example.com/http-bind', // FIXME: use xep-0156 for that - desktopSharing: 'false' // Desktop sharing method. Can be set to 'ext', 'webrtc' or false to disable. - //chromeExtensionId: 'diibjkoicjeejcmhdnailmkgecihlobk', // Id of desktop streamer Chrome extension - //minChromeExtVersion: '0.1' // Required version of Chrome extension -}; -``` - -Restart nginx to get the new configuration: -```sh -invoke-rc.d nginx restart -``` - -## Running behind NAT -In case of videobridge being installed on a machine behind NAT, add the following extra lines to the file `~/.sip-communicator/sip-communicator.properties` (in the home of user running the videobridge): -``` -org.jitsi.videobridge.NAT_HARVESTER_LOCAL_ADDRESS= -org.jitsi.videobridge.NAT_HARVESTER_PUBLIC_ADDRESS= -``` - -So the file should look like this at the end: -``` -org.jitsi.impl.neomedia.transform.srtp.SRTPCryptoContext.checkReplay=false -org.jitsi.videobridge.NAT_HARVESTER_LOCAL_ADDRESS= -org.jitsi.videobridge.NAT_HARVESTER_PUBLIC_ADDRESS= -``` - -# Hold your first conference -You are now all set and ready to have your first meet by going to http://jitsi.example.com - - -## Enabling recording -Currently recording is only supported for linux-64 and macos. To enable it, add -the following properties to sip-communicator.properties: -``` -org.jitsi.videobridge.ENABLE_MEDIA_RECORDING=true -org.jitsi.videobridge.MEDIA_RECORDING_PATH=/path/to/recordings/dir -org.jitsi.videobridge.MEDIA_RECORDING_TOKEN=secret -``` - -where /path/to/recordings/dir is the path to a pre-existing directory where recordings -will be stored (needs to be writeable by the user running jitsi-videobridge), -and "secret" is a string which will be used for authentication. - -Then, edit the Jitsi-Meet config.js file and set: -``` -enableRecording: true -``` - -Restart jitsi-videobridge and start a new conference (making sure that the page -is reloaded with the new config.js) -- the organizer of the conference should -now have a "recording" button in the floating menu, near the "mute" button. diff --git a/doc/quick-install.md b/doc/quick-install.md deleted file mode 100644 index 3868daa1e..000000000 --- a/doc/quick-install.md +++ /dev/null @@ -1,74 +0,0 @@ -# Jitsi Meet quick install - -This document describes the required steps for a quick Jitsi Meet installation on a Debian based GNU/Linux system. - -N.B.: All commands are supposed to be run by root. If you are logged in as a regular user with sudo rights, please prepend ___sudo___ to each of the commands. - -## Basic Jitsi Meet install - -### Add the repository -```sh -echo 'deb http://download.jitsi.org/nightly/deb unstable/' >> /etc/apt/sources.list -wget -qO - https://download.jitsi.org/nightly/deb/unstable/archive.key | apt-key add - -``` - -### Update the package lists - -```sh -apt-get update -``` - -### Install Jitsi Meet - -```sh -apt-get -y install jitsi-meet -``` - -During the installation, you will be asked to enter the hostname of the Jitsi Meet instance. If you have a FQDN hostname for the instance already set up in DNS, enter it there. If you don't have a resolvable hostname, you can enter the IP address of the machine (if it is static or doesn't change). - -This hostname (or IP address) will be used for virtualhost configuration inside the Jitsi Meet and also, you and your correspondents will be using it to access the web conferences. - -### Open a conference - -Launch a web browser (Chrome, Chromium or latest Opera) and enter in the URL bar the hostname (or IP address) you used in the previous step. - -Confirm that you trust the self-signed certificate of the newly installed Jitsi Meet. - -Enjoy! - -## Adding sip-gateway to Jitsi Meet - -### Install Jigasi - -```sh -apt-get -y install jigasi -``` -or - -```sh -wget https://download.jitsi.org/jigasi_1.0-1_amd64.deb -dpkg -i jigasi_1.0-1_amd64.deb -``` - -During the installation, you will be asked to enter your SIP account and password. This account will be used to invite the other SIP participants. - -### Reload Jitsi Meet - -Launch again a browser with the Jitsi Meet URL and you'll see a telephone icon on the right end of the toolbar. Use it to invite SIP accounts to join the current conference. - -Enjoy! - -## Uninstall - -```sh -apt-get purge jigasi jitsi-meet jicofo jitsi-videobridge -``` - -Sometimes the following packages will fail to uninstall properly: - -- jigasi -- jitsi-videobridge - -When this happens, just run the uninstall command a second time and it should be ok. - -The reason for failure is that sometimes, the uninstall script is faster than the process that stops the daemons. The second run of the uninstall command fixes this, as by then the jigasi or jvb daemons are already stopped. diff --git a/external_api.js b/external_api.js deleted file mode 100644 index 5d23daeb7..000000000 --- a/external_api.js +++ /dev/null @@ -1,355 +0,0 @@ -/** - * Implements API class that embeds Jitsi Meet in external applications. - */ -var JitsiMeetExternalAPI = (function() -{ - /** - * The minimum width for the Jitsi Meet frame - * @type {number} - */ - var MIN_WIDTH = 790; - - /** - * The minimum height for the Jitsi Meet frame - * @type {number} - */ - var MIN_HEIGHT = 300; - - /** - * Constructs new API instance. Creates iframe element that loads - * Jitsi Meet. - * @param domain the domain name of the server that hosts the conference - * @param room_name the name of the room to join - * @param width width of the iframe - * @param height height of the iframe - * @param parent_node the node that will contain the iframe - * @param filmStripOnly if the value is true only the small videos will be - * visible. - * @constructor - */ - function JitsiMeetExternalAPI(domain, room_name, width, height, parentNode, - filmStripOnly) { - if(!width || width < MIN_WIDTH) - width = MIN_WIDTH; - if(!height || height < MIN_HEIGHT) - height = MIN_HEIGHT; - - this.parentNode = null; - if (parentNode) { - this.parentNode = parentNode; - } else { - var scriptTag = document.scripts[document.scripts.length - 1]; - this.parentNode = scriptTag.parentNode; - } - - this.iframeHolder = - this.parentNode.appendChild(document.createElement("div")); - this.iframeHolder.id = "jitsiConference" + JitsiMeetExternalAPI.id; - this.iframeHolder.style.width = width + "px"; - this.iframeHolder.style.height = height + "px"; - this.frameName = "jitsiConferenceFrame" + JitsiMeetExternalAPI.id; - this.url = "//" + domain + "/"; - if(room_name) - this.url += room_name; - this.url += "#external=true"; - if(filmStripOnly) - this.url += "&interfaceConfig.filmStripOnly=true"; - - JitsiMeetExternalAPI.id++; - - this.frame = document.createElement("iframe"); - this.frame.src = this.url; - this.frame.name = this.frameName; - this.frame.id = this.frameName; - this.frame.width = "100%"; - this.frame.height = "100%"; - this.frame.setAttribute("allowFullScreen","true"); - this.frame = this.iframeHolder.appendChild(this.frame); - - - this.frameLoaded = false; - this.initialCommands = []; - this.eventHandlers = {}; - this.initListeners(); - } - - /** - * Last id of api object - * @type {number} - */ - JitsiMeetExternalAPI.id = 0; - - /** - * Sends the passed object to Jitsi Meet - * @param object the object to be sent - */ - JitsiMeetExternalAPI.prototype.sendMessage = function(object) { - if (this.frameLoaded) { - this.frame.contentWindow.postMessage( - JSON.stringify(object), this.frame.src); - } - else { - this.initialCommands.push(object); - } - - }; - - /** - * Executes command. The available commands are: - * displayName - sets the display name of the local participant to the value - * passed in the arguments array. - * toggleAudio - mutes / unmutes audio with no arguments - * toggleVideo - mutes / unmutes video with no arguments - * filmStrip - hides / shows the film strip with no arguments - * If the command doesn't require any arguments the parameter should be set - * to empty array or it may be omitted. - * @param name the name of the command - * @param arguments array of arguments - */ - JitsiMeetExternalAPI.prototype.executeCommand = function(name, - argumentsList) { - var argumentsArray = argumentsList; - if (!argumentsArray) - argumentsArray = []; - var object = {type: "command", action: "execute"}; - object[name] = argumentsArray; - this.sendMessage(object); - }; - - /** - * Executes commands. The available commands are: - * displayName - sets the display name of the local participant to the value - * passed in the arguments array. - * toggleAudio - mutes / unmutes audio with no arguments - * toggleVideo - mutes / unmutes video with no arguments - * filmStrip - hides / shows the film strip with no arguments - * @param object the object with commands to be executed. The keys of the - * object are the commands that will be executed and the values are the - * arguments for the command. - */ - JitsiMeetExternalAPI.prototype.executeCommands = function (object) { - object.type = "command"; - object.action = "execute"; - this.sendMessage(object); - }; - - /** - * Adds event listeners to Meet Jitsi. The object key should be the name of - * the event and value - the listener. - * Currently we support the following - * events: - * incomingMessage - receives event notifications about incoming - * messages. The listener will receive object with the following structure: - * {{ - * "from": from,//JID of the user that sent the message - * "nick": nick,//the nickname of the user that sent the message - * "message": txt//the text of the message - * }} - * outgoingMessage - receives event notifications about outgoing - * messages. The listener will receive object with the following structure: - * {{ - * "message": txt//the text of the message - * }} - * displayNameChanged - receives event notifications about display name - * change. The listener will receive object with the following structure: - * {{ - * jid: jid,//the JID of the participant that changed his display name - * displayname: displayName //the new display name - * }} - * participantJoined - receives event notifications about new participant. - * The listener will receive object with the following structure: - * {{ - * jid: jid //the jid of the participant - * }} - * participantLeft - receives event notifications about participant that left room. - * The listener will receive object with the following structure: - * {{ - * jid: jid //the jid of the participant - * }} - * @param object - */ - JitsiMeetExternalAPI.prototype.addEventListeners - = function (object) { - - var message = {type: "event", action: "add", events: []}; - for(var i in object) - { - message.events.push(i); - this.eventHandlers[i] = object[i]; - } - this.sendMessage(message); - }; - - /** - * Adds event listeners to Meet Jitsi. Currently we support the following - * events: - * incomingMessage - receives event notifications about incoming - * messages. The listener will receive object with the following structure: - * {{ - * "from": from,//JID of the user that sent the message - * "nick": nick,//the nickname of the user that sent the message - * "message": txt//the text of the message - * }} - * outgoingMessage - receives event notifications about outgoing - * messages. The listener will receive object with the following structure: - * {{ - * "message": txt//the text of the message - * }} - * displayNameChanged - receives event notifications about display name - * change. The listener will receive object with the following structure: - * {{ - * jid: jid,//the JID of the participant that changed his display name - * displayname: displayName //the new display name - * }} - * participantJoined - receives event notifications about new participant. - * The listener will receive object with the following structure: - * {{ - * jid: jid //the jid of the participant - * }} - * participantLeft - receives event notifications about participant that left room. - * The listener will receive object with the following structure: - * {{ - * jid: jid //the jid of the participant - * }} - * @param event the name of the event - * @param listener the listener - */ - JitsiMeetExternalAPI.prototype.addEventListener - = function (event, listener) { - - var message = {type: "event", action: "add", events: [event]}; - this.eventHandlers[event] = listener; - this.sendMessage(message); - }; - - /** - * Removes event listener. - * @param event the name of the event. - */ - JitsiMeetExternalAPI.prototype.removeEventListener - = function (event) { - if(!this.eventHandlers[event]) - { - console.error("The event " + event + " is not registered."); - return; - } - var message = {type: "event", action: "remove", events: [event]}; - delete this.eventHandlers[event]; - this.sendMessage(message); - }; - - /** - * Removes event listeners. - * @param events array with the names of the events. - */ - JitsiMeetExternalAPI.prototype.removeEventListeners - = function (events) { - var eventsArray = []; - for(var i = 0; i < events.length; i++) - { - var event = events[i]; - if(!this.eventHandlers[event]) - { - console.error("The event " + event + " is not registered."); - continue; - } - delete this.eventHandlers[event]; - eventsArray.push(event); - } - - if(eventsArray.length > 0) - { - this.sendMessage( - {type: "event", action: "remove", events: eventsArray}); - } - - }; - - /** - * Processes message events sent from Jitsi Meet - * @param event the event - */ - JitsiMeetExternalAPI.prototype.processMessage = function(event) { - var message; - try { - message = JSON.parse(event.data); - } catch (e) {} - - if(!message.type) { - console.error("Message without type is received."); - return; - } - switch (message.type) { - case "system": - if(message.loaded) { - this.onFrameLoaded(); - } - break; - case "event": - if(message.action != "result" || - !message.event || !this.eventHandlers[message.event]) { - console.warn("The received event cannot be parsed."); - return; - } - this.eventHandlers[message.event](message.result); - break; - default : - console.error("Unknown message type."); - return; - } - }; - - /** - * That method is called when the Jitsi Meet is loaded. Executes saved - * commands that are send before the frame was loaded. - */ - JitsiMeetExternalAPI.prototype.onFrameLoaded = function () { - this.frameLoaded = true; - for (var i = 0; i < this.initialCommands.length; i++) { - this.sendMessage(this.initialCommands[i]); - } - this.initialCommands = null; - }; - - /** - * Setups the listener for message events from Jitsi Meet. - */ - JitsiMeetExternalAPI.prototype.initListeners = function () { - var self = this; - this.eventListener = function (event) { - self.processMessage(event); - }; - if (window.addEventListener) { - window.addEventListener('message', - this.eventListener, false); - } - else { - window.attachEvent('onmessage', this.eventListener); - } - }; - - /** - * Removes the listeners and removes the Jitsi Meet frame. - */ - JitsiMeetExternalAPI.prototype.dispose = function () { - if (window.removeEventListener) { - window.removeEventListener('message', - this.eventListener, false); - } - else { - window.detachEvent('onmessage', - this.eventListener); - } - var frame = document.getElementById(this.frameName); - if(frame) - frame.src = 'about:blank'; - var self = this; - window.setTimeout(function () { - self.iframeHolder.removeChild(self.frame); - self.iframeHolder.parentNode.removeChild(self.iframeHolder); - }, 10); - }; - - return JitsiMeetExternalAPI; - -})(); \ No newline at end of file diff --git a/favicon.ico b/favicon.ico deleted file mode 100644 index bb34caf1f..000000000 Binary files a/favicon.ico and /dev/null differ diff --git a/fonts/jitsi.eot b/fonts/jitsi.eot deleted file mode 100644 index 76d3bb429..000000000 Binary files a/fonts/jitsi.eot and /dev/null differ diff --git a/fonts/jitsi.svg b/fonts/jitsi.svg deleted file mode 100644 index b78a3ebb0..000000000 --- a/fonts/jitsi.svg +++ /dev/null @@ -1,39 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/fonts/jitsi.ttf b/fonts/jitsi.ttf deleted file mode 100644 index bb7402098..000000000 Binary files a/fonts/jitsi.ttf and /dev/null differ diff --git a/fonts/jitsi.woff b/fonts/jitsi.woff deleted file mode 100644 index 0551381e1..000000000 Binary files a/fonts/jitsi.woff and /dev/null differ diff --git a/fonts/selection.json b/fonts/selection.json deleted file mode 100644 index 696fa39e3..000000000 --- a/fonts/selection.json +++ /dev/null @@ -1,916 +0,0 @@ -{ - "IcoMoonType": "selection", - "icons": [ - { - "icon": { - "paths": [ - "M74.418 78.701h239.304v228.491h-239.304v-228.491z", - "M393.455 78.701h239.304v228.491h-239.304v-228.491z", - "M712.494 78.701h239.263v228.491h-239.263v-228.491z", - "M74.418 397.735h239.304v228.555h-239.304v-228.555z", - "M393.455 397.735h239.304v228.555h-239.304v-228.555z", - "M712.494 397.735h239.263v228.555h-239.263v-228.555z", - "M74.418 716.834h239.304v228.465h-239.304v-228.465z", - "M393.455 716.834h239.304v228.465h-239.304v-228.465z", - "M712.494 716.834h239.263v228.465h-239.263v-228.465z" - ], - "attrs": [ - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {} - ], - "isMulticolor": false, - "width": 1026, - "grid": 0, - "tags": [ - "dailPad" - ] - }, - "attrs": [ - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {}, - {} - ], - "properties": { - "order": 29, - "id": 0, - "prevSize": 32, - "code": 58908, - "name": "dialPad" - }, - "setIdx": 0, - "setId": 2, - "iconIdx": 0 - }, - { - "icon": { - "paths": [ - "M526.071 725.251c-28.637 30.869-56.465 60.861-84.282 90.859-51.578 55.636-103.047 111.376-154.842 166.832-7.606 8.135-15.958 16.1-25.317 22.012-28.075 17.708-58.31 18.090-88.472 6.492-59.84-23.028-80.004-90.727-59.734-139.234 5.413-12.95 13.721-23.601 23.709-33.173 70.256-67.351 140.506-134.717 210.76-202.077 15.638-14.993 31.264-29.995 47.364-45.45-9.302-9.529-18.386-18.833-27.451-28.137-12.122-12.442-13.234-20.28-5.067-35.498 4.735-8.816 4.789-8.878-2.627-16.198-20.012-19.72-40.168-39.198-63.498-55.188-27.167-18.624-57.161-24.233-89.083-19.849-53.402 7.328-91.609 38.372-121.413 81.046-12.774 18.299-15.365 40.313-17.517 61.875-3.23 32.245-2.415 64.479 2.209 96.597 1.654 11.515-3.863 16.539-13.835 11.175-8.306-4.448-16.095-11.048-22.115-18.353-15.574-18.89-22.223-42.042-27.474-65.395-12.955-57.652-8.86-114.49 12.191-169.495 32.345-84.537 79.743-159.571 145.953-221.932 13.659-12.857 176.841-180.564 202.944-207.021 7.493-7.599 14.895-7.635 22.393-0.028 43.009 43.641 85.985 87.316 128.927 131.029 8.117 8.267 8.019 15.097-0.222 23.49-26.339 26.834-52.726 53.627-79.106 80.419-6.244 6.334-97.34 82.437-73.027 128.816 22.693 25.090 46.196 49.449 69.575 73.904 1.189 1.238 4.686 1.386 6.523 0.632 3.63-1.499 6.848-3.997 10.248-6.066 9.745-5.94 19.545-4.918 27.812 3.083 11.755 11.381 23.405 22.858 35.392 34.59 4.807-4.575 9.939-9.41 15.027-14.294 27.128-26.039 54.272-52.071 81.351-78.146 16.413-15.778 18.652-28.418 11.038-49.658-10.473-29.221-14.356-59.677-13.85-90.624 1.017-61.045 20.438-115.334 61.003-161.416 32.825-37.286 72.054-64.311 121.643-74.325 35.227-7.101 69.139-4.513 100.663 14.026 6.365 3.752 11.908 9.007 17.455 14.005 3.491 3.125 3.153 6.236-0.565 9.98-42.503 42.885-84.772 86.013-127.154 129.035-12.442 12.638-12.356 23.167 0.196 35.914 40.344 40.978 80.597 82.050 120.936 123.052 10.076 10.233 19.537 10.021 29.504-0.134 43.195-44.077 86.449-88.090 129.706-132.118 1.21-1.233 2.572-2.322 5.135-4.624 5.491 5.893 11.895 10.924 15.961 17.406 19.452 30.944 22.608 64.83 17.073 100.25-14.253 91.080-97.188 175.638-197.712 190.123-39.977 5.764-79.372 2.562-118.067-9.031-5.898-1.775-11.541-4.629-17.538-5.829-12.47-2.474-23.872 0.366-32.74 9.877-30.921 33.168-61.674 66.484-92.474 99.758-0.73 0.805-1.349 1.718-0.181 1.099 8.992 10.006 17.354 20.662 27.061 29.94 81.064 77.54 164.91 151.986 250.882 224.063 9.936 8.347 10.274 15.695 1.040 25.1-42.338 43.068-84.689 86.111-127.059 129.154-9.413 9.575-16.846 9.152-25.291-1.295-76.686-94.78-156.8-186.609-239.707-276.002-1.334-1.453-2.562-3.029-4.257-5.042z" - ], - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "width": 1105, - "grid": 0, - "tags": [ - "settings" - ] - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 1, - "id": 33, - "prevSize": 32, - "code": 58907, - "name": "settings" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 0 - }, - { - "icon": { - "paths": [ - "M1223.129 242.783l-180.128 175.796v-217.716c0-74.673-59.512-135.496-132.599-135.496h-634.716c-73.084 0-132.596 60.823-132.596 135.496v609.237c0 74.673 59.512 135.496 132.596 135.496h634.716c73.084 0 132.599-60.82 132.599-135.496v-172.679l193.45 153.712c48.784 35.558 96.695-5.178 96.695-40.424v-483.533c-0.003-35.248-55.897-71.306-110.017-24.393zM601.169 760.065c-141.111 0-255.524-114.411-255.524-255.521s114.411-255.521 255.524-255.521c141.108 0 255.519 114.411 255.519 255.521-0 141.113-114.408 255.521-255.519 255.521z", - "M599.045 359.751c-80.474 0-145.727 65.253-145.727 145.729 0 80.471 65.25 145.727 145.727 145.727s145.729-65.256 145.729-145.727c0-80.474-65.253-145.729-145.729-145.729z" - ], - "width": 1334, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "tags": [ - "webCam" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 4, - "id": 32, - "prevSize": 32, - "code": 58888, - "name": "webCam", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 1 - }, - { - "icon": { - "paths": [ - "M3.881 813.165h220.26v210.835h-220.26v-210.835z", - "M308.817 609.857h220.27v414.143h-220.27v-414.143z", - "M613.764 406.588h220.268v617.412h-220.268v-617.412z", - "M918.685 203.285h220.265v820.715h-220.265v-820.715z", - "M1223.629 0h220.263v1024h-220.263v-1024z" - ], - "width": 1444, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "tags": [ - "connection-2" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 27, - "id": 31, - "prevSize": 32, - "code": 58906, - "name": "connection", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 2 - }, - { - "icon": { - "paths": [ - "M46.993-1.7c461.234 0 553.793 0 1015.024 0 35.919 0 53.356 25.959 53.356 57.959-0.581 303.259-0.325 606.488-0.449 909.809 0 43.984-13.203 57.058-57.703 57.058-443.072 0.126-556.453 0.126-999.553 0-44.534 0-57.799-13.009-57.799-57.058-0.098-303.257 0.485-608.072-0.093-911.329-0.034-26.21 11.301-53.761 47.217-56.439zM311.405 509.702c0 119.045-0.072 172.168 0.057 291.249 0.036 50.043 11.208 61.050 62.12 61.050 233.352 0 137.075 0 370.522 0 47.075 0 59.249-11.982 59.249-58.095 0.126-239.111 0.126-346.338 0-585.389 0-48.138-10.687-58.991-57.768-58.991-235.323-0.101-140.844-0.101-376.157 0-47.044 0-57.93 11.043-57.966 58.89-0.129 119.109-0.057 172.209-0.057 291.287zM153.944 121.434c-74.929 0.062-66.687-5.958-66.845 66.685-0.201 63.95-7.054 63.534 62.528 63.372 72.999-0.194 67.201 3.764 67.302-67.554 0-67.722 4.087-62.595-62.985-62.502zM963.644 121.434c-71.159 0.034-65.56-6.185-65.751 65.364-0.129 67.302-4.508 64.693 64.528 64.693 73.089 0 65.299 2.031 65.299-66.238-0.003-68.646 6.956-63.911-64.076-63.818zM216.828 837.592c0.359-73.094 4.639-66.914-67.358-67.17-68.104-0.191-62.569-2.763-62.407 63.31 0.129 73.476-6.954 66.52 67.074 66.649 66.042 0.065 63.142 6.056 62.691-62.789zM1027.718 835.6c0.134-68.334 6.443-65.304-63.297-65.178-70.132 0.132-66.656-5.793-66.527 65.304 0.129 70.645-4.384 64.721 63.756 64.657 71.995-0.132 66.202 6.698 66.068-64.783zM1027.718 617.923c0-70.55 7.219-66.842-67.485-66.522-0.898 0-1.873 0-2.838 0-59.375 0-59.375 0-59.375 58.023 0 77.922-6.443 69.936 69.293 70.196 66.076 0.387 60.539 3.091 60.405-61.697zM151.307 470.127c68.295 0.163 65.815 5.568 65.624-62.982-0.194-71.128 4.895-64.917-66.014-65.010-69.905-0.101-63.813-4.704-63.885 63.978-0.062 67.431-5.7 64.463 64.275 64.014zM961.263 470.127c72.511 0.258 66.589 4.603 66.455-64.494 0-68.558 6.185-63.537-64.267-63.498-70.196 0.028-65.686-6.053-65.498 65.493 0.132 62.5 0.067 62.5 63.31 62.5zM150.399 679.62c71.004 0 66.659 6.567 66.466-64.528-0.163-63.694-0.036-63.501-65.013-63.756-70.805-0.258-64.822-2.673-64.822 63.756 0.036 69.167-5.919 64.788 63.369 64.528z" - ], - "width": 1115, - "attrs": [], - "tags": [ - "filmstrip" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 25, - "id": 29, - "prevSize": 32, - "code": 58905, - "name": "filmstrip", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 3 - }, - { - "icon": { - "paths": [ - "", - "M797.086 847.699c-0.059-0.163-0.119-0.328-0.16-0.485-71.399 45.638-151.782 69.931-234.023 69.931-0.013 0-0.021 0-0.028 0-122.52 0-237.501-52.772-315.469-144.741-99.778-117.698-134.252-329.954-73.022-427.789 4.004 1.662 7.875 3.233 11.68 4.773 13.585 5.511 26.413 10.716 42.305 19.096 6.063 3.202 12.338 4.812 18.673 4.812 11.714 0 22.6-5.648 29.848-15.486 7.815-10.617 10.313-24.778 6.538-36.951l-3.525-11.41c-10.687-34.59-21.723-70.354-34.211-105.078-9.983-27.765-22.399-62.327-59.226-62.327-12.057 0-26.037 3.656-46.73 12.204-44.294 18.319-71.058 29.961-114.534 49.81-15.102 6.887-25.234 22.698-25.203 39.343 0.028 15.842 8.992 29.337 23.975 36.115 18.208 8.257 30.536 13.716 43.468 19.447l10.687 4.753c-101.938 259.102 24.803 526.458 211.314 639.212 83.497 50.474 178.5 77.14 274.769 77.14h0.041c102.72 0 205.561-31.099 284.501-85.198-31.729-28.803-45.566-69.167-51.671-87.171z", - "M1098.203 749.91c-18.113-8.577-30.356-14.258-43.221-20.244l-10.496-4.892c106.448-257.268-15.569-526.801-200.067-642.788-85.36-53.663-183.123-82.032-282.716-82.032-104.848 0-206.41 30.593-285.967 86.165l-5.385 3.764c31.597 27.564 45.86 66.788 52.917 86.41 72.926-47.94 155.675-73.409 239.895-73.409 125.407 0 242.142 54.785 320.294 150.316 97.683 119.447 128.439 332.255 65.498 429.015-3.989-1.736-7.815-3.385-11.624-4.998-13.471-5.759-26.204-11.18-41.954-19.821-6.203-3.424-12.645-5.155-19.212-5.155-11.585 0-22.399 5.558-29.69 15.267-7.813 10.434-10.478 24.432-6.966 36.515l3.279 11.301c10.096 34.845 20.531 70.857 32.412 105.842 9.588 28.238 21.514 63.382 59.179 63.382 11.843 0 25.577-3.424 45.881-11.399 44.351-17.439 71.319-28.601 115.409-47.777 15.19-6.623 25.601-22.252 25.859-38.894 0.281-15.822-8.445-29.499-23.325-36.569z" - ], - "width": 1122, - "attrs": [], - "tags": [ - "reload" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 24, - "id": 28, - "prevSize": 32, - "code": 58904, - "name": "reload", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 4 - }, - { - "icon": { - "paths": [ - "M65.774 443.252c10.052-9.358 25.988-21.772 43.285-32.699 51.335-32.619 108.115-50.897 166.829-64.133 48.763-10.95 98.246-16.887 148.066-20.203 55.755-3.754 111.559-3.78 167.392-0.797 39.944 2.185 79.686 6.502 119.119 13.211 43.956 7.506 87.037 17.994 128.785 33.751 24.419 9.175 48.172 20.105 70.534 33.573 29.716 17.891 56.552 39.224 77.22 67.348 20.819 28.302 31.721 60.407 33.829 95.392 1.747 27.402 0.717 54.697-5.656 81.588-2.877 12.083-8.226 23.134-16.554 32.386-11.417 12.648-26.424 17.021-42.772 17.636-20.463 0.668-40.411-4.113-60.361-8.226-38.912-7.97-77.836-16.245-116.699-24.728-14.137-3.034-28.689-5.093-41.649-12.596-22.308-12.955-34.445-31.775-34.033-57.783 0.258-16.869 2.216-33.782 2.469-50.695 0.312-25.010-9.923-45.161-30.898-59.042-14.395-9.539-30.694-14.911-47.452-18.665-40.411-9.046-81.387-10.179-122.561-10.050-28.821 0.126-57.582 1.669-86.093 6.143-19.947 3.161-39.562 7.813-57.732 17.014-24.318 12.364-39.353 31.465-40.073 59.352-0.441 16.351 0.973 32.802 1.927 49.15 0.642 11.822-0.080 23.446-5.295 34.288-9.26 19.385-24.935 31.672-45.37 36.964-22.646 5.865-45.605 10.54-68.504 15.223-38.102 7.764-76.216 15.368-114.416 22.517-14.526 2.774-29.254 1.951-43.133-3.602-18.742-7.457-28.924-22.775-34.138-41.337-7.096-25.397-7.841-51.513-6.966-77.731 0.9-27.040 5.883-53.237 18.404-77.607 9.794-19.065 22.491-35.955 42.493-55.642z" - ], - "width": 1026, - "attrs": [], - "tags": [ - "hangup" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 23, - "id": 27, - "prevSize": 32, - "code": 58903, - "name": "hangup", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 5 - }, - { - "icon": { - "paths": [ - "M1016.824 954.234c-2.051-15.373-5.331-30.537-7.859-45.847-8.334-50.458-33.006-86.503-82.063-107.922-78.373-34.198-155.103-72.121-232.111-109.395-55.686-27.025-52.409-88.519-34.097-114.413 11.89-16.88 22.344-34.572 23.575-56.852 0.444-8.226 8.303-18.99 15.817-23.294 26.070-15.035 38.161-39.565 50.020-64.982 3.109-6.696 7.379-13.187 12.266-18.722 8.471-9.668 12.264-19.235 6.079-31.842-1.435-2.97 1.331-8.334 2.8-12.367 4.304-12.026 10.285-23.676 13.12-36.043 3.556-15.339 5.398-31.225 6.252-46.975 0.374-6.523-6.045-13.528-5.362-19.95 3.483-31.912-14.557-56.202-24.739-83.977-12.465-34.198-36.928-55.619-58.519-81.106-4.066-4.784-5.227-13.051-5.571-19.886-0.72-14.588-6.732-21.797-22.004-19.813-6.11 0.787-12.772 2.495-18.41 0.991-4.957-1.334-12.406-6.288-12.676-10.112-1.538-19.336-8.264-22.517-28.016-19.235-12.364 2.049-28.457-9.155-40.584-17.561-10.145-7.041-18.89-10.045-30.681-7.176-4.915 1.195-11.544 0.991-15.716-1.435-4.441-2.663-8.775-4.237-13.118-5.124v-0.748c-0.957 0.031-1.982 0.204-2.939 0.307-0.955-0.103-1.912-0.274-2.867-0.307v0.751c-4.371 0.888-8.749 2.462-13.156 5.124-4.133 2.425-10.762 2.632-15.68 1.435-11.822-2.867-20.569 0.137-30.684 7.176-12.158 8.404-28.217 19.609-40.584 17.561-19.746-3.282-26.509-0.103-28.047 19.235-0.307 3.824-7.686 8.778-12.676 10.112-5.669 1.504-12.297-0.204-18.446-0.991-15.236-1.984-21.25 5.225-21.97 19.813-0.338 6.832-1.502 15.102-5.568 19.886-21.588 25.485-46.051 46.908-58.555 81.106-10.117 27.773-28.189 52.063-24.669 83.975 0.686 6.422-5.744 13.427-5.4 19.95 0.89 15.749 2.735 31.636 6.254 46.975 2.836 12.367 8.814 24.019 13.151 36.043 1.437 4.033 4.242 9.397 2.769 12.367-6.182 12.607-2.358 22.174 6.115 31.842 4.853 5.535 9.121 12.026 12.23 18.722 11.859 25.417 23.947 49.947 50.014 64.982 7.519 4.304 15.378 15.068 15.858 23.294 1.192 22.28 11.65 39.972 23.57 56.852 18.281 25.895 21.147 86.738-34.162 114.413-76.456 38.264-153.741 75.2-232.042 109.395-49.129 21.418-73.726 57.463-82.063 107.922-2.526 15.311-5.878 30.475-7.859 45.847-3.009 22.928-7.823 69.766-7.823 69.766h1024.611c-0.003 0-4.781-46.838-7.787-69.766z" - ], - "width": 1025, - "attrs": [], - "tags": [ - "contactListIcon" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 21, - "id": 26, - "prevSize": 32, - "code": 58901, - "name": "contactList", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 6 - }, - { - "icon": { - "paths": [ - "M1026.175 510.933c0 283.345-229.709 513.051-513.108 513.051-283.348 0-513.069-229.703-513.069-513.051 0-283.384 229.721-513.106 513.069-513.106 283.4-0 513.108 229.721 513.108 513.106z", - "M513.069 1023.985c135.725 0 259.112-52.711 350.874-138.739-9.717-11.65-22.551-21.114-39.113-28.343-58.934-25.745-116.627-54.256-174.534-82.256-41.871-20.322-39.405-66.587-25.639-86.057 8.943-12.692 16.805-25.998 17.728-42.746 0.333-6.169 6.241-14.284 11.889-17.522 19.604-11.304 28.697-29.747 37.604-48.861 2.34-5.031 5.555-9.89 9.229-14.077 6.37-7.243 9.224-14.436 4.572-23.942-1.086-2.209 1.004-6.241 2.105-9.273 3.238-9.067 7.733-17.801 9.861-27.115 2.67-11.549 4.059-23.48 4.701-35.323 0.281-4.902-4.544-10.184-4.033-14.986 2.621-24.022-10.943-42.271-18.598-63.158-9.376-25.714-27.771-41.82-44.005-60.97-3.058-3.623-3.927-9.838-4.188-14.952-0.539-10.981-5.060-16.415-16.544-14.924-4.598 0.601-9.611 1.886-13.843 0.756-3.728-0.988-9.327-4.724-9.534-7.604-1.153-14.539-6.213-16.929-21.065-14.475-9.296 1.543-21.395-6.858-30.513-13.203-7.632-5.292-14.209-7.555-23.069-5.38-3.697 0.9-8.682 0.746-11.815-1.094-3.341-1.976-6.605-3.184-9.867-3.839v-0.552c-0.72 0.013-1.489 0.129-2.209 0.217-0.722-0.088-1.44-0.206-2.157-0.217v0.552c-3.29 0.653-6.574 1.863-9.89 3.839-3.112 1.837-8.091 1.992-11.797 1.094-8.886-2.173-15.448 0.088-23.064 5.38-9.157 6.345-21.222 14.746-30.518 13.203-14.862-2.451-19.94-0.062-21.093 14.475-0.219 2.879-5.793 6.616-9.516 7.604-4.278 1.13-9.247-0.155-13.887-0.756-11.456-1.491-15.987 3.943-16.516 14.924-0.261 5.111-1.13 11.33-4.19 14.952-16.222 19.15-34.616 35.258-44.018 60.97-7.627 20.887-21.204 39.136-18.57 63.158 0.511 4.802-4.304 10.083-4.046 14.986 0.655 11.846 2.041 23.776 4.701 35.323 2.131 9.312 6.626 18.048 9.89 27.115 1.094 3.032 3.174 7.062 2.082 9.273-4.649 9.508-1.788 16.702 4.582 23.942 3.674 4.188 6.874 9.046 9.224 14.077 8.899 19.111 17.992 37.557 37.596 48.861 5.653 3.238 11.559 11.353 11.905 17.522 0.913 16.748 8.773 30.054 17.739 42.746 13.745 19.47 15.902 65.245-25.673 86.057-57.52 28.772-115.6 56.511-174.503 82.256-16.57 7.23-29.409 16.694-39.123 28.338 91.759 86.031 215.138 138.744 350.843 138.744z" - ], - "width": 1026, - "attrs": [], - "tags": [ - "avatar" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 22, - "id": 25, - "prevSize": 32, - "code": 58902, - "name": "avatar", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 7 - }, - { - "icon": { - "paths": [ - "M839.334 573.513c0 79.199-64.257 143.461-143.486 143.461-79.174 0-143.431-64.262-143.431-143.461 0-79.227 64.257-143.431 143.431-143.431 79.23 0.003 143.486 64.204 143.486 143.431z", - "M1372.769 253.515c-6.595-39.459-29.496-64.168-70.606-69.276-23.788-2.918-38.256-15.637-44.726-39.040-9.706-35.519-33.678-58.993-67.811-70.76-24.807-8.595-50.3-16.462-76.186-20.491-69.655-10.911-140.51-15.924-209.526-29.943-69.53-14.178-139.053-23.342-208.893-24.073-69.845 0.731-139.371 9.895-208.893 24.073-69.022 14.016-139.876 19.029-209.526 29.94-25.884 4.028-51.385 11.896-76.189 20.491-34.13 11.767-58.105 35.24-67.814 70.76-6.469 23.403-20.934 36.122-44.723 39.040-41.105 5.108-64.006 29.82-70.601 69.278-6.788 40.41-11.737 81.202-16.811 121.885-2.728 22.109 6.405 32.576 30.386 32.448 120.839-0.697 241.692-0.697 362.595-0.095 24.045 0.128 33.115-9.388 33.433-33.338 0.762-57.369-4.631-111.895-47.136-156.618-7.041-7.39-10.849-25.281-6.726-33.846 4.062-8.5 40.856-16.716 45.992-16.716 43.328 0.19 43.138 0.223 49.418 43.423 1.205 8.28 2.539 18.46 7.803 23.853 30.319 30.863 21.252 66.706 7.234 97.634-30.389 67.139-61.537 134.827-100.867 196.869-73.458 115.831-104.41 160.744-198.679 260.844-58.675 62.293-68.573 101.687-68.573 137.466 0 70.989 41.038 96.744 137.148 96.744 181.614 0 260.908-0.315 442.528-0.315 181.614 0 260.905 0.315 442.528 0.315 96.102 0 137.142-25.752 137.142-96.744 0-35.779-9.898-75.173-68.573-137.466-94.264-100.1-125.222-145.012-198.679-260.844-39.333-62.042-70.475-129.73-100.861-196.869-14.019-30.927-23.091-66.77 7.234-97.634 5.264-5.393 6.595-15.575 7.803-23.853 6.28-43.202 6.090-43.233 49.412-43.423 5.139 0 41.933 8.216 45.992 16.716 4.126 8.565 0.318 26.453-6.723 33.846-42.502 44.723-47.898 99.249-47.136 156.618 0.315 23.947 9.388 33.466 33.43 33.338 120.909-0.603 241.753-0.603 362.601 0.095 23.975 0.126 33.109-10.342 30.383-32.448-5.075-40.686-10.018-81.475-16.806-121.885zM959.991 576.495c0 146.315-118.624 264.936-264.97 264.936s-264.973-118.621-264.973-264.936c0-146.318 118.624-264.936 264.973-264.936 146.343-0 264.97 118.621 264.97 264.936z" - ], - "width": 1390, - "attrs": [], - "tags": [ - "callRetro" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 17, - "id": 24, - "prevSize": 32, - "code": 58897, - "name": "callRetro", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 8 - }, - { - "icon": { - "paths": [ - "M310.262 929.57c0 52.13-42.207 94.43-94.399 94.43h-121.405c-52.195 0-94.458-42.3-94.458-94.43v-835.67c0-52.158 42.266-94.458 94.458-94.458h121.403c52.195 0 94.399 42.3 94.399 94.458v835.67z", - "M1077.118-0.56h-561.987c-72.919 0-132.33 60.673-132.33 135.253v754.115c0 74.518 59.411 135.191 132.33 135.191h561.987c72.98 0 132.394-60.673 132.394-135.191v-754.115c0-74.58-59.414-135.253-132.394-135.253zM529.83 133.094h532.653l0.062 143.298h-532.715v-143.298zM643.255 908.372h-113.551v-113.551h113.551v113.551zM643.255 703.252h-113.551v-113.554h113.551v113.554zM643.382 496.244h-113.551v-113.554h113.551v113.554zM852.9 908.372h-113.551v-113.551h113.551v113.551zM852.9 703.252h-113.551v-113.554h113.551v113.554zM853.027 496.244h-113.556v-113.554h113.556v113.554zM1062.548 908.372h-113.556v-113.551h113.556v113.551zM1062.548 703.252h-113.556v-113.554h113.556v113.554zM1062.669 496.244h-113.554v-113.554h113.554v113.554z" - ], - "width": 1210, - "attrs": [], - "tags": [ - "callModern" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 18, - "id": 23, - "prevSize": 32, - "code": 58898, - "name": "callModern", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 9 - }, - { - "icon": { - "paths": [ - "M1123.444 20.985c-23.593-26.481-64.131-28.989-90.74-5.395l-1008.269 893.436c-26.609 23.468-28.991 64.131-5.46 90.676 12.674 14.306 30.308 21.649 48.126 21.649 15.123 0 30.372-5.401 42.544-16.195l130.045-115.22c90.743 81.844 210.569 132.165 342.473 132.101 282.816-0.061 510.913-227.969 511.287-510.972 0.126-109.934-34.682-211.367-93.499-294.72l118.088-104.625c26.483-23.526 28.997-64.129 5.404-90.735zM944.422 510.182c0.128 200.922-161.896 363.201-362.509 362.952-87.56-0.123-167.573-31.151-230.061-82.569l331.277-293.509v73.176c1.071 60.993 32.696 92.18 94.944 93.692 61.997-1.512 93.686-32.763 95.131-93.756v-41.096h-72.227v47.499c0.251 4.642-0.564 10.607-2.511 17.949-1.25 3.261-3.448 6.020-6.525 8.093-3.197 2.572-7.845 3.828-13.868 3.828-10.543-0.31-17.132-4.268-19.827-11.921-1.068-3.512-1.947-6.905-2.508-10.163-0.254-2.887-0.377-5.532-0.377-7.786v-143.511l42.477-37.634c0.215 0.432 0.452 0.851 0.63 1.303 1.947 6.467 2.762 12.799 2.511 19.076v36.772h72.227v-30.121c-0.246-31.245-9.086-54.699-26.363-70.447l40.711-36.069c35.787 56.055 56.803 122.585 56.867 194.244z", - "M239.795 628.53c-12.613-37.023-19.827-76.557-19.827-117.913-0.19-200.236 161.584-362.009 361.945-362.135 56.853 0 110.313 13.302 158.133 36.398l117.846-104.421c-79.444-50.952-173.758-80.817-275.292-80.948-283.377-0.181-511.354 227.729-511.789 511.675-0.126 79.567 18.636 154.679 51.137 221.882l117.848-104.538z", - "M388.576 333.98h-97.514v249.057l72.23-64.070v-0.689h0.815l117.72-104.418c0-0.564 0.123-0.94 0.123-1.509 0.753-53.898-30.369-80.069-93.374-78.37zM405.959 398.483c1.942 2.767 3.074 6.469 3.323 11.112 0.312 4.452 0.438 9.6 0.438 15.246 0.251 10.916-0.689 19.83-2.949 26.985-2.952 7.594-10.983 11.357-24.159 11.357h-19.325v-74.043h15.31c7.842 0 13.865 0.683 18.072 2.19 4.397 1.573 7.468 3.953 9.29 7.153z" - ], - "width": 1140, - "attrs": [], - "tags": [ - "recDisable" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 19, - "id": 22, - "prevSize": 32, - "code": 58899, - "name": "recDisable", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 10 - }, - { - "icon": { - "paths": [ - "M581.278-1.708c284.857 0.19 514.807 230.517 514.427 514.997-0.378 285.047-230.073 514.553-514.869 514.615-284.541 0.062-515.311-230.517-514.933-514.422 0.439-285.936 230.009-515.439 515.375-515.19zM580.579 148.244c-201.764 0.123-364.666 163.032-364.478 364.663 0 202.018 162.524 364.735 364.478 364.984 202.018 0.316 365.174-163.030 365.048-365.423-0.252-201.767-163.156-364.35-365.048-364.224z", - "M287.698 335.093h98.196c63.442-1.767 94.785 24.518 94.027 78.863 0.254 19.081-2.211 34.882-7.456 47.521-6.005 12.508-18.706 21.988-38.167 28.181v0.819c28.373 6.259 43.031 23.573 43.981 51.946v57.689c0 11.247 0.254 22.813 0.758 34.756 0.819 12.005 3.033 20.979 6.696 27.043h-71.846c-3.727-6.064-6.128-15.038-7.14-27.043-1.012-11.943-1.454-23.509-1.138-34.756v-52.321c0-9.603-2.214-16.553-6.573-20.979-4.675-4.107-12.701-6.19-24.012-6.19h-14.599v141.291h-72.73v-326.82zM360.428 465.139h19.463c13.271 0 21.359-3.794 24.331-11.375 2.276-7.204 3.221-16.304 2.969-27.171 0-5.815-0.126-10.867-0.442-15.418-0.252-4.675-1.392-8.404-3.352-11.247-1.831-3.157-4.926-5.561-9.352-7.14-4.233-1.454-10.299-2.211-18.2-2.211h-15.418v74.564z", - "M498.372 335.093h162.082v62.687h-89.35v65.587h78.103v62.685h-78.103v73.11h92.822v62.749h-165.557v-326.818z", - "M682.507 424.001c0.316-31.782 9.416-55.542 27.425-71.407 17.44-15.29 40.185-22.936 68.181-22.936 28.247 0 51.119 7.646 68.623 23 17.82 15.798 26.92 39.623 27.171 71.407v30.333h-72.73v-37.031c0.254-6.192-0.57-12.639-2.527-19.209-1.264-3.157-3.475-5.938-6.573-8.214-3.221-1.515-7.898-2.404-13.964-2.404-10.615 0.316-17.249 3.855-19.967 10.618-2.211 6.573-3.223 13.017-2.907 19.209v161.956c0 2.273 0.126 4.865 0.38 7.772 0.568 3.411 1.454 6.824 2.527 10.233 2.717 7.775 9.352 11.756 19.967 12.007 6.067 0 10.744-1.261 13.964-3.791 3.098-2.15 5.309-4.867 6.573-8.216 1.96-7.33 2.782-13.33 2.527-18.007v-47.837h72.73v41.328c-1.451 61.547-33.364 93.015-95.794 94.469-62.685-1.454-94.53-32.922-95.607-94.343v-148.937z" - ], - "width": 1142, - "attrs": [], - "tags": [ - "recEnable" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 20, - "id": 21, - "prevSize": 32, - "code": 58900, - "name": "recEnable", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 11 - }, - { - "icon": { - "paths": [ - "M513.036 0c283.57 0.188 512.414 229.474 512.037 512.664-0.377 283.756-228.965 512.228-512.541 512.288-283.191 0.067-512.912-229.474-512.533-512.099 0.374-284.638 228.965-513.103 513.036-512.853zM512.285 149.271c-200.79 0.126-362.957 162.291-362.831 363.014 0 201.105 161.788 363.081 362.831 363.334 201.164 0.312 363.581-162.294 363.455-363.772-0.25-200.852-162.417-362.702-363.455-362.575z", - "M597.392 512.412h-0.503l-0.126-0.126h0.63l115.615-115.866c0 0-78.247-78.505-82.153-82.153l-117.754 116.183-119.014-118.196-82.024 82.279 88.815 88.818 26.674 29.061h0.503l0.253 0.253h-0.756l-115.489 115.806c0 0 78.249 78.564 82.024 82.212l117.76-116.245 119.008 118.26 82.153-82.406-88.815-88.82-26.8-29.061z" - ], - "width": 1025, - "attrs": [], - "tags": [ - "kickUser1" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 16, - "id": 20, - "prevSize": 32, - "code": 58895, - "name": "kick1", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 12 - }, - { - "icon": { - "paths": [ - "M66.491 1023.997h1027.94z", - "M1198.596 472.014c-135.702-135.893-271.415-271.66-407.367-407.241-6.244-6.089-13.868-11.714-21.867-14.653-31.236-11.399-63.48 12.808-63.728 47.674-0.253 67.663-0.126 135.331-0.126 202.965 0 4.281 0 8.62 0 13.964-6.123 0-10.87 0-15.62 0-106.247 0-212.334-0.062-318.485 0-35.178 0.031-54.86 19.71-54.86 54.922-0.059 92.778-0.059 185.5 0 278.345 0 35.8 19.682 55.479 55.611 55.479 105.775 0.062 211.423 0 317.11 0 4.877 0 9.622 0 16.245 0 0 5.375 0 9.374 0 13.309 0 66.793 0.25 133.703 0 200.496 0 23.057 9.247 40.241 30.242 49.547 21.116 9.371 39.361 2.81 55.231-12.937 135.955-136.079 272.031-272.034 407.989-408.175 23.49-23.431 23.24-50.112-0.374-73.695z", - "M532.596 915.271c-2.627-19.62-22.055-32.116-27.928-35.426-8.811-5.186-18.371-5.811-25.683-5.811l-6.37 0.126-227.926-0.188c-56.042-0.124-98.468-42.173-98.591-97.717-0.188-177.127-0.188-354.321 0.065-531.51 0.059-53.983 42.671-96.53 96.968-96.811l235.922-0.062c33.426-0.031 51.294-16.121 54.481-49.235 1.001-12.965 0.81-26.052 0.439-39.172-1.128-39.737-19.369-57.481-59.107-57.512l-217.866 0.121c-15.494 0-30.926 0.562-46.361 2.343-115.52 13.154-207.555 113.649-209.681 228.798-1.313 63.888-0.996 127.804-0.684 191.718l0.186 60.201h-0.377c0 0-0.121 227.954 0.065 289.811 0.248 135.702 101.528 240.796 235.545 244.48 33.176 0.875 66.419 1.189 99.654 1.189h0.065l148.012-0.753c29.368 0 47.483-17.37 49.73-47.545 1.755-22.058 1.628-40.173-0.557-57.045z" - ], - "width": 1216, - "attrs": [], - "tags": [ - "kickUser" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 15, - "id": 19, - "prevSize": 32, - "code": 58896, - "name": "kick", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 13 - }, - { - "icon": { - "paths": [ - "M955.816-0.317h-822.841c-73.303 0-132.975 60.931-132.975 135.844v542.186c0 74.851 59.672 135.785 132.975 135.785h822.841c73.239 0 132.916-60.934 132.916-135.785v-542.186c0-74.913-59.677-135.844-132.916-135.844zM949.51 671.216h-810.226v-529.223h810.164l0.062 529.223z", - "M945.219 959.66c0 35.738-28.261 64.66-63.207 64.66h-675.228c-34.949 0-63.209-28.921-63.209-64.66v-29.618c0-35.7 28.261-64.657 63.209-64.657h675.228c34.946 0 63.207 28.957 63.207 64.657v29.618z", - "M776.792 617.566l-302.669-302.605 112.411-112.316 302.545 302.602v112.318z" - ], - "width": 1089, - "attrs": [], - "tags": [ - "shareDesktop" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 14, - "id": 18, - "prevSize": 32, - "code": 58882, - "name": "share-desktop", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 14 - }, - { - "icon": { - "paths": [ - "M953.901-2.387h-819.775c-72.965 0-132.418 60.712-132.418 135.344v540.168c0 74.567 59.453 135.279 132.418 135.279h35.823v212.891l344.966-212.891h438.986c72.963 0 132.415-60.709 132.415-135.279v-540.168c0.003-74.632-59.45-135.344-132.415-135.344zM494.429 666.646l-195.769 124.001v-124.001h-158.184v-527.252h807.078l0.124 527.252h-453.249z" - ], - "width": 1089, - "attrs": [], - "tags": [ - "chatNoLines" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 13, - "id": 17, - "prevSize": 32, - "code": 58886, - "name": "chat-simple", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 15 - }, - { - "icon": { - "paths": [ - "M952.366-0.134h-820.477c-73.027 0-132.531 60.761-132.531 135.455v752.358c0 74.66 59.504 135.424 132.531 135.424h820.48c73.089 0 132.596-60.766 132.596-135.424v-752.358c-0.003-74.694-59.507-135.455-132.599-135.455zM946.135 881.199h-807.894v-739.462h807.834l0.059 739.462z", - "M569.742 448.125l91.772-96.865-77.305-77.308 316.393-85.040-84.981 316.391-75.357-75.293-91.834 96.865z", - "M514.763 575.437l-91.767 96.865 77.3 77.305-316.388 85.043 84.979-316.388 75.357 75.29 91.834-96.871z" - ], - "width": 1089, - "attrs": [], - "tags": [ - "fullScreen 1" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 12, - "id": 16, - "prevSize": 32, - "code": 58893, - "name": "full-screen", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 16 - }, - { - "icon": { - "paths": [ - "M953.225 0.82h-820.663c-73.045 0-132.562 60.776-132.562 135.488v752.525c0 74.647 59.517 135.421 132.562 135.421h820.66c73.107 0 132.624-60.776 132.624-135.421v-752.525c0.003-74.712-59.515-135.488-132.622-135.488zM946.994 882.353h-808.079v-739.596h808.017l0.062 739.596z", - "M915.539 253.3l-91.795 96.889 77.326 77.323-316.463 85.030 84.999-316.463 75.373 75.339 91.852-96.889z", - "M170.625 771.779l91.793-96.884-77.323-77.326 316.463-85.028-84.997 316.46-75.373-75.342-91.857 96.891z" - ], - "width": 1089, - "attrs": [], - "tags": [ - "exitFullScreen 1" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 11, - "id": 15, - "prevSize": 32, - "code": 58894, - "name": "exit-full-screen", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 17 - }, - { - "icon": { - "paths": [ - "M512.356-0c-282.456 0-512.356 229.838-512.356 512.478 0 282.389 229.9 512.227 512.356 512.227 282.515 0 512.414-229.838 512.414-512.227 0-282.64-229.9-512.478-512.414-512.478zM512.356 945.144c-238.545 0-432.671-194.126-432.671-432.666 0-238.796 194.126-432.858 432.671-432.858 238.601 0 432.856 194.062 432.856 432.858 0 238.54-194.255 432.666-432.856 432.666z", - "M512.545 105.038c-224.755 0-407.508 182.75-407.508 407.315 0 224.563 182.75 407.315 407.508 407.315 224.437 0 407.187-182.755 407.187-407.315-0.003-224.566-182.75-407.315-407.187-407.315zM512.545 832.677c-176.715 0-320.453-143.804-320.453-320.324 0-176.523 143.737-320.324 320.453-320.324 176.523 0 320.196 143.802 320.196 320.324 0 176.52-143.673 320.324-320.196 320.324z", - "M283.851 397.211l-0.954 1.398v234.413l0.954 1.398c15.757 23.060 36.473 44.542 61.699 63.797l8.961 6.801v-378.341l-8.961 6.735c-25.1 19.191-45.814 40.544-61.699 63.799z", - "M415.637 294.271l-3.621 1.334v440.36l3.621 1.398c18.683 7.055 38.887 11.94 61.766 14.931l6.224 0.762v-474.415l-6.163 0.762c-22.237 2.795-43.016 7.753-61.827 14.869z", - "M547.367 279.401l-6.165-0.762v474.415l6.165-0.762c22.301-2.793 43.077-7.811 61.763-14.864l3.685-1.4v-440.488l-3.685-1.334c-18.811-7.053-39.525-12.010-61.763-14.805z", - "M740.98 397.211c-15.692-23.002-36.473-44.48-61.699-63.797l-8.894-6.86v378.469l8.894-6.801c25.351-19.381 46.132-40.862 61.699-63.861l0.89-1.398v-234.352l-0.89-1.4z" - ], - "width": 1025, - "attrs": [], - "tags": [ - "prezisimple" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 10, - "id": 14, - "prevSize": 32, - "code": 58892, - "name": "prezi", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 18 - }, - { - "icon": { - "paths": [ - "M831.678 943.614h-144.885v-258.653c-45.729-29.159-41.794-84.953-24.574-109.307 11.939-16.905 22.43-34.662 23.663-57.004 0.423-8.241 8.303-19.031 15.847-23.364 26.122-15.037 38.223-39.632 50.12-65.116 3.143-6.714 7.392-13.187 12.3-18.753 8.471-9.686 12.295-19.264 6.115-31.922-1.466-2.972 1.318-8.326 2.779-12.362 4.335-12.106 10.326-23.745 13.169-36.148 3.522-15.399 5.398-31.305 6.244-47.086 0.379-6.543-6.074-13.574-5.351-19.986 3.486-32.030-14.612-56.346-24.785-84.189-12.509-34.28-37.036-55.732-58.681-81.26-4.074-4.843-5.225-13.125-5.563-19.942-0.722-14.63-6.752-21.875-22.048-19.898-6.161 0.805-12.808 2.526-18.474 1.019-4.969-1.316-12.408-6.288-12.702-10.13-1.553-19.393-8.285-22.577-28.098-19.305-12.406 2.062-28.527-9.134-40.677-17.587-10.15-7.049-18.941-10.065-30.751-7.175-4.928 1.187-11.598 0.973-15.716-1.466-4.461-2.634-8.837-4.226-13.169-5.119v-0.722c-0.975 0-1.976 0.17-2.934 0.276-0.975-0.106-1.951-0.276-2.908-0.276v0.722c-4.355 0.893-8.726 2.485-13.169 5.119-4.167 2.441-10.811 2.652-15.718 1.466-11.851-2.89-20.598 0.126-30.751 7.175-12.212 8.453-28.287 19.648-40.671 17.587-19.816-3.272-26.591-0.085-28.119 19.305-0.299 3.844-7.73 8.816-12.7 10.13-5.692 1.509-12.32-0.212-18.497-1.019-15.27-1.976-21.302 5.269-22.024 19.898-0.338 6.819-1.486 15.102-5.565 19.942-21.622 25.528-46.154 46.98-58.684 81.26-10.171 27.843-28.271 52.161-24.765 84.189 0.699 6.412-5.736 13.443-5.395 19.986 0.87 15.78 2.74 31.687 6.267 47.086 2.843 12.403 8.835 24.042 13.187 36.148 1.466 4.033 4.229 9.387 2.784 12.362-6.203 12.658-2.379 22.236 6.115 31.922 4.887 5.565 9.134 12.039 12.277 18.753 11.874 25.484 24.001 50.079 50.125 65.116 7.516 4.332 15.417 15.122 15.863 23.364 1.21 22.342 11.701 40.099 23.64 57.004 18.33 25.954 21.194 86.95-34.216 114.687-76.673 38.336-154.083 75.357-232.624 109.632-49.189 21.498-73.891 57.6-82.238 108.192-2.549 15.331-5.862 30.539-7.88 45.961-3.014 22.956-7.839 69.874-7.839 69.874h831.678v-80.386z", - "M1188.556 879.11h-144.89v144.89h-147.481v-144.89h-144.885v-147.481h144.885v-144.888h147.481v144.888h144.89v147.481z" - ], - "width": 1189, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "tags": [ - "addNew-V5" - ], - "grid": 0 - }, - "attrs": [ - { - "opacity": 1, - "visibility": false - }, - { - "opacity": 1, - "visibility": false - } - ], - "properties": { - "order": 26, - "id": 30, - "prevSize": 32, - "code": 58880, - "name": "addNew-V5", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 19 - }, - { - "icon": { - "paths": [ - "M956.063-2.932h-819.824c-73.036 0-132.489 60.717-132.489 135.316v540.205c0 74.537 59.453 135.246 132.489 135.246h35.826v212.941l344.987-212.941h439.011c72.964 0 132.42-60.711 132.42-135.246v-540.202c0-74.602-59.456-135.318-132.42-135.318zM496.5 666.113l-195.714 123.997v-123.997h-158.261v-527.257h807.189l0.064 527.255h-453.278z", - "M239.062 244.446h605.126v110.62h-605.126v-110.62z", - "M239.062 437.524h605.126v110.615h-605.126v-110.615z" - ], - "width": 1088, - "attrs": [], - "tags": [ - "chat" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 1, - "id": 11, - "prevSize": 32, - "code": 58881, - "name": "chat", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 20 - }, - { - "icon": { - "paths": [ - "M952.495 4.935h-818.689c-72.81 0-132.183 60.63-132.183 135.162v750.719c0 74.473 59.372 135.101 132.183 135.101h818.686c72.936 0 132.314-60.625 132.314-135.101v-750.722c0.003-74.532-59.378-135.159-132.311-135.159zM946.346 884.349h-806.14v-737.822h806.015l0.126 737.822z", - "M685.753 285.456h216.911v566.758h-216.911v-566.758z", - "M428.672 413.998h216.911v438.216h-216.911v-438.216z", - "M172.339 542.54h216.161v309.677h-216.161v-309.677z" - ], - "width": 1088, - "attrs": [], - "tags": [ - "presentation" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 3, - "id": 9, - "prevSize": 32, - "code": 58883, - "name": "presentation", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 21 - }, - { - "icon": { - "paths": [ - "M878.259-5.513c-163.545 0-296.573 133.036-296.573 296.612v43.752h-448.909c-73.14 0-132.777 60.909-132.777 135.751v412.768c0 74.777 59.637 135.678 132.777 135.678h564.152c73.265 0 132.919-60.901 132.919-135.678v-412.768c0-70.054-52.267-127.895-119.040-135.009v-44.494c0-92.367 75.154-167.49 167.451-167.49 92.305 0 167.462 75.12 167.462 167.49v77.422c0 35.681 28.883 64.564 64.556 64.564 35.69 0 64.569-28.883 64.569-64.564v-77.422c-0.003-163.576-133.028-296.612-296.587-296.612z" - ], - "width": 1179, - "attrs": [], - "tags": [ - "security" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 5, - "id": 8, - "prevSize": 32, - "code": 58884, - "name": "security", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 22 - }, - { - "icon": { - "paths": [ - "M1.518 318.386h277.533v-319.798c0 0-78.033 8.102-176.18 111.633-98.139 103.529-101.353 208.165-101.353 208.165z", - "M683.281-1.412h-339.684v384.596l-342.080-0.251-1.515-3.468v510.502c0 73.845 61.4 133.979 136.847 133.979h546.434c75.514 0 136.911-60.137 136.911-133.979v-757.403c-0.003-73.843-61.397-133.976-136.914-133.976zM691.854 814.836h-572.848v-92.788h572.845v92.788zM691.854 621.198h-572.848v-92.783h572.845v92.783z" - ], - "width": 820, - "attrs": [], - "tags": [ - "shareDoc" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 6, - "id": 7, - "prevSize": 32, - "code": 58885, - "name": "share-doc", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 23 - }, - { - "icon": { - "paths": [ - "M709.515 339.906v-44.455c0-163.090-132.662-295.749-295.749-295.749-163.093 0-295.752 132.659-295.752 295.749v44.455c-66.226 7.393-118.013 64.915-118.013 134.607v411.623c0 74.629 59.481 135.365 132.472 135.365h562.583c73.059 0 132.534-60.736 132.534-135.365v-411.623c-0-69.697-51.792-127.219-118.074-134.607zM413.765 128.463c92.043 0 166.987 74.944 166.987 166.987v43.632h-333.978v-43.632c0-92.043 74.883-166.987 166.99-166.987z" - ], - "width": 828, - "attrs": [], - "tags": [ - "securityLock" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 2, - "id": 5, - "prevSize": 32, - "code": 58887, - "name": "security-locked", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 24 - }, - { - "icon": { - "paths": [ - "M1223.934 242.853l-180.299 175.956v-217.848c0-7.661-0.666-15.148-1.902-22.432l73.695-65.346c26.349-23.41 28.841-63.8 5.369-90.24-23.475-26.406-63.803-28.872-90.273-5.4l-1009.019 894.712c-26.408 23.41-28.841 63.806-5.398 90.209 12.607 14.237 30.183 21.539 47.85 21.539 15.076 0 30.214-5.305 42.39-16.1l95.841-84.979c20.995 14.627 46.26 23.232 73.592 23.232h635.191c73.099 0 132.66-60.807 132.66-135.537v-172.868l193.659 153.955c48.815 35.46 96.765-5.248 96.765-40.584v-483.829c0.003-35.305-55.933-71.386-110.123-24.44zM601.515 760.552c-58.81 0-112.566-20.216-155.526-53.797l82.93-73.533c20.863 11.665 44.849 18.386 70.47 18.386 80.533 0 145.832-65.299 145.832-145.835 0-19.421-3.896-37.857-10.857-54.713l86.847-77.001c22.848 38.259 36.012 82.969 36.012 130.782 0 141.214-114.493 255.71-255.707 255.71z", - "M345.797 504.84c0-141.216 114.496-255.715 255.717-255.715 21.501 0 42.075 3.434 61.986 8.429l216.757-192.191h-604.474c-73.138 0-132.697 60.838-132.697 135.597v518.074l205.894-182.543c-1.308-10.486-3.184-20.853-3.184-31.651z" - ], - "width": 1334, - "attrs": [], - "tags": [ - "disableWebCam" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 7, - "id": 3, - "prevSize": 32, - "code": 58889, - "name": "camera-disabled", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 25 - }, - { - "icon": { - "paths": [ - "M1121.124 21.134c-23.48-26.413-63.883-28.849-90.296-5.372l-1009.306 894.905c-26.413 23.418-28.852 63.816-5.434 90.232 12.612 14.243 30.224 21.547 47.893 21.547 15.050 0 30.224-5.307 42.403-16.108l257.072-227.934c33.225 22.863 69.988 39.678 108.611 49.713-70.191 35.653-118.771 107.715-118.771 191.894h431.872c0-85.737-50.329-159.115-122.765-194.079 54.95-14.49 105.842-39.965 147.497-77.496 51.888-46.712 113.712-131.515 113.712-270.329v-130.323c0-18.812-7.924-35.767-20.585-47.798l212.664-188.558c26.419-23.477 28.849-63.816 5.434-90.294zM791.535 478.109c0 157.985-117.649 229.923-226.99 229.923-35.214 0-68.659-7.217-98.285-20.786l55.735-49.416c14.733 4.59 30.356 7.132 46.609 7.132 89.357 0 161.984-72.687 161.984-161.979v-30.1l60.947-54.042v79.269z", - "M730.589 166.133c0-89.298-72.625-161.984-161.984-161.984-89.298 0-161.984 72.687-161.984 161.984v316.85c0 0.25 0 0.498 0 0.748l323.969-287.25v-30.348z", - "M350.795 533.31c-3.246-17.483-5.119-35.782-5.119-55.201v-130.323c0-36.406-29.6-66.004-66.006-66.004-36.466 0-66.004 29.597-66.004 66.004v130.323c0 57.198 11.115 107.026 29.099 150.931l108.030-95.73z" - ], - "width": 1137, - "attrs": [], - "tags": [ - "disableMic" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 8, - "id": 2, - "prevSize": 32, - "code": 58890, - "name": "mic-disabled", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 26 - }, - { - "icon": { - "paths": [ - "M858.414 280.056c-36.595 0-66.246 29.652-66.246 66.182v130.725c0 158.421-117.982 230.597-227.635 230.597-58.674 0-112.618-19.87-151.86-55.959-44.23-40.819-67.696-101.203-67.696-174.64v-130.725c0-36.53-29.654-66.182-66.182-66.182-36.53 0-66.182 29.652-66.182 66.182v130.725c0 195.834 119.494 314.763 259.177 351.040-70.408 35.71-119.176 108.014-119.176 192.431h433.118c0-85.993-50.409-159.621-123.029-194.572 55.079-14.64 106.121-40.127 147.886-77.79 52.050-46.877 114.008-131.925 114.008-271.106v-130.725c0-36.53-29.59-66.182-66.184-66.182z", - "M568.571 644.281c-89.589 0-162.459-72.932-162.459-162.521v-317.665c0-89.589 72.87-162.459 162.459-162.459 89.592 0 162.524 72.87 162.524 162.459v317.665c0.003 89.592-72.929 162.521-162.524 162.521z" - ], - "width": 1137, - "attrs": [], - "tags": [ - "mic" - ], - "grid": 0 - }, - "attrs": [], - "properties": { - "order": 9, - "id": 1, - "prevSize": 32, - "code": 58891, - "name": "microphone", - "ligatures": "" - }, - "setIdx": 1, - "setId": 1, - "iconIdx": 27 - } - ], - "height": 1024, - "metadata": { - "name": "jitsi" - }, - "preferences": { - "showGlyphs": true, - "showQuickUse": true, - "showQuickUse2": true, - "showSVGs": true, - "fontPref": { - "prefix": "icon-", - "metadata": { - "fontFamily": "jitsi", - "majorVersion": 1, - "minorVersion": 0 - }, - "metrics": { - "emSize": 1024, - "baseline": 6.25, - "whitespace": 50 - } - }, - "imagePref": { - "prefix": "icon-", - "png": true, - "useClassSelector": true - }, - "historySize": 100, - "showCodes": true, - "search": "" - } -} \ No newline at end of file diff --git a/images/avatar1.png b/images/avatar1.png deleted file mode 100644 index d3e9f351e..000000000 Binary files a/images/avatar1.png and /dev/null differ diff --git a/images/avatar2.png b/images/avatar2.png deleted file mode 100644 index f59231c87..000000000 Binary files a/images/avatar2.png and /dev/null differ diff --git a/images/avatarprezi.png b/images/avatarprezi.png deleted file mode 100644 index 949c49ec6..000000000 Binary files a/images/avatarprezi.png and /dev/null differ diff --git a/images/chatArrow.svg b/images/chatArrow.svg deleted file mode 100644 index f698c28ee..000000000 --- a/images/chatArrow.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - diff --git a/images/chrome.png b/images/chrome.png deleted file mode 100644 index 774be6e89..000000000 Binary files a/images/chrome.png and /dev/null differ diff --git a/images/chromium.png b/images/chromium.png deleted file mode 100644 index ef4516f9d..000000000 Binary files a/images/chromium.png and /dev/null differ diff --git a/images/dropdownPointer.png b/images/dropdownPointer.png deleted file mode 100644 index fcc7d0396..000000000 Binary files a/images/dropdownPointer.png and /dev/null differ diff --git a/images/estoslogo.png b/images/estoslogo.png deleted file mode 100644 index d8e78a831..000000000 Binary files a/images/estoslogo.png and /dev/null differ diff --git a/images/favicon.ico b/images/favicon.ico deleted file mode 100644 index 2197701f7..000000000 Binary files a/images/favicon.ico and /dev/null differ diff --git a/images/firefox-nightly.png b/images/firefox-nightly.png deleted file mode 100644 index 694669624..000000000 Binary files a/images/firefox-nightly.png and /dev/null differ diff --git a/images/firefox.png b/images/firefox.png deleted file mode 100644 index 5e2b110a5..000000000 Binary files a/images/firefox.png and /dev/null differ diff --git a/images/jitsilogo.png b/images/jitsilogo.png deleted file mode 100644 index 51a385452..000000000 Binary files a/images/jitsilogo.png and /dev/null differ diff --git a/images/noMic.png b/images/noMic.png deleted file mode 100644 index 287fd286b..000000000 Binary files a/images/noMic.png and /dev/null differ diff --git a/images/noVideo.png b/images/noVideo.png deleted file mode 100644 index 91cd97b19..000000000 Binary files a/images/noVideo.png and /dev/null differ diff --git a/images/opera.png b/images/opera.png deleted file mode 100644 index e0548b140..000000000 Binary files a/images/opera.png and /dev/null differ diff --git a/images/popupPointer.png b/images/popupPointer.png deleted file mode 100644 index 6beb71cad..000000000 Binary files a/images/popupPointer.png and /dev/null differ diff --git a/images/smile.svg b/images/smile.svg deleted file mode 100644 index cd254bd31..000000000 --- a/images/smile.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley1.svg b/images/smileys/smiley1.svg deleted file mode 100644 index b48703bd6..000000000 --- a/images/smileys/smiley1.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - diff --git a/images/smileys/smiley10.svg b/images/smileys/smiley10.svg deleted file mode 100644 index de0974726..000000000 --- a/images/smileys/smiley10.svg +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - diff --git a/images/smileys/smiley11.svg b/images/smileys/smiley11.svg deleted file mode 100644 index adfd0588f..000000000 --- a/images/smileys/smiley11.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley12.svg b/images/smileys/smiley12.svg deleted file mode 100644 index 94a04dddd..000000000 --- a/images/smileys/smiley12.svg +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley13.svg b/images/smileys/smiley13.svg deleted file mode 100644 index aa873fa9a..000000000 --- a/images/smileys/smiley13.svg +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - diff --git a/images/smileys/smiley14.svg b/images/smileys/smiley14.svg deleted file mode 100644 index 33c5826bc..000000000 --- a/images/smileys/smiley14.svg +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley15.svg b/images/smileys/smiley15.svg deleted file mode 100644 index 48970df1a..000000000 --- a/images/smileys/smiley15.svg +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - diff --git a/images/smileys/smiley16.svg b/images/smileys/smiley16.svg deleted file mode 100644 index 1e369e086..000000000 --- a/images/smileys/smiley16.svg +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley17.svg b/images/smileys/smiley17.svg deleted file mode 100644 index 75ebedddb..000000000 --- a/images/smileys/smiley17.svg +++ /dev/null @@ -1,152 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley18.svg b/images/smileys/smiley18.svg deleted file mode 100644 index dffc3440d..000000000 --- a/images/smileys/smiley18.svg +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley19.svg b/images/smileys/smiley19.svg deleted file mode 100644 index 1b143b8b1..000000000 --- a/images/smileys/smiley19.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - diff --git a/images/smileys/smiley2.svg b/images/smileys/smiley2.svg deleted file mode 100644 index 2b48e0703..000000000 --- a/images/smileys/smiley2.svg +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - diff --git a/images/smileys/smiley20.svg b/images/smileys/smiley20.svg deleted file mode 100644 index dc8832950..000000000 --- a/images/smileys/smiley20.svg +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley21.svg b/images/smileys/smiley21.svg deleted file mode 100644 index 634dd3ac8..000000000 --- a/images/smileys/smiley21.svg +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley3.svg b/images/smileys/smiley3.svg deleted file mode 100644 index 5f29de639..000000000 --- a/images/smileys/smiley3.svg +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley4.svg b/images/smileys/smiley4.svg deleted file mode 100644 index aa6082b8b..000000000 --- a/images/smileys/smiley4.svg +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley5.svg b/images/smileys/smiley5.svg deleted file mode 100644 index 5e2c2b2cc..000000000 --- a/images/smileys/smiley5.svg +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - diff --git a/images/smileys/smiley6.svg b/images/smileys/smiley6.svg deleted file mode 100644 index df46cfbbb..000000000 --- a/images/smileys/smiley6.svg +++ /dev/null @@ -1,116 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley7.svg b/images/smileys/smiley7.svg deleted file mode 100644 index 8eb166b7e..000000000 --- a/images/smileys/smiley7.svg +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley8.svg b/images/smileys/smiley8.svg deleted file mode 100644 index 1e8897cdc..000000000 --- a/images/smileys/smiley8.svg +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/images/smileys/smiley9.svg b/images/smileys/smiley9.svg deleted file mode 100644 index 31fe3cbda..000000000 --- a/images/smileys/smiley9.svg +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - diff --git a/images/videomask.svg b/images/videomask.svg deleted file mode 100644 index 76d67ae80..000000000 --- a/images/videomask.svg +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/images/watermark.png b/images/watermark.png deleted file mode 100644 index 6fa553d3b..000000000 Binary files a/images/watermark.png and /dev/null differ diff --git a/images/welcome_page/bubble.png b/images/welcome_page/bubble.png deleted file mode 100644 index 9a3edc6cc..000000000 Binary files a/images/welcome_page/bubble.png and /dev/null differ diff --git a/images/welcome_page/disable-welcome-selected.png b/images/welcome_page/disable-welcome-selected.png deleted file mode 100644 index 8f64eba94..000000000 Binary files a/images/welcome_page/disable-welcome-selected.png and /dev/null differ diff --git a/images/welcome_page/disable-welcome.png b/images/welcome_page/disable-welcome.png deleted file mode 100644 index a96a753f5..000000000 Binary files a/images/welcome_page/disable-welcome.png and /dev/null differ diff --git a/images/welcome_page/header-big.png b/images/welcome_page/header-big.png deleted file mode 100644 index d845c9d9a..000000000 Binary files a/images/welcome_page/header-big.png and /dev/null differ diff --git a/images/welcome_page/pattern-body.png b/images/welcome_page/pattern-body.png deleted file mode 100644 index 122dbca32..000000000 Binary files a/images/welcome_page/pattern-body.png and /dev/null differ diff --git a/images/welcome_page/pattern-header.png b/images/welcome_page/pattern-header.png deleted file mode 100644 index 83ff8eec3..000000000 Binary files a/images/welcome_page/pattern-header.png and /dev/null differ diff --git a/index.html b/index.html deleted file mode 100644 index 988756984..000000000 --- a/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
- -
-
- jitsi.org - -
-
-
-
- -
- - -
-
-
-
- - -
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- -
-
-
-
-
- - - - - - - - - - -
- - - - - - - - -
- - - - - - - -
- - - - - -
-
-
-
- -
- -
-
- - -
- - -
-
- -
-
-
-
-
- -
-
    -
    -
    -
    - -
    - - -
    - - -
    - -
    - -
    - - diff --git a/interface_config.js b/interface_config.js deleted file mode 100644 index 0317683e8..000000000 --- a/interface_config.js +++ /dev/null @@ -1,23 +0,0 @@ -var interfaceConfig = { - CANVAS_EXTRA: 104, - CANVAS_RADIUS: 7, - SHADOW_COLOR: '#ffffff', - INITIAL_TOOLBAR_TIMEOUT: 20000, - TOOLBAR_TIMEOUT: 4000, - DEFAULT_REMOTE_DISPLAY_NAME: "Fellow Jitster", - DEFAULT_DOMINANT_SPEAKER_DISPLAY_NAME: "speaker", - DEFAULT_LOCAL_DISPLAY_NAME: "me", - SHOW_JITSI_WATERMARK: true, - JITSI_WATERMARK_LINK: "https://jitsi.org", - SHOW_BRAND_WATERMARK: false, - BRAND_WATERMARK_LINK: "", - SHOW_POWERED_BY: false, - GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true, - APP_NAME: "Jitsi Meet", - INVITATION_POWERED_BY: true, - ACTIVE_SPEAKER_AVATAR_SIZE: 100, - /** - * Whether to only show the filmstrip (and hide the toolbar). - */ - filmStripOnly: false -}; diff --git a/lang/Translation.md b/lang/Translation.md deleted file mode 100644 index 2911c3412..000000000 --- a/lang/Translation.md +++ /dev/null @@ -1,57 +0,0 @@ -Jitsi Meet Translation -========================== -Jitsi Meet uses [i18next](http://i18next.com) library for translation. -i18next uses separate json files for each language. - - -Translating Jitsi Meet -====================== -The translation of Jitsi Meet is integrated with Pootle. You can translate Jitsi Meet via our Pootle user interface on -[http://translate.jitsi.org](http://translate.jitsi.org). - -**WARNING: Please don't create or edit manually the language files! Please use our Pootle user interface!** - -Development -=========== -If you want to add new functionality for Jitsi Meet and you have texts that need to be translated please use our translation module. -It is located in modules/translation. You must add key and value in main.json file in English for each translatable text. -Than you can use the key to get the translated text for the current language. - -**WARNING: Please don't change the other language files except main.json! They must be updated and translated via our Pootle user interface!** - -You can add translatable text in the HTML: - - -* **via attribute on HTML element** - add **data-i18n** attribute with value the key of the translatable text. - - - ``` - OK - ``` - - - You can also use APP.translation.generateTranslationHTML(key, options) to get this HTML code as Javascript string. - - - ``` - APP.translation.generateTranslationHTML("dialog.OK") // returns OK - ``` - - The value in the options parameter will be added in data-i18n-options attribute of the element. - - **Note:** If you dynamically add HTML elements don't forget to call APP.translation.translateElement(jquery_selector) to translate the text initially. - -* **via Javascript string** - call APP.translation.translateString(key, options). You can use that method to get the translated string in Javascript and then attach it in the HTML. - - ``` - APP.translation.translateString("dialog.OK") // returns the value for the key of the current language file. "OK" for example. - ``` - -For the available values of ``options`` parameter for the above methods of translation module see [i18next documentation](http://i18next.com/pages/doc_features). - -**Note:** It is useful to add attributes in the HTML for persistent HTML elements because when the language is changed the text will be automatically translated. - Otherwise you should call ``APP.translation.translateString`` and manually change the text every time the language is changed. - - - - diff --git a/lang/languages-bg.json b/lang/languages-bg.json deleted file mode 100644 index cff4ab662..000000000 --- a/lang/languages-bg.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "en": "Английски", - "bg": "Български", - "de": "Немски", - "tr": "Турски", - "it": "Италиански" -} \ No newline at end of file diff --git a/lang/languages-de.json b/lang/languages-de.json deleted file mode 100644 index 149a29e5b..000000000 --- a/lang/languages-de.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "en": "Englisch", - "bg": "Bulgarisch", - "de": "Deutsch", - "tr": "Türkisch", - "it": "Italienisch", - "fr": "Französisch" -} \ No newline at end of file diff --git a/lang/languages-fr.json b/lang/languages-fr.json deleted file mode 100644 index f50dd22d2..000000000 --- a/lang/languages-fr.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "en": "Anglais", - "bg": "Bulgare", - "de": "Allemand", - "tr": "Turc", - "it": "Italien" -} \ No newline at end of file diff --git a/lang/languages-it.json b/lang/languages-it.json deleted file mode 100644 index a9831eaed..000000000 --- a/lang/languages-it.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "en": "Inglese", - "bg": "Bulgaro", - "de": "Tedesco", - "tr": "Turco", - "it": "Italiano" -} \ No newline at end of file diff --git a/lang/languages-tr.json b/lang/languages-tr.json deleted file mode 100644 index 2d089e711..000000000 --- a/lang/languages-tr.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "en": "İngilizce", - "bg": "Bulgarca", - "de": "Almanca" -} \ No newline at end of file diff --git a/lang/languages.json b/lang/languages.json deleted file mode 100644 index b76ea1a15..000000000 --- a/lang/languages.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "en": "English", - "bg": "Bulgarian", - "de": "German", - "tr": "Turkish", - "it": "Italian", - "fr": "French" -} diff --git a/lang/main-bg.json b/lang/main-bg.json deleted file mode 100644 index da2cfebab..000000000 --- a/lang/main-bg.json +++ /dev/null @@ -1,224 +0,0 @@ -{ - "contactlist": "СПИСЪК С КОНТАКТИ", - "connectionsettings": "Настройки на връзката", - "poweredby": "powered by", - "downloadlogs": "Изтегли логовете", - "roomUrlDefaultMsg": "Конференцията се създава...", - "participant": "Участник", - "me": "аз", - "speaker": "Говорител", - "defaultNickname": "например __name__", - "defaultPreziLink": "например __url__", - "welcomepage": { - "go": "Влез", - "roomname": "Въведете име на стаята", - "disable": "Не показвай страницата следващия път", - "feature1": { - "title": "Лесен за употреба", - "content": "Не е необходимо да сваляте нищо. _app_ работи директно във вашия браузър. Просто споделете адреса на вашата конференция с другите за да започнете." - }, - "feature2": { - "title": "", - "content": "Видео конференциите могат да работят с по-малко от 128Kbps, а аудио конференциите и конференциите с споделен екран дори с по-малко." - }, - "feature3": { - "title": "Отворен код", - "content": "__app__ е лицензиран под MIT лиценз. Можете свободно да го изтеглите, използвате, променяте и споделяте според тези лицензи." - }, - "feature4": { - "title": "Неограничен брой потребители", - "content": "Няма изкуствени ограничения за броя на потребителите или участниците в конференция. Единствените ограничения са мощността на вашия сървър и качеството на интернет връзката му." - }, - "feature5": { - "title": "Споделяне на екрана", - "content": "Лесно е да споделите екрана си с другите. __app__ е идеален за онлайн презентации, лекции и техническа подръжка." - }, - "feature6": { - "title": "Сигурни стаи", - "content": "Нуждаете се от уединение? _app__ конферентните стай могат да бъдат защитени от парола за да се препазите от нежелани гости или прекъсвания." - }, - "feature7": { - "title": "Споделени бележки", - "content": "__app__ използва Etherpad, с който можете да редактирате текст в реално време заедно." - }, - "feature8": { - "title": "Статистики за използване", - "content": "Научете повече за своите потребители като интегрирате лесно Piwik, Google Analytics и други статистики за изполването." - } - }, - "toolbar": { - "mute": "Включи / Изключи микрофона", - "videomute": "Спри / пусни камерата", - "authenticate": "", - "record": "Запис", - "lock": "Заключи / отключи стаята", - "invite": "Поканване на други", - "chat": "", - "prezi": "Сподели Prezi", - "etherpad": "Споделяне на документ", - "sharescreen": "Споделяне на екрана", - "fullscreen": "Влез / Излез от Пълен екран", - "sip": "Обади се на SIP номер", - "Settings": "Настройки", - "hangup": "Затвори", - "login": "Влез", - "logout": "" - }, - "bottomtoolbar": { - "chat": "Отвори / затвори чат", - "filmstrip": "Покажи / скрий лентата с видеа", - "contactlist": "Отвори / затвори контакт листа" - }, - "chat": { - "nickname": { - "title": "Въведете име в полето", - "popover": "Избор на име" - }, - "messagebox": "Въведете текст..." - }, - "settings": { - "title": "НАСТРОЙКИ", - "update": "Актуализиране", - "name": "Име" - }, - "videothumbnail": { - "editnickname": "Натиснете за да
    промените името", - "moderator": "Създателя на
    конференцията", - "videomute": "Учасника е спрял
    камерата си.", - "mute": "Учасника е с изключен микрофон", - "kick": "Изгони", - "muted": "Изключен микрофон", - "domute": "Изключи микрофона" - }, - "connectionindicator": { - "bitrate": "", - "packetloss": "Загуба на пакети:", - "resolution": "Резолюция:", - "less": "Скрий", - "more": "Покажи", - "address": "Адрес:", - "remoteport": "Отдалечен порт:", - "remoteport_plural": "Отдалечени портове:", - "localport": "Локален порт:", - "localport_plural": "Локални портове:", - "localaddress": "Локален адрес:", - "localaddress_plural": "Локални адреси:", - "remoteaddress": "Отдалечен адрес:", - "remoteaddress_plural": "Отдалечени адреси:", - "transport": "Транспорт:", - "bandwidth": "", - "na": "Върнете се тук за информацията относно вашата връзка, когато започне конференцията" - }, - "notify": { - "disconnected": "връзката е прекъсната", - "moderator": "Придобихте права на модератор!", - "connected": "свързан", - "somebody": "Някой", - "me": "Аз", - "focus": "Конферентен фокус", - "focusFail": "__component__ не е на раположения - следващ опит след __ms__ секунди", - "grantedTo": "Даване на роля модератор на __to__!", - "grantedToUnknown": "Даване на роля модератор на $t(somebody)!" - }, - "dialog": { - "kickMessage": "Бяхте изгонен от срещата!", - "popupError": "Вашия браузър блокира попъп прозорците от този сайт. Моля позволете попъп прозорците от настройките на браузъра и опитайте пак.", - "passwordError": "Тази конференция е защитена с парола. Само създателя и може да промени паролата.", - "passwordError2": "Тази конференция не е защитена с парола. Само създателя и може да сложи парола.", - "joinError": "Не можете да се присъедините към конференцията. Може би имате проблем с конфигурацията на сифурността. Моля обърнете се към администратора на услугата.", - "connectError": "Опа! Нещо се обърка и не успяхме да се свържем с конференцията.", - "connecting": "", - "error": "", - "detectext": "Възникна грешка при опит да бъде намерено разширението за споделяне на екран.", - "failtoinstall": "Неуспешна инсталация на разширението за споделяне на екрана.", - "failedpermissions": "Неуспешен опит за получаване на права за използване на микрофон и/или камера.", - "bridgeUnavailable": "Jitsi Videobridge не е наличен. Моля опитайте пак!", - "lockTitle": "Неуспешно заключване", - "lockMessage": "Неуспешно заключване на конференцията.", - "warning": "Внимание", - "passwordNotSupported": "В момента не поддържаме стаи с пароли.", - "sorry": "Съжаляваме", - "internalError": "Вътрешна грешка [setRemoteDescription]", - "unableToSwitch": "Неуспешен опит за смяна на видеото.", - "SLDFailure": "Опа! Нещо се обърка и не успяхме да спрем микрофона! (SLD Failure)", - "SRDFailure": "Опа! Нещо се обърка и не успяхме да спрем камерата! (SRD Failure)", - "oops": "Опа!", - "defaultError": "Възникна грешка", - "passwordRequired": "Изисква се парола", - "Ok": "ОК", - "removePreziTitle": "Премахни Prezi", - "removePreziMsg": "Сигурни ли сте, че искате да премахнете Prezi?", - "sharePreziTitle": "Сподели Prezi", - "sharePreziMsg": "Друг участник вече е споделил Prezi. Тази конференция позволява само да се споделя само едно Prezi.", - "Remove": "Премахване", - "Stop": "Спиране", - "AuthMsg": "Нужна е идентификация, за да създадете стая:
    __room__
    Може да се идентифицирате, за да създадете стая или да изчакате някой друг да го направи.", - "Authenticate": "Идентификация", - "Cancel": "Отказ", - "retry": "Повторен опит", - "logoutTitle": "Изход", - "logoutQuestion": "Сигурни ли сте, че искате да излезете и да прекъснете конференцията?", - "sessTerminated": "Сесията е прекъсната.", - "hungUp": "Вие затворихте обаждането.", - "joinAgain": "Песъединете се отново", - "Share": "Споделяне", - "preziLinkError": "Моля въведете правилен Prezi линк.", - "Save": "Запазване", - "recordingToken": "Въведете код за достъп за запис на конференцията", - "Dial": "Набиране", - "sipMsg": "Въведете SIP номер", - "passwordCheck": "Сигурни ли сте, че искате да махнете паролата?", - "passwordMsg": "Въведете парола, за да заключите стаята", - "Invite": "Покани", - "shareLink": "Сподели този линк с всеки, който искаш да поканиш", - "settings1": "Конфигурирай конференцията", - "settings2": "Участниците се присъединиха с изключен микрофон.", - "settings3": "Изисквай имена

    Въведете парола за да заключите стаята:", - "yourPassword": "вашата парола", - "Back": "Назад", - "serviceUnavailable": "Услугата не е налична", - "gracefulShutdown": "Услугата временно не е достъпна поради профилактика. Моля опитайте по-късно.", - "Yes": "Да", - "reservationError": "Грешка в системата за резервации", - "reservationErrorMsg": "Грешка номер: __code__, съобщение: __msg__", - "password": "парола", - "userPassword": "потребителска парола", - "token": "код за достъп" - }, - "email": { - "sharedKey": [ - "Тази конференция е защитена с парола. Моля използвайте следния код за да се присъедините:", - "", - "", - "__sharedKey__", - "", - "" - ], - "subject": "Покана за __appName__ (__conferenceName__)", - "body": [ - "Здравей, Бих искал да те поканя в една __appName__ конференция, която създадох.", - "", - "", - "Кликни на следния линк за да се присъединиш в конференцията.", - "", - "", - "__sharedKeyText__", - "__appName__ поддържа __supportedBrowsers__, така че трябва да използваш един от тези браузъри.", - "", - "", - "Ще се видим след секунда!" - ], - "and": "и" - }, - "connection": { - "ERROR": "Грешка", - "CONNECTING": "Свързване", - "CONNFAIL": "Връзката е неуспешна", - "AUTHENTICATING": "Идентификация", - "AUTHFAIL": "Неуспешна идентификация", - "CONNECTED": "Свързан", - "DISCONNECTED": "Изключен", - "DISCONNECTING": "Прекъсване на връзката", - "ATTACHED": "Прикрепен" - } -} \ No newline at end of file diff --git a/lang/main-de.json b/lang/main-de.json deleted file mode 100644 index d15d3e06b..000000000 --- a/lang/main-de.json +++ /dev/null @@ -1,243 +0,0 @@ -{ - "contactlist": "Kontaktliste", - "connectionsettings": "Verbindungseinstellungen", - "poweredby": "Betrieben von", - "downloadlogs": "Log herunterladen", - "roomUrlDefaultMsg": "Die Konferenz wird erstellt...", - "participant": "Teilnehmer", - "me": "ich", - "speaker": "Sprecher", - "defaultNickname": "Bsp.: __name__", - "defaultPreziLink": "Bsp.: __url__", - "welcomepage": { - "go": "Los", - "roomname": "Raumnamen eingeben", - "disable": "Diese Seite beim nächsten Betreten nicht mehr anzeigen", - "feature1": { - "title": "Einfach zu benutzen", - "content": "Kein Download nötig. __app__ läuft direkt im Browser. Einfach die Konferenzadresse teilen und los geht's." - }, - "feature2": { - "title": "Niedrige Bandbreite", - "content": "Videokonferenzen mit mehreren Teilnehmen mit weniger als 128Kpbs. Bildschirmfreigaben und Telefonkonferenzen kommen sogar mit noch weniger Bandbreite aus." - }, - "feature3": { - "title": "Open Source", - "content": "__app__ steht unter der MIT Lizenz. __app__ kann gemäss der Lizenz heruntergeladen, verwendet, verändert und weitergegeben werden." - }, - "feature4": { - "title": "Unbegrenzte Anzahl Benutzer", - "content": "Es gibt keine künstliche Beschränkung der Anzahl der Benutzer oder Konferenzteilnehmer. Die Leistung des Servers und die Bandbreite sind die einzigen limitierenden Faktoren." - }, - "feature5": { - "title": "Bildschirmfreigabe", - "content": "Es ist ganz einfach den Bildschirm zu teilen. __app__ ist ideal für Online-Präsentationen, Vorlesungen und Fernwartungsanfragen." - }, - "feature6": { - "title": "Sichere Konferenzen", - "content": "Privatsphäre gewünscht? __app__ Konferenzen können mit einem Passwort geschützt werden um ungebetene Gäste fernzuhalten und Unterbrechungen zu vermeiden." - }, - "feature7": { - "title": "Freigegebene Notizen", - "content": "__app__ verwendent Etherpad, ein Editor zur kollaborativen Bearbeitung von Texten." - }, - "feature8": { - "title": "Benutzungsstatistiken", - "content": "Die Verwendung kann durch die Integration mit Piwik, Google Analytics und anderen Überwachungs- und Statistikprogrammen protokolliert werden." - } - }, - "toolbar": { - "mute": "Stummschaltung aktivieren / deaktivieren", - "videomute": "Kamera starten / stoppen", - "authenticate": "Anmelden", - "record": "Aufnehmen", - "lock": "Raum schützen / Schutz aufheben", - "invite": "Andere einladen", - "chat": "Chat öffnen / schliessen", - "prezi": "Prezi freigeben", - "etherpad": "Geteiltes Dokument", - "sharescreen": "Bildschirm freigeben", - "fullscreen": "Vollbildmodus aktivieren / deaktivieren", - "sip": "SIP Nummer anrufen", - "Settings": "Einstellungen", - "hangup": "Auflegen", - "login": "Anmelden", - "logout": "Abmelden", - "dialpad": "Tastenblock anzeigen" - }, - "bottomtoolbar": { - "chat": "Chat öffnen / schliessen", - "filmstrip": "Videovorschauen anzeigen / verstecken", - "contactlist": "Kontaktliste öffnen / schliessen" - }, - "chat": { - "nickname": { - "title": "Nickname im Eingabefeld eingeben", - "popover": "Einen Namen auswählen" - }, - "messagebox": "Text eingeben..." - }, - "settings": { - "title": "Einstellungen", - "update": "Aktualisieren", - "name": "Name", - "startAudioMuted": "Stumm beitreten", - "startVideoMuted": "Ohne Video beitreten" - }, - "videothumbnail": { - "editnickname": "Klicken um den Anzeigenamen zu bearbeiten", - "moderator": "Besitzer dieser Konferenz", - "videomute": "Teilnehmer hat die Kamera pausiert.", - "mute": "Teilnehmer ist stumm geschaltet", - "kick": "Hinauswerfen", - "muted": "Stummgeschaltet", - "domute": "Stummschalten" - }, - "connectionindicator": { - "bitrate": "Bitrate:", - "packetloss": "Paketverlust:", - "resolution": "Auflösung:", - "less": "Weniger anzeigen", - "more": "Mehr anzeigen", - "address": "Adresse:", - "remoteport": "Entfernter Port:", - "remoteport_plural": "Entfernte Ports:", - "localport": "Lokaler Port:", - "localport_plural": "Lokale Ports:", - "localaddress": "Lokale Adresse:", - "localaddress_plural": "Lokale Adressen:", - "remoteaddress": "Entfernte Adresse:", - "remoteaddress_plural": "Entfernte Adressen:", - "transport": "Protokoll:", - "bandwidth": "Geschätzte Bandbreite:", - "na": "Verbindungsdaten erneut anzeigen wenn die Konferenz begonnen hat" - }, - "notify": { - "disconnected": "getrennt", - "moderator": "Moderatorenrechte vergeben", - "connected": "verbunden", - "somebody": "Jemand", - "me": "Ich", - "focus": "Konferenz-Organisator", - "focusFail": "__component__ ist im Moment nicht verfügbar - wiederholen in __ms__ Sekunden", - "grantedTo": "Moderatorenrechte an __to__ vergeben.", - "grantedToUnknown": "Moderatorenrechte an $t(somebody) vergeben.", - "muted": "Der Konferenz wurde stumm beigetreten.", - "mutedTitle": "Stummschaltung aktiv." - }, - "dialog": { - "kickMessage": "Oh! Sie wurden aus der Konferenz ausgeschlossen.", - "popupError": "Ihr Browser blockiert Popups von dieser Webseite. Bitte erlauben Sie Popups in den Sicherheitseinstellungen und versuchen Sie es erneut.", - "passwordError": "Diese Konferenz ist mit einem Paswort geschützt. Nur der Besitzer der Konferenz kann ein Passwort vergeben.", - "passwordError2": "Diese Konferenzt ist nicht mit einem Passwort geschützt. Nur der Besitzer der Konferenz kann ein Passwort vergeben.", - "joinError": "Oh! Der Konferenz konnte nicht beigetreten werden. Diese könnte ein Problem mit den Sicherheitseinstellungen sein. Bitte kontaktieren Sie den Administrator des Dienstes.", - "connectError": "Oh! Es hat etwas nicht geklappt und der Konferenz konnte nicht beigetreten werden.", - "connectErrorWithMsg": "Oh! Es hat etwas nicht geklappt und der Konferenz konnte nicht beigetreten werden: __msg__", - "connecting": "Verbindung wird hergestellt", - "error": "Fehler", - "detectext": "Fehler bei der Erkennung der Bildschirmfreigabeerweiterung.", - "failtoinstall": "Die Bildschirmfreigabeerweiterung konnte nicht installiert werden.", - "failedpermissions": "Die Zugriffsberechtigungen auf das Mikrofon und/oder die Kamera konnte nicht eingeholt werden.", - "bridgeUnavailable": "Die Jitsi Videobridge ist momentan nicht erreichbar. Bitte versuchen Sie es später noch einmal.", - "lockTitle": "Sperren fehlgeschlagen", - "lockMessage": "Die Konferenz konnte nicht gesperrt werden.", - "warning": "Warnung", - "passwordNotSupported": "Passwörter für Räume werden nicht unterstützt.", - "sorry": "Entschuldigung", - "internalError": "Interner Anwendungsfehler [setRemoteDescription]", - "unableToSwitch": "Der Videodatenstrom kann nicht gewechselt werden.", - "SLDFailure": "Oh! Die Stummschaltung konnte nicht aktiviert werden. (SLD Fehler)", - "SRDFailure": "Oh! Das Video konnte nicht gestoppt werden. (SRD Fehler)", - "oops": "Oh!", - "defaultError": "Es ist ein Fehler aufgetreten", - "passwordRequired": "Passwort erforderlich", - "Ok": "OK", - "removePreziTitle": "Prezi entfernen", - "removePreziMsg": "Sind Sie sich sicher dass sie Prezi entfernen möchten?", - "sharePreziTitle": "Ein Prezi teilen", - "sharePreziMsg": "Ein anderer Teilnehmer teilt bereits ein Prezi. Diese Konferenz kann nur eine Prezi auf einmal anzeigen.", - "Remove": "Entfernen", - "WaitingForHost": "Warten auf den Organisator...", - "WaitForHostMsg": "Die Konferenz __room__ hat noch nicht begonnen. Wenn Sie der Organisator sind, melden Sie sich bitte an. Anderenfalls warten Sie bitte bis der Organisator beigetreten ist.", - "IamHost": "Ich bin der Organisator", - "Cancel": "Abbrechen", - "retry": "Wiederholen", - "logoutTitle": "Abmelden", - "logoutQuestion": "Sind Sie sicher dass Sie sich abmelden und die Konferenz verlassen möchten?", - "sessTerminated": "Sitzung beendet", - "hungUp": "Anruf beendet", - "joinAgain": "Erneut beitreten", - "Share": "Teilen", - "preziLinkError": "Bitte einen gültigen Prezi-Link angeben.", - "Save": "Speichern", - "recordingToken": "Aufnahme-Token eingeben", - "Dial": "Wählen", - "sipMsg": "Geben Sie eine SIP Nummer ein", - "passwordCheck": "Sind Sie sicher dass Sie das Passwort entfernen möchten?", - "passwordMsg": "Passwort setzen um den Raum zu schützen", - "Invite": "Einladen", - "shareLink": "Teilen Sie diesen Link mit jedem den Sie einladen möchten", - "settings1": "Konferenz einrichten", - "settings2": "Teilnehmer treten stummgeschaltet bei", - "settings3": "Nickname erforderlich

    Setzen Sie ein Passwort um den Raum zu schützen:", - "yourPassword": "Ihr Passwort", - "Back": "Zurück", - "serviceUnavailable": "Dienst nicht verfügbar", - "gracefulShutdown": "Der Dienst steht momentan wegen Wartungsarbeiten nicht zur Verfügung. Bitte versuchen Sie es später noch einmal.", - "Yes": "Ja", - "reservationError": "Fehler im Reservationssystem", - "reservationErrorMsg": "Fehler, Nummer: __code__, Nachricht: __msg__", - "password": "Passwort", - "userPassword": "Benutzerpasswort", - "token": "Token", - "displayNameRequired": "Geben Sie Ihren Anzeigenamen ein:" - }, - "email": { - "sharedKey": [ - "Diese Konferenz ist Passwortgeschützt. Bitte verwenden Sie diese PIN zum Beitreten:", - "", - "", - "__sharedKey__", - "", - "" - ], - "subject": "Einladung zu einer __appName__ (__conferenceName__)", - "body": [ - "Hallo!", - "", - "", - "Ich möchte dich zu einer eben erstellten __appName__-Konferenz einladen.", - "", - "", - "Bitte klicke auf den folgenden Link um der Konferenz ebenfalls beizutreten:", - "", - "", - "__roomUrl__", - "", - "", - "__sharedKeyText__", - " Bitte beachte, dass __appName__ momentan nur mit einem der Browser __supportedBrowsers__ verwendet werden kann.", - "", - "", - "Bis gleich!" - ], - "and": "und" - }, - "connection": { - "ERROR": "Fehler", - "CONNECTING": "Verbindung wird hergestellt", - "RECONNECTING": "Es ist ein Netzwerkproblem aufgetreten. Verbinde...", - "CONNFAIL": "Verbindungsaufbau gescheitert", - "AUTHENTICATING": "Anmeldung läuft", - "AUTHFAIL": "Authentifizierung fehlgeschlagen", - "CONNECTED": "Verbunden", - "DISCONNECTED": "Getrennt", - "DISCONNECTING": "Verbindung wird getrennt", - "ATTACHED": "Angehängt" - }, - "recording": { - "toaster": "Wird aufgezeichnet", - "pending": "Die Aufzeichnung wird gestartet sobald ein weiterer Teilnehmer beitritt", - "on": "Aufzeichnung wurde gestartet" - } -} \ No newline at end of file diff --git a/lang/main-fr.json b/lang/main-fr.json deleted file mode 100644 index 8d2d8ff0a..000000000 --- a/lang/main-fr.json +++ /dev/null @@ -1,227 +0,0 @@ -{ - "contactlist": "Liste de contacts", - "connectionsettings": "Paramètres de connexion", - "poweredby": "propulsé par", - "downloadlogs": "Téléchargement des logs", - "roomUrlDefaultMsg": "Votre conférence est en cours de création...", - "participant": "Participant", - "me": "moi", - "speaker": "Haut-parleur", - "defaultNickname": "ex: __name__", - "defaultPreziLink": "e.g. __url__", - "welcomepage": { - "go": "Créer", - "roomname": "Saisissez un nom de salle", - "disable": "Ne pas afficher cette page lors de ma prochaine visite", - "feature1": { - "title": "Simple à utiliser", - "content": "Aucun téléchargement requis. __app__ s'utilise directement depuis votre navigateur. Partager simplement l'URL de votre conférence avec les autres pour commencer." - }, - "feature2": { - "title": "Faible bande passante", - "content": "Les vidéo conférences à plusieurs participants nécessitent moins de 128 kbps. Le partage d'écran et les conférences avec seulement de l'audio sont possibles avec beaucoup moins de débit." - }, - "feature3": { - "title": "Open source", - "content": "__app__ est sous licence MIT. Vous êtes libre de le télécharger, l'utiliser, le modifier et le partager sous cette licence." - }, - "feature4": { - "title": "Nombre d'utilisateurs illimité", - "content": "Il n'y a pas de restrictions artificielles concernant le nombre d'utilisateurs ou de participants à une conférence. La puissance du serveur et la bande passante sont les seuls facteurs limitants." - }, - "feature5": { - "title": "Partage d'écan", - "content": "C'est facile de partager votre écran avec d'autres personnes. __app__ est idéal pour les présentations en ligne, les cours, et les sessions de support technique." - }, - "feature6": { - "title": "Salles sécurisées", - "content": "Besoin de confidentialité? Les salles de conférence __app__ peuvent être sécurisées par un mot de passe pour exclure des invités non désirées, et prévenir des interruptions. " - }, - "feature7": { - "title": "Notes partagées", - "content": "__app__ propose Etherpad, un éditeur de texte collaboratif en temps réel qui est parfait pour les procès-verbaux, l'édition d'articles et plus encore." - }, - "feature8": { - "title": "Statistiques d'utilisation", - "content": "Connaissez mieux vos utilisateurs avec une intégration facile de Piwik, Google Analytics et d'autres systèmes de statistiques et supervision d'utilisation." - } - }, - "toolbar": { - "mute": "Muet / Actif", - "videomute": "Démarrer / Arrêter la caméra", - "authenticate": "", - "record": "Enregistrer", - "lock": "Verrouiller / déverrouiller la salle", - "invite": "Inviter des participants", - "chat": "", - "prezi": "Partager une présentation Prezi", - "etherpad": "Partager un document", - "sharescreen": "Partager mon écran", - "fullscreen": "Activer / Désactiver le plein écran", - "sip": "Appeler un numéro SIP", - "Settings": "Paramètres", - "hangup": "Raccrocher", - "login": "Connexion", - "logout": "" - }, - "bottomtoolbar": { - "chat": "Ouvrir / fermer le chat", - "filmstrip": "Montrer / cacher ma vidéo miniature", - "contactlist": "Ouvrir / fermer ma liste de contacts" - }, - "chat": { - "nickname": { - "title": "Saisissez un pseudonyme dans le champ ci-dessous", - "popover": "Choisissez un pseudonyme" - }, - "messagebox": "Saisissez votre texte..." - }, - "settings": { - "title": "PARAMÈTRES", - "update": "Mise à jour", - "name": "Nom" - }, - "videothumbnail": { - "editnickname": "Cliquez pour modifier
    votre nom", - "moderator": "Le propriétaire de
    cette conférence", - "videomute": "Un participant a
    arrêté sa caméra.", - "mute": "Un participant a coupé son micro", - "kick": "Exclure", - "muted": "Coupé", - "domute": "Couper le son" - }, - "connectionindicator": { - "bitrate": "Débit", - "packetloss": "Perte de paquets:", - "resolution": "Résolution:", - "less": "Cacher le détail", - "more": "Montrer le détail", - "address": "Adresse:", - "remoteport": "Port distant:", - "remoteport_plural": "Ports distants:", - "localport": "Port local:", - "localport_plural": "Ports locaux:", - "localaddress": "Adresse locale:", - "localaddress_plural": "Adresses locales:", - "remoteaddress": "Adresse distante:", - "remoteaddress_plural": "Adresses distantes:", - "transport": "Transport:", - "bandwidth": "Bande passante estimée:", - "na": "Revenez ici pour afficher les informations de connexion une fois la conférence démarrée" - }, - "notify": { - "disconnected": "Déconnecté", - "moderator": "Droits modérateur accordés!", - "connected": "Connecté", - "somebody": "Quelqu'un", - "me": "Moi", - "focus": "", - "focusFail": "__component__ n'est pas disponible - réessayez dans __ms__ sec", - "grantedTo": "Droits modérateur accordés à __to__!", - "grantedToUnknown": "Droits modérateur accordés à $t(somebody)!" - }, - "dialog": { - "kickMessage": "Oups! Vous avez été renvoyé de la réunion!", - "popupError": "Votre navigateur bloque les popups pour ce site. Activez les popups pour ce site dans vos paramètres de sécurité et réessayez.", - "passwordError": "Cette conversation est protégée par un mot de passe. Seul le propriétaire de cette conférence peut paramétrer un mot de passe.", - "passwordError2": "Cette conversation n'est pas protégée par un mot de passe. Seul le propriétaire de cette conférence peut paramétrer un mot de passe.", - "joinError": "Oups! La conférence ne peut être rejointe. Il y a peut-être un souci avec les paramètres de sécurité. Contactez l'administrateur.", - "connectError": "Oups! Un problème est survenu et la connexion à la conférence est impossible.", - "connecting": "", - "error": "", - "detectext": "Une erreur est survenue pendant la détection de l'extension de partage d'écran.", - "failtoinstall": "Échec de l'installation de l'extension de partage d'écran", - "failedpermissions": "Échec d'obtention des permissions pour utiliser le micro et/ou la caméra local(e)", - "bridgeUnavailable": "Le pont de visioconférence Jitsi est indisponible pour le moment. Réessayez plus tard!", - "lockTitle": "Échec du verrouillage", - "lockMessage": "Impossible de verrouiller la conférence.", - "warning": "Avertissement", - "passwordNotSupported": "Les mots de passe de conférence ne sont pas supportés.", - "sorry": "Désolé", - "internalError": "Une erreur interne de l'application est survenue [setRemoteDescription]", - "unableToSwitch": "Impossible de passer le flux vidéo.", - "SLDFailure": "Oups! Un problème est survenu et le micro n'a pas été coupé! (Échec SLD)", - "SRDFailure": "Oups! Un problème est survenu et la caméra n'a pas été coupée! (Échec SRD)", - "oops": "Oups!", - "defaultError": "Une erreur est survenue", - "passwordRequired": "Mot de passe requis", - "Ok": "Ok", - "removePreziTitle": "Supprimer la présentation Prezi", - "removePreziMsg": "Voulez-vous vraiment supprimer votre présentation Prezi?", - "sharePreziTitle": "Partager une présentation Prezi", - "sharePreziMsg": "Un autre participant partage déjà une présentation Prezi. Cette conférence autorise une seule présentation Prezi à la fois.", - "Remove": "Supprimer", - "Stop": "Arrêter", - "AuthMsg": "L'authentification est requise pour créer la conférence:
    __room__
    Vous pouvez vous authentifier pour créer la conférence ou attendre que quelqu'un le fasse pour vous.", - "Authenticate": "Authentifiez-vous", - "Cancel": "Annuler", - "retry": "Réessayer", - "logoutTitle": "Déconnexion", - "logoutQuestion": "Voulez-vous vraiment vous déconnecter et arrêter la conférence?", - "sessTerminated": "Session terminée", - "hungUp": "Vous avez raccroché et quitté la conférence", - "joinAgain": "Rejoignez à nouveau la conférence", - "Share": "Partager", - "preziLinkError": "Fournissez s'il vous plaît un lien prezi fonctionnel.", - "Save": "Sauvegarder", - "recordingToken": "Saisissez un jeton d'enregistrement", - "Dial": "Composer", - "sipMsg": "Saisissez un numéro SIP", - "passwordCheck": "Voulez-vous vraiment supprimer votre mot de passe?", - "passwordMsg": "Saisissez un mot de passe pour verrouiller la conférence", - "Invite": "Inviter", - "shareLink": "Partagez ce lien avec toutes les personnes que vous voulez inviter", - "settings1": "Configurez votre conférence", - "settings2": "Les participants rejoignent la conférence en étant muets.", - "settings3": "Pseudonymes requis

    Saisissez un mot de passe pour verrouiller la conférence:", - "yourPassword": "Votre mot de passe", - "Back": "Retour", - "serviceUnavailable": "Service indisponible", - "gracefulShutdown": "Le service est actuellement en maintenance. Réessayez plus tard.", - "Yes": "Oui", - "reservationError": "Erreur du système de réservation", - "reservationErrorMsg": "Code d'erreur: __code__, message: __msg__", - "password": "mot de passe", - "userPassword": "mot de passe utilisateur", - "token": "jeton" - }, - "email": { - "sharedKey": [ - "Cette conférence est protégée par un mot de passe. Utilisez le code suivant pour la rejoindre:", - "", - "", - "__sharedKey__", - "", - "" - ], - "subject": "Invitation à la conférence __appName__ : __conferenceName__", - "body": [ - "Bonjour, je vous invite à la conférence __appName__ que je viens de créer.", - "", - "", - "Cliquez sur le lien suivant pour rejoindre la conférence.", - "", - "", - "__roomUrl__", - "", - "", - "__sharedKeyText__", - " Notez que __appName__ est actuellement seulement supporté par __supportedBrowsers__, vous devez donc utiliser un de ces navigateurs.", - "", - "", - "À tout de suite dans la conférence!" - ], - "and": "et" - }, - "connection": { - "ERROR": "Erreur", - "CONNECTING": "Connexion en cours...", - "CONNFAIL": "Échec de la Connexion", - "AUTHENTICATING": "Authentification en cours...", - "AUTHFAIL": "Échec de l'authentification", - "CONNECTED": "Connecté", - "DISCONNECTED": "Déconnecté", - "DISCONNECTING": "Déconnexion en cours...", - "ATTACHED": "Attachée" - } -} \ No newline at end of file diff --git a/lang/main-it.json b/lang/main-it.json deleted file mode 100644 index ff3b07404..000000000 --- a/lang/main-it.json +++ /dev/null @@ -1,227 +0,0 @@ -{ - "contactlist": "LISTA CONTATTI", - "connectionsettings": "Impostazioni Connessione", - "poweredby": "powered by", - "downloadlogs": "Scarica logs", - "roomUrlDefaultMsg": "La tua conferenza sta per essere creata...", - "participant": "Partecipante", - "me": "io", - "speaker": "Relatore", - "defaultNickname": "es. __nome__", - "defaultPreziLink": "es. __url__", - "welcomepage": { - "go": "VAI", - "roomname": "Inserisci Nome Stanza", - "disable": "Non visualizzare questa pagina la prossima volta", - "feature1": { - "title": "Semplice da usare", - "content": "Nessun download richiesto. __app__ funziona direttamente nel tuo browser. Condividi semplicemente l'URL della tua conferenza con altri per iniziare." - }, - "feature2": { - "title": "Poca banda", - "content": "Conferenze video multi utente funzionano con appena 128Kbps. La condivisione dello schermo ed conferenze solo audio sono possibili con molto meno." - }, - "feature3": { - "title": "Open source", - "content": "__app__ è sotto licenza MIT. Sei libero di scaricarla, usarla, modificarla e condividerla con la medesima licenza." - }, - "feature4": { - "title": "Utenti illimitati", - "content": "Non ci sono restrizioni sul numero di utenti per una conferenza. La potenza del server e la banda a disposizione sono gli unici fattori limitanti." - }, - "feature5": { - "title": "Condivisione Schermo", - "content": "é facile condividere il tuo schermo con altri. __app__ è l'ideale per presentazioni online, letture, e sessioni di supporto tecnico." - }, - "feature6": { - "title": "Stanze sicure", - "content": "Hai bisogno di più privacy? Le conferenze di __app__ possono essere rese sicure con una password per escludere ospiti non desiderati e prevenire interruzioni." - }, - "feature7": { - "title": "Note condivise", - "content": "__app__ utilizza Etherpad, un editor di testo real-time e collaborativo che è ottimo per meeting, scrivere articoli e tanto altro." - }, - "feature8": { - "title": "Statistiche di utilizzo", - "content": "Impara come i tuoi utenti lo utilizzano con la facile integrazione con PiWik, Google Analytics, e altri sistemi di statistica e monitor dell'utilizzo." - } - }, - "toolbar": { - "mute": "Microfono Attiva / Disattiva", - "videomute": "Abilita / Disabilita video", - "authenticate": "", - "record": "Registra", - "lock": "Blocca / Sblocca Stanza", - "invite": "Invita altri", - "chat": "", - "prezi": "Condividi con Prezi", - "etherpad": "Documento condiviso", - "sharescreen": "Condividi schermo", - "fullscreen": "Entra / Esci da schermo intero", - "sip": "Chiama numero SIP", - "Settings": "Impostazioni", - "hangup": "Termina", - "login": "Login", - "logout": "" - }, - "bottomtoolbar": { - "chat": "Apri / Chiudi chat", - "filmstrip": "Mostra / Nascondi miniature", - "contactlist": "Apri / Chiudi la lista contatti" - }, - "chat": { - "nickname": { - "title": "Scegli un nickname nel box qui sotto", - "popover": "Scegli un nickname" - }, - "messagebox": "Inserisci testo..." - }, - "settings": { - "title": "IMPOSTAZIONI", - "update": "Aggiorna", - "name": "Nome" - }, - "videothumbnail": { - "editnickname": "Clicca per modificare il tuo
    nome visualizzato", - "moderator": "Il proprietario
    della conferenza", - "videomute": "Il partecipante ha
    fermato il video.", - "mute": "Il partecipante è in muto", - "kick": "Espelli", - "muted": "Audio disattivato", - "domute": "Disattiva audio" - }, - "connectionindicator": { - "bitrate": "Bitrate:", - "packetloss": "Perdita pacchetti:", - "resolution": "Risoluzione:", - "less": "Mostra meno", - "more": "Mostra di più", - "address": "Indirizzo:", - "remoteport": "Porta remota:", - "remoteport_plural": "Porte remote:", - "localport": "Porta locale:", - "localport_plural": "Porte locali:", - "localaddress": "Indirizzo locale:", - "localaddress_plural": "Indirizzi locali:", - "remoteaddress": "Indirizzo remoto:", - "remoteaddress_plural": "Indirizzi remoti:", - "transport": "Trasporto:", - "bandwidth": "Banda stimata:", - "na": "Ritorna qui per informazioni sulla connessione una volta che la conferenza inizia" - }, - "notify": { - "disconnected": "disconnesso", - "moderator": "Impostati i permessi di moderatore!", - "connected": "connesso", - "somebody": "Qualcuno", - "me": "io", - "focus": "Focus su conferenza", - "focusFail": "__component__ non disponibile - riprova in __ms__ sec", - "grantedTo": "Permessi di moderatore garantiti a __to__!", - "grantedToUnknown": "Permessi di moderatore garantiti a $t(somebody)!" - }, - "dialog": { - "kickMessage": "Accidenti! Sei stato espulso dalla conferenza !", - "popupError": "Il tuo browser sta bloccando le finestre popup da questo sito. Abilita i popup tra le impostazioni di sicurezza del tuo browser e riprova.", - "passwordError": "Questa conversazione è protetta da una password. Solo il proprietario della conferenza può impostare una password.", - "passwordError2": "Questa conversazione non è al momento protetta da una password. Solo il proprietario può impostare la password.", - "joinError": "Oops! Non puoi entrare nella conferenza. Ci deve essere qualche problema con la configurazione di sicurezza. Contattare l'amministratore di sistema.", - "connectError": "Oops! Qualcosa è andato storto e non ti puoi collegare alla conferenza.", - "connecting": "", - "error": "", - "detectext": "Errore durante il rilevamento dell'estensione per il desktopsharing.", - "failtoinstall": "Impossibile installare l'estensione per il desktop sharing", - "failedpermissions": "Impossibile ottenere i permessi per usare il microfono e/o il video locale.", - "bridgeUnavailable": "Il Videobridge non è al momento disponibile. Si prega di riprovare più tardi!", - "lockTitle": "Blocco fallito", - "lockMessage": "Impossibile bloccare la conferenza.", - "warning": "Attenzione", - "passwordNotSupported": "Le password sulla stanza non sono al momento supportate.", - "sorry": "Spiacente", - "internalError": "Errore interno dell'applicazione [setRemoteDescription]", - "unableToSwitch": "Impossibile cambiare lo stream video.", - "SLDFailure": "Oops! Qualcosa è andato storto e non è possibile silenziare il microfono! (Errore SLD)", - "SRDFailure": "Oops! Qualcosa è andato storto e non è possibile fermare il video! (Errore SRD)", - "oops": "Oops!", - "defaultError": "C'è stato qualche tipo di errore", - "passwordRequired": "Richiesta password ", - "Ok": "Ok", - "removePreziTitle": "Rimuovi Prezi", - "removePreziMsg": "Sei sicuro di voler rimuovere il tuo Prezi?", - "sharePreziTitle": "Condividi un Prezi", - "sharePreziMsg": "Un altro partecipante sta già condividendo un Prezi. Questa conferenza permette un solo Prezi alla volta.", - "Remove": "Rimuovi", - "Stop": "Ferma", - "AuthMsg": "Autenticazione richiesta per creare la stanza:
    __room__
    Puoi autenticarti per creare la stanza o aspettare che qualcun altro lo faccia per te.", - "Authenticate": "Autenticazione", - "Cancel": "Annulla", - "retry": "Riprova", - "logoutTitle": "Logout", - "logoutQuestion": "Vuoi disconnetterti e interrompere la conferenza ?", - "sessTerminated": "Sessione Terminata", - "hungUp": "Hai terminato la conversazione", - "joinAgain": "Entra ancora", - "Share": "Condividi", - "preziLinkError": "Fornire un link Prezi esatto.", - "Save": "Salva", - "recordingToken": "Inserire token di registrazione", - "Dial": "Componi", - "sipMsg": "Inserire numero SIP", - "passwordCheck": "Confermi la rimozione della password?", - "passwordMsg": "Imposta una password per bloccare la stanza", - "Invite": "Invita", - "shareLink": "Condividi questo link con tutte le persone che vuoi invitare", - "settings1": "Configura la tua conferenza", - "settings2": "Partecipanti connessi in muto", - "settings3": "Richiedi nicknames

    Imposta una password per bloccare la tua stanza:", - "yourPassword": "la tua password", - "Back": "Indietro", - "serviceUnavailable": "Servizio non disponibile", - "gracefulShutdown": "Il nostro servizio è al momento spento per manutenzione. Si prega di riprovare più tardi.", - "Yes": "Sì", - "reservationError": "Errore di sistema in prenotazione", - "reservationErrorMsg": "Codice di errore: __code__, messaggio: __msg__", - "password": "password", - "userPassword": "password utente", - "token": "token" - }, - "email": { - "sharedKey": [ - "Questa conferenza è protetta da password. Utilizzare il seguente PIN alla connessione:", - "", - "", - "__sharedKey__", - "", - "" - ], - "subject": "Invito su __appName__ (__conferenceName__)", - "body": [ - "Ciao, Vorrei invitarti alla conferenza che ho appena creato su __appName__ .", - "", - "", - "Cliccare sul seguente link per entrare nella conferenza.", - "", - "", - "__roomUrl__", - "", - "", - "__sharedKeyText__", - "NOTA: __appName__ è al momento supportato da questi browsers: __supportedBrowsers__, è necessario utilizzare uno di questi programmi per poter entrare.", - "", - "", - "Ci sentiamo tra un secondo!" - ], - "and": "e" - }, - "connection": { - "ERROR": "Errore", - "CONNECTING": "Connessione", - "CONNFAIL": "Connessione non riuscita", - "AUTHENTICATING": "Autenticazione", - "AUTHFAIL": "Autenticazione fallita", - "CONNECTED": "Connesso", - "DISCONNECTED": "Disconnesso", - "DISCONNECTING": "Disconnessione in corso", - "ATTACHED": "Collegato" - } -} \ No newline at end of file diff --git a/lang/main-tr.json b/lang/main-tr.json deleted file mode 100644 index 89a4a7e3b..000000000 --- a/lang/main-tr.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "contactlist": "KİŞİ LİSTESİ", - "connectionsettings": "Bağlantı Ayarları", - "poweredby": "Gücünün kaynağı", - "downloadlogs": "Günlükleri indir", - "welcomepage": { - "go": "GİT", - "roomname": "Oda adı girin", - "disable": "Sonraki girişimde bu sayfayı gösterme", - "feature1": { - "title": "Kullanımı kolay", - "content": "İndirmeye gerek yok. __app__ tarayıcınızda doğrudan çalışır. Başlamak için görüşme bağlantısını URL diğerleri ile paylaşın." - }, - "feature2": { - "title": "Düşük bant genişliği ihtiyacı", - "content": "Ekran paylaşımı ve sadece ses ile çok katılımcılı video görüşmeleri, 128Kbps bağlantı ile mümkündür." - }, - "feature3": { - "title": "Açık kaynak kodlu", - "content": "__app__ MIT ile lisanslanmıştır. Bu lisansa uygun olarak indirmek, kullanmak, değiştirmek ve paylaşmakta özgürsün." - }, - "feature4": { - "title": "Sınırsız sayıda kullanıcı", - "content": "Kullanıcılar veya konferans katılımcılarının sayısında hiçbir yapay kısıtlama yoktur. Sadece sunucun güç ve bant genişliği, sınırlayıcı unsurdur." - }, - "feature5": { - "title": "Ekran paylaşımı", - "content": "Diğerlerinle ekranınızı kolayca paylaşın. __app__ çevrimiçi sunumlar, dersler ve teknik destek oturumları için idealdir." - }, - "feature6": { - "title": "Güvenli odalar", - "content": "Biraz gizliliğe ihtiyacınız var? __app__ görüşme odaları, istemeyen misafirleri uzak tutmak ve kesinleri önlemek için bir parola ile güvence altına alınabilir." - }, - "feature7": { - "title": "Paylaşımlı notlar", - "content": "__app__ Etherpad içerir, gerçek zamanlı bir ortak çalışma metin düzenleyicisidir. Görüşme tutanakları, makale yazımı ve daha fazlası için biçilmiş kaftandır." - }, - "feature8": { - "title": "Kullanım istatistikleri", - "content": "Piwik, Google Analytics ve diğer kullanım izleme ve istatistik sistemleri ile kolay tümleştirmeyle kullanıcılar hakkında bilgi edinin." - } - }, - "toolbar": { - "mute": "Sessiz / Sesli", - "videomute": "Kamera başlat / durdur", - "authenticate": "", - "record": "Kaydet", - "lock": "Odayı kilitle / kilit aç", - "invite": "Arkadaşlarını davet et", - "chat": "", - "prezi": "Prezi paylaş", - "etherpad": "Paylaşımlı belge", - "sharescreen": "Ekran paylaş", - "fullscreen": "Tam Ekrana Gir / Çık", - "sip": "SIP numara ara", - "Settings": "Ayarlar", - "hangup": "Kapat", - "login": "Oturum aç", - "logout": "" - }, - "bottomtoolbar": { - "chat": "Sohbeti aç / kapa", - "filmstrip": "Kişi listesi aç / kapa", - "contactlist": "Film şeridini göster / gizle" - }, - "chat": { - "nickname": { - "title": "Aşağıdaki kutuya bir takma ad girin", - "popover": "Bir takma ad seçin" - }, - "messagebox": "Metin girin..." - }, - "settings": { - "title": "AYARLAR", - "update": "Güncelle", - "name": "Ad" - }, - "videothumbnail": { - "editnickname": "Görünür adınızı değiştirmek
    için tıkla", - "moderator": "Bu görüşmenin
    sahibi", - "videomute": "Katılımcı
    kamera durdurdu.", - "mute": "Katılımcı sessiz", - "kick": "Kovuldu", - "muted": "Sessiz", - "domute": "Sustur" - }, - "connectionindicator": { - "bitrate": "Bit hızı:", - "packetloss": "Paket kaybı:", - "resolution": "Çözünürlük:", - "less": "Daha az göster", - "more": "Daha fazla göster", - "address": "Adres:", - "remoteport": "Uzak port:Uzak portlar:", - "localport": "Yerel port:Yerel portlar:", - "localaddress": "Yerel adres:Yerel adresler:", - "remoteaddress": "Uzak adres:Uzak adresler:", - "transport": "Transport:", - "bandwidth": "Tahmini bant genişliği:", - "na": "Görüşme başladıktan sonra bağlantı bilgileri için buraya gel" - }, - "notify": { - "disconnected": "bağlantı kesildi", - "moderator": "Görüşme yöneticisi hakları verildi!", - "connected": "bağlandı", - "somebody": "Birisi", - "me": "Bana", - "focus": "Görüşme odağı", - "focusFail": "__component__ uygun değil - __ms__ saniye içinde tekrar deneyin", - "grantedTo": "__to__, görüşme yöneticisi hakları verildi!", - "grantedToUnknown": "$t(somebody), görüşme yöneticisi hakları verildi!" - }, - "dialog": { - "kickMessage": "Ahhh! Görüşmeden, kavuldun!", - "popupError": "Tarayıcınız bu siteden açılır pencereleri engelliyor. Lütfen, tarayıcınızın güvenlik ayarlarında pop-up etkinleştirin ve tekrar deneyin.", - "passwordError": "Bu görüşme şu anda bir parola ile korunmaktadır. Sadece görüşmenin sahibi bir parola ayarlayabilir.", - "passwordError2": "Bu görüşme şu anda bir parola ile korunmamaktadır. Sadece görüşmenin sahibi bir parola ayarlayabilir.", - "joinError": "Amanin boo! Görüşmeye katılamadık. Güvenlik yapılandırması ile ilgili bir sorun olabilir. Hizmet yöneticisi ile bağlantı kurun.", - "connectError": "Amanin boo! Birşeyler ters gitti ve görüşmeye bağlanamadık.", - "error": "Hata", - "detectext": "Ekran paylaşımı eklentisi tespit edilirken hata.", - "failtoinstall": "Masaüstü paylaşım eklentisi yüklenemedi", - "failedpermissions": "Yerel mikrofon ve/veya kamerayı kullanmak için izinler alınamadı.", - "bridgeUnavailable": "Jitsi Videobridge şu anda kullanılamıyor. Daha sonra tekrar deneyiniz!", - "lockTitle": "Kilitlenemedi", - "lockMessage": "Görüşme kilitlenemedi.", - "warning": "Uyarı", - "passwordNotSupported": "Oda parolaları şu anda desteklenmemekte.", - "sorry": "Üzgünüz", - "internalError": "İç uygulama hatası [setRemoteDescription]", - "unableToSwitch": "Video akışı açılamıyor.", - "SLDFailure": "Amanin boo! Birşeyler ters gitti ve sessize alamadık! (SLD Başarısız)", - "SRDFailure": "Amanin boo! Birşeyler ters gitti ve videoyu durduramadık! (SRD Başarısız)", - "oops": "Amanin boo!", - "defaultError": "Bir tür hata var", - "passwordRequired": "Parola gerekli", - "Ok": "Tamam", - "removePreziTitle": "Prezi kaldır", - "removePreziMsg": "Prezi kaldırmak istediğinizden emin misiniz?", - "sharePreziTitle": "Bir Prezi paylaşın", - "sharePreziMsg": "Diğer katılımcı hala bir Prezi paylaşıyor.Bu görüşme aynı zamanda sadece bir Prezi izin verir.", - "Remove": "Kaldır", - "Stop": "Durdur", - "AuthMsg": "Oda oluşturmak için kimlik doğrulama gerekli:
    __room__
    Oda oluşturmak için ya kimlik doğrulamalı ya da bunu yapması için bir başkasını beklemelisiniz.", - "Authenticate": "Kimlik doğrula", - "Cancel": "İptal", - "logoutTitle": "Oturum kapat", - "logoutQuestion": "Oturumu ve görüşmeyi sonlandırmak istediğinizden emin misiniz?", - "sessTerminated": "Oturum sonlandırıldı", - "hungUp": "Görüşmeyi bitirdiniz", - "joinAgain": "Yeniden katıl", - "Share": "Paylaş", - "preziLinkError": "Lütfen doğru prezi bağlantısı verin.", - "Save": "Kaydet", - "recordingToken": "Kayıt jetonu girin", - "Dial": "Ara", - "sipMsg": "SIP numarası gir", - "passwordCheck": "Parolanızı kaldırmak istediğinizden emin misiniz?", - "passwordMsg": "Odanızı kilitlemek için bir parola koyun", - "Invite": "Davet et", - "shareLink": "Davet etmek istediğiniz herkesle bu bağlantıyı paylaşın", - "settings1": "Görüşmenizi yapılandır", - "settings2": "Katılımcılar sessiz katılsın", - "settings3": "Takma adlar gerekli

    Odanızı kitlemek için bir parola ayarlayın:", - "yourPassword": "parolanız", - "Back": "Geri", - "serviceUnavailable": "Hizmet kullanım dışı", - "gracefulShutdown": "Hizmetimiz bakıp için durduruldu. Daha sonra tekrar deneyiniz.", - "Yes": "Evet", - "reservationError": "Rezervasyon sistemi hatası", - "reservationErrorMsg": "Hata kodu: __code__, mesaj: __msg__" - } -} \ No newline at end of file diff --git a/lang/main.json b/lang/main.json deleted file mode 100644 index 29df8de17..000000000 --- a/lang/main.json +++ /dev/null @@ -1,250 +0,0 @@ -{ - "contactlist": "CONTACT LIST", - "connectionsettings": "Connection Settings", - "poweredby": "powered by", - "downloadlogs": "Download logs", - "roomUrlDefaultMsg": "Your conference is currently being created...", - "participant": "Participant", - "me": "me", - "speaker": "Speaker", - "defaultNickname": "ex. __name__", - "defaultPreziLink": "e.g. __url__", - "welcomepage":{ - "go": "GO", - "roomname": "Enter room name", - "disable": "Don't show this page next time I enter", - "feature1": { - "title": "Simple to use", - "content": "No downloads required. __app__ works directly within your browser. Simply share your conference URL with others to get started." - }, - "feature2": { - "title": "Low bandwidth", - "content": "Multi-party video conferences work with as little as 128Kbps. Screen-sharing and audio-only conferences are possible with far less." - }, - "feature3": { - "title": "Open source", - "content": "__app__ is licensed under MIT. You are free to download, use, modify, and share them as per these licenses." - }, - "feature4": { - "title": "Unlimited users", - "content": "There are no artificial restrictions on the number of users or conference participants. Server power and bandwidth are the only limiting factors." - }, - "feature5": { - "title": "Screen sharing", - "content": "It's easy to share your screen with others. __app__ is ideal for on-line presentations, lectures, and tech support sessions." - }, - "feature6": { - "title": "Secure rooms", - "content": "Need some privacy? __app__ conference rooms can be secured with a password in order to exclude unwanted guests and prevent interruptions." - }, - "feature7": { - "title": "Shared notes", - "content": "__app__ features Etherpad, a real-time collaborative text editor that's great for meeting minutes, writing articles, and more." - }, - "feature8": { - "title": "Usage statistics", - "content": "Learn about your users through easy integration with Piwik, Google Analytics, and other usage monitoring and statistics systems." - } - }, - "toolbar": { - "mute": "Mute / Unmute", - "videomute": "Start / stop camera", - "authenticate": "Authenticate", - "record": "Record", - "lock": "Lock / unlock room", - "invite": "Invite others", - "chat": "Open / close chat", - "prezi": "Share Prezi", - "etherpad": "Shared document", - "sharescreen": "Share screen", - "fullscreen": "Enter / Exit Full Screen", - "sip": "Call SIP number", - "Settings": "Settings", - "hangup": "Hang Up", - "login": "Login", - "logout": "Logout", - "dialpad": "Show dialpad" - }, - "bottomtoolbar": { - "chat": "Open / close chat", - "filmstrip": "Show / hide film strip", - "contactlist": "Open / close contact list" - }, - "chat":{ - "nickname": { - "title": "Enter a nickname in the box below", - "popover": "Choose a nickname" - }, - "messagebox": "Enter text..." - }, - "settings": - { - "title": "SETTINGS", - "update": "Update", - "name": "Name", - "startAudioMuted": "start without audio", - "startVideoMuted": "start without video" - }, - "videothumbnail": - { - "editnickname": "Click to edit your
    display name", - "moderator": "The owner of
    this conference", - "videomute": "Participant has
    stopped the camera.", - "mute": "Participant is muted", - "kick": "Kick out", - "muted": "Muted", - "domute": "Mute" - - }, - "connectionindicator": - { - "bitrate": "Bitrate:", - "packetloss": "Packet loss:", - "resolution": "Resolution:", - "less": "Show less", - "more": "Show more", - "address": "Address:", - "remoteport_plural": "Remote ports:", - "localport_plural": "Local ports:", - "remoteport": "Remote port:", - "localport": "Local port:", - "localaddress": "Local address:", - "localaddress_plural": "Local addresses:", - "remoteaddress": "Remote address:", - "remoteaddress_plural": "Remote addresses:", - "transport": "Transport:", - "bandwidth": "Estimated bandwidth:", - "na": "Come back here for connection information once the conference starts" - }, - "notify": { - "disconnected": "disconnected", - "moderator": "Moderator rights granted!", - "connected": "connected", - "somebody": "Somebody", - "me": "Me", - "focus": "Conference focus", - "focusFail": "__component__ not available - retry in __ms__ sec", - "grantedTo": "Moderator rights granted to __to__!", - "grantedToUnknown": "Moderator rights granted to $t(somebody)!", - "muted": "You have started the conversation muted.", - "mutedTitle": "You're muted!" - }, - "dialog": { - "kickMessage": "Ouch! You have been kicked out of the meet!", - "popupError": "Your browser is blocking popup windows from this site. Please enable popups in your browser security settings and try again.", - "passwordError": "This conversation is currently protected by a password. Only the owner of the conference could set a password.", - "passwordError2": "This conversation isn't currently protected by a password. Only the owner of the conference could set a password.", - "joinError": "Oops! We couldn't join the conference. There might be some problem with security configuration. Please contact service administrator.", - "connectError": "Oops! Something went wrong and we couldn't connect to the conference.", - "connectErrorWithMsg": "Oops! Something went wrong and we couldn't connect to the conference: __msg__", - "connecting": "Connecting", - "error": "Error", - "detectext": "Error when trying to detect desktopsharing extension.", - "failtoinstall": "Failed to install desktop sharing extension", - "failedpermissions": "Failed to obtain permissions to use the local microphone and/or camera.", - "bridgeUnavailable": "Jitsi Videobridge is currently unavailable. Please try again later!", - "lockTitle": "Lock failed", - "lockMessage": "Failed to lock conference.", - "warning": "Warning", - "passwordNotSupported": "Room passwords are currently not supported.", - "sorry": "Sorry", - "internalError": "Internal application error [setRemoteDescription]", - "unableToSwitch": "Unable to switch video stream.", - "SLDFailure": "Oops! Something went wrong and we failed to mute! (SLD Failure)", - "SRDFailure": "Oops! Something went wrong and we failed to stop video! (SRD Failure)", - "oops": "Oops!", - "defaultError": "There was some kind of error", - "passwordRequired": "Password required", - "Ok": "Ok", - "removePreziTitle": "Remove Prezi", - "removePreziMsg": "Are you sure you would like to remove your Prezi?", - "sharePreziTitle": "Share a Prezi", - "sharePreziMsg": "Another participant is already sharing a Prezi.This conference allows only one Prezi at a time.", - "Remove": "Remove", - "WaitingForHost": "Waiting for the host ...", - "WaitForHostMsg": "The conference __room__ has not yet started. If you are the host then please authenticate. Otherwise, please wait for the host to arrive.", - "IamHost": "I am the host", - "Cancel": "Cancel", - "retry": "Retry", - "logoutTitle" : "Logout", - "logoutQuestion" : "Are you sure you want to logout and stop the conference?", - "sessTerminated": "Session Terminated", - "hungUp": "You hung up the call", - "joinAgain": "Join again", - "Share": "Share", - "preziLinkError": "Please provide a correct prezi link.", - "Save": "Save", - "recordingToken": "Enter recording token", - "Dial": "Dial", - "sipMsg": "Enter SIP number", - "passwordCheck": "Are you sure you would like to remove your password?", - "Remove": "Remove", - "passwordMsg": "Set a password to lock your room", - "Invite": "Invite", - "shareLink": "Share this link with everyone you want to invite", - "settings1": "Configure your conference", - "settings2": "Participants join muted", - "settings3": "Require nicknames

    Set a password to lock your room:", - "yourPassword": "your password", - "Back": "Back", - "serviceUnavailable": "Service unavailable", - "gracefulShutdown": "Our service is currently down for maintenance. Please try again later.", - "Yes": "Yes", - "reservationError": "Reservation system error", - "reservationErrorMsg": "Error code: __code__, message: __msg__", - "password": "password", - "userPassword": "user password", - "token": "token", - "displayNameRequired": "Please enter your display name:" - }, - "email": - { - "sharedKey": [ - "This conference is password protected. Please use the following pin when joining:", - "", - "", - "__sharedKey__", - "", - ""], - "subject": "Invitation to a __appName__ (__conferenceName__)", - "body": [ - "Hey there, I%27d like to invite you to a __appName__ conference I%27ve just set up.", - "", - "", - "Please click on the following link in order to join the conference.", - "", - "", - "__roomUrl__", - "", - "", - "__sharedKeyText__", - " Note that __appName__ is currently only supported by __supportedBrowsers__, so you need to be using one of these browsers.", - "", - "", - "Talk to you in a sec!" - ], - "and": "and" - }, - "connection": - { - "ERROR": "Error", - "CONNECTING": "Connecting", - "RECONNECTING": "A network problem occurred. Reconnecting...", - "CONNFAIL": "Connection failed", - "AUTHENTICATING": "Authenticating", - "AUTHFAIL": "Authentication failed", - "CONNECTED": "Connected", - "DISCONNECTED": "Disconnected", - "DISCONNECTING": "Disconnecting", - "ATTACHED": "Attached", - "FETCH_SESSION_ID": "Obtaining session-id...", - "GOT_SESSION_ID": "Obtaining session-id... Done", - "GET_SESSION_ID_ERROR": "Get session-id error: " - }, - "recording": - { - "toaster": "Currently recording!", - "pending": "Your recording will start as soon as another participant joins", - "on": "Recording has been started" - } -} diff --git a/libs/app.bundle.js b/libs/app.bundle.js deleted file mode 100644 index 7367b804e..000000000 --- a/libs/app.bundle.js +++ /dev/null @@ -1,38194 +0,0 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.APP = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} - -},{}],2:[function(require,module,exports){ -// shim for using process in browser - -var process = module.exports = {}; -var queue = []; -var draining = false; - -function drainQueue() { - if (draining) { - return; - } - draining = true; - var currentQueue; - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - var i = -1; - while (++i < len) { - currentQueue[i](); - } - len = queue.length; - } - draining = false; -} -process.nextTick = function (fun) { - queue.push(fun); - if (!draining) { - setTimeout(drainQueue, 0); - } -}; - -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -// TODO(shtylman) -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],3:[function(require,module,exports){ -/* jshint -W117 */ -/* application specific logic */ - -var APP = -{ - init: function () { - this.UI = require("./modules/UI/UI"); - this.API = require("./modules/API/API"); - this.connectionquality = require("./modules/connectionquality/connectionquality"); - this.statistics = require("./modules/statistics/statistics"); - this.RTC = require("./modules/RTC/RTC"); - this.desktopsharing = require("./modules/desktopsharing/desktopsharing"); - this.xmpp = require("./modules/xmpp/xmpp"); - this.keyboardshortcut = require("./modules/keyboardshortcut/keyboardshortcut"); - this.translation = require("./modules/translation/translation"); - this.settings = require("./modules/settings/Settings"); - this.DTMF = require("./modules/DTMF/DTMF"); - this.members = require("./modules/members/MemberList"); - } -}; - -function init() { - - APP.desktopsharing.init(); - APP.RTC.start(); - APP.xmpp.start(); - APP.statistics.start(); - APP.connectionquality.init(); - APP.keyboardshortcut.init(); - APP.members.start(); -} - - -$(document).ready(function () { - - var URLProcessor = require("./modules/URLProcessor/URLProcessor"); - URLProcessor.setConfigParametersFromUrl(); - APP.init(); - - APP.translation.init(); - - if(APP.API.isEnabled()) - APP.API.init(); - - APP.UI.start(init); - -}); - -$(window).bind('beforeunload', function () { - if(APP.API.isEnabled()) - APP.API.dispose(); -}); - -module.exports = APP; - - -},{"./modules/API/API":4,"./modules/DTMF/DTMF":5,"./modules/RTC/RTC":9,"./modules/UI/UI":13,"./modules/URLProcessor/URLProcessor":44,"./modules/connectionquality/connectionquality":45,"./modules/desktopsharing/desktopsharing":46,"./modules/keyboardshortcut/keyboardshortcut":47,"./modules/members/MemberList":48,"./modules/settings/Settings":49,"./modules/statistics/statistics":53,"./modules/translation/translation":54,"./modules/xmpp/xmpp":70}],4:[function(require,module,exports){ -/* global APP */ -/** - * Implements API class that communicates with external api class - * and provides interface to access Jitsi Meet features by external - * applications that embed Jitsi Meet - */ - -var XMPPEvents = require("../../service/xmpp/XMPPEvents"); - -/** - * List of the available commands. - * @type {{ - * displayName: inputDisplayNameHandler, - * toggleAudio: toggleAudio, - * toggleVideo: toggleVideo, - * toggleFilmStrip: toggleFilmStrip, - * toggleChat: toggleChat, - * toggleContactList: toggleContactList - * }} - */ -var commands = {}; - -function initCommands() { - commands = { - displayName: APP.UI.inputDisplayNameHandler, - toggleAudio: APP.UI.toggleAudio, - toggleVideo: APP.UI.toggleVideo, - toggleFilmStrip: APP.UI.toggleFilmStrip, - toggleChat: APP.UI.toggleChat, - toggleContactList: APP.UI.toggleContactList - }; -} - - -/** - * Maps the supported events and their status - * (true it the event is enabled and false if it is disabled) - * @type {{ - * incomingMessage: boolean, - * outgoingMessage: boolean, - * displayNameChange: boolean, - * participantJoined: boolean, - * participantLeft: boolean - * }} - */ -var events = { - incomingMessage: false, - outgoingMessage:false, - displayNameChange: false, - participantJoined: false, - participantLeft: false -}; - -var displayName = {}; - -/** - * Processes commands from external application. - * @param message the object with the command - */ -function processCommand(message) { - if (message.action != "execute") { - console.error("Unknown action of the message"); - return; - } - for (var key in message) { - if(commands[key]) - commands[key].apply(null, message[key]); - } -} - -/** - * Processes events objects from external applications - * @param event the event - */ -function processEvent(event) { - if (!event.action) { - console.error("Event with no action is received."); - return; - } - - var i = 0; - switch(event.action) { - case "add": - for (; i < event.events.length; i++) { - events[event.events[i]] = true; - } - break; - case "remove": - for (; i < event.events.length; i++) { - events[event.events[i]] = false; - } - break; - default: - console.error("Unknown action for event."); - } -} - -/** - * Sends message to the external application. - * @param object - */ -function sendMessage(object) { - window.parent.postMessage(JSON.stringify(object), "*"); -} - -/** - * Processes a message event from the external application - * @param event the message event - */ -function processMessage(event) { - var message; - try { - message = JSON.parse(event.data); - } catch (e) {} - - if(!message.type) - return; - switch (message.type) { - case "command": - processCommand(message); - break; - case "event": - processEvent(message); - break; - default: - console.error("Unknown type of the message"); - return; - } -} - -function setupListeners() { - APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_JOINED, function (from) { - API.triggerEvent("participantJoined", {jid: from}); - }); - APP.xmpp.addListener(XMPPEvents.MESSAGE_RECEIVED, function (from, nick, txt, myjid, stamp) { - if (from != myjid) - API.triggerEvent("incomingMessage", - {"from": from, "nick": nick, "message": txt, "stamp": stamp}); - }); - APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_LEFT, function (jid) { - API.triggerEvent("participantLeft", {jid: jid}); - }); - APP.xmpp.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, function (jid, newDisplayName) { - var name = displayName[jid]; - if(!name || name != newDisplayName) { - API.triggerEvent("displayNameChange", {jid: jid, displayname: newDisplayName}); - displayName[jid] = newDisplayName; - } - }); - APP.xmpp.addListener(XMPPEvents.SENDING_CHAT_MESSAGE, function (body) { - APP.API.triggerEvent("outgoingMessage", {"message": body}); - }); -} - -var API = { - /** - * Check whether the API should be enabled or not. - * @returns {boolean} - */ - isEnabled: function () { - var hash = location.hash; - if (hash && hash.indexOf("external") > -1 && window.postMessage) - return true; - return false; - }, - /** - * Initializes the APIConnector. Setups message event listeners that will - * receive information from external applications that embed Jitsi Meet. - * It also sends a message to the external application that APIConnector - * is initialized. - */ - init: function () { - initCommands(); - if (window.addEventListener) { - window.addEventListener('message', - processMessage, false); - } - else { - window.attachEvent('onmessage', processMessage); - } - sendMessage({type: "system", loaded: true}); - setupListeners(); - }, - /** - * Checks whether the event is enabled ot not. - * @param name the name of the event. - * @returns {*} - */ - isEventEnabled: function (name) { - return events[name]; - }, - - /** - * Sends event object to the external application that has been subscribed - * for that event. - * @param name the name event - * @param object data associated with the event - */ - triggerEvent: function (name, object) { - if(this.isEnabled() && this.isEventEnabled(name)) - sendMessage({ - type: "event", action: "result", event: name, result: object}); - }, - - /** - * Removes the listeners. - */ - dispose: function () { - if(window.removeEventListener) { - window.removeEventListener("message", - processMessage, false); - } - else { - window.detachEvent('onmessage', processMessage); - } - } -}; - -module.exports = API; -},{"../../service/xmpp/XMPPEvents":166}],5:[function(require,module,exports){ -/* global APP */ - -/** - * A module for sending DTMF tones. - */ -var DTMFSender; -var initDtmfSender = function() { - // TODO: This needs to reset this if the peerconnection changes - // (e.g. the call is re-made) - if (DTMFSender) - return; - - var localAudio = APP.RTC.localAudio; - if (localAudio && localAudio.getTracks().length > 0) - { - var peerconnection - = APP.xmpp.getConnection().jingle.activecall.peerconnection; - if (peerconnection) { - DTMFSender = - peerconnection.peerconnection - .createDTMFSender(localAudio.getTracks()[0]); - console.log("Initialized DTMFSender"); - } - else { - console.log("Failed to initialize DTMFSender: no PeerConnection."); - } - } - else { - console.log("Failed to initialize DTMFSender: no audio track."); - } -}; - -var DTMF = { - sendTones: function (tones, duration, pause) { - if (!DTMFSender) - initDtmfSender(); - - if (DTMFSender){ - DTMFSender.insertDTMF(tones, - (duration || 200), - (pause || 200)); - } - } -}; - -module.exports = DTMF; - - -},{}],6:[function(require,module,exports){ -/* global config, APP, Strophe */ - -// cache datachannels to avoid garbage collection -// https://code.google.com/p/chromium/issues/detail?id=405545 -var RTCEvents = require("../../service/RTC/RTCEvents"); - -var _dataChannels = []; -var eventEmitter = null; - - -var DataChannels = { - /** - * Callback triggered by PeerConnection when new data channel is opened - * on the bridge. - * @param event the event info object. - */ - onDataChannel: function (event) { - var dataChannel = event.channel; - - dataChannel.onopen = function () { - console.info("Data channel opened by the Videobridge!", dataChannel); - - // Code sample for sending string and/or binary data - // Sends String message to the bridge - //dataChannel.send("Hello bridge!"); - // Sends 12 bytes binary message to the bridge - //dataChannel.send(new ArrayBuffer(12)); - - eventEmitter.emit(RTCEvents.DATA_CHANNEL_OPEN); - }; - - dataChannel.onerror = function (error) { - console.error("Data Channel Error:", error, dataChannel); - }; - - dataChannel.onmessage = function (event) { - var data = event.data; - // JSON - var obj; - - try { - obj = JSON.parse(data); - } - catch (e) { - console.error( - "Failed to parse data channel message as JSON: ", - data, - dataChannel); - } - if (('undefined' !== typeof(obj)) && (null !== obj)) { - var colibriClass = obj.colibriClass; - - if ("DominantSpeakerEndpointChangeEvent" === colibriClass) { - // Endpoint ID from the Videobridge. - var dominantSpeakerEndpoint = obj.dominantSpeakerEndpoint; - - console.info( - "Data channel new dominant speaker event: ", - dominantSpeakerEndpoint); - eventEmitter.emit(RTCEvents.DOMINANTSPEAKER_CHANGED, dominantSpeakerEndpoint); - } - else if ("InLastNChangeEvent" === colibriClass) { - var oldValue = obj.oldValue; - var newValue = obj.newValue; - // Make sure that oldValue and newValue are of type boolean. - var type; - - if ((type = typeof oldValue) !== 'boolean') { - if (type === 'string') { - oldValue = (oldValue == "true"); - } else { - oldValue = new Boolean(oldValue).valueOf(); - } - } - if ((type = typeof newValue) !== 'boolean') { - if (type === 'string') { - newValue = (newValue == "true"); - } else { - newValue = new Boolean(newValue).valueOf(); - } - } - - eventEmitter.emit(RTCEvents.LASTN_CHANGED, oldValue, newValue); - } - else if ("LastNEndpointsChangeEvent" === colibriClass) { - // The new/latest list of last-n endpoint IDs. - var lastNEndpoints = obj.lastNEndpoints; - // The list of endpoint IDs which are entering the list of - // last-n at this time i.e. were not in the old list of last-n - // endpoint IDs. - var endpointsEnteringLastN = obj.endpointsEnteringLastN; - - console.log( - "Data channel new last-n event: ", - lastNEndpoints, endpointsEnteringLastN, obj); - eventEmitter.emit(RTCEvents.LASTN_ENDPOINT_CHANGED, - lastNEndpoints, endpointsEnteringLastN, obj); - } - else { - console.debug("Data channel JSON-formatted message: ", obj); - } - } - }; - - dataChannel.onclose = function () { - console.info("The Data Channel closed", dataChannel); - var idx = _dataChannels.indexOf(dataChannel); - if (idx > -1) - _dataChannels = _dataChannels.splice(idx, 1); - }; - _dataChannels.push(dataChannel); - }, - - /** - * Binds "ondatachannel" event listener to given PeerConnection instance. - * @param peerConnection WebRTC peer connection instance. - */ - init: function (peerConnection, emitter) { - if(!config.openSctp) - return; - - peerConnection.ondatachannel = this.onDataChannel; - eventEmitter = emitter; - - // Sample code for opening new data channel from Jitsi Meet to the bridge. - // Although it's not a requirement to open separate channels from both bridge - // and peer as single channel can be used for sending and receiving data. - // So either channel opened by the bridge or the one opened here is enough - // for communication with the bridge. - /*var dataChannelOptions = - { - reliable: true - }; - var dataChannel - = peerConnection.createDataChannel("myChannel", dataChannelOptions); - - // Can be used only when is in open state - dataChannel.onopen = function () - { - dataChannel.send("My channel !!!"); - }; - dataChannel.onmessage = function (event) - { - var msgData = event.data; - console.info("Got My Data Channel Message:", msgData, dataChannel); - };*/ - }, - handleSelectedEndpointEvent: onSelectedEndpointChanged, - handlePinnedEndpointEvent: onPinnedEndpointChanged -}; - -function onSelectedEndpointChanged(userResource) { - console.log('selected endpoint changed: ', userResource); - if (_dataChannels && _dataChannels.length != 0) { - _dataChannels.some(function (dataChannel) { - if (dataChannel.readyState == 'open') { - console.log('sending selected endpoint changed ' + - 'notification to the bridge: ', userResource); - dataChannel.send(JSON.stringify({ - 'colibriClass': 'SelectedEndpointChangedEvent', - 'selectedEndpoint': - (!userResource || userResource === null)? - null : userResource - })); - - return true; - } - }); - } -} - -function onPinnedEndpointChanged(userResource) { - console.log('pinned endpoint changed: ', userResource); - if (_dataChannels && _dataChannels.length != 0) { - _dataChannels.some(function (dataChannel) { - if (dataChannel.readyState == 'open') { - dataChannel.send(JSON.stringify({ - 'colibriClass': 'PinnedEndpointChangedEvent', - 'pinnedEndpoint': - (!userResource || userResource == null)? - null : userResource - })); - - return true; - } - }); - } -} - -module.exports = DataChannels; - - -},{"../../service/RTC/RTCEvents":157}],7:[function(require,module,exports){ -/* global APP */ -var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js"); -var RTCEvents = require("../../service/RTC/RTCEvents"); -var RTCBrowserType = require("./RTCBrowserType"); - -/** - * This implements 'onended' callback normally fired by WebRTC after the stream - * is stopped. There is no such behaviour yet in FF, so we have to add it. - * @param stream original WebRTC stream object to which 'onended' handling - * will be added. - */ -function implementOnEndedHandling(stream) { - var originalStop = stream.stop; - stream.stop = function () { - originalStop.apply(stream); - if (!stream.ended) { - stream.ended = true; - stream.onended(); - } - }; -} - -function LocalStream(stream, type, eventEmitter, videoType, isGUMStream) { - this.stream = stream; - this.eventEmitter = eventEmitter; - this.type = type; - this.videoType = videoType; - this.isGUMStream = true; - if(isGUMStream === false) - this.isGUMStream = isGUMStream; - var self = this; - if(type == "audio") { - this.getTracks = function () { - return self.stream.getAudioTracks(); - }; - } else { - this.getTracks = function () { - return self.stream.getVideoTracks(); - }; - } - - this.stream.onended = function () { - self.streamEnded(); - }; - if (RTCBrowserType.isFirefox()) { - implementOnEndedHandling(this.stream); - } -} - -LocalStream.prototype.streamEnded = function () { - this.eventEmitter.emit(StreamEventTypes.EVENT_TYPE_LOCAL_ENDED, this); -}; - -LocalStream.prototype.getOriginalStream = function() -{ - return this.stream; -}; - -LocalStream.prototype.isAudioStream = function () { - return this.type === "audio"; -}; - -LocalStream.prototype.setMute = function (mute) -{ - var isAudio = this.isAudioStream(); - var eventType = isAudio ? RTCEvents.AUDIO_MUTE : RTCEvents.VIDEO_MUTE; - - if ((window.location.protocol != "https:" && this.isGUMStream) || - (isAudio && this.isGUMStream) || this.videoType === "screen" || - // FIXME FF does not support 'removeStream' method used to mute - RTCBrowserType.isFirefox()) { - - var tracks = this.getTracks(); - for (var idx = 0; idx < tracks.length; idx++) { - tracks[idx].enabled = !mute; - } - this.eventEmitter.emit(eventType, mute); - } else { - if (mute) { - APP.xmpp.removeStream(this.stream); - this.stream.stop(); - this.eventEmitter.emit(eventType, true); - } else { - var self = this; - APP.RTC.rtcUtils.obtainAudioAndVideoPermissions( - (this.isAudioStream() ? ["audio"] : ["video"]), - function (stream) { - if (isAudio) { - APP.RTC.changeLocalAudio(stream, - function () { - self.eventEmitter.emit(eventType, false); - }); - } else { - APP.RTC.changeLocalVideo(stream, false, - function () { - self.eventEmitter.emit(eventType, false); - }); - } - }); - } - } -}; - -LocalStream.prototype.isMuted = function () { - var tracks = []; - if (this.isAudioStream()) { - tracks = this.stream.getAudioTracks(); - } else { - if (this.stream.ended) - return true; - tracks = this.stream.getVideoTracks(); - } - for (var idx = 0; idx < tracks.length; idx++) { - if(tracks[idx].enabled) - return false; - } - return true; -}; - -LocalStream.prototype.getId = function () { - return this.stream.getTracks()[0].id; -}; - -module.exports = LocalStream; - -},{"../../service/RTC/RTCEvents":157,"../../service/RTC/StreamEventTypes.js":159,"./RTCBrowserType":10}],8:[function(require,module,exports){ -var MediaStreamType = require("../../service/RTC/MediaStreamTypes"); - -/** - * Creates a MediaStream object for the given data, session id and ssrc. - * It is a wrapper class for the MediaStream. - * - * @param data the data object from which we obtain the stream, - * the peerjid, etc. - * @param sid the session id - * @param ssrc the ssrc corresponding to this MediaStream - * - * @constructor - */ -function MediaStream(data, sid, ssrc, browser, eventEmitter) { - - // XXX(gp) to minimize headaches in the future, we should build our - // abstractions around tracks and not streams. ORTC is track based API. - // Mozilla expects m-lines to represent media tracks. - // - // Practically, what I'm saying is that we should have a MediaTrack class - // and not a MediaStream class. - // - // Also, we should be able to associate multiple SSRCs with a MediaTrack as - // a track might have an associated RTX and FEC sources. - - this.sid = sid; - this.stream = data.stream; - this.peerjid = data.peerjid; - this.videoType = data.videoType; - this.ssrc = ssrc; - this.type = (this.stream.getVideoTracks().length > 0)? - MediaStreamType.VIDEO_TYPE : MediaStreamType.AUDIO_TYPE; - this.muted = false; - this.eventEmitter = eventEmitter; -} - - -MediaStream.prototype.getOriginalStream = function() { - return this.stream; -}; - -MediaStream.prototype.setMute = function (value) { - this.stream.muted = value; - this.muted = value; -}; - -module.exports = MediaStream; - -},{"../../service/RTC/MediaStreamTypes":156}],9:[function(require,module,exports){ -/* global APP */ -var EventEmitter = require("events"); -var RTCBrowserType = require("./RTCBrowserType"); -var RTCUtils = require("./RTCUtils.js"); -var LocalStream = require("./LocalStream.js"); -var DataChannels = require("./DataChannels"); -var MediaStream = require("./MediaStream.js"); -var DesktopSharingEventTypes - = require("../../service/desktopsharing/DesktopSharingEventTypes"); -var MediaStreamType = require("../../service/RTC/MediaStreamTypes"); -var StreamEventTypes = require("../../service/RTC/StreamEventTypes.js"); -var RTCEvents = require("../../service/RTC/RTCEvents.js"); -var XMPPEvents = require("../../service/xmpp/XMPPEvents"); -var UIEvents = require("../../service/UI/UIEvents"); - -var eventEmitter = new EventEmitter(); - - -function getMediaStreamUsage() -{ - var result = { - audio: true, - video: true - }; - - /** There are some issues with the desktop sharing - * when this property is enabled. - * WARNING: We must change the implementation to start video/audio if we - * receive from the focus that the peer is not muted. - - var isSecureConnection = window.location.protocol == "https:"; - - if(config.disableEarlyMediaPermissionRequests || !isSecureConnection) - { - result = { - audio: false, - video: false - }; - - } - **/ - - return result; -} - -var RTC = { - rtcUtils: null, - devices: { - audio: true, - video: true - }, - localStreams: [], - remoteStreams: {}, - localAudio: null, - localVideo: null, - addStreamListener: function (listener, eventType) { - eventEmitter.on(eventType, listener); - }, - addListener: function (type, listener) { - eventEmitter.on(type, listener); - }, - removeStreamListener: function (listener, eventType) { - if(!(eventType instanceof StreamEventTypes)) - throw "Illegal argument"; - - eventEmitter.removeListener(eventType, listener); - }, - createLocalStream: function (stream, type, change, videoType, isMuted, isGUMStream) { - - var localStream = new LocalStream(stream, type, eventEmitter, videoType, isGUMStream); - //in firefox we have only one stream object - if(this.localStreams.length == 0 || - this.localStreams[0].getOriginalStream() != stream) - this.localStreams.push(localStream); - if(isMuted === true) - localStream.setMute(true); - - if(type == "audio") { - this.localAudio = localStream; - } else { - this.localVideo = localStream; - } - var eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CREATED; - if(change) - eventType = StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED; - - eventEmitter.emit(eventType, localStream, isMuted); - return localStream; - }, - removeLocalStream: function (stream) { - for(var i = 0; i < this.localStreams.length; i++) { - if(this.localStreams[i].getOriginalStream() === stream) { - delete this.localStreams[i]; - return; - } - } - }, - createRemoteStream: function (data, sid, thessrc) { - var remoteStream = new MediaStream(data, sid, thessrc, - RTCBrowserType.getBrowserType(), eventEmitter); - var jid = data.peerjid || APP.xmpp.myJid(); - if(!this.remoteStreams[jid]) { - this.remoteStreams[jid] = {}; - } - this.remoteStreams[jid][remoteStream.type]= remoteStream; - eventEmitter.emit(StreamEventTypes.EVENT_TYPE_REMOTE_CREATED, remoteStream); - return remoteStream; - }, - getPCConstraints: function () { - return this.rtcUtils.pc_constraints; - }, - getUserMediaWithConstraints:function(um, success_callback, - failure_callback, resolution, - bandwidth, fps, desktopStream) - { - return this.rtcUtils.getUserMediaWithConstraints(um, success_callback, - failure_callback, resolution, bandwidth, fps, desktopStream); - }, - attachMediaStream: function (elSelector, stream) { - this.rtcUtils.attachMediaStream(elSelector, stream); - }, - getStreamID: function (stream) { - return this.rtcUtils.getStreamID(stream); - }, - getVideoSrc: function (element) { - return this.rtcUtils.getVideoSrc(element); - }, - setVideoSrc: function (element, src) { - this.rtcUtils.setVideoSrc(element, src); - }, - getVideoElementName: function () { - return RTCBrowserType.isTemasysPluginUsed() ? 'object' : 'video'; - }, - dispose: function() { - if (this.rtcUtils) { - this.rtcUtils = null; - } - }, - stop: function () { - this.dispose(); - }, - start: function () { - var self = this; - APP.desktopsharing.addListener( - function (stream, isUsingScreenStream, callback) { - self.changeLocalVideo(stream, isUsingScreenStream, callback); - }, DesktopSharingEventTypes.NEW_STREAM_CREATED); - APP.xmpp.addListener(XMPPEvents.CALL_INCOMING, function(event) { - DataChannels.init(event.peerconnection, eventEmitter); - }); - APP.UI.addListener(UIEvents.SELECTED_ENDPOINT, - DataChannels.handleSelectedEndpointEvent); - APP.UI.addListener(UIEvents.PINNED_ENDPOINT, - DataChannels.handlePinnedEndpointEvent); - - // In case of IE we continue from 'onReady' callback - // passed to RTCUtils constructor. It will be invoked by Temasys plugin - // once it is initialized. - var onReady = function () { - eventEmitter.emit(RTCEvents.RTC_READY, true); - self.rtcUtils.obtainAudioAndVideoPermissions( - null, null, getMediaStreamUsage()); - }; - - this.rtcUtils = new RTCUtils(this, onReady); - - // Call onReady() if Temasys plugin is not used - if (!RTCBrowserType.isTemasysPluginUsed()) { - onReady(); - } - }, - muteRemoteVideoStream: function (jid, value) { - var stream; - - if(this.remoteStreams[jid] && - this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) { - stream = this.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]; - } - - if(!stream) - return true; - - if (value != stream.muted) { - stream.setMute(value); - return true; - } - return false; - }, - switchVideoStreams: function (new_stream) { - this.localVideo.stream = new_stream; - - this.localStreams = []; - - //in firefox we have only one stream object - if (this.localAudio.getOriginalStream() != new_stream) - this.localStreams.push(this.localAudio); - this.localStreams.push(this.localVideo); - }, - changeLocalVideo: function (stream, isUsingScreenStream, callback) { - var oldStream = this.localVideo.getOriginalStream(); - var type = (isUsingScreenStream ? "screen" : "camera"); - var localCallback = callback; - if(this.localVideo.isMuted() && this.localVideo.videoType !== type) { - localCallback = function() { - APP.xmpp.setVideoMute(false, function(mute) { - eventEmitter.emit(RTCEvents.VIDEO_MUTE, mute); - }); - - callback(); - }; - } - // FIXME: Workaround for FF/IE/Safari - if (stream && stream.videoStream) { - stream = stream.videoStream; - } - var videoStream = this.rtcUtils.createStream(stream, true); - this.localVideo = this.createLocalStream(videoStream, "video", true, type); - // Stop the stream to trigger onended event for old stream - oldStream.stop(); - - this.switchVideoStreams(videoStream, oldStream); - - APP.xmpp.switchStreams(videoStream, oldStream,localCallback); - }, - changeLocalAudio: function (stream, callback) { - var oldStream = this.localAudio.getOriginalStream(); - var newStream = this.rtcUtils.createStream(stream); - this.localAudio = this.createLocalStream(newStream, "audio", true); - // Stop the stream to trigger onended event for old stream - oldStream.stop(); - APP.xmpp.switchStreams(newStream, oldStream, callback, true); - }, - isVideoMuted: function (jid) { - if (jid === APP.xmpp.myJid()) { - var localVideo = APP.RTC.localVideo; - return (!localVideo || localVideo.isMuted()); - } else { - if (!APP.RTC.remoteStreams[jid] || - !APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE]) { - return null; - } - return APP.RTC.remoteStreams[jid][MediaStreamType.VIDEO_TYPE].muted; - } - }, - setVideoMute: function (mute, callback, options) { - if (!this.localVideo) - return; - - if (mute == APP.RTC.localVideo.isMuted()) - { - APP.xmpp.sendVideoInfoPresence(mute); - if (callback) - callback(mute); - } - else - { - APP.RTC.localVideo.setMute(mute); - APP.xmpp.setVideoMute( - mute, - callback, - options); - } - }, - setDeviceAvailability: function (devices) { - if(!devices) - return; - if(devices.audio === true || devices.audio === false) - this.devices.audio = devices.audio; - if(devices.video === true || devices.video === false) - this.devices.video = devices.video; - eventEmitter.emit(RTCEvents.AVAILABLE_DEVICES_CHANGED, this.devices); - } -}; - -module.exports = RTC; - -},{"../../service/RTC/MediaStreamTypes":156,"../../service/RTC/RTCEvents.js":157,"../../service/RTC/StreamEventTypes.js":159,"../../service/UI/UIEvents":160,"../../service/desktopsharing/DesktopSharingEventTypes":163,"../../service/xmpp/XMPPEvents":166,"./DataChannels":6,"./LocalStream.js":7,"./MediaStream.js":8,"./RTCBrowserType":10,"./RTCUtils.js":11,"events":1}],10:[function(require,module,exports){ - -var currentBrowser; - -var browserVersion; - -var RTCBrowserType = { - - RTC_BROWSER_CHROME: "rtc_browser.chrome", - - RTC_BROWSER_OPERA: "rtc_browser.opera", - - RTC_BROWSER_FIREFOX: "rtc_browser.firefox", - - RTC_BROWSER_IEXPLORER: "rtc_browser.iexplorer", - - RTC_BROWSER_SAFARI: "rtc_browser.safari", - - getBrowserType: function () { - return currentBrowser; - }, - - isChrome: function () { - return currentBrowser === RTCBrowserType.RTC_BROWSER_CHROME; - }, - - isOpera: function () { - return currentBrowser === RTCBrowserType.RTC_BROWSER_OPERA; - }, - isFirefox: function () { - return currentBrowser === RTCBrowserType.RTC_BROWSER_FIREFOX; - }, - - isIExplorer: function () { - return currentBrowser === RTCBrowserType.RTC_BROWSER_IEXPLORER; - }, - - isSafari: function () { - return currentBrowser === RTCBrowserType.RTC_BROWSER_SAFARI; - }, - isTemasysPluginUsed: function () { - return RTCBrowserType.isIExplorer() || RTCBrowserType.isSafari(); - }, - getFirefoxVersion: function () { - return RTCBrowserType.isFirefox() ? browserVersion : null; - }, - - getChromeVersion: function () { - return RTCBrowserType.isChrome() ? browserVersion : null; - }, - - usesPlanB: function() { - return RTCBrowserType.isChrome() || RTCBrowserType.isOpera() || - RTCBrowserType.isTemasysPluginUsed(); - }, - - usesUnifiedPlan: function() { - return RTCBrowserType.isFirefox(); - } - - // Add version getters for other browsers when needed -}; - -// detectOpera() must be called before detectChrome() !!! -// otherwise Opera wil be detected as Chrome -function detectChrome() { - if (navigator.webkitGetUserMedia) { - currentBrowser = RTCBrowserType.RTC_BROWSER_CHROME; - var userAgent = navigator.userAgent.toLowerCase(); - // We can assume that user agent is chrome, because it's - // enforced when 'ext' streaming method is set - var ver = parseInt(userAgent.match(/chrome\/(\d+)\./)[1], 10); - console.log("This appears to be Chrome, ver: " + ver); - return ver; - } - return null; -} - -function detectOpera() { - var userAgent = navigator.userAgent; - if (userAgent.match(/Opera|OPR/)) { - currentBrowser = RTCBrowserType.RTC_BROWSER_OPERA; - var version = userAgent.match(/(Opera|OPR) ?\/?(\d+)\.?/)[2]; - console.info("This appears to be Opera, ver: " + version); - return version; - } - return null; -} - -function detectFirefox() { - if (navigator.mozGetUserMedia) { - currentBrowser = RTCBrowserType.RTC_BROWSER_FIREFOX; - var version = parseInt( - navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10); - console.log('This appears to be Firefox, ver: ' + version); - return version; - } - return null; -} - -function detectSafari() { - if ((/^((?!chrome).)*safari/i.test(navigator.userAgent))) { - currentBrowser = RTCBrowserType.RTC_BROWSER_SAFARI; - console.info("This appears to be Safari"); - // FIXME detect Safari version when needed - return 1; - } - return null; -} - -function detectIE() { - var version; - var ua = window.navigator.userAgent; - - var msie = ua.indexOf('MSIE '); - if (msie > 0) { - // IE 10 or older => return version number - version = parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10); - } - - var trident = ua.indexOf('Trident/'); - if (!version && trident > 0) { - // IE 11 => return version number - var rv = ua.indexOf('rv:'); - version = parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10); - } - - var edge = ua.indexOf('Edge/'); - if (!version && edge > 0) { - // IE 12 => return version number - version = parseInt(ua.substring(edge + 5, ua.indexOf('.', edge)), 10); - } - - if (version) { - currentBrowser = RTCBrowserType.RTC_BROWSER_IEXPLORER; - console.info("This appears to be IExplorer, ver: " + version); - } - return version; -} - -function detectBrowser() { - var version; - var detectors = [ - detectOpera, - detectChrome, - detectFirefox, - detectIE, - detectSafari - ]; - // Try all browser detectors - for (var i = 0; i < detectors.length; i++) { - version = detectors[i](); - if (version) - return version; - } - console.error("Failed to detect browser type"); - return undefined; -} - -browserVersion = detectBrowser(); - -module.exports = RTCBrowserType; -},{}],11:[function(require,module,exports){ -/* global config, require, attachMediaStream, getUserMedia */ -var RTCBrowserType = require("./RTCBrowserType"); -var Resolutions = require("../../service/RTC/Resolutions"); -var AdapterJS = require("./adapter.screenshare"); -var SDPUtil = require("../xmpp/SDPUtil"); - -var currentResolution = null; - -function getPreviousResolution(resolution) { - if(!Resolutions[resolution]) - return null; - var order = Resolutions[resolution].order; - var res = null; - var resName = null; - for(var i in Resolutions) { - var tmp = Resolutions[i]; - if(res == null || (res.order < tmp.order && tmp.order < order)) { - resName = i; - res = tmp; - } - } - return resName; -} - -function setResolutionConstraints(constraints, resolution, isAndroid) { - - if (Resolutions[resolution]) { - constraints.video.mandatory.minWidth = Resolutions[resolution].width; - constraints.video.mandatory.minHeight = Resolutions[resolution].height; - } - else if (isAndroid) { - // FIXME can't remember if the purpose of this was to always request - // low resolution on Android ? if yes it should be moved up front - constraints.video.mandatory.minWidth = 320; - constraints.video.mandatory.minHeight = 240; - constraints.video.mandatory.maxFrameRate = 15; - } - - if (constraints.video.mandatory.minWidth) - constraints.video.mandatory.maxWidth = - constraints.video.mandatory.minWidth; - if (constraints.video.mandatory.minHeight) - constraints.video.mandatory.maxHeight = - constraints.video.mandatory.minHeight; -} - -function getConstraints(um, resolution, bandwidth, fps, desktopStream, isAndroid) -{ - var constraints = {audio: false, video: false}; - - if (um.indexOf('video') >= 0) { - // same behaviour as true - constraints.video = { mandatory: {}, optional: [] }; - - constraints.video.optional.push({ googLeakyBucket: true }); - - setResolutionConstraints(constraints, resolution, isAndroid); - } - if (um.indexOf('audio') >= 0) { - if (!RTCBrowserType.isFirefox()) { - // same behaviour as true - constraints.audio = { mandatory: {}, optional: []}; - // if it is good enough for hangouts... - constraints.audio.optional.push( - {googEchoCancellation: true}, - {googAutoGainControl: true}, - {googNoiseSupression: true}, - {googHighpassFilter: true}, - {googNoisesuppression2: true}, - {googEchoCancellation2: true}, - {googAutoGainControl2: true} - ); - } else { - constraints.audio = true; - } - } - if (um.indexOf('screen') >= 0) { - if (RTCBrowserType.isChrome()) { - constraints.video = { - mandatory: { - chromeMediaSource: "screen", - googLeakyBucket: true, - maxWidth: window.screen.width, - maxHeight: window.screen.height, - maxFrameRate: 3 - }, - optional: [] - }; - } else if (RTCBrowserType.isTemasysPluginUsed()) { - constraints.video = { - optional: [ - { - sourceId: AdapterJS.WebRTCPlugin.plugin.screensharingKey - } - ] - }; - } else { - console.error( - "'screen' WebRTC media source is supported only in Chrome" + - " and with Temasys plugin"); - } - } - if (um.indexOf('desktop') >= 0) { - constraints.video = { - mandatory: { - chromeMediaSource: "desktop", - chromeMediaSourceId: desktopStream, - googLeakyBucket: true, - maxWidth: window.screen.width, - maxHeight: window.screen.height, - maxFrameRate: 3 - }, - optional: [] - }; - } - - if (bandwidth) { - if (!constraints.video) { - //same behaviour as true - constraints.video = {mandatory: {}, optional: []}; - } - constraints.video.optional.push({bandwidth: bandwidth}); - } - if (fps) { - // for some cameras it might be necessary to request 30fps - // so they choose 30fps mjpg over 10fps yuy2 - if (!constraints.video) { - // same behaviour as true; - constraints.video = {mandatory: {}, optional: []}; - } - constraints.video.mandatory.minFrameRate = fps; - } - - return constraints; -} - - -function RTCUtils(RTCService, onTemasysPluginReady) -{ - var self = this; - this.service = RTCService; - if (RTCBrowserType.isFirefox()) { - var FFversion = RTCBrowserType.getFirefoxVersion(); - if (FFversion >= 40) { - this.peerconnection = mozRTCPeerConnection; - this.getUserMedia = navigator.mozGetUserMedia.bind(navigator); - this.pc_constraints = {}; - this.attachMediaStream = function (element, stream) { - // srcObject is being standardized and FF will eventually - // support that unprefixed. FF also supports the - // "element.src = URL.createObjectURL(...)" combo, but that - // will be deprecated in favour of srcObject. - // - // https://groups.google.com/forum/#!topic/mozilla.dev.media/pKOiioXonJg - // https://github.com/webrtc/samples/issues/302 - if(!element[0]) - return; - element[0].mozSrcObject = stream; - element[0].play(); - }; - this.getStreamID = function (stream) { - var id = stream.id; - if (!id) { - var tracks = stream.getVideoTracks(); - if (!tracks || tracks.length === 0) { - tracks = stream.getAudioTracks(); - } - id = tracks[0].id; - } - return SDPUtil.filter_special_chars(id); - }; - this.getVideoSrc = function (element) { - if(!element) - return null; - return element.mozSrcObject; - }; - this.setVideoSrc = function (element, src) { - if(element) - element.mozSrcObject = src; - }; - RTCSessionDescription = mozRTCSessionDescription; - RTCIceCandidate = mozRTCIceCandidate; - } else { - console.error( - "Firefox version too old: " + FFversion + ". Required >= 40."); - window.location.href = 'unsupported_browser.html'; - return; - } - - } else if (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()) { - this.peerconnection = webkitRTCPeerConnection; - this.getUserMedia = navigator.webkitGetUserMedia.bind(navigator); - this.attachMediaStream = function (element, stream) { - element.attr('src', webkitURL.createObjectURL(stream)); - }; - this.getStreamID = function (stream) { - // streams from FF endpoints have the characters '{' and '}' - // that make jQuery choke. - return SDPUtil.filter_special_chars(stream.id); - }; - this.getVideoSrc = function (element) { - if(!element) - return null; - return element.getAttribute("src"); - }; - this.setVideoSrc = function (element, src) { - if(element) - element.setAttribute("src", src); - }; - // DTLS should now be enabled by default but.. - this.pc_constraints = {'optional': [{'DtlsSrtpKeyAgreement': 'true'}]}; - if (navigator.userAgent.indexOf('Android') != -1) { - this.pc_constraints = {}; // disable DTLS on Android - } - if (!webkitMediaStream.prototype.getVideoTracks) { - webkitMediaStream.prototype.getVideoTracks = function () { - return this.videoTracks; - }; - } - if (!webkitMediaStream.prototype.getAudioTracks) { - webkitMediaStream.prototype.getAudioTracks = function () { - return this.audioTracks; - }; - } - } - // Detect IE/Safari - else if (RTCBrowserType.isTemasysPluginUsed()) { - - //AdapterJS.WebRTCPlugin.setLogLevel( - // AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS.VERBOSE); - - AdapterJS.webRTCReady(function (isPlugin) { - - self.peerconnection = RTCPeerConnection; - self.getUserMedia = getUserMedia; - self.attachMediaStream = function (elSel, stream) { - - if (stream.id === "dummyAudio" || stream.id === "dummyVideo") { - return; - } - - attachMediaStream(elSel[0], stream); - }; - self.getStreamID = function (stream) { - var id = SDPUtil.filter_special_chars(stream.label); - return id; - }; - self.getVideoSrc = function (element) { - if (!element) { - console.warn("Attempt to get video SRC of null element"); - return null; - } - var children = element.children; - for (var i = 0; i !== children.length; ++i) { - if (children[i].name === 'streamId') { - return children[i].value; - } - } - //console.info(element.id + " SRC: " + src); - return null; - }; - self.setVideoSrc = function (element, src) { - //console.info("Set video src: ", element, src); - if (!src) { - console.warn("Not attaching video stream, 'src' is null"); - return; - } - AdapterJS.WebRTCPlugin.WaitForPluginReady(); - var stream = AdapterJS.WebRTCPlugin.plugin - .getStreamWithId(AdapterJS.WebRTCPlugin.pageId, src); - attachMediaStream(element, stream); - }; - - onTemasysPluginReady(isPlugin); - }); - } else { - try { - console.log('Browser does not appear to be WebRTC-capable'); - } catch (e) { } - window.location.href = 'unsupported_browser.html'; - } -} - - -RTCUtils.prototype.getUserMediaWithConstraints = function( - um, success_callback, failure_callback, resolution,bandwidth, fps, - desktopStream) { - currentResolution = resolution; - // Check if we are running on Android device - var isAndroid = navigator.userAgent.indexOf('Android') != -1; - - var constraints = getConstraints( - um, resolution, bandwidth, fps, desktopStream, isAndroid); - - console.info("Get media constraints", constraints); - - var self = this; - - try { - this.getUserMedia(constraints, - function (stream) { - console.log('onUserMediaSuccess'); - self.setAvailableDevices(um, true); - success_callback(stream); - }, - function (error) { - self.setAvailableDevices(um, false); - console.warn('Failed to get access to local media. Error ', - error, constraints); - if (failure_callback) { - failure_callback(error); - } - }); - } catch (e) { - console.error('GUM failed: ', e); - if(failure_callback) { - failure_callback(e); - } - } -}; - -RTCUtils.prototype.setAvailableDevices = function (um, available) { - var devices = {}; - if(um.indexOf("video") != -1) { - devices.video = available; - } - if(um.indexOf("audio") != -1) { - devices.audio = available; - } - this.service.setDeviceAvailability(devices); -}; - -/** - * We ask for audio and video combined stream in order to get permissions and - * not to ask twice. - */ -RTCUtils.prototype.obtainAudioAndVideoPermissions = - function(devices, callback, usageOptions) -{ - var self = this; - // Get AV - - var successCallback = function (stream) { - if(callback) - callback(stream, usageOptions); - else - self.successCallback(stream, usageOptions); - }; - - if(!devices) - devices = ['audio', 'video']; - - var newDevices = []; - - - if(usageOptions) - for(var i = 0; i < devices.length; i++) { - var device = devices[i]; - if(usageOptions[device] === true) - newDevices.push(device); - } - else - newDevices = devices; - - if(newDevices.length === 0) { - successCallback(); - return; - } - - if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed()) { - - // With FF/IE we can't split the stream into audio and video because FF - // doesn't support media stream constructors. So, we need to get the - // audio stream separately from the video stream using two distinct GUM - // calls. Not very user friendly :-( but we don't have many other - // options neither. - // - // Note that we pack those 2 streams in a single object and pass it to - // the successCallback method. - var obtainVideo = function (audioStream) { - self.getUserMediaWithConstraints( - ['video'], - function (videoStream) { - return successCallback({ - audioStream: audioStream, - videoStream: videoStream - }); - }, - function (error) { - console.error( - 'failed to obtain video stream - stop', error); - self.errorCallback(error); - }, - config.resolution || '360'); - }; - var obtainAudio = function () { - self.getUserMediaWithConstraints( - ['audio'], - function (audioStream) { - if (newDevices.indexOf('video') !== -1) - obtainVideo(audioStream); - }, - function (error) { - console.error( - 'failed to obtain audio stream - stop', error); - self.errorCallback(error); - } - ); - }; - if (newDevices.indexOf('audio') !== -1) { - obtainAudio(); - } else { - obtainVideo(null); - } - } else { - this.getUserMediaWithConstraints( - newDevices, - function (stream) { - successCallback(stream); - }, - function (error) { - self.errorCallback(error); - }, - config.resolution || '360'); - } -}; - -RTCUtils.prototype.successCallback = function (stream, usageOptions) { - // If this is FF or IE, the stream parameter is *not* a MediaStream object, - // it's an object with two properties: audioStream, videoStream. - if (stream && stream.getAudioTracks && stream.getVideoTracks) - console.log('got', stream, stream.getAudioTracks().length, - stream.getVideoTracks().length); - this.handleLocalStream(stream, usageOptions); -}; - -RTCUtils.prototype.errorCallback = function (error) { - var self = this; - console.error('failed to obtain audio/video stream - trying audio only', error); - var resolution = getPreviousResolution(currentResolution); - if(typeof error == "object" && error.constraintName && error.name - && (error.name == "ConstraintNotSatisfiedError" || - error.name == "OverconstrainedError") && - (error.constraintName == "minWidth" || error.constraintName == "maxWidth" || - error.constraintName == "minHeight" || error.constraintName == "maxHeight") - && resolution != null) - { - self.getUserMediaWithConstraints(['audio', 'video'], - function (stream) { - return self.successCallback(stream); - }, function (error) { - return self.errorCallback(error); - }, resolution); - } - else { - self.getUserMediaWithConstraints( - ['audio'], - function (stream) { - return self.successCallback(stream); - }, - function (error) { - console.error('failed to obtain audio/video stream - stop', - error); - return self.successCallback(null); - } - ); - } -}; - -RTCUtils.prototype.handleLocalStream = function(stream, usageOptions) { - // If this is FF, the stream parameter is *not* a MediaStream object, it's - // an object with two properties: audioStream, videoStream. - var audioStream, videoStream; - if(window.webkitMediaStream) - { - audioStream = new webkitMediaStream(); - videoStream = new webkitMediaStream(); - if(stream) { - var audioTracks = stream.getAudioTracks(); - - for (var i = 0; i < audioTracks.length; i++) { - audioStream.addTrack(audioTracks[i]); - } - - var videoTracks = stream.getVideoTracks(); - - for (i = 0; i < videoTracks.length; i++) { - videoStream.addTrack(videoTracks[i]); - } - } - } - else if (RTCBrowserType.isFirefox() || RTCBrowserType.isTemasysPluginUsed()) - { // Firefox and Temasys plugin - if (stream && stream.audioStream) - audioStream = stream.audioStream; - else - audioStream = new DummyMediaStream("dummyAudio"); - - if (stream && stream.videoStream) - videoStream = stream.videoStream; - else - videoStream = new DummyMediaStream("dummyVideo"); - } - - var audioMuted = (usageOptions && usageOptions.audio === false), - videoMuted = (usageOptions && usageOptions.video === false); - - var audioGUM = (!usageOptions || usageOptions.audio !== false), - videoGUM = (!usageOptions || usageOptions.video !== false); - - - this.service.createLocalStream(audioStream, "audio", null, null, - audioMuted, audioGUM); - - this.service.createLocalStream(videoStream, "video", null, 'camera', - videoMuted, videoGUM); -}; - -function DummyMediaStream(id) { - this.id = id; - this.label = id; - this.stop = function() { }; - this.getAudioTracks = function() { return []; }; - this.getVideoTracks = function() { return []; }; -} - -RTCUtils.prototype.createStream = function(stream, isVideo) { - var newStream = null; - if (window.webkitMediaStream) { - newStream = new webkitMediaStream(); - if (newStream) { - var tracks = (isVideo ? stream.getVideoTracks() : stream.getAudioTracks()); - - for (var i = 0; i < tracks.length; i++) { - newStream.addTrack(tracks[i]); - } - } - - } - else { - // FIXME: this is duplicated with 'handleLocalStream' !!! - if (stream) { - newStream = stream; - } else { - newStream = - new DummyMediaStream(isVideo ? "dummyVideo" : "dummyAudio"); - } - } - - return newStream; -}; - -module.exports = RTCUtils; - -},{"../../service/RTC/Resolutions":158,"../xmpp/SDPUtil":60,"./RTCBrowserType":10,"./adapter.screenshare":12}],12:[function(require,module,exports){ -/*! adapterjs - custom version from - 2015-08-12 */ - -// Adapter's interface. -var AdapterJS = AdapterJS || {}; - -// Browserify compatibility -if(typeof exports !== 'undefined') { - module.exports = AdapterJS; -} - -AdapterJS.options = AdapterJS.options || {}; - -// uncomment to get virtual webcams -// AdapterJS.options.getAllCams = true; - -// uncomment to prevent the install prompt when the plugin in not yet installed -// AdapterJS.options.hidePluginInstallPrompt = true; - -// AdapterJS version -AdapterJS.VERSION = '0.11.1'; - -// This function will be called when the WebRTC API is ready to be used -// Whether it is the native implementation (Chrome, Firefox, Opera) or -// the plugin -// You may Override this function to synchronise the start of your application -// with the WebRTC API being ready. -// If you decide not to override use this synchronisation, it may result in -// an extensive CPU usage on the plugin start (once per tab loaded) -// Params: -// - isUsingPlugin: true is the WebRTC plugin is being used, false otherwise -// -AdapterJS.onwebrtcready = AdapterJS.onwebrtcready || function(isUsingPlugin) { - // The WebRTC API is ready. - // Override me and do whatever you want here -}; - -// Sets a callback function to be called when the WebRTC interface is ready. -// The first argument is the function to callback.\ -// Throws an error if the first argument is not a function -AdapterJS.webRTCReady = function (callback) { - if (typeof callback !== 'function') { - throw new Error('Callback provided is not a function'); - } - - if (true === AdapterJS.onwebrtcreadyDone) { - // All WebRTC interfaces are ready, just call the callback - callback(null !== AdapterJS.WebRTCPlugin.plugin); - } else { - // will be triggered automatically when your browser/plugin is ready. - AdapterJS.onwebrtcready = callback; - } -}; - -// Plugin namespace -AdapterJS.WebRTCPlugin = AdapterJS.WebRTCPlugin || {}; - -// The object to store plugin information -AdapterJS.WebRTCPlugin.pluginInfo = { - prefix : 'Tem', - plugName : 'TemWebRTCPlugin', - pluginId : 'plugin0', - type : 'application/x-temwebrtcplugin', - onload : '__TemWebRTCReady0', - portalLink : 'http://skylink.io/plugin/', - downloadLink : null, //set below - companyName: 'Temasys' -}; -if(!!navigator.platform.match(/^Mac/i)) { - AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1n77hco'; -} -else if(!!navigator.platform.match(/^Win/i)) { - AdapterJS.WebRTCPlugin.pluginInfo.downloadLink = 'http://bit.ly/1kkS4FN'; -} - -// Unique identifier of each opened page -AdapterJS.WebRTCPlugin.pageId = Math.random().toString(36).slice(2); - -// Use this whenever you want to call the plugin. -AdapterJS.WebRTCPlugin.plugin = null; - -// Set log level for the plugin once it is ready. -// The different values are -// This is an asynchronous function that will run when the plugin is ready -AdapterJS.WebRTCPlugin.setLogLevel = null; - -// Defines webrtc's JS interface according to the plugin's implementation. -// Define plugin Browsers as WebRTC Interface. -AdapterJS.WebRTCPlugin.defineWebRTCInterface = null; - -// This function detects whether or not a plugin is installed. -// Checks if Not IE (firefox, for example), else if it's IE, -// we're running IE and do something. If not it is not supported. -AdapterJS.WebRTCPlugin.isPluginInstalled = null; - - // Lets adapter.js wait until the the document is ready before injecting the plugin -AdapterJS.WebRTCPlugin.pluginInjectionInterval = null; - -// Inject the HTML DOM object element into the page. -AdapterJS.WebRTCPlugin.injectPlugin = null; - -// States of readiness that the plugin goes through when -// being injected and stated -AdapterJS.WebRTCPlugin.PLUGIN_STATES = { - NONE : 0, // no plugin use - INITIALIZING : 1, // Detected need for plugin - INJECTING : 2, // Injecting plugin - INJECTED: 3, // Plugin element injected but not usable yet - READY: 4 // Plugin ready to be used -}; - -// Current state of the plugin. You cannot use the plugin before this is -// equal to AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY -AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.NONE; - -// True is AdapterJS.onwebrtcready was already called, false otherwise -// Used to make sure AdapterJS.onwebrtcready is only called once -AdapterJS.onwebrtcreadyDone = false; - -// Log levels for the plugin. -// To be set by calling AdapterJS.WebRTCPlugin.setLogLevel -/* -Log outputs are prefixed in some cases. - INFO: Information reported by the plugin. - ERROR: Errors originating from within the plugin. - WEBRTC: Error originating from within the libWebRTC library -*/ -// From the least verbose to the most verbose -AdapterJS.WebRTCPlugin.PLUGIN_LOG_LEVELS = { - NONE : 'NONE', - ERROR : 'ERROR', - WARNING : 'WARNING', - INFO: 'INFO', - VERBOSE: 'VERBOSE', - SENSITIVE: 'SENSITIVE' -}; - -// Does a waiting check before proceeding to load the plugin. -AdapterJS.WebRTCPlugin.WaitForPluginReady = null; - -// This methid will use an interval to wait for the plugin to be ready. -AdapterJS.WebRTCPlugin.callWhenPluginReady = null; - -// !!!! WARNING: DO NOT OVERRIDE THIS FUNCTION. !!! -// This function will be called when plugin is ready. It sends necessary -// details to the plugin. -// The function will wait for the document to be ready and the set the -// plugin state to AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY, -// indicating that it can start being requested. -// This function is not in the IE/Safari condition brackets so that -// TemPluginLoaded function might be called on Chrome/Firefox. -// This function is the only private function that is not encapsulated to -// allow the plugin method to be called. -__TemWebRTCReady0 = function () { - if (document.readyState === 'complete') { - AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY; - - AdapterJS.maybeThroughWebRTCReady(); - } else { - AdapterJS.WebRTCPlugin.documentReadyInterval = setInterval(function () { - if (document.readyState === 'complete') { - // TODO: update comments, we wait for the document to be ready - clearInterval(AdapterJS.WebRTCPlugin.documentReadyInterval); - AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY; - - AdapterJS.maybeThroughWebRTCReady(); - } - }, 100); - } -}; - -AdapterJS.maybeThroughWebRTCReady = function() { - if (!AdapterJS.onwebrtcreadyDone) { - AdapterJS.onwebrtcreadyDone = true; - - if (typeof(AdapterJS.onwebrtcready) === 'function') { - AdapterJS.onwebrtcready(AdapterJS.WebRTCPlugin.plugin !== null); - } - } -}; - -// Text namespace -AdapterJS.TEXT = { - PLUGIN: { - REQUIRE_INSTALLATION: 'This website requires you to install a WebRTC-enabling plugin ' + - 'to work on this browser.', - NOT_SUPPORTED: 'Your browser does not support WebRTC.', - BUTTON: 'Install Now' - }, - REFRESH: { - REQUIRE_REFRESH: 'Please refresh page', - BUTTON: 'Refresh Page' - } -}; - -// The result of ice connection states. -// - starting: Ice connection is starting. -// - checking: Ice connection is checking. -// - connected Ice connection is connected. -// - completed Ice connection is connected. -// - done Ice connection has been completed. -// - disconnected Ice connection has been disconnected. -// - failed Ice connection has failed. -// - closed Ice connection is closed. -AdapterJS._iceConnectionStates = { - starting : 'starting', - checking : 'checking', - connected : 'connected', - completed : 'connected', - done : 'completed', - disconnected : 'disconnected', - failed : 'failed', - closed : 'closed' -}; - -//The IceConnection states that has been fired for each peer. -AdapterJS._iceConnectionFiredStates = []; - - -// Check if WebRTC Interface is defined. -AdapterJS.isDefined = null; - -// This function helps to retrieve the webrtc detected browser information. -// This sets: -// - webrtcDetectedBrowser: The browser agent name. -// - webrtcDetectedVersion: The browser version. -// - webrtcDetectedType: The types of webRTC support. -// - 'moz': Mozilla implementation of webRTC. -// - 'webkit': WebKit implementation of webRTC. -// - 'plugin': Using the plugin implementation. -AdapterJS.parseWebrtcDetectedBrowser = function () { - var hasMatch, checkMatch = navigator.userAgent.match( - /(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || []; - if (/trident/i.test(checkMatch[1])) { - hasMatch = /\brv[ :]+(\d+)/g.exec(navigator.userAgent) || []; - webrtcDetectedBrowser = 'IE'; - webrtcDetectedVersion = parseInt(hasMatch[1] || '0', 10); - } else if (checkMatch[1] === 'Chrome') { - hasMatch = navigator.userAgent.match(/\bOPR\/(\d+)/); - if (hasMatch !== null) { - webrtcDetectedBrowser = 'opera'; - webrtcDetectedVersion = parseInt(hasMatch[1], 10); - } - } - if (navigator.userAgent.indexOf('Safari')) { - if (typeof InstallTrigger !== 'undefined') { - webrtcDetectedBrowser = 'firefox'; - } else if (/*@cc_on!@*/ false || !!document.documentMode) { - webrtcDetectedBrowser = 'IE'; - } else if ( - Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) { - webrtcDetectedBrowser = 'safari'; - } else if (!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) { - webrtcDetectedBrowser = 'opera'; - } else if (!!window.chrome) { - webrtcDetectedBrowser = 'chrome'; - } - } - if (!webrtcDetectedBrowser) { - webrtcDetectedVersion = checkMatch[1]; - } - if (!webrtcDetectedVersion) { - try { - checkMatch = (checkMatch[2]) ? [checkMatch[1], checkMatch[2]] : - [navigator.appName, navigator.appVersion, '-?']; - if ((hasMatch = navigator.userAgent.match(/version\/(\d+)/i)) !== null) { - checkMatch.splice(1, 1, hasMatch[1]); - } - webrtcDetectedVersion = parseInt(checkMatch[1], 10); - } catch (error) { } - } -}; - -// To fix configuration as some browsers does not support -// the 'urls' attribute. -AdapterJS.maybeFixConfiguration = function (pcConfig) { - if (pcConfig === null) { - return; - } - for (var i = 0; i < pcConfig.iceServers.length; i++) { - if (pcConfig.iceServers[i].hasOwnProperty('urls')) { - pcConfig.iceServers[i].url = pcConfig.iceServers[i].urls; - delete pcConfig.iceServers[i].urls; - } - } -}; - -AdapterJS.addEvent = function(elem, evnt, func) { - if (elem.addEventListener) { // W3C DOM - elem.addEventListener(evnt, func, false); - } else if (elem.attachEvent) {// OLD IE DOM - elem.attachEvent('on'+evnt, func); - } else { // No much to do - elem[evnt] = func; - } -}; - -AdapterJS.renderNotificationBar = function (text, buttonText, buttonLink, openNewTab, displayRefreshBar) { - // only inject once the page is ready - if (document.readyState !== 'complete') { - return; - } - - var w = window; - var i = document.createElement('iframe'); - i.style.position = 'fixed'; - i.style.top = '-41px'; - i.style.left = 0; - i.style.right = 0; - i.style.width = '100%'; - i.style.height = '40px'; - i.style.backgroundColor = '#ffffe1'; - i.style.border = 'none'; - i.style.borderBottom = '1px solid #888888'; - i.style.zIndex = '9999999'; - if(typeof i.style.webkitTransition === 'string') { - i.style.webkitTransition = 'all .5s ease-out'; - } else if(typeof i.style.transition === 'string') { - i.style.transition = 'all .5s ease-out'; - } - document.body.appendChild(i); - c = (i.contentWindow) ? i.contentWindow : - (i.contentDocument.document) ? i.contentDocument.document : i.contentDocument; - c.document.open(); - c.document.write('' + text + ''); - if(buttonText && buttonLink) { - c.document.write(''); - c.document.close(); - - AdapterJS.addEvent(c.document.getElementById('okay'), 'click', function(e) { - if (!!displayRefreshBar) { - AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION ? - AdapterJS.TEXT.EXTENSION.REQUIRE_REFRESH : AdapterJS.TEXT.REFRESH.REQUIRE_REFRESH, - AdapterJS.TEXT.REFRESH.BUTTON, 'javascript:location.reload()'); - } - window.open(buttonLink, !!openNewTab ? '_blank' : '_top'); - - e.preventDefault(); - try { - event.cancelBubble = true; - } catch(error) { } - - var pluginInstallInterval = setInterval(function(){ - if(! isIE) { - navigator.plugins.refresh(false); - } - AdapterJS.WebRTCPlugin.isPluginInstalled( - AdapterJS.WebRTCPlugin.pluginInfo.prefix, - AdapterJS.WebRTCPlugin.pluginInfo.plugName, - function() { - clearInterval(pluginInstallInterval); - AdapterJS.WebRTCPlugin.defineWebRTCInterface(); - }, - function() { //Does nothing because not used here - }); - } , 500); - }); - - }else { - c.document.close(); - } - AdapterJS.addEvent(c.document, 'click', function() { - w.document.body.removeChild(i); - }); - setTimeout(function() { - if(typeof i.style.webkitTransform === 'string') { - i.style.webkitTransform = 'translateY(40px)'; - } else if(typeof i.style.transform === 'string') { - i.style.transform = 'translateY(40px)'; - } else { - i.style.top = '0px'; - } - }, 300); -}; - -// ----------------------------------------------------------- -// Detected webrtc implementation. Types are: -// - 'moz': Mozilla implementation of webRTC. -// - 'webkit': WebKit implementation of webRTC. -// - 'plugin': Using the plugin implementation. -webrtcDetectedType = null; - -// Detected webrtc datachannel support. Types are: -// - 'SCTP': SCTP datachannel support. -// - 'RTP': RTP datachannel support. -webrtcDetectedDCSupport = null; - -// Set the settings for creating DataChannels, MediaStream for -// Cross-browser compability. -// - This is only for SCTP based support browsers. -// the 'urls' attribute. -checkMediaDataChannelSettings = - function (peerBrowserAgent, peerBrowserVersion, callback, constraints) { - if (typeof callback !== 'function') { - return; - } - var beOfferer = true; - var isLocalFirefox = webrtcDetectedBrowser === 'firefox'; - // Nightly version does not require MozDontOfferDataChannel for interop - var isLocalFirefoxInterop = webrtcDetectedType === 'moz' && webrtcDetectedVersion > 30; - var isPeerFirefox = peerBrowserAgent === 'firefox'; - var isPeerFirefoxInterop = peerBrowserAgent === 'firefox' && - ((peerBrowserVersion) ? (peerBrowserVersion > 30) : false); - - // Resends an updated version of constraints for MozDataChannel to work - // If other userAgent is firefox and user is firefox, remove MozDataChannel - if ((isLocalFirefox && isPeerFirefox) || (isLocalFirefoxInterop)) { - try { - delete constraints.mandatory.MozDontOfferDataChannel; - } catch (error) { - console.error('Failed deleting MozDontOfferDataChannel'); - console.error(error); - } - } else if ((isLocalFirefox && !isPeerFirefox)) { - constraints.mandatory.MozDontOfferDataChannel = true; - } - if (!isLocalFirefox) { - // temporary measure to remove Moz* constraints in non Firefox browsers - for (var prop in constraints.mandatory) { - if (constraints.mandatory.hasOwnProperty(prop)) { - if (prop.indexOf('Moz') !== -1) { - delete constraints.mandatory[prop]; - } - } - } - } - // Firefox (not interopable) cannot offer DataChannel as it will cause problems to the - // interopability of the media stream - if (isLocalFirefox && !isPeerFirefox && !isLocalFirefoxInterop) { - beOfferer = false; - } - callback(beOfferer, constraints); -}; - -// Handles the differences for all browsers ice connection state output. -// - Tested outcomes are: -// - Chrome (offerer) : 'checking' > 'completed' > 'completed' -// - Chrome (answerer) : 'checking' > 'connected' -// - Firefox (offerer) : 'checking' > 'connected' -// - Firefox (answerer): 'checking' > 'connected' -checkIceConnectionState = function (peerId, iceConnectionState, callback) { - if (typeof callback !== 'function') { - console.warn('No callback specified in checkIceConnectionState. Aborted.'); - return; - } - peerId = (peerId) ? peerId : 'peer'; - - if (!AdapterJS._iceConnectionFiredStates[peerId] || - iceConnectionState === AdapterJS._iceConnectionStates.disconnected || - iceConnectionState === AdapterJS._iceConnectionStates.failed || - iceConnectionState === AdapterJS._iceConnectionStates.closed) { - AdapterJS._iceConnectionFiredStates[peerId] = []; - } - iceConnectionState = AdapterJS._iceConnectionStates[iceConnectionState]; - if (AdapterJS._iceConnectionFiredStates[peerId].indexOf(iceConnectionState) < 0) { - AdapterJS._iceConnectionFiredStates[peerId].push(iceConnectionState); - if (iceConnectionState === AdapterJS._iceConnectionStates.connected) { - setTimeout(function () { - AdapterJS._iceConnectionFiredStates[peerId] - .push(AdapterJS._iceConnectionStates.done); - callback(AdapterJS._iceConnectionStates.done); - }, 1000); - } - callback(iceConnectionState); - } - return; -}; - -// Firefox: -// - Creates iceServer from the url for Firefox. -// - Create iceServer with stun url. -// - Create iceServer with turn url. -// - Ignore the transport parameter from TURN url for FF version <=27. -// - Return null for createIceServer if transport=tcp. -// - FF 27 and above supports transport parameters in TURN url, -// - So passing in the full url to create iceServer. -// Chrome: -// - Creates iceServer from the url for Chrome M33 and earlier. -// - Create iceServer with stun url. -// - Chrome M28 & above uses below TURN format. -// Plugin: -// - Creates Ice Server for Plugin Browsers -// - If Stun - Create iceServer with stun url. -// - Else - Create iceServer with turn url -// - This is a WebRTC Function -createIceServer = null; - -// Firefox: -// - Creates IceServers for Firefox -// - Use .url for FireFox. -// - Multiple Urls support -// Chrome: -// - Creates iceServers from the urls for Chrome M34 and above. -// - .urls is supported since Chrome M34. -// - Multiple Urls support -// Plugin: -// - Creates Ice Servers for Plugin Browsers -// - Multiple Urls support -// - This is a WebRTC Function -createIceServers = null; -//------------------------------------------------------------ - -//The RTCPeerConnection object. -RTCPeerConnection = null; - -// Creates RTCSessionDescription object for Plugin Browsers -RTCSessionDescription = (typeof RTCSessionDescription === 'function') ? - RTCSessionDescription : null; - -// Creates RTCIceCandidate object for Plugin Browsers -RTCIceCandidate = (typeof RTCIceCandidate === 'function') ? - RTCIceCandidate : null; - -// Get UserMedia (only difference is the prefix). -// Code from Adam Barth. -getUserMedia = null; - -// Attach a media stream to an element. -attachMediaStream = null; - -// Re-attach a media stream to an element. -reattachMediaStream = null; - - -// Detected browser agent name. Types are: -// - 'firefox': Firefox browser. -// - 'chrome': Chrome browser. -// - 'opera': Opera browser. -// - 'safari': Safari browser. -// - 'IE' - Internet Explorer browser. -webrtcDetectedBrowser = null; - -// Detected browser version. -webrtcDetectedVersion = null; - -// Check for browser types and react accordingly -if (navigator.mozGetUserMedia) { - webrtcDetectedBrowser = 'firefox'; - webrtcDetectedVersion = parseInt(navigator - .userAgent.match(/Firefox\/([0-9]+)\./)[1], 10); - webrtcDetectedType = 'moz'; - webrtcDetectedDCSupport = 'SCTP'; - - RTCPeerConnection = function (pcConfig, pcConstraints) { - AdapterJS.maybeFixConfiguration(pcConfig); - return new mozRTCPeerConnection(pcConfig, pcConstraints); - }; - - // The RTCSessionDescription object. - RTCSessionDescription = mozRTCSessionDescription; - window.RTCSessionDescription = RTCSessionDescription; - - // The RTCIceCandidate object. - RTCIceCandidate = mozRTCIceCandidate; - window.RTCIceCandidate = RTCIceCandidate; - - window.getUserMedia = navigator.mozGetUserMedia.bind(navigator); - navigator.getUserMedia = window.getUserMedia; - - // Shim for MediaStreamTrack.getSources. - MediaStreamTrack.getSources = function(successCb) { - setTimeout(function() { - var infos = [ - { kind: 'audio', id: 'default', label:'', facing:'' }, - { kind: 'video', id: 'default', label:'', facing:'' } - ]; - successCb(infos); - }, 0); - }; - - createIceServer = function (url, username, password) { - var iceServer = null; - var url_parts = url.split(':'); - if (url_parts[0].indexOf('stun') === 0) { - iceServer = { url : url }; - } else if (url_parts[0].indexOf('turn') === 0) { - if (webrtcDetectedVersion < 27) { - var turn_url_parts = url.split('?'); - if (turn_url_parts.length === 1 || - turn_url_parts[1].indexOf('transport=udp') === 0) { - iceServer = { - url : turn_url_parts[0], - credential : password, - username : username - }; - } - } else { - iceServer = { - url : url, - credential : password, - username : username - }; - } - } - return iceServer; - }; - - createIceServers = function (urls, username, password) { - var iceServers = []; - for (i = 0; i < urls.length; i++) { - var iceServer = createIceServer(urls[i], username, password); - if (iceServer !== null) { - iceServers.push(iceServer); - } - } - return iceServers; - }; - - attachMediaStream = function (element, stream) { - element.mozSrcObject = stream; - if (stream !== null) - element.play(); - - return element; - }; - - reattachMediaStream = function (to, from) { - to.mozSrcObject = from.mozSrcObject; - to.play(); - return to; - }; - - MediaStreamTrack.getSources = MediaStreamTrack.getSources || function (callback) { - if (!callback) { - throw new TypeError('Failed to execute \'getSources\' on \'MediaStreamTrack\'' + - ': 1 argument required, but only 0 present.'); - } - return callback([]); - }; - - // Fake get{Video,Audio}Tracks - if (!MediaStream.prototype.getVideoTracks) { - MediaStream.prototype.getVideoTracks = function () { - return []; - }; - } - if (!MediaStream.prototype.getAudioTracks) { - MediaStream.prototype.getAudioTracks = function () { - return []; - }; - } - - AdapterJS.maybeThroughWebRTCReady(); -} else if (navigator.webkitGetUserMedia) { - webrtcDetectedBrowser = 'chrome'; - webrtcDetectedType = 'webkit'; - webrtcDetectedVersion = parseInt(navigator - .userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10); - // check if browser is opera 20+ - var checkIfOpera = navigator.userAgent.match(/\bOPR\/(\d+)/); - if (checkIfOpera !== null) { - webrtcDetectedBrowser = 'opera'; - webrtcDetectedVersion = parseInt(checkIfOpera[1], 10); - } - // check browser datachannel support - if ((webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion >= 31) || - (webrtcDetectedBrowser === 'opera' && webrtcDetectedVersion >= 20)) { - webrtcDetectedDCSupport = 'SCTP'; - } else if (webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion < 30 && - webrtcDetectedVersion > 24) { - webrtcDetectedDCSupport = 'RTP'; - } else { - webrtcDetectedDCSupport = ''; - } - - createIceServer = function (url, username, password) { - var iceServer = null; - var url_parts = url.split(':'); - if (url_parts[0].indexOf('stun') === 0) { - iceServer = { 'url' : url }; - } else if (url_parts[0].indexOf('turn') === 0) { - iceServer = { - 'url' : url, - 'credential' : password, - 'username' : username - }; - } - return iceServer; - }; - - createIceServers = function (urls, username, password) { - var iceServers = []; - if (webrtcDetectedVersion >= 34) { - iceServers = { - 'urls' : urls, - 'credential' : password, - 'username' : username - }; - } else { - for (i = 0; i < urls.length; i++) { - var iceServer = createIceServer(urls[i], username, password); - if (iceServer !== null) { - iceServers.push(iceServer); - } - } - } - return iceServers; - }; - - RTCPeerConnection = function (pcConfig, pcConstraints) { - if (webrtcDetectedVersion < 34) { - AdapterJS.maybeFixConfiguration(pcConfig); - } - return new webkitRTCPeerConnection(pcConfig, pcConstraints); - }; - - window.getUserMedia = navigator.webkitGetUserMedia.bind(navigator); - navigator.getUserMedia = window.getUserMedia; - - attachMediaStream = function (element, stream) { - if (typeof element.srcObject !== 'undefined') { - element.srcObject = stream; - } else if (typeof element.mozSrcObject !== 'undefined') { - element.mozSrcObject = stream; - } else if (typeof element.src !== 'undefined') { - element.src = (stream === null ? '' : URL.createObjectURL(stream)); - } else { - console.log('Error attaching stream to element.'); - } - return element; - }; - - reattachMediaStream = function (to, from) { - to.src = from.src; - return to; - }; - - AdapterJS.maybeThroughWebRTCReady(); -} else { // TRY TO USE PLUGIN - // IE 9 is not offering an implementation of console.log until you open a console - if (typeof console !== 'object' || typeof console.log !== 'function') { - /* jshint -W020 */ - console = {} || console; - // Implemented based on console specs from MDN - // You may override these functions - console.log = function (arg) {}; - console.info = function (arg) {}; - console.error = function (arg) {}; - console.dir = function (arg) {}; - console.exception = function (arg) {}; - console.trace = function (arg) {}; - console.warn = function (arg) {}; - console.count = function (arg) {}; - console.debug = function (arg) {}; - console.count = function (arg) {}; - console.time = function (arg) {}; - console.timeEnd = function (arg) {}; - console.group = function (arg) {}; - console.groupCollapsed = function (arg) {}; - console.groupEnd = function (arg) {}; - /* jshint +W020 */ - } - webrtcDetectedType = 'plugin'; - webrtcDetectedDCSupport = 'plugin'; - AdapterJS.parseWebrtcDetectedBrowser(); - isIE = webrtcDetectedBrowser === 'IE'; - - /* jshint -W035 */ - AdapterJS.WebRTCPlugin.WaitForPluginReady = function() { - while (AdapterJS.WebRTCPlugin.pluginState !== AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) { - /* empty because it needs to prevent the function from running. */ - } - }; - /* jshint +W035 */ - - AdapterJS.WebRTCPlugin.callWhenPluginReady = function (callback) { - if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) { - // Call immediately if possible - // Once the plugin is set, the code will always take this path - callback(); - } else { - // otherwise start a 100ms interval - var checkPluginReadyState = setInterval(function () { - if (AdapterJS.WebRTCPlugin.pluginState === AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) { - clearInterval(checkPluginReadyState); - callback(); - } - }, 100); - } - }; - - AdapterJS.WebRTCPlugin.setLogLevel = function(logLevel) { - AdapterJS.WebRTCPlugin.callWhenPluginReady(function() { - AdapterJS.WebRTCPlugin.plugin.setLogLevel(logLevel); - }); - }; - - AdapterJS.WebRTCPlugin.injectPlugin = function () { - // only inject once the page is ready - if (document.readyState !== 'complete') { - return; - } - - // Prevent multiple injections - if (AdapterJS.WebRTCPlugin.pluginState !== AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING) { - return; - } - - AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTING; - - if (webrtcDetectedBrowser === 'IE' && webrtcDetectedVersion <= 10) { - var frag = document.createDocumentFragment(); - AdapterJS.WebRTCPlugin.plugin = document.createElement('div'); - AdapterJS.WebRTCPlugin.plugin.innerHTML = '' + - ' ' + - ' ' + - ' ' + - '' + - // uncomment to be able to use virtual cams - (AdapterJS.options.getAllCams ? '':'') + - - ''; - while (AdapterJS.WebRTCPlugin.plugin.firstChild) { - frag.appendChild(AdapterJS.WebRTCPlugin.plugin.firstChild); - } - document.body.appendChild(frag); - - // Need to re-fetch the plugin - AdapterJS.WebRTCPlugin.plugin = - document.getElementById(AdapterJS.WebRTCPlugin.pluginInfo.pluginId); - } else { - // Load Plugin - AdapterJS.WebRTCPlugin.plugin = document.createElement('object'); - AdapterJS.WebRTCPlugin.plugin.id = - AdapterJS.WebRTCPlugin.pluginInfo.pluginId; - // IE will only start the plugin if it's ACTUALLY visible - if (isIE) { - AdapterJS.WebRTCPlugin.plugin.width = '1px'; - AdapterJS.WebRTCPlugin.plugin.height = '1px'; - } else { // The size of the plugin on Safari should be 0x0px - // so that the autorisation prompt is at the top - AdapterJS.WebRTCPlugin.plugin.width = '0px'; - AdapterJS.WebRTCPlugin.plugin.height = '0px'; - } - AdapterJS.WebRTCPlugin.plugin.type = AdapterJS.WebRTCPlugin.pluginInfo.type; - AdapterJS.WebRTCPlugin.plugin.innerHTML = '' + - '' + - ' ' + - (AdapterJS.options.getAllCams ? '':'') + - ''; - document.body.appendChild(AdapterJS.WebRTCPlugin.plugin); - } - - - AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INJECTED; - }; - - AdapterJS.WebRTCPlugin.isPluginInstalled = - function (comName, plugName, installedCb, notInstalledCb) { - if (!isIE) { - var pluginArray = navigator.plugins; - for (var i = 0; i < pluginArray.length; i++) { - if (pluginArray[i].name.indexOf(plugName) >= 0) { - installedCb(); - return; - } - } - notInstalledCb(); - } else { - try { - var axo = new ActiveXObject(comName + '.' + plugName); - } catch (e) { - notInstalledCb(); - return; - } - installedCb(); - } - }; - - AdapterJS.WebRTCPlugin.defineWebRTCInterface = function () { - if (AdapterJS.WebRTCPlugin.pluginState === - AdapterJS.WebRTCPlugin.PLUGIN_STATES.READY) { - console.error("WebRTC interface has been defined already"); - return; - } - AdapterJS.WebRTCPlugin.pluginState = AdapterJS.WebRTCPlugin.PLUGIN_STATES.INITIALIZING; - - AdapterJS.isDefined = function (variable) { - return variable !== null && variable !== undefined; - }; - - createIceServer = function (url, username, password) { - var iceServer = null; - var url_parts = url.split(':'); - if (url_parts[0].indexOf('stun') === 0) { - iceServer = { - 'url' : url, - 'hasCredentials' : false - }; - } else if (url_parts[0].indexOf('turn') === 0) { - iceServer = { - 'url' : url, - 'hasCredentials' : true, - 'credential' : password, - 'username' : username - }; - } - return iceServer; - }; - - createIceServers = function (urls, username, password) { - var iceServers = []; - for (var i = 0; i < urls.length; ++i) { - iceServers.push(createIceServer(urls[i], username, password)); - } - return iceServers; - }; - - RTCSessionDescription = function (info) { - AdapterJS.WebRTCPlugin.WaitForPluginReady(); - return AdapterJS.WebRTCPlugin.plugin. - ConstructSessionDescription(info.type, info.sdp); - }; - - RTCPeerConnection = function (servers, constraints) { - var iceServers = null; - if (servers) { - iceServers = servers.iceServers; - for (var i = 0; i < iceServers.length; i++) { - if (iceServers[i].urls && !iceServers[i].url) { - iceServers[i].url = iceServers[i].urls; - } - iceServers[i].hasCredentials = AdapterJS. - isDefined(iceServers[i].username) && - AdapterJS.isDefined(iceServers[i].credential); - } - } - var mandatory = (constraints && constraints.mandatory) ? - constraints.mandatory : null; - var optional = (constraints && constraints.optional) ? - constraints.optional : null; - - AdapterJS.WebRTCPlugin.WaitForPluginReady(); - return AdapterJS.WebRTCPlugin.plugin. - PeerConnection(AdapterJS.WebRTCPlugin.pageId, - iceServers, mandatory, optional); - }; - - MediaStreamTrack = {}; - MediaStreamTrack.getSources = function (callback) { - AdapterJS.WebRTCPlugin.callWhenPluginReady(function() { - AdapterJS.WebRTCPlugin.plugin.GetSources(callback); - }); - }; - - window.getUserMedia = function (constraints, successCallback, failureCallback) { - constraints.audio = constraints.audio || false; - constraints.video = constraints.video || false; - - AdapterJS.WebRTCPlugin.callWhenPluginReady(function() { - AdapterJS.WebRTCPlugin.plugin. - getUserMedia(constraints, successCallback, failureCallback); - }); - }; - window.navigator.getUserMedia = window.getUserMedia; - - attachMediaStream = function (element, stream) { - if (!element || !element.parentNode) { - return; - } - - var streamId - if (stream === null) { - streamId = ''; - } - else { - stream.enableSoundTracks(true); - streamId = stream.id; - } - - if (element.nodeName.toLowerCase() !== 'audio') { - var elementId = element.id.length === 0 ? Math.random().toString(36).slice(2) : element.id; - if (!element.isWebRTCPlugin || !element.isWebRTCPlugin()) { - var frag = document.createDocumentFragment(); - var temp = document.createElement('div'); - var classHTML = ''; - if (element.className) { - classHTML = 'class="' + element.className + '" '; - } else if (element.attributes && element.attributes['class']) { - classHTML = 'class="' + element.attributes['class'].value + '" '; - } - - temp.innerHTML = '' + - ' ' + - ' ' + - ' ' + - ' ' + - ''; - while (temp.firstChild) { - frag.appendChild(temp.firstChild); - } - - var height = ''; - var width = ''; - if (element.getBoundingClientRect) { - var rectObject = element.getBoundingClientRect(); - width = rectObject.width + 'px'; - height = rectObject.height + 'px'; - } - else if (element.width) { - width = element.width; - height = element.height; - } else { - // TODO: What scenario could bring us here? - } - - element.parentNode.insertBefore(frag, element); - frag = document.getElementById(elementId); - frag.width = width; - frag.height = height; - element.parentNode.removeChild(element); - } else { - var children = element.children; - for (var i = 0; i !== children.length; ++i) { - if (children[i].name === 'streamId') { - children[i].value = streamId; - break; - } - } - element.setStreamId(streamId); - } - var newElement = document.getElementById(elementId); - newElement.onplaying = (element.onplaying) ? element.onplaying : function (arg) {}; - if (isIE) { // on IE the event needs to be plugged manually - newElement.attachEvent('onplaying', newElement.onplaying); - newElement.onclick = (element.onclick) ? element.onclick : function (arg) {}; - newElement._TemOnClick = function (id) { - var arg = { - srcElement : document.getElementById(id) - }; - newElement.onclick(arg); - }; - } - return newElement; - } else { - return element; - } - }; - - reattachMediaStream = function (to, from) { - var stream = null; - var children = from.children; - for (var i = 0; i !== children.length; ++i) { - if (children[i].name === 'streamId') { - AdapterJS.WebRTCPlugin.WaitForPluginReady(); - stream = AdapterJS.WebRTCPlugin.plugin - .getStreamWithId(AdapterJS.WebRTCPlugin.pageId, children[i].value); - break; - } - } - if (stream !== null) { - return attachMediaStream(to, stream); - } else { - console.log('Could not find the stream associated with this element'); - } - }; - - RTCIceCandidate = function (candidate) { - if (!candidate.sdpMid) { - candidate.sdpMid = ''; - } - - AdapterJS.WebRTCPlugin.WaitForPluginReady(); - return AdapterJS.WebRTCPlugin.plugin.ConstructIceCandidate( - candidate.sdpMid, candidate.sdpMLineIndex, candidate.candidate - ); - }; - - // inject plugin - AdapterJS.addEvent(document, 'readystatechange', AdapterJS.WebRTCPlugin.injectPlugin); - AdapterJS.WebRTCPlugin.injectPlugin(); - }; - - // This function will be called if the plugin is needed (browser different - // from Chrome or Firefox), but the plugin is not installed. - AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb = AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb || - function() { - AdapterJS.addEvent(document, - 'readystatechange', - AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv); - AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv(); - }; - - AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCbPriv = function () { - if (AdapterJS.options.hidePluginInstallPrompt) { - return; - } - - var downloadLink = AdapterJS.WebRTCPlugin.pluginInfo.downloadLink; - if(downloadLink) { // if download link - var popupString; - if (AdapterJS.WebRTCPlugin.pluginInfo.portalLink) { // is portal link - popupString = 'This website requires you to install the ' + - ' ' + AdapterJS.WebRTCPlugin.pluginInfo.companyName + - ' WebRTC Plugin' + - ' to work on this browser.'; - } else { // no portal link, just print a generic explanation - popupString = AdapterJS.TEXT.PLUGIN.REQUIRE_INSTALLATION; - } - - AdapterJS.renderNotificationBar(popupString, AdapterJS.TEXT.PLUGIN.BUTTON, downloadLink); - } else { // no download link, just print a generic explanation - AdapterJS.renderNotificationBar(AdapterJS.TEXT.PLUGIN.NOT_SUPPORTED); - } - }; - - // Try to detect the plugin and act accordingly - AdapterJS.WebRTCPlugin.isPluginInstalled( - AdapterJS.WebRTCPlugin.pluginInfo.prefix, - AdapterJS.WebRTCPlugin.pluginInfo.plugName, - AdapterJS.WebRTCPlugin.defineWebRTCInterface, - AdapterJS.WebRTCPlugin.pluginNeededButNotInstalledCb); -} - - - -(function () { - - 'use strict'; - - var baseGetUserMedia = null; - - AdapterJS.TEXT.EXTENSION = { - REQUIRE_INSTALLATION_FF: 'To enable screensharing you need to install the Skylink WebRTC tools Firefox Add-on.', - REQUIRE_INSTALLATION_CHROME: 'To enable screensharing you need to install the Skylink WebRTC tools Chrome Extension.', - REQUIRE_REFRESH: 'Please refresh this page after the Skylink WebRTC tools extension has been installed.', - BUTTON_FF: 'Install Now', - BUTTON_CHROME: 'Go to Chrome Web Store' - }; - - var clone = function(obj) { - if (null == obj || "object" != typeof obj) return obj; - var copy = obj.constructor(); - for (var attr in obj) { - if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr]; - } - return copy; - }; - - if (window.navigator.mozGetUserMedia) { - baseGetUserMedia = window.navigator.getUserMedia; - - navigator.getUserMedia = function (constraints, successCb, failureCb) { - - if (constraints && constraints.video && !!constraints.video.mediaSource) { - // intercepting screensharing requests - - if (constraints.video.mediaSource !== 'screen' && constraints.video.mediaSource !== 'window') { - throw new Error('Only "screen" and "window" option is available as mediaSource'); - } - - var updatedConstraints = clone(constraints); - - //constraints.video.mediaSource = constraints.video.mediaSource; - updatedConstraints.video.mozMediaSource = updatedConstraints.video.mediaSource; - - // so generally, it requires for document.readyState to be completed before the getUserMedia could be invoked. - // strange but this works anyway - var checkIfReady = setInterval(function () { - if (document.readyState === 'complete') { - clearInterval(checkIfReady); - - baseGetUserMedia(updatedConstraints, successCb, function (error) { - if (error.name === 'PermissionDeniedError' && window.parent.location.protocol === 'https:') { - AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION.REQUIRE_INSTALLATION_FF, - AdapterJS.TEXT.EXTENSION.BUTTON_FF, - 'http://skylink.io/screensharing/ff_addon.php?domain=' + window.location.hostname, false, true); - //window.location.href = 'http://skylink.io/screensharing/ff_addon.php?domain=' + window.location.hostname; - } else { - failureCb(error); - } - }); - } - }, 1); - - } else { // regular GetUserMediaRequest - baseGetUserMedia(constraints, successCb, failureCb); - } - }; - - getUserMedia = navigator.getUserMedia; - - } else if (window.navigator.webkitGetUserMedia) { - baseGetUserMedia = window.navigator.getUserMedia; - - navigator.getUserMedia = function (constraints, successCb, failureCb) { - - if (constraints && constraints.video && !!constraints.video.mediaSource) { - if (window.webrtcDetectedBrowser !== 'chrome') { - throw new Error('Current browser does not support screensharing'); - } - - // would be fine since no methods - var updatedConstraints = clone(constraints); - - var chromeCallback = function(error, sourceId) { - if(!error) { - updatedConstraints.video.mandatory = updatedConstraints.video.mandatory || {}; - updatedConstraints.video.mandatory.chromeMediaSource = 'desktop'; - updatedConstraints.video.mandatory.maxWidth = window.screen.width > 1920 ? window.screen.width : 1920; - updatedConstraints.video.mandatory.maxHeight = window.screen.height > 1080 ? window.screen.height : 1080; - - if (sourceId) { - updatedConstraints.video.mandatory.chromeMediaSourceId = sourceId; - } - - delete updatedConstraints.video.mediaSource; - - baseGetUserMedia(updatedConstraints, successCb, failureCb); - - } else { - if (error === 'permission-denied') { - throw new Error('Permission denied for screen retrieval'); - } else { - throw new Error('Failed retrieving selected screen'); - } - } - }; - - var onIFrameCallback = function (event) { - if (!event.data) { - return; - } - - if (event.data.chromeMediaSourceId) { - if (event.data.chromeMediaSourceId === 'PermissionDeniedError') { - chromeCallback('permission-denied'); - } else { - chromeCallback(null, event.data.chromeMediaSourceId); - } - } - - if (event.data.chromeExtensionStatus) { - if (event.data.chromeExtensionStatus === 'not-installed') { - AdapterJS.renderNotificationBar(AdapterJS.TEXT.EXTENSION.REQUIRE_INSTALLATION_CHROME, - AdapterJS.TEXT.EXTENSION.BUTTON_CHROME, - event.data.data, true, true); - } else { - chromeCallback(event.data.chromeExtensionStatus, null); - } - } - - // this event listener is no more needed - window.removeEventListener('message', onIFrameCallback); - }; - - window.addEventListener('message', onIFrameCallback); - - postFrameMessage({ - captureSourceId: true - }); - - } else { - baseGetUserMedia(constraints, successCb, failureCb); - } - }; - - getUserMedia = navigator.getUserMedia; - - } else { - baseGetUserMedia = window.navigator.getUserMedia; - - navigator.getUserMedia = function (constraints, successCb, failureCb) { - if (constraints && constraints.video && !!constraints.video.mediaSource) { - // would be fine since no methods - var updatedConstraints = clone(constraints); - - // wait for plugin to be ready - AdapterJS.WebRTCPlugin.callWhenPluginReady(function() { - // check if screensharing feature is available - if (!!AdapterJS.WebRTCPlugin.plugin.HasScreensharingFeature && - !!AdapterJS.WebRTCPlugin.plugin.isScreensharingAvailable) { - - - // set the constraints - updatedConstraints.video.optional = updatedConstraints.video.optional || []; - updatedConstraints.video.optional.push({ - sourceId: AdapterJS.WebRTCPlugin.plugin.screensharingKey || 'Screensharing' - }); - - delete updatedConstraints.video.mediaSource; - } else { - throw new Error('Your WebRTC plugin does not support screensharing'); - } - baseGetUserMedia(updatedConstraints, successCb, failureCb); - }); - } else { - baseGetUserMedia(constraints, successCb, failureCb); - } - }; - - getUserMedia = window.navigator.getUserMedia; - } - - if (window.webrtcDetectedBrowser === 'chrome') { - var iframe = document.createElement('iframe'); - - iframe.onload = function() { - iframe.isLoaded = true; - }; - - iframe.src = 'https://cdn.temasys.com.sg/skylink/extensions/detectRTC.html'; - //'https://temasys-cdn.s3.amazonaws.com/skylink/extensions/detection-script-dev/detectRTC.html'; - iframe.style.display = 'none'; - - (document.body || document.documentElement).appendChild(iframe); - - var postFrameMessage = function (object) { - object = object || {}; - - if (!iframe.isLoaded) { - setTimeout(function () { - iframe.contentWindow.postMessage(object, '*'); - }, 100); - return; - } - - iframe.contentWindow.postMessage(object, '*'); - }; - } -})(); -},{}],13:[function(require,module,exports){ -/* global Strophe, APP, $, config, interfaceConfig, toastr */ -var UI = {}; - -var VideoLayout = require("./videolayout/VideoLayout.js"); -var AudioLevels = require("./audio_levels/AudioLevels.js"); -var Prezi = require("./prezi/Prezi.js"); -var Etherpad = require("./etherpad/Etherpad.js"); -var Chat = require("./side_pannels/chat/Chat.js"); -var Toolbar = require("./toolbars/Toolbar"); -var ToolbarToggler = require("./toolbars/ToolbarToggler"); -var BottomToolbar = require("./toolbars/BottomToolbar"); -var ContactList = require("./side_pannels/contactlist/ContactList"); -var Avatar = require("./avatar/Avatar"); -var EventEmitter = require("events"); -var SettingsMenu = require("./side_pannels/settings/SettingsMenu"); -var Settings = require("./../settings/Settings"); -var PanelToggler = require("./side_pannels/SidePanelToggler"); -var RoomNameGenerator = require("./welcome_page/RoomnameGenerator"); -UI.messageHandler = require("./util/MessageHandler"); -var messageHandler = UI.messageHandler; -var Authentication = require("./authentication/Authentication"); -var UIUtil = require("./util/UIUtil"); -var NicknameHandler = require("./util/NicknameHandler"); -var JitsiPopover = require("./util/JitsiPopover"); -var CQEvents = require("../../service/connectionquality/CQEvents"); -var DesktopSharingEventTypes - = require("../../service/desktopsharing/DesktopSharingEventTypes"); -var RTCEvents = require("../../service/RTC/RTCEvents"); -var RTCBrowserType = require("../RTC/RTCBrowserType"); -var StreamEventTypes = require("../../service/RTC/StreamEventTypes"); -var XMPPEvents = require("../../service/xmpp/XMPPEvents"); -var UIEvents = require("../../service/UI/UIEvents"); -var MemberEvents = require("../../service/members/Events"); - -var eventEmitter = new EventEmitter(); -var roomName = null; - - -function promptDisplayName() { - var message = '

    '; - message += APP.translation.translateString( - "dialog.displayNameRequired"); - message += '

    ' + - ''; - - var buttonTxt - = APP.translation.generateTranslationHTML("dialog.Ok"); - var buttons = []; - buttons.push({title: buttonTxt, value: "ok"}); - - messageHandler.openDialog(null, message, - true, - buttons, - function (e, v, m, f) { - if (v == "ok") { - var displayName = f.displayName; - if (displayName) { - VideoLayout.inputDisplayNameHandler(displayName); - return true; - } - } - e.preventDefault(); - }, - function () { - var form = $.prompt.getPrompt(); - var input = form.find("input[name='displayName']"); - input.focus(); - var button = form.find("button"); - button.attr("disabled", "disabled"); - input.keyup(function () { - if(!input.val()) - button.attr("disabled", "disabled"); - else - button.removeAttr("disabled"); - }); - } - ); -} - -function notifyForInitialMute() { - messageHandler.notify(null, "notify.mutedTitle", "connected", - "notify.muted", null, {timeOut: 120000}); -} - -function setupPrezi() { - $("#reloadPresentationLink").click(function() { - Prezi.reloadPresentation(); - }); -} - -function setupChat() { - Chat.init(); - $("#toggle_smileys").click(function() { - Chat.toggleSmileys(); - }); -} - -function setupToolbars() { - Toolbar.init(UI); - Toolbar.setupButtonsFromConfig(); - BottomToolbar.init(); -} - -function streamHandler(stream, isMuted) { - switch (stream.type) { - case "audio": - VideoLayout.changeLocalAudio(stream, isMuted); - break; - case "video": - VideoLayout.changeLocalVideo(stream, isMuted); - break; - case "stream": - VideoLayout.changeLocalStream(stream, isMuted); - break; - } -} - -function onXmppConnectionFailed(stropheErrorMsg) { - - var title = APP.translation.generateTranslationHTML( - "dialog.error"); - - var message; - if (stropheErrorMsg) { - message = APP.translation.generateTranslationHTML( - "dialog.connectErrorWithMsg", {msg: stropheErrorMsg}); - } else { - message = APP.translation.generateTranslationHTML( - "dialog.connectError"); - } - - messageHandler.openDialog( - title, message, true, {}, function (e, v, m, f) { return false; }); -} - -function onDisposeConference(unload) { - Toolbar.showAuthenticateButton(false); -} - -function onDisplayNameChanged(jid, displayName) { - ContactList.onDisplayNameChange(jid, displayName); - SettingsMenu.onDisplayNameChange(jid, displayName); - VideoLayout.onDisplayNameChanged(jid, displayName); -} - -function registerListeners() { - APP.RTC.addStreamListener(streamHandler, - StreamEventTypes.EVENT_TYPE_LOCAL_CREATED); - APP.RTC.addStreamListener(streamHandler, - StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED); - APP.RTC.addStreamListener(function (stream) { - VideoLayout.onRemoteStreamAdded(stream); - }, StreamEventTypes.EVENT_TYPE_REMOTE_CREATED); - APP.RTC.addListener(RTCEvents.LASTN_CHANGED, onLastNChanged); - APP.RTC.addListener(RTCEvents.DOMINANTSPEAKER_CHANGED, - function (resourceJid) { - VideoLayout.onDominantSpeakerChanged(resourceJid); - }); - APP.RTC.addListener(RTCEvents.LASTN_ENDPOINT_CHANGED, - function (lastNEndpoints, endpointsEnteringLastN, stream) { - VideoLayout.onLastNEndpointsChanged(lastNEndpoints, - endpointsEnteringLastN, stream); - }); - APP.RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, - function (devices) { - VideoLayout.setDeviceAvailabilityIcons(null, devices); - }); - APP.RTC.addListener(RTCEvents.VIDEO_MUTE, UI.setVideoMuteButtonsState); - APP.RTC.addListener(RTCEvents.DATA_CHANNEL_OPEN, function () { - // when the data channel becomes available, tell the bridge about video - // selections so that it can do adaptive simulcast, - // we want the notification to trigger even if userJid is undefined, - // or null. - var userResource = APP.UI.getLargeVideoResource(); - eventEmitter.emit(UIEvents.SELECTED_ENDPOINT, userResource); - }); - APP.statistics.addAudioLevelListener(function(jid, audioLevel) { - var resourceJid; - if(jid === APP.statistics.LOCAL_JID) { - resourceJid = AudioLevels.LOCAL_LEVEL; - if(APP.RTC.localAudio.isMuted()) { - audioLevel = 0; - } - } else { - resourceJid = Strophe.getResourceFromJid(jid); - } - - AudioLevels.updateAudioLevel(resourceJid, audioLevel, - UI.getLargeVideoResource()); - }); - APP.desktopsharing.addListener(function () { - ToolbarToggler.showDesktopSharingButton(); - }, DesktopSharingEventTypes.INIT); - APP.desktopsharing.addListener( - Toolbar.changeDesktopSharingButtonState, - DesktopSharingEventTypes.SWITCHING_DONE); - APP.connectionquality.addListener(CQEvents.LOCALSTATS_UPDATED, - VideoLayout.updateLocalConnectionStats); - APP.connectionquality.addListener(CQEvents.REMOTESTATS_UPDATED, - VideoLayout.updateConnectionStats); - APP.connectionquality.addListener(CQEvents.STOP, - VideoLayout.onStatsStop); - APP.xmpp.addListener(XMPPEvents.CONNECTION_FAILED, onXmppConnectionFailed); - APP.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE, onDisposeConference); - APP.xmpp.addListener(XMPPEvents.GRACEFUL_SHUTDOWN, function () { - messageHandler.openMessageDialog( - 'dialog.serviceUnavailable', - 'dialog.gracefulShutdown' - ); - }); - APP.xmpp.addListener(XMPPEvents.RESERVATION_ERROR, function (code, msg) { - var title = APP.translation.generateTranslationHTML( - "dialog.reservationError"); - var message = APP.translation.generateTranslationHTML( - "dialog.reservationErrorMsg", {code: code, msg: msg}); - messageHandler.openDialog( - title, - message, - true, {}, - function (event, value, message, formVals) { - return false; - } - ); - }); - APP.xmpp.addListener(XMPPEvents.KICKED, function () { - messageHandler.openMessageDialog("dialog.sessTerminated", - "dialog.kickMessage"); - }); - APP.xmpp.addListener(XMPPEvents.MUC_DESTROYED, function (reason) { - //FIXME: use Session Terminated from translation, but - // 'reason' text comes from XMPP packet and is not translated - var title = APP.translation.generateTranslationHTML("dialog.sessTerminated"); - messageHandler.openDialog( - title, reason, true, {}, - function (event, value, message, formVals) { - return false; - } - ); - }); - APP.xmpp.addListener(XMPPEvents.BRIDGE_DOWN, function () { - messageHandler.showError("dialog.error", - "dialog.bridgeUnavailable"); - }); - APP.xmpp.addListener(XMPPEvents.USER_ID_CHANGED, function (from, id) { - Avatar.setUserAvatar(from, id); - }); - APP.xmpp.addListener(XMPPEvents.DISPLAY_NAME_CHANGED, onDisplayNameChanged); - APP.xmpp.addListener(XMPPEvents.MUC_JOINED, onMucJoined); - APP.xmpp.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, onLocalRoleChanged); - APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_JOINED, onMucMemberJoined); - APP.xmpp.addListener(XMPPEvents.MUC_ROLE_CHANGED, onMucRoleChanged); - APP.xmpp.addListener(XMPPEvents.PRESENCE_STATUS, onMucPresenceStatus); - APP.xmpp.addListener(XMPPEvents.SUBJECT_CHANGED, chatSetSubject); - APP.xmpp.addListener(XMPPEvents.MUC_MEMBER_LEFT, onMucMemberLeft); - APP.xmpp.addListener(XMPPEvents.PASSWORD_REQUIRED, onPasswordRequired); - APP.xmpp.addListener(XMPPEvents.ETHERPAD, initEtherpad); - APP.xmpp.addListener(XMPPEvents.AUTHENTICATION_REQUIRED, - onAuthenticationRequired); - APP.xmpp.addListener(XMPPEvents.VIDEO_TYPE, onPeerVideoTypeChanged); - APP.xmpp.addListener(XMPPEvents.DEVICE_AVAILABLE, - function (resource, devices) { - VideoLayout.setDeviceAvailabilityIcons(resource, devices); - }); - - APP.xmpp.addListener(XMPPEvents.AUDIO_MUTED, VideoLayout.onAudioMute); - APP.xmpp.addListener(XMPPEvents.VIDEO_MUTED, VideoLayout.onVideoMute); - APP.xmpp.addListener(XMPPEvents.AUDIO_MUTED_BY_FOCUS, function (doMuteAudio) { - UI.setAudioMuted(doMuteAudio); - }); - APP.members.addListener(MemberEvents.DTMF_SUPPORT_CHANGED, - onDtmfSupportChanged); - APP.xmpp.addListener(XMPPEvents.START_MUTED_SETTING_CHANGED, function (audio, video) { - SettingsMenu.setStartMuted(audio, video); - }); - APP.xmpp.addListener(XMPPEvents.START_MUTED_FROM_FOCUS, function (audio, video) { - UI.setInitialMuteFromFocus(audio, video); - }); - - APP.xmpp.addListener(XMPPEvents.JINGLE_FATAL_ERROR, function (session, error) { - UI.messageHandler.showError("dialog.sorry", - "dialog.internalError"); - }); - - APP.xmpp.addListener(XMPPEvents.SET_LOCAL_DESCRIPTION_ERROR, function () { - messageHandler.showError("dialog.error", - "dialog.SLDFailure"); - }); - APP.xmpp.addListener(XMPPEvents.SET_REMOTE_DESCRIPTION_ERROR, function () { - messageHandler.showError("dialog.error", - "dialog.SRDFailure"); - }); - APP.xmpp.addListener(XMPPEvents.CREATE_ANSWER_ERROR, function () { - messageHandler.showError(); - }); - APP.xmpp.addListener(XMPPEvents.PROMPT_FOR_LOGIN, function () { - // FIXME: re-use LoginDialog which supports retries - UI.showLoginPopup(connect); - }); - - APP.xmpp.addListener(XMPPEvents.FOCUS_DISCONNECTED, function (focusComponent, retrySec) { - UI.messageHandler.notify( - null, "notify.focus", - 'disconnected', "notify.focusFail", - {component: focusComponent, ms: retrySec}); - }); - - APP.xmpp.addListener(XMPPEvents.ROOM_JOIN_ERROR, function (pres) { - UI.messageHandler.openReportDialog(null, - "dialog.joinError", pres); - }); - APP.xmpp.addListener(XMPPEvents.ROOM_CONNECT_ERROR, function (pres) { - UI.messageHandler.openReportDialog(null, - "dialog.connectError", pres); - }); - - APP.xmpp.addListener(XMPPEvents.READY_TO_JOIN, function () { - var roomName = UI.generateRoomName(); - APP.xmpp.allocateConferenceFocus(roomName, UI.checkForNicknameAndJoin); - }); - - //NicknameHandler emits this event - UI.addListener(UIEvents.NICKNAME_CHANGED, function (nickname) { - APP.xmpp.addToPresence("displayName", nickname); - }); - - UI.addListener(UIEvents.LARGEVIDEO_INIT, function () { - AudioLevels.init(); - }); - - if (!interfaceConfig.filmStripOnly) { - APP.xmpp.addListener(XMPPEvents.MESSAGE_RECEIVED, updateChatConversation); - APP.xmpp.addListener(XMPPEvents.CHAT_ERROR_RECEIVED, chatAddError); - // Listens for video interruption events. - APP.xmpp.addListener(XMPPEvents.CONNECTION_INTERRUPTED, VideoLayout.onVideoInterrupted); - // Listens for video restores events. - APP.xmpp.addListener(XMPPEvents.CONNECTION_RESTORED, VideoLayout.onVideoRestored); - } -} - - -/** - * Mutes/unmutes the local video. - * - * @param mute true to mute the local video; otherwise, false - * @param options an object which specifies optional arguments such as the - * boolean key byUser with default value true which - * specifies whether the method was initiated in response to a user command (in - * contrast to an automatic decision taken by the application logic) - */ -function setVideoMute(mute, options) { - APP.RTC.setVideoMute(mute, - UI.setVideoMuteButtonsState, - options); -} - -function onResize() { - Chat.resizeChat(); - VideoLayout.resizeLargeVideoContainer(); -} - -function bindEvents() { - /** - * Resizes and repositions videos in full screen mode. - */ - $(document).on('webkitfullscreenchange mozfullscreenchange fullscreenchange', - onResize); - - $(window).resize(onResize); -} - -UI.start = function (init) { - document.title = interfaceConfig.APP_NAME; - var setupWelcomePage = null; - if(config.enableWelcomePage && window.location.pathname == "/" && - (!window.localStorage.welcomePageDisabled || - window.localStorage.welcomePageDisabled == "false")) { - $("#videoconference_page").hide(); - if (!setupWelcomePage) - setupWelcomePage = require("./welcome_page/WelcomePage"); - setupWelcomePage(); - - return; - } - - $("#welcome_page").hide(); - - // Set the defaults for prompt dialogs. - $.prompt.setDefaults({persistent: false}); - - - registerListeners(); - - VideoLayout.init(eventEmitter); - NicknameHandler.init(eventEmitter); - - bindEvents(); - setupPrezi(); - if (!interfaceConfig.filmStripOnly) { - $("#videospace").mousemove(function () { - return ToolbarToggler.showToolbar(); - }); - setupToolbars(); - setupChat(); - // Display notice message at the top of the toolbar - if (config.noticeMessage) { - $('#noticeText').text(config.noticeMessage); - $('#notice').css({display: 'block'}); - } - $("#downloadlog").click(function (event) { - dump(event.target); - }); - } - else - { - $("#header").css("display", "none"); - $("#bottomToolbar").css("display", "none"); - $("#downloadlog").css("display", "none"); - $("#remoteVideos").css("padding", "0px 0px 18px 0px"); - $("#remoteVideos").css("right", "0px"); - messageHandler.disableNotifications(); - $('body').popover("disable"); -// $("[data-toggle=popover]").popover("disable"); - JitsiPopover.enabled = false; - } - - document.title = interfaceConfig.APP_NAME; - - - - - - if(config.requireDisplayName) { - var currentSettings = Settings.getSettings(); - if (!currentSettings.displayName) { - promptDisplayName(); - } - } - - init(); - - if (!interfaceConfig.filmStripOnly) { - toastr.options = { - "closeButton": true, - "debug": false, - "positionClass": "notification-bottom-right", - "onclick": null, - "showDuration": "300", - "hideDuration": "1000", - "timeOut": "2000", - "extendedTimeOut": "1000", - "showEasing": "swing", - "hideEasing": "linear", - "showMethod": "fadeIn", - "hideMethod": "fadeOut", - "reposition": function () { - if (PanelToggler.isVisible()) { - $("#toast-container").addClass("notification-bottom-right-center"); - } else { - $("#toast-container").removeClass("notification-bottom-right-center"); - } - }, - "newestOnTop": false - }; - - - SettingsMenu.init(); - } - -}; - -function chatAddError(errorMessage, originalText) { - return Chat.chatAddError(errorMessage, originalText); -} - -function chatSetSubject(text) { - return Chat.chatSetSubject(text); -} - -function updateChatConversation(from, displayName, message, myjid, stamp) { - return Chat.updateChatConversation(from, displayName, message, myjid, stamp); -} - -function onMucJoined(jid, info) { - Toolbar.updateRoomUrl(window.location.href); - var meHTML = APP.translation.generateTranslationHTML("me"); - $("#localNick").html(Strophe.getResourceFromJid(jid) + " (" + meHTML + ")"); - - var settings = Settings.getSettings(); - - // Make sure we configure our avatar id, before creating avatar for us - Avatar.setUserAvatar(jid, settings.email || settings.uid); - - // Add myself to the contact list. - ContactList.addContact(jid); - - // Once we've joined the muc show the toolbar - ToolbarToggler.showToolbar(); - - var displayName = - config.displayJids ? Strophe.getResourceFromJid(jid) : info.displayName; - - if (displayName) - onDisplayNameChanged('localVideoContainer', displayName); - - - VideoLayout.mucJoined(); -} - -function initEtherpad(name) { - Etherpad.init(name); -} - -function onMucMemberLeft(jid) { - console.log('left.muc', jid); - var displayName = $('#participant_' + Strophe.getResourceFromJid(jid) + - '>.displayname').html(); - messageHandler.notify(displayName,'notify.somebody', - 'disconnected', - 'notify.disconnected'); - if (!config.startAudioMuted || - config.startAudioMuted > APP.members.size()) { - UIUtil.playSoundNotification('userLeft'); - } - - ContactList.removeContact(jid); - - VideoLayout.participantLeft(jid); -} - -function onLocalRoleChanged(jid, info, pres, isModerator) { - console.info("My role changed, new role: " + info.role); - onModeratorStatusChanged(isModerator); - VideoLayout.showModeratorIndicator(); - SettingsMenu.onRoleChanged(); - - if (isModerator) { - Authentication.closeAuthenticationWindow(); - messageHandler.notify(null, "notify.me", - 'connected', "notify.moderator"); - - Toolbar.checkAutoRecord(); - } -} - -function onModeratorStatusChanged(isModerator) { - Toolbar.showSipCallButton(isModerator); - Toolbar.showRecordingButton( - isModerator); //&& - // FIXME: - // Recording visible if - // there are at least 2(+ 1 focus) participants - //Object.keys(connection.emuc.members).length >= 3); -} - -function onPasswordRequired(callback) { - // password is required - Toolbar.lockLockButton(); - var message = '

    '; - message += APP.translation.translateString( - "dialog.passwordRequired"); - message += '

    ' + - ''; - - messageHandler.openTwoButtonDialog(null, null, null, message, - true, - "dialog.Ok", - function (e, v, m, f) {}, - null, - function (e, v, m, f) { - if (v) { - var lockKey = f.lockKey; - if (lockKey) { - Toolbar.setSharedKey(lockKey); - callback(lockKey); - } - } - }, - ':input:first' - ); -} - -/** - * The dialpad button is shown iff there is at least one member that supports - * DTMF (e.g. jigasi). - */ -function onDtmfSupportChanged(dtmfSupport) { - //TODO: enable when the UI is ready - //Toolbar.showDialPadButton(dtmfSupport); -} - -function onMucMemberJoined(jid, id, displayName) { - messageHandler.notify(displayName,'notify.somebody', - 'connected', - 'notify.connected'); - - if (!config.startAudioMuted || - config.startAudioMuted > APP.members.size()) - UIUtil.playSoundNotification('userJoined'); - - // Configure avatar - Avatar.setUserAvatar(jid, id); - - // Add Peer's container - VideoLayout.ensurePeerContainerExists(jid); -} - -function onMucPresenceStatus(jid, info) { - VideoLayout.setPresenceStatus(Strophe.getResourceFromJid(jid), info.status); -} - -function onPeerVideoTypeChanged(resourceJid, newVideoType) { - VideoLayout.onVideoTypeChanged(resourceJid, newVideoType); -} - -function onMucRoleChanged(role, displayName) { - VideoLayout.showModeratorIndicator(); - - if (role === 'moderator') { - var messageKey, messageOptions = {}; - if (!displayName) { - messageKey = "notify.grantedToUnknown"; - } - else { - messageKey = "notify.grantedTo"; - messageOptions = {to: displayName}; - } - messageHandler.notify( - displayName,'notify.somebody', - 'connected', messageKey, - messageOptions); - } -} - -function onAuthenticationRequired(intervalCallback) { - Authentication.openAuthenticationDialog( - roomName, intervalCallback, function () { - Toolbar.authenticateClicked(); - }); -} - - -function onLastNChanged(oldValue, newValue) { - if (config.muteLocalVideoIfNotInLastN) { - setVideoMute(!newValue, { 'byUser': false }); - } -} - - -UI.toggleSmileys = function () { - Chat.toggleSmileys(); -}; - -UI.getSettings = function () { - return Settings.getSettings(); -}; - -UI.toggleFilmStrip = function () { - return BottomToolbar.toggleFilmStrip(); -}; - -UI.toggleChat = function () { - return BottomToolbar.toggleChat(); -}; - -UI.toggleContactList = function () { - return BottomToolbar.toggleContactList(); -}; - -UI.inputDisplayNameHandler = function (value) { - VideoLayout.inputDisplayNameHandler(value); -}; - -UI.getLargeVideoResource = function () { - return VideoLayout.getLargeVideoResource(); -}; - -UI.generateRoomName = function() { - if(roomName) - return roomName; - var roomnode = null; - var path = window.location.pathname; - - // determinde the room node from the url - // TODO: just the roomnode or the whole bare jid? - if (config.getroomnode && typeof config.getroomnode === 'function') { - // custom function might be responsible for doing the pushstate - roomnode = config.getroomnode(path); - } else { - /* fall back to default strategy - * this is making assumptions about how the URL->room mapping happens. - * It currently assumes deployment at root, with a rewrite like the - * following one (for nginx): - location ~ ^/([a-zA-Z0-9]+)$ { - rewrite ^/(.*)$ / break; - } - */ - if (path.length > 1) { - roomnode = path.substr(1).toLowerCase(); - } else { - var word = RoomNameGenerator.generateRoomWithoutSeparator(); - roomnode = word.toLowerCase(); - - window.history.pushState('VideoChat', - 'Room: ' + word, window.location.pathname + word); - } - } - - roomName = roomnode + '@' + config.hosts.muc; - return roomName; -}; - - -UI.connectionIndicatorShowMore = function(jid) { - return VideoLayout.showMore(jid); -}; - -UI.showLoginPopup = function(callback) { - console.log('password is required'); - var message = '

    '; - message += APP.translation.translateString( - "dialog.passwordRequired"); - message += '

    ' + - '' + - ''; - UI.messageHandler.openTwoButtonDialog(null, null, null, message, - true, - "dialog.Ok", - function (e, v, m, f) { - if (v) { - if (f.username !== null && f.password != null) { - callback(f.username, f.password); - } - } - }, - null, null, ':input:first' - - ); -}; - -UI.checkForNicknameAndJoin = function () { - - Authentication.closeAuthenticationDialog(); - Authentication.stopInterval(); - - var nick = null; - if (config.useNicks) { - nick = window.prompt('Your nickname (optional)'); - } - APP.xmpp.joinRoom(roomName, config.useNicks, nick); -}; - - -function dump(elem, filename) { - elem = elem.parentNode; - elem.download = filename || 'meetlog.json'; - elem.href = 'data:application/json;charset=utf-8,\n'; - var data = APP.xmpp.getJingleLog(); - var metadata = {}; - metadata.time = new Date(); - metadata.url = window.location.href; - metadata.ua = navigator.userAgent; - var log = APP.xmpp.getXmppLog(); - if (log) { - metadata.xmpp = log; - } - data.metadata = metadata; - elem.href += encodeURIComponent(JSON.stringify(data, null, ' ')); - return false; -} - -UI.getRoomName = function () { - return roomName; -}; - -UI.setInitialMuteFromFocus = function (muteAudio, muteVideo) { - if (muteAudio || muteVideo) - notifyForInitialMute(); - if (muteAudio) - UI.setAudioMuted(true); - if (muteVideo) - UI.setVideoMute(true); -}; - -/** - * Mutes/unmutes the local video. - */ -UI.toggleVideo = function () { - setVideoMute(!APP.RTC.localVideo.isMuted()); -}; - -/** - * Mutes / unmutes audio for the local participant. - */ -UI.toggleAudio = function() { - UI.setAudioMuted(!APP.RTC.localAudio.isMuted()); -}; - -/** - * Sets muted audio state for the local participant. - */ -UI.setAudioMuted = function (mute, earlyMute) { - var audioMute = null; - if (earlyMute) - audioMute = function (mute, cb) { - return APP.xmpp.sendAudioInfoPresence(mute, cb); - }; - else - audioMute = function (mute, cb) { - return APP.xmpp.setAudioMute(mute, cb); - }; - if (!audioMute(mute, function () { - VideoLayout.showLocalAudioIndicator(mute); - - UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled"); - })) { - // We still click the button. - UIUtil.buttonClick("#toolbar_button_mute", "icon-microphone icon-mic-disabled"); - return; - } -}; - -UI.addListener = function (type, listener) { - eventEmitter.on(type, listener); -}; - -UI.clickOnVideo = function (videoNumber) { - var remoteVideos = $(".videocontainer:not(#mixedstream)"); - if (remoteVideos.length > videoNumber) { - remoteVideos[videoNumber].click(); - } -}; - -//Used by torture -UI.showToolbar = function () { - return ToolbarToggler.showToolbar(); -}; - -//Used by torture -UI.dockToolbar = function (isDock) { - return ToolbarToggler.dockToolbar(isDock); -}; - -UI.setVideoMuteButtonsState = function (mute) { - var video = $('#toolbar_button_camera'); - var communicativeClass = "icon-camera"; - var muteClass = "icon-camera icon-camera-disabled"; - - if (mute) { - video.removeClass(communicativeClass); - video.addClass(muteClass); - } else { - video.removeClass(muteClass); - video.addClass(communicativeClass); - } -}; - -UI.userAvatarChanged = function (resourceJid, thumbUrl, contactListUrl) { - VideoLayout.userAvatarChanged(resourceJid, thumbUrl); - ContactList.userAvatarChanged(resourceJid, contactListUrl); - if(resourceJid === APP.xmpp.myResource()) - SettingsMenu.changeAvatar(thumbUrl); -}; - -UI.setVideoMute = setVideoMute; - -module.exports = UI; - - -},{"../../service/RTC/RTCEvents":157,"../../service/RTC/StreamEventTypes":159,"../../service/UI/UIEvents":160,"../../service/connectionquality/CQEvents":162,"../../service/desktopsharing/DesktopSharingEventTypes":163,"../../service/members/Events":164,"../../service/xmpp/XMPPEvents":166,"../RTC/RTCBrowserType":10,"./../settings/Settings":49,"./audio_levels/AudioLevels.js":14,"./authentication/Authentication":16,"./avatar/Avatar":18,"./etherpad/Etherpad.js":19,"./prezi/Prezi.js":20,"./side_pannels/SidePanelToggler":22,"./side_pannels/chat/Chat.js":23,"./side_pannels/contactlist/ContactList":27,"./side_pannels/settings/SettingsMenu":28,"./toolbars/BottomToolbar":29,"./toolbars/Toolbar":30,"./toolbars/ToolbarToggler":31,"./util/JitsiPopover":32,"./util/MessageHandler":33,"./util/NicknameHandler":34,"./util/UIUtil":35,"./videolayout/VideoLayout.js":41,"./welcome_page/RoomnameGenerator":42,"./welcome_page/WelcomePage":43,"events":1}],14:[function(require,module,exports){ -/* global APP, interfaceConfig, $, Strophe */ -var CanvasUtil = require("./CanvasUtils"); - -var ASDrawContext = null; - -function initActiveSpeakerAudioLevels() { - var ASRadius = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE / 2; - var ASCenter = (interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE + ASRadius) / 2; - - // Draw a circle. - ASDrawContext.arc(ASCenter, ASCenter, ASRadius, 0, 2 * Math.PI); - - // Add a shadow around the circle - ASDrawContext.shadowColor = interfaceConfig.SHADOW_COLOR; - ASDrawContext.shadowOffsetX = 0; - ASDrawContext.shadowOffsetY = 0; -} - -/** - * The audio Levels plugin. - */ -var AudioLevels = (function(my) { - var audioLevelCanvasCache = {}; - - my.LOCAL_LEVEL = 'local'; - - my.init = function () { - ASDrawContext = $('#activeSpeakerAudioLevel')[0].getContext('2d'); - initActiveSpeakerAudioLevels(); - }; - - /** - * Updates the audio level canvas for the given peerJid. If the canvas - * didn't exist we create it. - */ - my.updateAudioLevelCanvas = function (peerJid, VideoLayout) { - var resourceJid = null; - var videoSpanId = null; - if (!peerJid) - videoSpanId = 'localVideoContainer'; - else { - resourceJid = Strophe.getResourceFromJid(peerJid); - - videoSpanId = 'participant_' + resourceJid; - } - - var videoSpan = document.getElementById(videoSpanId); - - if (!videoSpan) { - if (resourceJid) - console.error("No video element for jid", resourceJid); - else - console.error("No video element for local video."); - - return; - } - - var audioLevelCanvas = $('#' + videoSpanId + '>canvas'); - - var videoSpaceWidth = $('#remoteVideos').width(); - var thumbnailSize = VideoLayout.calculateThumbnailSize(videoSpaceWidth); - var thumbnailWidth = thumbnailSize[0]; - var thumbnailHeight = thumbnailSize[1]; - - if (!audioLevelCanvas || audioLevelCanvas.length === 0) { - - audioLevelCanvas = document.createElement('canvas'); - audioLevelCanvas.className = "audiolevel"; - audioLevelCanvas.style.bottom = "-" + interfaceConfig.CANVAS_EXTRA/2 + "px"; - audioLevelCanvas.style.left = "-" + interfaceConfig.CANVAS_EXTRA/2 + "px"; - resizeAudioLevelCanvas( audioLevelCanvas, - thumbnailWidth, - thumbnailHeight); - - videoSpan.appendChild(audioLevelCanvas); - } else { - audioLevelCanvas = audioLevelCanvas.get(0); - - resizeAudioLevelCanvas( audioLevelCanvas, - thumbnailWidth, - thumbnailHeight); - } - }; - - /** - * Updates the audio level UI for the given resourceJid. - * - * @param resourceJid the resource jid indicating the video element for - * which we draw the audio level - * @param audioLevel the newAudio level to render - */ - my.updateAudioLevel = function (resourceJid, audioLevel, largeVideoResourceJid) { - drawAudioLevelCanvas(resourceJid, audioLevel); - - var videoSpanId = getVideoSpanId(resourceJid); - - var audioLevelCanvas = $('#' + videoSpanId + '>canvas').get(0); - - if (!audioLevelCanvas) - return; - - var drawContext = audioLevelCanvas.getContext('2d'); - - var canvasCache = audioLevelCanvasCache[resourceJid]; - - drawContext.clearRect (0, 0, - audioLevelCanvas.width, audioLevelCanvas.height); - drawContext.drawImage(canvasCache, 0, 0); - - if(resourceJid === AudioLevels.LOCAL_LEVEL) { - if(!APP.xmpp.myJid()) { - return; - } - resourceJid = APP.xmpp.myResource(); - } - - if(resourceJid === largeVideoResourceJid) { - window.requestAnimationFrame(function () { - AudioLevels.updateActiveSpeakerAudioLevel(audioLevel); - }); - } - }; - - my.updateActiveSpeakerAudioLevel = function(audioLevel) { - if($("#activeSpeaker").css("visibility") == "hidden" || ASDrawContext === null) - return; - - ASDrawContext.clearRect(0, 0, 300, 300); - if(audioLevel == 0) - return; - - ASDrawContext.shadowBlur = getShadowLevel(audioLevel); - - - // Fill the shape. - ASDrawContext.fill(); - }; - - /** - * Resizes the given audio level canvas to match the given thumbnail size. - */ - function resizeAudioLevelCanvas(audioLevelCanvas, - thumbnailWidth, - thumbnailHeight) { - audioLevelCanvas.width = thumbnailWidth + interfaceConfig.CANVAS_EXTRA; - audioLevelCanvas.height = thumbnailHeight + interfaceConfig.CANVAS_EXTRA; - } - - /** - * Draws the audio level canvas into the cached canvas object. - * - * @param resourceJid the resource jid indicating the video element for - * which we draw the audio level - * @param audioLevel the newAudio level to render - */ - function drawAudioLevelCanvas(resourceJid, audioLevel) { - if (!audioLevelCanvasCache[resourceJid]) { - - var videoSpanId = getVideoSpanId(resourceJid); - - var audioLevelCanvasOrig = $('#' + videoSpanId + '>canvas').get(0); - - /* - * FIXME Testing has shown that audioLevelCanvasOrig may not exist. - * In such a case, the method CanvasUtil.cloneCanvas may throw an - * error. Since audio levels are frequently updated, the errors have - * been observed to pile into the console, strain the CPU. - */ - if (audioLevelCanvasOrig) { - audioLevelCanvasCache[resourceJid] = - CanvasUtil.cloneCanvas(audioLevelCanvasOrig); - } - } - - var canvas = audioLevelCanvasCache[resourceJid]; - - if (!canvas) - return; - - var drawContext = canvas.getContext('2d'); - - drawContext.clearRect(0, 0, canvas.width, canvas.height); - - var shadowLevel = getShadowLevel(audioLevel); - - if (shadowLevel > 0) { - // drawContext, x, y, w, h, r, shadowColor, shadowLevel - CanvasUtil.drawRoundRectGlow(drawContext, - interfaceConfig.CANVAS_EXTRA / 2, interfaceConfig.CANVAS_EXTRA / 2, - canvas.width - interfaceConfig.CANVAS_EXTRA, - canvas.height - interfaceConfig.CANVAS_EXTRA, - interfaceConfig.CANVAS_RADIUS, - interfaceConfig.SHADOW_COLOR, - shadowLevel); - } - } - - /** - * Returns the shadow/glow level for the given audio level. - * - * @param audioLevel the audio level from which we determine the shadow - * level - */ - function getShadowLevel (audioLevel) { - var shadowLevel = 0; - - if (audioLevel <= 0.3) { - shadowLevel = Math.round(interfaceConfig.CANVAS_EXTRA/2*(audioLevel/0.3)); - } - else if (audioLevel <= 0.6) { - shadowLevel = Math.round(interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.3) / 0.3)); - } - else { - shadowLevel = Math.round(interfaceConfig.CANVAS_EXTRA/2*((audioLevel - 0.6) / 0.4)); - } - return shadowLevel; - } - - /** - * Returns the video span id corresponding to the given resourceJid or local - * user. - */ - function getVideoSpanId(resourceJid) { - var videoSpanId = null; - if (resourceJid === AudioLevels.LOCAL_LEVEL || - (APP.xmpp.myResource() && resourceJid === APP.xmpp.myResource())) - videoSpanId = 'localVideoContainer'; - else - videoSpanId = 'participant_' + resourceJid; - - return videoSpanId; - } - - /** - * Indicates that the remote video has been resized. - */ - $(document).bind('remotevideo.resized', function (event, width, height) { - var resized = false; - $('#remoteVideos>span>canvas').each(function() { - var canvas = $(this).get(0); - if (canvas.width !== width + interfaceConfig.CANVAS_EXTRA) { - canvas.width = width + interfaceConfig.CANVAS_EXTRA; - resized = true; - } - - if (canvas.heigh !== height + interfaceConfig.CANVAS_EXTRA) { - canvas.height = height + interfaceConfig.CANVAS_EXTRA; - resized = true; - } - }); - - if (resized) - Object.keys(audioLevelCanvasCache).forEach(function (resourceJid) { - audioLevelCanvasCache[resourceJid].width = - width + interfaceConfig.CANVAS_EXTRA; - audioLevelCanvasCache[resourceJid].height = - height + interfaceConfig.CANVAS_EXTRA; - }); - }); - - return my; - -})(AudioLevels || {}); - -module.exports = AudioLevels; -},{"./CanvasUtils":15}],15:[function(require,module,exports){ -/** - * Utility class for drawing canvas shapes. - */ -var CanvasUtil = (function(my) { - - /** - * Draws a round rectangle with a glow. The glowWidth indicates the depth - * of the glow. - * - * @param drawContext the context of the canvas to draw to - * @param x the x coordinate of the round rectangle - * @param y the y coordinate of the round rectangle - * @param w the width of the round rectangle - * @param h the height of the round rectangle - * @param glowColor the color of the glow - * @param glowWidth the width of the glow - */ - my.drawRoundRectGlow - = function(drawContext, x, y, w, h, r, glowColor, glowWidth) { - - // Save the previous state of the context. - drawContext.save(); - - if (w < 2 * r) r = w / 2; - if (h < 2 * r) r = h / 2; - - // Draw a round rectangle. - drawContext.beginPath(); - drawContext.moveTo(x+r, y); - drawContext.arcTo(x+w, y, x+w, y+h, r); - drawContext.arcTo(x+w, y+h, x, y+h, r); - drawContext.arcTo(x, y+h, x, y, r); - drawContext.arcTo(x, y, x+w, y, r); - drawContext.closePath(); - - // Add a shadow around the rectangle - drawContext.shadowColor = glowColor; - drawContext.shadowBlur = glowWidth; - drawContext.shadowOffsetX = 0; - drawContext.shadowOffsetY = 0; - - // Fill the shape. - drawContext.fill(); - - drawContext.save(); - - drawContext.restore(); - -// 1) Uncomment this line to use Composite Operation, which is doing the -// same as the clip function below and is also antialiasing the round -// border, but is said to be less fast performance wise. - -// drawContext.globalCompositeOperation='destination-out'; - - drawContext.beginPath(); - drawContext.moveTo(x+r, y); - drawContext.arcTo(x+w, y, x+w, y+h, r); - drawContext.arcTo(x+w, y+h, x, y+h, r); - drawContext.arcTo(x, y+h, x, y, r); - drawContext.arcTo(x, y, x+w, y, r); - drawContext.closePath(); - -// 2) Uncomment this line to use Composite Operation, which is doing the -// same as the clip function below and is also antialiasing the round -// border, but is said to be less fast performance wise. - -// drawContext.fill(); - - // Comment these two lines if choosing to do the same with composite - // operation above 1 and 2. - drawContext.clip(); - drawContext.clearRect(0, 0, 277, 200); - - // Restore the previous context state. - drawContext.restore(); - }; - - /** - * Clones the given canvas. - * - * @return the new cloned canvas. - */ - my.cloneCanvas = function (oldCanvas) { - /* - * FIXME Testing has shown that oldCanvas may not exist. In such a case, - * the method CanvasUtil.cloneCanvas may throw an error. Since audio - * levels are frequently updated, the errors have been observed to pile - * into the console, strain the CPU. - */ - if (!oldCanvas) - return oldCanvas; - - //create a new canvas - var newCanvas = document.createElement('canvas'); - var context = newCanvas.getContext('2d'); - - //set dimensions - newCanvas.width = oldCanvas.width; - newCanvas.height = oldCanvas.height; - - //apply the old canvas to the new one - context.drawImage(oldCanvas, 0, 0); - - //return the new canvas - return newCanvas; - }; - - return my; -})(CanvasUtil || {}); - -module.exports = CanvasUtil; -},{}],16:[function(require,module,exports){ -/* global $, APP*/ - -var LoginDialog = require('./LoginDialog'); -var Moderator = require('../../xmpp/moderator'); - -/* Initial "authentication required" dialog */ -var authDialog = null; -/* Loop retry ID that wits for other user to create the room */ -var authRetryId = null; -var authenticationWindow = null; - -var Authentication = { - openAuthenticationDialog: function (roomName, intervalCallback, callback) { - // This is the loop that will wait for the room to be created by - // someone else. 'auth_required.moderator' will bring us back here. - authRetryId = window.setTimeout(intervalCallback, 5000); - // Show prompt only if it's not open - if (authDialog !== null) { - return; - } - // extract room name from 'room@muc.server.net' - var room = roomName.substr(0, roomName.indexOf('@')); - - var title - = APP.translation.generateTranslationHTML("dialog.WaitingForHost"); - var msg - = APP.translation.generateTranslationHTML( - "dialog.WaitForHostMsg", {room: room}); - - var buttonTxt - = APP.translation.generateTranslationHTML("dialog.IamHost"); - var buttons = []; - buttons.push({title: buttonTxt, value: "authNow"}); - - authDialog = APP.UI.messageHandler.openDialog( - title, - msg, - true, - buttons, - function (onSubmitEvent, submitValue) { - - // Do not close the dialog yet - onSubmitEvent.preventDefault(); - - // Open login popup - if (submitValue === 'authNow') { - callback(); - } - } - ); - }, - closeAuthenticationWindow: function () { - if (authenticationWindow) { - authenticationWindow.close(); - authenticationWindow = null; - } - }, - xmppAuthenticate: function () { - - var loginDialog = LoginDialog.show( - function (connection, state) { - if (!state) { - // User cancelled - loginDialog.close(); - return; - } else if (state == APP.xmpp.Status.CONNECTED) { - - loginDialog.close(); - - Authentication.stopInterval(); - Authentication.closeAuthenticationDialog(); - - // Close the connection as anonymous one will be used - // to create the conference. Session-id will authorize - // the request. - connection.disconnect(); - - var roomName = APP.UI.generateRoomName(); - Moderator.allocateConferenceFocus(roomName, function () { - // If it's not "on the fly" authentication now join - // the conference room - if (!APP.xmpp.isMUCJoined()) { - APP.UI.checkForNicknameAndJoin(); - } - }); - } - }, true); - }, - focusAuthenticationWindow: function () { - // If auth window exists just bring it to the front - if (authenticationWindow) { - authenticationWindow.focus(); - return; - } - }, - closeAuthenticationDialog: function () { - // Close authentication dialog if opened - if (authDialog) { - authDialog.close(); - authDialog = null; - } - }, - createAuthenticationWindow: function (callback, url) { - authenticationWindow = APP.UI.messageHandler.openCenteredPopup( - url, 910, 660, - // On closed - function () { - // Close authentication dialog if opened - Authentication.closeAuthenticationDialog(); - callback(); - authenticationWindow = null; - }); - return authenticationWindow; - }, - stopInterval: function () { - // Clear retry interval, so that we don't call 'doJoinAfterFocus' twice - if (authRetryId) { - window.clearTimeout(authRetryId); - authRetryId = null; - } - } -}; - -module.exports = Authentication; -},{"../../xmpp/moderator":62,"./LoginDialog":17}],17:[function(require,module,exports){ -/* global $, APP, config*/ - -var XMPP = require('../../xmpp/xmpp'); -var Moderator = require('../../xmpp/moderator'); - -//FIXME: use LoginDialog to add retries to XMPP.connect method used when -// anonymous domain is not enabled - -/** - * Creates new Dialog instance. - * @param callback function(Strophe.Connection, Strophe.Status) called - * when we either fail to connect or succeed(check Strophe.Status). - * @param obtainSession true if we want to send ConferenceIQ to Jicofo - * in order to create session-id after the connection is established. - * @constructor - */ -function Dialog(callback, obtainSession) { - - var self = this; - - var stop = false; - - var connection = APP.xmpp.createConnection(); - - var message = '

    '; - message += APP.translation.translateString("dialog.passwordRequired"); - message += '

    ' + - '' + - ''; - - var okButton = APP.translation.generateTranslationHTML("dialog.Ok"); - - var cancelButton = APP.translation.generateTranslationHTML("dialog.Cancel"); - - var states = { - login: { - html: message, - buttons: [ - { title: okButton, value: true}, - { title: cancelButton, value: false} - ], - focus: ':input:first', - submit: function (e, v, m, f) { - e.preventDefault(); - if (v) { - var jid = f.username; - var password = f.password; - if (jid && password) { - stop = false; - connection.reset(); - connDialog.goToState('connecting'); - connection.connect(jid, password, stateHandler); - } - } else { - // User cancelled - stop = true; - callback(); - } - } - }, - connecting: { - title: APP.translation.translateString('dialog.connecting'), - html: '
    ', - buttons: [], - defaultButton: 0 - }, - finished: { - title: APP.translation.translateString('dialog.error'), - html: '
    ', - buttons: [ - { - title: APP.translation.translateString('dialog.retry'), - value: 'retry' - }, - { - title: APP.translation.translateString('dialog.Cancel'), - value: 'cancel' - }, - ], - defaultButton: 0, - submit: function (e, v, m, f) { - e.preventDefault(); - if (v === 'retry') - connDialog.goToState('login'); - else - callback(); - } - } - }; - - var connDialog - = APP.UI.messageHandler.openDialogWithStates(states, - { persistent: true, closeText: '' }, null); - - var stateHandler = function (status, message) { - if (stop) { - return; - } - - var translateKey = "connection." + XMPP.getStatusString(status); - var statusStr = APP.translation.translateString(translateKey); - - // Display current state - var connectionStatus = - connDialog.getState('connecting').find('#connectionStatus'); - - connectionStatus.text(statusStr); - - switch (status) { - case XMPP.Status.CONNECTED: - - stop = true; - if (!obtainSession) { - callback(connection, status); - return; - } - // Obtaining session-id status - connectionStatus.text( - APP.translation.translateString( - 'connection.FETCH_SESSION_ID')); - - // Authenticate with Jicofo and obtain session-id - var roomName = APP.UI.generateRoomName(); - - // Jicofo will return new session-id when connected - // from authenticated domain - connection.sendIQ( - Moderator.createConferenceIq(roomName), - function (result) { - - connectionStatus.text( - APP.translation.translateString( - 'connection.GOT_SESSION_ID')); - - stop = true; - - // Parse session-id - Moderator.parseSessionId(result); - - callback(connection, status); - }, - function (error) { - console.error("Auth on the fly failed", error); - - stop = true; - - var errorMsg = - APP.translation.translateString( - 'connection.GET_SESSION_ID_ERROR') + - $(error).find('>error').attr('code'); - - self.displayError(errorMsg); - - connection.disconnect(); - }); - - break; - case XMPP.Status.AUTHFAIL: - case XMPP.Status.CONNFAIL: - case XMPP.Status.DISCONNECTED: - - stop = true; - - callback(connection, status); - - var errorMessage = statusStr; - - if (message) - { - errorMessage += ': ' + message; - } - self.displayError(errorMessage); - - break; - default: - break; - } - }; - - /** - * Displays error message in 'finished' state which allows either to cancel - * or retry. - * @param message the final message to be displayed. - */ - this.displayError = function (message) { - - var finishedState = connDialog.getState('finished'); - - var errorMessageElem = finishedState.find('#errorMessage'); - errorMessageElem.text(message); - - connDialog.goToState('finished'); - }; - - /** - * Closes LoginDialog. - */ - this.close = function () { - stop = true; - connDialog.close(); - }; -} - -var LoginDialog = { - - /** - * Displays login prompt used to establish new XMPP connection. Given - * callback(Strophe.Connection, Strophe.Status) function will be - * called when we connect successfully(status === CONNECTED) or when we fail - * to do so. On connection failure program can call Dialog.close() method in - * order to cancel or do nothing to let the user retry. - * @param callback function(Strophe.Connection, Strophe.Status) - * called when we either fail to connect or succeed(check - * Strophe.Status). - * @param obtainSession true if we want to send ConferenceIQ to - * Jicofo in order to create session-id after the connection is - * established. - * @returns {Dialog} - */ - show: function (callback, obtainSession) { - return new Dialog(callback, obtainSession); - } -}; - -module.exports = LoginDialog; -},{"../../xmpp/moderator":62,"../../xmpp/xmpp":70}],18:[function(require,module,exports){ -var Settings = require("../../settings/Settings"); - -var users = {}; - -var Avatar = { - - /** - * Sets the user's avatar in the settings menu(if local user), contact list - * and thumbnail - * @param jid jid of the user - * @param id email or userID to be used as a hash - */ - setUserAvatar: function (jid, id) { - if (id) { - if (users[jid] === id) { - return; - } - users[jid] = id; - } - var thumbUrl = this.getThumbUrl(jid); - var contactListUrl = this.getContactListUrl(jid); - var resourceJid = Strophe.getResourceFromJid(jid); - - APP.UI.userAvatarChanged(resourceJid, thumbUrl, contactListUrl); - }, - /** - * Returns image URL for the avatar to be displayed on large video area - * where current active speaker is presented. - * @param jid full MUC jid of the user for whom we want to obtain avatar URL - */ - getActiveSpeakerUrl: function (jid) { - return this.getGravatarUrl(jid, 100); - }, - /** - * Returns image URL for the avatar to be displayed on small video thumbnail - * @param jid full MUC jid of the user for whom we want to obtain avatar URL - */ - getThumbUrl: function (jid) { - return this.getGravatarUrl(jid, 100); - }, - /** - * Returns the URL for the avatar to be displayed as contactlist item - * @param jid full MUC jid of the user for whom we want to obtain avatar URL - */ - getContactListUrl: function (jid) { - return this.getGravatarUrl(jid, 30); - }, - getGravatarUrl: function (jid, size) { - if (!jid) { - console.error("Get gravatar - jid is undefined"); - return null; - } - var id = users[jid]; - if (!id) { - console.warn( - "No avatar stored yet for " + jid + " - using JID as ID"); - id = jid; - } - return 'https://www.gravatar.com/avatar/' + - MD5.hexdigest(id.trim().toLowerCase()) + - "?d=wavatar&size=" + (size || "30"); - } - -}; - - -module.exports = Avatar; -},{"../../settings/Settings":49}],19:[function(require,module,exports){ -/* global $, config, - setLargeVideoVisible, Util */ - -var VideoLayout = require("../videolayout/VideoLayout"); -var Prezi = require("../prezi/Prezi"); -var UIUtil = require("../util/UIUtil"); - -var etherpadName = null; -var etherpadIFrame = null; -var domain = null; -var options = "?showControls=true&showChat=false&showLineNumbers=true&useMonospaceFont=false"; - - -/** - * Resizes the etherpad. - */ -function resize() { - if ($('#etherpad>iframe').length) { - var remoteVideos = $('#remoteVideos'); - var availableHeight - = window.innerHeight - remoteVideos.outerHeight(); - var availableWidth = UIUtil.getAvailableVideoWidth(); - - $('#etherpad>iframe').width(availableWidth); - $('#etherpad>iframe').height(availableHeight); - } -} - -/** - * Creates the Etherpad button and adds it to the toolbar. - */ -function enableEtherpadButton() { - if (!$('#toolbar_button_etherpad').is(":visible")) - $('#toolbar_button_etherpad').css({display: 'inline-block'}); -} - -/** - * Creates the IFrame for the etherpad. - */ -function createIFrame() { - etherpadIFrame = VideoLayout.createEtherpadIframe( - domain + etherpadName + options, function() { - - document.domain = document.domain; - bubbleIframeMouseMove(etherpadIFrame); - setTimeout(function() { - // the iframes inside of the etherpad are - // not yet loaded when the etherpad iframe is loaded - var outer = etherpadIFrame. - contentDocument.getElementsByName("ace_outer")[0]; - bubbleIframeMouseMove(outer); - var inner = outer. - contentDocument.getElementsByName("ace_inner")[0]; - bubbleIframeMouseMove(inner); - }, 2000); - }); -} - -function bubbleIframeMouseMove(iframe){ - var existingOnMouseMove = iframe.contentWindow.onmousemove; - iframe.contentWindow.onmousemove = function(e){ - if(existingOnMouseMove) existingOnMouseMove(e); - var evt = document.createEvent("MouseEvents"); - var boundingClientRect = iframe.getBoundingClientRect(); - evt.initMouseEvent( - "mousemove", - true, // bubbles - false, // not cancelable - window, - e.detail, - e.screenX, - e.screenY, - e.clientX + boundingClientRect.left, - e.clientY + boundingClientRect.top, - e.ctrlKey, - e.altKey, - e.shiftKey, - e.metaKey, - e.button, - null // no related element - ); - iframe.dispatchEvent(evt); - }; -} - - -var Etherpad = { - /** - * Initializes the etherpad. - */ - init: function (name) { - - if (config.etherpad_base && !etherpadName && name) { - - domain = config.etherpad_base; - - etherpadName = name; - - enableEtherpadButton(); - - /** - * Resizes the etherpad, when the window is resized. - */ - $(window).resize(function () { - resize(); - }); - } - }, - - /** - * Opens/hides the Etherpad. - */ - toggleEtherpad: function (isPresentation) { - if (!etherpadIFrame) - createIFrame(); - - - if(VideoLayout.getLargeVideoState() === "etherpad") - { - VideoLayout.setLargeVideoState("video"); - } - else - { - VideoLayout.setLargeVideoState("etherpad"); - } - resize(); - } -}; - -module.exports = Etherpad; - -},{"../prezi/Prezi":20,"../util/UIUtil":35,"../videolayout/VideoLayout":41}],20:[function(require,module,exports){ -var ToolbarToggler = require("../toolbars/ToolbarToggler"); -var UIUtil = require("../util/UIUtil"); -var VideoLayout = require("../videolayout/VideoLayout"); -var messageHandler = require("../util/MessageHandler"); -var PreziPlayer = require("./PreziPlayer"); - -var preziPlayer = null; - - -/** - * Shows/hides a presentation. - */ -function setPresentationVisible(visible) { - - if (visible) { - VideoLayout.setLargeVideoState("prezi"); - } - else { - VideoLayout.setLargeVideoState("video"); - } -} - -var Prezi = { - - - /** - * Reloads the current presentation. - */ - reloadPresentation: function() { - var iframe = document.getElementById(preziPlayer.options.preziId); - iframe.src = iframe.src; - }, - - /** - * Returns true if the presentation is visible, false - - * otherwise. - */ - isPresentationVisible: function () { - return ($('#presentation>iframe') != null - && $('#presentation>iframe').css('opacity') == 1); - }, - - /** - * Opens the Prezi dialog, from which the user could choose a presentation - * to load. - */ - openPreziDialog: function() { - var myprezi = APP.xmpp.getPrezi(); - if (myprezi) { - messageHandler.openTwoButtonDialog("dialog.removePreziTitle", - null, - "dialog.removePreziMsg", - null, - false, - "dialog.Remove", - function(e,v,m,f) { - if(v) { - APP.xmpp.removePreziFromPresence(); - } - } - ); - } - else if (preziPlayer != null) { - messageHandler.openTwoButtonDialog("dialog.sharePreziTitle", - null, "dialog.sharePreziMsg", - null, - false, - "dialog.Ok", - function(e,v,m,f) { - $.prompt.close(); - } - ); - } - else { - var html = APP.translation.generateTranslationHTML( - "dialog.sharePreziTitle"); - var cancelButton = APP.translation.generateTranslationHTML( - "dialog.Cancel"); - var shareButton = APP.translation.generateTranslationHTML( - "dialog.Share"); - var backButton = APP.translation.generateTranslationHTML( - "dialog.Back"); - var buttons = []; - var buttons1 = []; - // Cancel button to both states - buttons.push({title: cancelButton, value: false}); - buttons1.push({title: cancelButton, value: false}); - // Share button - buttons.push({title: shareButton, value: true}); - // Back button - buttons1.push({title: backButton, value: true}); - var linkError = APP.translation.generateTranslationHTML( - "dialog.preziLinkError"); - var defaultUrl = APP.translation.translateString("defaultPreziLink", - {url: "http://prezi.com/wz7vhjycl7e6/my-prezi"}); - var openPreziState = { - state0: { - html: '

    ' + html + '

    ' + - '', - persistent: false, - buttons: buttons, - focus: ':input:first', - defaultButton: 0, - submit: function (e, v, m, f) { - e.preventDefault(); - if(v) - { - var preziUrl = f.preziUrl; - - if (preziUrl) - { - var urlValue - = encodeURI(UIUtil.escapeHtml(preziUrl)); - - if (urlValue.indexOf('http://prezi.com/') != 0 - && urlValue.indexOf('https://prezi.com/') != 0) - { - $.prompt.goToState('state1'); - return false; - } - else { - var presIdTmp = urlValue.substring( - urlValue.indexOf("prezi.com/") + 10); - if (!isAlphanumeric(presIdTmp) - || presIdTmp.indexOf('/') < 2) { - $.prompt.goToState('state1'); - return false; - } - else { - APP.xmpp.addToPresence("prezi", urlValue); - $.prompt.close(); - } - } - } - } - else - $.prompt.close(); - } - }, - state1: { - html: '

    ' + html + '

    ' + - linkError, - persistent: false, - buttons: buttons1, - focus: ':input:first', - defaultButton: 1, - submit: function (e, v, m, f) { - e.preventDefault(); - if (v === 0) - $.prompt.close(); - else - $.prompt.goToState('state0'); - } - } - }; - messageHandler.openDialogWithStates(openPreziState); - } - } - -}; - -/** - * A new presentation has been added. - * - * @param event the event indicating the add of a presentation - * @param jid the jid from which the presentation was added - * @param presUrl url of the presentation - * @param currentSlide the current slide to which we should move - */ -function presentationAdded(event, jid, presUrl, currentSlide) { - console.log("presentation added", presUrl); - - var presId = getPresentationId(presUrl); - - var elementId = 'participant_' - + Strophe.getResourceFromJid(jid) - + '_' + presId; - - VideoLayout.addPreziContainer(elementId); - - var controlsEnabled = false; - if (jid === APP.xmpp.myJid()) - controlsEnabled = true; - - setPresentationVisible(true); - VideoLayout.setLargeVideoHover( - function (event) { - if (Prezi.isPresentationVisible()) { - var reloadButtonRight = window.innerWidth - - $('#presentation>iframe').offset().left - - $('#presentation>iframe').width(); - - $('#reloadPresentation').css({ right: reloadButtonRight, - display:'inline-block'}); - } - }, - function (event) { - if (!Prezi.isPresentationVisible()) - $('#reloadPresentation').css({display:'none'}); - else { - var e = event.toElement || event.relatedTarget; - - if (e && e.id != 'reloadPresentation' && e.id != 'header') - $('#reloadPresentation').css({display:'none'}); - } - }); - - preziPlayer = new PreziPlayer( - 'presentation', - {preziId: presId, - width: getPresentationWidth(), - height: getPresentationHeihgt(), - controls: controlsEnabled, - debug: true - }); - - $('#presentation>iframe').attr('id', preziPlayer.options.preziId); - - preziPlayer.on(PreziPlayer.EVENT_STATUS, function(event) { - console.log("prezi status", event.value); - if (event.value == PreziPlayer.STATUS_CONTENT_READY) { - if (jid != APP.xmpp.myJid()) - preziPlayer.flyToStep(currentSlide); - } - }); - - preziPlayer.on(PreziPlayer.EVENT_CURRENT_STEP, function(event) { - console.log("event value", event.value); - APP.xmpp.addToPresence("preziSlide", event.value); - }); - - $("#" + elementId).css( 'background-image', - 'url(../images/avatarprezi.png)'); - $("#" + elementId).click( - function () { - setPresentationVisible(true); - } - ); -}; - -/** - * A presentation has been removed. - * - * @param event the event indicating the remove of a presentation - * @param jid the jid for which the presentation was removed - * @param the url of the presentation - */ -function presentationRemoved(event, jid, presUrl) { - console.log('presentation removed', presUrl); - var presId = getPresentationId(presUrl); - setPresentationVisible(false); - $('#participant_' - + Strophe.getResourceFromJid(jid) - + '_' + presId).remove(); - $('#presentation>iframe').remove(); - if (preziPlayer != null) { - preziPlayer.destroy(); - preziPlayer = null; - } -}; - -/** - * Indicates if the given string is an alphanumeric string. - * Note that some special characters are also allowed (-, _ , /, &, ?, =, ;) for the - * purpose of checking URIs. - */ -function isAlphanumeric(unsafeText) { - var regex = /^[a-z0-9-_\/&\?=;]+$/i; - return regex.test(unsafeText); -} - -/** - * Returns the presentation id from the given url. - */ -function getPresentationId (presUrl) { - var presIdTmp = presUrl.substring(presUrl.indexOf("prezi.com/") + 10); - return presIdTmp.substring(0, presIdTmp.indexOf('/')); -} - -/** - * Returns the presentation width. - */ -function getPresentationWidth() { - var availableWidth = UIUtil.getAvailableVideoWidth(); - var availableHeight = getPresentationHeihgt(); - - var aspectRatio = 16.0 / 9.0; - if (availableHeight < availableWidth / aspectRatio) { - availableWidth = Math.floor(availableHeight * aspectRatio); - } - return availableWidth; -} - -/** - * Returns the presentation height. - */ -function getPresentationHeihgt() { - var remoteVideos = $('#remoteVideos'); - return window.innerHeight - remoteVideos.outerHeight(); -} - -/** - * Resizes the presentation iframe. - */ -function resize() { - if ($('#presentation>iframe')) { - $('#presentation>iframe').width(getPresentationWidth()); - $('#presentation>iframe').height(getPresentationHeihgt()); - } -} - -/** - * Presentation has been removed. - */ -$(document).bind('presentationremoved.muc', presentationRemoved); - -/** - * Presentation has been added. - */ -$(document).bind('presentationadded.muc', presentationAdded); - -/* - * Indicates presentation slide change. - */ -$(document).bind('gotoslide.muc', function (event, jid, presUrl, current) { - if (preziPlayer && preziPlayer.getCurrentStep() != current) { - preziPlayer.flyToStep(current); - - var animationStepsArray = preziPlayer.getAnimationCountOnSteps(); - for (var i = 0; i < parseInt(animationStepsArray[current]); i++) { - preziPlayer.flyToStep(current, i); - } - } -}); - -$(window).resize(function () { - resize(); -}); - -module.exports = Prezi; - -},{"../toolbars/ToolbarToggler":31,"../util/MessageHandler":33,"../util/UIUtil":35,"../videolayout/VideoLayout":41,"./PreziPlayer":21}],21:[function(require,module,exports){ -(function() { - "use strict"; - var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - window.PreziPlayer = (function() { - - PreziPlayer.API_VERSION = 1; - PreziPlayer.CURRENT_STEP = 'currentStep'; - PreziPlayer.CURRENT_ANIMATION_STEP = 'currentAnimationStep'; - PreziPlayer.CURRENT_OBJECT = 'currentObject'; - PreziPlayer.STATUS_LOADING = 'loading'; - PreziPlayer.STATUS_READY = 'ready'; - PreziPlayer.STATUS_CONTENT_READY = 'contentready'; - PreziPlayer.EVENT_CURRENT_STEP = "currentStepChange"; - PreziPlayer.EVENT_CURRENT_ANIMATION_STEP = "currentAnimationStepChange"; - PreziPlayer.EVENT_CURRENT_OBJECT = "currentObjectChange"; - PreziPlayer.EVENT_STATUS = "statusChange"; - PreziPlayer.EVENT_PLAYING = "isAutoPlayingChange"; - PreziPlayer.EVENT_IS_MOVING = "isMovingChange"; - PreziPlayer.domain = "https://prezi.com"; - PreziPlayer.path = "/player/"; - PreziPlayer.players = {}; - PreziPlayer.binded_methods = ['changesHandler']; - - PreziPlayer.createMultiplePlayers = function(optionArray){ - for(var i=0; i 0 && - obj.values.animationCountOnSteps && - obj.values.animationCountOnSteps[step] <= animation_step) { - animation_step = obj.values.animationCountOnSteps[step]; - } - // jump to animation steps by calling flyToNextStep() - function doAnimationSteps() { - if (obj.values.isMoving == true) { - setTimeout(doAnimationSteps, 100); // wait until the flight ends - return; - } - while (animation_step-- > 0) { - obj.flyToNextStep(); // do the animation steps - } - } - setTimeout(doAnimationSteps, 200); // 200ms is the internal "reporting" time - // jump to the step - return this.sendMessage({ - 'action': 'present', - 'data': ['moveToStep', step] - }); - }; - - PreziPlayer.prototype.toObject = /* toObject is DEPRECATED */ - PreziPlayer.prototype.flyToObject = function(objectId) { - return this.sendMessage({ - 'action': 'present', - 'data': ['moveToObject', objectId] - }); - }; - - PreziPlayer.prototype.play = function(defaultDelay) { - return this.sendMessage({ - 'action': 'present', - 'data': ['startAutoPlay', defaultDelay] - }); - }; - - PreziPlayer.prototype.stop = function() { - return this.sendMessage({ - 'action': 'present', - 'data': ['stopAutoPlay'] - }); - }; - - PreziPlayer.prototype.pause = function(defaultDelay) { - return this.sendMessage({ - 'action': 'present', - 'data': ['pauseAutoPlay', defaultDelay] - }); - }; - - PreziPlayer.prototype.getCurrentStep = function() { - return this.values.currentStep; - }; - - PreziPlayer.prototype.getCurrentAnimationStep = function() { - return this.values.currentAnimationStep; - }; - - PreziPlayer.prototype.getCurrentObject = function() { - return this.values.currentObject; - }; - - PreziPlayer.prototype.getStatus = function() { - return this.values.status; - }; - - PreziPlayer.prototype.isPlaying = function() { - return this.values.isAutoPlaying; - }; - - PreziPlayer.prototype.getStepCount = function() { - return this.values.stepCount; - }; - - PreziPlayer.prototype.getAnimationCountOnSteps = function() { - return this.values.animationCountOnSteps; - }; - - PreziPlayer.prototype.getTitle = function() { - return this.values.title; - }; - - PreziPlayer.prototype.setDimensions = function(dims) { - for (var parameter in dims) { - this.iframe[parameter] = dims[parameter]; - } - } - - PreziPlayer.prototype.getDimensions = function() { - return { - width: parseInt(this.iframe.width, 10), - height: parseInt(this.iframe.height, 10) - } - } - - PreziPlayer.prototype.on = function(event, callback) { - this.callbacks.push({ - event: event, - callback: callback - }); - }; - - PreziPlayer.prototype.off = function(event, callback) { - var j, item; - if (event === undefined) { - this.callbacks = []; - } - j = this.callbacks.length; - while (j--) { - item = this.callbacks[j]; - if (item && item.event === event && (callback === undefined || item.callback === callback)){ - this.callbacks.splice(j, 1); - } - } - }; - - if (window.addEventListener) { - window.addEventListener('message', PreziPlayer.messageReceived, false); - } else { - window.attachEvent('onmessage', PreziPlayer.messageReceived); - } - - return PreziPlayer; - - })(); - -})(); - -module.exports = PreziPlayer; - -},{}],22:[function(require,module,exports){ -/* global require, $ */ -var Chat = require("./chat/Chat"); -var ContactList = require("./contactlist/ContactList"); -var Settings = require("./../../settings/Settings"); -var SettingsMenu = require("./settings/SettingsMenu"); -var VideoLayout = require("../videolayout/VideoLayout"); -var ToolbarToggler = require("../toolbars/ToolbarToggler"); -var UIUtil = require("../util/UIUtil"); -var LargeVideo = require("../videolayout/LargeVideo"); - -/** - * Toggler for the chat, contact list, settings menu, etc.. - */ -var PanelToggler = (function(my) { - - var currentlyOpen = null; - var buttons = { - '#chatspace': '#chatBottomButton', - '#contactlist': '#contactListButton', - '#settingsmenu': '#toolbar_button_settings' - }; - - /** - * Toggles the windows in the side panel - * @param object the window that should be shown - * @param selector the selector for the element containing the panel - * @param onOpenComplete function to be called when the panel is opened - * @param onOpen function to be called if the window is going to be opened - * @param onClose function to be called if the window is going to be closed - */ - var toggle = function(object, selector, onOpenComplete, onOpen, onClose) { - UIUtil.buttonClick(buttons[selector], "active"); - - if (object.isVisible()) { - $("#toast-container").animate({ - right: '5px' - }, - { - queue: false, - duration: 500 - }); - $(selector).hide("slide", { - direction: "right", - queue: false, - duration: 500 - }); - if(typeof onClose === "function") { - onClose(); - } - - currentlyOpen = null; - } - else { - // Undock the toolbar when the chat is shown and if we're in a - // video mode. - if (LargeVideo.isLargeVideoVisible()) { - ToolbarToggler.dockToolbar(false); - } - - if(currentlyOpen) { - var current = $(currentlyOpen); - UIUtil.buttonClick(buttons[currentlyOpen], "active"); - current.css('z-index', 4); - setTimeout(function () { - current.css('display', 'none'); - current.css('z-index', 5); - }, 500); - } - - $("#toast-container").animate({ - right: (PanelToggler.getPanelSize()[0] + 5) + 'px' - }, - { - queue: false, - duration: 500 - }); - $(selector).show("slide", { - direction: "right", - queue: false, - duration: 500, - complete: onOpenComplete - }); - if(typeof onOpen === "function") { - onOpen(); - } - - currentlyOpen = selector; - } - }; - - /** - * Opens / closes the chat area. - */ - my.toggleChat = function() { - var chatCompleteFunction = Chat.isVisible() ? - function() {} : function () { - Chat.scrollChatToBottom(); - $('#chatspace').trigger('shown'); - }; - - VideoLayout.resizeVideoArea(!Chat.isVisible(), chatCompleteFunction); - - toggle(Chat, - '#chatspace', - function () { - // Request the focus in the nickname field or the chat input field. - if ($('#nickname').css('visibility') === 'visible') { - $('#nickinput').focus(); - } else { - $('#usermsg').focus(); - } - }, - null, - Chat.resizeChat, - null); - }; - - /** - * Opens / closes the contact list area. - */ - my.toggleContactList = function () { - var completeFunction = ContactList.isVisible() ? - function() {} : function () { $('#contactlist').trigger('shown');}; - VideoLayout.resizeVideoArea(!ContactList.isVisible(), completeFunction); - - toggle(ContactList, - '#contactlist', - null, - function() { - ContactList.setVisualNotification(false); - }, - null); - }; - - /** - * Opens / closes the settings menu - */ - my.toggleSettingsMenu = function() { - VideoLayout.resizeVideoArea(!SettingsMenu.isVisible(), function (){}); - toggle(SettingsMenu, - '#settingsmenu', - null, - function() { - var settings = Settings.getSettings(); - $('#setDisplayName').get(0).value = settings.displayName; - $('#setEmail').get(0).value = settings.email; - }, - null); - }; - - /** - * Returns the size of the side panel. - */ - my.getPanelSize = function () { - var availableHeight = window.innerHeight; - var availableWidth = window.innerWidth; - - var panelWidth = 200; - if (availableWidth * 0.2 < 200) { - panelWidth = availableWidth * 0.2; - } - - return [panelWidth, availableHeight]; - }; - - my.isVisible = function() { - return (Chat.isVisible() || ContactList.isVisible() || SettingsMenu.isVisible()); - }; - - return my; - -}(PanelToggler || {})); - -module.exports = PanelToggler; -},{"../toolbars/ToolbarToggler":31,"../util/UIUtil":35,"../videolayout/LargeVideo":37,"../videolayout/VideoLayout":41,"./../../settings/Settings":49,"./chat/Chat":23,"./contactlist/ContactList":27,"./settings/SettingsMenu":28}],23:[function(require,module,exports){ -/* global APP, $, Util, nickname:true */ -var Replacement = require("./Replacement"); -var CommandsProcessor = require("./Commands"); -var ToolbarToggler = require("../../toolbars/ToolbarToggler"); -var smileys = require("./smileys.json").smileys; -var NicknameHandler = require("../../util/NicknameHandler"); -var UIUtil = require("../../util/UIUtil"); -var UIEvents = require("../../../../service/UI/UIEvents"); - -var notificationInterval = false; -var unreadMessages = 0; - - -/** - * Shows/hides a visual notification, indicating that a message has arrived. - */ -function setVisualNotification(show) { - var unreadMsgElement = document.getElementById('unreadMessages'); - var unreadMsgBottomElement - = document.getElementById('bottomUnreadMessages'); - - var glower = $('#toolbar_button_chat'); - var bottomGlower = $('#chatBottomButton'); - - if (unreadMessages) { - unreadMsgElement.innerHTML = unreadMessages.toString(); - unreadMsgBottomElement.innerHTML = unreadMessages.toString(); - - ToolbarToggler.dockToolbar(true); - - var chatButtonElement - = document.getElementById('toolbar_button_chat'); - var leftIndent = (UIUtil.getTextWidth(chatButtonElement) - - UIUtil.getTextWidth(unreadMsgElement)) / 2; - var topIndent = (UIUtil.getTextHeight(chatButtonElement) - - UIUtil.getTextHeight(unreadMsgElement)) / 2 - 3; - - unreadMsgElement.setAttribute( - 'style', - 'top:' + topIndent + - '; left:' + leftIndent + ';'); - - var chatBottomButtonElement - = document.getElementById('chatBottomButton').parentNode; - var bottomLeftIndent = (UIUtil.getTextWidth(chatBottomButtonElement) - - UIUtil.getTextWidth(unreadMsgBottomElement)) / 2; - var bottomTopIndent = (UIUtil.getTextHeight(chatBottomButtonElement) - - UIUtil.getTextHeight(unreadMsgBottomElement)) / 2 - 2; - - unreadMsgBottomElement.setAttribute( - 'style', - 'top:' + bottomTopIndent + - '; left:' + bottomLeftIndent + ';'); - - - if (!glower.hasClass('icon-chat-simple')) { - glower.removeClass('icon-chat'); - glower.addClass('icon-chat-simple'); - } - } - else { - unreadMsgElement.innerHTML = ''; - unreadMsgBottomElement.innerHTML = ''; - glower.removeClass('icon-chat-simple'); - glower.addClass('icon-chat'); - } - - if (show && !notificationInterval) { - notificationInterval = window.setInterval(function () { - glower.toggleClass('active'); - bottomGlower.toggleClass('active glowing'); - }, 800); - } - else if (!show && notificationInterval) { - window.clearInterval(notificationInterval); - notificationInterval = false; - glower.removeClass('active'); - bottomGlower.removeClass('glowing'); - bottomGlower.addClass('active'); - } -} - - -/** - * Returns the current time in the format it is shown to the user - * @returns {string} - */ -function getCurrentTime(stamp) { - var now = (stamp? new Date(stamp): new Date()); - var hour = now.getHours(); - var minute = now.getMinutes(); - var second = now.getSeconds(); - if(hour.toString().length === 1) { - hour = '0'+hour; - } - if(minute.toString().length === 1) { - minute = '0'+minute; - } - if(second.toString().length === 1) { - second = '0'+second; - } - return hour+':'+minute+':'+second; -} - -function toggleSmileys() { - var smileys = $('#smileysContainer'); - if(!smileys.is(':visible')) { - smileys.show("slide", { direction: "down", duration: 300}); - } else { - smileys.hide("slide", { direction: "down", duration: 300}); - } - $('#usermsg').focus(); -} - -function addClickFunction(smiley, number) { - smiley.onclick = function addSmileyToMessage() { - var usermsg = $('#usermsg'); - var message = usermsg.val(); - message += smileys['smiley' + number]; - usermsg.val(message); - usermsg.get(0).setSelectionRange(message.length, message.length); - toggleSmileys(); - usermsg.focus(); - }; -} - -/** - * Adds the smileys container to the chat - */ -function addSmileys() { - var smileysContainer = document.createElement('div'); - smileysContainer.id = 'smileysContainer'; - for(var i = 1; i <= 21; i++) { - var smileyContainer = document.createElement('div'); - smileyContainer.id = 'smiley' + i; - smileyContainer.className = 'smileyContainer'; - var smiley = document.createElement('img'); - smiley.src = 'images/smileys/smiley' + i + '.svg'; - smiley.className = 'smiley'; - addClickFunction(smiley, i); - smileyContainer.appendChild(smiley); - smileysContainer.appendChild(smileyContainer); - } - - $("#chatspace").append(smileysContainer); -} - -/** - * Resizes the chat conversation. - */ -function resizeChatConversation() { - var msgareaHeight = $('#usermsg').outerHeight(); - var chatspace = $('#chatspace'); - var width = chatspace.width(); - var chat = $('#chatconversation'); - var smileys = $('#smileysarea'); - - smileys.height(msgareaHeight); - $("#smileys").css('bottom', (msgareaHeight - 26) / 2); - $('#smileysContainer').css('bottom', msgareaHeight); - chat.width(width - 10); - chat.height(window.innerHeight - 15 - msgareaHeight); -} - -/** - * Chat related user interface. - */ -var Chat = (function (my) { - /** - * Initializes chat related interface. - */ - my.init = function () { - if(NicknameHandler.getNickname()) - Chat.setChatConversationMode(true); - NicknameHandler.addListener(UIEvents.NICKNAME_CHANGED, - function (nickname) { - Chat.setChatConversationMode(true); - }); - - $('#nickinput').keydown(function (event) { - if (event.keyCode === 13) { - event.preventDefault(); - var val = UIUtil.escapeHtml(this.value); - this.value = ''; - if (!NicknameHandler.getNickname()) { - NicknameHandler.setNickname(val); - - return; - } - } - }); - - var usermsg = $('#usermsg'); - usermsg.keydown(function (event) { - if (event.keyCode === 13) { - event.preventDefault(); - var value = this.value; - usermsg.val('').trigger('autosize.resize'); - this.focus(); - var command = new CommandsProcessor(value); - if(command.isCommand()) { - command.processCommand(); - } - else { - var message = UIUtil.escapeHtml(value); - APP.xmpp.sendChatMessage(message, NicknameHandler.getNickname()); - } - } - }); - - var onTextAreaResize = function () { - resizeChatConversation(); - Chat.scrollChatToBottom(); - }; - usermsg.autosize({callback: onTextAreaResize}); - - $("#chatspace").bind("shown", - function () { - unreadMessages = 0; - setVisualNotification(false); - }); - - addSmileys(); - }; - - /** - * Appends the given message to the chat conversation. - */ - my.updateChatConversation = - function (from, displayName, message, myjid, stamp) { - var divClassName = ''; - - if (APP.xmpp.myJid() === from) { - divClassName = "localuser"; - } - else { - divClassName = "remoteuser"; - - if (!Chat.isVisible()) { - unreadMessages++; - UIUtil.playSoundNotification('chatNotification'); - setVisualNotification(true); - } - } - - // replace links and smileys - // Strophe already escapes special symbols on sending, - // so we escape here only tags to avoid double & - var escMessage = message.replace(//g, '>').replace(/\n/g, '
    '); - var escDisplayName = UIUtil.escapeHtml(displayName); - message = Replacement.processReplacements(escMessage); - - var messageContainer = - '
    '+ - '' + - '
    ' + escDisplayName + - '
    ' + '
    ' + getCurrentTime(stamp) + - '
    ' + '
    ' + message + '
    ' + - '
    '; - - $('#chatconversation').append(messageContainer); - $('#chatconversation').animate( - { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000); - }; - - /** - * Appends error message to the conversation - * @param errorMessage the received error message. - * @param originalText the original message. - */ - my.chatAddError = function(errorMessage, originalText) { - errorMessage = UIUtil.escapeHtml(errorMessage); - originalText = UIUtil.escapeHtml(originalText); - - $('#chatconversation').append( - '
    Error: ' + 'Your message' + - (originalText? (' \"'+ originalText + '\"') : "") + - ' was not sent.' + - (errorMessage? (' Reason: ' + errorMessage) : '') + '
    '); - $('#chatconversation').animate( - { scrollTop: $('#chatconversation')[0].scrollHeight}, 1000); - }; - - /** - * Sets the subject to the UI - * @param subject the subject - */ - my.chatSetSubject = function(subject) { - if (subject) - subject = subject.trim(); - $('#subject').html(Replacement.linkify(UIUtil.escapeHtml(subject))); - if(subject === "") { - $("#subject").css({display: "none"}); - } - else { - $("#subject").css({display: "block"}); - } - }; - - /** - * Sets the chat conversation mode. - */ - my.setChatConversationMode = function (isConversationMode) { - if (isConversationMode) { - $('#nickname').css({visibility: 'hidden'}); - $('#chatconversation').css({visibility: 'visible'}); - $('#usermsg').css({visibility: 'visible'}); - $('#smileysarea').css({visibility: 'visible'}); - $('#usermsg').focus(); - } - }; - - /** - * Resizes the chat area. - */ - my.resizeChat = function () { - var chatSize = require("../SidePanelToggler").getPanelSize(); - - $('#chatspace').width(chatSize[0]); - $('#chatspace').height(chatSize[1]); - - resizeChatConversation(); - }; - - /** - * Indicates if the chat is currently visible. - */ - my.isVisible = function () { - return $('#chatspace').is(":visible"); - }; - /** - * Shows and hides the window with the smileys - */ - my.toggleSmileys = toggleSmileys; - - /** - * Scrolls chat to the bottom. - */ - my.scrollChatToBottom = function() { - setTimeout(function () { - $('#chatconversation').scrollTop( - $('#chatconversation')[0].scrollHeight); - }, 5); - }; - - - return my; -}(Chat || {})); -module.exports = Chat; -},{"../../../../service/UI/UIEvents":160,"../../toolbars/ToolbarToggler":31,"../../util/NicknameHandler":34,"../../util/UIUtil":35,"../SidePanelToggler":22,"./Commands":24,"./Replacement":25,"./smileys.json":26}],24:[function(require,module,exports){ -/* global APP, require */ -var UIUtil = require("../../util/UIUtil"); - -/** - * List with supported commands. The keys are the names of the commands and - * the value is the function that processes the message. - * @type {{String: function}} - */ -var commands = { - "topic" : processTopic -}; - -/** - * Extracts the command from the message. - * @param message the received message - * @returns {string} the command - */ -function getCommand(message) { - if(message) { - for(var command in commands) { - if(message.indexOf("/" + command) == 0) - return command; - } - } - return ""; -} - -/** - * Processes the data for topic command. - * @param commandArguments the arguments of the topic command. - */ -function processTopic(commandArguments) { - var topic = UIUtil.escapeHtml(commandArguments); - APP.xmpp.setSubject(topic); -} - -/** - * Constructs a new CommandProccessor instance from a message that - * handles commands received via chat messages. - * @param message the message - * @constructor - */ -function CommandsProcessor(message) { - var command = getCommand(message); - - /** - * Returns the name of the command. - * @returns {String} the command - */ - this.getCommand = function() { - return command; - }; - - - var messageArgument = message.substr(command.length + 2); - - /** - * Returns the arguments of the command. - * @returns {string} - */ - this.getArgument = function() { - return messageArgument; - }; -} - -/** - * Checks whether this instance is valid command or not. - * @returns {boolean} - */ -CommandsProcessor.prototype.isCommand = function() { - if (this.getCommand()) - return true; - return false; -}; - -/** - * Processes the command. - */ -CommandsProcessor.prototype.processCommand = function() { - if(!this.isCommand()) - return; - - commands[this.getCommand()](this.getArgument()); -}; - -module.exports = CommandsProcessor; -},{"../../util/UIUtil":35}],25:[function(require,module,exports){ -var Smileys = require("./smileys.json"); -/** - * Processes links and smileys in "body" - */ -function processReplacements(body) -{ - //make links clickable - body = linkify(body); - - //add smileys - body = smilify(body); - - return body; -} - -/** - * Finds and replaces all links in the links in "body" - * with their - */ -function linkify(inputText) -{ - var replacedText, replacePattern1, replacePattern2, replacePattern3; - - //URLs starting with http://, https://, or ftp:// - replacePattern1 = /(\b(https?|ftp):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim; - replacedText = inputText.replace(replacePattern1, '$1'); - - //URLs starting with "www." (without // before it, or it'd re-link the ones done above). - replacePattern2 = /(^|[^\/])(www\.[\S]+(\b|$))/gim; - replacedText = replacedText.replace(replacePattern2, '$1$2'); - - //Change email addresses to mailto:: links. - replacePattern3 = /(([a-zA-Z0-9\-\_\.])+@[a-zA-Z\_]+?(\.[a-zA-Z]{2,6})+)/gim; - replacedText = replacedText.replace(replacePattern3, '$1'); - - return replacedText; -} - -/** - * Replaces common smiley strings with images - */ -function smilify(body) -{ - if(!body) { - return body; - } - - var regexs = Smileys["regexs"]; - for(var smiley in regexs) { - if(regexs.hasOwnProperty(smiley)) { - body = body.replace(regexs[smiley], - ''); - } - } - - return body; -} - -module.exports = { - processReplacements: processReplacements, - linkify: linkify -}; - -},{"./smileys.json":26}],26:[function(require,module,exports){ -module.exports={ - "smileys": { - "smiley1": ":)", - "smiley2": ":(", - "smiley3": ":D", - "smiley4": "(y)", - "smiley5": " :P", - "smiley6": "(wave)", - "smiley7": "(blush)", - "smiley8": "(chuckle)", - "smiley9": "(shocked)", - "smiley10": ":*", - "smiley11": "(n)", - "smiley12": "(search)", - "smiley13": " <3", - "smiley14": "(oops)", - "smiley15": "(angry)", - "smiley16": "(angel)", - "smiley17": "(sick)", - "smiley18": ";(", - "smiley19": "(bomb)", - "smiley20": "(clap)", - "smiley21": " ;)" - }, - "regexs": { - "smiley2": /(:-\(\(|:-\(|:\(\(|:\(|\(sad\))/gi, - "smiley3": /(:-\)\)|:\)\)|\(lol\)|:-D|:D)/gi, - "smiley1": /(:-\)|:\))/gi, - "smiley4": /(\(y\)|\(Y\)|\(ok\))/gi, - "smiley5": /(:-P|:P|:-p|:p)/gi, - "smiley6": /(\(wave\))/gi, - "smiley7": /(\(blush\))/gi, - "smiley8": /(\(chuckle\))/gi, - "smiley9": /(:-0|\(shocked\))/gi, - "smiley10": /(:-\*|:\*|\(kiss\))/gi, - "smiley11": /(\(n\))/gi, - "smiley12": /(\(search\))/g, - "smiley13": /(<3|<3|&lt;3|\(L\)|\(l\)|\(H\)|\(h\))/gi, - "smiley14": /(\(oops\))/gi, - "smiley15": /(\(angry\))/gi, - "smiley16": /(\(angel\))/gi, - "smiley17": /(\(sick\))/gi, - "smiley18": /(;-\(\(|;\(\(|;-\(|;\(|:"\(|:"-\(|:~-\(|:~\(|\(upset\))/gi, - "smiley19": /(\(bomb\))/gi, - "smiley20": /(\(clap\))/gi, - "smiley21": /(;-\)|;\)|;-\)\)|;\)\)|;-D|;D|\(wink\))/gi - } -} - -},{}],27:[function(require,module,exports){ -/* global $, APP, Strophe */ -var Avatar = require('../../avatar/Avatar'); - -var numberOfContacts = 0; -var notificationInterval; - -/** - * Updates the number of participants in the contact list button and sets - * the glow - * @param delta indicates whether a new user has joined (1) or someone has - * left(-1) - */ -function updateNumberOfParticipants(delta) { - numberOfContacts += delta; - if (numberOfContacts === 1) { - // when the user is alone we don't show the number of participants - $("#numberOfParticipants").text(''); - ContactList.setVisualNotification(false); - } else if (numberOfContacts > 1) { - ContactList.setVisualNotification(!ContactList.isVisible()); - $("#numberOfParticipants").text(numberOfContacts); - } else { - console.error("Invalid number of participants: " + numberOfContacts); - } -} - -/** - * Creates the avatar element. - * - * @return {object} the newly created avatar element - */ -function createAvatar(jid) { - var avatar = document.createElement('img'); - avatar.className = "icon-avatar avatar"; - avatar.src = Avatar.getContactListUrl(jid); - - return avatar; -} - -/** - * Creates the display name paragraph. - * - * @param displayName the display name to set - */ -function createDisplayNameParagraph(key, displayName) { - var p = document.createElement('p'); - if(displayName) - p.innerText = displayName; - else if(key) { - p.setAttribute("data-i18n",key); - p.innerText = APP.translation.translateString(key); - } - - return p; -} - - -function stopGlowing(glower) { - window.clearInterval(notificationInterval); - notificationInterval = false; - glower.removeClass('glowing'); - if (!ContactList.isVisible()) { - glower.removeClass('active'); - } -} - -/** - * Contact list. - */ -var ContactList = { - /** - * Indicates if the chat is currently visible. - * - * @return true if the chat is currently visible, false - - * otherwise - */ - isVisible: function () { - return $('#contactlist').is(":visible"); - }, - - /** - * Adds a contact for the given peerJid if such doesn't yet exist. - * - * @param peerJid the peerJid corresponding to the contact - */ - ensureAddContact: function (peerJid) { - var resourceJid = Strophe.getResourceFromJid(peerJid); - - var contact = $('#contacts>li[id="' + resourceJid + '"]'); - - if (!contact || contact.length <= 0) - ContactList.addContact(peerJid); - }, - - /** - * Adds a contact for the given peer jid. - * - * @param peerJid the jid of the contact to add - */ - addContact: function (peerJid) { - var resourceJid = Strophe.getResourceFromJid(peerJid); - - var contactlist = $('#contacts'); - - var newContact = document.createElement('li'); - newContact.id = resourceJid; - newContact.className = "clickable"; - newContact.onclick = function (event) { - if (event.currentTarget.className === "clickable") { - $(ContactList).trigger('contactclicked', [peerJid]); - } - }; - - newContact.appendChild(createAvatar(peerJid)); - newContact.appendChild(createDisplayNameParagraph("participant")); - - if (resourceJid === APP.xmpp.myResource()) { - contactlist.prepend(newContact); - } - else { - contactlist.append(newContact); - } - updateNumberOfParticipants(1); - }, - - /** - * Removes a contact for the given peer jid. - * - * @param peerJid the peerJid corresponding to the contact to remove - */ - removeContact: function (peerJid) { - var resourceJid = Strophe.getResourceFromJid(peerJid); - - var contact = $('#contacts>li[id="' + resourceJid + '"]'); - - if (contact && contact.length > 0) { - var contactlist = $('#contactlist>ul'); - - contactlist.get(0).removeChild(contact.get(0)); - - updateNumberOfParticipants(-1); - } - }, - - setVisualNotification: function (show, stopGlowingIn) { - var glower = $('#contactListButton'); - - if (show && !notificationInterval) { - notificationInterval = window.setInterval(function () { - glower.toggleClass('active glowing'); - }, 800); - } - else if (!show && notificationInterval) { - stopGlowing(glower); - } - if (stopGlowingIn) { - setTimeout(function () { - stopGlowing(glower); - }, stopGlowingIn); - } - }, - - setClickable: function (resourceJid, isClickable) { - var contact = $('#contacts>li[id="' + resourceJid + '"]'); - if (isClickable) { - contact.addClass('clickable'); - } else { - contact.removeClass('clickable'); - } - }, - - onDisplayNameChange: function (peerJid, displayName) { - if (peerJid === 'localVideoContainer') - peerJid = APP.xmpp.myJid(); - - var resourceJid = Strophe.getResourceFromJid(peerJid); - - var contactName = $('#contacts #' + resourceJid + '>p'); - - if (contactName && displayName && displayName.length > 0) - contactName.html(displayName); - }, - - userAvatarChanged: function (resourceJid, contactListUrl) { - // set the avatar in the contact list - var contact = $('#' + resourceJid + '>img'); - if (contact && contact.length > 0) { - contact.get(0).src = contactListUrl; - } - - } -}; - -module.exports = ContactList; -},{"../../avatar/Avatar":18}],28:[function(require,module,exports){ -/* global APP, $ */ -var Avatar = require("../../avatar/Avatar"); -var Settings = require("./../../../settings/Settings"); -var UIUtil = require("../../util/UIUtil"); -var languages = require("../../../../service/translation/languages"); - -function generateLanguagesSelectBox() { - var currentLang = APP.translation.getCurrentLanguage(); - var html = ""; -} - - -var SettingsMenu = { - - init: function () { - var startMutedSelector = $("#startMutedOptions"); - startMutedSelector.before(generateLanguagesSelectBox()); - APP.translation.translateElement($("#languages_selectbox")); - $('#settingsmenu>input').keyup(function(event){ - if(event.keyCode === 13) {//enter - SettingsMenu.update(); - } - }); - - if (APP.xmpp.isModerator()) { - startMutedSelector.css("display", "block"); - } - else { - startMutedSelector.css("display", "none"); - } - - $("#updateSettings").click(function () { - SettingsMenu.update(); - }); - }, - - onRoleChanged: function () { - if(APP.xmpp.isModerator()) { - $("#startMutedOptions").css("display", "block"); - } - else { - $("#startMutedOptions").css("display", "none"); - } - }, - - setStartMuted: function (audio, video) { - $("#startAudioMuted").attr("checked", audio); - $("#startVideoMuted").attr("checked", video); - }, - - update: function() { - var newDisplayName = UIUtil.escapeHtml($('#setDisplayName').get(0).value); - var newEmail = UIUtil.escapeHtml($('#setEmail').get(0).value); - - if(newDisplayName) { - var displayName = Settings.setDisplayName(newDisplayName); - APP.xmpp.addToPresence("displayName", displayName, true); - } - - var language = $("#languages_selectbox").val(); - APP.translation.setLanguage(language); - Settings.setLanguage(language); - - APP.xmpp.addToPresence("email", newEmail); - var email = Settings.setEmail(newEmail); - - var startAudioMuted = ($("#startAudioMuted").is(":checked")); - var startVideoMuted = ($("#startVideoMuted").is(":checked")); - APP.xmpp.addToPresence("startMuted", - [startAudioMuted, startVideoMuted]); - - Avatar.setUserAvatar(APP.xmpp.myJid(), email); - }, - - isVisible: function() { - return $('#settingsmenu').is(':visible'); - }, - - setDisplayName: function(newDisplayName) { - var displayName = Settings.setDisplayName(newDisplayName); - $('#setDisplayName').get(0).value = displayName; - }, - - onDisplayNameChange: function(peerJid, newDisplayName) { - if(peerJid === 'localVideoContainer' || - peerJid === APP.xmpp.myJid()) { - this.setDisplayName(newDisplayName); - } - }, - changeAvatar: function (thumbUrl) { - $('#avatar').get(0).src = thumbUrl; - } -}; - - -module.exports = SettingsMenu; -},{"../../../../service/translation/languages":165,"../../avatar/Avatar":18,"../../util/UIUtil":35,"./../../../settings/Settings":49}],29:[function(require,module,exports){ -/* global $ */ -var PanelToggler = require("../side_pannels/SidePanelToggler"); - -var buttonHandlers = { - "bottom_toolbar_contact_list": function () { - BottomToolbar.toggleContactList(); - }, - "bottom_toolbar_film_strip": function () { - BottomToolbar.toggleFilmStrip(); - }, - "bottom_toolbar_chat": function () { - BottomToolbar.toggleChat(); - } -}; - -var BottomToolbar = (function (my) { - my.init = function () { - for(var k in buttonHandlers) - $("#" + k).click(buttonHandlers[k]); - }; - - my.toggleChat = function() { - PanelToggler.toggleChat(); - }; - - my.toggleContactList = function() { - PanelToggler.toggleContactList(); - }; - - my.toggleFilmStrip = function() { - var filmstrip = $("#remoteVideos"); - filmstrip.toggleClass("hidden"); - }; - - $(document).bind("remotevideo.resized", function (event, width, height) { - var bottom = (height - $('#bottomToolbar').outerHeight())/2 + 18; - - $('#bottomToolbar').css({bottom: bottom + 'px'}); - }); - - return my; -}(BottomToolbar || {})); - -module.exports = BottomToolbar; - -},{"../side_pannels/SidePanelToggler":22}],30:[function(require,module,exports){ -/* global APP, $, buttonClick, config, lockRoom, interfaceConfig, setSharedKey, - Util */ -var messageHandler = require("../util/MessageHandler"); -var BottomToolbar = require("./BottomToolbar"); -var Prezi = require("../prezi/Prezi"); -var Etherpad = require("../etherpad/Etherpad"); -var PanelToggler = require("../side_pannels/SidePanelToggler"); -var Authentication = require("../authentication/Authentication"); -var UIUtil = require("../util/UIUtil"); -var AuthenticationEvents - = require("../../../service/authentication/AuthenticationEvents"); - -var roomUrl = null; -var sharedKey = ''; -var UI = null; -var recordingToaster = null; - -var buttonHandlers = { - "toolbar_button_mute": function () { - return APP.UI.toggleAudio(); - }, - "toolbar_button_camera": function () { - return APP.UI.toggleVideo(); - }, - /*"toolbar_button_authentication": function () { - return Toolbar.authenticateClicked(); - },*/ - "toolbar_button_record": function () { - return toggleRecording(); - }, - "toolbar_button_security": function () { - return Toolbar.openLockDialog(); - }, - "toolbar_button_link": function () { - return Toolbar.openLinkDialog(); - }, - "toolbar_button_chat": function () { - return BottomToolbar.toggleChat(); - }, - "toolbar_button_prezi": function () { - return Prezi.openPreziDialog(); - }, - "toolbar_button_etherpad": function () { - return Etherpad.toggleEtherpad(0); - }, - "toolbar_button_desktopsharing": function () { - return APP.desktopsharing.toggleScreenSharing(); - }, - "toolbar_button_fullScreen": function() { - UIUtil.buttonClick("#toolbar_button_fullScreen", "icon-full-screen icon-exit-full-screen"); - return Toolbar.toggleFullScreen(); - }, - "toolbar_button_sip": function () { - return callSipButtonClicked(); - }, - "toolbar_button_dialpad": function () { - return dialpadButtonClicked(); - }, - "toolbar_button_settings": function () { - PanelToggler.toggleSettingsMenu(); - }, - "toolbar_button_hangup": function () { - return hangup(); - }, - "toolbar_button_login": function () { - Toolbar.authenticateClicked(); - }, - "toolbar_button_logout": function () { - // Ask for confirmation - messageHandler.openTwoButtonDialog( - "dialog.logoutTitle", - null, - "dialog.logoutQuestion", - null, - false, - "dialog.Yes", - function (evt, yes) { - if (yes) { - APP.xmpp.logout(function (url) { - if (url) { - window.location.href = url; - } else { - hangup(); - } - }); - } - }); - } -}; - -function hangup() { - APP.xmpp.disposeConference(); - if(config.enableWelcomePage) { - setTimeout(function() { - window.localStorage.welcomePageDisabled = false; - window.location.pathname = "/"; - }, 10000); - - } - - var title = APP.translation.generateTranslationHTML( - "dialog.sessTerminated"); - var msg = APP.translation.generateTranslationHTML( - "dialog.hungUp"); - var button = APP.translation.generateTranslationHTML( - "dialog.joinAgain"); - var buttons = []; - buttons.push({title: button, value: true}); - - UI.messageHandler.openDialog( - title, - msg, - true, - buttons, - function(event, value, message, formVals) { - window.location.reload(); - return false; - } - ); -} - -/** - * Starts or stops the recording for the conference. - */ - -function toggleRecording(predefinedToken) { - APP.xmpp.toggleRecording(function (callback) { - if (predefinedToken) { - callback(UIUtil.escapeHtml(predefinedToken)); - return; - } - - var msg = APP.translation.generateTranslationHTML( - "dialog.recordingToken"); - var token = APP.translation.translateString("dialog.token"); - APP.UI.messageHandler.openTwoButtonDialog(null, null, null, - '

    ' + msg + '

    ' + - '', - false, - "dialog.Save", - function (e, v, m, f) { - if (v) { - var token = f.recordingToken; - - if (token) { - callback(UIUtil.escapeHtml(token)); - } - } - }, - null, - function () { }, - ':input:first' - ); - }, Toolbar.setRecordingButtonState); -} - -/** - * Locks / unlocks the room. - */ -function lockRoom(lock) { - var currentSharedKey = ''; - if (lock) - currentSharedKey = sharedKey; - - APP.xmpp.lockRoom(currentSharedKey, function (res) { - // password is required - if (sharedKey) { - console.log('set room password'); - Toolbar.lockLockButton(); - } - else { - console.log('removed room password'); - Toolbar.unlockLockButton(); - } - }, function (err) { - console.warn('setting password failed', err); - messageHandler.showError("dialog.lockTitle", - "dialog.lockMessage"); - Toolbar.setSharedKey(''); - }, function () { - console.warn('room passwords not supported'); - messageHandler.showError("dialog.warning", - "dialog.passwordNotSupported"); - Toolbar.setSharedKey(''); - }); -} - -/** - * Invite participants to conference. - */ -function inviteParticipants() { - if (roomUrl === null) - return; - - var sharedKeyText = ""; - if (sharedKey && sharedKey.length > 0) { - sharedKeyText = - APP.translation.translateString("email.sharedKey", - {sharedKey: sharedKey}); - sharedKeyText = sharedKeyText.replace(/\n/g, "%0D%0A"); - } - - var supportedBrowsers = "Chromium, Google Chrome " + - APP.translation.translateString("email.and") + " Opera"; - var conferenceName = roomUrl.substring(roomUrl.lastIndexOf('/') + 1); - var subject = APP.translation.translateString("email.subject", - {appName:interfaceConfig.APP_NAME, conferenceName: conferenceName}); - var body = APP.translation.translateString("email.body", - {appName:interfaceConfig.APP_NAME, sharedKeyText: sharedKeyText, - roomUrl: roomUrl, supportedBrowsers: supportedBrowsers}); - body = body.replace(/\n/g, "%0D%0A"); - - if (window.localStorage.displayname) { - body += "%0D%0A%0D%0A" + window.localStorage.displayname; - } - - if (interfaceConfig.INVITATION_POWERED_BY) { - body += "%0D%0A%0D%0A--%0D%0Apowered by jitsi.org"; - } - - window.open("mailto:?subject=" + subject + "&body=" + body, '_blank'); -} - -function dialpadButtonClicked() { - //TODO show the dialpad box -} - -function callSipButtonClicked() { - var defaultNumber - = config.defaultSipNumber ? config.defaultSipNumber : ''; - - var sipMsg = APP.translation.generateTranslationHTML( - "dialog.sipMsg"); - messageHandler.openTwoButtonDialog(null, null, null, - '

    ' + sipMsg + '

    ' + - '', - false, - "dialog.Dial", - function (e, v, m, f) { - if (v) { - var numberInput = f.sipNumber; - if (numberInput) { - APP.xmpp.dial( - numberInput, 'fromnumber', UI.getRoomName(), sharedKey); - } - } - }, - null, null, ':input:first' - ); -} - -var Toolbar = (function (my) { - - my.init = function (ui) { - for(var k in buttonHandlers) - $("#" + k).click(buttonHandlers[k]); - UI = ui; - // Update login info - APP.xmpp.addListener( - AuthenticationEvents.IDENTITY_UPDATED, - function (authenticationEnabled, userIdentity) { - - var loggedIn = false; - if (userIdentity) { - loggedIn = true; - } - - Toolbar.showAuthenticateButton(authenticationEnabled); - - if (authenticationEnabled) { - Toolbar.setAuthenticatedIdentity(userIdentity); - - Toolbar.showLoginButton(!loggedIn); - Toolbar.showLogoutButton(loggedIn); - } - } - ); - }; - - /** - * Sets shared key - * @param sKey the shared key - */ - my.setSharedKey = function (sKey) { - sharedKey = sKey; - }; - - my.authenticateClicked = function () { - Authentication.focusAuthenticationWindow(); - if (!APP.xmpp.isExternalAuthEnabled()) { - Authentication.xmppAuthenticate(); - return; - } - // Get authentication URL - if (!APP.xmpp.isMUCJoined()) { - APP.xmpp.getLoginUrl(UI.getRoomName(), function (url) { - // If conference has not been started yet - redirect to login page - window.location.href = url; - }); - } else { - APP.xmpp.getPopupLoginUrl(UI.getRoomName(), function (url) { - // Otherwise - open popup with authentication URL - var authenticationWindow = Authentication.createAuthenticationWindow( - function () { - // On popup closed - retry room allocation - APP.xmpp.allocateConferenceFocus( - APP.UI.getRoomName(), - function () { console.info("AUTH DONE"); } - ); - }, url); - if (!authenticationWindow) { - messageHandler.openMessageDialog( - null, "dialog.popupError"); - } - }); - } - }; - - /** - * Updates the room invite url. - */ - my.updateRoomUrl = function (newRoomUrl) { - roomUrl = newRoomUrl; - - // If the invite dialog has been already opened we update the information. - var inviteLink = document.getElementById('inviteLinkRef'); - if (inviteLink) { - inviteLink.value = roomUrl; - inviteLink.select(); - $('#inviteLinkRef').parent() - .find('button[value=true]').prop('disabled', false); - } - }; - - /** - * Disables and enables some of the buttons. - */ - my.setupButtonsFromConfig = function () { - if (config.disablePrezi) { - $("#toolbar_button_prezi").css({display: "none"}); - } - }; - - /** - * Opens the lock room dialog. - */ - my.openLockDialog = function () { - // Only the focus is able to set a shared key. - if (!APP.xmpp.isModerator()) { - if (sharedKey) { - messageHandler.openMessageDialog(null, - "dialog.passwordError"); - } else { - messageHandler.openMessageDialog(null, "dialog.passwordError2"); - } - } else { - if (sharedKey) { - messageHandler.openTwoButtonDialog(null, null, - "dialog.passwordCheck", - null, - false, - "dialog.Remove", - function (e, v) { - if (v) { - Toolbar.setSharedKey(''); - lockRoom(false); - } - }); - } else { - var msg = APP.translation.generateTranslationHTML( - "dialog.passwordMsg"); - var yourPassword = APP.translation.translateString( - "dialog.yourPassword"); - messageHandler.openTwoButtonDialog(null, null, null, - '

    ' + msg + '

    ' + - '', - false, - "dialog.Save", - function (e, v, m, f) { - if (v) { - var lockKey = f.lockKey; - - if (lockKey) { - Toolbar.setSharedKey( - UIUtil.escapeHtml(lockKey)); - lockRoom(true); - } - } - }, - null, null, 'input:first' - ); - } - } - }; - - /** - * Opens the invite link dialog. - */ - my.openLinkDialog = function () { - var inviteAttreibutes; - - if (roomUrl === null) { - inviteAttreibutes = 'data-i18n="[value]roomUrlDefaultMsg" value="' + - APP.translation.translateString("roomUrlDefaultMsg") + '"'; - } else { - inviteAttreibutes = "value=\"" + encodeURI(roomUrl) + "\""; - } - messageHandler.openTwoButtonDialog("dialog.shareLink", - null, null, - '', - false, - "dialog.Invite", - function (e, v) { - if (v) { - if (roomUrl) { - inviteParticipants(); - } - } - }, - function (event) { - if (roomUrl) { - document.getElementById('inviteLinkRef').select(); - } else { - if (event && event.target) - $(event.target) - .find('button[value=true]').prop('disabled', true); - } - } - ); - }; - - /** - * Opens the settings dialog. - * FIXME: not used ? - */ - my.openSettingsDialog = function () { - var settings1 = APP.translation.generateTranslationHTML( - "dialog.settings1"); - var settings2 = APP.translation.generateTranslationHTML( - "dialog.settings2"); - var settings3 = APP.translation.generateTranslationHTML( - "dialog.settings3"); - - var yourPassword = APP.translation.translateString( - "dialog.yourPassword"); - - messageHandler.openTwoButtonDialog(null, - '

    ' + settings1 + '

    ' + - '' + - settings2 + '
    ' + - '' + - settings3 + - '', - null, - null, - false, - "dialog.Save", - function () { - document.getElementById('lockKey').focus(); - }, - function (e, v) { - if (v) { - if ($('#initMuted').is(":checked")) { - // it is checked - } - - if ($('#requireNicknames').is(":checked")) { - // it is checked - } - /* - var lockKey = document.getElementById('lockKey'); - - if (lockKey.value) { - setSharedKey(lockKey.value); - lockRoom(true); - } - */ - } - } - ); - }; - - /** - * Toggles the application in and out of full screen mode - * (a.k.a. presentation mode in Chrome). - */ - my.toggleFullScreen = function () { - var fsElement = document.documentElement; - - if (!document.mozFullScreen && !document.webkitIsFullScreen) { - //Enter Full Screen - if (fsElement.mozRequestFullScreen) { - fsElement.mozRequestFullScreen(); - } - else { - fsElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); - } - } else { - //Exit Full Screen - if (document.mozCancelFullScreen) { - document.mozCancelFullScreen(); - } else { - document.webkitCancelFullScreen(); - } - } - }; - /** - * Unlocks the lock button state. - */ - my.unlockLockButton = function () { - if ($("#toolbar_button_security").hasClass("icon-security-locked")) - UIUtil.buttonClick("#toolbar_button_security", "icon-security icon-security-locked"); - }; - /** - * Updates the lock button state to locked. - */ - my.lockLockButton = function () { - if ($("#toolbar_button_security").hasClass("icon-security")) - UIUtil.buttonClick("#toolbar_button_security", "icon-security icon-security-locked"); - }; - - /** - * Shows or hides authentication button - * @param show true to show or false to hide - */ - my.showAuthenticateButton = function (show) { - if (show) { - $('#authentication').css({display: "inline"}); - } - else { - $('#authentication').css({display: "none"}); - } - }; - - // Shows or hides the 'recording' button. - my.showRecordingButton = function (show) { - if (!config.enableRecording) { - return; - } - - if (show) { - $('#toolbar_button_record').css({display: "inline-block"}); - } - else { - $('#toolbar_button_record').css({display: "none"}); - } - }; - - // Sets the state of the recording button - my.setRecordingButtonState = function (recordingState) { - var selector = $('#toolbar_button_record'); - - if (recordingState === 'on') { - selector.removeClass("icon-recEnable"); - selector.addClass("icon-recEnable active"); - - $("#largeVideo").toggleClass("videoMessageFilter", true); - var recordOnKey = "recording.on"; - $('#videoConnectionMessage').attr("data-i18n", recordOnKey); - $('#videoConnectionMessage').text(APP.translation.translateString(recordOnKey)); - - setTimeout(function(){ - $("#largeVideo").toggleClass("videoMessageFilter", false); - $('#videoConnectionMessage').css({display: "none"}); - }, 1500); - - recordingToaster = messageHandler.notify(null, "recording.toaster", null, - null, null, {timeOut: 0, closeButton: null, tapToDismiss: false}); - } else if (recordingState === 'off') { - selector.removeClass("icon-recEnable active"); - selector.addClass("icon-recEnable"); - - $("#largeVideo").toggleClass("videoMessageFilter", false); - $('#videoConnectionMessage').css({display: "none"}); - - if (recordingToaster) - messageHandler.remove(recordingToaster); - - } else if (recordingState === 'pending') { - selector.removeClass("icon-recEnable active"); - selector.addClass("icon-recEnable"); - - $("#largeVideo").toggleClass("videoMessageFilter", true); - var recordPendingKey = "recording.pending"; - $('#videoConnectionMessage').attr("data-i18n", recordPendingKey); - $('#videoConnectionMessage').text(APP.translation.translateString(recordPendingKey)); - $('#videoConnectionMessage').css({display: "block"}); - } - }; - - // checks whether recording is enabled and whether we have params to start automatically recording - my.checkAutoRecord = function () { - if (config.enableRecording && config.autoRecord) { - toggleRecording(config.autoRecordToken); - } - } - - // Shows or hides SIP calls button - my.showSipCallButton = function (show) { - if (APP.xmpp.isSipGatewayEnabled() && show) { - $('#toolbar_button_sip').css({display: "inline-block"}); - } else { - $('#toolbar_button_sip').css({display: "none"}); - } - }; - - // Shows or hides the dialpad button - my.showDialPadButton = function (show) { - if (show) { - $('#toolbar_button_dialpad').css({display: "inline-block"}); - } else { - $('#toolbar_button_dialpad').css({display: "none"}); - } - }; - - /** - * Displays user authenticated identity name(login). - * @param authIdentity identity name to be displayed. - */ - my.setAuthenticatedIdentity = function (authIdentity) { - if (authIdentity) { - var selector = $('#toolbar_auth_identity'); - selector.css({display: "list-item"}); - selector.text(authIdentity); - } else { - $('#toolbar_auth_identity').css({display: "none"}); - } - }; - - /** - * Shows/hides login button. - * @param show true to show - */ - my.showLoginButton = function (show) { - if (show) { - $('#toolbar_button_login').css({display: "list-item"}); - } else { - $('#toolbar_button_login').css({display: "none"}); - } - }; - - /** - * Shows/hides logout button. - * @param show true to show - */ - my.showLogoutButton = function (show) { - if (show) { - $('#toolbar_button_logout').css({display: "list-item"}); - } else { - $('#toolbar_button_logout').css({display: "none"}); - } - }; - - /** - * Sets the state of the button. The button has blue glow if desktop - * streaming is active. - * @param active the state of the desktop streaming. - */ - my.changeDesktopSharingButtonState = function (active) { - var button = $("#toolbar_button_desktopsharing"); - if (active) { - button.addClass("glow"); - } else { - button.removeClass("glow"); - } - }; - - return my; -}(Toolbar || {})); - -module.exports = Toolbar; -},{"../../../service/authentication/AuthenticationEvents":161,"../authentication/Authentication":16,"../etherpad/Etherpad":19,"../prezi/Prezi":20,"../side_pannels/SidePanelToggler":22,"../util/MessageHandler":33,"../util/UIUtil":35,"./BottomToolbar":29}],31:[function(require,module,exports){ -/* global APP, config, $, interfaceConfig, Moderator, - DesktopStreaming.showDesktopSharingButton */ - -var toolbarTimeoutObject, - toolbarTimeout = interfaceConfig.INITIAL_TOOLBAR_TIMEOUT; - -function showDesktopSharingButton() { - if (APP.desktopsharing.isDesktopSharingEnabled()) { - $('#toolbar_button_desktopsharing').css({display: "inline-block"}); - } else { - $('#toolbar_button_desktopsharing').css({display: "none"}); - } -} - -/** - * Hides the toolbar. - */ -function hideToolbar() { - if(config.alwaysVisibleToolbar) - return; - - var header = $("#header"), - bottomToolbar = $("#bottomToolbar"); - var isToolbarHover = false; - header.find('*').each(function () { - var id = $(this).attr('id'); - if ($("#" + id + ":hover").length > 0) { - isToolbarHover = true; - } - }); - if ($("#bottomToolbar:hover").length > 0) { - isToolbarHover = true; - } - - clearTimeout(toolbarTimeoutObject); - toolbarTimeoutObject = null; - - if (!isToolbarHover) { - header.hide("slide", { direction: "up", duration: 300}); - $('#subject').animate({top: "-=40"}, 300); - if ($("#remoteVideos").hasClass("hidden")) { - bottomToolbar.hide( - "slide", {direction: "right", duration: 300}); - } - } - else { - toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout); - } -} - -var ToolbarToggler = { - /** - * Shows the main toolbar. - */ - showToolbar: function () { - if (interfaceConfig.filmStripOnly) - return; - var header = $("#header"), - bottomToolbar = $("#bottomToolbar"); - if (!header.is(':visible') || !bottomToolbar.is(":visible")) { - header.show("slide", { direction: "up", duration: 300}); - $('#subject').animate({top: "+=40"}, 300); - if (!bottomToolbar.is(":visible")) { - bottomToolbar.show( - "slide", {direction: "right", duration: 300}); - } - - if (toolbarTimeoutObject) { - clearTimeout(toolbarTimeoutObject); - toolbarTimeoutObject = null; - } - toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout); - toolbarTimeout = interfaceConfig.TOOLBAR_TIMEOUT; - } - - if (APP.xmpp.isModerator()) - { -// TODO: Enable settings functionality. -// Need to uncomment the settings button in index.html. -// $('#settingsButton').css({visibility:"visible"}); - } - - // Show/hide desktop sharing button - showDesktopSharingButton(); - }, - - /** - * Docks/undocks the toolbar. - * - * @param isDock indicates what operation to perform - */ - dockToolbar: function (isDock) { - if (interfaceConfig.filmStripOnly) - return; - - if (isDock) { - // First make sure the toolbar is shown. - if (!$('#header').is(':visible')) { - this.showToolbar(); - } - - // Then clear the time out, to dock the toolbar. - if (toolbarTimeoutObject) { - clearTimeout(toolbarTimeoutObject); - toolbarTimeoutObject = null; - } - } - else { - if (!$('#header').is(':visible')) { - this.showToolbar(); - } - else { - toolbarTimeoutObject = setTimeout(hideToolbar, toolbarTimeout); - } - } - }, - - showDesktopSharingButton: showDesktopSharingButton -}; - -module.exports = ToolbarToggler; -},{}],32:[function(require,module,exports){ -/* global $ */ -var JitsiPopover = (function () { - /** - * Constructs new JitsiPopover and attaches it to the element - * @param element jquery selector - * @param options the options for the popover. - * @constructor - */ - function JitsiPopover(element, options) - { - this.options = { - skin: "white", - content: "" - }; - if(options) - { - if(options.skin) - this.options.skin = options.skin; - - if(options.content) - this.options.content = options.content; - } - - this.elementIsHovered = false; - this.popoverIsHovered = false; - this.popoverShown = false; - - element.data("jitsi_popover", this); - this.element = element; - this.template = '
    ' + - '
    '; - var self = this; - this.element.on("mouseenter", function () { - self.elementIsHovered = true; - self.show(); - }).on("mouseleave", function () { - self.elementIsHovered = false; - setTimeout(function () { - self.hide(); - }, 10); - }); - } - - /** - * Shows the popover - */ - JitsiPopover.prototype.show = function () { - if(!JitsiPopover.enabled) - return; - this.createPopover(); - this.popoverShown = true; - }; - - /** - * Hides the popover - */ - JitsiPopover.prototype.hide = function () { - if(!this.elementIsHovered && !this.popoverIsHovered && - this.popoverShown) { - this.forceHide(); - } - }; - - /** - * Hides the popover. - */ - JitsiPopover.prototype.forceHide = function () { - $(".jitsipopover").remove(); - this.popoverShown = false; - }; - - /** - * Creates the popover html. - */ - JitsiPopover.prototype.createPopover = function () { - $("body").append(this.template); - $(".jitsipopover > .jitsipopover-content").html(this.options.content); - var self = this; - $(".jitsipopover").on("mouseenter", function () { - self.popoverIsHovered = true; - }).on("mouseleave", function () { - self.popoverIsHovered = false; - self.hide(); - }); - - this.refreshPosition(); - }; - - /** - * Refreshes the position of the popover. - */ - JitsiPopover.prototype.refreshPosition = function () { - $(".jitsipopover").position({ - my: "bottom", - at: "top", - collision: "fit", - of: this.element, - using: function (position, elements) { - var calcLeft = elements.target.left - elements.element.left + - elements.target.width/2; - $(".jitsipopover").css( - {top: position.top, left: position.left, display: "table"}); - $(".jitsipopover > .arrow").css({left: calcLeft}); - $(".jitsipopover > .jitsiPopupmenuPadding").css( - {left: calcLeft - 50}); - } - }); - }; - - /** - * Updates the content of popover. - * @param content new content - */ - JitsiPopover.prototype.updateContent = function (content) { - this.options.content = content; - if(!this.popoverShown) - return; - $(".jitsipopover").remove(); - this.createPopover(); - }; - - JitsiPopover.enabled = true; - - return JitsiPopover; -})(); - -module.exports = JitsiPopover; -},{}],33:[function(require,module,exports){ -/* global $, APP, jQuery, toastr */ - -/** - * Flag for enable/disable of the notifications. - * @type {boolean} - */ -var notificationsEnabled = true; - -var messageHandler = (function(my) { - - /** - * Shows a message to the user. - * - * @param titleKey the title of the message - * @param messageKey the text of the message - */ - my.openMessageDialog = function(titleKey, messageKey) { - var title = null; - if(titleKey) { - title = APP.translation.generateTranslationHTML(titleKey); - } - var message = APP.translation.generateTranslationHTML(messageKey); - $.prompt(message, - {title: title, persistent: false} - ); - }; - - /** - * Shows a message to the user with two buttons: first is given as a - * parameter and the second is Cancel. - * - * @param titleString the title of the message - * @param msgString the text of the message - * @param persistent boolean value which determines whether the message is - * persistent or not - * @param leftButton the fist button's text - * @param submitFunction function to be called on submit - * @param loadedFunction function to be called after the prompt is fully - * loaded - * @param closeFunction function to be called after the prompt is closed - * @param focus optional focus selector or button index to be focused after - * the dialog is opened - * @param defaultButton index of default button which will be activated when - * the user press 'enter'. Indexed from 0. - */ - my.openTwoButtonDialog = function(titleKey, titleString, msgKey, msgString, - persistent, leftButtonKey, submitFunction, loadedFunction, - closeFunction, focus, defaultButton) { - var buttons = []; - - var leftButton = APP.translation.generateTranslationHTML(leftButtonKey); - buttons.push({ title: leftButton, value: true}); - - var cancelButton - = APP.translation.generateTranslationHTML("dialog.Cancel"); - buttons.push({title: cancelButton, value: false}); - - var message = msgString, title = titleString; - if (titleKey) { - title = APP.translation.generateTranslationHTML(titleKey); - } - if (msgKey) { - message = APP.translation.generateTranslationHTML(msgKey); - } - $.prompt(message, { - title: title, - persistent: false, - buttons: buttons, - defaultButton: defaultButton, - focus: focus, - loaded: loadedFunction, - submit: submitFunction, - close: closeFunction - }); - }; - - /** - * Shows a message to the user with two buttons: first is given as a parameter and the second is Cancel. - * - * @param titleString the title of the message - * @param msgString the text of the message - * @param persistent boolean value which determines whether the message is - * persistent or not - * @param buttons object with the buttons. The keys must be the name of the - * button and value is the value that will be passed to - * submitFunction - * @param submitFunction function to be called on submit - * @param loadedFunction function to be called after the prompt is fully - * loaded - */ - my.openDialog = function (titleString, msgString, persistent, buttons, - submitFunction, loadedFunction) { - var args = { - title: titleString, - persistent: persistent, - buttons: buttons, - defaultButton: 1, - loaded: loadedFunction, - submit: submitFunction - }; - if (persistent) { - args.closeText = ''; - } - return new Impromptu(msgString, args); - }; - - /** - * Closes currently opened dialog. - */ - my.closeDialog = function () { - $.prompt.close(); - }; - - /** - * Shows a dialog with different states to the user. - * - * @param statesObject object containing all the states of the dialog. - */ - my.openDialogWithStates = function (statesObject, options) { - return new Impromptu(statesObject, options); - }; - - /** - * Opens new popup window for given url centered over current - * window. - * - * @param url the URL to be displayed in the popup window - * @param w the width of the popup window - * @param h the height of the popup window - * @param onPopupClosed optional callback function called when popup window - * has been closed. - * - * @returns {object} popup window object if opened successfully or undefined - * in case we failed to open it(popup blocked) - */ - my.openCenteredPopup = function (url, w, h, onPopupClosed) { - var l = window.screenX + (window.innerWidth / 2) - (w / 2); - var t = window.screenY + (window.innerHeight / 2) - (h / 2); - var popup = window.open( - url, '_blank', - 'top=' + t + ', left=' + l + ', width=' + w + ', height=' + h + ''); - if (popup && onPopupClosed) { - var pollTimer = window.setInterval(function () { - if (popup.closed !== false) { - window.clearInterval(pollTimer); - onPopupClosed(); - } - }, 200); - } - return popup; - }; - - /** - * Shows a dialog prompting the user to send an error report. - * - * @param titleKey the title of the message - * @param msgKey the text of the message - * @param error the error that is being reported - */ - my.openReportDialog = function(titleKey, msgKey, error) { - my.openMessageDialog(titleKey, msgKey); - console.log(error); - //FIXME send the error to the server - }; - - /** - * Shows an error dialog to the user. - * @param titleKey the title of the message. - * @param msgKey the text of the message. - */ - my.showError = function(titleKey, msgKey) { - - if (!titleKey) { - titleKey = "dialog.oops"; - } - if (!msgKey) { - msgKey = "dialog.defaultError"; - } - messageHandler.openMessageDialog(titleKey, msgKey); - }; - - /** - * Displayes notification. - * @param displayName display name of the participant that is associated with the notification. - * @param displayNameKey the key from the language file for the display name. - * @param cls css class for the notification - * @param messageKey the key from the language file for the text of the message. - * @param messageArguments object with the arguments for the message. - * @param options object with language options. - */ - my.notify = function(displayName, displayNameKey, - cls, messageKey, messageArguments, options) { - if(!notificationsEnabled) - return; - var displayNameSpan = '" + APP.translation.translateString(displayNameKey); - } - displayNameSpan += ""; - return toastr.info( - displayNameSpan + '
    ' + - '" + - APP.translation.translateString(messageKey, - messageArguments) + - '', null, options); - }; - - /** - * Removes the toaster. - * @param toasterElement - */ - my.remove = function(toasterElement) { - toasterElement.remove(); - }; - - /** - * Disables notifications. - */ - my.disableNotifications = function () { - notificationsEnabled = false; - }; - - /** - * Enables notifications. - */ - my.enableNotifications = function () { - notificationsEnabled = true; - }; - - return my; -}(messageHandler || {})); - -module.exports = messageHandler; - - - -},{}],34:[function(require,module,exports){ -var UIEvents = require("../../../service/UI/UIEvents"); - -var nickname = null; -var eventEmitter = null; - -var NicknameHandler = { - init: function (emitter) { - eventEmitter = emitter; - var storedDisplayName = window.localStorage.displayname; - if (storedDisplayName) { - nickname = storedDisplayName; - } - }, - setNickname: function (newNickname) { - if (!newNickname || nickname === newNickname) - return; - - nickname = newNickname; - window.localStorage.displayname = nickname; - eventEmitter.emit(UIEvents.NICKNAME_CHANGED, newNickname); - }, - getNickname: function () { - return nickname; - }, - addListener: function (type, listener) { - eventEmitter.on(type, listener); - } -}; - -module.exports = NicknameHandler; -},{"../../../service/UI/UIEvents":160}],35:[function(require,module,exports){ -/* global $ */ -/** - * Created by hristo on 12/22/14. - */ -module.exports = { - /** - * Returns the available video width. - */ - getAvailableVideoWidth: function (isVisible) { - var PanelToggler = require("../side_pannels/SidePanelToggler"); - if(typeof isVisible === "undefined" || isVisible === null) - isVisible = PanelToggler.isVisible(); - var rightPanelWidth - = isVisible ? PanelToggler.getPanelSize()[0] : 0; - - return window.innerWidth - rightPanelWidth; - }, - /** - * Changes the style class of the element given by id. - */ - buttonClick: function(id, classname) { - $(id).toggleClass(classname); // add the class to the clicked element - }, - /** - * Returns the text width for the given element. - * - * @param el the element - */ - getTextWidth: function (el) { - return (el.clientWidth + 1); - }, - - /** - * Returns the text height for the given element. - * - * @param el the element - */ - getTextHeight: function (el) { - return (el.clientHeight + 1); - }, - - /** - * Plays the sound given by id. - * - * @param id the identifier of the audio element. - */ - playSoundNotification: function (id) { - document.getElementById(id).play(); - }, - - /** - * Escapes the given text. - */ - escapeHtml: function (unsafeText) { - return $('
    ').text(unsafeText).html(); - }, - - imageToGrayScale: function (canvas) { - var context = canvas.getContext('2d'); - var imgData = context.getImageData(0, 0, canvas.width, canvas.height); - var pixels = imgData.data; - - for (var i = 0, n = pixels.length; i < n; i += 4) { - var grayscale - = pixels[i] * 0.3 + pixels[i+1] * 0.59 + pixels[i+2] * 0.11; - pixels[i ] = grayscale; // red - pixels[i+1] = grayscale; // green - pixels[i+2] = grayscale; // blue - // pixels[i+3] is alpha - } - // redraw the image in black & white - context.putImageData(imgData, 0, 0); - }, - - setTooltip: function (element, key, position) { - element.setAttribute("data-i18n", "[data-content]" + key); - element.setAttribute("data-toggle", "popover"); - element.setAttribute("data-placement", position); - element.setAttribute("data-html", true); - element.setAttribute("data-container", "body"); - }, - - /** - * Inserts given child element as the first one into the container. - * @param container the container to which new child element will be added - * @param newChild the new element that will be inserted into the container - */ - prependChild: function (container, newChild) { - var firstChild = container.childNodes[0]; - if (firstChild) { - container.insertBefore(newChild, firstChild); - } else { - container.appendChild(newChild); - } - } -}; -},{"../side_pannels/SidePanelToggler":22}],36:[function(require,module,exports){ -/* global APP, $ */ -var JitsiPopover = require("../util/JitsiPopover"); - -/** - * Constructs new connection indicator. - * @param videoContainer the video container associated with the indicator. - * @constructor - */ -function ConnectionIndicator(videoContainer, jid) { - this.videoContainer = videoContainer; - this.bandwidth = null; - this.packetLoss = null; - this.bitrate = null; - this.showMoreValue = false; - this.resolution = null; - this.transport = []; - this.popover = null; - this.jid = jid; - this.create(); -} - -/** - * Values for the connection quality - * @type {{98: string, - * 81: string, - * 64: string, - * 47: string, - * 30: string, - * 0: string}} - */ -ConnectionIndicator.connectionQualityValues = { - 98: "18px", //full - 81: "15px",//4 bars - 64: "11px",//3 bars - 47: "7px",//2 bars - 30: "3px",//1 bar - 0: "0px"//empty -}; - -ConnectionIndicator.getIP = function(value) { - return value.substring(0, value.lastIndexOf(":")); -}; - -ConnectionIndicator.getPort = function(value) { - return value.substring(value.lastIndexOf(":") + 1, value.length); -}; - -ConnectionIndicator.getStringFromArray = function (array) { - var res = ""; - for(var i = 0; i < array.length; i++) { - res += (i === 0? "" : ", ") + array[i]; - } - return res; -}; - -/** - * Generates the html content. - * @returns {string} the html content. - */ -ConnectionIndicator.prototype.generateText = function () { - var downloadBitrate, uploadBitrate, packetLoss, resolution, i; - - var translate = APP.translation.translateString; - - if(this.bitrate === null) { - downloadBitrate = "N/A"; - uploadBitrate = "N/A"; - } - else { - downloadBitrate = - this.bitrate.download? this.bitrate.download + " Kbps" : "N/A"; - uploadBitrate = - this.bitrate.upload? this.bitrate.upload + " Kbps" : "N/A"; - } - - if(this.packetLoss === null) { - packetLoss = "N/A"; - } else { - - packetLoss = "" + - (this.packetLoss.download !== null ? - this.packetLoss.download : "N/A") + - "% " + - (this.packetLoss.upload !== null? this.packetLoss.upload : "N/A") + - "%"; - } - - var resolutionValue = null; - if(this.resolution && this.jid != null) { - var keys = Object.keys(this.resolution); - for(var ssrc in this.resolution) { - resolutionValue = this.resolution[ssrc]; - } - } - - if(this.jid === null) { - resolution = ""; - if(this.resolution === null || !Object.keys(this.resolution) || - Object.keys(this.resolution).length === 0) { - resolution = "N/A"; - } else { - for (i in this.resolution) { - resolutionValue = this.resolution[i]; - if (resolutionValue) { - if (resolutionValue.height && - resolutionValue.width) { - resolution += (resolution === "" ? "" : ", ") + - resolutionValue.width + "x" + - resolutionValue.height; - } - } - } - } - } else if(!resolutionValue || - !resolutionValue.height || - !resolutionValue.width) { - resolution = "N/A"; - } else { - resolution = resolutionValue.width + "x" + resolutionValue.height; - } - - var result = "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "
    " + - translate("connectionindicator.bitrate") + "" + - downloadBitrate + " " + - uploadBitrate + "
    " + - translate("connectionindicator.packetloss") + "" + packetLoss + "
    " + - translate("connectionindicator.resolution") + "" + resolution + "
    "; - - if(this.videoContainer.videoSpanId == "localVideoContainer") { - result += "
    " + - translate("connectionindicator." + (this.showMoreValue ? "less" : "more")) + - "

    "; - } - - if (this.showMoreValue) { - var downloadBandwidth, uploadBandwidth, transport; - if (this.bandwidth === null) { - downloadBandwidth = "N/A"; - uploadBandwidth = "N/A"; - } else { - downloadBandwidth = this.bandwidth.download? - this.bandwidth.download + " Kbps" : - "N/A"; - uploadBandwidth = this.bandwidth.upload? - this.bandwidth.upload + " Kbps" : - "N/A"; - } - - if (!this.transport || this.transport.length === 0) { - transport = "" + - "" + - translate("connectionindicator.address") + "" + - " N/A"; - } else { - var data = {remoteIP: [], localIP:[], remotePort:[], localPort:[]}; - for(i = 0; i < this.transport.length; i++) { - var ip = ConnectionIndicator.getIP(this.transport[i].ip); - var port = ConnectionIndicator.getPort(this.transport[i].ip); - var localIP = - ConnectionIndicator.getIP(this.transport[i].localip); - var localPort = - ConnectionIndicator.getPort(this.transport[i].localip); - if(data.remoteIP.indexOf(ip) == -1) { - data.remoteIP.push(ip); - } - - if(data.remotePort.indexOf(port) == -1) { - data.remotePort.push(port); - } - - if(data.localIP.indexOf(localIP) == -1) { - data.localIP.push(localIP); - } - - if(data.localPort.indexOf(localPort) == -1) { - data.localPort.push(localPort); - } - } - - var local_address_key = "connectionindicator.localaddress"; - var remote_address_key = "connectionindicator.remoteaddress"; - var localTransport = - "" + - translate(local_address_key, {count: data.localIP.length}) + - " " + - ConnectionIndicator.getStringFromArray(data.localIP) + - ""; - transport = - "" + - translate(remote_address_key, - {count: data.remoteIP.length}) + - " " + - ConnectionIndicator.getStringFromArray(data.remoteIP) + - ""; - - var key_remote = "connectionindicator.remoteport", - key_local = "connectionindicator.localport"; - - transport += "" + - "" + - "" + - translate(key_remote, {count: this.transport.length}) + - ""; - localTransport += "" + - "" + - "" + - translate(key_local, {count: this.transport.length}) + - ""; - - transport += - ConnectionIndicator.getStringFromArray(data.remotePort); - localTransport += - ConnectionIndicator.getStringFromArray(data.localPort); - transport += ""; - transport += localTransport + ""; - transport +="" + - "" + - translate("connectionindicator.transport") + "" + - "" + this.transport[0].type + ""; - - } - - result += "" + - "" + - ""; - - result += transport + "
    " + - "" + - translate("connectionindicator.bandwidth") + "" + - "" + - "" + - downloadBandwidth + - " " + - uploadBandwidth + "
    "; - } - - return result; -}; - -/** - * Shows or hide the additional information. - */ -ConnectionIndicator.prototype.showMore = function () { - this.showMoreValue = !this.showMoreValue; - this.updatePopoverData(); -}; - - -function createIcon(classes) { - var icon = document.createElement("span"); - for(var i in classes) { - icon.classList.add(classes[i]); - } - icon.appendChild( - document.createElement("i")).classList.add("icon-connection"); - return icon; -} - -/** - * Creates the indicator - */ -ConnectionIndicator.prototype.create = function () { - this.connectionIndicatorContainer = document.createElement("div"); - this.connectionIndicatorContainer.className = "connectionindicator"; - this.connectionIndicatorContainer.style.display = "none"; - this.videoContainer.container.appendChild( - this.connectionIndicatorContainer); - this.popover = new JitsiPopover( - $("#" + this.videoContainer.videoSpanId + " > .connectionindicator"), - {content: "
    " + - APP.translation.translateString("connectionindicator.na") + "
    ", - skin: "black"}); - - this.emptyIcon = this.connectionIndicatorContainer.appendChild( - createIcon(["connection", "connection_empty"])); - this.fullIcon = this.connectionIndicatorContainer.appendChild( - createIcon(["connection", "connection_full"])); -}; - -/** - * Removes the indicator - */ -ConnectionIndicator.prototype.remove = function() { - if (this.connectionIndicatorContainer.parentNode) { - this.connectionIndicatorContainer.parentNode.removeChild( - this.connectionIndicatorContainer); - } - this.popover.forceHide(); -}; - -/** - * Updates the data of the indicator - * @param percent the percent of connection quality - * @param object the statistics data. - */ -ConnectionIndicator.prototype.updateConnectionQuality = - function (percent, object) { - - if (percent === null) { - this.connectionIndicatorContainer.style.display = "none"; - this.popover.forceHide(); - return; - } else { - if(this.connectionIndicatorContainer.style.display == "none") { - this.connectionIndicatorContainer.style.display = "block"; - this.videoContainer.updateIconPositions(); - } - } - this.bandwidth = object.bandwidth; - this.bitrate = object.bitrate; - this.packetLoss = object.packetLoss; - this.transport = object.transport; - if (object.resolution) { - this.resolution = object.resolution; - } - for (var quality in ConnectionIndicator.connectionQualityValues) { - if (percent >= quality) { - this.fullIcon.style.width = - ConnectionIndicator.connectionQualityValues[quality]; - } - } - this.updatePopoverData(); -}; - -/** - * Updates the resolution - * @param resolution the new resolution - */ -ConnectionIndicator.prototype.updateResolution = function (resolution) { - this.resolution = resolution; - this.updatePopoverData(); -}; - -/** - * Updates the content of the popover - */ -ConnectionIndicator.prototype.updatePopoverData = function () { - this.popover.updateContent( - "
    " + this.generateText() + "
    "); - APP.translation.translateElement($(".connection_info")); -}; - -/** - * Hides the popover - */ -ConnectionIndicator.prototype.hide = function () { - this.popover.forceHide(); -}; - -/** - * Hides the indicator - */ -ConnectionIndicator.prototype.hideIndicator = function () { - this.connectionIndicatorContainer.style.display = "none"; - if(this.popover) - this.popover.forceHide(); -}; - -module.exports = ConnectionIndicator; -},{"../util/JitsiPopover":32}],37:[function(require,module,exports){ -/* global $, APP, Strophe, interfaceConfig */ -var Avatar = require("../avatar/Avatar"); -var RTCBrowserType = require("../../RTC/RTCBrowserType"); -var UIUtil = require("../util/UIUtil"); -var UIEvents = require("../../../service/UI/UIEvents"); -var xmpp = require("../../xmpp/xmpp"); -var ToolbarToggler = require("../toolbars/ToolbarToggler"); - -// FIXME: With Temasys we have to re-select everytime -//var video = $('#largeVideo'); - -var currentVideoWidth = null; -var currentVideoHeight = null; -// By default we use camera -var getVideoSize = getCameraVideoSize; -var getVideoPosition = getCameraVideoPosition; -/** - * The small video instance that is displayed in the large video - * @type {SmallVideo} - */ -var currentSmallVideo = null; -/** - * Indicates whether the large video is enabled. - * @type {boolean} - */ -var isEnabled = true; -/** - * Current large video state. - * Possible values - video, prezi or etherpad. - * @type {string} - */ -var state = "video"; - -/** - * Returns the html element associated with the passed state of large video - * @param state the state. - * @returns {JQuery|*|jQuery|HTMLElement} the container. - */ -function getContainerByState(state) -{ - var selector = null; - switch (state) - { - case "video": - selector = "#largeVideo"; - break; - case "etherpad": - selector = "#etherpad>iframe"; - break; - case "prezi": - selector = "#presentation>iframe"; - break; - } - return (selector !== null)? $(selector) : null; -} - -/** - * Sets the size and position of the given video element. - * - * @param video the video element to position - * @param width the desired video width - * @param height the desired video height - * @param horizontalIndent the left and right indent - * @param verticalIndent the top and bottom indent - */ -function positionVideo(video, - width, - height, - horizontalIndent, - verticalIndent, - animate) { - if (animate) { - video.animate({ - width: width, - height: height, - top: verticalIndent, - bottom: verticalIndent, - left: horizontalIndent, - right: horizontalIndent - }, - { - queue: false, - duration: 500 - }); - } else { - video.width(width); - video.height(height); - video.css({ top: verticalIndent + 'px', - bottom: verticalIndent + 'px', - left: horizontalIndent + 'px', - right: horizontalIndent + 'px'}); - } - -} - -/** - * Returns an array of the video dimensions, so that it keeps it's aspect - * ratio and fits available area with it's larger dimension. This method - * ensures that whole video will be visible and can leave empty areas. - * - * @return an array with 2 elements, the video width and the video height - */ -function getDesktopVideoSize(videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight) { - if (!videoWidth) - videoWidth = currentVideoWidth; - if (!videoHeight) - videoHeight = currentVideoHeight; - - var aspectRatio = videoWidth / videoHeight; - - var availableWidth = Math.max(videoWidth, videoSpaceWidth); - var availableHeight = Math.max(videoHeight, videoSpaceHeight); - - videoSpaceHeight -= $('#remoteVideos').outerHeight(); - - if (availableWidth / aspectRatio >= videoSpaceHeight) - { - availableHeight = videoSpaceHeight; - availableWidth = availableHeight * aspectRatio; - } - - if (availableHeight * aspectRatio >= videoSpaceWidth) - { - availableWidth = videoSpaceWidth; - availableHeight = availableWidth / aspectRatio; - } - - return [availableWidth, availableHeight]; -} - - -/** - * Returns an array of the video horizontal and vertical indents, - * so that if fits its parent. - * - * @return an array with 2 elements, the horizontal indent and the vertical - * indent - */ -function getCameraVideoPosition(videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight) { - // Parent height isn't completely calculated when we position the video in - // full screen mode and this is why we use the screen height in this case. - // Need to think it further at some point and implement it properly. - var isFullScreen = document.fullScreen || - document.mozFullScreen || - document.webkitIsFullScreen; - if (isFullScreen) - videoSpaceHeight = window.innerHeight; - - var horizontalIndent = (videoSpaceWidth - videoWidth) / 2; - var verticalIndent = (videoSpaceHeight - videoHeight) / 2; - - return [horizontalIndent, verticalIndent]; -} - -/** - * Returns an array of the video horizontal and vertical indents. - * Centers horizontally and top aligns vertically. - * - * @return an array with 2 elements, the horizontal indent and the vertical - * indent - */ -function getDesktopVideoPosition(videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight) { - - var horizontalIndent = (videoSpaceWidth - videoWidth) / 2; - - var verticalIndent = 0;// Top aligned - - return [horizontalIndent, verticalIndent]; -} - - -/** - * Returns an array of the video dimensions, so that it covers the screen. - * It leaves no empty areas, but some parts of the video might not be visible. - * - * @return an array with 2 elements, the video width and the video height - */ -function getCameraVideoSize(videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight) { - if (!videoWidth) - videoWidth = currentVideoWidth; - if (!videoHeight) - videoHeight = currentVideoHeight; - - var aspectRatio = videoWidth / videoHeight; - - var availableWidth = Math.max(videoWidth, videoSpaceWidth); - var availableHeight = Math.max(videoHeight, videoSpaceHeight); - - if (availableWidth / aspectRatio < videoSpaceHeight) { - availableHeight = videoSpaceHeight; - availableWidth = availableHeight * aspectRatio; - } - - if (availableHeight * aspectRatio < videoSpaceWidth) { - availableWidth = videoSpaceWidth; - availableHeight = availableWidth / aspectRatio; - } - - return [availableWidth, availableHeight]; -} - -/** - * Updates the src of the active speaker avatar - * @param jid of the current active speaker - */ -function updateActiveSpeakerAvatarSrc() { - var avatar = $("#activeSpeakerAvatar")[0]; - var jid = currentSmallVideo.peerJid; - var url = Avatar.getActiveSpeakerUrl(jid); - if (avatar.src === url) - return; - if (jid) { - avatar.src = url; - currentSmallVideo.showAvatar(); - } -} - -/** - * Change the video source of the large video. - * @param isVisible - */ -function changeVideo(isVisible) { - - if (!currentSmallVideo) { - console.error("Unable to change large video - no 'currentSmallVideo'"); - return; - } - - updateActiveSpeakerAvatarSrc(); - - APP.RTC.setVideoSrc($('#largeVideo')[0], currentSmallVideo.getSrc()); - - var videoTransform = document.getElementById('largeVideo') - .style.webkitTransform; - - var flipX = currentSmallVideo.flipX; - - if (flipX && videoTransform !== 'scaleX(-1)') { - document.getElementById('largeVideo').style.webkitTransform = - "scaleX(-1)"; - } else if (!flipX && videoTransform === 'scaleX(-1)') { - document.getElementById('largeVideo').style.webkitTransform = - "none"; - } - - var isDesktop = currentSmallVideo.getVideoType() === 'screen'; - // Change the way we'll be measuring and positioning large video - - getVideoSize = isDesktop ? getDesktopVideoSize : getCameraVideoSize; - getVideoPosition = isDesktop ? getDesktopVideoPosition : - getCameraVideoPosition; - - - // Only if the large video is currently visible. - if (isVisible) { - LargeVideo.VideoLayout.largeVideoUpdated(currentSmallVideo); - - $('#largeVideo').fadeIn(300); - } -} - -/** - * Creates the html elements for the large video. - */ -function createLargeVideoHTML() -{ - var html = '
    '; - html += '
    ' + - '
    ' + - '
    ' + - '
    ' + - '' + - ' jitsi.org' + - ''+ - '
    ' + - '' + - '' + - '
    ' + - '' + - ''; - html += '
    '; - $(html).prependTo("#videospace"); - - if (interfaceConfig.SHOW_JITSI_WATERMARK) { - var leftWatermarkDiv - = $("#largeVideoContainer div[class='watermark leftwatermark']"); - - leftWatermarkDiv.css({display: 'block'}); - leftWatermarkDiv.parent().get(0).href - = interfaceConfig.JITSI_WATERMARK_LINK; - } - - if (interfaceConfig.SHOW_BRAND_WATERMARK) { - var rightWatermarkDiv - = $("#largeVideoContainer div[class='watermark rightwatermark']"); - - rightWatermarkDiv.css({display: 'block'}); - rightWatermarkDiv.parent().get(0).href - = interfaceConfig.BRAND_WATERMARK_LINK; - rightWatermarkDiv.get(0).style.backgroundImage - = "url(images/rightwatermark.png)"; - } - - if (interfaceConfig.SHOW_POWERED_BY) { - $("#largeVideoContainer>a[class='poweredby']").css({display: 'block'}); - } - - if (!RTCBrowserType.isIExplorer()) { - $('#largeVideo').volume = 0; - } -} - -var LargeVideo = { - - init: function (VideoLayout, emitter) { - if(!isEnabled) - return; - createLargeVideoHTML(); - - this.VideoLayout = VideoLayout; - this.eventEmitter = emitter; - this.eventEmitter.emit(UIEvents.LARGEVIDEO_INIT); - var self = this; - // Listen for large video size updates - var largeVideo = $('#largeVideo')[0]; - var onplaying = function (arg1, arg2, arg3) { - // re-select - if (RTCBrowserType.isTemasysPluginUsed()) - largeVideo = $('#largeVideo')[0]; - currentVideoWidth = largeVideo.videoWidth; - currentVideoHeight = largeVideo.videoHeight; - self.position(currentVideoWidth, currentVideoHeight); - }; - largeVideo.onplaying = onplaying; - }, - /** - * Indicates if the large video is currently visible. - * - * @return true if visible, false - otherwise - */ - isLargeVideoVisible: function() { - return $('#largeVideo').is(':visible'); - }, - /** - * Returns true if the user is currently displayed on large video. - */ - isCurrentlyOnLarge: function (resourceJid) { - return currentSmallVideo && resourceJid && - currentSmallVideo.getResourceJid() === resourceJid; - }, - /** - * Updates the large video with the given new video source. - */ - updateLargeVideo: function (resourceJid, forceUpdate) { - if(!isEnabled) - return; - var newSmallVideo = this.VideoLayout.getSmallVideo(resourceJid); - console.log('hover in ' + resourceJid + ', video: ', newSmallVideo); - - if (!LargeVideo.isCurrentlyOnLarge(resourceJid) || forceUpdate) { - $('#activeSpeaker').css('visibility', 'hidden'); - - var oldSmallVideo = null; - if (currentSmallVideo) { - oldSmallVideo = currentSmallVideo; - } - currentSmallVideo = newSmallVideo; - - var oldJid = null; - if (oldSmallVideo) - oldJid = oldSmallVideo.peerJid; - if (oldJid !== resourceJid) { - // we want the notification to trigger even if userJid is undefined, - // or null. - this.eventEmitter.emit(UIEvents.SELECTED_ENDPOINT, resourceJid); - } - if (RTCBrowserType.isSafari()) { - // FIXME In Safari fadeOut works only for the first time - changeVideo(this.isLargeVideoVisible()); - } else { - $('#largeVideo').fadeOut(300, - changeVideo.bind($('#largeVideo'), this.isLargeVideoVisible())); - } - } else { - if (currentSmallVideo) { - currentSmallVideo.showAvatar(); - } - } - - }, - - /** - * Shows/hides the large video. - */ - setLargeVideoVisible: function(isVisible) { - if(!isEnabled) - return; - if (isVisible) { - $('#largeVideo').css({visibility: 'visible'}); - $('.watermark').css({visibility: 'visible'}); - if(currentSmallVideo) - currentSmallVideo.enableDominantSpeaker(true); - } - else { - $('#largeVideo').css({visibility: 'hidden'}); - $('#activeSpeaker').css('visibility', 'hidden'); - $('.watermark').css({visibility: 'hidden'}); - if(currentSmallVideo) - currentSmallVideo.enableDominantSpeaker(false); - } - }, - onVideoTypeChanged: function (resourceJid, newVideoType) { - if (!isEnabled) - return; - if (LargeVideo.isCurrentlyOnLarge(resourceJid)) - { - var isDesktop = newVideoType === 'screen'; - getVideoSize = isDesktop ? getDesktopVideoSize : getCameraVideoSize; - getVideoPosition = isDesktop ? getDesktopVideoPosition - : getCameraVideoPosition; - this.position(null, null); - } - }, - /** - * Positions the large video. - * - * @param videoWidth the stream video width - * @param videoHeight the stream video height - */ - position: function (videoWidth, videoHeight, - videoSpaceWidth, videoSpaceHeight, animate) { - if(!isEnabled) - return; - if(!videoSpaceWidth) - videoSpaceWidth = $('#videospace').width(); - if(!videoSpaceHeight) - videoSpaceHeight = window.innerHeight; - - var videoSize = getVideoSize(videoWidth, - videoHeight, - videoSpaceWidth, - videoSpaceHeight); - - var largeVideoWidth = videoSize[0]; - var largeVideoHeight = videoSize[1]; - - var videoPosition = getVideoPosition(largeVideoWidth, - largeVideoHeight, - videoSpaceWidth, - videoSpaceHeight); - - var horizontalIndent = videoPosition[0]; - var verticalIndent = videoPosition[1]; - - positionVideo($('#largeVideo'), - largeVideoWidth, - largeVideoHeight, - horizontalIndent, verticalIndent, animate); - }, - /** - * Resizes the large html elements. - * @param animate boolean property that indicates whether the resize should be animated or not. - * @param isChatVisible boolean property that indicates whether the chat area is displayed or not. - * If that parameter is null the method will check the chat pannel visibility. - * @param completeFunction a function to be called when the video space is resized - * @returns {*[]} array with the current width and height values of the largeVideo html element. - */ - resize: function (animate, isVisible, completeFunction) { - if(!isEnabled) - return; - var availableHeight = window.innerHeight; - var availableWidth = UIUtil.getAvailableVideoWidth(isVisible); - - if (availableWidth < 0 || availableHeight < 0) return; - - var avatarSize = interfaceConfig.ACTIVE_SPEAKER_AVATAR_SIZE; - var top = availableHeight / 2 - avatarSize / 4 * 3; - $('#activeSpeaker').css('top', top); - - this.VideoLayout.resizeVideoSpace(animate, isVisible, completeFunction); - if(animate) { - $('#largeVideoContainer').animate({ - width: availableWidth, - height: availableHeight - }, - { - queue: false, - duration: 500 - }); - } else { - $('#largeVideoContainer').width(availableWidth); - $('#largeVideoContainer').height(availableHeight); - } - return [availableWidth, availableHeight]; - }, - resizeVideoAreaAnimated: function (isVisible, completeFunction) { - if(!isEnabled) - return; - var size = this.resize(true, isVisible, completeFunction); - this.position(null, null, size[0], size[1], true); - }, - getResourceJid: function () { - return currentSmallVideo ? currentSmallVideo.getResourceJid() : null; - }, - updateAvatar: function (resourceJid) { - if(!isEnabled) - return; - if (resourceJid === this.getResourceJid()) { - updateActiveSpeakerAvatarSrc(); - } - }, - showAvatar: function (resourceJid, show) { - if(!isEnabled) - return; - if(this.getResourceJid() === resourceJid && state === "video") { - $("#largeVideo").css("visibility", show ? "hidden" : "visible"); - $('#activeSpeaker').css("visibility", show ? "visible" : "hidden"); - return true; - } - return false; - }, - /** - * Disables the large video - */ - disable: function () { - isEnabled = false; - }, - /** - * Enables the large video - */ - enable: function () { - isEnabled = true; - }, - /** - * Returns true if the video is enabled. - */ - isEnabled: function () { - return isEnabled; - }, - /** - * Creates the iframe used by the etherpad - * @param src the value for src attribute - * @param onloadHandler handler executed when the iframe loads it content - * @returns {HTMLElement} the iframe - */ - createEtherpadIframe: function (src, onloadHandler) { - if(!isEnabled) - return; - - var etherpadIFrame = document.createElement('iframe'); - etherpadIFrame.src = src; - etherpadIFrame.frameBorder = 0; - etherpadIFrame.scrolling = "no"; - etherpadIFrame.width = $('#largeVideoContainer').width() || 640; - etherpadIFrame.height = $('#largeVideoContainer').height() || 480; - etherpadIFrame.setAttribute('style', 'visibility: hidden;'); - - document.getElementById('etherpad').appendChild(etherpadIFrame); - - etherpadIFrame.onload = onloadHandler; - - return etherpadIFrame; - }, - /** - * Changes the state of the large video. - * Possible values - video, prezi, etherpad. - * @param newState - the new state - */ - setState: function (newState) { - if(state === newState) - return; - var currentContainer = getContainerByState(state); - if(!currentContainer) - return; - - var self = this; - var oldState = state; - - switch (newState) - { - case "etherpad": - $('#activeSpeaker').css('visibility', 'hidden'); - currentContainer.fadeOut(300, function () { - if (oldState === "prezi") { - currentContainer.css({opacity: '0'}); - $('#reloadPresentation').css({display: 'none'}); - } - else { - self.setLargeVideoVisible(false); - } - }); - - $('#etherpad>iframe').fadeIn(300, function () { - document.body.style.background = '#eeeeee'; - $('#etherpad>iframe').css({visibility: 'visible'}); - $('#etherpad').css({zIndex: 2}); - }); - break; - case "prezi": - var prezi = $('#presentation>iframe'); - currentContainer.fadeOut(300, function() { - document.body.style.background = 'black'; - }); - prezi.fadeIn(300, function() { - prezi.css({opacity:'1'}); - ToolbarToggler.dockToolbar(true);//fix that - self.setLargeVideoVisible(false); - $('#etherpad>iframe').css({visibility: 'hidden'}); - $('#etherpad').css({zIndex: 0}); - }); - $('#activeSpeaker').css('visibility', 'hidden'); - break; - - case "video": - currentContainer.fadeOut(300, function () { - $('#presentation>iframe').css({opacity:'0'}); - $('#reloadPresentation').css({display:'none'}); - $('#etherpad>iframe').css({visibility: 'hidden'}); - $('#etherpad').css({zIndex: 0}); - document.body.style.background = 'black'; - ToolbarToggler.dockToolbar(false);//fix that - }); - $('#largeVideo').fadeIn(300, function () { - self.setLargeVideoVisible(true); - }); - break; - } - - state = newState; - - }, - /** - * Returns the current state of the large video. - * @returns {string} the current state - video, prezi or etherpad. - */ - getState: function () { - return state; - }, - /** - * Sets hover handlers for the large video container div. - * - * @param inHandler - * @param outHandler - */ - setHover: function(inHandler, outHandler) - { - $('#largeVideoContainer').hover(inHandler, outHandler); - }, - - /** - * Enables/disables the filter indicating a video problem to the user. - * - * @param enable true to enable, false to disable - */ - enableVideoProblemFilter: function (enable) { - $("#largeVideo").toggleClass("videoProblemFilter", enable); - } -}; - -module.exports = LargeVideo; -},{"../../../service/UI/UIEvents":160,"../../RTC/RTCBrowserType":10,"../../xmpp/xmpp":70,"../avatar/Avatar":18,"../toolbars/ToolbarToggler":31,"../util/UIUtil":35}],38:[function(require,module,exports){ -/* global $, interfaceConfig, APP */ -var SmallVideo = require("./SmallVideo"); -var ConnectionIndicator = require("./ConnectionIndicator"); -var NicknameHandler = require("../util/NicknameHandler"); -var UIUtil = require("../util/UIUtil"); -var LargeVideo = require("./LargeVideo"); -var RTCBrowserType = require("../../RTC/RTCBrowserType"); - -function LocalVideo(VideoLayout) { - this.videoSpanId = "localVideoContainer"; - this.container = $("#localVideoContainer").get(0); - this.VideoLayout = VideoLayout; - this.flipX = true; - this.isLocal = true; - this.peerJid = null; -} - -LocalVideo.prototype = Object.create(SmallVideo.prototype); -LocalVideo.prototype.constructor = LocalVideo; - -/** - * Creates the edit display name button. - * - * @returns {object} the edit button - */ -function createEditDisplayNameButton() { - var editButton = document.createElement('a'); - editButton.className = 'displayname'; - UIUtil.setTooltip(editButton, - "videothumbnail.editnickname", - "top"); - editButton.innerHTML = ''; - - return editButton; -} - -/** - * Sets the display name for the given video span id. - */ -LocalVideo.prototype.setDisplayName = function(displayName, key) { - if (!this.container) { - console.warn( - "Unable to set displayName - " + this.videoSpanId + - " does not exist"); - return; - } - - var nameSpan = $('#' + this.videoSpanId + '>span.displayname'); - var defaultLocalDisplayName = APP.translation.generateTranslationHTML( - interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME); - - var meHTML; - // If we already have a display name for this video. - if (nameSpan.length > 0) { - if (nameSpan.text() !== displayName) { - if (displayName && displayName.length > 0) { - meHTML = APP.translation.generateTranslationHTML("me"); - $('#localDisplayName').html(displayName + ' (' + meHTML + ')'); - } else { - $('#localDisplayName').html(defaultLocalDisplayName); - } - } - } else { - var editButton = createEditDisplayNameButton(); - - nameSpan = document.createElement('span'); - nameSpan.className = 'displayname'; - $('#' + this.videoSpanId)[0].appendChild(nameSpan); - - - if (displayName && displayName.length > 0) { - meHTML = APP.translation.generateTranslationHTML("me"); - nameSpan.innerHTML = displayName + meHTML; - } - else { - nameSpan.innerHTML = defaultLocalDisplayName; - } - - - nameSpan.id = 'localDisplayName'; - this.container.appendChild(editButton); - //translates popover of edit button - APP.translation.translateElement($("a.displayname")); - - var editableText = document.createElement('input'); - editableText.className = 'displayname'; - editableText.type = 'text'; - editableText.id = 'editDisplayName'; - - if (displayName && displayName.length) { - editableText.value = displayName; - } - - var defaultNickname = APP.translation.translateString( - "defaultNickname", {name: "Jane Pink"}); - editableText.setAttribute('style', 'display:none;'); - editableText.setAttribute('data-18n', - '[placeholder]defaultNickname'); - editableText.setAttribute("data-i18n-options", - JSON.stringify({name: "Jane Pink"})); - editableText.setAttribute("placeholder", defaultNickname); - - this.container.appendChild(editableText); - - var self = this; - $('#localVideoContainer .displayname') - .bind("click", function (e) { - - var editDisplayName = $('#editDisplayName'); - e.preventDefault(); - e.stopPropagation(); - $('#localDisplayName').hide(); - editDisplayName.show(); - editDisplayName.focus(); - editDisplayName.select(); - - editDisplayName.one("focusout", function (e) { - self.VideoLayout.inputDisplayNameHandler(this.value); - }); - - editDisplayName.on('keydown', function (e) { - if (e.keyCode === 13) { - e.preventDefault(); - self.VideoLayout.inputDisplayNameHandler(this.value); - } - }); - }); - } -}; - -LocalVideo.prototype.inputDisplayNameHandler = function (name) { - NicknameHandler.setNickname(name); - - var localDisplayName = $('#localDisplayName'); - if (!localDisplayName.is(":visible")) { - if (NicknameHandler.getNickname()) { - var meHTML = APP.translation.generateTranslationHTML("me"); - localDisplayName.html(NicknameHandler.getNickname() + " (" + - meHTML + ")"); - } else { - var defaultHTML = APP.translation.generateTranslationHTML( - interfaceConfig.DEFAULT_LOCAL_DISPLAY_NAME); - localDisplayName .html(defaultHTML); - } - localDisplayName.show(); - } - - $('#editDisplayName').hide(); -}; - -LocalVideo.prototype.createConnectionIndicator = function() { - if(this.connectionIndicator) - return; - - this.connectionIndicator = new ConnectionIndicator(this, null); -}; - -LocalVideo.prototype.changeVideo = function (stream, isMuted) { - var self = this; - - function localVideoClick(event) { - // FIXME: with Temasys plugin event arg is not an event, but - // the clicked object itself, so we have to skip this call - if (event.stopPropagation) { - event.stopPropagation(); - } - self.VideoLayout.handleVideoThumbClicked( - false, - APP.xmpp.myResource()); - } - - var localVideoContainerSelector = $('#localVideoContainer'); - localVideoContainerSelector.off('click'); - localVideoContainerSelector.on('click', localVideoClick); - - // Add hover handler - localVideoContainerSelector.hover( - function() { - self.showDisplayName(true); - }, - function() { - if (!LargeVideo.isLargeVideoVisible() || - !LargeVideo.isCurrentlyOnLarge(self.getResourceJid())) { - self.showDisplayName(false); - } - } - ); - - if(isMuted) { - APP.UI.setVideoMute(true); - return; - } - this.flipX = stream.videoType != "screen"; - var localVideo = document.createElement('video'); - localVideo.id = 'localVideo_' + - APP.RTC.getStreamID(stream.getOriginalStream()); - if (!RTCBrowserType.isIExplorer()) { - localVideo.autoplay = true; - localVideo.volume = 0; // is it required if audio is separated ? - } - localVideo.oncontextmenu = function () { return false; }; - - var localVideoContainer = document.getElementById('localVideoWrapper'); - // Put the new video always in front - UIUtil.prependChild(localVideoContainer, localVideo); - - var localVideoSelector = $('#' + localVideo.id); - - // Add click handler to both video and video wrapper elements in case - // there's no video. - - // onclick has to be used with Temasys plugin - localVideo.onclick = localVideoClick; - - if (this.flipX) { - localVideoSelector.addClass("flipVideoX"); - } - - // Attach WebRTC stream - APP.RTC.attachMediaStream(localVideoSelector, stream.getOriginalStream()); - - // Add stream ended handler - stream.getOriginalStream().onended = function () { - // We have to re-select after attach when Temasys plugin is used, - // because