mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2026-01-05 22:32:31 +00:00
Compare commits
209 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2c5439112 | ||
|
|
19362d1904 | ||
|
|
1a69fd8a49 | ||
|
|
224670ed03 | ||
|
|
bb705e32d9 | ||
|
|
3e269978d9 | ||
|
|
9ba62c320b | ||
|
|
8e6d7d3960 | ||
|
|
3138748f57 | ||
|
|
6f10156bf3 | ||
|
|
3852b34397 | ||
|
|
3128628d09 | ||
|
|
d8c4c0627a | ||
|
|
d9559ecf63 | ||
|
|
2b492883ca | ||
|
|
5ab6c551df | ||
|
|
0e27f471f1 | ||
|
|
ba477ad720 | ||
|
|
7858c157c1 | ||
|
|
a5d3cc63c3 | ||
|
|
cac7ccf176 | ||
|
|
9693cba17a | ||
|
|
45e38ae4c9 | ||
|
|
ad68d535b4 | ||
|
|
bb56ea4b33 | ||
|
|
7076ada6f4 | ||
|
|
84834dc4e6 | ||
|
|
f9b3f34593 | ||
|
|
c17576a931 | ||
|
|
570124058c | ||
|
|
3793119209 | ||
|
|
7fb18d1cb3 | ||
|
|
4fc86175e1 | ||
|
|
c951f7f3e9 | ||
|
|
777217bd75 | ||
|
|
2bb637e140 | ||
|
|
b5c1c95a15 | ||
|
|
f2e369cfc0 | ||
|
|
6329271731 | ||
|
|
1428559546 | ||
|
|
5c9a85e928 | ||
|
|
00355caf8d | ||
|
|
feb1d9d8e1 | ||
|
|
7f2fa9597c | ||
|
|
246ab88a3e | ||
|
|
49cc4ae087 | ||
|
|
8d466ad77f | ||
|
|
f824f78db9 | ||
|
|
35f592bb2c | ||
|
|
25a6728acc | ||
|
|
169da33411 | ||
|
|
db70cf4aa9 | ||
|
|
dcfab4401f | ||
|
|
d85a91ae49 | ||
|
|
a3b1a80658 | ||
|
|
db20f145fb | ||
|
|
986bfd02b3 | ||
|
|
57506934f2 | ||
|
|
372a5e2a49 | ||
|
|
726b972223 | ||
|
|
65300b34df | ||
|
|
d7a7733d30 | ||
|
|
7154fd4d39 | ||
|
|
45830c1086 | ||
|
|
202ad0542f | ||
|
|
c59d9e7c8b | ||
|
|
f4f0a7d90e | ||
|
|
ec98e6fdff | ||
|
|
c68bcb8fbc | ||
|
|
c37876a8b7 | ||
|
|
23a805b79c | ||
|
|
157bb1931d | ||
|
|
e59ad67055 | ||
|
|
97b9b67768 | ||
|
|
f899d16a79 | ||
|
|
53288fc997 | ||
|
|
7c89f2b7d1 | ||
|
|
2c39514359 | ||
|
|
536ffb31e0 | ||
|
|
a50a980de4 | ||
|
|
da0898a066 | ||
|
|
541f83cf71 | ||
|
|
fe6588516f | ||
|
|
6651168dd3 | ||
|
|
ced7da405d | ||
|
|
fd836560aa | ||
|
|
5654d34ee8 | ||
|
|
6302e42229 | ||
|
|
34a24ce290 | ||
|
|
71a778b65c | ||
|
|
62fa4dffa8 | ||
|
|
d3dd643a88 | ||
|
|
6116df9411 | ||
|
|
db0c4e95f7 | ||
|
|
9a25db34aa | ||
|
|
c7710bfe1c | ||
|
|
dd7502f8de | ||
|
|
df01358fb8 | ||
|
|
d3cd634bff | ||
|
|
1454a28a69 | ||
|
|
7251c7a641 | ||
|
|
06c636311d | ||
|
|
b457166726 | ||
|
|
562c2e38db | ||
|
|
e2c16c9c11 | ||
|
|
db91040443 | ||
|
|
9f3c209096 | ||
|
|
123b5abb08 | ||
|
|
6cb89891ce | ||
|
|
ff68caaa16 | ||
|
|
a58190a935 | ||
|
|
372278d163 | ||
|
|
a5a7b63abf | ||
|
|
e9b7aaea84 | ||
|
|
132d823f54 | ||
|
|
75eb30b09d | ||
|
|
baa60347fb | ||
|
|
8de3e0ff0b | ||
|
|
443c29f505 | ||
|
|
b309ef25fd | ||
|
|
0ea5175354 | ||
|
|
10517115c3 | ||
|
|
ddb356482f | ||
|
|
6ae35fb21d | ||
|
|
330597182c | ||
|
|
adefa40dcc | ||
|
|
8d162609e0 | ||
|
|
0a51ddd7ef | ||
|
|
c3ae8669e8 | ||
|
|
974ba47e3c | ||
|
|
9d170e4c59 | ||
|
|
ae0e950c16 | ||
|
|
79412f20ab | ||
|
|
7ea047cf1b | ||
|
|
4bf5d69002 | ||
|
|
0e2d8a323a | ||
|
|
9a4cee1818 | ||
|
|
b0957f387e | ||
|
|
1f8dc54368 | ||
|
|
74ece3a775 | ||
|
|
60f7b9ab93 | ||
|
|
f8d555790b | ||
|
|
4ff297730c | ||
|
|
29050ea917 | ||
|
|
c4c0bc1c37 | ||
|
|
0f52f4e5a1 | ||
|
|
cff7a5c2f5 | ||
|
|
626d9a40ed | ||
|
|
b8f26c58e3 | ||
|
|
9dbd9b8405 | ||
|
|
08f200f0eb | ||
|
|
9fa65ccda6 | ||
|
|
d0fa9e7ef1 | ||
|
|
d7c1976a52 | ||
|
|
39e71efb2f | ||
|
|
855bcf8fe3 | ||
|
|
97069f1dc6 | ||
|
|
bc3c6412f6 | ||
|
|
51dcb2befb | ||
|
|
805c9e4eda | ||
|
|
a38e85b39c | ||
|
|
96bd3a54cb | ||
|
|
4fd5fba768 | ||
|
|
06027ea8e5 | ||
|
|
6f38d58954 | ||
|
|
30c964f1e3 | ||
|
|
2a8e0bd866 | ||
|
|
644e12929c | ||
|
|
d625b8e3f3 | ||
|
|
5b884806d2 | ||
|
|
7aa47647f0 | ||
|
|
c779dbe8ad | ||
|
|
64ee01d831 | ||
|
|
52c6bbe731 | ||
|
|
1963972f75 | ||
|
|
85d0c62c1d | ||
|
|
dfa9bab9e1 | ||
|
|
3ed1532f25 | ||
|
|
115420db82 | ||
|
|
d2a6c4a97f | ||
|
|
c04874b087 | ||
|
|
a0b3018ea0 | ||
|
|
e46d45adea | ||
|
|
f977030bd6 | ||
|
|
38fc1c01d4 | ||
|
|
2f202deedf | ||
|
|
08bd40bb26 | ||
|
|
28700173a0 | ||
|
|
66a46fc580 | ||
|
|
de41977c77 | ||
|
|
45c420561a | ||
|
|
e240b15d61 | ||
|
|
486058834e | ||
|
|
3e473ea9d7 | ||
|
|
62dd54ab31 | ||
|
|
b3e02add3d | ||
|
|
7bf9a82f0b | ||
|
|
ce5ff20d5b | ||
|
|
615daa8c9f | ||
|
|
5dffddceec | ||
|
|
d5de49b5cf | ||
|
|
62f7553ba4 | ||
|
|
b7ad6b606a | ||
|
|
60c2ee41e3 | ||
|
|
64475143cf | ||
|
|
c1122eae3a | ||
|
|
1792b1ed85 | ||
|
|
d624f2584d | ||
|
|
8196233ed2 |
5
Makefile
5
Makefile
@@ -3,7 +3,7 @@ BROWSERIFY = ./node_modules/.bin/browserify
|
||||
UGLIFYJS = ./node_modules/.bin/uglifyjs
|
||||
EXORCIST = ./node_modules/.bin/exorcist
|
||||
CLEANCSS = ./node_modules/.bin/cleancss
|
||||
CSS_FILES = font.css toastr.css main.css overlay.css videolayout_default.css font-awesome.css jquery-impromptu.css modaldialog.css notice.css popup_menu.css login_menu.css popover.css jitsi_popover.css contact_list.css chat.css welcome_page.css settingsmenu.css feedback.css jquery.contextMenu.css keyboard-shortcuts.css
|
||||
CSS_FILES = font.css toastr.css main.css overlay.css videolayout_default.css font-awesome.css jquery-impromptu.css modaldialog.css notice.css popup_menu.css recording.css login_menu.css popover.css jitsi_popover.css contact_list.css chat.css welcome_page.css settingsmenu.css feedback.css jquery.contextMenu.css keyboard-shortcuts.css
|
||||
DEPLOY_DIR = libs
|
||||
BROWSERIFY_FLAGS = -d
|
||||
OUTPUT_DIR = .
|
||||
@@ -13,7 +13,7 @@ IFRAME_API_DIR = ./modules/API/external
|
||||
all: update-deps compile compile-iframe-api uglify uglify-iframe-api deploy clean
|
||||
|
||||
update-deps:
|
||||
$(NPM) install
|
||||
$(NPM) update
|
||||
|
||||
compile:
|
||||
$(BROWSERIFY) $(BROWSERIFY_FLAGS) -e app.js -s APP | $(EXORCIST) $(OUTPUT_DIR)/app.bundle.js.map > $(OUTPUT_DIR)/app.bundle.js
|
||||
@@ -34,6 +34,7 @@ deploy-appbundle:
|
||||
$(OUTPUT_DIR)/app.bundle.js $(OUTPUT_DIR)/app.bundle.js.map \
|
||||
$(OUTPUT_DIR)/external_api.js.map $(OUTPUT_DIR)/external_api.js \
|
||||
$(OUTPUT_DIR)/external_api.min.map $(OUTPUT_DIR)/external_api.min.js \
|
||||
$(OUTPUT_DIR)/analytics.js \
|
||||
$(DEPLOY_DIR)
|
||||
|
||||
deploy-lib-jitsi-meet:
|
||||
|
||||
@@ -66,6 +66,7 @@ npm link lib-jitsi-meet
|
||||
```
|
||||
|
||||
So now after changes in local `lib-jitsi-meet` repository you can rebuild it with `npm run install` and your `jitsi-meet` repository will use that modified library.
|
||||
Note: when using node version 4.x, the make file of jitsi-meet do npm update which will delete the link, no longer the case with version 6.x.
|
||||
|
||||
If you do not want to use local repository anymore you should run
|
||||
```bash
|
||||
|
||||
@@ -10,8 +10,13 @@
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
|
||||
Analytics.prototype.sendEvent = function (action, data) {
|
||||
ga('send', 'event', 'jit.si', action);
|
||||
Analytics.prototype.sendEvent = function (action, data, label) {
|
||||
// empty label if missing value for it and add the value,
|
||||
// the value should be integer or null
|
||||
var value = Math.round(parseFloat(data));
|
||||
|
||||
ga('send', 'event', 'jit.si',
|
||||
action, label ? label : "", value ? value : null);
|
||||
};
|
||||
|
||||
ctx.Analytics = Analytics;
|
||||
|
||||
4
app.js
4
app.js
@@ -95,9 +95,9 @@ const APP = {
|
||||
function setTokenData() {
|
||||
let localUser = APP.tokenData.caller;
|
||||
if(localUser) {
|
||||
APP.settings.setEmail((localUser.getEmail() || "").trim());
|
||||
APP.settings.setEmail((localUser.getEmail() || "").trim(), true);
|
||||
APP.settings.setAvatarUrl((localUser.getAvatarUrl() || "").trim());
|
||||
APP.settings.setDisplayName((localUser.getName() || "").trim());
|
||||
APP.settings.setDisplayName((localUser.getName() || "").trim(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
241
conference.js
241
conference.js
@@ -14,6 +14,10 @@ import UIEvents from './service/UI/UIEvents';
|
||||
|
||||
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
|
||||
|
||||
import {reportError} from './modules/util/helpers';
|
||||
|
||||
import UIErrors from './modules/UI/UIErrors';
|
||||
|
||||
const ConnectionEvents = JitsiMeetJS.events.connection;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
|
||||
@@ -25,6 +29,16 @@ const TrackErrors = JitsiMeetJS.errors.track;
|
||||
|
||||
let room, connection, localAudio, localVideo, roomLocker;
|
||||
|
||||
/**
|
||||
* Indicates whether the connection is interrupted or not.
|
||||
*/
|
||||
let connectionIsInterrupted = false;
|
||||
|
||||
/**
|
||||
* Indicates whether extension external installation is in progress or not.
|
||||
*/
|
||||
let DSExternalInstallationInProgress = false;
|
||||
|
||||
import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/LargeVideo";
|
||||
|
||||
/**
|
||||
@@ -34,6 +48,7 @@ const commands = {
|
||||
CONNECTION_QUALITY: "stats",
|
||||
EMAIL: "email",
|
||||
AVATAR_URL: "avatar-url",
|
||||
AVATAR_ID: "avatar-id",
|
||||
ETHERPAD: "etherpad",
|
||||
SHARED_VIDEO: "shared-video",
|
||||
CUSTOM_ROLE: "custom-role"
|
||||
@@ -221,15 +236,28 @@ function disconnectAndShowFeedback(requestFeedback) {
|
||||
*/
|
||||
function hangup (requestFeedback = false) {
|
||||
const errCallback = (f, err) => {
|
||||
console.error('Error occurred during hanging up: ', err);
|
||||
return f();
|
||||
|
||||
// If we want to break out the chain in our error handler, it needs
|
||||
// to return a rejected promise. In the case of feedback request
|
||||
// in progress it's important to not redirect to the welcome page
|
||||
// (see below maybeRedirectToWelcomePage call).
|
||||
if (err === UIErrors.FEEDBACK_REQUEST_IN_PROGRESS) {
|
||||
return Promise.reject('Feedback request in progress.');
|
||||
}
|
||||
else {
|
||||
console.error('Error occurred during hanging up: ', err);
|
||||
return Promise.resolve();
|
||||
}
|
||||
};
|
||||
const disconnect = disconnectAndShowFeedback.bind(null, requestFeedback);
|
||||
APP.conference._room.leave()
|
||||
.then(disconnect)
|
||||
.catch(errCallback.bind(null, disconnect))
|
||||
.then(maybeRedirectToWelcomePage)
|
||||
.catch(errCallback.bind(null, maybeRedirectToWelcomePage));
|
||||
.catch(function(err){
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,7 +290,9 @@ function createLocalTracks (options, checkForPermissionPrompt) {
|
||||
? APP.settings.getMicDeviceId()
|
||||
: options.micDeviceId,
|
||||
// adds any ff fake device settings if any
|
||||
firefox_fake_device: config.firefox_fake_device
|
||||
firefox_fake_device: config.firefox_fake_device,
|
||||
desktopSharingExtensionExternalInstallation:
|
||||
options.desktopSharingExtensionExternalInstallation
|
||||
}, checkForPermissionPrompt)
|
||||
.catch(function (err) {
|
||||
console.error(
|
||||
@@ -287,23 +317,6 @@ function changeLocalEmail(email = '') {
|
||||
sendData(commands.EMAIL, email);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Changes the local avatar url for the local user
|
||||
* @param avatarUrl {string} the new avatar url
|
||||
*/
|
||||
function changeLocalAvatarUrl(avatarUrl = '') {
|
||||
avatarUrl = avatarUrl.trim();
|
||||
|
||||
if (avatarUrl === APP.settings.getAvatarUrl()) {
|
||||
return;
|
||||
}
|
||||
|
||||
APP.settings.setAvatarUrl(avatarUrl);
|
||||
APP.UI.setUserAvatarUrl(room.myUserId(), avatarUrl);
|
||||
sendData(commands.AVATAR_URL, avatarUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the display name for the local user
|
||||
* @param nickname {string} the new display name
|
||||
@@ -317,7 +330,7 @@ function changeLocalDisplayName(nickname = '') {
|
||||
|
||||
APP.settings.setDisplayName(nickname);
|
||||
room.setDisplayName(nickname);
|
||||
APP.UI.changeDisplayName(APP.conference.localId, nickname);
|
||||
APP.UI.changeDisplayName(APP.conference.getMyUserId(), nickname);
|
||||
}
|
||||
|
||||
class ConferenceConnector {
|
||||
@@ -410,6 +423,9 @@ class ConferenceConnector {
|
||||
connection.disconnect();
|
||||
APP.UI.notifyMaxUsersLimitReached();
|
||||
break;
|
||||
case ConferenceErrors.INCOMPATIBLE_SERVER_VERSIONS:
|
||||
window.location.reload();
|
||||
break;
|
||||
default:
|
||||
this._handleConferenceFailed(err, ...params);
|
||||
}
|
||||
@@ -447,7 +463,6 @@ class ConferenceConnector {
|
||||
}
|
||||
|
||||
export default {
|
||||
localId: undefined,
|
||||
isModerator: false,
|
||||
audioMuted: false,
|
||||
videoMuted: false,
|
||||
@@ -530,7 +545,7 @@ export default {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isLocalId (id) {
|
||||
return this.localId === id;
|
||||
return this.getMyUserId() === id;
|
||||
},
|
||||
/**
|
||||
* Simulates toolbar button click for audio mute. Used by shortcuts and API.
|
||||
@@ -618,6 +633,12 @@ export default {
|
||||
sendFeedback (overallFeedback, detailedFeedback) {
|
||||
return room.sendFeedback (overallFeedback, detailedFeedback);
|
||||
},
|
||||
/**
|
||||
* Returns the connection times stored in the library.
|
||||
*/
|
||||
getConnectionTimes () {
|
||||
return this._room.getConnectionTimes();
|
||||
},
|
||||
// used by torture currently
|
||||
isJoined () {
|
||||
return this._room
|
||||
@@ -728,7 +749,6 @@ export default {
|
||||
_createRoom (localTracks) {
|
||||
room = connection.initJitsiConference(APP.conference.roomName,
|
||||
this._getConferenceOptions());
|
||||
this.localId = room.myUserId();
|
||||
this._setLocalAudioVideoStreams(localTracks);
|
||||
roomLocker = createRoomLocker(room);
|
||||
this._room = room; // FIXME do not use this
|
||||
@@ -739,6 +759,8 @@ export default {
|
||||
let avatarUrl = APP.settings.getAvatarUrl();
|
||||
avatarUrl && sendData(this.commands.defaults.AVATAR_URL,
|
||||
avatarUrl);
|
||||
!email && sendData(
|
||||
this.commands.defaults.AVATAR_ID, APP.settings.getAvatarId());
|
||||
|
||||
let nick = APP.settings.getDisplayName();
|
||||
if (config.useNicks && !nick) {
|
||||
@@ -812,7 +834,7 @@ export default {
|
||||
this.isSharingScreen = false;
|
||||
}
|
||||
|
||||
APP.UI.setVideoMuted(this.localId, this.videoMuted);
|
||||
APP.UI.setVideoMuted(this.getMyUserId(), this.videoMuted);
|
||||
|
||||
APP.UI.updateDesktopSharingButtons();
|
||||
});
|
||||
@@ -847,7 +869,7 @@ export default {
|
||||
}
|
||||
|
||||
APP.UI.enableMicrophoneButton();
|
||||
APP.UI.setAudioMuted(this.localId, this.audioMuted);
|
||||
APP.UI.setAudioMuted(this.getMyUserId(), this.audioMuted);
|
||||
});
|
||||
},
|
||||
|
||||
@@ -863,9 +885,38 @@ export default {
|
||||
}
|
||||
|
||||
this.videoSwitchInProgress = true;
|
||||
let externalInstallation = false;
|
||||
|
||||
if (shareScreen) {
|
||||
createLocalTracks({ devices: ['desktop'] }).then(([stream]) => {
|
||||
createLocalTracks({
|
||||
devices: ['desktop'],
|
||||
desktopSharingExtensionExternalInstallation: {
|
||||
interval: 500,
|
||||
checkAgain: () => {
|
||||
return DSExternalInstallationInProgress;
|
||||
},
|
||||
listener: (status, url) => {
|
||||
switch(status) {
|
||||
case "waitingForExtension":
|
||||
DSExternalInstallationInProgress = true;
|
||||
externalInstallation = true;
|
||||
APP.UI.showExtensionExternalInstallationDialog(
|
||||
url);
|
||||
break;
|
||||
case "extensionFound":
|
||||
if(externalInstallation) //close the dialog
|
||||
$.prompt.close();
|
||||
break;
|
||||
default:
|
||||
//Unknown status
|
||||
}
|
||||
}
|
||||
}
|
||||
}).then(([stream]) => {
|
||||
DSExternalInstallationInProgress = false;
|
||||
// close external installation dialog on success.
|
||||
if(externalInstallation)
|
||||
$.prompt.close();
|
||||
stream.on(
|
||||
TrackEvents.LOCAL_TRACK_STOPPED,
|
||||
() => {
|
||||
@@ -881,8 +932,13 @@ export default {
|
||||
return this.useVideoStream(stream);
|
||||
}).then(() => {
|
||||
this.videoSwitchInProgress = false;
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'conference.sharingDesktop.start');
|
||||
console.log('sharing local desktop');
|
||||
}).catch((err) => {
|
||||
// close external installation dialog to show the error.
|
||||
if(externalInstallation)
|
||||
$.prompt.close();
|
||||
this.videoSwitchInProgress = false;
|
||||
this.toggleScreenSharing(false);
|
||||
|
||||
@@ -926,6 +982,8 @@ export default {
|
||||
([stream]) => this.useVideoStream(stream)
|
||||
).then(() => {
|
||||
this.videoSwitchInProgress = false;
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'conference.sharingDesktop.stop');
|
||||
console.log('sharing local video');
|
||||
}).catch((err) => {
|
||||
this.useVideoStream(null);
|
||||
@@ -942,6 +1000,8 @@ export default {
|
||||
room.on(ConferenceEvents.CONFERENCE_JOINED, () => {
|
||||
APP.UI.mucJoined();
|
||||
APP.API.notifyConferenceJoined(APP.conference.roomName);
|
||||
connectionIsInterrupted = false;
|
||||
APP.UI.markVideoInterrupted(false);
|
||||
});
|
||||
|
||||
room.on(
|
||||
@@ -1009,7 +1069,7 @@ export default {
|
||||
let id;
|
||||
const mute = track.isMuted();
|
||||
if(track.isLocal()){
|
||||
id = this.localId;
|
||||
id = APP.conference.getMyUserId();
|
||||
if(track.getType() === "audio") {
|
||||
this.audioMuted = mute;
|
||||
} else {
|
||||
@@ -1075,6 +1135,15 @@ export default {
|
||||
});
|
||||
}
|
||||
|
||||
room.on(ConferenceEvents.CONNECTION_INTERRUPTED, () => {
|
||||
connectionIsInterrupted = true;
|
||||
ConnectionQuality.updateLocalConnectionQuality(0);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.CONNECTION_RESTORED, () => {
|
||||
connectionIsInterrupted = false;
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.DISPLAY_NAME_CHANGED, (id, displayName) => {
|
||||
APP.API.notifyDisplayNameChanged(id, displayName);
|
||||
APP.UI.changeDisplayName(id, displayName);
|
||||
@@ -1092,6 +1161,11 @@ export default {
|
||||
APP.UI.updateRecordingState(status);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.LOCK_STATE_CHANGED, (state, error) => {
|
||||
console.log("Received channel password lock change: ", state, error);
|
||||
APP.UI.markRoomLocked(state);
|
||||
});
|
||||
|
||||
room.on(ConferenceEvents.USER_STATUS_CHANGED, function (id, status) {
|
||||
APP.UI.updateUserStatus(id, status);
|
||||
});
|
||||
@@ -1106,6 +1180,17 @@ export default {
|
||||
APP.UI.updateDTMFSupport(isDTMFSupported);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.EXTERNAL_INSTALLATION_CANCELED, () => {
|
||||
// Wait a little bit more just to be sure that we won't miss the
|
||||
// extension installation
|
||||
setTimeout(() => DSExternalInstallationInProgress = false, 500);
|
||||
});
|
||||
APP.UI.addListener(UIEvents.OPEN_EXTENSION_STORE, (url) => {
|
||||
window.open(
|
||||
url, "extension_store_window",
|
||||
"resizable,scrollbars=yes,status=1");
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.ROOM_LOCK_CLICKED, () => {
|
||||
if (room.isModerator()) {
|
||||
let promise = roomLocker.isLocked
|
||||
@@ -1130,29 +1215,36 @@ export default {
|
||||
}
|
||||
|
||||
room.on(ConferenceEvents.CONNECTION_STATS, function (stats) {
|
||||
ConnectionQuality.updateLocalStats(stats);
|
||||
ConnectionQuality.updateLocalStats(stats, connectionIsInterrupted);
|
||||
});
|
||||
ConnectionQuality.addListener(
|
||||
CQEvents.LOCALSTATS_UPDATED,
|
||||
|
||||
ConnectionQuality.addListener(CQEvents.LOCALSTATS_UPDATED,
|
||||
(percent, stats) => {
|
||||
APP.UI.updateLocalStats(percent, stats);
|
||||
// Send only the data that remote participants care about.
|
||||
let data = {
|
||||
bitrate: stats.bitrate,
|
||||
packetLoss: stats.packetLoss};
|
||||
try {
|
||||
room.broadcastEndpointMessage({
|
||||
type: this.commands.defaults.CONNECTION_QUALITY,
|
||||
values: data });
|
||||
} catch (e) {
|
||||
reportError(e);
|
||||
}
|
||||
});
|
||||
|
||||
// send local stats to other users
|
||||
room.sendCommandOnce(this.commands.defaults.CONNECTION_QUALITY,
|
||||
{
|
||||
children: ConnectionQuality.convertToMUCStats(stats),
|
||||
attributes: {
|
||||
xmlns: 'http://jitsi.org/jitmeet/stats'
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// listen to remote stats
|
||||
room.addCommandListener(this.commands.defaults.CONNECTION_QUALITY,
|
||||
(values, from) => {
|
||||
ConnectionQuality.updateRemoteStats(from, values);
|
||||
});
|
||||
room.on(ConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
|
||||
(participant, payload) => {
|
||||
switch(payload.type) {
|
||||
case this.commands.defaults.CONNECTION_QUALITY:
|
||||
ConnectionQuality.updateRemoteStats(participant.getId(),
|
||||
payload.values);
|
||||
break;
|
||||
default:
|
||||
console.warn("Unknown datachannel message", payload);
|
||||
}
|
||||
});
|
||||
|
||||
ConnectionQuality.addListener(CQEvents.REMOTESTATS_UPDATED,
|
||||
(id, percent, stats) => {
|
||||
@@ -1168,13 +1260,16 @@ export default {
|
||||
APP.UI.setUserEmail(from, data.value);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.AVATAR_URL_CHANGED, changeLocalAvatarUrl);
|
||||
|
||||
room.addCommandListener(this.commands.defaults.AVATAR_URL,
|
||||
(data, from) => {
|
||||
APP.UI.setUserAvatarUrl(from, data.value);
|
||||
});
|
||||
|
||||
room.addCommandListener(this.commands.defaults.AVATAR_ID,
|
||||
(data, from) => {
|
||||
APP.UI.setUserAvatarID(from, data.value);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.NICKNAME_CHANGED, changeLocalDisplayName);
|
||||
|
||||
APP.UI.addListener(UIEvents.START_MUTED_CHANGED,
|
||||
@@ -1231,6 +1326,24 @@ export default {
|
||||
room.dial(sipNumber);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.RESOLUTION_CHANGED,
|
||||
(id, oldResolution, newResolution, delay) => {
|
||||
var logObject = {
|
||||
id: "resolution_change",
|
||||
participant: id,
|
||||
oldValue: oldResolution,
|
||||
newValue: newResolution,
|
||||
delay: delay
|
||||
};
|
||||
room.sendApplicationLog(JSON.stringify(logObject));
|
||||
|
||||
// We only care about the delay between simulcast streams.
|
||||
// Longer delays will be caused by something else and will just
|
||||
// poison the data.
|
||||
if (delay < 2000) {
|
||||
JitsiMeetJS.analytics.sendEvent('stream.switch.delay', delay);
|
||||
}
|
||||
});
|
||||
|
||||
// Starts or stops the recording for the conference.
|
||||
APP.UI.addListener(UIEvents.RECORDING_TOGGLED, (options) => {
|
||||
@@ -1257,27 +1370,35 @@ export default {
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.SELECTED_ENDPOINT, (id) => {
|
||||
room.selectParticipant(id);
|
||||
try {
|
||||
room.selectParticipant(id);
|
||||
} catch (e) {
|
||||
JitsiMeetJS.analytics.sendEvent('selectParticipant.failed');
|
||||
reportError(e);
|
||||
}
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.PINNED_ENDPOINT, (smallVideo, isPinned) => {
|
||||
var smallVideoId = smallVideo.getId();
|
||||
|
||||
if (smallVideo.getVideoType() === VIDEO_CONTAINER_TYPE
|
||||
&& !APP.conference.isLocalId(smallVideoId))
|
||||
if (isPinned)
|
||||
room.pinParticipant(smallVideoId);
|
||||
&& !APP.conference.isLocalId(smallVideoId)) {
|
||||
|
||||
// When the library starts supporting multiple pins we would
|
||||
// pass the isPinned parameter together with the identifier,
|
||||
// but currently we send null to indicate that we unpin the
|
||||
// last pinned.
|
||||
else
|
||||
room.pinParticipant(null);
|
||||
try {
|
||||
room.pinParticipant(isPinned ? smallVideoId : null);
|
||||
} catch (e) {
|
||||
reportError(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
APP.UI.addListener(
|
||||
UIEvents.VIDEO_DEVICE_CHANGED,
|
||||
(cameraDeviceId) => {
|
||||
JitsiMeetJS.analytics.sendEvent('settings.changeDevice.video');
|
||||
createLocalTracks({
|
||||
devices: ['video'],
|
||||
cameraDeviceId: cameraDeviceId,
|
||||
@@ -1298,6 +1419,8 @@ export default {
|
||||
APP.UI.addListener(
|
||||
UIEvents.AUDIO_DEVICE_CHANGED,
|
||||
(micDeviceId) => {
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'settings.changeDevice.audioIn');
|
||||
createLocalTracks({
|
||||
devices: ['audio'],
|
||||
cameraDeviceId: null,
|
||||
@@ -1318,6 +1441,8 @@ export default {
|
||||
APP.UI.addListener(
|
||||
UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED,
|
||||
(audioOutputDeviceId) => {
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'settings.changeDevice.audioOut');
|
||||
APP.settings.setAudioOutputDeviceId(audioOutputDeviceId)
|
||||
.then(() => console.log('changed audio output device'))
|
||||
.catch((err) => {
|
||||
@@ -1513,4 +1638,4 @@ export default {
|
||||
APP.UI.setLocalRaisedHandStatus(raisedHand);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/* global APP, JitsiMeetJS, config */
|
||||
//FIXME:
|
||||
import LoginDialog from './modules/UI/authentication/LoginDialog';
|
||||
import AuthHandler from './modules/UI/authentication/AuthHandler';
|
||||
|
||||
const ConnectionEvents = JitsiMeetJS.events.connection;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
@@ -92,33 +91,6 @@ function connect(id, password, roomName) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Authentication Dialog and try to connect with new credentials.
|
||||
* If failed to connect because of PASSWORD_REQUIRED error
|
||||
* then ask for password again.
|
||||
* @param {string} [roomName]
|
||||
* @returns {Promise<JitsiConnection>}
|
||||
*/
|
||||
function requestAuth(roomName) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let authDialog = LoginDialog.showAuthDialog(
|
||||
function (id, password) {
|
||||
connect(id, password, roomName).then(function (connection) {
|
||||
authDialog.close();
|
||||
resolve(connection);
|
||||
}, function (err) {
|
||||
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
|
||||
authDialog.displayError(err);
|
||||
} else {
|
||||
authDialog.close();
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open JitsiConnection using provided credentials.
|
||||
* If retry option is true it will show auth dialog on PASSWORD_REQUIRED error.
|
||||
@@ -157,7 +129,7 @@ export function openConnection({id, password, retry, roomName}) {
|
||||
if (config.token) {
|
||||
throw err;
|
||||
} else {
|
||||
return requestAuth(roomName);
|
||||
return AuthHandler.requestAuth(roomName, connect);
|
||||
}
|
||||
} else {
|
||||
throw err;
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
height: 35px;
|
||||
width: 100px;
|
||||
position: absolute;
|
||||
bottom: -35;
|
||||
bottom: -35px;
|
||||
}
|
||||
|
||||
.jitsipopover_green
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
left: 20px;
|
||||
overflow: hidden;
|
||||
padding: 20px;
|
||||
z-index: 1;
|
||||
z-index: 10;
|
||||
border-radius: 15px;
|
||||
background-attachment: scroll;
|
||||
background-size: auto auto;
|
||||
@@ -16,4 +16,9 @@
|
||||
#keyboard-shortcuts .item-action {
|
||||
color: #209EFF;
|
||||
font-size: 14pt;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
#keyboard-shortcuts-list {
|
||||
list-style-type: none;
|
||||
}
|
||||
10
css/main.css
10
css/main.css
@@ -157,15 +157,6 @@ a.bottomToolbarButton:hover {
|
||||
color: #636363;
|
||||
}
|
||||
|
||||
.bottom_button_separator {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
left: 5px;
|
||||
width: 20px;
|
||||
height: 1px;
|
||||
background: #373737;
|
||||
}
|
||||
|
||||
input[type='text'], input[type='password'], textarea {
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
@@ -226,6 +217,7 @@ form {
|
||||
}
|
||||
|
||||
#downloadlog {
|
||||
display: none;
|
||||
position: absolute;
|
||||
bottom: 5;
|
||||
left: 5;
|
||||
|
||||
@@ -1,27 +1,10 @@
|
||||
/*Initialize*/
|
||||
ul.popupmenu {
|
||||
display:none;
|
||||
position: absolute;
|
||||
padding:10px;
|
||||
padding: 0px 10px 0px 10px;
|
||||
margin: 0;
|
||||
bottom: 0;
|
||||
margin-bottom: 35px;
|
||||
padding-bottom: 10px;
|
||||
padding-top: 10px;
|
||||
right: 10px;
|
||||
left: -5px;
|
||||
width: 100px;
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
border: 1px solid rgba(256, 256, 256, 0.2);
|
||||
border-radius:3px;
|
||||
}
|
||||
|
||||
ul.popupmenu:after {
|
||||
content: url('../images/popupPointer.png');
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: -8px;
|
||||
left: 11px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
ul.popupmenu li {
|
||||
@@ -36,11 +19,13 @@ ul.popupmenu li:hover {
|
||||
|
||||
/*Link Appearance*/
|
||||
ul.popupmenu li a {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
padding: 5px;
|
||||
display: inline-block;
|
||||
font-size: 9pt;
|
||||
width: 100%;
|
||||
cursor: hand;
|
||||
}
|
||||
|
||||
ul.popupmenu li a i.icon-kick {
|
||||
@@ -54,6 +39,15 @@ ul.popupmenu li a span {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul.popupmenu li a div {
|
||||
display: inline-block;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
ul.popupmenu li a i {
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
|
||||
display:block !important;
|
||||
}
|
||||
@@ -61,12 +55,4 @@ span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
|
||||
a.disabled {
|
||||
color: gray !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.popupmenuPadding {
|
||||
height: 35px;
|
||||
width: 100px;
|
||||
position: absolute;
|
||||
bottom: -35;
|
||||
left: 0px;
|
||||
}
|
||||
4
css/recording.css
Normal file
4
css/recording.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.recordingSpinner {
|
||||
display: none;
|
||||
vertical-align: text-bottom;
|
||||
}
|
||||
@@ -98,39 +98,39 @@ a {
|
||||
{
|
||||
width: 78px;
|
||||
height: 78px;
|
||||
background-image: url('/images/chrome.png');
|
||||
background-image: url('../images/chrome.png');
|
||||
}
|
||||
#chromium_logo
|
||||
{
|
||||
width: 77px;
|
||||
height: 78px;
|
||||
background-image: url('/images/chromium.png');
|
||||
background-image: url('../images/chromium.png');
|
||||
}
|
||||
#firefox_logo
|
||||
{
|
||||
width: 86px;
|
||||
height: 80px;
|
||||
background-image: url('/images/firefox.png');
|
||||
background-image: url('../images/firefox.png');
|
||||
}
|
||||
|
||||
#opera_logo
|
||||
{
|
||||
width: 73px;
|
||||
height: 78px;
|
||||
background-image: url('/images/opera.png');
|
||||
background-image: url('../images/opera.png');
|
||||
}
|
||||
|
||||
#safari_logo
|
||||
{
|
||||
width: 78px;
|
||||
height: 79px;
|
||||
background-image: url('/images/safari.png');
|
||||
background-image: url('../images/safari.png');
|
||||
}
|
||||
|
||||
#ie_logo
|
||||
{
|
||||
width: 80px;
|
||||
height: 78px;
|
||||
background-image: url('/images/ie.png');
|
||||
background-image: url('../images/ie.png');
|
||||
}
|
||||
|
||||
|
||||
@@ -41,20 +41,15 @@
|
||||
background-size: contain;
|
||||
border-radius:1px;
|
||||
border: 1px solid #212425;
|
||||
/*margin-right: 1px;*/
|
||||
}
|
||||
|
||||
/*#remoteVideos .videocontainer:hover,*/
|
||||
#remoteVideos .videocontainer.videoContainerFocused {
|
||||
cursor: hand;
|
||||
/* transform:scale(1.08, 1.08);
|
||||
-webkit-transform:scale(1.08, 1.08); */
|
||||
transition-duration: 0.5s;
|
||||
-webkit-transition-duration: 0.5s;
|
||||
-webkit-animation-name: greyPulse;
|
||||
-webkit-animation-duration: 2s;
|
||||
-webkit-animation-iteration-count: 1;
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
#remoteVideos .videocontainer:hover {
|
||||
@@ -82,6 +77,7 @@
|
||||
cursor: hand;
|
||||
border-radius:1px;
|
||||
object-fit: cover;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.flipVideoX {
|
||||
@@ -144,8 +140,7 @@
|
||||
}
|
||||
|
||||
#remoteVideos .videocontainer>span.focusindicator,
|
||||
#remoteVideos .videocontainer>span.remotevideomenu {
|
||||
display: inline-block;
|
||||
#remoteVideos .videocontainer>div.remotevideomenu {
|
||||
position: absolute;
|
||||
color: #FFFFFF;
|
||||
top: 0;
|
||||
@@ -159,6 +154,14 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#remoteVideos .videocontainer>span.focusindicator {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#remoteVideos .videocontainer>div.remotevideomenu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.videocontainer>span.displayname,
|
||||
.videocontainer>input.displayname {
|
||||
display: none;
|
||||
|
||||
4
debian/jitsi-meet-tokens.postinst
vendored
4
debian/jitsi-meet-tokens.postinst
vendored
@@ -67,8 +67,8 @@ case "$1" in
|
||||
sed -i 's/ --modules_enabled = { "token_verification" }/ modules_enabled = { "token_verification" }/g' $PROSODY_HOST_CONFIG
|
||||
|
||||
# Install luajwt
|
||||
if ! luarocks install jwt; then
|
||||
echo "Failed to install jwt - try installing it manually"
|
||||
if ! luarocks install luajwtjitsi; then
|
||||
echo "Failed to install luajwtjitsi - try installing it manually"
|
||||
fi
|
||||
|
||||
if [ -x "/etc/init.d/prosody" ]; then
|
||||
|
||||
1
debian/jitsi-meet.postinst
vendored
1
debian/jitsi-meet.postinst
vendored
@@ -88,6 +88,7 @@ case "$1" in
|
||||
echo "org.jitsi.videobridge.rest.jetty.ProxyServlet.proxyTo=http://localhost:5280/http-bind" >> $JVB_CONFIG
|
||||
echo "org.jitsi.videobridge.rest.jetty.ResourceHandler.resourceBase=/usr/share/jitsi-meet" >> $JVB_CONFIG
|
||||
echo "org.jitsi.videobridge.rest.jetty.ResourceHandler.alias./config.js=/etc/jitsi/meet/$JVB_HOSTNAME-config.js" >> $JVB_CONFIG
|
||||
echo "org.jitsi.videobridge.rest.jetty.ResourceHandler.alias./interface_config.js=/usr/share/jitsi-meet/interface_config.js" >> $JVB_CONFIG
|
||||
echo "org.jitsi.videobridge.rest.jetty.RewriteHandler.regex=^/([a-zA-Z0-9]+)$" >> $JVB_CONFIG
|
||||
echo "org.jitsi.videobridge.rest.jetty.RewriteHandler.replacement=/" >> $JVB_CONFIG
|
||||
echo "org.jitsi.videobridge.rest.jetty.SSIResourceHandler.paths=/" >> $JVB_CONFIG
|
||||
|
||||
202
debian/missing-source/libs/strophe/sha1.js
vendored
202
debian/missing-source/libs/strophe/sha1.js
vendored
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
|
||||
* in FIPS PUB 180-1
|
||||
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
|
||||
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
||||
* Distributed under the BSD License
|
||||
* See http://pajhome.org.uk/crypt/md5 for details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Configurable variables. You may need to tweak these to be compatible with
|
||||
* the server-side, but the defaults work in most cases.
|
||||
*/
|
||||
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
||||
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
|
||||
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
|
||||
|
||||
/*
|
||||
* These are the functions you'll usually want to call
|
||||
* They take string arguments and return either hex or base-64 encoded strings
|
||||
*/
|
||||
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
|
||||
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
|
||||
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
|
||||
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
|
||||
|
||||
/*
|
||||
* Perform a simple self-test to see if the VM is working
|
||||
*/
|
||||
function sha1_vm_test()
|
||||
{
|
||||
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the SHA-1 of an array of big-endian words, and a bit length
|
||||
*/
|
||||
function core_sha1(x, len)
|
||||
{
|
||||
/* append padding */
|
||||
x[len >> 5] |= 0x80 << (24 - len % 32);
|
||||
x[((len + 64 >> 9) << 4) + 15] = len;
|
||||
|
||||
var w = Array(80);
|
||||
var a = 1732584193;
|
||||
var b = -271733879;
|
||||
var c = -1732584194;
|
||||
var d = 271733878;
|
||||
var e = -1009589776;
|
||||
|
||||
for(var i = 0; i < x.length; i += 16)
|
||||
{
|
||||
var olda = a;
|
||||
var oldb = b;
|
||||
var oldc = c;
|
||||
var oldd = d;
|
||||
var olde = e;
|
||||
|
||||
for(var j = 0; j < 80; j++)
|
||||
{
|
||||
if(j < 16) w[j] = x[i + j];
|
||||
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
|
||||
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
|
||||
safe_add(safe_add(e, w[j]), sha1_kt(j)));
|
||||
e = d;
|
||||
d = c;
|
||||
c = rol(b, 30);
|
||||
b = a;
|
||||
a = t;
|
||||
}
|
||||
|
||||
a = safe_add(a, olda);
|
||||
b = safe_add(b, oldb);
|
||||
c = safe_add(c, oldc);
|
||||
d = safe_add(d, oldd);
|
||||
e = safe_add(e, olde);
|
||||
}
|
||||
return Array(a, b, c, d, e);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform the appropriate triplet combination function for the current
|
||||
* iteration
|
||||
*/
|
||||
function sha1_ft(t, b, c, d)
|
||||
{
|
||||
if(t < 20) return (b & c) | ((~b) & d);
|
||||
if(t < 40) return b ^ c ^ d;
|
||||
if(t < 60) return (b & c) | (b & d) | (c & d);
|
||||
return b ^ c ^ d;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the appropriate additive constant for the current iteration
|
||||
*/
|
||||
function sha1_kt(t)
|
||||
{
|
||||
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
|
||||
(t < 60) ? -1894007588 : -899497514;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the HMAC-SHA1 of a key and some data
|
||||
*/
|
||||
function core_hmac_sha1(key, data)
|
||||
{
|
||||
var bkey = str2binb(key);
|
||||
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
|
||||
|
||||
var ipad = Array(16), opad = Array(16);
|
||||
for(var i = 0; i < 16; i++)
|
||||
{
|
||||
ipad[i] = bkey[i] ^ 0x36363636;
|
||||
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
||||
}
|
||||
|
||||
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
|
||||
return core_sha1(opad.concat(hash), 512 + 160);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
||||
* to work around bugs in some JS interpreters.
|
||||
*/
|
||||
function safe_add(x, y)
|
||||
{
|
||||
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
||||
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
||||
return (msw << 16) | (lsw & 0xFFFF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bitwise rotate a 32-bit number to the left.
|
||||
*/
|
||||
function rol(num, cnt)
|
||||
{
|
||||
return (num << cnt) | (num >>> (32 - cnt));
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an 8-bit or 16-bit string to an array of big-endian words
|
||||
* In 8-bit function, characters >255 have their hi-byte silently ignored.
|
||||
*/
|
||||
function str2binb(str)
|
||||
{
|
||||
var bin = Array();
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < str.length * chrsz; i += chrsz)
|
||||
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
|
||||
return bin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a string
|
||||
*/
|
||||
function binb2str(bin)
|
||||
{
|
||||
var str = "";
|
||||
var mask = (1 << chrsz) - 1;
|
||||
for(var i = 0; i < bin.length * 32; i += chrsz)
|
||||
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a hex string.
|
||||
*/
|
||||
function binb2hex(binarray)
|
||||
{
|
||||
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i++)
|
||||
{
|
||||
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
|
||||
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert an array of big-endian words to a base-64 string
|
||||
*/
|
||||
function binb2b64(binarray)
|
||||
{
|
||||
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
var str = "";
|
||||
for(var i = 0; i < binarray.length * 4; i += 3)
|
||||
{
|
||||
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
|
||||
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
|
||||
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
|
||||
for(var j = 0; j < 4; j++)
|
||||
{
|
||||
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
|
||||
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
/**
|
||||
* Entity Capabilities (XEP-0115)
|
||||
*
|
||||
* Depends on disco plugin.
|
||||
*
|
||||
* See: http://xmpp.org/extensions/xep-0115.html
|
||||
*
|
||||
* Authors:
|
||||
* - Michael Weibel <michael.weibel@gmail.com>
|
||||
*
|
||||
* Copyright:
|
||||
* - Michael Weibel <michael.weibel@gmail.com>
|
||||
*/
|
||||
|
||||
Strophe.addConnectionPlugin('caps', {
|
||||
/** Constant: HASH
|
||||
* Hash used
|
||||
*
|
||||
* Currently only sha-1 is supported.
|
||||
*/
|
||||
HASH: 'sha-1',
|
||||
/** Variable: node
|
||||
* Client which is being used.
|
||||
*
|
||||
* Can be overwritten as soon as Strophe has been initialized.
|
||||
*/
|
||||
node: 'http://strophe.im/strophejs/',
|
||||
/** PrivateVariable: _ver
|
||||
* Own generated version string
|
||||
*/
|
||||
_ver: '',
|
||||
/** PrivateVariable: _connection
|
||||
* Strophe connection
|
||||
*/
|
||||
_connection: null,
|
||||
/** PrivateVariable: _knownCapabilities
|
||||
* A hashtable containing version-strings and their capabilities, serialized
|
||||
* as string.
|
||||
*
|
||||
* TODO: Maybe those caps shouldn't be serialized.
|
||||
*/
|
||||
_knownCapabilities: {},
|
||||
/** PrivateVariable: _jidVerIndex
|
||||
* A hashtable containing jids and their versions for better lookup of capabilities.
|
||||
*/
|
||||
_jidVerIndex: {},
|
||||
|
||||
/** Function: init
|
||||
* Initialize plugin:
|
||||
* - Add caps namespace
|
||||
* - Add caps feature to disco plugin
|
||||
* - Add handler for caps stanzas
|
||||
*
|
||||
* Parameters:
|
||||
* (Strophe.Connection) conn - Strophe connection
|
||||
*/
|
||||
init: function(conn) {
|
||||
this._connection = conn;
|
||||
|
||||
Strophe.addNamespace('CAPS', 'http://jabber.org/protocol/caps');
|
||||
|
||||
if (!this._connection.disco) {
|
||||
throw "Caps plugin requires the disco plugin to be installed.";
|
||||
}
|
||||
|
||||
this._connection.disco.addFeature(Strophe.NS.CAPS);
|
||||
this._connection.addHandler(this._delegateCapabilities.bind(this), Strophe.NS.CAPS);
|
||||
},
|
||||
|
||||
/** Function: generateCapsAttrs
|
||||
* Returns the attributes for generating the "c"-stanza containing the own version
|
||||
*
|
||||
* Returns:
|
||||
* (Object) - attributes
|
||||
*/
|
||||
generateCapsAttrs: function() {
|
||||
return {
|
||||
'xmlns': Strophe.NS.CAPS,
|
||||
'hash': this.HASH,
|
||||
'node': this.node,
|
||||
'ver': this.generateVer()
|
||||
};
|
||||
},
|
||||
|
||||
/** Function: generateVer
|
||||
* Returns the base64 encoded version string (encoded itself with sha1)
|
||||
*
|
||||
* Returns:
|
||||
* (String) - version
|
||||
*/
|
||||
generateVer: function() {
|
||||
if (this._ver !== "") {
|
||||
return this._ver;
|
||||
}
|
||||
|
||||
var ver = "",
|
||||
identities = this._connection.disco._identities.sort(this._sortIdentities),
|
||||
identitiesLen = identities.length,
|
||||
features = this._connection.disco._features.sort(),
|
||||
featuresLen = features.length;
|
||||
for(var i = 0; i < identitiesLen; i++) {
|
||||
var curIdent = identities[i];
|
||||
ver += curIdent.category + "/" + curIdent.type + "/" + curIdent.lang + "/" + curIdent.name + "<";
|
||||
}
|
||||
for(var i = 0; i < featuresLen; i++) {
|
||||
ver += features[i] + '<';
|
||||
}
|
||||
|
||||
this._ver = b64_sha1(ver);
|
||||
return this._ver;
|
||||
},
|
||||
|
||||
/** Function: getCapabilitiesByJid
|
||||
* Returns serialized capabilities of a jid (if available).
|
||||
* Otherwise null.
|
||||
*
|
||||
* Parameters:
|
||||
* (String) jid - Jabber id
|
||||
*
|
||||
* Returns:
|
||||
* (String|null) - capabilities, serialized; or null when not available.
|
||||
*/
|
||||
getCapabilitiesByJid: function(jid) {
|
||||
if (this._jidVerIndex[jid]) {
|
||||
return this._knownCapabilities[this._jidVerIndex[jid]];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/** PrivateFunction: _delegateCapabilities
|
||||
* Checks if the version has already been saved.
|
||||
* If yes: do nothing.
|
||||
* If no: Request capabilities
|
||||
*
|
||||
* Parameters:
|
||||
* (Strophe.Builder) stanza - Stanza
|
||||
*
|
||||
* Returns:
|
||||
* (Boolean)
|
||||
*/
|
||||
_delegateCapabilities: function(stanza) {
|
||||
var from = stanza.getAttribute('from'),
|
||||
c = stanza.querySelector('c'),
|
||||
ver = c.getAttribute('ver'),
|
||||
node = c.getAttribute('node');
|
||||
if (!this._knownCapabilities[ver]) {
|
||||
return this._requestCapabilities(from, node, ver);
|
||||
} else {
|
||||
this._jidVerIndex[from] = ver;
|
||||
}
|
||||
if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) {
|
||||
this._jidVerIndex[from] = ver;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/** PrivateFunction: _requestCapabilities
|
||||
* Requests capabilities from the one which sent the caps-info stanza.
|
||||
* This is done using disco info.
|
||||
*
|
||||
* Additionally, it registers a handler for handling the reply.
|
||||
*
|
||||
* Parameters:
|
||||
* (String) to - Destination jid
|
||||
* (String) node - Node attribute of the caps-stanza
|
||||
* (String) ver - Version of the caps-stanza
|
||||
*
|
||||
* Returns:
|
||||
* (Boolean) - true
|
||||
*/
|
||||
_requestCapabilities: function(to, node, ver) {
|
||||
if (to !== this._connection.jid) {
|
||||
var id = this._connection.disco.info(to, node + '#' + ver);
|
||||
this._connection.addHandler(this._handleDiscoInfoReply.bind(this), Strophe.NS.DISCO_INFO, 'iq', 'result', id, to);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/** PrivateFunction: _handleDiscoInfoReply
|
||||
* Parses the disco info reply and adds the version & it's capabilities to the _knownCapabilities variable.
|
||||
* Additionally, it adds the jid & the version to the _jidVerIndex variable for a better lookup.
|
||||
*
|
||||
* Parameters:
|
||||
* (Strophe.Builder) stanza - Disco info stanza
|
||||
*
|
||||
* Returns:
|
||||
* (Boolean) - false, to automatically remove the handler.
|
||||
*/
|
||||
_handleDiscoInfoReply: function(stanza) {
|
||||
var query = stanza.querySelector('query'),
|
||||
node = query.getAttribute('node').split('#'),
|
||||
ver = node[1],
|
||||
from = stanza.getAttribute('from');
|
||||
if (!this._knownCapabilities[ver]) {
|
||||
var childNodes = query.childNodes,
|
||||
childNodesLen = childNodes.length;
|
||||
this._knownCapabilities[ver] = [];
|
||||
for(var i = 0; i < childNodesLen; i++) {
|
||||
var node = childNodes[i];
|
||||
this._knownCapabilities[ver].push({name: node.nodeName, attributes: node.attributes});
|
||||
}
|
||||
this._jidVerIndex[from] = ver;
|
||||
} else if (!this._jidVerIndex[from] || !this._jidVerIndex[from] !== ver) {
|
||||
this._jidVerIndex[from] = ver;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/** PrivateFunction: _sortIdentities
|
||||
* Sorts two identities according the sorting requirements in XEP-0115.
|
||||
*
|
||||
* Parameters:
|
||||
* (Object) a - Identity a
|
||||
* (Object) b - Identity b
|
||||
*
|
||||
* Returns:
|
||||
* (Integer) - 1, 0 or -1; according to which one's greater.
|
||||
*/
|
||||
_sortIdentities: function(a, b) {
|
||||
if (a.category > b.category) {
|
||||
return 1;
|
||||
}
|
||||
if (a.category < b.category) {
|
||||
return -1;
|
||||
}
|
||||
if (a.type > b.type) {
|
||||
return 1;
|
||||
}
|
||||
if (a.type < b.type) {
|
||||
return -1;
|
||||
}
|
||||
if (a.lang > b.lang) {
|
||||
return 1;
|
||||
}
|
||||
if (a.lang < b.lang) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
232
debian/missing-source/libs/strophe/strophe.disco.js
vendored
232
debian/missing-source/libs/strophe/strophe.disco.js
vendored
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
Copyright 2010, François de Metz <francois@2metz.fr>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Disco Strophe Plugin
|
||||
* Implement http://xmpp.org/extensions/xep-0030.html
|
||||
* TODO: manage node hierarchies, and node on info request
|
||||
*/
|
||||
Strophe.addConnectionPlugin('disco',
|
||||
{
|
||||
_connection: null,
|
||||
_identities : [],
|
||||
_features : [],
|
||||
_items : [],
|
||||
/** Function: init
|
||||
* Plugin init
|
||||
*
|
||||
* Parameters:
|
||||
* (Strophe.Connection) conn - Strophe connection
|
||||
*/
|
||||
init: function(conn)
|
||||
{
|
||||
this._connection = conn;
|
||||
this._identities = [];
|
||||
this._features = [];
|
||||
this._items = [];
|
||||
// disco info
|
||||
conn.addHandler(this._onDiscoInfo.bind(this), Strophe.NS.DISCO_INFO, 'iq', 'get', null, null);
|
||||
// disco items
|
||||
conn.addHandler(this._onDiscoItems.bind(this), Strophe.NS.DISCO_ITEMS, 'iq', 'get', null, null);
|
||||
},
|
||||
/** Function: addIdentity
|
||||
* See http://xmpp.org/registrar/disco-categories.html
|
||||
* Parameters:
|
||||
* (String) category - category of identity (like client, automation, etc ...)
|
||||
* (String) type - type of identity (like pc, web, bot , etc ...)
|
||||
* (String) name - name of identity in natural language
|
||||
* (String) lang - lang of name parameter
|
||||
*
|
||||
* Returns:
|
||||
* Boolean
|
||||
*/
|
||||
addIdentity: function(category, type, name, lang)
|
||||
{
|
||||
for (var i=0; i<this._identities.length; i++)
|
||||
{
|
||||
if (this._identities[i].category == category &&
|
||||
this._identities[i].type == type &&
|
||||
this._identities[i].name == name &&
|
||||
this._identities[i].lang == lang)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this._identities.push({category: category, type: type, name: name, lang: lang});
|
||||
return true;
|
||||
},
|
||||
/** Function: addFeature
|
||||
*
|
||||
* Parameters:
|
||||
* (String) var_name - feature name (like jabber:iq:version)
|
||||
*
|
||||
* Returns:
|
||||
* boolean
|
||||
*/
|
||||
addFeature: function(var_name)
|
||||
{
|
||||
for (var i=0; i<this._features.length; i++)
|
||||
{
|
||||
if (this._features[i] == var_name)
|
||||
return false;
|
||||
}
|
||||
this._features.push(var_name);
|
||||
return true;
|
||||
},
|
||||
/** Function: removeFeature
|
||||
*
|
||||
* Parameters:
|
||||
* (String) var_name - feature name (like jabber:iq:version)
|
||||
*
|
||||
* Returns:
|
||||
* boolean
|
||||
*/
|
||||
removeFeature: function(var_name)
|
||||
{
|
||||
for (var i=0; i<this._features.length; i++)
|
||||
{
|
||||
if (this._features[i] === var_name){
|
||||
this._features.splice(i,1)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
/** Function: addItem
|
||||
*
|
||||
* Parameters:
|
||||
* (String) jid
|
||||
* (String) name
|
||||
* (String) node
|
||||
* (Function) call_back
|
||||
*
|
||||
* Returns:
|
||||
* boolean
|
||||
*/
|
||||
addItem: function(jid, name, node, call_back)
|
||||
{
|
||||
if (node && !call_back)
|
||||
return false;
|
||||
this._items.push({jid: jid, name: name, node: node, call_back: call_back});
|
||||
return true;
|
||||
},
|
||||
/** Function: info
|
||||
* Info query
|
||||
*
|
||||
* Parameters:
|
||||
* (Function) call_back
|
||||
* (String) jid
|
||||
* (String) node
|
||||
*/
|
||||
info: function(jid, node, success, error, timeout)
|
||||
{
|
||||
var attrs = {xmlns: Strophe.NS.DISCO_INFO};
|
||||
if (node)
|
||||
attrs.node = node;
|
||||
|
||||
var info = $iq({from:this._connection.jid,
|
||||
to:jid, type:'get'}).c('query', attrs);
|
||||
this._connection.sendIQ(info, success, error, timeout);
|
||||
},
|
||||
/** Function: items
|
||||
* Items query
|
||||
*
|
||||
* Parameters:
|
||||
* (Function) call_back
|
||||
* (String) jid
|
||||
* (String) node
|
||||
*/
|
||||
items: function(jid, node, success, error, timeout)
|
||||
{
|
||||
var attrs = {xmlns: Strophe.NS.DISCO_ITEMS};
|
||||
if (node)
|
||||
attrs.node = node;
|
||||
|
||||
var items = $iq({from:this._connection.jid,
|
||||
to:jid, type:'get'}).c('query', attrs);
|
||||
this._connection.sendIQ(items, success, error, timeout);
|
||||
},
|
||||
|
||||
/** PrivateFunction: _buildIQResult
|
||||
*/
|
||||
_buildIQResult: function(stanza, query_attrs)
|
||||
{
|
||||
var id = stanza.getAttribute('id');
|
||||
var from = stanza.getAttribute('from');
|
||||
var iqresult = $iq({type: 'result', id: id});
|
||||
|
||||
if (from !== null) {
|
||||
iqresult.attrs({to: from});
|
||||
}
|
||||
|
||||
return iqresult.c('query', query_attrs);
|
||||
},
|
||||
|
||||
/** PrivateFunction: _onDiscoInfo
|
||||
* Called when receive info request
|
||||
*/
|
||||
_onDiscoInfo: function(stanza)
|
||||
{
|
||||
var node = stanza.getElementsByTagName('query')[0].getAttribute('node');
|
||||
var attrs = {xmlns: Strophe.NS.DISCO_INFO};
|
||||
if (node)
|
||||
{
|
||||
attrs.node = node;
|
||||
}
|
||||
var iqresult = this._buildIQResult(stanza, attrs);
|
||||
for (var i=0; i<this._identities.length; i++)
|
||||
{
|
||||
var attrs = {category: this._identities[i].category,
|
||||
type : this._identities[i].type};
|
||||
if (this._identities[i].name)
|
||||
attrs.name = this._identities[i].name;
|
||||
if (this._identities[i].lang)
|
||||
attrs['xml:lang'] = this._identities[i].lang;
|
||||
iqresult.c('identity', attrs).up();
|
||||
}
|
||||
for (var i=0; i<this._features.length; i++)
|
||||
{
|
||||
iqresult.c('feature', {'var':this._features[i]}).up();
|
||||
}
|
||||
this._connection.send(iqresult.tree());
|
||||
return true;
|
||||
},
|
||||
/** PrivateFunction: _onDiscoItems
|
||||
* Called when receive items request
|
||||
*/
|
||||
_onDiscoItems: function(stanza)
|
||||
{
|
||||
var query_attrs = {xmlns: Strophe.NS.DISCO_ITEMS};
|
||||
var node = stanza.getElementsByTagName('query')[0].getAttribute('node');
|
||||
if (node)
|
||||
{
|
||||
query_attrs.node = node;
|
||||
var items = [];
|
||||
for (var i = 0; i < this._items.length; i++)
|
||||
{
|
||||
if (this._items[i].node == node)
|
||||
{
|
||||
items = this._items[i].call_back(stanza);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var items = this._items;
|
||||
}
|
||||
var iqresult = this._buildIQResult(stanza, query_attrs);
|
||||
for (var i = 0; i < items.length; i++)
|
||||
{
|
||||
var attrs = {jid: items[i].jid};
|
||||
if (items[i].name)
|
||||
attrs.name = items[i].name;
|
||||
if (items[i].node)
|
||||
attrs.node = items[i].node;
|
||||
iqresult.c('item', attrs).up();
|
||||
}
|
||||
this._connection.send(iqresult.tree());
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
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`.
|
||||
`YOURSECRET1`, `YOURSECRET2` and `YOURSECRET3`.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ N.B.: All commands are supposed to be run by root. If you are logged in as a reg
|
||||
|
||||
### 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 -
|
||||
echo 'deb https://download.jitsi.org stable/' >> /etc/apt/sources.list.d/jitsi-stable.list
|
||||
wget -qO - https://download.jitsi.org/jitsi-key.gpg.key | apt-key add -
|
||||
```
|
||||
|
||||
### Update the package lists
|
||||
@@ -48,8 +48,8 @@ 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
|
||||
wget https://download.jitsi.org/unstable/jigasi_1.0-107_amd64.deb
|
||||
dpkg -i jigasi_1.0-107_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.
|
||||
|
||||
2
images/spin.svg
Normal file
2
images/spin.svg
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg width='20px' height='20px' xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="uil-spin"><rect x="0" y="0" width="100" height="100" fill="none" class="bk"></rect><g transform="translate(50 50)"><g transform="rotate(0) translate(34 0)"><circle cx="0" cy="0" r="8" fill="#ffffff"><animate attributeName="opacity" from="1" to="0.1" begin="0s" dur="1s" repeatCount="indefinite"></animate><animateTransform attributeName="transform" type="scale" from="1.5" to="1" begin="0s" dur="1s" repeatCount="indefinite"></animateTransform></circle></g><g transform="rotate(45) translate(34 0)"><circle cx="0" cy="0" r="8" fill="#ffffff"><animate attributeName="opacity" from="1" to="0.1" begin="0.12s" dur="1s" repeatCount="indefinite"></animate><animateTransform attributeName="transform" type="scale" from="1.5" to="1" begin="0.12s" dur="1s" repeatCount="indefinite"></animateTransform></circle></g><g transform="rotate(90) translate(34 0)"><circle cx="0" cy="0" r="8" fill="#ffffff"><animate attributeName="opacity" from="1" to="0.1" begin="0.25s" dur="1s" repeatCount="indefinite"></animate><animateTransform attributeName="transform" type="scale" from="1.5" to="1" begin="0.25s" dur="1s" repeatCount="indefinite"></animateTransform></circle></g><g transform="rotate(135) translate(34 0)"><circle cx="0" cy="0" r="8" fill="#ffffff"><animate attributeName="opacity" from="1" to="0.1" begin="0.37s" dur="1s" repeatCount="indefinite"></animate><animateTransform attributeName="transform" type="scale" from="1.5" to="1" begin="0.37s" dur="1s" repeatCount="indefinite"></animateTransform></circle></g><g transform="rotate(180) translate(34 0)"><circle cx="0" cy="0" r="8" fill="#ffffff"><animate attributeName="opacity" from="1" to="0.1" begin="0.5s" dur="1s" repeatCount="indefinite"></animate><animateTransform attributeName="transform" type="scale" from="1.5" to="1" begin="0.5s" dur="1s" repeatCount="indefinite"></animateTransform></circle></g><g transform="rotate(225) translate(34 0)"><circle cx="0" cy="0" r="8" fill="#ffffff"><animate attributeName="opacity" from="1" to="0.1" begin="0.62s" dur="1s" repeatCount="indefinite"></animate><animateTransform attributeName="transform" type="scale" from="1.5" to="1" begin="0.62s" dur="1s" repeatCount="indefinite"></animateTransform></circle></g><g transform="rotate(270) translate(34 0)"><circle cx="0" cy="0" r="8" fill="#ffffff"><animate attributeName="opacity" from="1" to="0.1" begin="0.75s" dur="1s" repeatCount="indefinite"></animate><animateTransform attributeName="transform" type="scale" from="1.5" to="1" begin="0.75s" dur="1s" repeatCount="indefinite"></animateTransform></circle></g><g transform="rotate(315) translate(34 0)"><circle cx="0" cy="0" r="8" fill="#ffffff"><animate attributeName="opacity" from="1" to="0.1" begin="0.87s" dur="1s" repeatCount="indefinite"></animate><animateTransform attributeName="transform" type="scale" from="1.5" to="1" begin="0.87s" dur="1s" repeatCount="indefinite"></animateTransform></circle></g></g></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
83
index.html
83
index.html
@@ -3,26 +3,18 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
||||
<!--#include virtual="base.html" -->
|
||||
<!--#include virtual="title.html" -->
|
||||
<script>
|
||||
window.indexLoadedTime = window.performance.now();
|
||||
console.log("(TIME) index.html loaded:\t", indexLoadedTime);
|
||||
</script>
|
||||
<script><!--#include virtual="config.js" --></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
|
||||
<script><!--#include virtual="/config.js" --></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
|
||||
<script src="utils.js?v=1"></script>
|
||||
<!--#include virtual="connection_optimization/connection_optimization.html" -->
|
||||
<script src="connection_optimization/do_external_connect.js?v=1"></script>
|
||||
<script src="interface_config.js?v=6"></script>
|
||||
<script><!--#include virtual="/interface_config.js" --></script>
|
||||
<script src="libs/lib-jitsi-meet.min.js?v=139"></script>
|
||||
<script src="libs/app.bundle.min.js?v=139"></script>
|
||||
<link rel="icon" type="image/png" href="/images/favicon.ico?v=1"/>
|
||||
<meta property="og:title" content="Jitsi Meet"/>
|
||||
<meta property="og:image" content="/images/jitsilogo.png?v=1"/>
|
||||
<meta property="og:description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
|
||||
<meta description="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
|
||||
<meta itemprop="name" content="Jitsi Meet"/>
|
||||
<meta itemprop="description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
|
||||
<meta itemprop="image" content="/images/jitsilogo.png?v=1"/>
|
||||
<!--#include virtual="title.html" -->
|
||||
<link rel="stylesheet" href="css/all.css"/>
|
||||
<!--#include virtual="plugin.head.html" -->
|
||||
</head>
|
||||
@@ -174,7 +166,10 @@
|
||||
</div>
|
||||
<span id="videoConnectionMessage"></span>
|
||||
<span id="videoResolutionLabel">HD</span>
|
||||
<span id="recordingLabel" class="centeredVideoLabel"></span>
|
||||
<span id="recordingLabel" class="centeredVideoLabel">
|
||||
<span id="recordingLabelText"></span>
|
||||
<img id="recordingSpinner" class="recordingSpinner" src="images/spin.svg"></img>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div id="remoteVideos">
|
||||
@@ -196,7 +191,6 @@
|
||||
</i>
|
||||
</a>
|
||||
</span>
|
||||
<div class="bottom_button_separator"></div>
|
||||
<span class="bottomToolbar_span">
|
||||
<a class="bottomToolbarButton" id="bottom_toolbar_contact_list" data-container="body" data-toggle="popover" data-placement="top" id="contactlistpopover" data-i18n="[content]bottomtoolbar.contactlist" content="Open / close contact list">
|
||||
<i id="contactListButton" class="icon-contactList">
|
||||
@@ -204,7 +198,6 @@
|
||||
</i>
|
||||
</a>
|
||||
</span>
|
||||
<div class="bottom_button_separator"></div>
|
||||
<span class="bottomToolbar_span">
|
||||
<a class="bottomToolbarButton" id="bottom_toolbar_film_strip" data-container="body" data-toggle="popover" shortcut="filmstripPopover" data-placement="top" data-i18n="[content]bottomtoolbar.filmstrip" content="Show / hide film strip">
|
||||
<i id="filmStripButton" class="icon-filmstrip"></i>
|
||||
@@ -286,67 +279,7 @@
|
||||
<div id="keyboard-shortcuts" class="keyboard-shortcuts" style="display:none;">
|
||||
<div class="header"><h3 data-i18n="keyboardShortcuts.keyboardShortcuts"></h3></div>
|
||||
<div class="content">
|
||||
<ul class="item">
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">M</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.mute"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">V</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.videoMute"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">C</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.toggleChat"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">R</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.raiseHand"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">T</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.pushToTalk"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">D</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.toggleScreensharing"></span>
|
||||
</li>
|
||||
<li class="item-details">
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">F</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.toggleFilmstrip"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">?</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.toggleShortcuts"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">0</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.focusLocal"></span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="item-action">
|
||||
<kbd class="regular-key">1-9</kbd>
|
||||
</span>
|
||||
<span class="item-description" data-i18n="keyboardShortcuts.focusRemote"></span>
|
||||
</li>
|
||||
<ul id="keyboard-shortcuts-list" class="item">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,10 +14,9 @@ var interfaceConfig = {
|
||||
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
|
||||
APP_NAME: "Jitsi Meet",
|
||||
INVITATION_POWERED_BY: true,
|
||||
TOOLBAR_BUTTONS: ['authentication', 'microphone', 'camera', 'desktop',
|
||||
'recording', 'security', 'invite', 'chat', 'etherpad', 'sharedvideo',
|
||||
'fullscreen', 'sip', 'dialpad', 'settings', 'hangup', 'filmstrip',
|
||||
'contacts'],
|
||||
// the toolbar buttons line is intentionally left in one line, to be able
|
||||
// to easily override values or remove them using regex
|
||||
TOOLBAR_BUTTONS: ['authentication', 'microphone', 'camera', 'desktop', 'recording', 'security', 'invite', 'chat', 'etherpad', 'sharedvideo', 'fullscreen', 'sip', 'dialpad', 'settings', 'hangup', 'filmstrip', 'contacts'], // jshint ignore:line
|
||||
// Determines how the video would fit the screen. 'both' would fit the whole
|
||||
// screen, 'height' would fit the original video height to the height of the
|
||||
// screen, 'width' would fit the original video width to the width of the
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
"en": "Английски",
|
||||
"bg": "Български",
|
||||
"de": "Немски",
|
||||
"tr": "Турски",
|
||||
"it": "Италиански",
|
||||
"es": "",
|
||||
"fr": "Френски",
|
||||
"hy": "",
|
||||
"it": "Италиански",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "Словашки",
|
||||
"sl": "Словенски",
|
||||
"sk": "Словашки"
|
||||
"sv": "Шведски",
|
||||
"tr": "Турски"
|
||||
}
|
||||
@@ -2,10 +2,14 @@
|
||||
"en": "Englisch",
|
||||
"bg": "Bulgarisch",
|
||||
"de": "Deutsch",
|
||||
"tr": "Türkisch",
|
||||
"it": "Italienisch",
|
||||
"es": "Spanisch",
|
||||
"fr": "Französisch",
|
||||
"sl": "Slowenisch",
|
||||
"hy": "Armenisch",
|
||||
"it": "Italienisch",
|
||||
"oc": "Okzitanisch",
|
||||
"ptBR": "Portugiesisch (Brasilien)",
|
||||
"sk": "Slowakisch",
|
||||
"sv": "Schwedisch"
|
||||
"sl": "Slowenisch",
|
||||
"sv": "Schwedisch",
|
||||
"tr": "Türkisch"
|
||||
}
|
||||
@@ -2,9 +2,14 @@
|
||||
"en": "Inglés",
|
||||
"bg": "Búlgaro",
|
||||
"de": "Alemán",
|
||||
"tr": "Turco",
|
||||
"it": "Italiano",
|
||||
"es": "",
|
||||
"fr": "Francés",
|
||||
"hy": "",
|
||||
"it": "Italiano",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "Eslovaco",
|
||||
"sl": "Esloveno",
|
||||
"sk": "Eslovaco"
|
||||
"sv": "Sueco",
|
||||
"tr": "Turco"
|
||||
}
|
||||
@@ -2,10 +2,14 @@
|
||||
"en": "Anglais",
|
||||
"bg": "Bulgare",
|
||||
"de": "Allemand",
|
||||
"tr": "Turc",
|
||||
"it": "Italien",
|
||||
"es": "Espagnol",
|
||||
"fr": "Français",
|
||||
"sl": "Slovène",
|
||||
"hy": "Arménien",
|
||||
"it": "Italien",
|
||||
"oc": "Occitan",
|
||||
"ptBR": "Portugais (Brésil)",
|
||||
"sk": "Slovaque",
|
||||
"sv": "Suédois"
|
||||
"sl": "Slovène",
|
||||
"sv": "Suédois",
|
||||
"tr": "Turc"
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
{
|
||||
"en": "",
|
||||
"bg": "",
|
||||
"de": "",
|
||||
"tr": "",
|
||||
"it": "",
|
||||
"fr": "",
|
||||
"sl": "",
|
||||
"sk": "",
|
||||
"sv": ""
|
||||
"en": "Անգլերեն",
|
||||
"bg": "Բուլղարերեն",
|
||||
"de": "Գերմաներեն ",
|
||||
"es": "",
|
||||
"fr": "Ֆրանսերեն",
|
||||
"hy": "",
|
||||
"it": "Իտալերեն",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "Սլովակերեն",
|
||||
"sl": "Սլովեներեն ",
|
||||
"sv": "Շվեդերեն ",
|
||||
"tr": "Թուրքերեն"
|
||||
}
|
||||
@@ -2,6 +2,14 @@
|
||||
"en": "Inglese",
|
||||
"bg": "Bulgaro",
|
||||
"de": "Tedesco",
|
||||
"tr": "Turco",
|
||||
"it": "Italiano"
|
||||
"es": "",
|
||||
"fr": "Francese",
|
||||
"hy": "",
|
||||
"it": "Italiano",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "Slovacco",
|
||||
"sl": "Sloveno",
|
||||
"sv": "",
|
||||
"tr": "Turco"
|
||||
}
|
||||
@@ -1,10 +1,15 @@
|
||||
{
|
||||
"en": "",
|
||||
"bg": "",
|
||||
"de": "",
|
||||
"tr": "",
|
||||
"it": "",
|
||||
"fr": "",
|
||||
"sl": "",
|
||||
"sk": ""
|
||||
"en": "Anglés",
|
||||
"bg": "Bulgar",
|
||||
"de": "Aleman",
|
||||
"es": "",
|
||||
"fr": "Francés",
|
||||
"hy": "",
|
||||
"it": "Italian",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "Eslovac",
|
||||
"sl": "Eslovèn",
|
||||
"sv": "Suedés",
|
||||
"tr": "Turc"
|
||||
}
|
||||
15
lang/languages-ptBR.json
Normal file
15
lang/languages-ptBR.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"en": "Inglês",
|
||||
"bg": "Búlgaro",
|
||||
"de": "Alemão",
|
||||
"es": "Espanhol",
|
||||
"fr": "Francês",
|
||||
"hy": "Armênio",
|
||||
"it": "Italiano",
|
||||
"oc": "Provençal",
|
||||
"ptBR": "Português (Brasil)",
|
||||
"sk": "Eslovaco",
|
||||
"sl": "Esloveno",
|
||||
"sv": "Sueco",
|
||||
"tr": "Turco"
|
||||
}
|
||||
15
lang/languages-ru.json
Normal file
15
lang/languages-ru.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"en": "",
|
||||
"bg": "",
|
||||
"de": "",
|
||||
"es": "",
|
||||
"fr": "",
|
||||
"hy": "",
|
||||
"it": "",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "",
|
||||
"sl": "",
|
||||
"sv": "",
|
||||
"tr": ""
|
||||
}
|
||||
@@ -2,9 +2,14 @@
|
||||
"en": "Angličtina",
|
||||
"bg": "Bulharština",
|
||||
"de": "Nemčina",
|
||||
"tr": "Turečtina",
|
||||
"it": "Taliančina",
|
||||
"es": "",
|
||||
"fr": "Francúžtina",
|
||||
"hy": "",
|
||||
"it": "Taliančina",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "Slovenčina",
|
||||
"sl": "Slovinčina",
|
||||
"sk": "Slovenčina"
|
||||
"sv": "",
|
||||
"tr": "Turečtina"
|
||||
}
|
||||
@@ -2,8 +2,14 @@
|
||||
"en": "Angleščina",
|
||||
"bg": "Bolgarščina",
|
||||
"de": "Nemščina",
|
||||
"tr": "Turščina",
|
||||
"it": "Italjanščina",
|
||||
"es": "",
|
||||
"fr": "Francoščina",
|
||||
"sl": ""
|
||||
"hy": "",
|
||||
"it": "Italjanščina",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "",
|
||||
"sl": "Slovenščina",
|
||||
"sv": "",
|
||||
"tr": "Turščina"
|
||||
}
|
||||
@@ -2,9 +2,14 @@
|
||||
"en": "Engelska",
|
||||
"bg": "Bulgariska",
|
||||
"de": "Tyska",
|
||||
"tr": "Turkiska",
|
||||
"it": "Italienska",
|
||||
"es": "",
|
||||
"fr": "Franska",
|
||||
"hy": "",
|
||||
"it": "Italienska",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "Slovakiska",
|
||||
"sl": "Slovenska",
|
||||
"sk": "Slovakiska"
|
||||
"sv": "",
|
||||
"tr": "Turkiska"
|
||||
}
|
||||
@@ -1,5 +1,15 @@
|
||||
{
|
||||
"en": "İngilizce",
|
||||
"bg": "Bulgarca",
|
||||
"de": "Almanca"
|
||||
"de": "Almanca",
|
||||
"es": "",
|
||||
"fr": "",
|
||||
"hy": "",
|
||||
"it": "",
|
||||
"oc": "",
|
||||
"ptBR": "",
|
||||
"sk": "",
|
||||
"sl": "",
|
||||
"sv": "",
|
||||
"tr": ""
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
"hy": "Armenian",
|
||||
"it": "Italian",
|
||||
"oc": "Occitan",
|
||||
"ptBR": "Portuguese (Brazil)",
|
||||
"sk": "Slovak",
|
||||
"sl": "Slovenian",
|
||||
"sv": "Swedish",
|
||||
|
||||
@@ -8,12 +8,37 @@
|
||||
"participant": "Участник",
|
||||
"me": "аз",
|
||||
"speaker": "Говорител",
|
||||
"defaultNickname": "например __name__",
|
||||
"defaultPreziLink": "например __url__",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "Яна Розова",
|
||||
"defaultLink": "например __url__",
|
||||
"calling": "Обаждане към __name__ ...",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "Клавишни комбинации:",
|
||||
"raiseHand": "Вдигни ръка.",
|
||||
"pushToTalk": "Push to talk.",
|
||||
"toggleScreensharing": "Смяна между камера и споделен екран.",
|
||||
"toggleFilmstrip": "Показване/скриване на лентата с видеата.",
|
||||
"toggleShortcuts": "Показване/скриване на това меню.",
|
||||
"focusLocal": "Фокусиране върху нашето видео.",
|
||||
"focusRemote": "Фокусиране върху видео на участник.",
|
||||
"toggleChat": "Отваряне/скриване на чат панела.",
|
||||
"mute": "Спиране/пускане на микрофона.",
|
||||
"videoMute": "Спиране/пускане на нашето видео."
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "Влез",
|
||||
"roomname": "Въведете име на стаята",
|
||||
"disable": "Не показвай страницата следващия път",
|
||||
"disable": "Не показвай повече тази страница",
|
||||
"feature1": {
|
||||
"title": "Лесен за употреба",
|
||||
"content": "Не е необходимо да сваляте нищо. _app_ работи директно във вашия браузър. Просто споделете адреса на вашата конференция с другите за да започнете."
|
||||
@@ -51,12 +76,11 @@
|
||||
"mute": "Включи / Изключи микрофона",
|
||||
"videomute": "Включи / Изключи камерата",
|
||||
"authenticate": "Идентификация",
|
||||
"record": "Запис",
|
||||
"lock": "Заключи / отключи стаята",
|
||||
"invite": "Покани други",
|
||||
"chat": "Отвори / затвори чат",
|
||||
"prezi": "Сподели Prezi",
|
||||
"etherpad": "Покажи споделения документ",
|
||||
"sharedvideo": "Сподели YouTube видео",
|
||||
"sharescreen": "Сподели екрана",
|
||||
"fullscreen": "Влез / Излез от Пълен екран",
|
||||
"sip": "Обади се на SIP номер",
|
||||
@@ -64,7 +88,12 @@
|
||||
"hangup": "Затвори",
|
||||
"login": "Влез",
|
||||
"logout": "Изход",
|
||||
"dialpad": "Цифров панел"
|
||||
"dialpad": "Цифров панел",
|
||||
"sharedVideoMutedPopup": "Споделеното видео е заглуено,<br/>, за да можете да говорите.",
|
||||
"micMutedPopup": "Микрофонът е заглушен, за да<br/>не пречи на YouTube видеото.",
|
||||
"unableToUnmutePopup": "Не се говори по време на филм!",
|
||||
"cameraDisabled": "Не е налична камера",
|
||||
"micDisabled": "Не е наличен микрофон"
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Отвори / затвори чат",
|
||||
@@ -82,8 +111,15 @@
|
||||
"title": "НАСТРОЙКИ",
|
||||
"update": "Актуализиране",
|
||||
"name": "Име",
|
||||
"startAudioMuted": "започни без аудио",
|
||||
"startVideoMuted": "започни без видео"
|
||||
"startAudioMuted": "Започни без аудио",
|
||||
"startVideoMuted": "Започни без видео",
|
||||
"selectCamera": "Избери камера",
|
||||
"selectMic": "Избери микрофон",
|
||||
"selectAudioOutput": "Избери аудио изход",
|
||||
"followMe": "Включи \"следвай ме\"",
|
||||
"noDevice": "Няма",
|
||||
"noPermission": "Не е разрешен достъп до устройството",
|
||||
"avatarUrl": "Адрес на аватар"
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Натиснете за да<br/>промените името",
|
||||
@@ -92,7 +128,8 @@
|
||||
"mute": "Учасника е с изключен микрофон",
|
||||
"kick": "Изгони",
|
||||
"muted": "Изключен микрофон",
|
||||
"domute": "Изключи микрофона"
|
||||
"domute": "Изключи микрофона",
|
||||
"flip": "Огледално"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Дебит:",
|
||||
@@ -124,7 +161,8 @@
|
||||
"grantedTo": "Даване на роля модератор на __to__!",
|
||||
"grantedToUnknown": "Даване на роля модератор на $t(somebody)!",
|
||||
"muted": "Започвате разговора без звук.",
|
||||
"mutedTitle": "Звукът ви е спрян!"
|
||||
"mutedTitle": "Звукът ви е спрян!",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "Бяхте изгонен от срещата!",
|
||||
@@ -139,6 +177,8 @@
|
||||
"failtoinstall": "Неуспешна инсталация на разширението за споделяне на екрана.",
|
||||
"failedpermissions": "Неуспешен опит за получаване на права за използване на микрофон и/или камера.",
|
||||
"bridgeUnavailable": "Jitsi Videobridge не е наличен. Моля опитайте пак!",
|
||||
"jicofoUnavailable": "Jitsi Videobridge не е наличен. Моля опитайте пак!",
|
||||
"maxUsersLimitReached": "Конференцията е пълна. Моля, опитайте по-късно!",
|
||||
"lockTitle": "Неуспешно заключване",
|
||||
"lockMessage": "Неуспешно заключване на конференцията.",
|
||||
"warning": "Внимание",
|
||||
@@ -152,11 +192,12 @@
|
||||
"defaultError": "Възникна грешка",
|
||||
"passwordRequired": "Изисква се парола",
|
||||
"Ok": "ОК",
|
||||
"removePreziTitle": "Премахни Prezi",
|
||||
"removePreziMsg": "Сигурни ли сте, че искате да премахнете Prezi?",
|
||||
"sharePreziTitle": "Сподели Prezi",
|
||||
"sharePreziMsg": "Prezi string delete",
|
||||
"Remove": "DELETE DELETE DELETE DELETE DELETE DELETE DELETE DELETE DELETE DELETE ",
|
||||
"shareVideoTitle": "Сподели видео",
|
||||
"shareVideoLinkError": "Моля въведете правилен Prezi линк.",
|
||||
"removeSharedVideoTitle": "Край на споделянето на видео",
|
||||
"removeSharedVideoMsg": "Сигурни ли сте, че искате да премахнете Prezi?",
|
||||
"alreadySharedVideoMsg": "Друг участник вече споделя видео. Споделянето е възможно само по веднъж на стая.",
|
||||
"WaitingForHost": "Чакаме домакина ...",
|
||||
"WaitForHostMsg": "<b>__room__ </b> още не е започнал. Ако вие сте домакина моля идентифицирайте се. В противен случай ще изчакаме домакина.",
|
||||
"IamHost": "Аз съм домакина",
|
||||
@@ -168,8 +209,8 @@
|
||||
"hungUp": "Затворихте",
|
||||
"joinAgain": "Присъединете се отново",
|
||||
"Share": "Споделяне",
|
||||
"preziLinkError": "Моля въведете правилен Prezi линк.",
|
||||
"Save": "Запазване",
|
||||
"recording": "Запис",
|
||||
"recordingToken": "Въведете код за достъп за запис на конференцията",
|
||||
"Dial": "Набиране",
|
||||
"sipMsg": "Въведете SIP номер",
|
||||
@@ -196,7 +237,28 @@
|
||||
"firefoxExtensionPrompt": "За да споделите екрана си, трябва да инсталирате Firefox разширение. <a href='__url__'>свалете го тук</a> и пробвайте пак!",
|
||||
"feedbackQuestion": "Как мина разговора?",
|
||||
"thankYou": "Благодарим, че използвахте __appName__!",
|
||||
"sorryFeedback": "Много съжаляваме! Бихте ли ни казали повече?"
|
||||
"sorryFeedback": "Много съжаляваме! Бихте ли ни казали повече?",
|
||||
"liveStreaming": "Пряко предаване",
|
||||
"streamKey": "Имке/ключ на потока",
|
||||
"startLiveStreaming": "Пряко предаване",
|
||||
"stopStreamingWarning": "Наистина ли искате да спрем прякото предаване?",
|
||||
"stopRecordingWarning": "Наистина ли искате да спрем записа?",
|
||||
"stopLiveStreaming": "Край на прякото предаване",
|
||||
"stopRecording": "Край на записа",
|
||||
"doNotShowWarningAgain": "Занапред не ме предупреждавай пак",
|
||||
"permissionDenied": "Достъпът е отказан",
|
||||
"screenSharingPermissionDeniedError": "Не сте дали права за споделяне на екран",
|
||||
"micErrorPresent": "Грешка при достъп до микрофона",
|
||||
"cameraErrorPresent": "Грешка при достъп до камерата.",
|
||||
"cameraUnsupportedResolutionError": "Камерата ви не поддържа тази резолюция",
|
||||
"cameraUnknownError": "Невъзможен достъп до камерата по неясна причина.",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "Указаната камера не е намерена.",
|
||||
"cameraConstraintFailedError": "Камерата ви не задоволява зададените условия.",
|
||||
"micUnknownError": "Не възможен достъп до микрофона по неясна причина.",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "Микрофонът не задоволява зададените условия.",
|
||||
"micConstraintFailedError": "Микрофонът не задоволява зададените условия."
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
@@ -236,8 +298,23 @@
|
||||
"ATTACHED": "Прикрепен"
|
||||
},
|
||||
"recording": {
|
||||
"toaster": "В момента записваме!",
|
||||
"pending": "Записът ви ще започне щом влезе втори участник",
|
||||
"on": "Записът започна"
|
||||
"pending": "Записът изчаква участник.",
|
||||
"on": "Запис",
|
||||
"off": "Записът спрян",
|
||||
"failedToStart": "Неуспешен опит за записване",
|
||||
"buttonTooltip": "Пускане / спиране на запис",
|
||||
"error": "Грешка при опит за запис. Моля опитайте отново.",
|
||||
"unavailable": "Записите са временно невъзможни. Моля опитайте по-късно."
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "Започва пряко предаване...",
|
||||
"on": "Пряко предаване",
|
||||
"off": "Край на прякото предаване",
|
||||
"unavailable": "Услугата за пряко предаване е временно недостъпна. Опитайте по-късно.",
|
||||
"failedToStart": "Неуспешен опит за пряко предаване",
|
||||
"buttonTooltip": "Начало / край на пряко предаване",
|
||||
"streamIdRequired": "Моля попълнете името на потока, за да можем да започнем прякото предаване.",
|
||||
"error": "Неуспешно пряко предаване. Опитайте пак.",
|
||||
"busy": "Всички записвачки са временно заети. Опитайте отново по-късно."
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,20 @@
|
||||
"participant": "Teilnehmer",
|
||||
"me": "ich",
|
||||
"speaker": "Sprecher",
|
||||
"raisedHand": "Möchte sprechen",
|
||||
"defaultNickname": "Bsp: Heidi Blau",
|
||||
"defaultLink": "Bsp.: __url__",
|
||||
"calling": "Rufe __name__ an...",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "Bitte Berechtigungen zur Verwendung der Kamera und des Mikrofons durch anwählen von <b><i>Erlauben</i></b>",
|
||||
"chromeGrantPermissions": "Bitte Berechtigungen zur Verwendung der Kamera und des Mikrofons durch anwählen von <b><i>Erlauben</i></b>",
|
||||
"androidGrantPermissions": "Bitte Berechtigungen zur Verwendung der Kamera und des Mikrofons durch anwählen von <b><i>Erlauben</i></b>",
|
||||
"firefoxGrantPermissions": "Bitte Berechtigungen zur Verwendung der Kamera und des Mikrofons durch anwählen von <b><i>Ausgewähltes Gerät freigeben</i></b>",
|
||||
"operaGrantPermissions": "Bitte Berechtigungen zur Verwendung der Kamera und des Mikrofons durch anwählen von <b><i>Erlauben</i></b>",
|
||||
"iexplorerGrantPermissions": "Bitte Berechtigung zur Verwendung der Kamera und des Mikrofons durch anwählen von <b><i>OK</i></b> erteilen",
|
||||
"safariGrantPermissions": "Bitte Berechtigung zur Verwendung der Kamera und des Mikrofons durch anwählen von <b><i>OK</i></b> erteilen",
|
||||
"nwjsGrantPermissions": "Bitte Berechtigungen zur Verwendung der Kamera und des Mikrofons erteilen"
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "Tastaturkürzel:",
|
||||
"raiseHand": "Heben Sie Ihre Hand.",
|
||||
@@ -150,7 +161,8 @@
|
||||
"grantedTo": "Moderatorenrechte an __to__ vergeben.",
|
||||
"grantedToUnknown": "Moderatorenrechte an $t(somebody) vergeben.",
|
||||
"muted": "Der Konferenz wurde stumm beigetreten.",
|
||||
"mutedTitle": "Stummschaltung aktiv!"
|
||||
"mutedTitle": "Stummschaltung aktiv!",
|
||||
"raisedHand": "Möchte sprechen."
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "Oh! Sie wurden aus der Konferenz ausgeschlossen.",
|
||||
@@ -240,11 +252,11 @@
|
||||
"cameraErrorPresent": "Fehler beim Verbinden zur Kamera.",
|
||||
"cameraUnsupportedResolutionError": "Die Kamera unterstützt die erforderliche Auflösung nicht.",
|
||||
"cameraUnknownError": "Die Kamera kann aus einem unbekannten Grund nicht verwendet werden.",
|
||||
"cameraPermissionDeniedError": "Sie haben die Berechtigung für die Benutzung der Kamera nicht erteilt.",
|
||||
"cameraNotFoundError": "Die angeforderte Kamera konnte nicht gefunden werden.",
|
||||
"cameraPermissionDeniedError": "Die Berechtigung zur Verwendung der Kamera wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht sehen. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste um die Berechtigungen zu erteilen.",
|
||||
"cameraNotFoundError": "Die Berechtigung zur Verwendung der Kamera wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht sehen. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste um die Berechtigungen zu erteilen.",
|
||||
"cameraConstraintFailedError": "Ihre Kamera erfüllt die notwendigen Anforderungen nicht.",
|
||||
"micUnknownError": "Das Mikrofon kann aus einem unbekannten Grund nicht verwendet werden.",
|
||||
"micPermissionDeniedError": "Sie haben die Berechtigung für die Benutzung des Mikrofons nicht erteilt.",
|
||||
"micPermissionDeniedError": "Die Berechtigung zur Verwendung des Mikrofons wurde nicht erteilt. Sie können trotzdem an der Konferenz teilnehmen, aber die anderen Teilnehmer können Sie nicht hören. Verwenden Sie die Kamera-Schaltfläche in der Adressleiste um die Berechtigungen zu erteilen.",
|
||||
"micNotFoundError": "Das angeforderte Mikrofon konnte nicht gefunden werden.",
|
||||
"micConstraintFailedError": "Ihr Mikrofon erfüllt die notwendigen Anforderungen nicht."
|
||||
},
|
||||
|
||||
@@ -2,25 +2,50 @@
|
||||
"contactlist": "LISTA DE CONTACTOS",
|
||||
"connectionsettings": "Ajustes de la conexión",
|
||||
"poweredby": "impulsado por",
|
||||
"downloadlogs": "Descargar bitácora",
|
||||
"downloadlogs": "Descargar logs",
|
||||
"feedback": "Danos tu opinión",
|
||||
"roomUrlDefaultMsg": "Tu conferencia está siendo creada...",
|
||||
"participant": "Participante",
|
||||
"me": "yo",
|
||||
"speaker": "Orador",
|
||||
"defaultNickname": "ej. __name__",
|
||||
"defaultPreziLink": "ej. __url__",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "ej. Juana Rosas",
|
||||
"defaultLink": "ej. __url__",
|
||||
"calling": "Llamando __nombre__ ...",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "Atajos de teclado:",
|
||||
"raiseHand": "Levantar la mano.",
|
||||
"pushToTalk": "Presione para hablar.",
|
||||
"toggleScreensharing": "Cambiar entre cámara y compartir pantalla.",
|
||||
"toggleFilmstrip": "Mostrar u ocultar película.",
|
||||
"toggleShortcuts": "Muestra u oculta este menú de ayuda.",
|
||||
"focusLocal": "Enfocar el video local.",
|
||||
"focusRemote": "Enfocarse en uno de los videos remotos.",
|
||||
"toggleChat": "Abrir o cerrar panel de charlas.",
|
||||
"mute": "Activar o desactivar micrófono.",
|
||||
"videoMute": "Detener o iniciar el video local."
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "IR",
|
||||
"roomname": "Introduzca un nombre de sala:",
|
||||
"disable": "No mostrar esta página en el próximo acceso ",
|
||||
"disable": "No mostrar esta página otra vez",
|
||||
"feature1": {
|
||||
"title": "Sencillo de usar",
|
||||
"content": "No se requiere descargar nada. __app__ funciona directamente con tu navegador. Solo comparte el URL de tu conferencia con otros para comenzar."
|
||||
},
|
||||
"feature2": {
|
||||
"title": "Bajo Ancho de Banda",
|
||||
"content": "Videoconferencias con múltiples participantes con tan poco como 128 Kbps. Conferencias compartiendo pantalla y audio con mucho menos."
|
||||
"content": "Las Videoconferencias con múltiples participantes funcionan con tan solo 128 Kbps. Conferencias para compartir pantalla y audio son posibles con mucho menos."
|
||||
},
|
||||
"feature3": {
|
||||
"title": "Código abierto",
|
||||
@@ -32,39 +57,43 @@
|
||||
},
|
||||
"feature5": {
|
||||
"title": "Compartir pantalla",
|
||||
"content": "Es fácil de compartir su pantalla con otros. __app__ es ideal para presentaciones en línea, conferencias y sesiones de soporte técnico. "
|
||||
"content": "Es fácil compartir su pantalla con otros. __app__ es ideal para presentaciones en línea, conferencias y sesiones de soporte técnico."
|
||||
},
|
||||
"feature6": {
|
||||
"title": "Salas seguras",
|
||||
"content": "¿Necesita un poco de privacidad? Las salas de conferencias __app__ se pueden asegurar con una contraseña con el fin de excluir a los invitados no deseados y evitar interrupciones."
|
||||
"content": "¿Necesita un poco de privacidad? Las salas de conferencias __app__ se pueden asegurar con una contraseña con el fin de excluir a los invitados no deseados y evitar interrupciones."
|
||||
},
|
||||
"feature7": {
|
||||
"title": "Notas compartidas",
|
||||
"content": "__app__ incluye Etherpad, un editor de texto colaborativo, en tiempo real, que es genial para minutas de junta, redactar artículos, y más."
|
||||
"content": "__app__ incluye Etherpad, un editor de texto colaborativo, en tiempo real, que es genial para minutas de reuniones, redactar artículos, y más."
|
||||
},
|
||||
"feature8": {
|
||||
"title": "Estadísticas de uso",
|
||||
"content": "Conozca acerca de sus usuarios a través de una fácil integración con Piwik, Google Analytics, y otros sistemas de seguimiento y análisis de uso."
|
||||
"content": "Aprenda de sus usuarios a través de una fácil integración con Piwik, Google Analytics, y otros sistemas de seguimiento y análisis de uso."
|
||||
}
|
||||
},
|
||||
"toolbar": {
|
||||
"mute": "Silenciar / Activar",
|
||||
"mute": "Activar / Desactivar Silencio",
|
||||
"videomute": "Iniciar / detener cámara",
|
||||
"authenticate": "Autenticar",
|
||||
"record": "Grabar",
|
||||
"lock": "Bloquear / desbloquear sala",
|
||||
"invite": "Invitar a otros",
|
||||
"chat": "",
|
||||
"prezi": "Compartir Prezi",
|
||||
"etherpad": "Compartir Documento",
|
||||
"chat": "Abrir / cerrar chat",
|
||||
"etherpad": "Compartir documento",
|
||||
"sharedvideo": "Compartir un vídeo de YouTube",
|
||||
"sharescreen": "Compartir pantalla",
|
||||
"fullscreen": "Entrar / Salir de Pantalla completa",
|
||||
"sip": "Llamar a un número SIP",
|
||||
"Settings": "Ajustes",
|
||||
"hangup": "Colgar",
|
||||
"login": "Inicio de sesión",
|
||||
"logout": "",
|
||||
"dialpad": "Mostrar teclado de llamada"
|
||||
"logout": "Cerrar sesión",
|
||||
"dialpad": "Mostrar teclado de llamada",
|
||||
"sharedVideoMutedPopup": "Su vídeo compartido ha sido silenciado<br/>para que pueda hablar con otros participantes.",
|
||||
"micMutedPopup": "Su micrófono ha sido silenciado para que<br/>pueda disfrutar completamente de compartir su vídeo.",
|
||||
"unableToUnmutePopup": "No puede silenciar su micrófono mientras el vídeo compartido está activo.",
|
||||
"cameraDisabled": "Cámara no disponible",
|
||||
"micDisabled": "Micrófono no disponible"
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Abrir / cerrar chat",
|
||||
@@ -82,20 +111,28 @@
|
||||
"title": "CONFIGURAR",
|
||||
"update": "Actualizar",
|
||||
"name": "Nombre",
|
||||
"startAudioMuted": "iniciar sin audio",
|
||||
"startVideoMuted": "iniciar sin video"
|
||||
"startAudioMuted": "Iniciar sin audio",
|
||||
"startVideoMuted": "Iniciar sin vídeo",
|
||||
"selectCamera": "Seleccionar cámara",
|
||||
"selectMic": "Seleccionar micrófono",
|
||||
"selectAudioOutput": "Selecciona salida de audio",
|
||||
"followMe": "Habilitar sígueme",
|
||||
"noDevice": "Ninguno",
|
||||
"noPermission": "Permiso para usar el dispositivo no permitido",
|
||||
"avatarUrl": "URL del Avatar"
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Pica para editar tu <br/>nombre",
|
||||
"moderator": "El dueño de<br/>esta conferencia",
|
||||
"editnickname": "Click para editar tu <br/>nombre",
|
||||
"moderator": "El propietario de<br/>esta conferencia",
|
||||
"videomute": "Participante ha<br/>detenido la cámara.",
|
||||
"mute": "Participante está silenciado",
|
||||
"kick": "Expulsar",
|
||||
"muted": "Silenciado",
|
||||
"domute": "Silenciar"
|
||||
"domute": "Silenciar",
|
||||
"flip": "Voltear"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Frecuencia de bits:",
|
||||
"bitrate": "Tasa de bits:",
|
||||
"packetloss": "Pérdida de paquetes:",
|
||||
"resolution": "Resolución:",
|
||||
"less": "Mostrar menos",
|
||||
@@ -111,7 +148,7 @@
|
||||
"remoteaddress_plural": "Direcciones remotas:",
|
||||
"transport": "Transporte:",
|
||||
"bandwidth": "Ancho de banda estimado:",
|
||||
"na": "Volver aquí por información de la conexión, una vez que se inicia la conferencia"
|
||||
"na": "Volver aquí para ver información de la conexión, una vez que se inicia la conferencia"
|
||||
},
|
||||
"notify": {
|
||||
"disconnected": "desconectado",
|
||||
@@ -120,26 +157,29 @@
|
||||
"somebody": "Alguien",
|
||||
"me": "Yo",
|
||||
"focus": "Foco de conferencia",
|
||||
"focusFail": "__component__ not available - retry en __ms__ sec",
|
||||
"focusFail": "__component__ no disponible - reintentar en __ms__ seg",
|
||||
"grantedTo": "¡Derechos de moderador otorgados a __to__!",
|
||||
"grantedToUnknown": "¡Derechos de moderador otorgados a $t(somebody)!",
|
||||
"muted": "Haz iniciado la conversación silenciado.",
|
||||
"mutedTitle": "¡Estás silenciado!"
|
||||
"muted": "Has iniciado la conversación silenciado.",
|
||||
"mutedTitle": "¡Estás silenciado!",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "¡Auch! ¡Haz sido expulsado de la reunión!",
|
||||
"popupError": "Tu navegador está bloqueando las ventanas emergentes de este sitio. Por favor, activa las ventanas emergentes en la configuración de seguridad de su navegador y vuelva a intentarlo.",
|
||||
"passwordError": "Esta conversación está protegido con una contraseña. Sólo el propietario de la conferencia puede establecer una contraseña.",
|
||||
"passwordError2": "Esta conversación está protegido con una contraseña. Sólo el propietario de la conferencia puede establecer una contraseña.",
|
||||
"popupError": "Su navegador está bloqueando las ventanas emergentes de este sitio. Por favor, activa las ventanas emergentes en la configuración de seguridad del navegador y vuelva a intentarlo.",
|
||||
"passwordError": "Esta conversación está protegida con una contraseña. Sólo el propietario de la conferencia puede establecer una contraseña.",
|
||||
"passwordError2": "Esta conversación no está protegida con una contraseña. Sólo el propietario de la conferencia puede establecer una contraseña.",
|
||||
"connectError": "¡Uups! Algo salió mal y no pudimos conectarnos a la conferencia.",
|
||||
"connectErrorWithMsg": "¡Uups! Algo salió mal y no pudimos conectarnos a la conferencia: __msg__",
|
||||
"connecting": "",
|
||||
"error": "",
|
||||
"connecting": "Conectando",
|
||||
"error": "Error",
|
||||
"detectext": "Error al tratar de detectar la extensión de compartir escritorio.",
|
||||
"failtoinstall": "Fallo al instalar la extensión de compartir escritorio",
|
||||
"failedpermissions": "Fallo al obtener permisos para utilizar el micrófono y/o cámara de tu equipo.",
|
||||
"bridgeUnavailable": "Videobridge Jitsi no está actualmente disponible. ¡Por favor intente después!",
|
||||
"lockTitle": "Fallo al bloquear",
|
||||
"bridgeUnavailable": "Videobridge Jitsi no está actualmente disponible. ¡Por favor inténtelo más tarde!",
|
||||
"jicofoUnavailable": "Jicofo no está disponible actualmente. ¡Por favor inténtelo más tarde!",
|
||||
"maxUsersLimitReached": "El número máximo de participantes en la conferencia ha sido alcanzado. La conferencia está llena. ¡Por favor intente nuevamente más tarde!",
|
||||
"lockTitle": "El número máximo de participantes en la conferencia ha sido alcanzado. La conferencia está llena. ¡Por favor intente nuevamente más tarde!",
|
||||
"lockMessage": "No se pudo bloquear la conferencia.",
|
||||
"warning": "Advertencia",
|
||||
"passwordNotSupported": "No se soportan contraseñas para la sala. ",
|
||||
@@ -152,11 +192,12 @@
|
||||
"defaultError": "Hubo algún tipo de error",
|
||||
"passwordRequired": "Se necesita contraseña",
|
||||
"Ok": "Aceptar",
|
||||
"removePreziTitle": "Eliminar Prezi",
|
||||
"removePreziMsg": "¿Estas seguro que deseas eliminar tu Prezi?",
|
||||
"sharePreziTitle": "Compartir un Prezi",
|
||||
"sharePreziMsg": "Otro participante ya está compartiendo un Prezi. Esta conferencia permite sólo un Prezi a la vez.",
|
||||
"Remove": "Eliminar",
|
||||
"shareVideoTitle": "Compartir un vídeo",
|
||||
"shareVideoLinkError": "Por favor introduzca un enlace correcto de Youtube.",
|
||||
"removeSharedVideoTitle": "Eliminar video compartido",
|
||||
"removeSharedVideoMsg": "¿Estas seguro que deseas eliminar tu vídeo compartido?",
|
||||
"alreadySharedVideoMsg": "Otro participante esta ahora mismo compartiendo el vídeo. Esta conferencia permite sólo compartir un único vídeo a la vez.",
|
||||
"WaitingForHost": "Esperando al anfitrión...",
|
||||
"WaitForHostMsg": "La conferencia <b>__room__ </b> aún no inicia. Si usted es el anfitrión, por favor autentíquese. De lo contrario, por favor espere a que el anfitrión llegue.",
|
||||
"IamHost": "Yo soy el anfitrión",
|
||||
@@ -168,8 +209,8 @@
|
||||
"hungUp": "Colgaste",
|
||||
"joinAgain": "Unirse de nuevo",
|
||||
"Share": "Compartir",
|
||||
"preziLinkError": "Por favor indique una liga Prezi correcta. ",
|
||||
"Save": "Guardar",
|
||||
"recording": "Grabando",
|
||||
"recordingToken": "Introduzca el token de grabación",
|
||||
"Dial": "Marcar",
|
||||
"sipMsg": "Introduzca número SIP",
|
||||
@@ -196,7 +237,28 @@
|
||||
"firefoxExtensionPrompt": "Es necesario instalar una extensión para Firefox con el fin de utilizar la pantalla compartida. Por favor, inténtelo de nuevo después de que lo obtenga de aquí <a href='__url__'> </a>!",
|
||||
"feedbackQuestion": "¿Como fue su llamada?",
|
||||
"thankYou": "Gracias por usar __appName__!",
|
||||
"sorryFeedback": " Sentimos escuchar eso. ¿Quieres decirnos algo más?"
|
||||
"sorryFeedback": " Sentimos escuchar eso. ¿Quieres decirnos algo más?",
|
||||
"liveStreaming": "Emisión en Directo",
|
||||
"streamKey": "Nombre/clave de emisión",
|
||||
"startLiveStreaming": "Comenzar streaming en tiempo real",
|
||||
"stopStreamingWarning": "¿Estas seguro que quieres parar la retransmisión en directo?",
|
||||
"stopRecordingWarning": "¿Estás seguro que quieres parar la grabación?",
|
||||
"stopLiveStreaming": "Parar retransmisión en directo",
|
||||
"stopRecording": "Parar grabación",
|
||||
"doNotShowWarningAgain": "No volver a mostrar esta advertencia",
|
||||
"permissionDenied": "Permiso Denegado",
|
||||
"screenSharingPermissionDeniedError": "No ha otorgado permiso para compartir su pantalla.",
|
||||
"micErrorPresent": "Hubo un error conectando su micrófono.",
|
||||
"cameraErrorPresent": "Hubo un error conectando su cámara.",
|
||||
"cameraUnsupportedResolutionError": "Su cámara no soporta la resolución de video.",
|
||||
"cameraUnknownError": "No se puede usar su cámara por motivos desconocidos.",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "No se encontró la cámara.",
|
||||
"cameraConstraintFailedError": "Su cámara no cumple los requerimientos.",
|
||||
"micUnknownError": "No se puede usar su micrófono por motivos desconocidos.",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "No se encontró el micrófono.",
|
||||
"micConstraintFailedError": "Su micrófono no cumple los requerimientos."
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
@@ -239,8 +301,23 @@
|
||||
"ATTACHED": "Adjunto"
|
||||
},
|
||||
"recording": {
|
||||
"toaster": "¡Actualmente Grabando! ",
|
||||
"pending": "Tu grabación se iniciará tan pronto como otro participante se una",
|
||||
"on": "La grabación ha iniciado"
|
||||
"pending": "La grabación esta esperando la entrada de un participante...",
|
||||
"on": "Grabando",
|
||||
"off": "Grabación parada",
|
||||
"failedToStart": "No se pudo iniciar la grabación",
|
||||
"buttonTooltip": "Iniciar / parar grabación",
|
||||
"error": "Falla de grabación. Vuelva a intentarlo.",
|
||||
"unavailable": "El servicio de grabación no está disponible. Inténtelo más tarde."
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "Iniciando Emisión en Directo",
|
||||
"on": "Emisión en Directo",
|
||||
"off": "Emisión en Directo Detenida",
|
||||
"unavailable": "El servicio de emisión en directo no está disponible actualmente. Por favor inténtelo de nuevo más tarde.",
|
||||
"failedToStart": "La emisión en Directo falló al iniciar",
|
||||
"buttonTooltip": "Iniciar / parar emisión en directo",
|
||||
"streamIdRequired": "Por favor introduzca el id de emisión para poder lanzar la emisión en directo",
|
||||
"error": "Falló el video en vivo. Por favor, vuelva a intentarlo.",
|
||||
"busy": "Todos los grabadores están ocupados. Por favor intente más tarde."
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,33 @@
|
||||
"participant": "Participant",
|
||||
"me": "moi",
|
||||
"speaker": "Haut-parleur",
|
||||
"raisedHand": "Aimerais prendre la parole",
|
||||
"defaultNickname": "ex. Jean Dupont",
|
||||
"defaultLink": "ex. __url__",
|
||||
"calling": "Appel __nom__ ...",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "Merci d'autoriser le partage de votre camera et microphone en appuyant sur le bouton <b><i>Autoriser</i></b>",
|
||||
"chromeGrantPermissions": "Merci d'autoriser le partage de votre camera et microphone en appuyant sur le bouton <b><i>Autoriser</i></b>",
|
||||
"androidGrantPermissions": "Merci d'autoriser le partage de votre camera et microphone en appuyant sur le bouton <b><i>Autoriser</i></b>",
|
||||
"firefoxGrantPermissions": "Merci d'accorder l'autorisation d'utiliser votre caméra et un microphone en appuyant sur le bouton<b> <i> Partager le périphérique sélectionné </ i> </ b> ",
|
||||
"operaGrantPermissions": "Merci d'autoriser le partage de votre camera et microphone en appuyant sur le bouton <b><i>Autoriser</i></b>",
|
||||
"iexplorerGrantPermissions": "Merci d'autoriser l'utilisation de votre caméra et du microphone en appuyant sur <b><i>OK</i></b>",
|
||||
"safariGrantPermissions": "Merci d'autoriser l'utilisation de votre caméra et du microphone en appuyant sur <b><i>OK</i></b>",
|
||||
"nwjsGrantPermissions": "Merci d'autoriser le partage de votre camera et microphone"
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "Raccourcis clavier :",
|
||||
"raiseHand": "Demander la parole.",
|
||||
"pushToTalk": "Appuyer pour parler.",
|
||||
"toggleScreensharing": "Basculer entre la caméra et le partage d'écran.",
|
||||
"toggleFilmstrip": "Afficher ou masquer les vidéos miniatures.",
|
||||
"toggleShortcuts": "Afficher ou masquer ce menu d'aide.",
|
||||
"focusLocal": "Focus sur la vidéo locale.",
|
||||
"focusRemote": "Focus sur l'une des vidéos distantes.",
|
||||
"toggleChat": "Ouvrir ou fermer le panneau de conversation.",
|
||||
"mute": "Activer ou désactiver le microphone.",
|
||||
"videoMute": "Arrêter ou démarrer la vidéo locale."
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "Créer",
|
||||
"roomname": "Saisissez un nom de salle",
|
||||
@@ -66,7 +91,9 @@
|
||||
"dialpad": "Afficher le clavier de numérotation",
|
||||
"sharedVideoMutedPopup": "Votre vidéo a été mise en muet<br/>pour que vous puissiez parler aux autres participants.",
|
||||
"micMutedPopup": "Votre microphone a été désactivé afin que vous<br/>puissiez profiter pleinement de votre vidéo partagée.",
|
||||
"unableToUnmutePopup": "Vous ne pouvez pas réactiver votre microphone pendant que la vidéo partagée est activée."
|
||||
"unableToUnmutePopup": "Vous ne pouvez pas réactiver votre microphone pendant que la vidéo partagée est activée.",
|
||||
"cameraDisabled": "La camera n'est pas disponible",
|
||||
"micDisabled": "Le microphone n'est pas disponible"
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Ouvrir / fermer le chat",
|
||||
@@ -88,7 +115,11 @@
|
||||
"startVideoMuted": "Démarrer sans vidéo",
|
||||
"selectCamera": "Sélectionnez une caméra",
|
||||
"selectMic": "Sélectionnez un microphone",
|
||||
"followMe": "Activer \"me suivre\""
|
||||
"selectAudioOutput": "Sélectionner la sortie audio",
|
||||
"followMe": "Activer \"me suivre\"",
|
||||
"noDevice": "Aucun",
|
||||
"noPermission": "L'autorisation d'utiliser l'appareil n'a pas été accordé",
|
||||
"avatarUrl": "URL de l'avatar"
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Cliquez pour modifier<br/>votre nom",
|
||||
@@ -97,7 +128,8 @@
|
||||
"mute": "Un participant a coupé son micro",
|
||||
"kick": "Exclure",
|
||||
"muted": "Muet",
|
||||
"domute": "Couper le son"
|
||||
"domute": "Couper le son",
|
||||
"flip": "Retourner"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Débit :",
|
||||
@@ -129,7 +161,8 @@
|
||||
"grantedTo": "Droits modérateur accordés à __to__ !",
|
||||
"grantedToUnknown": "Droits modérateur accordés à $t(somebody) !",
|
||||
"muted": "Vous avez commencé la conversation en muet.",
|
||||
"mutedTitle": "Vous êtes en muet !"
|
||||
"mutedTitle": "Vous êtes en muet !",
|
||||
"raisedHand": "Aimerais prendre la parole."
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "Oups! Vous avez été renvoyé de la réunion !",
|
||||
@@ -177,7 +210,7 @@
|
||||
"joinAgain": "Rejoignez à nouveau la conférence",
|
||||
"Share": "Partager",
|
||||
"Save": "Sauvegarder",
|
||||
"recording": "",
|
||||
"recording": "Enregistrement",
|
||||
"recordingToken": "Saisissez un jeton d'enregistrement",
|
||||
"Dial": "Composer",
|
||||
"sipMsg": "Saisissez un numéro SIP",
|
||||
@@ -205,13 +238,27 @@
|
||||
"feedbackQuestion": "Comment était votre conférence ?",
|
||||
"thankYou": "Merci d'avoir utilisé __appName__ !",
|
||||
"sorryFeedback": "Nous sommes désolés d'apprendre cela. Voulez-vous nous en dire plus ?",
|
||||
"liveStreaming": "",
|
||||
"liveStreaming": "Direct",
|
||||
"streamKey": "Stream name/key",
|
||||
"startLiveStreaming": "Commencer le direct",
|
||||
"stopStreamingWarning": "Désirez-vous vraiment arrêter le direct?",
|
||||
"stopRecordingWarning": "Désirez-vous vraiment arrêter l'enregistrement?",
|
||||
"stopLiveStreaming": "Arrêter le direct",
|
||||
"stopRecording": "Arrêter l'enregistrement"
|
||||
"stopRecording": "Arrêter l'enregistrement",
|
||||
"doNotShowWarningAgain": "Ne plus afficher cet avertissement",
|
||||
"permissionDenied": "Permission refusée",
|
||||
"screenSharingPermissionDeniedError": "Vous n'avez pas autorisé le partage de votre écran.",
|
||||
"micErrorPresent": "Une erreur est survenue lors de la connexion à votre microphone.",
|
||||
"cameraErrorPresent": "Votre caméra ne satisfait pas certaines des contraintes nécessaires.",
|
||||
"cameraUnsupportedResolutionError": "Votre appareil ne prend pas en charge la résolution vidéo requise.",
|
||||
"cameraUnknownError": "Vous ne pouvez pas utiliser la caméra pour une raison inconnue.",
|
||||
"cameraPermissionDeniedError": "Vous n'avez pas autorisé l'utilisation de votre caméra. Vous pouvez toujours participer à la conférence, mais les autres ne vont pas vous voir. Utilisez le bouton de la caméra dans la barre d'adresse pour résoudre ce problème.",
|
||||
"cameraNotFoundError": "La caméra demandée n'a pas été trouvée.",
|
||||
"cameraConstraintFailedError": "Votre caméra ne satisfait pas certaines des contraintes nécessaires.",
|
||||
"micUnknownError": "Vous ne pouvez pas utiliser le microphone pour une raison inconnue.",
|
||||
"micPermissionDeniedError": "Vous n'avez pas autorisé l'utilisation de votre microphone. Vous pouvez toujours participer à la conférence, mais les autres ne vont pas vous entendre. Utilisez le bouton du microphone dans la barre d'adresse pour résoudre ce problème.",
|
||||
"micNotFoundError": "Le microphone demandé n'a pas été trouvé.",
|
||||
"micConstraintFailedError": "Votre microphone ne satisfait pas certaines des contraintes nécessaires."
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
@@ -258,7 +305,9 @@
|
||||
"on": "Enregistrement",
|
||||
"off": "Enregistrement arrêter",
|
||||
"failedToStart": "L'enregistrement n'as pas réussi à démarrer",
|
||||
"buttonTooltip": "Démarrer / arrêter l'enregistrement"
|
||||
"buttonTooltip": "Démarrer / arrêter l'enregistrement",
|
||||
"error": "Échec de l'enregistrement. Veuillez réessayer.",
|
||||
"unavailable": "Le service d'enregistrement est actuellement indisponible. Veuillez réessayer plus tard."
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "Commencer le direct...",
|
||||
@@ -267,6 +316,8 @@
|
||||
"unavailable": "Le direct est temporairement indisponible. Veuillez réessayer plus tard.",
|
||||
"failedToStart": "Le direct n'as pas réussi à démarrer",
|
||||
"buttonTooltip": "Démarrer / arrêter le direct",
|
||||
"streamIdRequired": "Merci de renseigner le stream id pour lancer le direct."
|
||||
"streamIdRequired": "Merci de renseigner le stream id pour lancer le direct.",
|
||||
"error": "La retransmission en direct a échoué. Veuillez réessayer.",
|
||||
"busy": "Tous les enregistreurs sont actuellement occupés. Veuillez réessayer plus tard."
|
||||
}
|
||||
}
|
||||
@@ -1,250 +1,315 @@
|
||||
{
|
||||
"contactlist": "",
|
||||
"connectionsettings": "",
|
||||
"poweredby": "",
|
||||
"downloadlogs": "",
|
||||
"feedback": "",
|
||||
"roomUrlDefaultMsg": "",
|
||||
"participant": "",
|
||||
"me": "",
|
||||
"speaker": "",
|
||||
"defaultNickname": "",
|
||||
"defaultLink": "",
|
||||
"contactlist": "ԿՈՆՏԱԿՏՆԵՐ",
|
||||
"connectionsettings": "Միացման կարգավորումներ",
|
||||
"poweredby": "Հիմնված է",
|
||||
"downloadlogs": "Բեռնել log-էրը",
|
||||
"feedback": "Հայտնեք ձեր կարծիքը",
|
||||
"roomUrlDefaultMsg": "Ձեր կոնֆերանսը այժմ ստեղծվում է...",
|
||||
"participant": "Մասնակից",
|
||||
"me": "ես",
|
||||
"speaker": "Հռետոր",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "օրինակ՝ Պողոս Պողոսյան",
|
||||
"defaultLink": "օրինակ՝ __url__",
|
||||
"calling": "",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "",
|
||||
"raiseHand": "",
|
||||
"pushToTalk": "",
|
||||
"toggleScreensharing": "",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleShortcuts": "",
|
||||
"focusLocal": "",
|
||||
"focusRemote": "",
|
||||
"toggleChat": "",
|
||||
"mute": "",
|
||||
"videoMute": ""
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "",
|
||||
"roomname": "",
|
||||
"disable": "",
|
||||
"go": "ՄՈՒՏՔ",
|
||||
"roomname": "Մուտքագրեք սենյակի անունը",
|
||||
"disable": "Այլևս ցույց չտալ այս էջը",
|
||||
"feature1": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Հեշտ է օգտվել",
|
||||
"content": "Ոչ մի լրացուցիչ ներբեռնումներ: __apple__ աշխատում է անմիջապես Ձեր բրաուզերում: Պարզապես հայտնեք ձեր կոնֆերանսի URL հասցեն ուրիշներին և դուք կապի մեջ էք:"
|
||||
},
|
||||
"feature2": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Պետք չէ արագ կապ",
|
||||
"content": "Բազմամասնակից վիդեո կոնֆերանսները աշխատում են ընդամենը 128 Կբ/վ արագությամբ: Իսկ միայն էկրանի ցուցադրման կամ միայն ձայնի դեպքում՝ ավելի քիչ:"
|
||||
},
|
||||
"feature3": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Բաց կոդ",
|
||||
"content": "_app_ լիցենզավորված է Apache լիցենզիայով: Կարող էք ազատորեն ներբեռնել, օգտագործել, ձևափոխել և կիսվել դրանով այդ լիցենզիայի համապատասխան:"
|
||||
},
|
||||
"feature4": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Օգտվողների թիվը սահմանափակ չէ",
|
||||
"content": "Չկան արհեստական սահմանափակումներ օգտագործողների կամ կոնֆերանսի մասնակիցների թվի համար: Սահմանափակող գործոնները՝ միայն սերվերի հզորությունն ու թողունակությունն են:"
|
||||
},
|
||||
"feature5": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Էկրանի ցուցադրում",
|
||||
"content": "Շատ հեշտ է ցուցադրել Ձեր էկրանը ուրիշներին: __app__ իդեալական է օնլայն ներկայացումների, դասախոսությունների և տեխնիկական սպասարկման համար:"
|
||||
},
|
||||
"feature6": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Փակ սենյակներ",
|
||||
"content": "Պե՞տք է առանձնանալ: __app__ կոնֆերանսում կարող էք փակվել սենյակը գաղտնաբառով, որպեսզի անսպասելի հյուրեր կամ ընդհատումներ չունենաք:"
|
||||
},
|
||||
"feature7": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Համատեղ նշումներ",
|
||||
"content": "Շնորհիվ __app__ -ում ընդգրկված Etherpad տեքստային խմբագրի, իրական ժամանակում կարող էք համատեղ նշումներ կատարել, ինչը շատ հարմար է հանդիպումն արձանագրելու, հոդվածներ գրելու և այլ նպատակների համար:"
|
||||
},
|
||||
"feature8": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Օգտագործման վիճակագրություն",
|
||||
"content": "Օգտագործման վիճակագրություն կարելի է ստանալ հեշտ ինտեգրվող Piwik, Google Analytics կամ այլ մոնիտորինգի համակարգերի միջոցով:"
|
||||
}
|
||||
},
|
||||
"toolbar": {
|
||||
"mute": "",
|
||||
"videomute": "",
|
||||
"authenticate": "",
|
||||
"lock": "",
|
||||
"invite": "",
|
||||
"chat": "",
|
||||
"etherpad": "",
|
||||
"sharedvideo": "",
|
||||
"sharescreen": "",
|
||||
"fullscreen": "",
|
||||
"sip": "",
|
||||
"Settings": "",
|
||||
"hangup": "",
|
||||
"login": "",
|
||||
"logout": "",
|
||||
"dialpad": "",
|
||||
"sharedVideoMutedPopup": "",
|
||||
"micMutedPopup": "",
|
||||
"unableToUnmutePopup": ""
|
||||
"mute": "Ձայնը Միացնել/Անջատել ",
|
||||
"videomute": "Տեսախցիկը Միացնել/Անջատել ",
|
||||
"authenticate": "Վավերացում",
|
||||
"lock": "Փակել/բացել սենյակը",
|
||||
"invite": "Հրավիրել ուրիշներին",
|
||||
"chat": "Բացել/փակել չատը",
|
||||
"etherpad": "Համատեղ փաստաթուղթ",
|
||||
"sharedvideo": "Կիսվել YouTube-ի նյութով",
|
||||
"sharescreen": "Ցուցադրել էկրանը",
|
||||
"fullscreen": "Ամբողջ Էկրանի ռեժիմը միացնել/անջատել",
|
||||
"sip": "Զանգել SIP համարով",
|
||||
"Settings": "Կարգավորումներ",
|
||||
"hangup": "Անջատել",
|
||||
"login": "Մուտք",
|
||||
"logout": "Ելք",
|
||||
"dialpad": "Ցույց տալ թվաշարը",
|
||||
"sharedVideoMutedPopup": "Ձեր ցուցադրված տեսանյութի ձայնը անջատված է, այնպես որ <br />, կարող եք խոսել մյուս մասնակիցների հետ:",
|
||||
"micMutedPopup": "Ձեր խոսափողը անջատված է՝<br/> կարող եք լիովին վայելել ձեր ցուցադրված տեսանյութը:",
|
||||
"unableToUnmutePopup": "Դուք չեք կարող միացնել ձայնը, քանի դեռ միանցված է ցուցադրվող տեսանյութը:",
|
||||
"cameraDisabled": "",
|
||||
"micDisabled": ""
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "",
|
||||
"filmstrip": "",
|
||||
"contactlist": ""
|
||||
"chat": "Բացել/փակել չատը",
|
||||
"filmstrip": "Ցույղ տալ/թաքցնել ժապավենը",
|
||||
"contactlist": "Բացել/փակել կոնտակտների ցուցակը"
|
||||
},
|
||||
"chat": {
|
||||
"nickname": {
|
||||
"title": "",
|
||||
"popover": ""
|
||||
"title": "Գրեք մականուն ստորև գտնվող հատվածում",
|
||||
"popover": "Ընտրեք մականուն"
|
||||
},
|
||||
"messagebox": ""
|
||||
"messagebox": "Գրեք տեքստ..."
|
||||
},
|
||||
"settings": {
|
||||
"title": "",
|
||||
"update": "",
|
||||
"name": "",
|
||||
"startAudioMuted": "",
|
||||
"startVideoMuted": "",
|
||||
"selectCamera": "",
|
||||
"selectMic": "",
|
||||
"followMe": ""
|
||||
"title": "ԿԱՐԳԱՎՈՐՈՒՄՆԵՐ",
|
||||
"update": "Թարմացնել",
|
||||
"name": "Անուն",
|
||||
"startAudioMuted": "Սկսել առանց ձայնի",
|
||||
"startVideoMuted": "Սկսել առանց վիդեոյի",
|
||||
"selectCamera": "Ընտրեք տեսախցիկը",
|
||||
"selectMic": "Ընտրեք խոսափողը",
|
||||
"selectAudioOutput": "",
|
||||
"followMe": "Թույլ տալ ինձ հետևելը",
|
||||
"noDevice": "",
|
||||
"noPermission": "",
|
||||
"avatarUrl": ""
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "",
|
||||
"moderator": "",
|
||||
"videomute": "",
|
||||
"mute": "",
|
||||
"kick": "",
|
||||
"muted": "",
|
||||
"domute": ""
|
||||
"editnickname": "Սեղմեք Ձեր անունը <br/>փոխելու համար",
|
||||
"moderator": "Այս կոնֆերանսի տերը",
|
||||
"videomute": "Մասնակիցը անջատեց<br/>իր տեսախցիկը",
|
||||
"mute": "Մասնակիցը անջատեց ձայնը",
|
||||
"kick": "Դուրս հանել",
|
||||
"muted": "Ձայնը անջատված է",
|
||||
"domute": "Անջատել ձայնը",
|
||||
"flip": ""
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "",
|
||||
"packetloss": "",
|
||||
"resolution": "",
|
||||
"less": "",
|
||||
"more": "",
|
||||
"address": "",
|
||||
"remoteport": "",
|
||||
"remoteport_plural": "",
|
||||
"localport": "",
|
||||
"localport_plural": "",
|
||||
"localaddress": "",
|
||||
"localaddress_plural": "",
|
||||
"remoteaddress": "",
|
||||
"remoteaddress_plural": "",
|
||||
"transport": "",
|
||||
"bandwidth": "",
|
||||
"na": ""
|
||||
"bitrate": "Բիթրեյթ",
|
||||
"packetloss": "Փաթեթների կորուստ՝",
|
||||
"resolution": "Որակ՝",
|
||||
"less": "Ցույց տալ ավելի քիչ",
|
||||
"more": "Ցույց տալ ավելի շատ",
|
||||
"address": "Հասցե՝",
|
||||
"remoteport": "Հեռակա պորտ՝Հեռակա պորտեր՝",
|
||||
"localport": "Տեղային պորտ՝Տեղային պորտեր՝",
|
||||
"localaddress": "Տեղային հասցե՝Տեղային հասցեներ՝",
|
||||
"remoteaddress": "Հեռակա հասցե՝Հեռակա հասցեներ՝",
|
||||
"transport": "Տրանսպորտ՝",
|
||||
"bandwidth": "Մոտավոր թողունակություն՝",
|
||||
"na": "Միացման տվյալները հասանելի կլինեն այստեղ կոնֆերանսի մեկնարկից հետո:"
|
||||
},
|
||||
"notify": {
|
||||
"disconnected": "",
|
||||
"moderator": "",
|
||||
"connected": "",
|
||||
"somebody": "",
|
||||
"me": "",
|
||||
"focus": "",
|
||||
"focusFail": "",
|
||||
"grantedTo": "",
|
||||
"grantedToUnknown": "",
|
||||
"muted": "",
|
||||
"mutedTitle": ""
|
||||
"disconnected": "անջատված է",
|
||||
"moderator": "Կարգավորիչ իրավունքները տրամադրված են:",
|
||||
"connected": "միացված է",
|
||||
"somebody": "Ոմն",
|
||||
"me": "Ես",
|
||||
"focus": "Կոնֆերանսի կենտրոնացումը",
|
||||
"focusFail": "__component__ հասանելի չէ - փորձեք կրկին __ms__ վայրկյանից",
|
||||
"grantedTo": "Կարգավորիչի իրավունքները տրամադրված է __to__-ին",
|
||||
"grantedToUnknown": "Կարգավորիչի իրավունքները տրամադրված է $t(somebody)! -ին",
|
||||
"muted": "Դուք խոսակցությունը սկսեցիք անջատած ձայնով:",
|
||||
"mutedTitle": "Ձեր ձայնը անջատվա'ծ է",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "",
|
||||
"popupError": "",
|
||||
"passwordError": "",
|
||||
"passwordError2": "",
|
||||
"connectError": "",
|
||||
"connectErrorWithMsg": "",
|
||||
"connecting": "",
|
||||
"error": "",
|
||||
"detectext": "",
|
||||
"failtoinstall": "",
|
||||
"failedpermissions": "",
|
||||
"bridgeUnavailable": "",
|
||||
"jicofoUnavailable": "",
|
||||
"maxUsersLimitReached": "",
|
||||
"lockTitle": "",
|
||||
"lockMessage": "",
|
||||
"warning": "",
|
||||
"passwordNotSupported": "",
|
||||
"sorry": "",
|
||||
"internalError": "",
|
||||
"unableToSwitch": "",
|
||||
"SLDFailure": "",
|
||||
"SRDFailure": "",
|
||||
"oops": "",
|
||||
"defaultError": "",
|
||||
"passwordRequired": "",
|
||||
"Ok": "",
|
||||
"Remove": "",
|
||||
"shareVideoTitle": "",
|
||||
"shareVideoLinkError": "",
|
||||
"removeSharedVideoTitle": "",
|
||||
"removeSharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"WaitingForHost": "",
|
||||
"WaitForHostMsg": "",
|
||||
"IamHost": "",
|
||||
"Cancel": "",
|
||||
"retry": "",
|
||||
"logoutTitle": "",
|
||||
"logoutQuestion": "",
|
||||
"sessTerminated": "",
|
||||
"hungUp": "",
|
||||
"joinAgain": "",
|
||||
"Share": "",
|
||||
"Save": "",
|
||||
"recording": "",
|
||||
"recordingToken": "",
|
||||
"Dial": "",
|
||||
"sipMsg": "",
|
||||
"passwordCheck": "",
|
||||
"passwordMsg": "",
|
||||
"Invite": "",
|
||||
"shareLink": "",
|
||||
"settings1": "",
|
||||
"settings2": "",
|
||||
"settings3": "",
|
||||
"yourPassword": "",
|
||||
"Back": "",
|
||||
"serviceUnavailable": "",
|
||||
"gracefulShutdown": "",
|
||||
"Yes": "",
|
||||
"reservationError": "",
|
||||
"reservationErrorMsg": "",
|
||||
"password": "",
|
||||
"userPassword": "",
|
||||
"token": "",
|
||||
"tokenAuthFailed": "",
|
||||
"displayNameRequired": "",
|
||||
"extensionRequired": "",
|
||||
"firefoxExtensionPrompt": "",
|
||||
"feedbackQuestion": "",
|
||||
"thankYou": "",
|
||||
"sorryFeedback": "",
|
||||
"liveStreaming": "",
|
||||
"streamKey": "",
|
||||
"startLiveStreaming": "",
|
||||
"stopStreamingWarning": "",
|
||||
"stopRecordingWarning": "",
|
||||
"stopLiveStreaming": "",
|
||||
"stopRecording": ""
|
||||
"kickMessage": "Վա՜յ: Ձեզ դուրս հանեցին հանդիպումից:",
|
||||
"popupError": "Ձեր բրաուզերը արգելափակել է թռուցիկ(popup) պատուհանները այս կայքում: Խնդրում ենք միացրեք թռուցիկները Ձեր բրաուզերի անվտանգության կարգավորումներում և կրկին փորձեք:",
|
||||
"passwordError": "Այս խոսակցությունը այս պահին պաշտպանված է գաղտնաբառով:Միայն կոնֆերանսի սեփականատերը կարող է սահմանել գաղտնաբառ:",
|
||||
"passwordError2": "Այս խոսակցությունը այս պահին պաշտպանված չէ գաղտնաբառով:Միայն կոնֆերանսի սեփականատերը կարող է սահմանել գաղտնաբառ:",
|
||||
"connectError": "Ու՜պս! Ինչոր բան այն չէ և մենք չկարողացանք միանալ կոնֆերանսին:",
|
||||
"connectErrorWithMsg": "Ու՜պս! Ինչոր բան այն չէ և մենք չկարողացանք միանալ կոնֆերանսին: __msg__",
|
||||
"connecting": "Միանում է...",
|
||||
"error": "Սխալ",
|
||||
"detectext": "Սխալ, երբ փորձում է հայտնաբերել էկրանի ցուցադրման ընդլայնումը:",
|
||||
"failtoinstall": "Չհաջողվեց տեղադրել էկրանի ցուցադրման ընդլայնումը",
|
||||
"failedpermissions": "Չհաջողվեց ստանալ թույլտվություն օգտագործելու տեղի խոսափողը և/ կամ տեսախցիկը:",
|
||||
"bridgeUnavailable": "Jitsi Videobridge-ը ներկայումս անհասանելի է: Խնդրում ենք փորձեք մի փոքր ուշ!",
|
||||
"jicofoUnavailable": "Jicofo ներկայումս անհասանելի է: Խնդրում ենք փորձեք ավելի ուշ:",
|
||||
"maxUsersLimitReached": "Մասնակիցների առավելագույն թիվը արդեն լրացել է: Մասնակիցները արդեն հավաքվել են: Խնդրում ենք փորձեք ավելի ուշ:",
|
||||
"lockTitle": "Փակումը ձախողվեց",
|
||||
"lockMessage": "Ձախողվեց արգելափակել կոնֆերանսը:",
|
||||
"warning": "Ուշադրությու՝ն",
|
||||
"passwordNotSupported": "Սենյակների գաղտնաբառերը ներկայումս չեն ապահովվում:",
|
||||
"sorry": "Ներողություն",
|
||||
"internalError": "Ներքին ծրագրային սխալ [setRemoteDescription]",
|
||||
"unableToSwitch": "Անհնար է անցնել վիդեո հոսքին:",
|
||||
"SLDFailure": "Ու՜պս: Ինչ-որ բան գնաց սխալ, և մենք չկարողացանք անջատել ձայնը (SLD Failure)",
|
||||
"SRDFailure": "Ու՜պս: Ինչ-որ բան գնաց սխալ, և մենք չկարողացանք անջատել տեսահոսքը (SRD Failure)",
|
||||
"oops": "Ու՜պս:",
|
||||
"defaultError": "Առկա էր որոշակի սխալ",
|
||||
"passwordRequired": "Պահանջվում է գաղտնաբառ",
|
||||
"Ok": "Ok",
|
||||
"Remove": "Հեռացնել",
|
||||
"shareVideoTitle": "Տարածել տեսանյութը",
|
||||
"shareVideoLinkError": "Խնդրում ենք ներկայացնել ճիշտ Youtube հղում:",
|
||||
"removeSharedVideoTitle": "Հեռացնել տարածված տեսանյութը",
|
||||
"removeSharedVideoMsg": "Համոզված եք, որ ցանկանում եք հեռացնել ձեր կիսած տեսանյութը:",
|
||||
"alreadySharedVideoMsg": "Մեկ այլ մասնակից արդեն կիսում է տեսանյութ: Այս կոնֆերանսը հնարավորություն է տալիս միայն մեկ հիմնական տեսանյութ միաժամանակ:",
|
||||
"WaitingForHost": "Սպասում է հյուրընկալողի ...",
|
||||
"WaitForHostMsg": "Կոնֆերանսը <b> __ root__ </ b> դեռ չի սկսվել. Եթե դուք են հյուրընկալող եք ապա խնդրում ենք հաստատել իսկությունը: Հակառակ դեպքում, խնդրում ենք սպասել հյուրընկալող կժամանի.",
|
||||
"IamHost": "Ես եմ ընդունողը",
|
||||
"Cancel": "Չեղարկել",
|
||||
"retry": "Կրկին փորձել",
|
||||
"logoutTitle": "Ելք",
|
||||
"logoutQuestion": "Համոզված եք, որ ցանկանում եք դուրս գալ, եւ դադարեցնել կոնֆերանսը:",
|
||||
"sessTerminated": "Նիստը ավարտված է",
|
||||
"hungUp": "Դուք անջատեցիք",
|
||||
"joinAgain": "Միանալ կրկին",
|
||||
"Share": "Տարածել",
|
||||
"Save": "Պահպանել",
|
||||
"recording": "Գրանցում",
|
||||
"recordingToken": "Մուտքագրեք ձայնագրման կոդանշանը",
|
||||
"Dial": "Զանգ",
|
||||
"sipMsg": "Նշեք SIP համարը",
|
||||
"passwordCheck": "Դուք վստա՞հ էք որ ցանկանում էք ջնջել Ձեր գաղտնաբառը։",
|
||||
"passwordMsg": "Սահմանել գաղտնաբառ ձեր սենյակը կողպելու համար",
|
||||
"Invite": "Հրավիրել",
|
||||
"shareLink": "Տարածել այս հղումը բոլոր նրանց ում կհրավիրեմ:",
|
||||
"settings1": "Կարգավորել Ձեր կոնֆերանսը",
|
||||
"settings2": "Մասնակիցները միացան անջատվախ ձայնով",
|
||||
"settings3": "Պահանջվում է մականունը<br/><br/>Դրեք գաղտնաբառ Ձեր սենյակը արգելափակելու համար",
|
||||
"yourPassword": "Ձեր գաղտնաբառը",
|
||||
"Back": "Վերադառնալ",
|
||||
"serviceUnavailable": "Ծառայությունը անհասանելի է",
|
||||
"gracefulShutdown": "Մեր ծառայությունը ներկայումս չի գործում տեխնիկական սպասարկման համար: Խնդրում ենք փորձեք ավելի ուշ:",
|
||||
"Yes": "Այո",
|
||||
"reservationError": "Վերապահման համակարգի սխալ",
|
||||
"reservationErrorMsg": "Սխալ. __code__, ծանուցում. __msg__",
|
||||
"password": "Գաղտնաբառ",
|
||||
"userPassword": "օգտագործողի գաղտնաբառը",
|
||||
"token": "սիմվոլ",
|
||||
"tokenAuthFailed": "Սխալ: XMPP սերվեր մուտք գործելուց. սխալ սիմվոլ",
|
||||
"displayNameRequired": "Խնդրում ենք մուտքագրել Ձեր ցուցադրման անունը",
|
||||
"extensionRequired": "Ընդլայնում է պահանջվում:",
|
||||
"firefoxExtensionPrompt": "Դուք պետք է տեղադրեք Firefox ընդլայնում, որպեսզի օգտագործել էկրանի փոխանակման ռեժիմը: Խնդրում ենք փորձեք կրկին՝ այն <a href='__url__'> այստեղից ձեռք բերելուց հետո</a>:",
|
||||
"feedbackQuestion": "Ինչպիսին էր ձեր զանգը:",
|
||||
"thankYou": "Շնորհակալություն __appName__ -ից օգտվելու համար:",
|
||||
"sorryFeedback": "Մենք շատ ցավում ենք լսել դա: Կուզե՞ք ինչոր բան ասել ավելին:",
|
||||
"liveStreaming": "Ուղիղ Հեռարձակում",
|
||||
"streamKey": "Հոսքի անուն/բանալի",
|
||||
"startLiveStreaming": "Սկսել ուղիղ հեռարձակումը",
|
||||
"stopStreamingWarning": "Վստա՞հ եք որ ցանկանում եք կանգնացնել ուղիղ հեռարձակումը:",
|
||||
"stopRecordingWarning": "Վստա՞հ եք որ ցանկանում եք կանգնացնել ձայնագրումը",
|
||||
"stopLiveStreaming": "Կանգնացնել ուղիղ հեռարձակումը:",
|
||||
"stopRecording": "Կանգնացնել ձայնագրումը",
|
||||
"doNotShowWarningAgain": "",
|
||||
"permissionDenied": "",
|
||||
"screenSharingPermissionDeniedError": "",
|
||||
"micErrorPresent": "",
|
||||
"cameraErrorPresent": "",
|
||||
"cameraUnsupportedResolutionError": "",
|
||||
"cameraUnknownError": "",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "",
|
||||
"cameraConstraintFailedError": "",
|
||||
"micUnknownError": "",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "",
|
||||
"micConstraintFailedError": ""
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": "",
|
||||
"subject": "",
|
||||
"body": "",
|
||||
"and": ""
|
||||
"sharedKey": [
|
||||
"Այս կոնֆերանսը գաղտնաբառով փակ է: Խնդրում ենք օգտագործեք այս կոդը միանալիս:",
|
||||
"",
|
||||
"",
|
||||
"__sharedKey__",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"subject": "Հրավեր __appName__ (__conferenceName__)",
|
||||
"body": [
|
||||
"Ես ուզում եմ հրավիրել __appName__ կոնֆերանսին, ես հենց նոր ստեղծցի այն ",
|
||||
"",
|
||||
"",
|
||||
"Խնդրում ենք սեղմեք հետևյալ հղմանը, որպեսզի միանալ կոնֆերանսին \\ n",
|
||||
"",
|
||||
"__roomUrl__",
|
||||
"",
|
||||
"",
|
||||
"Նշենք նաեւ, որ __appName__ներկայումս միայն աջակցում է __supportedBrowsers__, այնպես որ դուք պետք է, օգտագործեք այս բրաուզերներից մեկը ",
|
||||
"\\ n\\ nԽոսեք մի քանի վայրկյանից:"
|
||||
],
|
||||
"and": "և"
|
||||
},
|
||||
"connection": {
|
||||
"ERROR": "",
|
||||
"CONNECTING": "",
|
||||
"RECONNECTING": "",
|
||||
"CONNFAIL": "",
|
||||
"AUTHENTICATING": "",
|
||||
"AUTHFAIL": "",
|
||||
"CONNECTED": "",
|
||||
"DISCONNECTED": "",
|
||||
"DISCONNECTING": "",
|
||||
"ATTACHED": ""
|
||||
"ERROR": "Սխալ",
|
||||
"CONNECTING": "Միանում է...",
|
||||
"RECONNECTING": "Ցանցի խնդիր է տեղի ունեցել: Վերամիացում...",
|
||||
"CONNFAIL": "Միացումը չստացվեց",
|
||||
"AUTHENTICATING": "Վավերացում",
|
||||
"AUTHFAIL": "Վավերացումը չի ստացվել",
|
||||
"CONNECTED": "Միացված է",
|
||||
"DISCONNECTED": "Անջատված է",
|
||||
"DISCONNECTING": "Անջատում...",
|
||||
"ATTACHED": "Կցված"
|
||||
},
|
||||
"recording": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": ""
|
||||
"pending": "Ձայնագրությունը սպասում է մասնակցի միանացմանը ...",
|
||||
"on": "Գրանցում",
|
||||
"off": "Ձայնագրությունը կանգնացված է",
|
||||
"failedToStart": "Ձայնագրությունը ստացվեց սկսել",
|
||||
"buttonTooltip": "Սկսել / կանգնացնել ձայնագրությունը",
|
||||
"error": "",
|
||||
"unavailable": ""
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"unavailable": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"streamIdRequired": ""
|
||||
"pending": "Սկսում ենք Ուղիղ Հեռարձակումը",
|
||||
"on": "Ուղիղ Հեռարձակում",
|
||||
"off": "Ուղիղ Հեռարձակումը կանգնեցված է",
|
||||
"unavailable": "Ուղիղ հեռարձակման ծառայությունը ներկայումս հասանելի չէ: Խնդրում եք փորձեք ավելի ուշ:",
|
||||
"failedToStart": "Ուղիղ հեռարձակումը չստացվեց սկսել",
|
||||
"buttonTooltip": "Սկսել / կանգնեցնել ուղիղ հեռարձակումը",
|
||||
"streamIdRequired": "Խնդրում ենք լրացնել հոսքի ID-ն, որպեսզի կսկսի հեռարձակումը:",
|
||||
"error": "",
|
||||
"busy": ""
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,42 @@
|
||||
"connectionsettings": "Impostazioni Connessione",
|
||||
"poweredby": "powered by",
|
||||
"downloadlogs": "Scarica logs",
|
||||
"feedback": "",
|
||||
"roomUrlDefaultMsg": "La tua conferenza sta per essere creata...",
|
||||
"participant": "Partecipante",
|
||||
"me": "io",
|
||||
"speaker": "Relatore",
|
||||
"defaultNickname": "es. __nome__",
|
||||
"defaultPreziLink": "es. __url__",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "",
|
||||
"defaultLink": "es. __url__",
|
||||
"calling": "",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "",
|
||||
"raiseHand": "",
|
||||
"pushToTalk": "",
|
||||
"toggleScreensharing": "",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleShortcuts": "",
|
||||
"focusLocal": "",
|
||||
"focusRemote": "",
|
||||
"toggleChat": "",
|
||||
"mute": "",
|
||||
"videoMute": ""
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "VAI",
|
||||
"roomname": "Inserisci Nome Stanza",
|
||||
"disable": "Non visualizzare questa pagina la prossima volta",
|
||||
"disable": "",
|
||||
"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."
|
||||
@@ -23,7 +49,7 @@
|
||||
},
|
||||
"feature3": {
|
||||
"title": "Open source",
|
||||
"content": "__app__ è sotto licenza MIT. Sei libero di scaricarla, usarla, modificarla e condividerla con la medesima licenza."
|
||||
"content": ""
|
||||
},
|
||||
"feature4": {
|
||||
"title": "Utenti illimitati",
|
||||
@@ -31,7 +57,7 @@
|
||||
},
|
||||
"feature5": {
|
||||
"title": "Condivisione Schermo",
|
||||
"content": "é facile condividere il tuo schermo con altri. __app__ è l'ideale per presentazioni online, letture, e sessioni di supporto tecnico."
|
||||
"content": "è facile condividere il tuo schermo con altri. __app__ è l'ideale per presentazioni online, letture, e sessioni di supporto tecnico."
|
||||
},
|
||||
"feature6": {
|
||||
"title": "Stanze sicure",
|
||||
@@ -49,20 +75,25 @@
|
||||
"toolbar": {
|
||||
"mute": "Microfono Attiva / Disattiva",
|
||||
"videomute": "Abilita / Disabilita video",
|
||||
"authenticate": "",
|
||||
"record": "Registra",
|
||||
"authenticate": "Autenticazione",
|
||||
"lock": "Blocca / Sblocca Stanza",
|
||||
"invite": "Invita altri",
|
||||
"chat": "",
|
||||
"prezi": "Condividi con Prezi",
|
||||
"chat": "Apri / Chiudi chat",
|
||||
"etherpad": "Documento condiviso",
|
||||
"sharedvideo": "",
|
||||
"sharescreen": "Condividi schermo",
|
||||
"fullscreen": "Entra / Esci da schermo intero",
|
||||
"sip": "Chiama numero SIP",
|
||||
"Settings": "Impostazioni",
|
||||
"hangup": "Termina",
|
||||
"login": "Login",
|
||||
"logout": ""
|
||||
"logout": "Logout",
|
||||
"dialpad": "Mostra il tastierino",
|
||||
"sharedVideoMutedPopup": "",
|
||||
"micMutedPopup": "",
|
||||
"unableToUnmutePopup": "",
|
||||
"cameraDisabled": "",
|
||||
"micDisabled": ""
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Apri / Chiudi chat",
|
||||
@@ -79,7 +110,16 @@
|
||||
"settings": {
|
||||
"title": "IMPOSTAZIONI",
|
||||
"update": "Aggiorna",
|
||||
"name": "Nome"
|
||||
"name": "Nome",
|
||||
"startAudioMuted": "",
|
||||
"startVideoMuted": "",
|
||||
"selectCamera": "",
|
||||
"selectMic": "",
|
||||
"selectAudioOutput": "",
|
||||
"followMe": "",
|
||||
"noDevice": "",
|
||||
"noPermission": "",
|
||||
"avatarUrl": ""
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Clicca per modificare il tuo<br/>nome visualizzato",
|
||||
@@ -88,7 +128,8 @@
|
||||
"mute": "Il partecipante è in muto",
|
||||
"kick": "Espelli",
|
||||
"muted": "Audio disattivato",
|
||||
"domute": "Disattiva audio"
|
||||
"domute": "Disattiva audio",
|
||||
"flip": ""
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Bitrate:",
|
||||
@@ -118,23 +159,28 @@
|
||||
"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)!"
|
||||
"grantedToUnknown": "Permessi di moderatore garantiti a $t(somebody)!",
|
||||
"muted": "Hai iniziato la conversazione con l'audio disattivato.",
|
||||
"mutedTitle": "Hai l'audio disattivato!",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"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.",
|
||||
"popupError": "",
|
||||
"passwordError": "",
|
||||
"passwordError2": "",
|
||||
"connectError": "Oops! Qualcosa è andato storto e non ti puoi collegare alla conferenza.",
|
||||
"connecting": "",
|
||||
"error": "",
|
||||
"connectErrorWithMsg": "Oops! Qualcosa è andato storto e non ti puoi collegare alla conferenza: __msg__",
|
||||
"connecting": "Connessione",
|
||||
"error": "Errore",
|
||||
"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!",
|
||||
"jicofoUnavailable": "",
|
||||
"maxUsersLimitReached": "",
|
||||
"lockTitle": "Blocco fallito",
|
||||
"lockMessage": "Impossibile bloccare la conferenza.",
|
||||
"lockMessage": "",
|
||||
"warning": "Attenzione",
|
||||
"passwordNotSupported": "Le password sulla stanza non sono al momento supportate.",
|
||||
"sorry": "Spiacente",
|
||||
@@ -146,24 +192,25 @@
|
||||
"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:<br/><b>__room__ </b></br> Puoi autenticarti per creare la stanza o aspettare che qualcun altro lo faccia per te.",
|
||||
"Authenticate": "Autenticazione",
|
||||
"shareVideoTitle": "",
|
||||
"shareVideoLinkError": "",
|
||||
"removeSharedVideoTitle": "",
|
||||
"removeSharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"WaitingForHost": "In attesa dell'organizzatore ...",
|
||||
"WaitForHostMsg": "La conferenza <b>__room__ </b> non è ancora iniziata. Se sei l'organizzatore sei pregato di autenticarti, altrimenti ti preghiamo di attendere l'arrivo dell'organizzatore.",
|
||||
"IamHost": "Sono l'organizzatore",
|
||||
"Cancel": "Annulla",
|
||||
"retry": "Riprova",
|
||||
"logoutTitle": "Logout",
|
||||
"logoutQuestion": "Vuoi disconnetterti e interrompere la conferenza ?",
|
||||
"sessTerminated": "Sessione Terminata",
|
||||
"hungUp": "Hai terminato la conversazione",
|
||||
"hungUp": "",
|
||||
"joinAgain": "Entra ancora",
|
||||
"Share": "Condividi",
|
||||
"preziLinkError": "Fornire un link Prezi esatto.",
|
||||
"Save": "Salva",
|
||||
"recording": "",
|
||||
"recordingToken": "Inserire token di registrazione",
|
||||
"Dial": "Componi",
|
||||
"sipMsg": "Inserire numero SIP",
|
||||
@@ -183,17 +230,38 @@
|
||||
"reservationErrorMsg": "Codice di errore: __code__, messaggio: __msg__",
|
||||
"password": "password",
|
||||
"userPassword": "password utente",
|
||||
"token": "token"
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "",
|
||||
"displayNameRequired": "",
|
||||
"extensionRequired": "",
|
||||
"firefoxExtensionPrompt": "",
|
||||
"feedbackQuestion": "",
|
||||
"thankYou": "",
|
||||
"sorryFeedback": "",
|
||||
"liveStreaming": "",
|
||||
"streamKey": "",
|
||||
"startLiveStreaming": "",
|
||||
"stopStreamingWarning": "",
|
||||
"stopRecordingWarning": "",
|
||||
"stopLiveStreaming": "",
|
||||
"stopRecording": "",
|
||||
"doNotShowWarningAgain": "",
|
||||
"permissionDenied": "",
|
||||
"screenSharingPermissionDeniedError": "",
|
||||
"micErrorPresent": "",
|
||||
"cameraErrorPresent": "",
|
||||
"cameraUnsupportedResolutionError": "",
|
||||
"cameraUnknownError": "",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "",
|
||||
"cameraConstraintFailedError": "",
|
||||
"micUnknownError": "",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "",
|
||||
"micConstraintFailedError": ""
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
"Questa conferenza è protetta da password. Utilizzare il seguente PIN alla connessione:",
|
||||
"",
|
||||
"",
|
||||
"__sharedKey__",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"sharedKey": "",
|
||||
"subject": "Invito su __appName__ (__conferenceName__)",
|
||||
"body": [
|
||||
"Ciao, Vorrei invitarti alla conferenza che ho appena creato su __appName__ .",
|
||||
@@ -216,6 +284,7 @@
|
||||
"connection": {
|
||||
"ERROR": "Errore",
|
||||
"CONNECTING": "Connessione",
|
||||
"RECONNECTING": "Si è verificato un problema di rete. Riconnessione...",
|
||||
"CONNFAIL": "Connessione non riuscita",
|
||||
"AUTHENTICATING": "Autenticazione",
|
||||
"AUTHFAIL": "Autenticazione fallita",
|
||||
@@ -223,5 +292,25 @@
|
||||
"DISCONNECTED": "Disconnesso",
|
||||
"DISCONNECTING": "Disconnessione in corso",
|
||||
"ATTACHED": "Collegato"
|
||||
},
|
||||
"recording": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"error": "",
|
||||
"unavailable": ""
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"unavailable": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"streamIdRequired": "",
|
||||
"error": "",
|
||||
"busy": ""
|
||||
}
|
||||
}
|
||||
@@ -1,224 +1,323 @@
|
||||
{
|
||||
"contactlist": "",
|
||||
"connectionsettings": "",
|
||||
"poweredby": "",
|
||||
"downloadlogs": "",
|
||||
"feedback": "",
|
||||
"roomUrlDefaultMsg": "",
|
||||
"participant": "",
|
||||
"me": "",
|
||||
"speaker": "",
|
||||
"defaultNickname": "",
|
||||
"defaultPreziLink": "",
|
||||
"contactlist": "Lista de contactes",
|
||||
"connectionsettings": "Paramètres de connexion",
|
||||
"poweredby": "Produit per",
|
||||
"downloadlogs": "Telecargament dels logs",
|
||||
"feedback": "Donatz-nos vòstre vejaire",
|
||||
"roomUrlDefaultMsg": "Vòstra conferéncia es en cors de creacion...",
|
||||
"participant": "Participant",
|
||||
"me": "ieu",
|
||||
"speaker": "Nautparlaire",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "ex. Joan Delpuèch",
|
||||
"defaultLink": "ex. __url__",
|
||||
"calling": "",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "",
|
||||
"raiseHand": "",
|
||||
"pushToTalk": "",
|
||||
"toggleScreensharing": "",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleShortcuts": "",
|
||||
"focusLocal": "",
|
||||
"focusRemote": "",
|
||||
"toggleChat": "",
|
||||
"mute": "",
|
||||
"videoMute": ""
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "",
|
||||
"roomname": "",
|
||||
"disable": "",
|
||||
"go": "Crear",
|
||||
"roomname": "Sasissètz un nom de sala",
|
||||
"disable": "Afichar pas mai aquesta pagina",
|
||||
"feature1": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "De bon utilizar",
|
||||
"content": "Cap de telecargament pas requesit. __app__ s'utiliza dirèctament dempuèi vòstre navigador. Partejar simplament l'URL de vòstra conferéncia amb los autres per començar."
|
||||
},
|
||||
"feature2": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Benda passanta febla",
|
||||
"content": "Las videoconferéncias de mantun participant necessitan mens de 128 kbps. Lo partiment d'ecran e las conferéncias amb solament d'àudio son possiblas amb plan mens de debit."
|
||||
},
|
||||
"feature3": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Open source",
|
||||
"content": "__app__ es jos licéncia Apache. Sètz liure de telecargar, d'utilizar, de modificar e de partejar __app__ segon aquesta licéncia liura."
|
||||
},
|
||||
"feature4": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Nombre d'utilizaires illimitat",
|
||||
"content": "I a pas de restriccions artificialas a prepaus del nombre d'utilizaires o de participants a una conferéncia. La poténcia del servidor e la benda passanta son los sols factors limitants."
|
||||
},
|
||||
"feature5": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Partiment d'ecran",
|
||||
"content": "Es aisit de partejar vòstre ecran amb d'autras personas. __app__ es ideal per las presentacions en linha, los corses, e las sessions de supòrt tecnic."
|
||||
},
|
||||
"feature6": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Salas securizadas",
|
||||
"content": "Besonh de confidencialitat ? Las salas de conferéncia __app__ pòdon èsser securizadas per un senhal per exclure los convidats pas desirats, e prevenir de las interrupcions."
|
||||
},
|
||||
"feature7": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Nòtas partejadas",
|
||||
"content": "__app__ prepausa Etherpad, un editor de tèxte collaboratiu en temps real qu'es parfèit pels procèsses verbals, l'edicion d'articles e plan mai encara."
|
||||
},
|
||||
"feature8": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
"title": "Estatisticas d'utilizacion",
|
||||
"content": "Aprenètz mai a prepaus de vòstres utilizaires amb una integracion aisida de Piwik, Google Analytics e d'autres sistèmas d'estatisticas e supervision d'utilizacion."
|
||||
}
|
||||
},
|
||||
"toolbar": {
|
||||
"mute": "",
|
||||
"videomute": "",
|
||||
"authenticate": "",
|
||||
"record": "",
|
||||
"lock": "",
|
||||
"invite": "",
|
||||
"chat": "",
|
||||
"prezi": "",
|
||||
"etherpad": "",
|
||||
"sharescreen": "",
|
||||
"fullscreen": "",
|
||||
"sip": "",
|
||||
"Settings": "",
|
||||
"hangup": "",
|
||||
"login": "",
|
||||
"logout": "",
|
||||
"dialpad": ""
|
||||
"mute": "Mut / Actiu",
|
||||
"videomute": "Aviar / Arrestar la camèra",
|
||||
"authenticate": "Autentificatz-vos",
|
||||
"lock": "Verrolhar / desverrolhar la sala",
|
||||
"invite": "Convidar de participants",
|
||||
"chat": "Dobrir / tampar lo chat",
|
||||
"etherpad": "Document partejat",
|
||||
"sharedvideo": "Partejar una vidèo Youtube",
|
||||
"sharescreen": "Partejar mon ecran",
|
||||
"fullscreen": "Activar / Désactivar l'ecran complet",
|
||||
"sip": "Sonar un numèro SIP",
|
||||
"Settings": "Paramètres",
|
||||
"hangup": "Tornar penjar",
|
||||
"login": "Connexion",
|
||||
"logout": "Desconnexion",
|
||||
"dialpad": "Afichar lo clavièr de numerotacion",
|
||||
"sharedVideoMutedPopup": "Vòstra vidèo es estada mesa en mut<br/>per que poscatz parlar als autres participants.",
|
||||
"micMutedPopup": "Vòstre microfòn es estat desactivat per fin que <br/>poscatz profeitar plenament de vòstra vidèo partejada.",
|
||||
"unableToUnmutePopup": "Podètz pas reactivar vòstre microfòn pendent que la vidèo partejada es activada.",
|
||||
"cameraDisabled": "",
|
||||
"micDisabled": ""
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "",
|
||||
"filmstrip": "",
|
||||
"contactlist": ""
|
||||
"chat": "Dobrir / tampar lo chat",
|
||||
"filmstrip": "Mostrar / amagar ma vidèo miniatura",
|
||||
"contactlist": "Dobrir / tampar ma lista de contactes"
|
||||
},
|
||||
"chat": {
|
||||
"nickname": {
|
||||
"title": "",
|
||||
"popover": ""
|
||||
"title": "Sasissètz un escais dins lo camp çaijós",
|
||||
"popover": "Causissètz un escais"
|
||||
},
|
||||
"messagebox": ""
|
||||
"messagebox": "Sasissètz vòstre tèxte..."
|
||||
},
|
||||
"settings": {
|
||||
"title": "",
|
||||
"update": "",
|
||||
"name": "",
|
||||
"startAudioMuted": "",
|
||||
"startVideoMuted": ""
|
||||
"title": "PARAMÈTRES",
|
||||
"update": "Mesa a jorn",
|
||||
"name": "Nom",
|
||||
"startAudioMuted": "Aviar sens son",
|
||||
"startVideoMuted": "Aviar sens vidèo",
|
||||
"selectCamera": "Seleccionatz una camèra",
|
||||
"selectMic": "Seleccionatz un microfòn",
|
||||
"selectAudioOutput": "",
|
||||
"followMe": "Activar \"me seguir\"",
|
||||
"noDevice": "",
|
||||
"noPermission": "",
|
||||
"avatarUrl": ""
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "",
|
||||
"moderator": "",
|
||||
"videomute": "",
|
||||
"mute": "",
|
||||
"kick": "",
|
||||
"muted": "",
|
||||
"domute": ""
|
||||
"editnickname": "Clicatz per modificar<br/>vòstre nom",
|
||||
"moderator": "Lo proprietari de<br/>aquesta conferéncia",
|
||||
"videomute": "Un participant a<br/>arrestat sa camèra.",
|
||||
"mute": "Un participant a copat son micro",
|
||||
"kick": "Exclure",
|
||||
"muted": "Mut",
|
||||
"domute": "Copar lo son",
|
||||
"flip": ""
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "",
|
||||
"packetloss": "",
|
||||
"resolution": "",
|
||||
"less": "",
|
||||
"more": "",
|
||||
"address": "",
|
||||
"remoteport": "",
|
||||
"remoteport_plural": "",
|
||||
"localport": "",
|
||||
"localport_plural": "",
|
||||
"localaddress": "",
|
||||
"localaddress_plural": "",
|
||||
"remoteaddress": "",
|
||||
"remoteaddress_plural": "",
|
||||
"transport": "",
|
||||
"bandwidth": "",
|
||||
"na": ""
|
||||
"bitrate": "Debit :",
|
||||
"packetloss": "Pèrda de paquets :",
|
||||
"resolution": "Resolucion :",
|
||||
"less": "Amagar lo detalh",
|
||||
"more": "Mostrar lo deta1h",
|
||||
"address": "Adreça :",
|
||||
"remoteport": "Pòrt distant :",
|
||||
"remoteport_plural": "Pòrts distants :",
|
||||
"localport": "Pòrt local :",
|
||||
"localport_plural": "Pòrts locals :",
|
||||
"localaddress": "Adreça locala :",
|
||||
"localaddress_plural": "Adreças localas :",
|
||||
"remoteaddress": "Adreça distanta :",
|
||||
"remoteaddress_plural": "Adreças distantas :",
|
||||
"transport": "Transpòrt :",
|
||||
"bandwidth": "Benda passanta estimada :",
|
||||
"na": "Tornatz aicí per afichar las informacions de connexion un còp la conferéncia aviada"
|
||||
},
|
||||
"notify": {
|
||||
"disconnected": "",
|
||||
"moderator": "",
|
||||
"connected": "",
|
||||
"somebody": "",
|
||||
"me": "",
|
||||
"focus": "",
|
||||
"focusFail": "",
|
||||
"grantedTo": "",
|
||||
"grantedToUnknown": "",
|
||||
"muted": "",
|
||||
"mutedTitle": ""
|
||||
"disconnected": "desconnectat",
|
||||
"moderator": "Dreits moderator acordats !",
|
||||
"connected": "connectat",
|
||||
"somebody": "Qualqu'un",
|
||||
"me": "Ieu",
|
||||
"focus": "Focus de conferéncia",
|
||||
"focusFail": "__component__ es pas disponible - ensajatz tornamai dins __ms__ sec",
|
||||
"grantedTo": "Dreits moderator acordats a __to__ !",
|
||||
"grantedToUnknown": "Dreits moderator acordats a $t(somebody) !",
|
||||
"muted": "Avètz començat la conversacion en mut.",
|
||||
"mutedTitle": "Sètz en mut !",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "",
|
||||
"popupError": "",
|
||||
"passwordError": "",
|
||||
"passwordError2": "",
|
||||
"connectError": "",
|
||||
"connectErrorWithMsg": "",
|
||||
"connecting": "",
|
||||
"error": "",
|
||||
"detectext": "",
|
||||
"failtoinstall": "",
|
||||
"failedpermissions": "",
|
||||
"bridgeUnavailable": "",
|
||||
"lockTitle": "",
|
||||
"lockMessage": "",
|
||||
"warning": "",
|
||||
"passwordNotSupported": "",
|
||||
"sorry": "",
|
||||
"internalError": "",
|
||||
"unableToSwitch": "",
|
||||
"SLDFailure": "",
|
||||
"SRDFailure": "",
|
||||
"oops": "",
|
||||
"defaultError": "",
|
||||
"passwordRequired": "",
|
||||
"Ok": "",
|
||||
"removePreziTitle": "",
|
||||
"removePreziMsg": "",
|
||||
"sharePreziTitle": "",
|
||||
"sharePreziMsg": "",
|
||||
"Remove": "",
|
||||
"WaitingForHost": "",
|
||||
"WaitForHostMsg": "",
|
||||
"IamHost": "",
|
||||
"Cancel": "",
|
||||
"retry": "",
|
||||
"logoutTitle": "",
|
||||
"logoutQuestion": "",
|
||||
"sessTerminated": "",
|
||||
"hungUp": "",
|
||||
"joinAgain": "",
|
||||
"Share": "",
|
||||
"preziLinkError": "",
|
||||
"Save": "",
|
||||
"recordingToken": "",
|
||||
"Dial": "",
|
||||
"sipMsg": "",
|
||||
"passwordCheck": "",
|
||||
"passwordMsg": "",
|
||||
"Invite": "",
|
||||
"shareLink": "",
|
||||
"settings1": "",
|
||||
"settings2": "",
|
||||
"settings3": "",
|
||||
"yourPassword": "",
|
||||
"Back": "",
|
||||
"serviceUnavailable": "",
|
||||
"gracefulShutdown": "",
|
||||
"Yes": "",
|
||||
"reservationError": "",
|
||||
"reservationErrorMsg": "",
|
||||
"password": "",
|
||||
"userPassword": "",
|
||||
"token": "",
|
||||
"tokenAuthFailed": "",
|
||||
"displayNameRequired": "",
|
||||
"extensionRequired": "",
|
||||
"firefoxExtensionPrompt": "",
|
||||
"feedbackQuestion": "",
|
||||
"thankYou": "",
|
||||
"sorryFeedback": ""
|
||||
"kickMessage": "Ops! Sètz estat bandit de la reünion !",
|
||||
"popupError": "Vòstre navigador blòca las fenèstras popup d'aqueste site. Mercé d'activar las popups dins los paramètres de seguretat de vòstre navigador e d'ensajar tornamai.",
|
||||
"passwordError": "Aquesta conversacion es actualament protegida per un senhal. Sol lo proprietari de la conferéncia pòt definir un senhal.",
|
||||
"passwordError2": "Actualament, aquesta conversacion es pas protegida per un senhal. Sol lo proprietari de la conferéncia pòt definir un senhal.",
|
||||
"connectError": "Ops! Quicòm a trucat e la connexion a la conferéncia es impossibla.",
|
||||
"connectErrorWithMsg": "Ops! Quicòm a trucat e la connexion a la conferéncia es impossibla: __msg__",
|
||||
"connecting": "Connexion en cors",
|
||||
"error": "Error",
|
||||
"detectext": "Una error s'es produita pendent la deteccion de l'extension de partiment d'ecran.",
|
||||
"failtoinstall": "Fracàs de l'installacion de l'extension de partiment d'ecran",
|
||||
"failedpermissions": "Fracàs d'obtencion de las permissions per utilizar lo micro e/o la camèra.",
|
||||
"bridgeUnavailable": "Lo pont de visioconferéncia Jitsi es indisponible pel moment. Ensajatz tornamai pus tard !",
|
||||
"jicofoUnavailable": "Lo pont de visioconferéncia Jitsi es indisponible pel moment. Ensajatz tornamai pus tard !",
|
||||
"maxUsersLimitReached": "Lo limit pel nombre maximum de participants a la conferéncia es estat atent. La conferéncia es plena. Ensajatz tornamai pus tard !",
|
||||
"lockTitle": "Fracàs del verrolhatge",
|
||||
"lockMessage": "Impossible de verrolhar la conferéncia.",
|
||||
"warning": "Avertiment",
|
||||
"passwordNotSupported": "Los senhals de conferéncia son pas suportats.",
|
||||
"sorry": "O planhèm",
|
||||
"internalError": "Una error intèrna de l'aplicacion s'es produita [setRemoteDescription]",
|
||||
"unableToSwitch": "Impossible de cambiar lo flux vidèo.",
|
||||
"SLDFailure": "Ops! Quicòm a trucat e lo micro es pas estat copat! (Fracàs SLD)",
|
||||
"SRDFailure": "Ops! Quicòm a trucat e la camèra es pas estada copada! (Fracàs SRD)",
|
||||
"oops": "Ops !",
|
||||
"defaultError": "Una error s'es produita",
|
||||
"passwordRequired": "Senhal requesit",
|
||||
"Ok": "D'acòrdi",
|
||||
"Remove": "Suprimir",
|
||||
"shareVideoTitle": "Partejar una vidèo",
|
||||
"shareVideoLinkError": "Se vos plai, provesissètz un ligam Youtube foncional.",
|
||||
"removeSharedVideoTitle": "Suprimir la vidèo partejada",
|
||||
"removeSharedVideoMsg": "Sètz segur que volètz suprimir vòstra vidèo partejada ?",
|
||||
"alreadySharedVideoMsg": "Un autre participant parteja ja una vidèo. Aquesta conferéncia permet pas qu'una sola vidèo partejada a l'encòp.",
|
||||
"WaitingForHost": "En espèra de l'òste ...",
|
||||
"WaitForHostMsg": "La conferéncia <b> __ room__ </b> es pas encara començat. Se sètz l'òste, mercé de vos autentificar. Siquenon, mercé d'esperar que l'òste arribe.",
|
||||
"IamHost": "Soi l’òste",
|
||||
"Cancel": "Anullar",
|
||||
"retry": "Ensajar tornamai",
|
||||
"logoutTitle": "Desconnexion",
|
||||
"logoutQuestion": "Sètz segur que vos volètz desconnectar e arrestar la conferéncia ?",
|
||||
"sessTerminated": "Session acabada",
|
||||
"hungUp": "Avètz tornat penjar",
|
||||
"joinAgain": "Rejonhètz tornamai la conferéncia",
|
||||
"Share": "Partejar",
|
||||
"Save": "Salvar",
|
||||
"recording": "Enregistrament",
|
||||
"recordingToken": "Sasissètz un geton d'enregistrament",
|
||||
"Dial": "Compausar",
|
||||
"sipMsg": "Sasissètz un numèro SIP",
|
||||
"passwordCheck": "Sètz segur que volètz suprimir vòstre senhal ?",
|
||||
"passwordMsg": "Sasissètz un senhal per verrolhar la conferéncia",
|
||||
"Invite": "Convidar",
|
||||
"shareLink": "Partejatz aqueste ligam amb totas las personas que volètz convidar",
|
||||
"settings1": "Configuratz vòstra conferéncia",
|
||||
"settings2": "Los participants rejonhon la conferéncia en essent muts",
|
||||
"settings3": "Escaisses requesits<br/><br/>Sasissètz un senhal per verrolhar la conferéncia :",
|
||||
"yourPassword": "vòstre senhal",
|
||||
"Back": "Retorn",
|
||||
"serviceUnavailable": "Servici indisponible",
|
||||
"gracefulShutdown": "Lo servici es actualament en mantenença. Ensajatz tornamai pus tard.",
|
||||
"Yes": "Òc",
|
||||
"reservationError": "Error del sistèma de reservacion",
|
||||
"reservationErrorMsg": "Còdi d'error: __code__, messatge: __msg__",
|
||||
"password": "senhal",
|
||||
"userPassword": "senhal utilizaire",
|
||||
"token": "geton",
|
||||
"tokenAuthFailed": "Fracàs de l'autentificacion amb lo servidor XMPP : geton pas valid",
|
||||
"displayNameRequired": "Sasissètz vòstre nom",
|
||||
"extensionRequired": "Extension requesida :",
|
||||
"firefoxExtensionPrompt": "Vos cal installar una extension Firefox per utilizar lo partiment d'ecran. Mercé ensajar tornamai aprèp l'installacion <a href='__url__'>dempuèi aqueste ligam</a> !",
|
||||
"feedbackQuestion": "Cossí èra vòstra conferéncia ?",
|
||||
"thankYou": "Mercé d'aver utilizat __appName__ !",
|
||||
"sorryFeedback": "Planhèm d'aprene aquò. Ne nos volètz dire mai ?",
|
||||
"liveStreaming": "Dirècte",
|
||||
"streamKey": "Stream name/key",
|
||||
"startLiveStreaming": "Començar lo dirècte",
|
||||
"stopStreamingWarning": "Sètz segur que volètz arrestar lo dirècte?",
|
||||
"stopRecordingWarning": "Sètz segur que volètz arrestar l'enregistrament?",
|
||||
"stopLiveStreaming": "Arrestar lo dirècte",
|
||||
"stopRecording": "Arrestar l'enregistrament",
|
||||
"doNotShowWarningAgain": "",
|
||||
"permissionDenied": "",
|
||||
"screenSharingPermissionDeniedError": "",
|
||||
"micErrorPresent": "",
|
||||
"cameraErrorPresent": "",
|
||||
"cameraUnsupportedResolutionError": "",
|
||||
"cameraUnknownError": "",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "",
|
||||
"cameraConstraintFailedError": "",
|
||||
"micUnknownError": "",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "",
|
||||
"micConstraintFailedError": ""
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": "",
|
||||
"subject": "",
|
||||
"body": "",
|
||||
"and": ""
|
||||
"sharedKey": [
|
||||
"Aquesta conferéncia es protégée per un senhal. Mercé utilizar la code seguent lors de la connexion :",
|
||||
"",
|
||||
"",
|
||||
"__sharedKey __",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"subject": "Convit a la conferéncia __appName__ : __conferenceName__",
|
||||
"body": [
|
||||
"Bonjorn, vos convida a la conferéncia __appName__ que veni de crear.",
|
||||
"",
|
||||
"",
|
||||
"Clicatz sul ligam seguent per rejónher la conferéncia.",
|
||||
"",
|
||||
"",
|
||||
"__roomUrl__",
|
||||
"",
|
||||
"",
|
||||
"__sharedKeyText__",
|
||||
" Notatz que __appName__ es actualament suportat sonque per __supportedBrowsers__, doncas, vos cal utilizar un d'aqueles navigadors.",
|
||||
"",
|
||||
"",
|
||||
"A sulpic dins la conferéncia !"
|
||||
],
|
||||
"and": "e"
|
||||
},
|
||||
"connection": {
|
||||
"ERROR": "",
|
||||
"CONNECTING": "",
|
||||
"RECONNECTING": "",
|
||||
"CONNFAIL": "",
|
||||
"AUTHENTICATING": "",
|
||||
"AUTHFAIL": "",
|
||||
"CONNECTED": "",
|
||||
"DISCONNECTED": "",
|
||||
"DISCONNECTING": "",
|
||||
"ATTACHED": ""
|
||||
"ERROR": "Error",
|
||||
"CONNECTING": "Connexion en cors",
|
||||
"RECONNECTING": "Un problèma ret s'es produita. Reconnexion en cors...",
|
||||
"CONNFAIL": "Fracàs de la connexion",
|
||||
"AUTHENTICATING": "Autentificacion en cors",
|
||||
"AUTHFAIL": "Fracàs de l'autentificacion",
|
||||
"CONNECTED": "Connectat",
|
||||
"DISCONNECTED": "Desconnectat",
|
||||
"DISCONNECTING": "Desconnexion en cors",
|
||||
"ATTACHED": "Estacada"
|
||||
},
|
||||
"recording": {
|
||||
"toaster": "",
|
||||
"pending": "",
|
||||
"on": ""
|
||||
"pending": "Enregistrament en espèra de participant...",
|
||||
"on": "Enregistrament",
|
||||
"off": "Enregistrament arrestar",
|
||||
"failedToStart": "L'enregistrament n'as pas réussi a démarrer",
|
||||
"buttonTooltip": "Aviar / arrestar l'enregistrament",
|
||||
"error": "",
|
||||
"unavailable": ""
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "Començar lo dirècte...",
|
||||
"on": "Dirècte",
|
||||
"off": "Lo dirècte es estat arrestat",
|
||||
"unavailable": "Lo dirècte es temporàriament indisponible. Ensajatz tornamai pus tard.",
|
||||
"failedToStart": "Lo dirècte a pas capitat de s'aviar",
|
||||
"buttonTooltip": "Aviar / arrestar lo dirècte",
|
||||
"streamIdRequired": "Mercé de completar lo stream id per aviar lo dirècte.",
|
||||
"error": "",
|
||||
"busy": ""
|
||||
}
|
||||
}
|
||||
319
lang/main-ptBR.json
Normal file
319
lang/main-ptBR.json
Normal file
@@ -0,0 +1,319 @@
|
||||
{
|
||||
"contactlist": "LISTA DE CONTATO",
|
||||
"connectionsettings": "Configurações de conexão",
|
||||
"poweredby": "distribuído por",
|
||||
"downloadlogs": "Baixar registros",
|
||||
"feedback": "Dê seus comentários",
|
||||
"roomUrlDefaultMsg": "Sua conferência está sendo criado...",
|
||||
"participant": "Participante",
|
||||
"me": "eu",
|
||||
"speaker": "Orador",
|
||||
"raisedHand": "Gostaria de falar",
|
||||
"defaultNickname": "ex. João Pedro",
|
||||
"defaultLink": "i.e. __url__",
|
||||
"calling": "Chamando __name__ ...",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "Dê as permissões para usar sua câmera e microfone pressionando o botão <b> <i>Permitir</i> </b>",
|
||||
"chromeGrantPermissions": "Dê as permissões para usar sua câmera e microfone pressionando o botão <b> <i>Permitir</i> </b>",
|
||||
"androidGrantPermissions": "Dê as permissões para usar sua câmera e microfone pressionando o botão <b> <i>Permitir</i> </b>",
|
||||
"firefoxGrantPermissions": "Dê as permissões para usar sua câmera e microfone pressionando o botão <b> <i>Compartilhar Dispositivos Selecionados</i> </b>",
|
||||
"operaGrantPermissions": "Dê as permissões para usar sua câmera e microfone pressionando o botão <b> <i>Permitir</i> </b>",
|
||||
"iexplorerGrantPermissions": "Dê as permissões para usar sua câmera e microfone pressionando o botão <b> <i>OK</i> </b>",
|
||||
"safariGrantPermissions": "Dê as permissões para usar sua câmera e microfone pressionando o botão <b> <i>OK</i> </b>",
|
||||
"nwjsGrantPermissions": "Dê as permissões para usar sua câmera e microfone"
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "Atalhos de teclado:",
|
||||
"raiseHand": "Erguer sua mão.",
|
||||
"pushToTalk": "Pressione para falar.",
|
||||
"toggleScreensharing": "Trocar entre câmera e compartilhamento de tela.",
|
||||
"toggleFilmstrip": "Mostrar ou ocultar a tira de filme.",
|
||||
"toggleShortcuts": "Mostrar ou ocultar este menu de ajuda.",
|
||||
"focusLocal": "Foco no vídeo local.",
|
||||
"focusRemote": "Foco em um dos vídeos remotos.",
|
||||
"toggleChat": "Abrir ou fechar o painel de bate-papo.",
|
||||
"mute": "Deixar mudo ou não o microfone.",
|
||||
"videoMute": "Parar ou iniciar o vídeo local."
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "IR",
|
||||
"roomname": "Digite o nome da sala",
|
||||
"disable": "Não mostre esta página novamente",
|
||||
"feature1": {
|
||||
"title": "Simples para usar",
|
||||
"content": "Não precisa baixar nada. __app__ trabalha diretamente no seu navegador. Simplesmente compartilhe sua URL da conferência com outros para começar."
|
||||
},
|
||||
"feature2": {
|
||||
"title": "Largura de banda baixa",
|
||||
"content": "Conferências de vídeo de multipartes trabalha com tão pouco quanto 128 kbps. Compartilhamento de tela e conferências de áudio somente são possíveis com muito menos."
|
||||
},
|
||||
"feature3": {
|
||||
"title": "Código aberto",
|
||||
"content": "__app__ é licenciado sob a Licença Apache. Você é livre para baixar, usar, modificar e compartilhar ela com a mesma licença."
|
||||
},
|
||||
"feature4": {
|
||||
"title": "Usuários ilimitados",
|
||||
"content": "Aqui não há restrições artificiais no número de usuários ou participantes da conferência. A potência do servidor e largura de banda são os únicos fatores limitantes."
|
||||
},
|
||||
"feature5": {
|
||||
"title": "Compartilhamento de tela",
|
||||
"content": "É fácil compartilhar sua tela com outros. __app__ é ideal para apresentações online, leituras, e sessões de suporte técnico."
|
||||
},
|
||||
"feature6": {
|
||||
"title": "Salas seguras",
|
||||
"content": "Precisa alguma privacidade? Salas de conferência do __app__ podem ser seguras com uma senha para excluir visitantes indesejados e prevenir interrupções."
|
||||
},
|
||||
"feature7": {
|
||||
"title": "Notas compartilhadas",
|
||||
"content": "__app_ disponibiliza o Etherpad, um editor de texto colaborativo em tempo real, que é ótimo para reuniões rápidas, escrevendo artigos, e mais."
|
||||
},
|
||||
"feature8": {
|
||||
"title": "Estatísticas de uso",
|
||||
"content": "Aprenda sobre seus usuários através de integração fácil com o Piwik, Google Analytics, e outros sistemas de monitoramento e estatísticas."
|
||||
}
|
||||
},
|
||||
"toolbar": {
|
||||
"mute": "Mudo / Não mudo",
|
||||
"videomute": "Iniciar / parar a câmera",
|
||||
"authenticate": "Autenticar",
|
||||
"lock": "Travar / destravar a sala",
|
||||
"invite": "Convidar outros",
|
||||
"chat": "Abrir / fechar bate-papo",
|
||||
"etherpad": "Documento compartilhado",
|
||||
"sharedvideo": "Compartilhar um vídeo do YouTube",
|
||||
"sharescreen": "Compartilhar tela",
|
||||
"fullscreen": "Entrar / Sair de Tela Cheia",
|
||||
"sip": "Chamar número SIP",
|
||||
"Settings": "Configurações",
|
||||
"hangup": "Desligar",
|
||||
"login": "Iniciar sessão",
|
||||
"logout": "Encerrar sessão",
|
||||
"dialpad": "Mostrar teclas de discagem",
|
||||
"sharedVideoMutedPopup": "Seu vídeo compartilhado está mudo assim<br/>você pode falar com os outros participantes.",
|
||||
"micMutedPopup": "Seu microfone está mudo assim que você<br/>pode curtir plenamente seu vídeo compartilhado.",
|
||||
"unableToUnmutePopup": "Você não pode sair do mudo enquanto seu vídeo compartilhado está ativo.",
|
||||
"cameraDisabled": "A câmera não está disponível",
|
||||
"micDisabled": "O microfone não está disponível"
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Abrir / fechar bate-papo",
|
||||
"filmstrip": "Mostrar / ocultar a tira de usuários",
|
||||
"contactlist": "Abrir / fechar a lista de contatos"
|
||||
},
|
||||
"chat": {
|
||||
"nickname": {
|
||||
"title": "Digite um apelido na caixa a seguir",
|
||||
"popover": "Escolha um apelido"
|
||||
},
|
||||
"messagebox": "Digite um texto..."
|
||||
},
|
||||
"settings": {
|
||||
"title": "CONFIGURAÇÕES",
|
||||
"update": "Atualizar",
|
||||
"name": "Nome",
|
||||
"startAudioMuted": "Iniciar sem áudio",
|
||||
"startVideoMuted": "Iniciar sem vídeo",
|
||||
"selectCamera": "Selecione a câmera",
|
||||
"selectMic": "Selecionar o microfone",
|
||||
"selectAudioOutput": "Selecionar a saída de áudio",
|
||||
"followMe": "Habilitar o siga-me",
|
||||
"noDevice": "Nenhum",
|
||||
"noPermission": "Permissão para usar o dispositivo não concedida",
|
||||
"avatarUrl": "URL do Avatar"
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Clique para editar o seu <br/>nome de exibição",
|
||||
"moderator": "O proprietário<br/>desta conferência",
|
||||
"videomute": "Participante parou<br/>a câmera.",
|
||||
"mute": "Participante está mudo",
|
||||
"kick": "Chutar fora",
|
||||
"muted": "Mudo",
|
||||
"domute": "Mudo",
|
||||
"flip": "Inverter"
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Taxa de bits:",
|
||||
"packetloss": "Perda de pacote:",
|
||||
"resolution": "Resolução:",
|
||||
"less": "Mostrar menos",
|
||||
"more": "Mostrar mais",
|
||||
"address": "Endereço:",
|
||||
"remoteport": "Porta remota:",
|
||||
"remoteport_plural": "Portas remotas:",
|
||||
"localport": "Porta local:",
|
||||
"localport_plural": "Portas locais:",
|
||||
"localaddress": "Endereço local:",
|
||||
"localaddress_plural": "Endereços locais:",
|
||||
"remoteaddress": "Endereço remoto:",
|
||||
"remoteaddress_plural": "Endereços remotos:",
|
||||
"transport": "Transporte:",
|
||||
"bandwidth": "Largura de banda estimada:",
|
||||
"na": "Volte aqui para informações de conexão uma vez que a conferência inicie"
|
||||
},
|
||||
"notify": {
|
||||
"disconnected": "desconectado",
|
||||
"moderator": "Direitos de moderador concedidos!",
|
||||
"connected": "conectado",
|
||||
"somebody": "Alguém",
|
||||
"me": "Eu",
|
||||
"focus": "Foco da conferência",
|
||||
"focusFail": "__component__ não disponĩvel - tente em __ms__ seg.",
|
||||
"grantedTo": "Direitos de moderador concedido para __to__!",
|
||||
"grantedToUnknown": "Direitos de moderador concedido para $t(somebody)!",
|
||||
"muted": "Você iniciou uma conversa muda.",
|
||||
"mutedTitle": "Você está mudo!",
|
||||
"raisedHand": "Gostaria de falar."
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "Ouch! Você o chutou para fora da reunião!",
|
||||
"popupError": "Seu navegador está bloqueando janelas popup deste site. Por favor, habilite popups nas configurações de segurança do seu navegador e tente novamente.",
|
||||
"passwordError": "Esta conversa está protegida atualmente por uma senha. Somente o dono da conferência pode definir a senha.",
|
||||
"passwordError2": "Esta reunião não está protegida por senha atualmente. Somente o dono da conferência pode definir a senha.",
|
||||
"connectError": "Oops! Alguma coisa está errada e nós não pudemos conectar à conferência.",
|
||||
"connectErrorWithMsg": "Oops! Alguma coisa está errada e não podemos conectar à conferência: __msg__",
|
||||
"connecting": "Conectando",
|
||||
"error": "Erro",
|
||||
"detectext": "Erro enquanto tenta detectar a extensão de compartilhamento de tela.",
|
||||
"failtoinstall": "Falhou a instalação da extensão de compartilhamento de tela",
|
||||
"failedpermissions": "Falha ao obter permissões para usar o microfone e/ou câmera local.",
|
||||
"bridgeUnavailable": "Jitsi Videobridge está atualmente indisponível. Por favor, tente mais tarde!",
|
||||
"jicofoUnavailable": "Jicofo está atualmente indisponível. Por favor, tente mais tarde!",
|
||||
"maxUsersLimitReached": "O limite para o número máximo de participantes na conferência foi atingida. A conferência está cheia. Por favor, tente mais tarde!",
|
||||
"lockTitle": "Bloqueio falhou",
|
||||
"lockMessage": "Falha ao travar a conferência.",
|
||||
"warning": "Atenção",
|
||||
"passwordNotSupported": "Senhas de salas não são suportadas atualmente.",
|
||||
"sorry": "Desculpe",
|
||||
"internalError": "Erro interno de aplicação [setRemoteDescription]",
|
||||
"unableToSwitch": "Impossível trocar o fluxo de vídeo.",
|
||||
"SLDFailure": "Oops! Alguma coisa está errada e nós falhamos em silenciar! (Falha do SLD)",
|
||||
"SRDFailure": "Oops! Alguma coisa está errada e nós falhamos em parar o vídeo! (Falha do SRD)",
|
||||
"oops": "Oops!",
|
||||
"defaultError": "Aqui teve algum tipo de erro",
|
||||
"passwordRequired": "Senha requerida",
|
||||
"Ok": "Ok",
|
||||
"Remove": "Remover",
|
||||
"shareVideoTitle": "Compartilhar um vídeo",
|
||||
"shareVideoLinkError": "Por favor, forneça um link do youtube correto.",
|
||||
"removeSharedVideoTitle": "Remover vídeo compartilhado",
|
||||
"removeSharedVideoMsg": "Está certo que gostaria de remover seu vídeo compartilhado?",
|
||||
"alreadySharedVideoMsg": "Outro participante já está compartilhando o vídeo. Esta conferência permite somente um vídeo compartilhado por vez.",
|
||||
"WaitingForHost": "Esperando o hospedeiro...",
|
||||
"WaitForHostMsg": "A conferência <b>__room__</b> não foi iniciada. Se você é o hospedeiro, então autentique-se. Caso contrário, aguarde o hospedeiro chegar.",
|
||||
"IamHost": "Eu sou o hospedeiro",
|
||||
"Cancel": "Cancelar",
|
||||
"retry": "Tentar novamente",
|
||||
"logoutTitle": "Encerrar sessão",
|
||||
"logoutQuestion": "Está certo em encerrar a sessão e terminar a conferência?",
|
||||
"sessTerminated": "Sessão Terminada",
|
||||
"hungUp": "Você desconectou",
|
||||
"joinAgain": "Conectar novamente",
|
||||
"Share": "Compartilhar",
|
||||
"Save": "Salvar",
|
||||
"recording": "Gravando",
|
||||
"recordingToken": "Digite o token de gravação",
|
||||
"Dial": "Discar",
|
||||
"sipMsg": "Digite o número SIP",
|
||||
"passwordCheck": "Você tem certeza que deseja remover sua senha?",
|
||||
"passwordMsg": "Definir uma senha para trancar sua sala",
|
||||
"Invite": "Convidar",
|
||||
"shareLink": "Compartilhar este link com quem você espera convidar",
|
||||
"settings1": "Configure sua conferência",
|
||||
"settings2": "Participantes entram mudos",
|
||||
"settings3": "Requer apelidos<br/><br/>Defina uma senha para trancar sua sala:",
|
||||
"yourPassword": "sua Senha",
|
||||
"Back": "Voltar",
|
||||
"serviceUnavailable": "Serviço indisponível",
|
||||
"gracefulShutdown": "Nosso serviço está desligado para manutenção. Por favor, tente mais tarde.",
|
||||
"Yes": "Sim",
|
||||
"reservationError": "Erro de sistema de reserva",
|
||||
"reservationErrorMsg": "Código do erro: __code__, mensagem: __msg__",
|
||||
"password": "senha",
|
||||
"userPassword": "senha do usuário",
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "Falha em autenticar com o servidor XMPP: token inválido",
|
||||
"displayNameRequired": "Digite seu nome de exibição",
|
||||
"extensionRequired": "Extensão requerida:",
|
||||
"firefoxExtensionPrompt": "Você precisa instalar uma extensão do Firefox para compartilhar a tela. Tente novamente depois que você <a href='__url__'>pegá-lo aqui</a>!",
|
||||
"feedbackQuestion": "Como foi a chamada?",
|
||||
"thankYou": "Obrigado por usar o __appName__!",
|
||||
"sorryFeedback": "Lamentamos escutar isso. Gostaria de nos contar mais?",
|
||||
"liveStreaming": "Live Streaming",
|
||||
"streamKey": "Nome/chave do fluxo",
|
||||
"startLiveStreaming": "Iniciar live streaming",
|
||||
"stopStreamingWarning": "Você tem certeza que deseja parar o live streaming?",
|
||||
"stopRecordingWarning": "Tem certeza que deseja parar a gravação?",
|
||||
"stopLiveStreaming": "Parar o live streaming",
|
||||
"stopRecording": "Parar a gravação",
|
||||
"doNotShowWarningAgain": "Não exibir este aviso novamente",
|
||||
"permissionDenied": "Permissão Negada",
|
||||
"screenSharingPermissionDeniedError": "Você não tem permissão concedida para compartilhar sua tela.",
|
||||
"micErrorPresent": "Ocorreu um erro conectando seu microfone.",
|
||||
"cameraErrorPresent": "Ocorreu um erro conectando sua câmera.",
|
||||
"cameraUnsupportedResolutionError": "Sua câmera não suporta a resolução de vídeo requerida.",
|
||||
"cameraUnknownError": "Não pode usar a câmera por uma razão desconhecida.",
|
||||
"cameraPermissionDeniedError": "Você não tem permissão para usar sua câmera. Você ainda pode entrar na conferência, mas os outros não verão você. Use o botão da câmera na barra de endereço para fixar isto.",
|
||||
"cameraNotFoundError": "Câmera solicitada não foi encontrada.",
|
||||
"cameraConstraintFailedError": "Sua câmera não satisfaz algumas condições requeridas.",
|
||||
"micUnknownError": "Não pode usar o microfone por uma razão desconhecida.",
|
||||
"micPermissionDeniedError": "Você não tem permissão para usar seu microfone. Você ainda pode entrar na conferência, mas os outros não ouvirão você. Use o botão da câmera na barra de endereço para fixar isto.",
|
||||
"micNotFoundError": "O microfone solicitado não foi encontrado.",
|
||||
"micConstraintFailedError": "Seu microfone não satisfaz algumas condições requeridas."
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
"Esta conferência está protegida com senha. Use o seguinte código quando entrar:",
|
||||
"",
|
||||
"",
|
||||
"__sharedKey__",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"subject": "Convite para __appName__ (__conferenceName__)",
|
||||
"body": [
|
||||
"Olá, gostaria de convidá-lo para uma conferência do __appName__ na qual eu estou participando.",
|
||||
"",
|
||||
"Por favor clique no endereço a seguir para participar:",
|
||||
"",
|
||||
"__roomUrl__",
|
||||
"",
|
||||
"__sharedKeyText__",
|
||||
" Note que o __appName__ atualmente só funciona nos navegadores __supportedBrowsers__, assim é preciso abrir o link com um deles para poder participar.",
|
||||
"",
|
||||
"Aguardo sua presença!"
|
||||
],
|
||||
"and": "e"
|
||||
},
|
||||
"connection": {
|
||||
"ERROR": "Erro",
|
||||
"CONNECTING": "Conectando",
|
||||
"RECONNECTING": "Ocorreu um problema de rede. Reconectando...",
|
||||
"CONNFAIL": "Falha de conexão",
|
||||
"AUTHENTICATING": "Autenticando",
|
||||
"AUTHFAIL": "Falha de autenticação",
|
||||
"CONNECTED": "Conectado",
|
||||
"DISCONNECTED": "Desconectado",
|
||||
"DISCONNECTING": "Desconectando",
|
||||
"ATTACHED": "Anexado"
|
||||
},
|
||||
"recording": {
|
||||
"pending": "Aguardando um participante para iniciar a gravação...",
|
||||
"on": "Gravando",
|
||||
"off": "Gravação parada",
|
||||
"failedToStart": "Falha ao iniciar a gravação",
|
||||
"buttonTooltip": "Iniciar / parar gravação",
|
||||
"error": "A gravação falhou. Tente novamente.",
|
||||
"unavailable": "O serviço de gravação está indisponível. Por favor, tente mais tarde."
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "Iniciando Transmissão Ao Vivo...",
|
||||
"on": "Live Streaming",
|
||||
"off": "Transmissão ao vivo encerrada",
|
||||
"unavailable": "O serviço de transmissão ao vivo está indisponível no momento.Por favor, tente mais tarde.",
|
||||
"failedToStart": "Falha ao iniciar a transmissão ao vivo",
|
||||
"buttonTooltip": "Iniciar / parar live stream",
|
||||
"streamIdRequired": "Por favor digite o id da transmissão ao vivo para começar a transmitir.",
|
||||
"error": "Falha na transmissão ao vivo. Tente novamente",
|
||||
"busy": "Todos os gravadores estão ocupados no momento. Por favor, tente mais tarde."
|
||||
}
|
||||
}
|
||||
301
lang/main-ru.json
Normal file
301
lang/main-ru.json
Normal file
@@ -0,0 +1,301 @@
|
||||
{
|
||||
"contactlist": "",
|
||||
"connectionsettings": "",
|
||||
"poweredby": "",
|
||||
"downloadlogs": "",
|
||||
"feedback": "",
|
||||
"roomUrlDefaultMsg": "",
|
||||
"participant": "",
|
||||
"me": "",
|
||||
"speaker": "",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "",
|
||||
"defaultLink": "",
|
||||
"calling": "",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "",
|
||||
"raiseHand": "",
|
||||
"pushToTalk": "",
|
||||
"toggleScreensharing": "",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleShortcuts": "",
|
||||
"focusLocal": "",
|
||||
"focusRemote": "",
|
||||
"toggleChat": "",
|
||||
"mute": "",
|
||||
"videoMute": ""
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "",
|
||||
"roomname": "",
|
||||
"disable": "",
|
||||
"feature1": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
},
|
||||
"feature2": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
},
|
||||
"feature3": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
},
|
||||
"feature4": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
},
|
||||
"feature5": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
},
|
||||
"feature6": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
},
|
||||
"feature7": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
},
|
||||
"feature8": {
|
||||
"title": "",
|
||||
"content": ""
|
||||
}
|
||||
},
|
||||
"toolbar": {
|
||||
"mute": "",
|
||||
"videomute": "",
|
||||
"authenticate": "",
|
||||
"lock": "",
|
||||
"invite": "",
|
||||
"chat": "",
|
||||
"etherpad": "",
|
||||
"sharedvideo": "",
|
||||
"sharescreen": "",
|
||||
"fullscreen": "",
|
||||
"sip": "",
|
||||
"Settings": "",
|
||||
"hangup": "",
|
||||
"login": "",
|
||||
"logout": "",
|
||||
"dialpad": "",
|
||||
"sharedVideoMutedPopup": "",
|
||||
"micMutedPopup": "",
|
||||
"unableToUnmutePopup": "",
|
||||
"cameraDisabled": "",
|
||||
"micDisabled": ""
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "",
|
||||
"filmstrip": "",
|
||||
"contactlist": ""
|
||||
},
|
||||
"chat": {
|
||||
"nickname": {
|
||||
"title": "",
|
||||
"popover": ""
|
||||
},
|
||||
"messagebox": ""
|
||||
},
|
||||
"settings": {
|
||||
"title": "",
|
||||
"update": "",
|
||||
"name": "",
|
||||
"startAudioMuted": "",
|
||||
"startVideoMuted": "",
|
||||
"selectCamera": "",
|
||||
"selectMic": "",
|
||||
"selectAudioOutput": "",
|
||||
"followMe": "",
|
||||
"noDevice": "",
|
||||
"noPermission": "",
|
||||
"avatarUrl": ""
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "",
|
||||
"moderator": "",
|
||||
"videomute": "",
|
||||
"mute": "",
|
||||
"kick": "",
|
||||
"muted": "",
|
||||
"domute": "",
|
||||
"flip": ""
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "",
|
||||
"packetloss": "",
|
||||
"resolution": "",
|
||||
"less": "",
|
||||
"more": "",
|
||||
"address": "",
|
||||
"remoteport": "",
|
||||
"remoteport_plural_2": "",
|
||||
"localport": "",
|
||||
"localport_plural_2": "",
|
||||
"localaddress": "",
|
||||
"localaddress_plural_2": "",
|
||||
"remoteaddress": "",
|
||||
"remoteaddress_plural_2": "",
|
||||
"transport": "",
|
||||
"bandwidth": "",
|
||||
"na": ""
|
||||
},
|
||||
"notify": {
|
||||
"disconnected": "",
|
||||
"moderator": "",
|
||||
"connected": "",
|
||||
"somebody": "",
|
||||
"me": "",
|
||||
"focus": "",
|
||||
"focusFail": "",
|
||||
"grantedTo": "",
|
||||
"grantedToUnknown": "",
|
||||
"muted": "",
|
||||
"mutedTitle": "",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "",
|
||||
"popupError": "",
|
||||
"passwordError": "",
|
||||
"passwordError2": "",
|
||||
"connectError": "",
|
||||
"connectErrorWithMsg": "",
|
||||
"connecting": "",
|
||||
"error": "",
|
||||
"detectext": "",
|
||||
"failtoinstall": "",
|
||||
"failedpermissions": "",
|
||||
"bridgeUnavailable": "",
|
||||
"jicofoUnavailable": "",
|
||||
"maxUsersLimitReached": "",
|
||||
"lockTitle": "",
|
||||
"lockMessage": "",
|
||||
"warning": "",
|
||||
"passwordNotSupported": "",
|
||||
"sorry": "",
|
||||
"internalError": "",
|
||||
"unableToSwitch": "",
|
||||
"SLDFailure": "",
|
||||
"SRDFailure": "",
|
||||
"oops": "",
|
||||
"defaultError": "",
|
||||
"passwordRequired": "",
|
||||
"Ok": "",
|
||||
"Remove": "",
|
||||
"shareVideoTitle": "",
|
||||
"shareVideoLinkError": "",
|
||||
"removeSharedVideoTitle": "",
|
||||
"removeSharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"WaitingForHost": "",
|
||||
"WaitForHostMsg": "",
|
||||
"IamHost": "",
|
||||
"Cancel": "",
|
||||
"retry": "",
|
||||
"logoutTitle": "",
|
||||
"logoutQuestion": "",
|
||||
"sessTerminated": "",
|
||||
"hungUp": "",
|
||||
"joinAgain": "",
|
||||
"Share": "",
|
||||
"Save": "",
|
||||
"recording": "",
|
||||
"recordingToken": "",
|
||||
"Dial": "",
|
||||
"sipMsg": "",
|
||||
"passwordCheck": "",
|
||||
"passwordMsg": "",
|
||||
"Invite": "",
|
||||
"shareLink": "",
|
||||
"settings1": "",
|
||||
"settings2": "",
|
||||
"settings3": "",
|
||||
"yourPassword": "",
|
||||
"Back": "",
|
||||
"serviceUnavailable": "",
|
||||
"gracefulShutdown": "",
|
||||
"Yes": "",
|
||||
"reservationError": "",
|
||||
"reservationErrorMsg": "",
|
||||
"password": "",
|
||||
"userPassword": "",
|
||||
"token": "",
|
||||
"tokenAuthFailed": "",
|
||||
"displayNameRequired": "",
|
||||
"extensionRequired": "",
|
||||
"firefoxExtensionPrompt": "",
|
||||
"feedbackQuestion": "",
|
||||
"thankYou": "",
|
||||
"sorryFeedback": "",
|
||||
"liveStreaming": "",
|
||||
"streamKey": "",
|
||||
"startLiveStreaming": "",
|
||||
"stopStreamingWarning": "",
|
||||
"stopRecordingWarning": "",
|
||||
"stopLiveStreaming": "",
|
||||
"stopRecording": "",
|
||||
"doNotShowWarningAgain": "",
|
||||
"permissionDenied": "",
|
||||
"screenSharingPermissionDeniedError": "",
|
||||
"micErrorPresent": "",
|
||||
"cameraErrorPresent": "",
|
||||
"cameraUnsupportedResolutionError": "",
|
||||
"cameraUnknownError": "",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "",
|
||||
"cameraConstraintFailedError": "",
|
||||
"micUnknownError": "",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "",
|
||||
"micConstraintFailedError": ""
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": "",
|
||||
"subject": "",
|
||||
"body": "",
|
||||
"and": ""
|
||||
},
|
||||
"connection": {
|
||||
"ERROR": "",
|
||||
"CONNECTING": "",
|
||||
"RECONNECTING": "",
|
||||
"CONNFAIL": "",
|
||||
"AUTHENTICATING": "",
|
||||
"AUTHFAIL": "",
|
||||
"CONNECTED": "",
|
||||
"DISCONNECTED": "",
|
||||
"DISCONNECTING": "",
|
||||
"ATTACHED": ""
|
||||
},
|
||||
"recording": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"error": "",
|
||||
"unavailable": ""
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"unavailable": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"streamIdRequired": "",
|
||||
"error": "",
|
||||
"busy": ""
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,42 @@
|
||||
"connectionsettings": "Nastavenie spojenia",
|
||||
"poweredby": "založené na",
|
||||
"downloadlogs": "Stiahnúť logy",
|
||||
"feedback": "",
|
||||
"roomUrlDefaultMsg": "Vaša konferencia bola práve vytvorená...",
|
||||
"participant": "Účastník",
|
||||
"me": "ja",
|
||||
"speaker": "Rečník",
|
||||
"defaultNickname": "napr. __name__",
|
||||
"defaultPreziLink": "napr. __url__",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "",
|
||||
"defaultLink": "napr. __url__",
|
||||
"calling": "",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "",
|
||||
"raiseHand": "",
|
||||
"pushToTalk": "",
|
||||
"toggleScreensharing": "",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleShortcuts": "",
|
||||
"focusLocal": "",
|
||||
"focusRemote": "",
|
||||
"toggleChat": "",
|
||||
"mute": "",
|
||||
"videoMute": ""
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "Pripojiť",
|
||||
"roomname": "Zadajte názov miestnosti",
|
||||
"disable": "Nezobrazovať túto stranku pri ďalšej návšteve",
|
||||
"disable": "",
|
||||
"feature1": {
|
||||
"title": "Jednoduché na používanie",
|
||||
"content": "Nie je potrebne nič sťahovať. __app_ funguje priamo vo Vašom prehliadači. Jednoducho zdieľajte URL adresu konferenčnej miestnosti a možete začať."
|
||||
@@ -50,20 +76,24 @@
|
||||
"mute": "Vypnúť / Zapnúť mikrofón",
|
||||
"videomute": "Vypnúť / Zapnúť kameru",
|
||||
"authenticate": "Overiť",
|
||||
"record": "Uložiť záznam",
|
||||
"lock": "Zamknúť / Odomknúť miestnosť",
|
||||
"invite": "Pozvať ďalšich",
|
||||
"chat": "",
|
||||
"prezi": "Zdieľať Prezi",
|
||||
"chat": "Otvoriť / zatvoriť chat",
|
||||
"etherpad": "Zdieľať dokument",
|
||||
"sharedvideo": "",
|
||||
"sharescreen": "Zdieľať prac. plochu",
|
||||
"fullscreen": "Zapnúť / Vypnúť plnú obrazovku",
|
||||
"sip": "Zavolať SIP číslo",
|
||||
"Settings": "Nastavenia",
|
||||
"hangup": "Zložiť",
|
||||
"login": "Prihlásiť",
|
||||
"logout": "",
|
||||
"dialpad": "Zobraziť číselník"
|
||||
"logout": "Odhlásiť",
|
||||
"dialpad": "Zobraziť číselník",
|
||||
"sharedVideoMutedPopup": "",
|
||||
"micMutedPopup": "",
|
||||
"unableToUnmutePopup": "",
|
||||
"cameraDisabled": "",
|
||||
"micDisabled": ""
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Otvoriť / zatvoriť chat",
|
||||
@@ -81,8 +111,15 @@
|
||||
"title": "NASTAVENIA",
|
||||
"update": "Nastaviť",
|
||||
"name": "Meno",
|
||||
"startAudioMuted": "začat s vypnutým mikrofónom",
|
||||
"startVideoMuted": "začať s vypnutou kamerou"
|
||||
"startAudioMuted": "",
|
||||
"startVideoMuted": "",
|
||||
"selectCamera": "",
|
||||
"selectMic": "",
|
||||
"selectAudioOutput": "",
|
||||
"followMe": "",
|
||||
"noDevice": "",
|
||||
"noPermission": "",
|
||||
"avatarUrl": ""
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Kliknite pre zmenu<br/>Vášho mena",
|
||||
@@ -91,7 +128,8 @@
|
||||
"mute": "Učastník s<br/>vypnutým mikrofónom",
|
||||
"kick": "Vyhodiť",
|
||||
"muted": "Vypnutý mikrofón",
|
||||
"domute": "Vypnút mikrofón"
|
||||
"domute": "Vypnút mikrofón",
|
||||
"flip": ""
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Prenos. rýchlosť",
|
||||
@@ -127,7 +165,8 @@
|
||||
"grantedTo": "Práva moderátora boli udelené __to__!",
|
||||
"grantedToUnknown": "Práva moderátora boli udelené $t(somebody)!",
|
||||
"muted": "Začali ste rozhovor s vypnutým mikrofónom.",
|
||||
"mutedTitle": "Boli ste stíšený!"
|
||||
"mutedTitle": "Boli ste stíšený!",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "Boli ste vyhodený z konferencie!",
|
||||
@@ -136,12 +175,14 @@
|
||||
"passwordError2": "Táto diskusia nie je momentálne zabezpečená heslom. Iba majiteľ tejto konferencie može nastaviť heslo.",
|
||||
"connectError": "Oops! Niečo je zle a nemožem sa pripojiť do konferencie.",
|
||||
"connectErrorWithMsg": "Oops! Niečo je zle a nemožem sa pripojiť do konferencie. Správa: __msg__",
|
||||
"connecting": "",
|
||||
"error": "",
|
||||
"connecting": "Pripájam",
|
||||
"error": "Chyba",
|
||||
"detectext": "Chyba pri pokuse najsť rozšírenie pre zdieľanie prac. plochy",
|
||||
"failtoinstall": "Zlyhanie pri inštalácií rozšírenia pre zdieľanie prac. plochy",
|
||||
"failedpermissions": "Zlyhanie pri pokuse získať prístup k lokálnemu mikrofonu alebo kamere.",
|
||||
"bridgeUnavailable": "Jitsi Videobridge je momentálne nedostupné. Prosím, skúste neskor!",
|
||||
"jicofoUnavailable": "",
|
||||
"maxUsersLimitReached": "",
|
||||
"lockTitle": "Zabezpečenie zlyhalo",
|
||||
"lockMessage": "Zlyhanie pri pokuse o zabezpečenie konferencie.",
|
||||
"warning": "Upozornenie",
|
||||
@@ -155,11 +196,12 @@
|
||||
"defaultError": "Nastala neznáma chyba",
|
||||
"passwordRequired": "Je potrebné heslo",
|
||||
"Ok": "Ok",
|
||||
"removePreziTitle": "Odstrániť Prezi",
|
||||
"removePreziMsg": "Ste si naozaj istý pre odstránenie Vášho Prezi?",
|
||||
"sharePreziTitle": "Zdieľať Prezi",
|
||||
"sharePreziMsg": "Iný účastník už zdieľa Prezi. Je možne zdieľať iba jeden Prezi.",
|
||||
"Remove": "Odstrániť",
|
||||
"shareVideoTitle": "",
|
||||
"shareVideoLinkError": "",
|
||||
"removeSharedVideoTitle": "",
|
||||
"removeSharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"WaitingForHost": "Čakám na hostiteľa ...",
|
||||
"WaitForHostMsg": "Konferencia <b>__room__ </b> ešte nezačala. Ak ste hostiteľ Vy, overte sa. Inak čakajte kým sa prihlási hostiteľ.",
|
||||
"IamHost": "Ja som hostiteľ",
|
||||
@@ -171,8 +213,8 @@
|
||||
"hungUp": "Ste odpojený",
|
||||
"joinAgain": "Znova prihlásiť",
|
||||
"Share": "Zdieľať",
|
||||
"preziLinkError": "Prosím, zadajte správny Prezi odkaz.",
|
||||
"Save": "Uložiť",
|
||||
"recording": "",
|
||||
"recordingToken": "Zadajte názov nahrávky",
|
||||
"Dial": "Volať",
|
||||
"sipMsg": "Vložte SIP číslo",
|
||||
@@ -193,9 +235,34 @@
|
||||
"password": "heslo",
|
||||
"userPassword": "uživateľské heslo",
|
||||
"token": "token",
|
||||
"displayNameRequired": "Prosím, vložte Vaše meno:",
|
||||
"tokenAuthFailed": "",
|
||||
"displayNameRequired": "",
|
||||
"extensionRequired": "Potrebné rozšírenie:",
|
||||
"firefoxExtensionPrompt": "Potrebujete nainštalovať rozšírenie do Firefoxu pre možnosť zdieľať prac. plochu. Prosím, skúste znovu po nainštalovaní z: <a href='__url__'>"
|
||||
"firefoxExtensionPrompt": "Potrebujete nainštalovať rozšírenie do Firefoxu pre možnosť zdieľať prac. plochu. Prosím, skúste znovu po nainštalovaní z: <a href='__url__'>",
|
||||
"feedbackQuestion": "",
|
||||
"thankYou": "",
|
||||
"sorryFeedback": "",
|
||||
"liveStreaming": "",
|
||||
"streamKey": "",
|
||||
"startLiveStreaming": "",
|
||||
"stopStreamingWarning": "",
|
||||
"stopRecordingWarning": "",
|
||||
"stopLiveStreaming": "",
|
||||
"stopRecording": "",
|
||||
"doNotShowWarningAgain": "",
|
||||
"permissionDenied": "",
|
||||
"screenSharingPermissionDeniedError": "",
|
||||
"micErrorPresent": "",
|
||||
"cameraErrorPresent": "",
|
||||
"cameraUnsupportedResolutionError": "",
|
||||
"cameraUnknownError": "",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "",
|
||||
"cameraConstraintFailedError": "",
|
||||
"micUnknownError": "",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "",
|
||||
"micConstraintFailedError": ""
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
@@ -242,8 +309,23 @@
|
||||
"ATTACHED": "Priložený"
|
||||
},
|
||||
"recording": {
|
||||
"toaster": "Momentálne nahrávam!",
|
||||
"pending": "Ukladanie začne hneď ako sa další účastník prihlási",
|
||||
"on": "Nahrávanie sa začalo"
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"error": "",
|
||||
"unavailable": ""
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"unavailable": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"streamIdRequired": "",
|
||||
"error": "",
|
||||
"busy": ""
|
||||
}
|
||||
}
|
||||
@@ -3,16 +3,42 @@
|
||||
"connectionsettings": "Nastavitve povezave",
|
||||
"poweredby": "poganja",
|
||||
"downloadlogs": "Shrani zapis",
|
||||
"feedback": "",
|
||||
"roomUrlDefaultMsg": "Ustvarjanje vaše konference ...",
|
||||
"participant": "Udeleženec",
|
||||
"me": "jaz",
|
||||
"speaker": "Govornik",
|
||||
"defaultNickname": "npr. __name__",
|
||||
"defaultPreziLink": "npr. __url__",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "",
|
||||
"defaultLink": "npr. __url__",
|
||||
"calling": "",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "",
|
||||
"raiseHand": "",
|
||||
"pushToTalk": "",
|
||||
"toggleScreensharing": "",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleShortcuts": "",
|
||||
"focusLocal": "",
|
||||
"focusRemote": "",
|
||||
"toggleChat": "",
|
||||
"mute": "",
|
||||
"videoMute": ""
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "POJDI",
|
||||
"roomname": "Vpišite ime sobe",
|
||||
"disable": "Prihodnjič ne prikaži te strani",
|
||||
"disable": "",
|
||||
"feature1": {
|
||||
"title": "Enostavna uporaba",
|
||||
"content": "Nič ni treba namestiti. __app__ deluje direktno v vašem brskalniku. Enostavno sporočite ostalim udeležencem URL svoje konference in začnite."
|
||||
@@ -23,7 +49,7 @@
|
||||
},
|
||||
"feature3": {
|
||||
"title": "Odprta koda",
|
||||
"content": "__app__ je objavljen po licenci MIT. Pod pogoji te licence lahko prosto snamete, uporabljate, spreminjate in delite."
|
||||
"content": ""
|
||||
},
|
||||
"feature4": {
|
||||
"title": "Neomejeno število uporabnikov",
|
||||
@@ -50,12 +76,11 @@
|
||||
"mute": "Utišaj / Povrni glasnost",
|
||||
"videomute": "Zaženi / Ustavi kamero",
|
||||
"authenticate": "Overi",
|
||||
"record": "Snemaj",
|
||||
"lock": "Zakleni / Odkleni sobo",
|
||||
"invite": "Povabite ostale",
|
||||
"chat": "Odpri / zapri klepetalnico",
|
||||
"prezi": "Skupna raba Prezi",
|
||||
"etherpad": "Dokument v skupni rabi",
|
||||
"sharedvideo": "",
|
||||
"sharescreen": "Zaslon v souporabi",
|
||||
"fullscreen": "Vklopi / Izklopi celozaslonski način",
|
||||
"sip": "Pokliči številko SIP",
|
||||
@@ -63,7 +88,12 @@
|
||||
"hangup": "Odloži",
|
||||
"login": "Prijava",
|
||||
"logout": "Odjava",
|
||||
"dialpad": "Pokaži številčnico"
|
||||
"dialpad": "Pokaži številčnico",
|
||||
"sharedVideoMutedPopup": "",
|
||||
"micMutedPopup": "",
|
||||
"unableToUnmutePopup": "",
|
||||
"cameraDisabled": "",
|
||||
"micDisabled": ""
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Odpri / zapri klepetalnico",
|
||||
@@ -81,8 +111,15 @@
|
||||
"title": "NASTAVITVE",
|
||||
"update": "Posodobi",
|
||||
"name": "Ime",
|
||||
"startAudioMuted": "začni brez zvoka",
|
||||
"startVideoMuted": "začni brez slike"
|
||||
"startAudioMuted": "",
|
||||
"startVideoMuted": "",
|
||||
"selectCamera": "",
|
||||
"selectMic": "",
|
||||
"selectAudioOutput": "",
|
||||
"followMe": "",
|
||||
"noDevice": "",
|
||||
"noPermission": "",
|
||||
"avatarUrl": ""
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Kliknite, da spremenite<br/>svoje ime",
|
||||
@@ -91,7 +128,8 @@
|
||||
"mute": "Udeleženec je utišan",
|
||||
"kick": "Izženi",
|
||||
"muted": "Utišan",
|
||||
"domute": "Utišaj"
|
||||
"domute": "Utišaj",
|
||||
"flip": ""
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Bitna hitrost:",
|
||||
@@ -131,14 +169,14 @@
|
||||
"grantedTo": "Moderatorske pravice dodeljene uporabniku __to__!",
|
||||
"grantedToUnknown": "Moderatorske pravice dodeljene uporabniku $t(somebody)!",
|
||||
"muted": "Pogovor ste začeli utišano.",
|
||||
"mutedTitle": "Utišani ste!"
|
||||
"mutedTitle": "Utišani ste!",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "Ojej! Izgnali so vas iz srečanja!",
|
||||
"popupError": "Vaš brskalnik ne dovoli pojavnih oken iz te spletne strani. Omogočite prosim pojavna okna v varnostnih nastavitvah svojega brskalnika in ponovno poskusite.",
|
||||
"passwordError": "Ta pogovor je zaščiten z geslom. Samo lastnik konference lahko nastavi geslo.",
|
||||
"passwordError2": "Ta pogovor ni zaščiten z geslom. Samo lastnik konference lahko nastavi geslo.",
|
||||
"joinError": "Ups! Ni se bilo mogoče pridružiti konferenci. Mogoče je kakšna težava z varnostnimi nastavitvami. Pišite prosim administratorju storitve.",
|
||||
"popupError": "",
|
||||
"passwordError": "",
|
||||
"passwordError2": "",
|
||||
"connectError": "Ups! Nekaj je narobe in se ni bilo mogoče povezati s konferenco.",
|
||||
"connectErrorWithMsg": "Ups! Nekaj je narobe in se ni bilo mogoče povezati s konferenco: __msg__",
|
||||
"connecting": "Povezovanje",
|
||||
@@ -147,8 +185,10 @@
|
||||
"failtoinstall": "Razširitve za skupno uporabo namizja ni bilo mogoče namestiti",
|
||||
"failedpermissions": "Ni bilo mogoče pridobiti dovoljenja za uporabo lokalnega mikrofona ali kamere.",
|
||||
"bridgeUnavailable": "Jitsi Videobridge trenutno ni na razpolago. Prosim poskusite kasneje!",
|
||||
"jicofoUnavailable": "",
|
||||
"maxUsersLimitReached": "",
|
||||
"lockTitle": "Zaklepanje ni uspelo",
|
||||
"lockMessage": "Konference ni bilo mogoče zakleniti.",
|
||||
"lockMessage": "",
|
||||
"warning": "Opozorilo",
|
||||
"passwordNotSupported": "Trenutno ni mogoče zakleniti sobe z geslom.",
|
||||
"sorry": "Oprostite",
|
||||
@@ -160,11 +200,12 @@
|
||||
"defaultError": "Prišlo je do neke napake",
|
||||
"passwordRequired": "Potrebno je geslo",
|
||||
"Ok": "V redu",
|
||||
"removePreziTitle": "Odstrani Prezi",
|
||||
"removePreziMsg": "Ali res želite odstraniti Prezi?",
|
||||
"sharePreziTitle": "Dajte Prezi v skupno rabo",
|
||||
"sharePreziMsg": "Drug uporabnik je že dal Prezi v skupno rabo. Ta konferenca podpira samo en Prezi naenkrat.",
|
||||
"Remove": "Odstrani",
|
||||
"shareVideoTitle": "",
|
||||
"shareVideoLinkError": "",
|
||||
"removeSharedVideoTitle": "",
|
||||
"removeSharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"WaitingForHost": "Čakanje na gostitelja ...",
|
||||
"WaitForHostMsg": "Ta konferenca <b>__room__ </b> se še ni začela. V primeru, da ste vi gostitelj se prosim overite. Drugače počakajte prosim na prihod gostitelja.",
|
||||
"IamHost": "Jaz sem gostitelj",
|
||||
@@ -173,11 +214,11 @@
|
||||
"logoutTitle": "Odjava",
|
||||
"logoutQuestion": "Ali se res želite odjaviti in prekiniti konferenco?",
|
||||
"sessTerminated": "Seja je končana",
|
||||
"hungUp": "Prekinili ste klic",
|
||||
"hungUp": "",
|
||||
"joinAgain": "Ponovno se pridruži",
|
||||
"Share": "Souporaba",
|
||||
"preziLinkError": "Prosim, pravilno vpišite povezavo Prezi.",
|
||||
"Save": "Shrani",
|
||||
"recording": "",
|
||||
"recordingToken": "Vnesite žeton za registracijo",
|
||||
"Dial": "Pokliči",
|
||||
"sipMsg": "Vnesite številko SIP",
|
||||
@@ -198,17 +239,37 @@
|
||||
"password": "geslo",
|
||||
"userPassword": "uporabniško geslo",
|
||||
"token": "žeton",
|
||||
"displayNameRequired": "Vpišite svoje ime:"
|
||||
"tokenAuthFailed": "",
|
||||
"displayNameRequired": "",
|
||||
"extensionRequired": "",
|
||||
"firefoxExtensionPrompt": "",
|
||||
"feedbackQuestion": "",
|
||||
"thankYou": "",
|
||||
"sorryFeedback": "",
|
||||
"liveStreaming": "",
|
||||
"streamKey": "",
|
||||
"startLiveStreaming": "",
|
||||
"stopStreamingWarning": "",
|
||||
"stopRecordingWarning": "",
|
||||
"stopLiveStreaming": "",
|
||||
"stopRecording": "",
|
||||
"doNotShowWarningAgain": "",
|
||||
"permissionDenied": "",
|
||||
"screenSharingPermissionDeniedError": "",
|
||||
"micErrorPresent": "",
|
||||
"cameraErrorPresent": "",
|
||||
"cameraUnsupportedResolutionError": "",
|
||||
"cameraUnknownError": "",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "",
|
||||
"cameraConstraintFailedError": "",
|
||||
"micUnknownError": "",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "",
|
||||
"micConstraintFailedError": ""
|
||||
},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
"Ta konferenca je zaklenjena z geslom. Uporabite sledeči PIN ko se pridružite:",
|
||||
"",
|
||||
"",
|
||||
"__sharedKey__",
|
||||
"",
|
||||
""
|
||||
],
|
||||
"sharedKey": "",
|
||||
"subject": "Povabilo na __appName__ (__conferenceName__)",
|
||||
"body": [
|
||||
"Pozdravljeni,",
|
||||
@@ -242,8 +303,23 @@
|
||||
"ATTACHED": "Priključeno"
|
||||
},
|
||||
"recording": {
|
||||
"toaster": "Trenutno poteka snemanje!",
|
||||
"pending": "Snemanje se bo začelo takoj, ko se bo pridružil drugi udeleženec",
|
||||
"on": "Snemanje se je začelo"
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"error": "",
|
||||
"unavailable": ""
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"unavailable": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"streamIdRequired": "",
|
||||
"error": "",
|
||||
"busy": ""
|
||||
}
|
||||
}
|
||||
@@ -3,17 +3,42 @@
|
||||
"connectionsettings": "Anslutningsinställningar",
|
||||
"poweredby": "drivs av",
|
||||
"downloadlogs": "Hämta loggar",
|
||||
"feedback": "",
|
||||
"feedback": "Ge oss din feedback",
|
||||
"roomUrlDefaultMsg": "Din konferens håller på att skapas...",
|
||||
"participant": "Deltagare",
|
||||
"me": "jag",
|
||||
"speaker": "Talare",
|
||||
"defaultNickname": "t ex. __namn__",
|
||||
"defaultPreziLink": "t ex. __url__",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "",
|
||||
"defaultLink": "t ex. __url__",
|
||||
"calling": "",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "",
|
||||
"raiseHand": "",
|
||||
"pushToTalk": "",
|
||||
"toggleScreensharing": "",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleShortcuts": "",
|
||||
"focusLocal": "",
|
||||
"focusRemote": "",
|
||||
"toggleChat": "",
|
||||
"mute": "",
|
||||
"videoMute": ""
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "KÖR",
|
||||
"roomname": "Skriv in rumsnamn",
|
||||
"disable": "Visa inte den här sidan nästa gång jag kommer hit",
|
||||
"disable": "",
|
||||
"feature1": {
|
||||
"title": "Enkelt att använda",
|
||||
"content": "Ingen nedladdning behövs. __app__ fungerar direkt inuti din webbläsare. Dela bara din konferens-URL med andra för att börja."
|
||||
@@ -51,12 +76,11 @@
|
||||
"mute": "Slå av/på ljud",
|
||||
"videomute": "Starta / stoppa kamera",
|
||||
"authenticate": "Autentisera",
|
||||
"record": "Spela in",
|
||||
"lock": "Lås / lås upp rum",
|
||||
"invite": "Bjud in andra",
|
||||
"chat": "Öppna / stäng chat",
|
||||
"prezi": "Dela Prezi",
|
||||
"etherpad": "Delat dokument",
|
||||
"sharedvideo": "",
|
||||
"sharescreen": "Dela skärm",
|
||||
"fullscreen": "Aktivera / avaktivera helskärm",
|
||||
"sip": "Ring SIP-nummer",
|
||||
@@ -64,7 +88,12 @@
|
||||
"hangup": "Lägg på",
|
||||
"login": "Logga in",
|
||||
"logout": "Logga ut",
|
||||
"dialpad": "Visa knappsats"
|
||||
"dialpad": "Visa knappsats",
|
||||
"sharedVideoMutedPopup": "",
|
||||
"micMutedPopup": "",
|
||||
"unableToUnmutePopup": "",
|
||||
"cameraDisabled": "",
|
||||
"micDisabled": ""
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Öppna / stäng chat",
|
||||
@@ -82,8 +111,15 @@
|
||||
"title": "INSTÄLLNINGAR",
|
||||
"update": "Uppdatera",
|
||||
"name": "Namn",
|
||||
"startAudioMuted": "starta utan ljud",
|
||||
"startVideoMuted": "starta utan video"
|
||||
"startAudioMuted": "",
|
||||
"startVideoMuted": "",
|
||||
"selectCamera": "",
|
||||
"selectMic": "",
|
||||
"selectAudioOutput": "",
|
||||
"followMe": "",
|
||||
"noDevice": "",
|
||||
"noPermission": "",
|
||||
"avatarUrl": ""
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Klicka här för att <br/>redigera namn",
|
||||
@@ -92,7 +128,8 @@
|
||||
"mute": "Deltagaren har avstängd mikrofon",
|
||||
"kick": "Sparka ut",
|
||||
"muted": "Tystad",
|
||||
"domute": "Tysta"
|
||||
"domute": "Tysta",
|
||||
"flip": ""
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Bithastighet:",
|
||||
@@ -124,7 +161,8 @@
|
||||
"grantedTo": "Moderatorsrättigheter tilldelat till __to__!",
|
||||
"grantedToUnknown": "Moderatorsrättigheter tilldelat till $t(somebody)!",
|
||||
"muted": "Du har startat konversationen utan mikrofon.",
|
||||
"mutedTitle": "Du har mikrofonen avstängd!"
|
||||
"mutedTitle": "Du har mikrofonen avstängd!",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"dialog": {
|
||||
"kickMessage": "Aj! Du har sparkats ur mötet!",
|
||||
@@ -139,6 +177,8 @@
|
||||
"failtoinstall": "Misslyckades att installera skrivbordsdelnings-tillägget",
|
||||
"failedpermissions": "Misslyckades med att få tillåtelse att använda lokal mikrofon och/eller kamera.",
|
||||
"bridgeUnavailable": "Jitsi Videobridge är för tillfället inte tillgänglig. Vänligen försök senare!",
|
||||
"jicofoUnavailable": "",
|
||||
"maxUsersLimitReached": "",
|
||||
"lockTitle": "Låsning misslyckades",
|
||||
"lockMessage": "Misslyckades att låsa konferensen.",
|
||||
"warning": "Varning",
|
||||
@@ -152,11 +192,12 @@
|
||||
"defaultError": "Det uppstod någon typ av fel",
|
||||
"passwordRequired": "Lösenord krävs",
|
||||
"Ok": "Ok",
|
||||
"removePreziTitle": "Ta bort Prezi",
|
||||
"removePreziMsg": "Är du säker på att du vill ta bort din Prezi?",
|
||||
"sharePreziTitle": "Dela en Prezi",
|
||||
"sharePreziMsg": "En annan deltagare delar redan en Prezi. Den här konferensen tillåter bara en Prezi i taget.",
|
||||
"Remove": "Ta bort",
|
||||
"shareVideoTitle": "",
|
||||
"shareVideoLinkError": "",
|
||||
"removeSharedVideoTitle": "",
|
||||
"removeSharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"WaitingForHost": "Väntar på värden ...",
|
||||
"WaitForHostMsg": "Konferensen <b>__room__</b> har inte startat än. Om du är värd för konferensen, vänligen logga in. Annars, vänta kvar på att konferensvärden kommer.",
|
||||
"IamHost": "Jag är värd",
|
||||
@@ -168,8 +209,8 @@
|
||||
"hungUp": "Du lade på",
|
||||
"joinAgain": "Anslut igen",
|
||||
"Share": "Dela",
|
||||
"preziLinkError": "Vänligen skriv in en korrekt prezi-länk.",
|
||||
"Save": "Spara",
|
||||
"recording": "",
|
||||
"recordingToken": "Skriv in inspelnings-token",
|
||||
"Dial": "Ring upp",
|
||||
"sipMsg": "Skriv in SIP-nummer",
|
||||
@@ -190,14 +231,36 @@
|
||||
"password": "lösenord",
|
||||
"userPassword": "användarlösenord",
|
||||
"token": "token",
|
||||
"tokenAuthFailed": "",
|
||||
"displayNameRequired": "Vänligen skriv in ditt visningsnamn:",
|
||||
"tokenAuthFailed": "Misslyckades att autentisera mot XMPP-server: ogiltig token",
|
||||
"displayNameRequired": "",
|
||||
"extensionRequired": "Tillägg krävs:",
|
||||
"firefoxExtensionPrompt": "Du behöver installera ett Firefox-tillägg för att kunna använda skärmdelning. Vänligen försök igen efter att du <a href='__url__'>hämtat det här</a>!",
|
||||
"feedbackQuestion": "",
|
||||
"thankYou": "",
|
||||
"sorryFeedback": ""
|
||||
"feedbackQuestion": "Hur upplevde du samtalet?",
|
||||
"thankYou": "Tack för att du använder __appName__!",
|
||||
"sorryFeedback": "Tråkigt att du känner så. Vill du berätta mer?",
|
||||
"liveStreaming": "",
|
||||
"streamKey": "",
|
||||
"startLiveStreaming": "",
|
||||
"stopStreamingWarning": "",
|
||||
"stopRecordingWarning": "",
|
||||
"stopLiveStreaming": "",
|
||||
"stopRecording": "",
|
||||
"doNotShowWarningAgain": "",
|
||||
"permissionDenied": "",
|
||||
"screenSharingPermissionDeniedError": "",
|
||||
"micErrorPresent": "",
|
||||
"cameraErrorPresent": "",
|
||||
"cameraUnsupportedResolutionError": "",
|
||||
"cameraUnknownError": "",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "",
|
||||
"cameraConstraintFailedError": "",
|
||||
"micUnknownError": "",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "",
|
||||
"micConstraintFailedError": ""
|
||||
},
|
||||
"\u0005dialog": {},
|
||||
"email": {
|
||||
"sharedKey": [
|
||||
"Den här konferensen är lösenordsskyddad. Vänligen använd följande kod när du kopplar upp dig:",
|
||||
@@ -239,8 +302,23 @@
|
||||
"ATTACHED": "Ansluten"
|
||||
},
|
||||
"recording": {
|
||||
"toaster": "Spelar nu in!",
|
||||
"pending": "Din inspelning kommer att starta så snart andra deltagare ansluter",
|
||||
"on": "Inspelningen har startats"
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"error": "",
|
||||
"unavailable": ""
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"unavailable": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"streamIdRequired": "",
|
||||
"error": "",
|
||||
"busy": ""
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,42 @@
|
||||
"connectionsettings": "Bağlantı Ayarları",
|
||||
"poweredby": "Gücünün kaynağı",
|
||||
"downloadlogs": "Günlükleri indir",
|
||||
"feedback": "",
|
||||
"roomUrlDefaultMsg": "",
|
||||
"participant": "",
|
||||
"me": "",
|
||||
"speaker": "",
|
||||
"raisedHand": "",
|
||||
"defaultNickname": "",
|
||||
"defaultLink": "",
|
||||
"calling": "",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "",
|
||||
"chromeGrantPermissions": "",
|
||||
"androidGrantPermissions": "",
|
||||
"firefoxGrantPermissions": "",
|
||||
"operaGrantPermissions": "",
|
||||
"iexplorerGrantPermissions": "",
|
||||
"safariGrantPermissions": "",
|
||||
"nwjsGrantPermissions": ""
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "",
|
||||
"raiseHand": "",
|
||||
"pushToTalk": "",
|
||||
"toggleScreensharing": "",
|
||||
"toggleFilmstrip": "",
|
||||
"toggleShortcuts": "",
|
||||
"focusLocal": "",
|
||||
"focusRemote": "",
|
||||
"toggleChat": "",
|
||||
"mute": "",
|
||||
"videoMute": ""
|
||||
},
|
||||
"welcomepage": {
|
||||
"go": "GİT",
|
||||
"roomname": "Oda adı girin",
|
||||
"disable": "Sonraki girişimde bu sayfayı gösterme",
|
||||
"disable": "",
|
||||
"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."
|
||||
@@ -17,7 +49,7 @@
|
||||
},
|
||||
"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."
|
||||
"content": ""
|
||||
},
|
||||
"feature4": {
|
||||
"title": "Sınırsız sayıda kullanıcı",
|
||||
@@ -43,25 +75,30 @@
|
||||
"toolbar": {
|
||||
"mute": "Sessiz / Sesli",
|
||||
"videomute": "Kamera başlat / durdur",
|
||||
"authenticate": "",
|
||||
"record": "Kaydet",
|
||||
"authenticate": "Kimlik doğrula",
|
||||
"lock": "Odayı kilitle / kilit aç",
|
||||
"invite": "Arkadaşlarını davet et",
|
||||
"chat": "",
|
||||
"prezi": "Prezi paylaş",
|
||||
"chat": "Sohbeti aç / kapa",
|
||||
"etherpad": "Paylaşımlı belge",
|
||||
"sharedvideo": "",
|
||||
"sharescreen": "Ekran paylaş",
|
||||
"fullscreen": "Tam Ekrana Gir / Çık",
|
||||
"sip": "SIP numara ara",
|
||||
"Settings": "Ayarlar",
|
||||
"hangup": "Kapat",
|
||||
"login": "Oturum aç",
|
||||
"logout": ""
|
||||
"logout": "Oturum kapat",
|
||||
"dialpad": "",
|
||||
"sharedVideoMutedPopup": "",
|
||||
"micMutedPopup": "",
|
||||
"unableToUnmutePopup": "",
|
||||
"cameraDisabled": "",
|
||||
"micDisabled": ""
|
||||
},
|
||||
"bottomtoolbar": {
|
||||
"chat": "Sohbeti aç / kapa",
|
||||
"filmstrip": "Kişi listesi aç / kapa",
|
||||
"contactlist": "Film şeridini göster / gizle"
|
||||
"filmstrip": "Film şeridini göster / gizle",
|
||||
"contactlist": "Kişi listesi aç / kapa"
|
||||
},
|
||||
"chat": {
|
||||
"nickname": {
|
||||
@@ -73,7 +110,16 @@
|
||||
"settings": {
|
||||
"title": "AYARLAR",
|
||||
"update": "Güncelle",
|
||||
"name": "Ad"
|
||||
"name": "Ad",
|
||||
"startAudioMuted": "",
|
||||
"startVideoMuted": "",
|
||||
"selectCamera": "",
|
||||
"selectMic": "",
|
||||
"selectAudioOutput": "",
|
||||
"followMe": "",
|
||||
"noDevice": "",
|
||||
"noPermission": "",
|
||||
"avatarUrl": ""
|
||||
},
|
||||
"videothumbnail": {
|
||||
"editnickname": "Görünür adınızı değiştirmek<br/>için tıkla",
|
||||
@@ -82,7 +128,8 @@
|
||||
"mute": "Katılımcı sessiz",
|
||||
"kick": "Kovuldu",
|
||||
"muted": "Sessiz",
|
||||
"domute": "Sustur"
|
||||
"domute": "Sustur",
|
||||
"flip": ""
|
||||
},
|
||||
"connectionindicator": {
|
||||
"bitrate": "Bit hızı:",
|
||||
@@ -108,20 +155,26 @@
|
||||
"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!"
|
||||
"grantedToUnknown": "$t(somebody), görüşme yöneticisi hakları verildi!",
|
||||
"muted": "",
|
||||
"mutedTitle": "",
|
||||
"raisedHand": ""
|
||||
},
|
||||
"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.",
|
||||
"popupError": "",
|
||||
"passwordError": "",
|
||||
"passwordError2": "",
|
||||
"connectError": "Amanin boo! Birşeyler ters gitti ve görüşmeye bağlanamadık.",
|
||||
"connectErrorWithMsg": "Amanin boo! Birşeyler ters gitti ve görüşmeye bağlanamadık.",
|
||||
"connecting": "",
|
||||
"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!",
|
||||
"jicofoUnavailable": "",
|
||||
"maxUsersLimitReached": "",
|
||||
"lockTitle": "Kilitlenemedi",
|
||||
"lockMessage": "Görüşme kilitlenemedi.",
|
||||
"warning": "Uyarı",
|
||||
@@ -135,23 +188,25 @@
|
||||
"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:<br/><b>__room__ </b></br> Oda oluşturmak için ya kimlik doğrulamalı ya da bunu yapması için bir başkasını beklemelisiniz.",
|
||||
"Authenticate": "Kimlik doğrula",
|
||||
"shareVideoTitle": "",
|
||||
"shareVideoLinkError": "",
|
||||
"removeSharedVideoTitle": "",
|
||||
"removeSharedVideoMsg": "",
|
||||
"alreadySharedVideoMsg": "",
|
||||
"WaitingForHost": "",
|
||||
"WaitForHostMsg": "",
|
||||
"IamHost": "",
|
||||
"Cancel": "İptal",
|
||||
"retry": "",
|
||||
"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",
|
||||
"hungUp": "",
|
||||
"joinAgain": "Yeniden katıl",
|
||||
"Share": "Paylaş",
|
||||
"preziLinkError": "Lütfen doğru prezi bağlantısı verin.",
|
||||
"Save": "Kaydet",
|
||||
"recording": "",
|
||||
"recordingToken": "Kayıt jetonu girin",
|
||||
"Dial": "Ara",
|
||||
"sipMsg": "SIP numarası gir",
|
||||
@@ -168,6 +223,77 @@
|
||||
"gracefulShutdown": "Hizmetimiz bakıp için durduruldu. Daha sonra tekrar deneyiniz.",
|
||||
"Yes": "Evet",
|
||||
"reservationError": "Rezervasyon sistemi hatası",
|
||||
"reservationErrorMsg": "Hata kodu: __code__, mesaj: __msg__"
|
||||
"reservationErrorMsg": "Hata kodu: __code__, mesaj: __msg__",
|
||||
"password": "",
|
||||
"userPassword": "parolanız",
|
||||
"token": "",
|
||||
"tokenAuthFailed": "",
|
||||
"displayNameRequired": "",
|
||||
"extensionRequired": "",
|
||||
"firefoxExtensionPrompt": "",
|
||||
"feedbackQuestion": "",
|
||||
"thankYou": "",
|
||||
"sorryFeedback": "",
|
||||
"liveStreaming": "",
|
||||
"streamKey": "",
|
||||
"startLiveStreaming": "",
|
||||
"stopStreamingWarning": "",
|
||||
"stopRecordingWarning": "",
|
||||
"stopLiveStreaming": "",
|
||||
"stopRecording": "",
|
||||
"doNotShowWarningAgain": "",
|
||||
"permissionDenied": "",
|
||||
"screenSharingPermissionDeniedError": "",
|
||||
"micErrorPresent": "",
|
||||
"cameraErrorPresent": "",
|
||||
"cameraUnsupportedResolutionError": "",
|
||||
"cameraUnknownError": "",
|
||||
"cameraPermissionDeniedError": "",
|
||||
"cameraNotFoundError": "",
|
||||
"cameraConstraintFailedError": "",
|
||||
"micUnknownError": "",
|
||||
"micPermissionDeniedError": "",
|
||||
"micNotFoundError": "",
|
||||
"micConstraintFailedError": ""
|
||||
},
|
||||
"\u0005dialog": {},
|
||||
"email": {
|
||||
"sharedKey": "",
|
||||
"subject": "",
|
||||
"body": "",
|
||||
"and": ""
|
||||
},
|
||||
"connection": {
|
||||
"ERROR": "Hata",
|
||||
"CONNECTING": "",
|
||||
"RECONNECTING": "",
|
||||
"CONNFAIL": "",
|
||||
"AUTHENTICATING": "Kimlik doğrula",
|
||||
"AUTHFAIL": "",
|
||||
"CONNECTED": "bağlandı",
|
||||
"DISCONNECTED": "bağlantı kesildi",
|
||||
"DISCONNECTING": "bağlantı kesildi",
|
||||
"ATTACHED": ""
|
||||
},
|
||||
"\u0005connection": {},
|
||||
"recording": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"error": "",
|
||||
"unavailable": ""
|
||||
},
|
||||
"liveStreaming": {
|
||||
"pending": "",
|
||||
"on": "",
|
||||
"off": "",
|
||||
"unavailable": "",
|
||||
"failedToStart": "",
|
||||
"buttonTooltip": "",
|
||||
"streamIdRequired": "",
|
||||
"error": "",
|
||||
"busy": ""
|
||||
}
|
||||
}
|
||||
@@ -119,8 +119,7 @@
|
||||
"selectAudioOutput": "Select audio output",
|
||||
"followMe": "Enable follow me",
|
||||
"noDevice": "None",
|
||||
"noPermission": "Permission to use device is not granted",
|
||||
"avatarUrl": "Avatar URL"
|
||||
"noPermission": "Permission to use device is not granted"
|
||||
},
|
||||
"videothumbnail":
|
||||
{
|
||||
@@ -258,12 +257,15 @@
|
||||
"cameraUnsupportedResolutionError": "Your camera does not support required video resolution.",
|
||||
"cameraUnknownError": "Cannot use camera for a unknown reason.",
|
||||
"cameraPermissionDeniedError": "You have not granted permission to use your camera. You can still join the conference but others won't see you. Use the camera button in the address bar to fix this.",
|
||||
"cameraNotFoundError": "Requested camera was not found.",
|
||||
"cameraNotFoundError": "Camera was not found.",
|
||||
"cameraConstraintFailedError": "Yor camera does not satisfy some of required constraints.",
|
||||
"micUnknownError": "Cannot use microphone for a unknown reason.",
|
||||
"micPermissionDeniedError": "You have not granted permission to use your microphone. You can still join the conference but others won't hear you. Use the camera button in the address bar to fix this.",
|
||||
"micNotFoundError": "Requested microphone was not found.",
|
||||
"micConstraintFailedError": "Yor microphone does not satisfy some of required constraints."
|
||||
"micNotFoundError": "Microphone was not found.",
|
||||
"micConstraintFailedError": "Yor microphone does not satisfy some of required constraints.",
|
||||
"goToStore": "Go to the webstore",
|
||||
"externalInstallationTitle": "Extension required",
|
||||
"externalInstallationMsg": "You need to install our desktop sharing extension."
|
||||
},
|
||||
"email":
|
||||
{
|
||||
|
||||
2
modules/API/external/external_api.js
vendored
2
modules/API/external/external_api.js
vendored
@@ -345,7 +345,7 @@ JitsiMeetExternalAPI.prototype.removeEventListeners = function(events) {
|
||||
* Removes the listeners and removes the Jitsi Meet frame.
|
||||
*/
|
||||
JitsiMeetExternalAPI.prototype.dispose = function() {
|
||||
this.postis.dispose();
|
||||
this.postis.destroy();
|
||||
var frame = document.getElementById(this.frameName);
|
||||
if(frame)
|
||||
frame.src = 'about:blank';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global $, APP, config, interfaceConfig */
|
||||
/* global $, APP, config, interfaceConfig, JitsiMeetJS */
|
||||
import UIEvents from "../../service/UI/UIEvents";
|
||||
|
||||
/**
|
||||
@@ -90,6 +90,7 @@ var Feedback = {
|
||||
* The feedback score. -1 indicates no score has been given for now.
|
||||
*/
|
||||
feedbackScore: -1,
|
||||
|
||||
/**
|
||||
* Initialise the Feedback functionality.
|
||||
* @param emitter the EventEmitter to associate with the Feedback.
|
||||
@@ -134,6 +135,17 @@ var Feedback = {
|
||||
isEnabled: function() {
|
||||
return this.enabled && APP.conference.isCallstatsEnabled();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if the feedback window is currently visible and false
|
||||
* otherwise.
|
||||
* @return {boolean} true if the feedback window is visible, false
|
||||
* otherwise
|
||||
*/
|
||||
isVisible: function() {
|
||||
return $(".feedback").is(":visible");
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the feedback window.
|
||||
*/
|
||||
@@ -199,9 +211,12 @@ var Feedback = {
|
||||
var feedbackDetails
|
||||
= document.getElementById("feedbackTextArea").value;
|
||||
|
||||
if (feedbackDetails && feedbackDetails.length > 0)
|
||||
if (feedbackDetails && feedbackDetails.length > 0) {
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'feedback.rating', Feedback.feedbackScore);
|
||||
APP.conference.sendFeedback( Feedback.feedbackScore,
|
||||
feedbackDetails);
|
||||
}
|
||||
|
||||
if (feedbackWindowCallback)
|
||||
feedbackWindowCallback();
|
||||
@@ -227,6 +242,7 @@ var Feedback = {
|
||||
closeText: '',
|
||||
loaded: onLoadFunction,
|
||||
position: {width: 500}}, null);
|
||||
JitsiMeetJS.analytics.sendEvent('feedback.open');
|
||||
},
|
||||
/**
|
||||
* Toggles the appropriate css class for the given number of stars, to
|
||||
|
||||
121
modules/UI/UI.js
121
modules/UI/UI.js
@@ -23,6 +23,7 @@ import SettingsMenu from "./side_pannels/settings/SettingsMenu";
|
||||
import Settings from "./../settings/Settings";
|
||||
import { reload } from '../util/helpers';
|
||||
import RingOverlay from "./ring_overlay/RingOverlay";
|
||||
import UIErrors from './UIErrors';
|
||||
|
||||
var EventEmitter = require("events");
|
||||
UI.messageHandler = require("./util/MessageHandler");
|
||||
@@ -272,15 +273,24 @@ UI.setRaisedHandStatus = (participant, raisedHandStatus) => {
|
||||
* Sets the local "raised hand" status.
|
||||
*/
|
||||
UI.setLocalRaisedHandStatus = (raisedHandStatus) => {
|
||||
VideoLayout.setRaisedHandStatus(APP.conference.localId, raisedHandStatus);
|
||||
VideoLayout.setRaisedHandStatus(APP.conference.getMyUserId(), raisedHandStatus);
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize conference UI.
|
||||
*/
|
||||
UI.initConference = function () {
|
||||
let id = APP.conference.localId;
|
||||
Toolbar.updateRoomUrl(window.location.href);
|
||||
let id = APP.conference.getMyUserId();
|
||||
|
||||
// Do not include query parameters in the invite URL
|
||||
// "https:" + "//" + "example.com:8888" + "/SomeConference1245"
|
||||
var inviteURL = window.location.protocol + "//" +
|
||||
window.location.host + window.location.pathname;
|
||||
Toolbar.updateRoomUrl(inviteURL);
|
||||
// Clean up the URL displayed by the browser
|
||||
if (window.history && typeof window.history.replaceState === 'function') {
|
||||
window.history.replaceState({}, document.title, inviteURL);
|
||||
}
|
||||
|
||||
// Add myself to the contact list.
|
||||
ContactList.addContact(id);
|
||||
@@ -289,7 +299,6 @@ UI.initConference = function () {
|
||||
//if local role changes buttons state will be again updated
|
||||
UI.updateLocalRole(false);
|
||||
|
||||
// Once we've joined the muc show the toolbar
|
||||
ToolbarToggler.showToolbar();
|
||||
|
||||
let displayName = config.displayJids ? id : Settings.getDisplayName();
|
||||
@@ -299,7 +308,12 @@ UI.initConference = function () {
|
||||
}
|
||||
|
||||
// Make sure we configure our avatar id, before creating avatar for us
|
||||
UI.setUserEmail(id, Settings.getEmail());
|
||||
let email = Settings.getEmail();
|
||||
if (email) {
|
||||
UI.setUserEmail(id, email);
|
||||
} else {
|
||||
UI.setUserAvatarID(id, Settings.getAvatarId());
|
||||
}
|
||||
|
||||
Toolbar.checkAutoEnableDesktopSharing();
|
||||
|
||||
@@ -830,7 +844,7 @@ UI.dockToolbar = function (isDock) {
|
||||
/**
|
||||
* Updates the avatar for participant.
|
||||
* @param {string} id user id
|
||||
* @param {stirng} avatarUrl the URL for the avatar
|
||||
* @param {string} avatarUrl the URL for the avatar
|
||||
*/
|
||||
function changeAvatar(id, avatarUrl) {
|
||||
VideoLayout.changeUserAvatar(id, avatarUrl);
|
||||
@@ -843,7 +857,7 @@ function changeAvatar(id, avatarUrl) {
|
||||
/**
|
||||
* Update user email.
|
||||
* @param {string} id user id
|
||||
* @param {stirng} email user email
|
||||
* @param {string} email user email
|
||||
*/
|
||||
UI.setUserEmail = function (id, email) {
|
||||
// update avatar
|
||||
@@ -852,11 +866,22 @@ UI.setUserEmail = function (id, email) {
|
||||
changeAvatar(id, Avatar.getAvatarUrl(id));
|
||||
};
|
||||
|
||||
/**
|
||||
* Update user avtar id.
|
||||
* @param {string} id user id
|
||||
* @param {string} avatarId user's avatar id
|
||||
*/
|
||||
UI.setUserAvatarID = function (id, avatarId) {
|
||||
// update avatar
|
||||
Avatar.setUserAvatarID(id, avatarId);
|
||||
|
||||
changeAvatar(id, Avatar.getAvatarUrl(id));
|
||||
};
|
||||
|
||||
/**
|
||||
* Update user avatar URL.
|
||||
* @param {string} id user id
|
||||
* @param {stirng} url user avatar url
|
||||
* @param {string} url user avatar url
|
||||
*/
|
||||
UI.setUserAvatarUrl = function (id, url) {
|
||||
// update avatar
|
||||
@@ -1055,29 +1080,32 @@ UI.inviteParticipants = function (roomUrl, conferenceName, key, nick) {
|
||||
* @returns {Promise} when dialog is closed.
|
||||
*/
|
||||
UI.requestFeedback = function () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (Feedback.isEnabled()) {
|
||||
// If the user has already entered feedback, we'll show the window and
|
||||
// immidiately start the conference dispose timeout.
|
||||
if (Feedback.feedbackScore > 0) {
|
||||
Feedback.openFeedbackWindow();
|
||||
resolve();
|
||||
if (Feedback.isVisible())
|
||||
return Promise.reject(UIErrors.FEEDBACK_REQUEST_IN_PROGRESS);
|
||||
else
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (Feedback.isEnabled()) {
|
||||
// If the user has already entered feedback, we'll show the
|
||||
// window and immidiately start the conference dispose timeout.
|
||||
if (Feedback.feedbackScore > 0) {
|
||||
Feedback.openFeedbackWindow();
|
||||
resolve();
|
||||
|
||||
} else { // Otherwise we'll wait for user's feedback.
|
||||
Feedback.openFeedbackWindow(resolve);
|
||||
} else { // Otherwise we'll wait for user's feedback.
|
||||
Feedback.openFeedbackWindow(resolve);
|
||||
}
|
||||
} else {
|
||||
// If the feedback functionality isn't enabled we show a thank
|
||||
// you dialog.
|
||||
messageHandler.openMessageDialog(
|
||||
null, null, null,
|
||||
APP.translation.translateString(
|
||||
"dialog.thankYou", {appName:interfaceConfig.APP_NAME}
|
||||
)
|
||||
);
|
||||
resolve();
|
||||
}
|
||||
} else {
|
||||
// If the feedback functionality isn't enabled we show a thank you
|
||||
// dialog.
|
||||
messageHandler.openMessageDialog(
|
||||
null, null, null,
|
||||
APP.translation.translateString(
|
||||
"dialog.thankYou", {appName:interfaceConfig.APP_NAME}
|
||||
)
|
||||
);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
UI.updateRecordingState = function (state) {
|
||||
@@ -1202,6 +1230,33 @@ UI.showExtensionRequiredDialog = function (url) {
|
||||
"dialog.firefoxExtensionPrompt", {url: url}));
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows "Please go to chrome webstore to install the desktop sharing extension"
|
||||
* 2 button dialog with buttons - cancel and go to web store.
|
||||
* @param url {string} the url of the extension.
|
||||
*/
|
||||
UI.showExtensionExternalInstallationDialog = function (url) {
|
||||
messageHandler.openTwoButtonDialog(
|
||||
"dialog.externalInstallationTitle",
|
||||
null,
|
||||
"dialog.externalInstallationMsg",
|
||||
null,
|
||||
true,
|
||||
"dialog.goToStore",
|
||||
function(e,v,m,f){
|
||||
if (v) {
|
||||
e.preventDefault();
|
||||
eventEmitter.emit(UIEvents.OPEN_EXTENSION_STORE, url);
|
||||
}
|
||||
},
|
||||
function () {},
|
||||
function () {
|
||||
eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows dialog with combined information about camera and microphone errors.
|
||||
* @param {JitsiTrackError} micError
|
||||
@@ -1210,9 +1265,9 @@ UI.showExtensionRequiredDialog = function (url) {
|
||||
UI.showDeviceErrorDialog = function (micError, cameraError) {
|
||||
let localStoragePropName = "doNotShowErrorAgain";
|
||||
let isMicJitsiTrackErrorAndHasName = micError && micError.name &&
|
||||
micError instanceof JitsiMeetJS.JitsiTrackError;
|
||||
micError instanceof JitsiMeetJS.errorTypes.JitsiTrackError;
|
||||
let isCameraJitsiTrackErrorAndHasName = cameraError && cameraError.name &&
|
||||
cameraError instanceof JitsiMeetJS.JitsiTrackError;
|
||||
cameraError instanceof JitsiMeetJS.errorTypes.JitsiTrackError;
|
||||
let showDoNotShowWarning = false;
|
||||
|
||||
if (micError && cameraError && isMicJitsiTrackErrorAndHasName &&
|
||||
@@ -1401,18 +1456,14 @@ UI.enableMicrophoneButton = function () {
|
||||
Toolbar.markAudioIconAsDisabled(false);
|
||||
};
|
||||
|
||||
let bottomToolbarEnabled = null;
|
||||
|
||||
UI.showRingOverLay = function () {
|
||||
RingOverlay.show(APP.tokenData.callee);
|
||||
ToolbarToggler.setAlwaysVisibleToolbar(true);
|
||||
FilmStrip.toggleFilmStrip(false);
|
||||
};
|
||||
|
||||
UI.hideRingOverLay = function () {
|
||||
if (!RingOverlay.hide())
|
||||
return;
|
||||
ToolbarToggler.resetAlwaysVisibleToolbar();
|
||||
FilmStrip.toggleFilmStrip(true);
|
||||
};
|
||||
|
||||
|
||||
10
modules/UI/UIErrors.js
Normal file
10
modules/UI/UIErrors.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* A list of all UI errors.
|
||||
*/
|
||||
module.exports = {
|
||||
/**
|
||||
* Indicates that a Feedback request is currently in progress.
|
||||
* @type {{FEEDBACK_REQUEST_IN_PROGRESS: string}}
|
||||
*/
|
||||
FEEDBACK_REQUEST_IN_PROGRESS: "FeedbackRequestInProgress"
|
||||
};
|
||||
@@ -209,7 +209,7 @@ const AudioLevels = {
|
||||
drawContext.drawImage(canvasCache, 0, 0);
|
||||
|
||||
if (id === LOCAL_LEVEL) {
|
||||
id = APP.conference.localId;
|
||||
id = APP.conference.getMyUserId();
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
/* global JitsiMeetJS, APP */
|
||||
/* global APP, config, JitsiMeetJS, Promise */
|
||||
|
||||
import LoginDialog from './LoginDialog';
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
import UIUtil from '../util/UIUtil';
|
||||
import {openConnection} from '../../../connection';
|
||||
|
||||
const ConferenceEvents = JitsiMeetJS.events.conference;
|
||||
const ConnectionErrors = JitsiMeetJS.errors.connection;
|
||||
|
||||
let externalAuthWindow;
|
||||
let authRequiredDialog;
|
||||
|
||||
let isTokenAuthEnabled
|
||||
= typeof config.tokenAuthUrl === "string" && config.tokenAuthUrl.length;
|
||||
let getTokenAuthUrl
|
||||
= JitsiMeetJS.util.AuthUtil.getTokenAuthUrl.bind(null, config.tokenAuthUrl);
|
||||
|
||||
/**
|
||||
* Authenticate using external service or just focus
|
||||
* external auth window if there is one already.
|
||||
@@ -23,19 +28,103 @@ function doExternalAuth (room, lockPassword) {
|
||||
return;
|
||||
}
|
||||
if (room.isJoined()) {
|
||||
room.getExternalAuthUrl(true).then(function (url) {
|
||||
let getUrl;
|
||||
if (isTokenAuthEnabled) {
|
||||
getUrl = Promise.resolve(getTokenAuthUrl(room.getName(), true));
|
||||
initJWTTokenListener(room);
|
||||
} else {
|
||||
getUrl = room.getExternalAuthUrl(true);
|
||||
}
|
||||
getUrl.then(function (url) {
|
||||
externalAuthWindow = LoginDialog.showExternalAuthDialog(
|
||||
url,
|
||||
function () {
|
||||
externalAuthWindow = null;
|
||||
room.join(lockPassword);
|
||||
if (!isTokenAuthEnabled) {
|
||||
room.join(lockPassword);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// If conference has not been started yet
|
||||
// then redirect to login page
|
||||
room.getExternalAuthUrl().then(UIUtil.redirect);
|
||||
if (isTokenAuthEnabled) {
|
||||
redirectToTokenAuthService(room.getName());
|
||||
} else {
|
||||
room.getExternalAuthUrl().then(UIUtil.redirect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect the user to the token authentication service for the login to be
|
||||
* performed. Once complete it is expected that the service wil bring the user
|
||||
* back with "?jwt={the JWT token}" query parameter added.
|
||||
* @param {string} [roomName] the name of the conference room.
|
||||
*/
|
||||
function redirectToTokenAuthService(roomName) {
|
||||
UIUtil.redirect(getTokenAuthUrl(roomName, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes 'message' listener that will wait for a JWT token to be received
|
||||
* from the token authentication service opened in a popup window.
|
||||
* @param room the name fo the conference room.
|
||||
*/
|
||||
function initJWTTokenListener(room) {
|
||||
var self = this;
|
||||
var listener = function (event) {
|
||||
if (externalAuthWindow !== event.source) {
|
||||
console.warn("Ignored message not coming " +
|
||||
"from external authnetication window");
|
||||
return;
|
||||
}
|
||||
if (event.data && event.data.jwtToken) {
|
||||
config.token = event.data.jwtToken;
|
||||
console.info("Received JWT token:", config.token);
|
||||
var roomName = room.getName();
|
||||
openConnection({retry: false, roomName: roomName })
|
||||
.then(function (connection) {
|
||||
// Start new connection
|
||||
let newRoom = connection.initJitsiConference(
|
||||
roomName, APP.conference._getConferenceOptions());
|
||||
// Authenticate from the new connection to get
|
||||
// the session-ID from the focus, which wil then be used
|
||||
// to upgrade current connection's user role
|
||||
newRoom.room.moderator.authenticate().then(function () {
|
||||
connection.disconnect();
|
||||
// At this point we'll have session-ID stored in
|
||||
// the settings. It wil be used in the call below
|
||||
// to upgrade user's role
|
||||
room.room.moderator.authenticate()
|
||||
.then(function () {
|
||||
console.info("User role upgrade done !");
|
||||
unregister();
|
||||
}).catch(function (err, errCode) {
|
||||
console.error(
|
||||
"Authentication failed: ", err, errCode);
|
||||
unregister();
|
||||
}
|
||||
);
|
||||
}).catch(function (error, code) {
|
||||
unregister();
|
||||
connection.disconnect();
|
||||
console.error(
|
||||
'Authentication failed on the new connection',
|
||||
error, code);
|
||||
});
|
||||
}, function (err) {
|
||||
unregister();
|
||||
console.error("Failed to open new connection", err);
|
||||
});
|
||||
}
|
||||
};
|
||||
var unregister = function () {
|
||||
window.removeEventListener("message", listener);
|
||||
};
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("message", listener, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +141,8 @@ function doXmppAuth (room, lockPassword) {
|
||||
// (this will store sessionId in the localStorage)
|
||||
// 3. close new connection
|
||||
// 4. reallocate focus in current room
|
||||
openConnection({id, password}).then(function (connection) {
|
||||
openConnection({id, password, roomName: room.getName()}).then(
|
||||
function (connection) {
|
||||
// open room
|
||||
let newRoom = connection.initJitsiConference(
|
||||
room.getName(), APP.conference._getConferenceOptions()
|
||||
@@ -99,7 +189,7 @@ function doXmppAuth (room, lockPassword) {
|
||||
* @param {string} [lockPassword] password to use if the conference is locked
|
||||
*/
|
||||
function authenticate (room, lockPassword) {
|
||||
if (room.isExternalAuthEnabled()) {
|
||||
if (isTokenAuthEnabled || room.isExternalAuthEnabled()) {
|
||||
doExternalAuth(room, lockPassword);
|
||||
} else {
|
||||
doXmppAuth(room, lockPassword);
|
||||
@@ -156,10 +246,52 @@ function closeAuth() {
|
||||
}
|
||||
}
|
||||
|
||||
function showXmppPasswordPrompt(roomName, connect) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let authDialog = LoginDialog.showAuthDialog(
|
||||
function (id, password) {
|
||||
connect(id, password, roomName).then(function (connection) {
|
||||
authDialog.close();
|
||||
resolve(connection);
|
||||
}, function (err) {
|
||||
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
|
||||
authDialog.displayError(err);
|
||||
} else {
|
||||
authDialog.close();
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Authentication Dialog and try to connect with new credentials.
|
||||
* If failed to connect because of PASSWORD_REQUIRED error
|
||||
* then ask for password again.
|
||||
* @param {string} [roomName] name of the conference room
|
||||
* @param {function(id, password, roomName)} [connect] function that returns
|
||||
* a Promise which resolves with JitsiConnection or fails with one of
|
||||
* ConnectionErrors.
|
||||
* @returns {Promise<JitsiConnection>}
|
||||
*/
|
||||
function requestAuth(roomName, connect) {
|
||||
if (isTokenAuthEnabled) {
|
||||
// This Promise never resolves as user gets redirected to another URL
|
||||
return new Promise(function (resolve, reject) {
|
||||
redirectToTokenAuthService(roomName);
|
||||
});
|
||||
} else {
|
||||
return showXmppPasswordPrompt(roomName, connect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
authenticate,
|
||||
requireAuth,
|
||||
requestAuth,
|
||||
closeAuth,
|
||||
logout
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
/* global APP, JitsiMeetJS */
|
||||
import UIUtil from '../util/UIUtil';
|
||||
//FIXME:
|
||||
import AnalyticsAdapter from '../../statistics/AnalyticsAdapter';
|
||||
|
||||
/**
|
||||
* Show dialog which asks user for new password for the conference.
|
||||
@@ -116,6 +114,7 @@ const ConferenceErrors = JitsiMeetJS.errors.conference;
|
||||
*/
|
||||
export default function createRoomLocker (room) {
|
||||
let password;
|
||||
let dialog = null;
|
||||
|
||||
function lock (newPass) {
|
||||
return room.lock(newPass).then(function () {
|
||||
@@ -151,7 +150,7 @@ export default function createRoomLocker (room) {
|
||||
return askToUnlock().then(
|
||||
() => { return lock(); }
|
||||
).then(function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.lock.disabled');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.lock.disabled');
|
||||
}).catch(
|
||||
reason => {
|
||||
if (reason !== APP.UI.messageHandler.CANCEL)
|
||||
@@ -169,7 +168,7 @@ export default function createRoomLocker (room) {
|
||||
return askForNewPassword().then(
|
||||
newPass => { return lock(newPass);}
|
||||
).then(function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.lock.enabled');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.lock.enabled');
|
||||
}).catch(
|
||||
reason => {
|
||||
if (reason !== APP.UI.messageHandler.CANCEL)
|
||||
@@ -196,12 +195,21 @@ export default function createRoomLocker (room) {
|
||||
* Show notification that to set/remove password user must be moderator.
|
||||
*/
|
||||
notifyModeratorRequired () {
|
||||
if (dialog)
|
||||
return;
|
||||
|
||||
let closeCallback = function () {
|
||||
dialog = null;
|
||||
};
|
||||
|
||||
if (password) {
|
||||
APP.UI.messageHandler
|
||||
.openMessageDialog(null, "dialog.passwordError");
|
||||
dialog = APP.UI.messageHandler
|
||||
.openMessageDialog(null, "dialog.passwordError",
|
||||
null, null, closeCallback);
|
||||
} else {
|
||||
APP.UI.messageHandler
|
||||
.openMessageDialog(null, "dialog.passwordError2");
|
||||
dialog = APP.UI.messageHandler
|
||||
.openMessageDialog(null, "dialog.passwordError2",
|
||||
null, null, closeCallback);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,6 +37,15 @@ export default {
|
||||
this._setUserProp(id, "url", url);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the user's avatar id.
|
||||
* @param id id of the user
|
||||
* @param avatarId an id to be used for the avatar
|
||||
*/
|
||||
setUserAvatarID: function (id, avatarId) {
|
||||
this._setUserProp(id, "avatarId", avatarId);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the URL of the image for the avatar of a particular user,
|
||||
* identified by its id.
|
||||
@@ -55,11 +64,16 @@ export default {
|
||||
let avatarId = null;
|
||||
const user = users[userId];
|
||||
|
||||
// The priority is url, email and lowest is avatarId
|
||||
if(user) {
|
||||
if(user.url)
|
||||
return users[userId].url;
|
||||
return user.url;
|
||||
|
||||
avatarId = users[userId].email;
|
||||
if (user.email)
|
||||
avatarId = user.email;
|
||||
else {
|
||||
avatarId = user.avatarId;
|
||||
}
|
||||
}
|
||||
|
||||
// If the ID looks like an email, we'll use gravatar.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* global APP, $, config, interfaceConfig */
|
||||
/* global APP, $, config, interfaceConfig, JitsiMeetJS */
|
||||
/*
|
||||
* Copyright @ 2015 Atlassian Pty Ltd
|
||||
*
|
||||
@@ -21,6 +21,10 @@ import Feedback from '../Feedback.js';
|
||||
import Toolbar from '../toolbars/Toolbar';
|
||||
import BottomToolbar from '../toolbars/BottomToolbar';
|
||||
|
||||
/**
|
||||
* The dialog for user input.
|
||||
*/
|
||||
let dialog = null;
|
||||
|
||||
/**
|
||||
* Indicates if the recording button should be enabled.
|
||||
@@ -50,7 +54,7 @@ function _requestLiveStreamId() {
|
||||
"liveStreaming.streamIdRequired");
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
let dialog = APP.UI.messageHandler.openDialogWithStates({
|
||||
dialog = APP.UI.messageHandler.openDialogWithStates({
|
||||
state0: {
|
||||
html:
|
||||
`<h2>${msg}</h2>
|
||||
@@ -104,6 +108,10 @@ function _requestLiveStreamId() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
close: function () {
|
||||
dialog = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -117,7 +125,7 @@ function _requestRecordingToken () {
|
||||
let token = APP.translation.translateString("dialog.token");
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
APP.UI.messageHandler.openTwoButtonDialog(
|
||||
dialog = APP.UI.messageHandler.openTwoButtonDialog(
|
||||
null, null, null,
|
||||
`<h2>${msg}</h2>
|
||||
<input name="recordingToken" type="text"
|
||||
@@ -132,7 +140,9 @@ function _requestRecordingToken () {
|
||||
}
|
||||
},
|
||||
null,
|
||||
function () { },
|
||||
function () {
|
||||
dialog = null;
|
||||
},
|
||||
':input:first'
|
||||
);
|
||||
});
|
||||
@@ -161,7 +171,7 @@ function _showStopRecordingPrompt (recordingType) {
|
||||
}
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
APP.UI.messageHandler.openTwoButtonDialog(
|
||||
dialog = APP.UI.messageHandler.openTwoButtonDialog(
|
||||
title,
|
||||
null,
|
||||
message,
|
||||
@@ -174,6 +184,10 @@ function _showStopRecordingPrompt (recordingType) {
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
},
|
||||
null,
|
||||
function () {
|
||||
dialog = null;
|
||||
}
|
||||
);
|
||||
});
|
||||
@@ -187,10 +201,11 @@ function _showStopRecordingPrompt (recordingType) {
|
||||
*/
|
||||
function moveToCorner(selector, move) {
|
||||
let moveToCornerClass = "moveToCorner";
|
||||
let containsClass = selector.hasClass(moveToCornerClass);
|
||||
|
||||
if (move && !selector.hasClass(moveToCornerClass))
|
||||
if (move && !containsClass)
|
||||
selector.addClass(moveToCornerClass);
|
||||
else
|
||||
else if (!move && containsClass)
|
||||
selector.removeClass(moveToCornerClass);
|
||||
}
|
||||
|
||||
@@ -206,11 +221,21 @@ var Status = {
|
||||
AVAILABLE: "available",
|
||||
UNAVAILABLE: "unavailable",
|
||||
PENDING: "pending",
|
||||
RETRYING: "retrying",
|
||||
ERROR: "error",
|
||||
FAILED: "failed",
|
||||
BUSY: "busy"
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks whether if the given status is either PENDING or RETRYING
|
||||
* @param status {Status} Jibri status to be checked
|
||||
* @returns {boolean} true if the condition is met or false otherwise.
|
||||
*/
|
||||
function isStartingStatus(status) {
|
||||
return status === Status.PENDING || status === Status.RETRYING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages the recording user interface and user experience.
|
||||
* @type {{init, initRecordingButton, showRecordingButton, updateRecordingState,
|
||||
@@ -231,7 +256,7 @@ var Recording = {
|
||||
// everyone.
|
||||
if (config.iAmRecorder) {
|
||||
VideoLayout.enableDeviceAvailabilityIcons(
|
||||
APP.conference.localId, false);
|
||||
APP.conference.getMyUserId(), false);
|
||||
VideoLayout.setLocalVideoVisible(false);
|
||||
Feedback.enableFeedback(false);
|
||||
Toolbar.enable(false);
|
||||
@@ -279,11 +304,20 @@ var Recording = {
|
||||
|
||||
var self = this;
|
||||
selector.click(function () {
|
||||
if (dialog)
|
||||
return;
|
||||
JitsiMeetJS.analytics.sendEvent('recording.clicked');
|
||||
switch (self.currentState) {
|
||||
case Status.ON:
|
||||
case Status.RETRYING:
|
||||
case Status.PENDING: {
|
||||
_showStopRecordingPrompt(recordingType).then(() =>
|
||||
self.eventEmitter.emit(UIEvents.RECORDING_TOGGLED));
|
||||
_showStopRecordingPrompt(recordingType).then(
|
||||
() => {
|
||||
self.eventEmitter.emit(UIEvents.RECORDING_TOGGLED);
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'recording.stopped');
|
||||
},
|
||||
() => {});
|
||||
break;
|
||||
}
|
||||
case Status.AVAILABLE:
|
||||
@@ -292,42 +326,62 @@ var Recording = {
|
||||
_requestLiveStreamId().then((streamId) => {
|
||||
self.eventEmitter.emit( UIEvents.RECORDING_TOGGLED,
|
||||
{streamId: streamId});
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'recording.started');
|
||||
}).catch(
|
||||
reason => {
|
||||
if (reason !== APP.UI.messageHandler.CANCEL)
|
||||
console.error(reason);
|
||||
else
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'recording.canceled');
|
||||
}
|
||||
);
|
||||
else {
|
||||
if (self.predefinedToken) {
|
||||
self.eventEmitter.emit( UIEvents.RECORDING_TOGGLED,
|
||||
{token: self.predefinedToken});
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'recording.started');
|
||||
return;
|
||||
}
|
||||
|
||||
_requestRecordingToken().then((token) => {
|
||||
self.eventEmitter.emit( UIEvents.RECORDING_TOGGLED,
|
||||
{token: token});
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'recording.started');
|
||||
}).catch(
|
||||
reason => {
|
||||
if (reason !== APP.UI.messageHandler.CANCEL)
|
||||
console.error(reason);
|
||||
else
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'recording.canceled');
|
||||
}
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Status.BUSY: {
|
||||
APP.UI.messageHandler.openMessageDialog(
|
||||
dialog = APP.UI.messageHandler.openMessageDialog(
|
||||
self.recordingTitle,
|
||||
self.recordingBusy
|
||||
self.recordingBusy,
|
||||
null, null,
|
||||
function () {
|
||||
dialog = null;
|
||||
}
|
||||
);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
APP.UI.messageHandler.openMessageDialog(
|
||||
dialog = APP.UI.messageHandler.openMessageDialog(
|
||||
self.recordingTitle,
|
||||
self.recordingUnavailable
|
||||
self.recordingUnavailable,
|
||||
null, null,
|
||||
function () {
|
||||
dialog = null;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -373,7 +427,8 @@ var Recording = {
|
||||
this.currentState = recordingState;
|
||||
|
||||
// TODO: handle recording state=available
|
||||
if (recordingState === Status.ON) {
|
||||
if (recordingState === Status.ON ||
|
||||
recordingState === Status.RETRYING) {
|
||||
|
||||
buttonSelector.removeClass(this.baseClass);
|
||||
buttonSelector.addClass(this.baseClass + " active");
|
||||
@@ -388,14 +443,14 @@ var Recording = {
|
||||
// We don't want to do any changes if this is
|
||||
// an availability change.
|
||||
if (oldState !== Status.ON
|
||||
&& oldState !== Status.PENDING)
|
||||
&& !isStartingStatus(oldState))
|
||||
return;
|
||||
|
||||
buttonSelector.removeClass(this.baseClass + " active");
|
||||
buttonSelector.addClass(this.baseClass);
|
||||
|
||||
let messageKey;
|
||||
if (oldState === Status.PENDING)
|
||||
if (isStartingStatus(oldState))
|
||||
messageKey = this.failedToStartKey;
|
||||
else
|
||||
messageKey = this.recordingOffKey;
|
||||
@@ -427,6 +482,12 @@ var Recording = {
|
||||
if (recordingState !== Status.AVAILABLE
|
||||
&& !labelSelector.is(":visible"))
|
||||
labelSelector.css({display: "inline-block"});
|
||||
|
||||
// Recording spinner
|
||||
if (recordingState === Status.RETRYING)
|
||||
$("#recordingSpinner").show();
|
||||
else
|
||||
$("#recordingSpinner").hide();
|
||||
},
|
||||
// checks whether recording is enabled and whether we have params
|
||||
// to start automatically recording
|
||||
@@ -445,11 +506,12 @@ var Recording = {
|
||||
*/
|
||||
_updateStatusLabel(textKey, isCentered) {
|
||||
let labelSelector = $('#recordingLabel');
|
||||
let labelTextSelector = $('#recordingLabelText');
|
||||
|
||||
moveToCorner(labelSelector, !isCentered);
|
||||
|
||||
labelSelector.attr("data-i18n", textKey);
|
||||
labelSelector.text(APP.translation.translateString(textKey));
|
||||
labelTextSelector.attr("data-i18n", textKey);
|
||||
labelTextSelector.text(APP.translation.translateString(textKey));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -78,5 +78,14 @@ export default {
|
||||
overlay.destroy();
|
||||
overlay = null;
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* Checks whether or not the ring overlay is currently displayed.
|
||||
*
|
||||
* @returns {boolean} true if the ring overlay is currently displayed or
|
||||
* false otherwise.
|
||||
*/
|
||||
isDisplayed () {
|
||||
return overlay !== null;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
/* global $, APP, YT, onPlayerReady, onPlayerStateChange, onPlayerError */
|
||||
/* global $, APP, YT, onPlayerReady, onPlayerStateChange, onPlayerError,
|
||||
JitsiMeetJS */
|
||||
|
||||
import UIUtil from '../util/UIUtil';
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
@@ -17,6 +18,13 @@ export const SHARED_VIDEO_CONTAINER_TYPE = "sharedvideo";
|
||||
*/
|
||||
const defaultSharedVideoLink = "https://www.youtube.com/watch?v=xNXN7CZk8X0";
|
||||
const updateInterval = 5000; // milliseconds
|
||||
|
||||
/**
|
||||
* The dialog for user input (video link).
|
||||
* @type {null}
|
||||
*/
|
||||
let dialog = null;
|
||||
|
||||
/**
|
||||
* Manager of shared video.
|
||||
*/
|
||||
@@ -56,24 +64,41 @@ export default class SharedVideoManager {
|
||||
* asks whether the user wants to stop sharing the video.
|
||||
*/
|
||||
toggleSharedVideo () {
|
||||
if (dialog)
|
||||
return;
|
||||
|
||||
if(!this.isSharedVideoShown) {
|
||||
requestVideoLink().then(
|
||||
url => this.emitter.emit(
|
||||
UIEvents.UPDATE_SHARED_VIDEO, url, 'start'),
|
||||
err => console.error('SHARED VIDEO CANCELED', err)
|
||||
url => {
|
||||
this.emitter.emit(
|
||||
UIEvents.UPDATE_SHARED_VIDEO, url, 'start');
|
||||
JitsiMeetJS.analytics.sendEvent('sharedvideo.started');
|
||||
},
|
||||
err => {
|
||||
console.log('SHARED VIDEO CANCELED', err);
|
||||
JitsiMeetJS.analytics.sendEvent('sharedvideo.canceled');
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if(APP.conference.isLocalId(this.from)) {
|
||||
showStopVideoPropmpt().then(() =>
|
||||
this.emitter.emit(
|
||||
UIEvents.UPDATE_SHARED_VIDEO, this.url, 'stop'));
|
||||
showStopVideoPropmpt().then(() => {
|
||||
this.emitter.emit(
|
||||
UIEvents.UPDATE_SHARED_VIDEO, this.url, 'stop');
|
||||
JitsiMeetJS.analytics.sendEvent('sharedvideo.stoped');
|
||||
},
|
||||
() => {});
|
||||
} else {
|
||||
APP.UI.messageHandler.openMessageDialog(
|
||||
dialog = APP.UI.messageHandler.openMessageDialog(
|
||||
"dialog.shareVideoTitle",
|
||||
"dialog.alreadySharedVideoMsg"
|
||||
"dialog.alreadySharedVideoMsg",
|
||||
null, null,
|
||||
function () {
|
||||
dialog = null;
|
||||
}
|
||||
);
|
||||
JitsiMeetJS.analytics.sendEvent('sharedvideo.alreadyshared');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +202,7 @@ export default class SharedVideoManager {
|
||||
self.smartAudioMute();
|
||||
} else if (event.data == YT.PlayerState.PAUSED) {
|
||||
self.smartAudioUnmute();
|
||||
JitsiMeetJS.analytics.sendEvent('sharedvideo.paused');
|
||||
}
|
||||
self.fireSharedVideoEvent(event.data == YT.PlayerState.PAUSED);
|
||||
};
|
||||
@@ -206,6 +232,7 @@ export default class SharedVideoManager {
|
||||
else if (event.data.volume <=0 || event.data.muted) {
|
||||
self.smartAudioUnmute();
|
||||
}
|
||||
JitsiMeetJS.analytics.sendEvent('sharedvideo.volumechanged');
|
||||
};
|
||||
|
||||
window.onPlayerReady = function(event) {
|
||||
@@ -624,7 +651,6 @@ SharedVideoThumb.prototype.createContainer = function (spanId) {
|
||||
|
||||
// add the avatar
|
||||
var avatar = document.createElement('img');
|
||||
avatar.id = 'avatar_' + this.id;
|
||||
avatar.className = 'sharedVideoAvatar';
|
||||
avatar.src = "https://img.youtube.com/vi/" + this.url + "/0.jpg";
|
||||
container.appendChild(avatar);
|
||||
@@ -700,7 +726,7 @@ function getYoutubeLink(url) {
|
||||
*/
|
||||
function showStopVideoPropmpt() {
|
||||
return new Promise(function (resolve, reject) {
|
||||
APP.UI.messageHandler.openTwoButtonDialog(
|
||||
dialog = APP.UI.messageHandler.openTwoButtonDialog(
|
||||
"dialog.removeSharedVideoTitle",
|
||||
null,
|
||||
"dialog.removeSharedVideoMsg",
|
||||
@@ -713,6 +739,10 @@ function showStopVideoPropmpt() {
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
},
|
||||
null,
|
||||
function () {
|
||||
dialog = null;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -735,7 +765,7 @@ function requestVideoLink() {
|
||||
const defaultUrl = i18n.translateString("defaultLink", i18nOptions);
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
let dialog = APP.UI.messageHandler.openDialogWithStates({
|
||||
dialog = APP.UI.messageHandler.openDialogWithStates({
|
||||
state0: {
|
||||
html: `
|
||||
<h2>${title}</h2>
|
||||
@@ -795,8 +825,11 @@ function requestVideoLink() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
close: function () {
|
||||
dialog = null;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ var ContactList = {
|
||||
if(!displayName)
|
||||
return;
|
||||
if (id === 'localVideoContainer') {
|
||||
id = APP.conference.localId;
|
||||
id = APP.conference.getMyUserId();
|
||||
}
|
||||
let contactName = $(`#contacts #${id}>p`);
|
||||
|
||||
|
||||
@@ -82,11 +82,6 @@ export default {
|
||||
emitter.emit(UIEvents.EMAIL_CHANGED, $('#setEmail').val());
|
||||
}
|
||||
|
||||
// AVATAR URL CHANGED
|
||||
function updateAvatarUrl () {
|
||||
emitter.emit(UIEvents.AVATAR_URL_CHANGED, $('#setAvatarUrl').val());
|
||||
}
|
||||
|
||||
$('#setEmail')
|
||||
.val(Settings.getEmail())
|
||||
.keyup(function (event) {
|
||||
@@ -95,15 +90,6 @@ export default {
|
||||
}
|
||||
}).focusout(updateEmail);
|
||||
|
||||
$('#setAvatarUrl')
|
||||
.val(Settings.getAvatarUrl())
|
||||
.keyup(function (event) {
|
||||
if (event.keyCode === 13) { // enter
|
||||
updateAvatarUrl();
|
||||
}
|
||||
}).focusout(updateAvatarUrl);
|
||||
|
||||
|
||||
// START MUTED
|
||||
$("#startMutedOptions").change(function () {
|
||||
let startAudioMuted = $("#startAudioMuted").is(":checked");
|
||||
@@ -137,30 +123,37 @@ export default {
|
||||
|
||||
|
||||
// DEVICES LIST
|
||||
if (JitsiMeetJS.mediaDevices.isDeviceListAvailable() &&
|
||||
JitsiMeetJS.mediaDevices.isDeviceChangeAvailable()) {
|
||||
this.changeDevicesList([]);
|
||||
JitsiMeetJS.mediaDevices.isDeviceListAvailable()
|
||||
.then((isDeviceListAvailable) => {
|
||||
if (isDeviceListAvailable &&
|
||||
JitsiMeetJS.mediaDevices.isDeviceChangeAvailable()) {
|
||||
this._initializeDeviceSelectionSettings(emitter);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
$('#selectCamera').change(function () {
|
||||
let cameraDeviceId = $(this).val();
|
||||
if (cameraDeviceId !== Settings.getCameraDeviceId()) {
|
||||
emitter.emit(UIEvents.VIDEO_DEVICE_CHANGED, cameraDeviceId);
|
||||
}
|
||||
});
|
||||
$('#selectMic').change(function () {
|
||||
let micDeviceId = $(this).val();
|
||||
if (micDeviceId !== Settings.getMicDeviceId()) {
|
||||
emitter.emit(UIEvents.AUDIO_DEVICE_CHANGED, micDeviceId);
|
||||
}
|
||||
});
|
||||
$('#selectAudioOutput').change(function () {
|
||||
let audioOutputDeviceId = $(this).val();
|
||||
if (audioOutputDeviceId !== Settings.getAudioOutputDeviceId()) {
|
||||
emitter.emit(UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED,
|
||||
audioOutputDeviceId);
|
||||
}
|
||||
});
|
||||
}
|
||||
_initializeDeviceSelectionSettings(emitter) {
|
||||
this.changeDevicesList([]);
|
||||
|
||||
$('#selectCamera').change(function () {
|
||||
let cameraDeviceId = $(this).val();
|
||||
if (cameraDeviceId !== Settings.getCameraDeviceId()) {
|
||||
emitter.emit(UIEvents.VIDEO_DEVICE_CHANGED, cameraDeviceId);
|
||||
}
|
||||
});
|
||||
$('#selectMic').change(function () {
|
||||
let micDeviceId = $(this).val();
|
||||
if (micDeviceId !== Settings.getMicDeviceId()) {
|
||||
emitter.emit(UIEvents.AUDIO_DEVICE_CHANGED, micDeviceId);
|
||||
}
|
||||
});
|
||||
$('#selectAudioOutput').change(function () {
|
||||
let audioOutputDeviceId = $(this).val();
|
||||
if (audioOutputDeviceId !== Settings.getAudioOutputDeviceId()) {
|
||||
emitter.emit(
|
||||
UIEvents.AUDIO_OUTPUT_DEVICE_CHANGED, audioOutputDeviceId);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
/* global $, APP, interfaceConfig*/
|
||||
/* global $, APP, interfaceConfig, JitsiMeetJS */
|
||||
import UIUtil from '../util/UIUtil';
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
import AnalyticsAdapter from '../../statistics/AnalyticsAdapter';
|
||||
|
||||
const defaultBottomToolbarButtons = {
|
||||
'chat': '#bottom_toolbar_chat',
|
||||
'contacts': '#bottom_toolbar_contact_list',
|
||||
'filmstrip': '#bottom_toolbar_film_strip'
|
||||
'chat': {
|
||||
id: '#bottom_toolbar_chat'
|
||||
},
|
||||
'contacts': {
|
||||
id: '#bottom_toolbar_contact_list'
|
||||
},
|
||||
'filmstrip': {
|
||||
id: '#bottom_toolbar_film_strip',
|
||||
shortcut: "F",
|
||||
shortcutAttr: "filmstripPopover",
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent("shortcut.film.toggled");
|
||||
APP.UI.toggleFilmStrip();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.toggleFilmstrip"
|
||||
}
|
||||
};
|
||||
|
||||
const BottomToolbar = {
|
||||
@@ -33,24 +45,43 @@ const BottomToolbar = {
|
||||
isEnabled() {
|
||||
return this.enabled;
|
||||
},
|
||||
|
||||
setupListeners (emitter) {
|
||||
UIUtil.hideDisabledButtons(defaultBottomToolbarButtons);
|
||||
|
||||
const buttonHandlers = {
|
||||
"bottom_toolbar_contact_list": function () {
|
||||
AnalyticsAdapter.sendEvent('bottomtoolbar.contacts.toggled');
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'bottomtoolbar.contacts.toggled');
|
||||
emitter.emit(UIEvents.TOGGLE_CONTACT_LIST);
|
||||
},
|
||||
"bottom_toolbar_film_strip": function () {
|
||||
AnalyticsAdapter.sendEvent('bottomtoolbar.filmstrip.toggled');
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'bottomtoolbar.filmstrip.toggled');
|
||||
emitter.emit(UIEvents.TOGGLE_FILM_STRIP);
|
||||
},
|
||||
"bottom_toolbar_chat": function () {
|
||||
AnalyticsAdapter.sendEvent('bottomtoolbar.chat.toggled');
|
||||
JitsiMeetJS.analytics.sendEvent('bottomtoolbar.chat.toggled');
|
||||
emitter.emit(UIEvents.TOGGLE_CHAT);
|
||||
}
|
||||
};
|
||||
|
||||
Object.keys(defaultBottomToolbarButtons).forEach(
|
||||
id => {
|
||||
if (UIUtil.isButtonEnabled(id)) {
|
||||
var button = defaultBottomToolbarButtons[id];
|
||||
|
||||
if (button.shortcut)
|
||||
APP.keyboardshortcut.registerShortcut(
|
||||
button.shortcut,
|
||||
button.shortcutAttr,
|
||||
button.shortcutFunc,
|
||||
button.shortcutDescription
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Object.keys(buttonHandlers).forEach(
|
||||
buttonId => $(`#${buttonId}`).click(buttonHandlers[buttonId])
|
||||
);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/* global APP, $, config, interfaceConfig */
|
||||
/* global APP, $, config, interfaceConfig, JitsiMeetJS */
|
||||
/* jshint -W101 */
|
||||
import UIUtil from '../util/UIUtil';
|
||||
import AnalyticsAdapter from '../../statistics/AnalyticsAdapter';
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
|
||||
let roomUrl = null;
|
||||
@@ -26,8 +25,12 @@ function openLinkDialog () {
|
||||
false, "dialog.Invite",
|
||||
function (e, v) {
|
||||
if (v && roomUrl) {
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.invite.button');
|
||||
emitter.emit(UIEvents.USER_INVITED, roomUrl);
|
||||
}
|
||||
else {
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.invite.cancel');
|
||||
}
|
||||
},
|
||||
function (event) {
|
||||
if (roomUrl) {
|
||||
@@ -37,6 +40,10 @@ function openLinkDialog () {
|
||||
$(event.target).find('button[value=true]').prop('disabled', true);
|
||||
}
|
||||
}
|
||||
},
|
||||
function (e, v, m, f) {
|
||||
if(!v && !m && !f)
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.invite.close');
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -56,77 +63,79 @@ const buttonHandlers = {
|
||||
$("#unableToUnmutePopup"), true, 5000);
|
||||
}
|
||||
else {
|
||||
AnalyticsAdapter.sendEvent('toolbar.audio.unmuted');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.audio.unmuted');
|
||||
emitter.emit(UIEvents.AUDIO_MUTED, false, true);
|
||||
}
|
||||
} else {
|
||||
AnalyticsAdapter.sendEvent('toolbar.audio.muted');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.audio.muted');
|
||||
emitter.emit(UIEvents.AUDIO_MUTED, true, true);
|
||||
}
|
||||
},
|
||||
"toolbar_button_camera": function () {
|
||||
if (APP.conference.videoMuted) {
|
||||
AnalyticsAdapter.sendEvent('toolbar.video.enabled');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.video.enabled');
|
||||
emitter.emit(UIEvents.VIDEO_MUTED, false);
|
||||
} else {
|
||||
AnalyticsAdapter.sendEvent('toolbar.video.disabled');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.video.disabled');
|
||||
emitter.emit(UIEvents.VIDEO_MUTED, true);
|
||||
}
|
||||
},
|
||||
"toolbar_button_security": function () {
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.lock.clicked');
|
||||
emitter.emit(UIEvents.ROOM_LOCK_CLICKED);
|
||||
},
|
||||
"toolbar_button_link": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.invite.clicked');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.invite.clicked');
|
||||
openLinkDialog();
|
||||
},
|
||||
"toolbar_button_chat": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.chat.toggled');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.chat.toggled');
|
||||
emitter.emit(UIEvents.TOGGLE_CHAT);
|
||||
},
|
||||
"toolbar_button_etherpad": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.etherpad.clicked');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.etherpad.clicked');
|
||||
emitter.emit(UIEvents.ETHERPAD_CLICKED);
|
||||
},
|
||||
"toolbar_button_sharedvideo": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.sharedvideo.clicked');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.sharedvideo.clicked');
|
||||
emitter.emit(UIEvents.SHARED_VIDEO_CLICKED);
|
||||
},
|
||||
"toolbar_button_desktopsharing": function () {
|
||||
if (APP.conference.isSharingScreen) {
|
||||
AnalyticsAdapter.sendEvent('toolbar.screen.disabled');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.screen.disabled');
|
||||
} else {
|
||||
AnalyticsAdapter.sendEvent('toolbar.screen.enabled');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.screen.enabled');
|
||||
}
|
||||
emitter.emit(UIEvents.TOGGLE_SCREENSHARING);
|
||||
},
|
||||
"toolbar_button_fullScreen": function() {
|
||||
AnalyticsAdapter.sendEvent('toolbar.fullscreen.enabled');
|
||||
UIUtil.buttonClick("#toolbar_button_fullScreen", "icon-full-screen icon-exit-full-screen");
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.fullscreen.enabled');
|
||||
UIUtil.buttonClick("#toolbar_button_fullScreen",
|
||||
"icon-full-screen icon-exit-full-screen");
|
||||
emitter.emit(UIEvents.FULLSCREEN_TOGGLE);
|
||||
},
|
||||
"toolbar_button_sip": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.sip.clicked');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.sip.clicked');
|
||||
showSipNumberInput();
|
||||
},
|
||||
"toolbar_button_dialpad": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.sip.dialpad.clicked');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.sip.dialpad.clicked');
|
||||
dialpadButtonClicked();
|
||||
},
|
||||
"toolbar_button_settings": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.settings.toggled');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.settings.toggled');
|
||||
emitter.emit(UIEvents.TOGGLE_SETTINGS);
|
||||
},
|
||||
"toolbar_button_hangup": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.hangup');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.hangup');
|
||||
emitter.emit(UIEvents.HANGUP);
|
||||
},
|
||||
"toolbar_button_login": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.authenticate.login.clicked');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.authenticate.login.clicked');
|
||||
emitter.emit(UIEvents.AUTH_CLICKED);
|
||||
},
|
||||
"toolbar_button_logout": function () {
|
||||
AnalyticsAdapter.sendEvent('toolbar.authenticate.logout.clicked');
|
||||
JitsiMeetJS.analytics.sendEvent('toolbar.authenticate.logout.clicked');
|
||||
// Ask for confirmation
|
||||
APP.UI.messageHandler.openTwoButtonDialog(
|
||||
"dialog.logoutTitle",
|
||||
@@ -144,16 +153,64 @@ const buttonHandlers = {
|
||||
}
|
||||
};
|
||||
const defaultToolbarButtons = {
|
||||
'microphone': '#toolbar_button_mute',
|
||||
'camera': '#toolbar_button_camera',
|
||||
'desktop': '#toolbar_button_desktopsharing',
|
||||
'security': '#toolbar_button_security',
|
||||
'invite': '#toolbar_button_link',
|
||||
'chat': '#toolbar_button_chat',
|
||||
'etherpad': '#toolbar_button_etherpad',
|
||||
'fullscreen': '#toolbar_button_fullScreen',
|
||||
'settings': '#toolbar_button_settings',
|
||||
'hangup': '#toolbar_button_hangup'
|
||||
'microphone': {
|
||||
id: '#toolbar_button_mute',
|
||||
shortcut: 'M',
|
||||
shortcutAttr: 'mutePopover',
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent('shortcut.audiomute.toggled');
|
||||
APP.conference.toggleAudioMuted();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.mute"
|
||||
},
|
||||
'camera': {
|
||||
id: '#toolbar_button_camera',
|
||||
shortcut: 'V',
|
||||
shortcutAttr: 'toggleVideoPopover',
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent('shortcut.videomute.toggled');
|
||||
APP.conference.toggleVideoMuted();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.videoMute"
|
||||
},
|
||||
'desktop': {
|
||||
id: '#toolbar_button_desktopsharing',
|
||||
shortcut: 'D',
|
||||
shortcutAttr: 'toggleDesktopSharingPopover',
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent('shortcut.screen.toggled');
|
||||
APP.conference.toggleScreenSharing();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.toggleScreensharing"
|
||||
},
|
||||
'security': {
|
||||
id: '#toolbar_button_security'
|
||||
},
|
||||
'invite': {
|
||||
id: '#toolbar_button_link'
|
||||
},
|
||||
'chat': {
|
||||
id: '#toolbar_button_chat',
|
||||
shortcut: 'C',
|
||||
shortcutAttr: 'toggleChatPopover',
|
||||
shortcutFunc: function() {
|
||||
JitsiMeetJS.analytics.sendEvent('shortcut.chat.toggled');
|
||||
APP.UI.toggleChat();
|
||||
},
|
||||
shortcutDescription: "keyboardShortcuts.toggleChat"
|
||||
},
|
||||
'etherpad': {
|
||||
id: '#toolbar_button_etherpad'
|
||||
},
|
||||
'fullscreen': {
|
||||
id: '#toolbar_button_fullScreen'
|
||||
},
|
||||
'settings': {
|
||||
id: '#toolbar_button_settings'
|
||||
},
|
||||
'hangup': {
|
||||
id: '#toolbar_button_hangup'
|
||||
}
|
||||
};
|
||||
|
||||
function dialpadButtonClicked() {
|
||||
@@ -189,6 +246,22 @@ const Toolbar = {
|
||||
|
||||
UIUtil.hideDisabledButtons(defaultToolbarButtons);
|
||||
|
||||
Object.keys(defaultToolbarButtons).forEach(
|
||||
id => {
|
||||
if (UIUtil.isButtonEnabled(id)) {
|
||||
var button = defaultToolbarButtons[id];
|
||||
|
||||
if (button.shortcut)
|
||||
APP.keyboardshortcut.registerShortcut(
|
||||
button.shortcut,
|
||||
button.shortcutAttr,
|
||||
button.shortcutFunc,
|
||||
button.shortcutDescription
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Object.keys(buttonHandlers).forEach(
|
||||
buttonId => $(`#${buttonId}`).click(function(event) {
|
||||
!$(this).prop('disabled') && buttonHandlers[buttonId](event);
|
||||
@@ -419,15 +492,21 @@ const Toolbar = {
|
||||
|
||||
/**
|
||||
* Indicates if the toolbar is currently hovered.
|
||||
* @return {true} if the toolbar is currently hovered, {false} otherwise
|
||||
* @return {boolean} true if the toolbar is currently hovered,
|
||||
* false otherwise
|
||||
*/
|
||||
isHovered() {
|
||||
var hovered = false;
|
||||
this.toolbarSelector.find('*').each(function () {
|
||||
let id = $(this).attr('id');
|
||||
if ($(`#${id}:hover`).length > 0) {
|
||||
return true;
|
||||
hovered = true;
|
||||
// break each
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (hovered)
|
||||
return true;
|
||||
if ($("#bottomToolbar:hover").length > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,12 @@ let notificationsEnabled = true;
|
||||
*/
|
||||
let popupEnabled = true;
|
||||
|
||||
/**
|
||||
* Currently displayed two button dialog.
|
||||
* @type {null}
|
||||
*/
|
||||
let twoButtonDialog = null;
|
||||
|
||||
var messageHandler = {
|
||||
OK: "dialog.OK",
|
||||
CANCEL: "dialog.Cancel",
|
||||
@@ -30,10 +36,14 @@ var messageHandler = {
|
||||
* titleKey will be used to get a title via the translation API.
|
||||
* @param message the message to show. If a falsy value is provided,
|
||||
* messageKey will be used to get a message via the translation API.
|
||||
* @param closeFunction function to be called after
|
||||
* the prompt is closed (optional)
|
||||
* @return the prompt that was created, or null
|
||||
*/
|
||||
openMessageDialog: function(titleKey, messageKey, title, message) {
|
||||
openMessageDialog: function(titleKey, messageKey, title, message,
|
||||
closeFunction) {
|
||||
if (!popupEnabled)
|
||||
return;
|
||||
return null;
|
||||
|
||||
if (!title) {
|
||||
title = APP.translation.generateTranslationHTML(titleKey);
|
||||
@@ -42,9 +52,14 @@ var messageHandler = {
|
||||
message = APP.translation.generateTranslationHTML(messageKey);
|
||||
}
|
||||
|
||||
$.prompt(message,
|
||||
{title: title, persistent: false}
|
||||
);
|
||||
return $.prompt(message, {
|
||||
title: title,
|
||||
persistent: false,
|
||||
close: function (e, v, m, f) {
|
||||
if(closeFunction)
|
||||
closeFunction(e, v, m, f);
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Shows a message to the user with two buttons: first is given as a
|
||||
@@ -63,13 +78,14 @@ var messageHandler = {
|
||||
* the dialog is opened
|
||||
* @param defaultButton index of default button which will be activated when
|
||||
* the user press 'enter'. Indexed from 0.
|
||||
* @return the prompt that was created, or null
|
||||
*/
|
||||
openTwoButtonDialog: function(titleKey, titleString, msgKey, msgString,
|
||||
persistent, leftButtonKey, submitFunction, loadedFunction,
|
||||
closeFunction, focus, defaultButton) {
|
||||
|
||||
if (!popupEnabled)
|
||||
return;
|
||||
if (!popupEnabled || twoButtonDialog)
|
||||
return null;
|
||||
|
||||
var buttons = [];
|
||||
|
||||
@@ -87,16 +103,25 @@ var messageHandler = {
|
||||
if (msgKey) {
|
||||
message = APP.translation.generateTranslationHTML(msgKey);
|
||||
}
|
||||
$.prompt(message, {
|
||||
twoButtonDialog = $.prompt(message, {
|
||||
title: title,
|
||||
persistent: false,
|
||||
buttons: buttons,
|
||||
defaultButton: defaultButton,
|
||||
focus: focus,
|
||||
loaded: loadedFunction,
|
||||
submit: submitFunction,
|
||||
close: closeFunction
|
||||
submit: function (e, v, m, f) {
|
||||
twoButtonDialog = null;
|
||||
if (submitFunction)
|
||||
submitFunction(e, v, m, f);
|
||||
},
|
||||
close: function (e, v, m, f) {
|
||||
twoButtonDialog = null;
|
||||
if (closeFunction)
|
||||
closeFunction(e, v, m, f);
|
||||
}
|
||||
});
|
||||
return twoButtonDialog;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -133,7 +158,7 @@ var messageHandler = {
|
||||
if (persistent) {
|
||||
args.closeText = '';
|
||||
}
|
||||
|
||||
|
||||
return new Impromptu(msgString, args);
|
||||
},
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@
|
||||
var selector = Object.keys(mappings)
|
||||
.map(function (buttonName) {
|
||||
return UIUtil.isButtonEnabled(buttonName)
|
||||
? null : mappings[buttonName]; })
|
||||
? null : mappings[buttonName].id; })
|
||||
.filter(function (item) { return item; })
|
||||
.join(',');
|
||||
$(selector).hide();
|
||||
|
||||
@@ -21,7 +21,7 @@ function getStreamOwnerId(stream) {
|
||||
return;
|
||||
}
|
||||
if (stream.isLocal()) { // local stream doesn't have method "getParticipantId"
|
||||
return APP.conference.localId;
|
||||
return APP.conference.getMyUserId();
|
||||
} else {
|
||||
return stream.getParticipantId();
|
||||
}
|
||||
|
||||
@@ -18,10 +18,17 @@ function LocalVideo(VideoLayout, emitter) {
|
||||
this.emitter = emitter;
|
||||
Object.defineProperty(this, 'id', {
|
||||
get: function () {
|
||||
return APP.conference.localId;
|
||||
return APP.conference.getMyUserId();
|
||||
}
|
||||
});
|
||||
this.initBrowserSpecificProperties();
|
||||
|
||||
SmallVideo.call(this, VideoLayout);
|
||||
|
||||
// Set default display name.
|
||||
this.setDisplayName();
|
||||
|
||||
this.createConnectionIndicator();
|
||||
}
|
||||
|
||||
LocalVideo.prototype = Object.create(SmallVideo.prototype);
|
||||
|
||||
@@ -6,18 +6,21 @@ import SmallVideo from "./SmallVideo";
|
||||
import AudioLevels from "../audio_levels/AudioLevels";
|
||||
import UIUtils from "../util/UIUtil";
|
||||
import UIEvents from '../../../service/UI/UIEvents';
|
||||
import JitsiPopover from "../util/JitsiPopover";
|
||||
|
||||
function RemoteVideo(id, VideoLayout, emitter) {
|
||||
this.id = id;
|
||||
this.emitter = emitter;
|
||||
this.videoSpanId = `participant_${id}`;
|
||||
SmallVideo.call(this, VideoLayout);
|
||||
this.hasRemoteVideoMenu = false;
|
||||
this.addRemoteVideoContainer();
|
||||
this.connectionIndicator = new ConnectionIndicator(this, id);
|
||||
this.setDisplayName();
|
||||
this.bindHoverHandler();
|
||||
this.flipX = false;
|
||||
this.isLocal = false;
|
||||
this.isMuted = false;
|
||||
}
|
||||
|
||||
RemoteVideo.prototype = Object.create(SmallVideo.prototype);
|
||||
@@ -25,6 +28,9 @@ RemoteVideo.prototype.constructor = RemoteVideo;
|
||||
|
||||
RemoteVideo.prototype.addRemoteVideoContainer = function() {
|
||||
this.container = RemoteVideo.createContainer(this.videoSpanId);
|
||||
|
||||
this.initBrowserSpecificProperties();
|
||||
|
||||
if (APP.conference.isModerator) {
|
||||
this.addRemoteVideoMenu();
|
||||
}
|
||||
@@ -34,6 +40,127 @@ RemoteVideo.prototype.addRemoteVideoContainer = function() {
|
||||
return this.container;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the remote participant popup menu, by specifying previously
|
||||
* constructed popupMenuElement, containing all the menu items.
|
||||
*
|
||||
* @param popupMenuElement a pre-constructed element, containing the menu items
|
||||
* to display in the popup
|
||||
*/
|
||||
RemoteVideo.prototype._initPopupMenu = function (popupMenuElement) {
|
||||
this.popover = new JitsiPopover(
|
||||
$("#" + this.videoSpanId + " > .remotevideomenu"),
|
||||
{ content: popupMenuElement.outerHTML,
|
||||
skin: "black"});
|
||||
|
||||
// override popover show method to make sure we will update the content
|
||||
// before showing the popover
|
||||
var origShowFunc = this.popover.show;
|
||||
this.popover.show = function () {
|
||||
// update content by forcing it, to finish even if popover
|
||||
// is not visible
|
||||
this.updateRemoteVideoMenu(this.isMuted, true);
|
||||
// call the original show, passing its actual this
|
||||
origShowFunc.call(this.popover);
|
||||
}.bind(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Generates the popup menu content.
|
||||
*
|
||||
* @returns {Element|*} the constructed element, containing popup menu items
|
||||
* @private
|
||||
*/
|
||||
RemoteVideo.prototype._generatePopupContent = function () {
|
||||
var popupmenuElement = document.createElement('ul');
|
||||
popupmenuElement.className = 'popupmenu';
|
||||
popupmenuElement.id = `remote_popupmenu_${this.id}`;
|
||||
|
||||
var muteMenuItem = document.createElement('li');
|
||||
var muteLinkItem = document.createElement('a');
|
||||
|
||||
var mutedIndicator = "<i class='icon-mic-disabled'></i>";
|
||||
|
||||
var doMuteHTML = mutedIndicator +
|
||||
" <div " +
|
||||
"data-i18n='videothumbnail.domute'>" +
|
||||
APP.translation.translateString("videothumbnail.domute") +
|
||||
"</div>";
|
||||
|
||||
var mutedHTML = mutedIndicator +
|
||||
" <div " +
|
||||
"data-i18n='videothumbnail.muted'>" +
|
||||
APP.translation.translateString("videothumbnail.muted") +
|
||||
"</div>";
|
||||
|
||||
muteLinkItem.id = "mutelink_" + this.id;
|
||||
|
||||
if (this.isMuted) {
|
||||
muteLinkItem.innerHTML = mutedHTML;
|
||||
muteLinkItem.className = 'mutelink disabled';
|
||||
}
|
||||
else {
|
||||
muteLinkItem.innerHTML = doMuteHTML;
|
||||
muteLinkItem.className = 'mutelink';
|
||||
}
|
||||
|
||||
// Delegate event to the document.
|
||||
$(document).on("click", "#mutelink_" + this.id, function(){
|
||||
|
||||
if (this.isMuted)
|
||||
return;
|
||||
|
||||
this.emitter.emit(UIEvents.REMOTE_AUDIO_MUTED, this.id);
|
||||
|
||||
this.popover.forceHide();
|
||||
}.bind(this));
|
||||
|
||||
muteMenuItem.appendChild(muteLinkItem);
|
||||
popupmenuElement.appendChild(muteMenuItem);
|
||||
|
||||
var ejectIndicator = "<i style='float:left;' class='fa fa-eject'></i>";
|
||||
|
||||
var ejectMenuItem = document.createElement('li');
|
||||
var ejectLinkItem = document.createElement('a');
|
||||
|
||||
var ejectText = "<div " +
|
||||
"data-i18n='videothumbnail.kick'>" +
|
||||
APP.translation.translateString("videothumbnail.kick") +
|
||||
"</div>";
|
||||
|
||||
ejectLinkItem.className = 'ejectlink';
|
||||
ejectLinkItem.innerHTML = ejectIndicator + ' ' + ejectText;
|
||||
ejectLinkItem.id = "ejectlink_" + this.id;
|
||||
|
||||
$(document).on("click", "#ejectlink_" + this.id, function(){
|
||||
this.emitter.emit(UIEvents.USER_KICKED, this.id);
|
||||
this.popover.forceHide();
|
||||
}.bind(this));
|
||||
|
||||
ejectMenuItem.appendChild(ejectLinkItem);
|
||||
popupmenuElement.appendChild(ejectMenuItem);
|
||||
|
||||
return popupmenuElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the remote video menu.
|
||||
*
|
||||
* @param isMuted the new muted state to update to
|
||||
* @param force to work even if popover is not visible
|
||||
*/
|
||||
RemoteVideo.prototype.updateRemoteVideoMenu = function (isMuted, force) {
|
||||
|
||||
this.isMuted = isMuted;
|
||||
|
||||
// generate content, translate it and add it to document only if
|
||||
// popover is visible or we force to do so.
|
||||
if(this.popover.popoverShown || force) {
|
||||
this.popover.updateContent(this._generatePopupContent());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the remote video menu element for the given <tt>id</tt> in the
|
||||
* given <tt>parentElement</tt>.
|
||||
@@ -43,9 +170,8 @@ RemoteVideo.prototype.addRemoteVideoContainer = function() {
|
||||
*/
|
||||
if (!interfaceConfig.filmStripOnly) {
|
||||
RemoteVideo.prototype.addRemoteVideoMenu = function () {
|
||||
var spanElement = document.createElement('span');
|
||||
var spanElement = document.createElement('div');
|
||||
spanElement.className = 'remotevideomenu';
|
||||
|
||||
this.container.appendChild(spanElement);
|
||||
|
||||
var menuElement = document.createElement('i');
|
||||
@@ -53,77 +179,8 @@ if (!interfaceConfig.filmStripOnly) {
|
||||
menuElement.title = 'Remote user controls';
|
||||
spanElement.appendChild(menuElement);
|
||||
|
||||
|
||||
var popupmenuElement = document.createElement('ul');
|
||||
popupmenuElement.className = 'popupmenu';
|
||||
popupmenuElement.id = `remote_popupmenu_${this.id}`;
|
||||
spanElement.appendChild(popupmenuElement);
|
||||
|
||||
var muteMenuItem = document.createElement('li');
|
||||
var muteLinkItem = document.createElement('a');
|
||||
|
||||
var mutedIndicator = "<i style='float:left;' " +
|
||||
"class='icon-mic-disabled'></i>";
|
||||
|
||||
if (!this.isMuted) {
|
||||
muteLinkItem.innerHTML = mutedIndicator +
|
||||
" <div style='width: 90px;margin-left: 20px;' " +
|
||||
"data-i18n='videothumbnail.domute'></div>";
|
||||
muteLinkItem.className = 'mutelink';
|
||||
}
|
||||
else {
|
||||
muteLinkItem.innerHTML = mutedIndicator +
|
||||
" <div style='width: 90px;margin-left: 20px;' " +
|
||||
"data-i18n='videothumbnail.muted'></div>";
|
||||
muteLinkItem.className = 'mutelink disabled';
|
||||
}
|
||||
|
||||
muteLinkItem.onclick = (event) => {
|
||||
if ($(this).attr('disabled')) {
|
||||
event.preventDefault();
|
||||
}
|
||||
var isMute = !!this.isMuted;
|
||||
this.emitter.emit(UIEvents.REMOTE_AUDIO_MUTED, this.id);
|
||||
|
||||
popupmenuElement.setAttribute('style', 'display:none;');
|
||||
|
||||
if (isMute) {
|
||||
this.innerHTML = mutedIndicator +
|
||||
" <div style='width: 90px;margin-left: 20px;' " +
|
||||
"data-i18n='videothumbnail.muted'></div>";
|
||||
this.className = 'mutelink disabled';
|
||||
}
|
||||
else {
|
||||
this.innerHTML = mutedIndicator +
|
||||
" <div style='width: 90px;margin-left: 20px;' " +
|
||||
"data-i18n='videothumbnail.domute'></div>";
|
||||
this.className = 'mutelink';
|
||||
}
|
||||
};
|
||||
|
||||
muteMenuItem.appendChild(muteLinkItem);
|
||||
popupmenuElement.appendChild(muteMenuItem);
|
||||
|
||||
var ejectIndicator = "<i style='float:left;' class='fa fa-eject'></i>";
|
||||
|
||||
var ejectMenuItem = document.createElement('li');
|
||||
var ejectLinkItem = document.createElement('a');
|
||||
var ejectText = "<div style='width: 90px;margin-left: 20px;' " +
|
||||
"data-i18n='videothumbnail.kick'> </div>";
|
||||
ejectLinkItem.innerHTML = ejectIndicator + ' ' + ejectText;
|
||||
ejectLinkItem.onclick = (event) => {
|
||||
this.emitter.emit(UIEvents.USER_KICKED, this.id);
|
||||
popupmenuElement.setAttribute('style', 'display:none;');
|
||||
};
|
||||
|
||||
ejectMenuItem.appendChild(ejectLinkItem);
|
||||
popupmenuElement.appendChild(ejectMenuItem);
|
||||
|
||||
var paddingSpan = document.createElement('span');
|
||||
paddingSpan.className = 'popupmenuPadding';
|
||||
popupmenuElement.appendChild(paddingSpan);
|
||||
APP.translation.translateElement(
|
||||
$("#" + popupmenuElement.id + " > li > a > div"));
|
||||
this._initPopupMenu(this._generatePopupContent());
|
||||
this.hasRemoteVideoMenu = true;
|
||||
};
|
||||
|
||||
} else {
|
||||
@@ -144,13 +201,7 @@ RemoteVideo.prototype.removeRemoteStreamElement = function (stream) {
|
||||
var isVideo = stream.isVideoTrack();
|
||||
|
||||
var elementID = SmallVideo.getStreamElementID(stream);
|
||||
var select = null;
|
||||
if (isVideo) {
|
||||
select = $('#' + elementID);
|
||||
}
|
||||
else
|
||||
select = $('#' + this.videoSpanId + '>audio');
|
||||
|
||||
var select = $('#' + elementID);
|
||||
select.remove();
|
||||
|
||||
console.info((isVideo ? "Video" : "Audio") +
|
||||
@@ -216,6 +267,9 @@ RemoteVideo.prototype.addRemoteStreamElement = function (stream) {
|
||||
let isVideo = stream.isVideoTrack();
|
||||
isVideo ? this.videoStream = stream : this.audioStream = stream;
|
||||
|
||||
if (isVideo)
|
||||
this.setVideoType(stream.videoType);
|
||||
|
||||
// Add click handler.
|
||||
let onClickHandler = (event) => {
|
||||
let source = event.target || event.srcElement;
|
||||
@@ -316,31 +370,6 @@ RemoteVideo.prototype.hideConnectionIndicator = function () {
|
||||
this.connectionIndicator.hide();
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the remote video menu.
|
||||
*
|
||||
* @param id the id indicating the video for which we're adding a menu.
|
||||
* @param isMuted indicates the current mute state
|
||||
*/
|
||||
RemoteVideo.prototype.updateRemoteVideoMenu = function (isMuted) {
|
||||
var muteMenuItem = $(`#remote_popupmenu_${this.id}>li>a.mutelink`);
|
||||
|
||||
var mutedIndicator = "<i class='icon-mic-disabled'></i>";
|
||||
|
||||
if (muteMenuItem.length) {
|
||||
var muteLink = muteMenuItem.get(0);
|
||||
|
||||
if (isMuted) {
|
||||
muteLink.innerHTML = mutedIndicator + ' Muted';
|
||||
muteLink.className = 'mutelink disabled';
|
||||
}
|
||||
else {
|
||||
muteLink.innerHTML = mutedIndicator + ' Mute';
|
||||
muteLink.className = 'mutelink';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the display name for the given video span id.
|
||||
*/
|
||||
@@ -391,7 +420,9 @@ RemoteVideo.prototype.setDisplayName = function(displayName, key) {
|
||||
RemoteVideo.prototype.removeRemoteVideoMenu = function() {
|
||||
var menuSpan = $('#' + this.videoSpanId + '>span.remotevideomenu');
|
||||
if (menuSpan.length) {
|
||||
this.popover.forceHide();
|
||||
menuSpan.remove();
|
||||
this.hasRemoteVideoMenu = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/* jshint -W101 */
|
||||
import Avatar from "../avatar/Avatar";
|
||||
import UIUtil from "../util/UIUtil";
|
||||
import UIEvents from "../../../service/UI/UIEvents";
|
||||
|
||||
const RTCUIHelper = JitsiMeetJS.util.RTCUIHelper;
|
||||
|
||||
@@ -158,13 +159,6 @@ SmallVideo.createStreamElement = function (stream) {
|
||||
|
||||
element.id = SmallVideo.getStreamElementID(stream);
|
||||
|
||||
element.onplay = function () {
|
||||
var type = (isVideo ? 'video' : 'audio');
|
||||
var now = APP.connectionTimes[type + ".render"]
|
||||
= window.performance.now();
|
||||
console.log("(TIME) Render " + type + ":\t",
|
||||
now);
|
||||
};
|
||||
return element;
|
||||
};
|
||||
|
||||
@@ -299,9 +293,6 @@ SmallVideo.prototype.updateIconPositions = function () {
|
||||
|
||||
/**
|
||||
* Creates the element indicating the moderator(owner) of the conference.
|
||||
*
|
||||
* @param parentElement the parent element where the owner indicator will
|
||||
* be added
|
||||
*/
|
||||
SmallVideo.prototype.createModeratorIndicatorElement = function () {
|
||||
// Show moderator indicator
|
||||
@@ -329,6 +320,23 @@ SmallVideo.prototype.createModeratorIndicatorElement = function () {
|
||||
APP.translation.translateElement($('#' + this.videoSpanId + ' .focusindicator'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the element indicating the moderator(owner) of the conference.
|
||||
*/
|
||||
SmallVideo.prototype.removeModeratorIndicatorElement = function () {
|
||||
$('#' + this.videoSpanId + ' .focusindicator').remove();
|
||||
};
|
||||
|
||||
/**
|
||||
* This is an especially interesting function. A naive reader might think that
|
||||
* it returns this SmallVideo's "video" element. But it is much more exciting.
|
||||
* It first finds this video's parent element using jquery, then uses a utility
|
||||
* from lib-jitsi-meet to extract the video element from it (with two more
|
||||
* jquery calls), and finally uses jquery again to encapsulate the video element
|
||||
* in an array. This last step allows (some might prefer "forces") users of
|
||||
* this function to access the video element via the 0th element of the returned
|
||||
* array (after checking its length of course!).
|
||||
*/
|
||||
SmallVideo.prototype.selectVideoElement = function () {
|
||||
return $(RTCUIHelper.findVideoElement($('#' + this.videoSpanId)[0]));
|
||||
};
|
||||
@@ -376,7 +384,7 @@ SmallVideo.prototype.updateView = function () {
|
||||
|
||||
let video = this.selectVideoElement();
|
||||
|
||||
let avatar = $(`#avatar_${this.id}`);
|
||||
let avatar = $('#' + this.videoSpanId + ' .userAvatar');
|
||||
|
||||
var isCurrentlyOnLarge = this.VideoLayout.isCurrentlyOnLarge(this.id);
|
||||
|
||||
@@ -404,7 +412,7 @@ SmallVideo.prototype.updateView = function () {
|
||||
|
||||
SmallVideo.prototype.avatarChanged = function (avatarUrl) {
|
||||
var thumbnail = $('#' + this.videoSpanId);
|
||||
var avatar = $('#avatar_' + this.id);
|
||||
var avatar = $('#' + this.videoSpanId + ' .userAvatar');
|
||||
this.hasAvatar = true;
|
||||
|
||||
// set the avatar in the thumbnail
|
||||
@@ -413,7 +421,6 @@ SmallVideo.prototype.avatarChanged = function (avatarUrl) {
|
||||
} else {
|
||||
if (thumbnail && thumbnail.length > 0) {
|
||||
avatar = document.createElement('img');
|
||||
avatar.id = 'avatar_' + this.id;
|
||||
avatar.className = 'userAvatar';
|
||||
avatar.src = avatarUrl;
|
||||
thumbnail.append(avatar);
|
||||
@@ -487,4 +494,59 @@ SmallVideo.prototype.getIndicatorSpan = function(id) {
|
||||
return indicatorSpan;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a listener for onresize events for this video, which will monitor for
|
||||
* resolution changes, will calculate the delay since the moment the listened
|
||||
* is added, and will fire a RESOLUTION_CHANGED event.
|
||||
*/
|
||||
SmallVideo.prototype.waitForResolutionChange = function() {
|
||||
let self = this;
|
||||
let beforeChange = window.performance.now();
|
||||
let videos = this.selectVideoElement();
|
||||
if (!videos || !videos.length || videos.length <= 0)
|
||||
return;
|
||||
let video = videos[0];
|
||||
let oldWidth = video.videoWidth;
|
||||
let oldHeight = video.videoHeight;
|
||||
video.onresize = (event) => {
|
||||
if (video.videoWidth != oldWidth || video.videoHeight != oldHeight) {
|
||||
// Only run once.
|
||||
video.onresize = null;
|
||||
|
||||
let delay = window.performance.now() - beforeChange;
|
||||
let emitter = self.VideoLayout.getEventEmitter();
|
||||
if (emitter) {
|
||||
emitter.emit(
|
||||
UIEvents.RESOLUTION_CHANGED,
|
||||
self.getId(),
|
||||
oldWidth + "x" + oldHeight,
|
||||
video.videoWidth + "x" + video.videoHeight,
|
||||
delay);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Initalizes any browser specific properties. Currently sets the overflow
|
||||
* property for Qt browsers on Windows to hidden, thus fixing the following
|
||||
* problem:
|
||||
* Some browsers don't have full support of the object-fit property for the
|
||||
* video element and when we set video object-fit to "cover" the video
|
||||
* actually overflows the boundaries of its container, so it's important
|
||||
* to indicate that the "overflow" should be hidden.
|
||||
*
|
||||
* Setting this property for all browsers will result in broken audio levels,
|
||||
* which makes this a temporary solution, before reworking audio levels.
|
||||
*/
|
||||
SmallVideo.prototype.initBrowserSpecificProperties = function() {
|
||||
|
||||
var userAgent = window.navigator.userAgent;
|
||||
if (userAgent.indexOf("QtWebEngine") > -1
|
||||
&& (userAgent.indexOf("Windows") > -1
|
||||
|| userAgent.indexOf("Linux") > -1)) {
|
||||
$('#' + this.videoSpanId).css("overflow", "hidden");
|
||||
}
|
||||
};
|
||||
|
||||
export default SmallVideo;
|
||||
|
||||
@@ -107,7 +107,9 @@ var VideoLayout = {
|
||||
localVideoThumbnail.setVideoType(VIDEO_CONTAINER_TYPE);
|
||||
// if we do not resize the thumbs here, if there is no video device
|
||||
// the local video thumb maybe one pixel
|
||||
this.resizeThumbnails(false, true, false);
|
||||
let {thumbWidth, thumbHeight}
|
||||
= this.resizeThumbnails(false, true, false);
|
||||
AudioLevels.updateAudioLevelCanvas(null, thumbWidth, thumbHeight);
|
||||
|
||||
emitter.addListener(UIEvents.CONTACT_CLICKED, onContactClicked);
|
||||
this.lastNCount = config.channelLastN;
|
||||
@@ -158,16 +160,9 @@ var VideoLayout = {
|
||||
},
|
||||
|
||||
changeLocalVideo (stream) {
|
||||
// Set default display name.
|
||||
localVideoThumbnail.setDisplayName();
|
||||
localVideoThumbnail.createConnectionIndicator();
|
||||
|
||||
let localId = APP.conference.localId;
|
||||
let localId = APP.conference.getMyUserId();
|
||||
this.onVideoTypeChanged(localId, stream.videoType);
|
||||
|
||||
let {thumbWidth, thumbHeight} = this.resizeThumbnails(false, true);
|
||||
AudioLevels.updateAudioLevelCanvas(null, thumbWidth, thumbHeight);
|
||||
|
||||
if (!stream.isMuted()) {
|
||||
localVideoThumbnail.changeVideo(stream);
|
||||
}
|
||||
@@ -186,7 +181,7 @@ var VideoLayout = {
|
||||
*/
|
||||
mucJoined () {
|
||||
if (largeVideo && !largeVideo.id) {
|
||||
this.updateLargeVideo(APP.conference.localId, true);
|
||||
this.updateLargeVideo(APP.conference.getMyUserId(), true);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -290,7 +285,7 @@ var VideoLayout = {
|
||||
// Go with local video
|
||||
console.info("Fallback to local video...");
|
||||
|
||||
let id = APP.conference.localId;
|
||||
let id = APP.conference.getMyUserId();
|
||||
console.info("electLastVisibleVideo: " + id);
|
||||
|
||||
return id;
|
||||
@@ -457,6 +452,8 @@ var VideoLayout = {
|
||||
let isModerator = APP.conference.isModerator;
|
||||
if (isModerator) {
|
||||
localVideoThumbnail.createModeratorIndicatorElement();
|
||||
} else {
|
||||
localVideoThumbnail.removeModeratorIndicatorElement();
|
||||
}
|
||||
|
||||
APP.conference.listMembers().forEach(function (member) {
|
||||
@@ -470,7 +467,7 @@ var VideoLayout = {
|
||||
remoteVideo.createModeratorIndicatorElement();
|
||||
} else if (isModerator) {
|
||||
// We are moderator, but user is not - add menu
|
||||
if ($(`#remote_popupmenu_${id}`).length <= 0) {
|
||||
if(!remoteVideo.hasRemoteVideoMenu) {
|
||||
remoteVideo.addRemoteVideoMenu();
|
||||
}
|
||||
}
|
||||
@@ -775,7 +772,7 @@ var VideoLayout = {
|
||||
updateLocalConnectionStats (percent, object) {
|
||||
let resolutions = object.resolution;
|
||||
|
||||
object.resolution = resolutions[APP.conference.localId];
|
||||
object.resolution = resolutions[APP.conference.getMyUserId()];
|
||||
localVideoThumbnail.updateStatsIndicator(percent, object);
|
||||
|
||||
Object.keys(resolutions).forEach(function (id) {
|
||||
@@ -1010,11 +1007,16 @@ var VideoLayout = {
|
||||
if (id !== currentId && videoType === VIDEO_CONTAINER_TYPE) {
|
||||
eventEmitter.emit(UIEvents.SELECTED_ENDPOINT, id);
|
||||
}
|
||||
if (currentId) {
|
||||
var oldSmallVideo = this.getSmallVideo(currentId);
|
||||
}
|
||||
|
||||
let smallVideo = this.getSmallVideo(id);
|
||||
let oldSmallVideo;
|
||||
if (currentId) {
|
||||
oldSmallVideo = this.getSmallVideo(currentId);
|
||||
}
|
||||
|
||||
smallVideo.waitForResolutionChange();
|
||||
if (oldSmallVideo)
|
||||
oldSmallVideo.waitForResolutionChange();
|
||||
|
||||
largeVideo.updateLargeVideo(
|
||||
id,
|
||||
@@ -1118,7 +1120,9 @@ var VideoLayout = {
|
||||
setLocalFlipX: function (val) {
|
||||
this.localFlipX = val;
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
getEventEmitter: () => {return eventEmitter;}
|
||||
};
|
||||
|
||||
export default VideoLayout;
|
||||
|
||||
@@ -28,39 +28,6 @@ var localConnectionQuality = 100;
|
||||
*/
|
||||
var remoteConnectionQuality = {};
|
||||
|
||||
/**
|
||||
* Converts statistics to format used by VideoLayout
|
||||
* @param stats
|
||||
* @returns {{bitrate: {download: *, upload: *}, packetLoss: {total: *, download: *, upload: *}}}
|
||||
*/
|
||||
function parseMUCStats(stats) {
|
||||
if(!stats || !stats.children || !stats.children.length)
|
||||
return null;
|
||||
var children = stats.children;
|
||||
var extractedStats = {};
|
||||
children.forEach((child) => {
|
||||
if(child.tagName !== "stat" || !child.attributes)
|
||||
return;
|
||||
var attrKeys = Object.keys(child.attributes);
|
||||
if(!attrKeys || !attrKeys.length)
|
||||
return;
|
||||
attrKeys.forEach((attr) => {
|
||||
extractedStats[attr] = child.attributes[attr];
|
||||
});
|
||||
});
|
||||
return {
|
||||
bitrate: {
|
||||
download: extractedStats.bitrate_download,
|
||||
upload: extractedStats.bitrate_upload
|
||||
},
|
||||
packetLoss: {
|
||||
total: extractedStats.packetLoss_total,
|
||||
download: extractedStats.packetLoss_download,
|
||||
upload: extractedStats.packetLoss_upload
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the quality percent based on passed new and old value.
|
||||
* @param newVal the new value
|
||||
@@ -74,12 +41,26 @@ export default {
|
||||
/**
|
||||
* Updates the local statistics
|
||||
* @param data new statistics
|
||||
* @param dontUpdateLocalConnectionQuality {boolean} if true -
|
||||
* localConnectionQuality wont be recalculated.
|
||||
*/
|
||||
updateLocalStats: function (data) {
|
||||
updateLocalStats: function (data, dontUpdateLocalConnectionQuality) {
|
||||
stats = data;
|
||||
var newVal = 100 - stats.packetLoss.total;
|
||||
localConnectionQuality =
|
||||
calculateQuality(newVal, localConnectionQuality);
|
||||
if(!dontUpdateLocalConnectionQuality) {
|
||||
var newVal = 100 - stats.packetLoss.total;
|
||||
localConnectionQuality =
|
||||
calculateQuality(newVal, localConnectionQuality);
|
||||
}
|
||||
eventEmitter.emit(CQEvents.LOCALSTATS_UPDATED, localConnectionQuality,
|
||||
stats);
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates only the localConnectionQuality value
|
||||
* @param values {int} the new value. should be from 0 - 100.
|
||||
*/
|
||||
updateLocalConnectionQuality: function (value) {
|
||||
localConnectionQuality = value;
|
||||
eventEmitter.emit(CQEvents.LOCALSTATS_UPDATED, localConnectionQuality,
|
||||
stats);
|
||||
},
|
||||
@@ -90,11 +71,13 @@ export default {
|
||||
* @param data the statistics
|
||||
*/
|
||||
updateRemoteStats: function (id, data) {
|
||||
data = parseMUCStats(data);
|
||||
if (!data || !data.packetLoss || !data.packetLoss.total) {
|
||||
if (!data || !("packetLoss" in data) || !("total" in data.packetLoss)) {
|
||||
eventEmitter.emit(CQEvents.REMOTESTATS_UPDATED, id, null, null);
|
||||
return;
|
||||
}
|
||||
// Use only the fields we need
|
||||
data = {bitrate: data.bitrate, packetLoss: data.packetLoss};
|
||||
|
||||
remoteStats[id] = data;
|
||||
|
||||
var newVal = 100 - data.packetLoss.total;
|
||||
@@ -115,24 +98,5 @@ export default {
|
||||
|
||||
addListener: function (type, listener) {
|
||||
eventEmitter.on(type, listener);
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts statistics to format for sending through XMPP
|
||||
* @param stats the statistics
|
||||
* @returns [{tagName: "stat", attributes: {{bitrate_donwload: *}},
|
||||
* {tagName: "stat", attributes: {{ bitrate_uplpoad: *}},
|
||||
* {tagName: "stat", attributes: {{ packetLoss_total: *}},
|
||||
* {tagName: "stat", attributes: {{ packetLoss_download: *}},
|
||||
* {tagName: "stat", attributes: {{ packetLoss_upload: *}}]
|
||||
*/
|
||||
convertToMUCStats: function (stats) {
|
||||
return [
|
||||
{tagName: "stat", attributes: {"bitrate_download": stats.bitrate.download}},
|
||||
{tagName: "stat", attributes: {"bitrate_upload": stats.bitrate.upload}},
|
||||
{tagName: "stat", attributes: {"packetLoss_total": stats.packetLoss.total}},
|
||||
{tagName: "stat", attributes: {"packetLoss_download": stats.packetLoss.download}},
|
||||
{tagName: "stat", attributes: {"packetLoss_upload": stats.packetLoss.upload}}
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,91 +1,68 @@
|
||||
/* global APP, $ */
|
||||
//maps keycode to character, id of popover for given function and function
|
||||
var shortcuts = {};
|
||||
function initShortcutHandlers() {
|
||||
shortcuts = {
|
||||
27: {
|
||||
character: "Esc",
|
||||
function: function() {
|
||||
APP.UI.showKeyboardShortcutsPanel(false);
|
||||
}
|
||||
},
|
||||
67: {
|
||||
character: "C",
|
||||
id: "toggleChatPopover",
|
||||
function: function() {
|
||||
APP.UI.toggleChat();
|
||||
}
|
||||
},
|
||||
68: {
|
||||
character: "D",
|
||||
id: "toggleDesktopSharingPopover",
|
||||
function: function () {
|
||||
APP.conference.toggleScreenSharing();
|
||||
}
|
||||
},
|
||||
70: {
|
||||
character: "F",
|
||||
id: "filmstripPopover",
|
||||
function: function() {
|
||||
APP.UI.toggleFilmStrip();
|
||||
}
|
||||
},
|
||||
77: {
|
||||
character: "M",
|
||||
id: "mutePopover",
|
||||
function: function() {
|
||||
APP.conference.toggleAudioMuted();
|
||||
}
|
||||
},
|
||||
82: {
|
||||
character: "R",
|
||||
function: function() {
|
||||
APP.conference.maybeToggleRaisedHand();
|
||||
}
|
||||
/* global APP, $, JitsiMeetJS */
|
||||
|
||||
},
|
||||
84: {
|
||||
character: "T",
|
||||
function: function() {
|
||||
APP.conference.muteAudio(true);
|
||||
}
|
||||
},
|
||||
86: {
|
||||
character: "V",
|
||||
id: "toggleVideoPopover",
|
||||
function: function() {
|
||||
APP.conference.toggleVideoMuted();
|
||||
}
|
||||
},
|
||||
191: {
|
||||
character: "/",
|
||||
function: function(e) {
|
||||
// Only trigger on "?", not on "/".
|
||||
if (e.shiftKey) {
|
||||
APP.UI.toggleKeyboardShortcutsPanel();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
/**
|
||||
* Initialise global shortcuts.
|
||||
* Global shortcuts are shortcuts for features that don't have a button or
|
||||
* link associated with the action. In other words they represent actions
|
||||
* triggered _only_ with a shortcut.
|
||||
*/
|
||||
function initGlobalShortcuts() {
|
||||
|
||||
KeyboardShortcut.registerShortcut("ESCAPE", null, function() {
|
||||
APP.UI.showKeyboardShortcutsPanel(false);
|
||||
});
|
||||
|
||||
KeyboardShortcut.registerShortcut("?", null, function() {
|
||||
JitsiMeetJS.analytics.sendEvent("shortcut.shortcut.help");
|
||||
APP.UI.toggleKeyboardShortcutsPanel();
|
||||
}, "keyboardShortcuts.toggleShortcuts");
|
||||
|
||||
KeyboardShortcut.registerShortcut("R", null, function() {
|
||||
JitsiMeetJS.analytics.sendEvent("shortcut.raisedhand.toggled");
|
||||
APP.conference.maybeToggleRaisedHand();
|
||||
}, "keyboardShortcuts.raiseHand");
|
||||
|
||||
KeyboardShortcut.registerShortcut("T", null, function() {
|
||||
JitsiMeetJS.analytics.sendEvent("shortcut.talk.clicked");
|
||||
APP.conference.muteAudio(true);
|
||||
}, "keyboardShortcuts.pushToTalk");
|
||||
|
||||
/**
|
||||
* FIXME: Currently focus keys are directly implemented below in onkeyup.
|
||||
* They should be moved to the SmallVideo instead.
|
||||
*/
|
||||
KeyboardShortcut._addShortcutToHelp("0", "keyboardShortcuts.focusLocal");
|
||||
KeyboardShortcut._addShortcutToHelp("1-9", "keyboardShortcuts.focusRemote");
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of shortcuts. When a shortcut is registered it enters the mapping.
|
||||
* @type {{}}
|
||||
*/
|
||||
let _shortcuts = {};
|
||||
|
||||
/**
|
||||
* Maps keycode to character, id of popover for given function and function.
|
||||
*/
|
||||
var KeyboardShortcut = {
|
||||
init: function () {
|
||||
initShortcutHandlers();
|
||||
initGlobalShortcuts();
|
||||
|
||||
var self = this;
|
||||
window.onkeyup = function(e) {
|
||||
var keycode = e.which;
|
||||
var key = self._getKeyboardKey(e).toUpperCase();
|
||||
var num = parseInt(key, 10);
|
||||
if(!($(":focus").is("input[type=text]") ||
|
||||
$(":focus").is("input[type=password]") ||
|
||||
$(":focus").is("textarea"))) {
|
||||
if (typeof shortcuts[keycode] === "object") {
|
||||
shortcuts[keycode].function(e);
|
||||
if (_shortcuts.hasOwnProperty(key)) {
|
||||
_shortcuts[key].function(e);
|
||||
}
|
||||
else if (keycode >= "0".charCodeAt(0) &&
|
||||
keycode <= "9".charCodeAt(0)) {
|
||||
APP.UI.clickOnVideo(keycode - "0".charCodeAt(0) + 1);
|
||||
else if (!isNaN(num) && num >= 0 && num <= 9) {
|
||||
APP.UI.clickOnVideo(num + 1);
|
||||
}
|
||||
//esc while the smileys are visible hides them
|
||||
} else if (keycode === 27 &&
|
||||
//esc while the smileys are visible hides them
|
||||
} else if (key === "ESCAPE" &&
|
||||
$('#smileysContainer').is(':visible')) {
|
||||
APP.UI.toggleSmileys();
|
||||
}
|
||||
@@ -95,35 +72,156 @@ var KeyboardShortcut = {
|
||||
if(!($(":focus").is("input[type=text]") ||
|
||||
$(":focus").is("input[type=password]") ||
|
||||
$(":focus").is("textarea"))) {
|
||||
if(e.which === "T".charCodeAt(0)) {
|
||||
var key = self._getKeyboardKey(e).toUpperCase();
|
||||
if(key === "T") {
|
||||
if(APP.conference.isLocalAudioMuted())
|
||||
APP.conference.muteAudio(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
var self = this;
|
||||
$('body').popover({ selector: '[data-toggle=popover]',
|
||||
trigger: 'click hover',
|
||||
content: function() {
|
||||
return this.getAttribute("content") +
|
||||
self.getShortcut(this.getAttribute("shortcut"));
|
||||
return this.getAttribute("content")
|
||||
+ self._getShortcutTooltip(this.getAttribute("shortcut"));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers a new shortcut.
|
||||
*
|
||||
* @param id indicates the popover associated with the shortcut
|
||||
* @returns {string} the keyboard shortcut used for the id given
|
||||
* @param shortcutChar the shortcut character triggering the action
|
||||
* @param shortcutAttr the "shortcut" html element attribute mappring an
|
||||
* element to this shortcut and used to show the shortcut character on the
|
||||
* element tooltip
|
||||
* @param exec the function to be executed when the shortcut is pressed
|
||||
* @param helpDescription the description of the shortcut that would appear
|
||||
* in the help menu
|
||||
*/
|
||||
getShortcut: function (id) {
|
||||
for (var keycode in shortcuts) {
|
||||
if (shortcuts.hasOwnProperty(keycode)) {
|
||||
if (shortcuts[keycode].id === id) {
|
||||
return " (" + shortcuts[keycode].character + ")";
|
||||
registerShortcut: function( shortcutChar,
|
||||
shortcutAttr,
|
||||
exec,
|
||||
helpDescription) {
|
||||
_shortcuts[shortcutChar] = {
|
||||
character: shortcutChar,
|
||||
shortcutAttr: shortcutAttr,
|
||||
function: exec
|
||||
};
|
||||
|
||||
if (helpDescription)
|
||||
this._addShortcutToHelp(shortcutChar, helpDescription);
|
||||
},
|
||||
|
||||
/**
|
||||
* Unregisters a shortcut.
|
||||
*
|
||||
* @param shortcutChar unregisters the given shortcut, which means it will
|
||||
* no longer be usable
|
||||
*/
|
||||
unregisterShortcut: function(shortcutChar) {
|
||||
_shortcuts.remove(shortcutChar);
|
||||
|
||||
this._removeShortcutFromHelp(shortcutChar);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the tooltip string for the given shortcut attribute.
|
||||
*
|
||||
* @param shortcutAttr indicates the popover associated with the shortcut
|
||||
* @returns {string} the tooltip string to add to the given shortcut popover
|
||||
* or an empty string if the shortcutAttr is null, an empty string or not
|
||||
* found in the shortcut mapping
|
||||
*/
|
||||
_getShortcutTooltip: function (shortcutAttr) {
|
||||
if (typeof shortcutAttr === "string" && shortcutAttr.length > 0) {
|
||||
for (var key in _shortcuts) {
|
||||
if (_shortcuts.hasOwnProperty(key)
|
||||
&& _shortcuts[key].shortcutAttr
|
||||
&& _shortcuts[key].shortcutAttr === shortcutAttr) {
|
||||
return " (" + _shortcuts[key].character + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
/**
|
||||
* @param e a KeyboardEvent
|
||||
* @returns {string} e.key or something close if not supported
|
||||
*/
|
||||
_getKeyboardKey: function (e) {
|
||||
if (typeof e.key === "string") {
|
||||
return e.key;
|
||||
}
|
||||
if (e.type === "keypress" && (
|
||||
(e.which >= 32 && e.which <= 126) ||
|
||||
(e.which >= 160 && e.which <= 255) )) {
|
||||
return String.fromCharCode(e.which);
|
||||
}
|
||||
// try to fallback (0-9A-Za-z and QWERTY keyboard)
|
||||
switch (e.which) {
|
||||
case 27:
|
||||
return "Escape";
|
||||
case 191:
|
||||
return e.shiftKey ? "?" : "/";
|
||||
}
|
||||
if (e.shiftKey || e.type === "keypress") {
|
||||
return String.fromCharCode(e.which);
|
||||
} else {
|
||||
return String.fromCharCode(e.which).toLowerCase();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds the given shortcut to the help dialog.
|
||||
*
|
||||
* @param shortcutChar the shortcut character
|
||||
* @param shortcutDescriptionKey the description of the shortcut
|
||||
* @private
|
||||
*/
|
||||
_addShortcutToHelp: function (shortcutChar, shortcutDescriptionKey) {
|
||||
|
||||
var listElement = document.createElement("li");
|
||||
listElement.id = shortcutChar;
|
||||
|
||||
var spanElement = document.createElement("span");
|
||||
spanElement.className = "item-action";
|
||||
|
||||
var kbdElement = document.createElement("kbd");
|
||||
kbdElement.className = "regular-key";
|
||||
kbdElement.innerHTML = shortcutChar;
|
||||
spanElement.appendChild(kbdElement);
|
||||
|
||||
var descriptionElement = document.createElement("span");
|
||||
descriptionElement.className = "item-description";
|
||||
descriptionElement.setAttribute("data-i18n", shortcutDescriptionKey);
|
||||
descriptionElement.innerHTML
|
||||
= APP.translation.translateString(shortcutDescriptionKey);
|
||||
|
||||
listElement.appendChild(spanElement);
|
||||
listElement.appendChild(descriptionElement);
|
||||
|
||||
var parentListElement
|
||||
= document.getElementById("keyboard-shortcuts-list");
|
||||
|
||||
if (parentListElement)
|
||||
parentListElement.appendChild(listElement);
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the list element corresponding to the given shortcut from the
|
||||
* help dialog
|
||||
* @private
|
||||
*/
|
||||
_removeShortcutFromHelp: function (shortcutChar) {
|
||||
var parentListElement
|
||||
= document.getElementById("keyboard-shortcuts-list");
|
||||
|
||||
var shortcutElement = document.getElementById(shortcutChar);
|
||||
|
||||
if (shortcutElement)
|
||||
parentListElement.removeChild(shortcutElement);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import UIUtil from '../UI/util/UIUtil';
|
||||
|
||||
let email = '';
|
||||
let avatarId = '';
|
||||
let displayName = '';
|
||||
let language = null;
|
||||
let cameraDeviceId = '';
|
||||
@@ -35,7 +36,13 @@ if (supportsLocalStorage()) {
|
||||
}
|
||||
|
||||
email = UIUtil.unescapeHtml(window.localStorage.email || '');
|
||||
avatarUrl = UIUtil.unescapeHtml(window.localStorage.avatarUrl || '');
|
||||
avatarId = UIUtil.unescapeHtml(window.localStorage.avatarId || '');
|
||||
if (!avatarId) {
|
||||
// if there is no avatar id, we generate a unique one and use it forever
|
||||
avatarId = generateUniqueId();
|
||||
window.localStorage.avatarId = avatarId;
|
||||
}
|
||||
|
||||
localFlipX = JSON.parse(window.localStorage.localFlipX || true);
|
||||
displayName = UIUtil.unescapeHtml(window.localStorage.displayname || '');
|
||||
language = window.localStorage.language;
|
||||
@@ -69,10 +76,13 @@ export default {
|
||||
* Sets the local user display name and saves it to local storage
|
||||
*
|
||||
* @param {string} newDisplayName unescaped display name for the local user
|
||||
* @param {boolean} disableLocalStore disables local store the display name
|
||||
*/
|
||||
setDisplayName (newDisplayName) {
|
||||
setDisplayName (newDisplayName, disableLocalStore) {
|
||||
displayName = newDisplayName;
|
||||
window.localStorage.displayname = UIUtil.escapeHtml(displayName);
|
||||
|
||||
if (!disableLocalStore)
|
||||
window.localStorage.displayname = UIUtil.escapeHtml(displayName);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -86,10 +96,13 @@ export default {
|
||||
/**
|
||||
* Sets new email for local user and saves it to the local storage.
|
||||
* @param {string} newEmail new email for the local user
|
||||
* @param {boolean} disableLocalStore disables local store the email
|
||||
*/
|
||||
setEmail: function (newEmail) {
|
||||
setEmail: function (newEmail, disableLocalStore) {
|
||||
email = newEmail;
|
||||
window.localStorage.email = UIUtil.escapeHtml(newEmail);
|
||||
|
||||
if (!disableLocalStore)
|
||||
window.localStorage.email = UIUtil.escapeHtml(newEmail);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -100,13 +113,20 @@ export default {
|
||||
return email;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns avatar id of the local user.
|
||||
* @returns {string} avatar id
|
||||
*/
|
||||
getAvatarId: function () {
|
||||
return avatarId;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets new avatarUrl for local user and saves it to the local storage.
|
||||
* @param {string} newAvatarUrl new avatarUrl for the local user
|
||||
*/
|
||||
setAvatarUrl: function (newAvatarUrl) {
|
||||
avatarUrl = newAvatarUrl;
|
||||
window.localStorage.avatarUrl = UIUtil.escapeHtml(newAvatarUrl);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -117,7 +137,6 @@ export default {
|
||||
return avatarUrl;
|
||||
},
|
||||
|
||||
|
||||
getLanguage () {
|
||||
return language;
|
||||
},
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/* global config, JitsiMeetJS */
|
||||
|
||||
// Load the integration of a third-party analytics API such as Google Analytics.
|
||||
// Since we cannot guarantee the quality of the third-party service (e.g. their
|
||||
// server may take noticeably long time to respond), it is in our best interest
|
||||
// (in the sense that the intergration of the analytics API is important to us
|
||||
// but not enough to allow it to prevent people from joining a conference) to
|
||||
// download the API asynchronously. Additionally, Google Analytics will download
|
||||
// its implementation asynchronously anyway so it makes sense to append the
|
||||
// loading on our side rather than prepend it.
|
||||
if (config.disableThirdPartyRequests !== true) {
|
||||
JitsiMeetJS.util.ScriptUtil.loadScript(
|
||||
'analytics.js?v=1',
|
||||
/* async */ true,
|
||||
/* prepend */ false);
|
||||
}
|
||||
|
||||
class NoopAnalytics {
|
||||
sendEvent () {}
|
||||
}
|
||||
|
||||
// XXX Since we asynchronously load the integration of the analytics API and the
|
||||
// analytics API may asynchronously load its implementation (e.g. Google
|
||||
// Analytics), we cannot make the decision with respect to which analytics
|
||||
// implementation we will use here and we have to postpone it i.e. we will make
|
||||
// a lazy decision.
|
||||
|
||||
class AnalyticsAdapter {
|
||||
constructor () {
|
||||
}
|
||||
|
||||
sendEvent (...args) {
|
||||
var a = this.analytics;
|
||||
|
||||
if (a === null || typeof a === 'undefined') {
|
||||
var AnalyticsImpl = window.Analytics || NoopAnalytics;
|
||||
|
||||
this.analytics = a = new AnalyticsImpl();
|
||||
}
|
||||
try {
|
||||
a.sendEvent(...args);
|
||||
} catch (ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
export default new AnalyticsAdapter();
|
||||
@@ -19,3 +19,15 @@ export function createDeferred () {
|
||||
export function reload () {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the error and reports it to the global error handler.
|
||||
* @param e {Error} the error
|
||||
* @param msg {string} [optional] the message printed in addition to the error
|
||||
*/
|
||||
export function reportError (e, msg = "") {
|
||||
console.error(msg, e);
|
||||
if(window.onerror)
|
||||
window.onerror(msg, null, null,
|
||||
null, e);
|
||||
}
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
"i18next-client": "1.7.7",
|
||||
"jquery": "~2.1.1",
|
||||
"jQuery-Impromptu": "git+https://github.com/trentrichardson/jQuery-Impromptu.git#v6.0.0",
|
||||
"lib-jitsi-meet": "jitsi/lib-jitsi-meet",
|
||||
"lib-jitsi-meet": "git+https://github.com/jitsi/lib-jitsi-meet.git",
|
||||
"jquery-contextmenu": "*",
|
||||
"jquery-ui": "^1.10.5",
|
||||
"jquery-ui": "1.10.5",
|
||||
"jssha": "1.5.0",
|
||||
"retry": "0.6.1",
|
||||
"strophe": "^1.2.2",
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
-- Token authentication
|
||||
-- Copyright (C) 2015 Atlassian
|
||||
|
||||
local basexx = require "basexx";
|
||||
local have_async, async = pcall(require, "util.async");
|
||||
local formdecode = require "util.http".formdecode;
|
||||
local generate_uuid = require "util.uuid".generate;
|
||||
local http = require "net.http";
|
||||
local json = require "cjson";
|
||||
local new_sasl = require "util.sasl".new;
|
||||
local sasl = require "util.sasl";
|
||||
local formdecode = require "util.http".formdecode;
|
||||
local sha256 = require "util.hashes".sha256;
|
||||
local timer = require "util.timer";
|
||||
local token_util = module:require "token/util";
|
||||
|
||||
-- define auth provider
|
||||
@@ -14,9 +20,14 @@ local host = module.host;
|
||||
|
||||
local appId = module:get_option_string("app_id");
|
||||
local appSecret = module:get_option_string("app_secret");
|
||||
local asapKeyServer = module:get_option_string("asap_key_server");
|
||||
local allowEmptyToken = module:get_option_boolean("allow_empty_token");
|
||||
local disableRoomNameConstraints = module:get_option_boolean("disable_room_name_constraints");
|
||||
|
||||
-- TODO: Figure out a less arbitrary default cache size.
|
||||
local cacheSize = module:get_option_number("jwt_pubkey_cache_size", 128);
|
||||
local cache = require"util.cache".new(cacheSize);
|
||||
|
||||
if allowEmptyToken == true then
|
||||
module:log("warn", "WARNING - empty tokens allowed");
|
||||
end
|
||||
@@ -26,8 +37,13 @@ if appId == nil then
|
||||
return;
|
||||
end
|
||||
|
||||
if appSecret == nil then
|
||||
module:log("error", "'app_secret' must not be empty");
|
||||
if appSecret == nil and asapKeyServer == nil then
|
||||
module:log("error", "'app_secret' or 'asap_key_server' must be specified");
|
||||
return;
|
||||
end
|
||||
|
||||
if asapKeyServer and not have_async then
|
||||
module:log("error", "requires a version of Prosody with util.async");
|
||||
return;
|
||||
end
|
||||
|
||||
@@ -38,7 +54,7 @@ module:hook("bosh-session", function(event)
|
||||
if query ~= nil then
|
||||
session.auth_token = query and formdecode(query).token or nil;
|
||||
end
|
||||
end)
|
||||
end);
|
||||
|
||||
function provider.test_password(username, password)
|
||||
return nil, "Password based auth not supported";
|
||||
@@ -64,6 +80,60 @@ function provider.delete_user(username)
|
||||
return nil;
|
||||
end
|
||||
|
||||
local http_timeout = 30;
|
||||
local http_headers = {
|
||||
["User-Agent"] = "Prosody ("..prosody.version.."; "..prosody.platform..")"
|
||||
};
|
||||
|
||||
function get_public_key(keyId)
|
||||
local content = cache:get(keyId);
|
||||
if content == nil then
|
||||
-- If the key is not found in the cache.
|
||||
module:log("debug", "Cache miss for key: "..keyId);
|
||||
local code;
|
||||
local wait, done = async.waiter();
|
||||
local function cb(content_, code_, response_, request_)
|
||||
content, code = content_, code_;
|
||||
if code == 200 or code == 204 then
|
||||
cache:set(keyId, content);
|
||||
end
|
||||
done();
|
||||
end
|
||||
module:log("debug", "Fetching public key from: "..asapKeyServer..keyId);
|
||||
|
||||
-- We hash the key ID to work around some legacy behavior and make
|
||||
-- deployment easier. It also helps prevent directory
|
||||
-- traversal attacks (although path cleaning could have done this too).
|
||||
local request = http.request(asapKeyServer..sha256(keyId)..'.pem', {
|
||||
headers = http_headers or {},
|
||||
method = "GET"
|
||||
}, cb);
|
||||
|
||||
-- TODO: Is the done() call racey? Can we cancel this if the request
|
||||
-- succeedes?
|
||||
local function cancel()
|
||||
-- TODO: This check is racey. Not likely to be a problem, but we should
|
||||
-- still stick a mutex on content / code at some point.
|
||||
if code == nil then
|
||||
http.destroy_request(request);
|
||||
done();
|
||||
end
|
||||
end
|
||||
timer.add_task(http_timeout, cancel);
|
||||
wait();
|
||||
|
||||
if code == 200 or code == 204 then
|
||||
return content;
|
||||
end
|
||||
else
|
||||
-- If the key is in the cache, use it.
|
||||
module:log("debug", "Cache hit for key: "..keyId);
|
||||
return content;
|
||||
end
|
||||
|
||||
return nil;
|
||||
end
|
||||
|
||||
function provider.get_sasl_handler(session)
|
||||
-- JWT token extracted from BOSH URL
|
||||
local token = session.auth_token;
|
||||
@@ -71,31 +141,41 @@ function provider.get_sasl_handler(session)
|
||||
local function get_username_from_token(self, message)
|
||||
|
||||
if token == nil then
|
||||
if allowEmptyToken == true then
|
||||
if allowEmptyToken then
|
||||
return true;
|
||||
else
|
||||
return false, "not-allowed", "token required";
|
||||
end
|
||||
end
|
||||
|
||||
-- here we check if 'room' claim exists
|
||||
local room, roomErr = token_util.get_room_name(token, appSecret);
|
||||
if room == nil and disableRoomNameConstraints ~= true then
|
||||
if roomErr == nil then
|
||||
roomErr = "'room' claim is missing";
|
||||
end
|
||||
return false, "not-allowed", roomErr;
|
||||
local pubKey;
|
||||
if asapKeyServer and session.auth_token ~= nil then
|
||||
local dotFirst = session.auth_token:find("%.");
|
||||
if not dotFirst then return nil, "Invalid token" end
|
||||
local header = json.decode(basexx.from_url64(session.auth_token:sub(1,dotFirst-1)));
|
||||
local kid = header["kid"];
|
||||
if kid == nil then
|
||||
return false, "not-allowed", "'kid' claim is missing";
|
||||
end
|
||||
pubKey = get_public_key(kid);
|
||||
if pubKey == nil then
|
||||
return false, "not-allowed", "could not obtain public key";
|
||||
end
|
||||
end
|
||||
|
||||
-- now verify the whole token
|
||||
local result, msg
|
||||
= token_util.verify_token(token, appId, appSecret, room, disableRoomNameConstraints);
|
||||
if result == true then
|
||||
-- Binds room name to the session which is later checked on MUC join
|
||||
session.jitsi_meet_room = room;
|
||||
return true
|
||||
local claims, msg;
|
||||
if asapKeyServer then
|
||||
claims, msg = token_util.verify_token(token, appId, pubKey, disableRoomNameConstraints);
|
||||
else
|
||||
return false, "not-allowed", msg
|
||||
claims, msg = token_util.verify_token(token, appId, appSecret, disableRoomNameConstraints);
|
||||
end
|
||||
if claims ~= nil then
|
||||
-- Binds room name to the session which is later checked on MUC join
|
||||
session.jitsi_meet_room = claims["room"];
|
||||
return true;
|
||||
else
|
||||
return false, "not-allowed", msg;
|
||||
end
|
||||
end
|
||||
|
||||
@@ -114,10 +194,10 @@ local function anonymous(self, message)
|
||||
self.username = username;
|
||||
|
||||
if result == true then
|
||||
return "success"
|
||||
return "success";
|
||||
else
|
||||
|
||||
return "failure", err, msg
|
||||
return "failure", err, msg;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
-- Token authentication
|
||||
-- Copyright (C) 2015 Atlassian
|
||||
|
||||
local jwt = require "jwt";
|
||||
local jwt = require "luajwtjitsi";
|
||||
|
||||
local _M = {};
|
||||
|
||||
local function _get_room_name(token, appSecret)
|
||||
local claims, err = jwt.decode(token, appSecret);
|
||||
if claims ~= nil then
|
||||
return claims["room"];
|
||||
else
|
||||
return nil, err;
|
||||
end
|
||||
end
|
||||
|
||||
local function _verify_token(token, appId, appSecret, roomName, disableRoomNameConstraints)
|
||||
local function _verify_token(token, appId, appSecret, disableRoomNameConstraints)
|
||||
|
||||
local claims, err = jwt.decode(token, appSecret, true);
|
||||
if claims == nil then
|
||||
return nil, err;
|
||||
end
|
||||
|
||||
local alg = claims["alg"];
|
||||
if alg ~= nil and (alg == "none" or alg == "") then
|
||||
return nil, "'alg' claim must not be empty";
|
||||
end
|
||||
|
||||
local issClaim = claims["iss"];
|
||||
if issClaim == nil then
|
||||
return nil, "'iss' claim is missing";
|
||||
@@ -33,19 +29,12 @@ local function _verify_token(token, appId, appSecret, roomName, disableRoomNameC
|
||||
if roomClaim == nil and disableRoomNameConstraints ~= true then
|
||||
return nil, "'room' claim is missing";
|
||||
end
|
||||
if roomName ~= nil and roomName ~= roomClaim and disableRoomNameConstraints ~= true then
|
||||
return nil, "Invalid room name('room' claim)";
|
||||
end
|
||||
|
||||
return true;
|
||||
return claims;
|
||||
end
|
||||
|
||||
function _M.verify_token(token, appId, appSecret, roomName, disableRoomNameConstraints)
|
||||
return _verify_token(token, appId, appSecret, roomName, disableRoomNameConstraints);
|
||||
end
|
||||
|
||||
function _M.get_room_name(token, appSecret)
|
||||
return _get_room_name(token, appSecret);
|
||||
function _M.verify_token(token, appId, appSecret, disableRoomNameConstraints)
|
||||
return _verify_token(token, appId, appSecret, disableRoomNameConstraints);
|
||||
end
|
||||
|
||||
return _M;
|
||||
|
||||
@@ -14,10 +14,6 @@ export default {
|
||||
* Notifies that local user changed email.
|
||||
*/
|
||||
EMAIL_CHANGED: "UI.email_changed",
|
||||
/**
|
||||
* Notifies that local user changed avatar url.
|
||||
*/
|
||||
AVATAR_URL_CHANGED: "UI.avatar_url_changed",
|
||||
/**
|
||||
* Notifies that "start muted" settings changed.
|
||||
*/
|
||||
@@ -80,5 +76,18 @@ export default {
|
||||
/**
|
||||
* Notifies that flipX property of the local video is changed.
|
||||
*/
|
||||
LOCAL_FLIPX_CHANGED: "UI.local_flipx_changed"
|
||||
LOCAL_FLIPX_CHANGED: "UI.local_flipx_changed",
|
||||
// An event which indicates that the resolution of a remote video has
|
||||
// changed.
|
||||
RESOLUTION_CHANGED: "UI.resolution_changed",
|
||||
/**
|
||||
* Notifies that the button "Go to webstore" is pressed on the dialog for
|
||||
* external extension installation.
|
||||
*/
|
||||
OPEN_EXTENSION_STORE: "UI.open_extension_store",
|
||||
/**
|
||||
* Notifies that the button "Cancel" is pressed on the dialog for
|
||||
* external extension installation.
|
||||
*/
|
||||
EXTERNAL_INSTALLATION_CANCELED: "UI.external_installation_canceled"
|
||||
};
|
||||
|
||||
@@ -12,5 +12,13 @@ module.exports = {
|
||||
BG: "bg",
|
||||
DE: "de",
|
||||
TR: "tr",
|
||||
FR: "fr"
|
||||
};
|
||||
FR: "fr",
|
||||
ES: "es",
|
||||
HY: "hy",
|
||||
IT: "it",
|
||||
OC: "oc",
|
||||
PTBR: "ptBR",
|
||||
SK: "sk",
|
||||
SL: "sl",
|
||||
SV: "sv"
|
||||
};
|
||||
|
||||
10
title.html
10
title.html
@@ -1 +1,9 @@
|
||||
<title>Jitsi Meet</title>
|
||||
<title>Jitsi Meet</title>
|
||||
<meta property="og:title" content="Jitsi Meet"/>
|
||||
<meta property="og:image" content="/images/jitsilogo.png?v=1"/>
|
||||
<meta property="og:description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
|
||||
<meta description="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
|
||||
<meta itemprop="name" content="Jitsi Meet"/>
|
||||
<meta itemprop="description" content="Join a WebRTC video conference powered by the Jitsi Videobridge"/>
|
||||
<meta itemprop="image" content="/images/jitsilogo.png?v=1"/>
|
||||
<link rel="icon" type="image/png" href="/images/favicon.ico?v=1"/>
|
||||
Reference in New Issue
Block a user