Compare commits

...

184 Commits

Author SHA1 Message Date
tmoldovan8x8
1224597ede feat(e2ee): auto turns on e2ee when one participant enabled it 2021-04-01 12:34:01 +03:00
Avram Tudor
58b7663a97 Merge pull request #8866 from jitsi/tavram/sip-invite
feat(sipcall) implement sip invite
2021-04-01 11:39:31 +03:00
Christoph Settgast
cf8ab5e13b fix(lang) Differentiate prejoin and lobby better in German translation
Signed-off-by: Christoph Settgast <csett86@web.de>
2021-03-31 15:46:05 -05:00
Tudor-Ovidiu Avram
f99c919416 code review changes 2021-03-31 15:51:53 +03:00
Tudor-Ovidiu Avram
ae21a09bd6 feat(sipcall) implement sip invite 2021-03-31 09:53:55 +03:00
Tudor D. Pop
39011d8fd3 feat(virtual-background) persist settings 2021-03-30 23:27:44 +02:00
Johnny998
77f1a24344 Update main-sk.json
Translated a few missing strings.
2021-03-30 08:41:32 -05:00
tudordan7
3453e49182 fix(virtual-background): Hide scrollbar on loading action. 2021-03-30 13:43:57 +02:00
tmoldovan8x8
b1d7debfb9 feat(e2ee): adds sounds for e2ee enabling/disabling 2021-03-30 12:59:32 +03:00
Дамян Минков
b826fc1d5a fix: Correct some missing comas in config.js. 2021-03-30 08:51:43 +02:00
Jaya Allamsetty
c5626e99e9 chore(deps) lib-jitsi-meet@latest
* feat(stats): Get audio levels for the top 5 speakers only.

1249681a0e...43c589f409
2021-03-29 17:21:46 -04:00
Christoph Wiechert
ae28fcc12f Fix: used deprecated onmousewheel event
https://developer.mozilla.org/en-US/docs/Web/API/Element/mousewheel_event
2021-03-29 10:53:13 -05:00
chipechop
987760abbd Update main-it.json (#8795)
* Update main-it.json

Added roughly 20 missinig lines

* Update main-it.json

Fixed two typos, left behind...
2021-03-29 10:53:02 -05:00
KyungheeKo
a3b364f8d7 lang: Update korean translation (#8879)
* Update main-ko.json

update korean translation

* Update main-ko.json

fix comma error

* Update languages-ko.json

add korean translation
2021-03-29 10:52:50 -05:00
JohnProv
2ea317d721 Update main-nl.json (#8891)
* Update main-nl.json

Add missing keys for virtualBackground

* Update main-nl.json
2021-03-29 10:52:22 -05:00
Vlad Piersec
eb41a306a6 fix(lobby): Knocking participants list for small widths 2021-03-29 09:47:11 -05:00
Vlad Piersec
3426290bf2 fix(captions): Lift captions upper when invite box is shown & fix icon 2021-03-29 09:09:21 -05:00
Tudor D. Pop
dfd33521bf fix(virtual-background): Fixes upload virtual background on Firefox
Fixes: #8892
2021-03-29 14:28:22 +02:00
Hristo Terezov
be3bc75403 chore(deps) lib-jitsi-meet@latest
* fix(caps): features update event is not emitted.

0e180efdfa...1249681a0e
2021-03-26 17:43:54 -05:00
Jaya Allamsetty
4621fad832 fix(large-video): Always pin screenshare to large-video if it exists.
Set higher preference for screenshare over dominant speaker when trying to elect a participant for large-video. This prevents the dominant speaker from taking over the stage when a user toggles tile view on and off while a screenshare is in progress.
2021-03-26 09:14:03 -04:00
tmoldovan8x8
e4b34e1c89 feat(rn): makes InputDialog textInput autoFocus 2021-03-26 10:51:47 +02:00
damencho
0067f6b077 fix: Fixes lobby when allowners is enabled. 2021-03-25 15:20:49 -06:00
JohnProv
989044b3a9 fix(lang) update Dutch translation 2021-03-25 17:43:52 +01:00
Mihai-Andrei Uscat
a78ca5fcad feat(external_api): Add command for toggling localFlipX 2021-03-25 14:57:41 +02:00
Mihai-Andrei Uscat
1ad40de487 feat(external_api): Add command for toggling camera on mobile web 2021-03-25 13:48:49 +02:00
ggalperi
2c9078985f fix(lang) fix typo in Russian translation
Fixed typo
2021-03-24 15:59:45 -06:00
Tudor D. Pop
77ee4b13e1 feat(virtual-backgrounds) add ability to upload custom images 2021-03-24 17:32:45 +01:00
Jaya Allamsetty
a3a2ce3875 feat(rn,polyfill): Add a polyfill for Promise.allSettled.
Promise.allSettled is supported from RN 0.63 onwards and is not supported on the current version, use a polyfill for that shims Promise.allSettled if its unavailable or noncompliant.

Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>
2021-03-24 11:59:52 -04:00
Saúl Ibarra Corretgé
e0c77dcd95 feat(tile-view) allow to toggle tile view while alone 2021-03-24 16:43:50 +01:00
Calinteodor
e035d33fa9 feat(authentication) refactor auth dialogs to use React 2021-03-24 15:09:40 +01:00
Kylian Kropf
11202595bd fix(lang) update Dutch translation 2021-03-24 11:16:32 +01:00
Jaya Allamsetty
415670e24b chore(deps) lib-jitsi-meet@latest
* fix(TPC): get ssrc info per ssrc and not per mline.
* feat: Consider absence of A/V muted from presence as muted.
* Feature: Moderator can revoke moderator role to others and himself (#1532)

4191198233...0e180efdfa
2021-03-23 18:11:23 -04:00
Izak Glasenčnik
05f3b4390d feat(iFrame): Emit event when recording status changes, including errors (#7973)
* feat(iFrame): Emit event when recording status changes, including errors

* Fix APP access on mobile
2021-03-23 11:35:46 -05:00
Saúl Ibarra Corretgé
cff0a619f5 fix(interfaceConfig) mark as deprecated 2021-03-23 16:59:46 +01:00
hmuresan
f7c0d4f1fe feat(background alpha) Set background transparency 2021-03-23 16:16:56 +02:00
TigiBoom
8fccb05519 fix(lang) fix typo in Russian translation 2021-03-23 14:47:25 +01:00
Vlad Piersec
b4155ab6d2 fix(toolbox): Add missing lang key for video settings 2021-03-23 15:38:15 +02:00
tmoldovan8x8
a1d3870634 feat(external_api): add videoMuted event and action (#8862) 2021-03-23 15:30:17 +02:00
hmuresan
07f16a7a51 feat (external-api) Add command for setting tile view mode 2021-03-23 15:21:57 +02:00
Vlad Piersec
0e7bde2ff0 fix(overflow-menu): Don't change state on hover for disabled items 2021-03-23 14:30:52 +02:00
Vlad Piersec
e9d00acad8 fix(menu): Pop menu icons & background 2021-03-23 14:18:22 +02:00
Mihai-Andrei Uscat
911aaed052 fix: Refactor client width computation.
* Unify chat open/close size changes and move them to redux.
* Fix responsive columns not accounting for chat.
2021-03-23 14:06:43 +02:00
Vlad Piersec
5fd9dc74e4 fix(welcome): Align meeting list at the top when no footer 2021-03-23 14:03:54 +02:00
Vlad Piersec
eb68467e15 fix(rn, toolbox): Change button appearing order 2021-03-23 10:14:54 +02:00
Jaya Allamsetty
6a5d6afc94 chore(deps) lib-jitsi-meet@latest
* fix(JingleSession): Avoid renegotiation when user with no sources leaves the call.
* feat: participant kick reason add
* ref(RTC): remove legacy pc constraints. Stop using the legacy pc constraints that are no longer wired up to WebRTC.
* fix(deps) update webrtc-adapter to v7.7.1

087a8e19eb...4191198233
2021-03-22 19:25:02 -04:00
Дамян Минков
2a9b6a7d28 fix(load-test): Fixes unmuting loadtest client. (#8849)
* fix(load-test): Fixes unmuting loadtest client.

Fixes the case where audio track was not added due to jicofo muting clients.

* squash(load-test): Drop noAutoLocalAudio and change add track logic.

Trying to mimic jitsi-meet.

* squash(load-test): Fix adding video.
2021-03-22 14:39:57 -05:00
adam j hartz
67beafc9af add option for disabling join/leave sounds (#8596)
* add option for disabling join/leave sounds

* document disableJoinLeaveSounds and add it to whitelist
2021-03-22 11:28:34 -05:00
BenjaminVega
6175a5cad5 Be able to toggle the raise-hand via external-api (#8838)
* Be able to toggle the raise-hand via external_api

* Code Review inputs
2021-03-22 11:22:45 -05:00
Vlad Piersec
678f3e232b fix(toolbar): Re-add "mute everyone's video" button 2021-03-22 15:25:30 +02:00
Jake Breen
f3c1b8ac08 fix(android) apply flags when launching activity from non-activity context
Check whether context is that of an Activity before launching the Jitsi Conference Activity. If context is not an activity context, apply flag FLAG_ACTIVITY_NEW_TASK to the Jitsi Activity Intent to ensure activity can launch without error.

This scenario would manifest when a user attempts to launch the Jitsi Actvity from a Widget... for example.

https://developer.android.com/about/versions/pie/android-9.0-changes-all#fant-required
2021-03-22 12:59:43 +01:00
John Wu
f225ce886f fix(chore) fix typo 2021-03-22 11:21:48 +01:00
dependabot[bot]
6a4417c6cc chore(deps): bump ini from 1.3.5 to 1.3.7
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.7)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-22 11:03:23 +01:00
Дамян Минков
6b66c8dd20 fix(config, docs) document feedbackPercentage 2021-03-22 10:56:26 +01:00
luz paz
d3680bbebd fix(misc) follow-up typos
Found via `codespell -q 3 -S ./lang`
2021-03-22 10:41:41 +01:00
dependabot[bot]
7933d4b4d6 chore(deps): bump xmldom from 0.1.27 to 0.5.0
Bumps [xmldom](https://github.com/xmldom/xmldom) from 0.1.27 to 0.5.0.
- [Release notes](https://github.com/xmldom/xmldom/releases)
- [Changelog](https://github.com/xmldom/xmldom/blob/master/CHANGELOG.md)
- [Commits](https://github.com/xmldom/xmldom/compare/v0.1.27...0.5.0)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-22 10:36:43 +01:00
Vlad Piersec
e7297714c6 feat(toolbox): Adaptive toolbar on mobile 2021-03-22 11:26:00 +02:00
Saúl Ibarra Corretgé
8da154b185 fix(android) remove leftover package 2021-03-19 12:58:47 +01:00
Saúl Ibarra Corretgé
3c94a5ccfd feat(rn,ui) update in-meeting colors 2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
78d4af6bf2 feat(rn,conference) new UI for conference name duration 2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
33fc3833f9 fix(rn,labels) don't add extra margin in tile view
There is no need to skip the filmstrip, since it's not there.
2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
b179542c39 fix(rn,labels) top-align with room name field 2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
49c38a73aa fix(filmstrip) make sure it's not rendered outside of a safe area 2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
fc27300132 fix(rn,filmstrip) simplify thumbnail height calculations 2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
57ecdff9eb fix(rn,conference) remove no longer needed margin
We are using a safe area view now.
2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
effa878fa4 fix(rn,filmstrip) simplify visibility calculation 2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
9d4e49a5af fix(rn,toolbox) fill gap underneath Toolbox
This is for devices without the home button.
2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
6b4d25c0d3 fix(rn,ui) move top labels to navbar component 2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
2f5ab2757f feat(rn,ui) get rid of the gradients 2021-03-19 11:32:00 +01:00
Saúl Ibarra Corretgé
bde26c4fbb fix(icons) never specify fill 2021-03-19 11:32:00 +01:00
trippledave
68c2c9be40 feat(flags) add feature flag for audio-only button 2021-03-19 08:17:37 +01:00
Jaya Allamsetty
5b21051c6b fix(startMuted): Fix unmute on mobile when it is muted by Jicofo on join. 2021-03-18 15:23:54 -04:00
hmuresan
8806269af0 * chore(deps) lib-jitsi-meet@latest
5796d83bb1...087a8e19eb
2021-03-18 19:34:44 +01:00
hmuresan
3a8bd852b2 feat(jwt) log jwt validation errors 2021-03-18 16:58:54 +02:00
Hristo Terezov
f50872285d ref(Filmstrip): Use Thumbnail component. 2021-03-18 09:37:55 -05:00
Jaya Allamsetty
e937e99284 chore(deps) lib-jitsi-meet@latest
* squash: Use different function syntax.
* squash: Fix lint errors.
* Process stats immediately before setting the interval.
* feat(ReceiveVideoController): Add the ability to send constraints in the new format. Add the ability to send the bridge messages for the receiver video constraints in the new format directly.

676c7a9105...5796d83bb1
2021-03-18 10:25:29 -04:00
Mihai-Andrei Uscat
3972e076f0 fix(Chat): Fix modals displaying improperly due to chat.
* Adjust chat font size.
* Adjust invite more button and text size.
* Remove useless constant.
2021-03-18 15:56:20 +02:00
Jonathan Lennox
81cf79e643 In loadtest, make localAudio non-const. (#8829)
(Because we modify it.)
2021-03-18 09:39:13 -04:00
Mihai-Andrei Uscat
a22d054b10 feat(InviteMore): Relocate invite prompt for mobile friendliness. 2021-03-18 14:09:22 +02:00
Vlad Piersec
7fce181080 feat(config): Add config option to allow unsetting local video flip 2021-03-18 09:35:42 +02:00
Vlad Piersec
92735478d1 fix(toolbox): Fix overflow menu & button background 2021-03-18 09:16:43 +02:00
Mihai-Andrei Uscat
7dabfc21b4 feat(Chat): Revamp design.
* ensure keyboard stays open when sending messages on mobile web.
2021-03-18 09:08:34 +02:00
Saúl Ibarra Corretgé
1395f84550 fix(virtual-background) fix tainted canvas when using the CDN
When we use a CDN the images come from an origin different than the site so
unless we mark them for CORS the canvas where they are painted will be tainted.

Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image
2021-03-17 16:32:16 +01:00
Vlad Piersec
d080460f9b fix(toolbox): Fix mic disabled icon 2021-03-17 15:23:45 +02:00
tmoldovan8x8
61567f47c0 fix(android) changes the property name for the manifestOutputDirectory 2021-03-17 14:19:43 +01:00
Avram Tudor
4f3058eae2 Merge pull request #8823 from jitsi/tavram/hide-support
fix(jaas) hide support link in invite error for jaas users
2021-03-17 15:16:32 +02:00
Tudor-Ovidiu Avram
3a073d9af4 fix(jaas) hide support link in invite error for jaas users 2021-03-17 11:53:58 +02:00
Mihai-Andrei Uscat
aef0287605 feat(ToggleCamera): Implement for web. 2021-03-17 10:44:18 +02:00
Vlad Piersec
bb19567efa fix(prejoin): Use localFlipX on prejoin screen 2021-03-17 09:19:55 +01:00
Saúl Ibarra Corretgé
79ab973694 chore(deps) update react-native-webrtc
Fix script for downloading bitcode.
2021-03-16 22:09:21 +01:00
Saúl Ibarra Corretgé
7046785ca3 chore(deps) update react-native-webrtc to 1.89.1 2021-03-16 19:57:26 +01:00
Saúl Ibarra Corretgé
b817bd19d5 chore(deps) bump js-utils to 1.0.6
Fixes a harmless but confusing error in postis processing when using the
Bitwarden Chrome extension, for example.
2021-03-16 19:57:03 +01:00
luz paz
817d54b0b9 fix(misc) typos
Found via `codespell -q 3 -S ./lang`
2021-03-16 16:12:12 +01:00
Vlad Piersec
3f0bb6818c fix(toolbox): Fix always on top toolbar 2021-03-16 16:07:49 +01:00
Saúl Ibarra Corretgé
4fa47c8070 fix(virtual-background) use a DOM element for storing the image
THis will reuse the previously cached image and obey the base href.

Ref:
https://stackoverflow.com/questions/6241716/is-there-a-difference-between-new-image-and-document-createelementimg
2021-03-16 11:27:27 +01:00
Saúl Ibarra Corretgé
0dcb8a025b fix(rn,bottomsheet) limit width 2021-03-16 11:19:52 +01:00
tmoldovan8x8
8defaa9aec feat(android): adds timer to OngoingNotification 2021-03-16 12:13:37 +02:00
Vlad Piersec
d214079148 fix(toolbox): Constrain toolbox width on large mobile device 2021-03-16 09:50:49 +01:00
Vlad Piersec
096ee3cb53 fix(toolbox): Background of disabled settings button & tileview button 2021-03-16 09:20:02 +01:00
Vlad Piersec
fd606896b8 fix(toolbox): Fix buttons size in minified mode 2021-03-16 09:32:36 +02:00
Jonathan Lennox
226581a81a Add muteAudio function to load test JS. (#8802) 2021-03-15 15:37:58 -04:00
Avram Tudor
e1c5b1e626 Merge pull request #8799 from jitsi/tavram/billing-id
fix(vpaas) send jitsiMeetId instead of billingId
2021-03-15 15:54:57 +02:00
Tudor-Ovidiu Avram
831c5ba59d fix(vpaas) send jitsiMeetId instead of billingId 2021-03-15 13:22:17 +02:00
Andrei Gavrilescu
bad1bc91cf fix(screenshare): audio screen share muted state (#8785)
* AudioMixerEffect muted state

* update lib-jitsi-meet
2021-03-15 11:44:03 +02:00
Saúl Ibarra Corretgé
30d0aabaca feat(build,rnnoise) don't use an external bundle for the effect
The majority of the code is in the WASM file, the JS is just 9KB.
It's so little, in fact, that the performance hint for the main bundle didn't
have to be adjusted.
2021-03-12 23:00:50 +01:00
Saúl Ibarra Corretgé
22b6d32174 feat(build,virtual-background) don't use an external bundle for the effect
The majority of the code is in the WASM file and models, this is just a few KB.
It's so little, in fact, that the performance hint for the main bundle didn't
have to be adjusted.
2021-03-12 23:00:50 +01:00
Saúl Ibarra Corretgé
31ace267ce fix(virtual-background) use tighter edge smoothing 2021-03-12 15:05:20 +01:00
tudordan7
194d357005 feat(virtual-backgrounds) add virtual background support 2021-03-12 15:05:20 +01:00
Vlad Piersec
c2ad06c5e6 fix(toolbox): Restructure items order for desktop & mobile 2021-03-12 15:19:23 +02:00
Vlad Piersec
e40b02ab3c fix(icons): No hardcoded colors for some svgs 2021-03-12 11:29:20 +02:00
titus.moldovan
2587eefefc fix(chat) hides send private chat button when enable.chat flag is false. 2021-03-12 09:19:31 +01:00
Vlad Piersec
b87c433e99 fix(toolbar): Update overflow menu according to review 2021-03-11 15:49:00 +02:00
tmoldovan8x8
751644db16 makes disableAudioFocus flag generic, so it can be used also from iOS 2021-03-11 15:13:24 +02:00
Vlad Piersec
c508572cc5 feat(toolbox): Redesign mobile toolbox 2021-03-11 12:38:37 +01:00
Vlad Piersec
b86c271a80 fix(toolbar): Small changes according to design review 2021-03-11 11:57:17 +01:00
Hristo Terezov
5efbe5f0ec chore(deps) lib-jitsi-meet@latest
* fix(modificationQueue): error handling & logs
* feat(dominantSpeaker): Add previous speaker list.

e60f09b189...0ec072378c
2021-03-10 17:30:06 -06:00
Jaya Allamsetty
2784c43a1b fix(UI): Add playsinline attribute for remote video.
For the video to play on Safari mobile browser, the playsInline attribute needs to be set to true. Set the mute attribute as well which was accidentally removed in code refactor.
2021-03-10 18:05:41 -05:00
Hristo Terezov
f5a34183e9 fix(useVideoStream): error handling & add logs. 2021-03-10 17:02:29 -06:00
Hristo Terezov
29f5d87d77 fix(prejoin): Don't overwrite display name with '' 2021-03-10 15:10:41 -06:00
hmuresan
ab6790bdaa (external_api) Add command for overwriting config values. 2021-03-10 18:30:14 +02:00
damencho
2e308d67d8 feat: Fixes filtering not needed presences.
We were filtering only self presences, no it filters and the presences to the other participants.
2021-03-09 16:19:43 -06:00
Vlad Piersec
91ba835f78 feat(Toolbar): Redesign web toolbar 2021-03-09 16:29:44 +02:00
dependabot[bot]
2643029ac8 chore(deps): bump elliptic from 6.5.3 to 6.5.4
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4.
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-09 14:19:38 +01:00
Saúl Ibarra Corretgé
e40e078a29 fix(ios,build) make sure the correct broadcast extension ID is set 2021-03-09 10:33:04 +01:00
Saúl Ibarra Corretgé
6df5a4cf31 fix(ios) make sure broadcast extension version matches
Fixes this Apple Store Connect warning:

~~~
ITMS-90473: CFBundleShortVersionString Mismatch - The CFBundleShortVersionString
value '1.0' of extension 'jitsi-meet.app/PlugIns/JitsiMeetBroadcast
Extension.appex' does not match the CFBundleShortVersionString value '21.0.0' of
its containing iOS application 'jitsi-meet.app'.
~~~
2021-03-09 10:33:04 +01:00
Saúl Ibarra Corretgé
c7c7d7a155 fix(ios) move extension to a path without spaces 2021-03-09 10:33:04 +01:00
Hristo Terezov
8f06866646 feat(config): Add useHostPageLocalStorage 2021-03-08 16:26:42 -06:00
damencho
b559cb8ec6 feat: Move checks for moderator in pre-join and filter extra presences.
We will filter the initial presence where participant is announced as `participant` and shortly after that we send a second presence with the new `moderator` role.
2021-03-08 16:01:32 -06:00
damencho
30a2e84da1 fix: Fixes filtering lobby presences. 2021-03-08 16:01:32 -06:00
Saúl Ibarra Corretgé
3122983000 fix(config) fix syntax error in commented code 2021-03-08 15:34:19 -06:00
Jean-François Alarie
407021e258 feat(rn,flags) add fullscreen.enabled flag 2021-03-08 22:11:39 +01:00
Jaya Allamsetty
1a62a7b1cc chore(deps) lib-jitsi-meet@latest
* feat(browser-support): Add support for WKWebview based browsers. Apple added getUserMedia support for WkWebview based browsers like chrome and Firefox on iOS 14.3. These browsers behave as Safari does on iOS. Therefore, extend the Safari checks to these webkit based browsers as well.

08ce96d881...e60f09b189
2021-03-08 12:12:31 -05:00
Jaya Allamsetty
0ee03f1538 feat(browser-support): Add support for WKWebview based browsers. 2021-03-08 11:16:02 -05:00
Jaya Allamsetty
572beb8382 chore(deps) lib-jitsi-meet@latest
* squash: Always get lastN value from JitsiConference instance.
* fix(lastN): Return the correct lastN value for the conference.
* Use unified plan for mobile browsers on iOS

d31b5a2d5e...08ce96d881
2021-03-08 10:26:14 -05:00
Mihai-Andrei Uscat
d0d32b8a19 fix(responsive): Fix tiles not recomputing when jumping between screen sizes 2021-03-05 12:35:09 -06:00
Saúl Ibarra Corretgé
82ff988c18 fix(ios) the broadcast extension'd bundle ID must match the app's 2021-03-05 18:02:48 +01:00
Jaya Allamsetty
8fa5d09612 chore(deps) lib-jitsi-meet@latest
* fix(conference): Do not signal muted tracks on join. Do not add the muted audio/video tracks to the peerconnection on join. The tracks will be added when the user unmutes for the first time. This reduces the number of remote sources that will be added when a participant joins a large call where everyone joins muted (startAudioMuted/startVideoMuted setting).

e83fb93d2d...d31b5a2d5e
2021-03-05 10:42:05 -05:00
Alex Bumbu
508f1e0da9 feat(iOS): screensharing support
The Jitsi team would like to thank @AliKarpuzoglu, @linuxpi and The Hopp Foundation for the initial effort and help throughout.
2021-03-05 16:33:53 +01:00
Jaya Allamsetty
dcda89012e fix(tracks): Do not signal muted audio tracks.
Do not add the muted audio tracks to peerconnection until the user unmutes the first time. This applies to startSilent, startWithAudioMuted and startAudioMuted/startVideoMuted config.js settings.
2021-03-05 10:18:34 -05:00
Saúl Ibarra Corretgé
d93a402cc2 fix(rn,tracks) fix not showing alert when permission is not granted
The error object changed its shape through time, adapt to the change.
2021-03-05 12:59:13 +01:00
Saúl Ibarra Corretgé
b7b260f4c9 feat(ci) fail CI if package-lock wasn't updated 2021-03-05 11:13:49 +01:00
Saúl Ibarra Corretgé
4db3f04c0c fix(deps) sync package-lock 2021-03-05 11:13:49 +01:00
Дамян Минков
126a2bd0d7 chore(deps): Checks presence editing and make sure we send only on change.
* fix: Checks presence editing and make sure we send only on change.

f1ec966780...e83fb93d2d
2021-03-04 16:52:24 -06:00
gpatel-fr
29bbcf8590 handles spaces around hostname
((users doubleclick a host name and paste result in the installer)
2021-03-04 11:39:05 -06:00
Saúl Ibarra Corretgé
5c46b03251 fix(copyText) use a helper library
It does a more elaborate way of textarea copying, hopefully it's more reliable.
2021-03-04 10:03:51 -06:00
るしふぁ
eeb5abbbe8 fix: date util localization (#8723)
* Update dateUtil.js

* version up moment

* exclude unnecessary languages in Moment.js from webpack

* add Occitan of Moment.js

* Fixed auto-formatting

* add require missing by mistake
2021-03-04 08:20:27 -06:00
roms2000
49583b611c Update main-fr.json
Add missing translation.
Improve French language / French styling.
Fix typos.
2021-03-03 21:22:52 -06:00
Hristo Terezov
9e29dd063f fix(live-stream-section): Use await for copyText 2021-03-03 16:26:36 -06:00
Hristo Terezov
a2e2d31dfd fix(copyText): in iframe for chrome<85 2021-03-03 16:12:59 -06:00
Óscar Carretero
62c06441b1 Normalize language format 2021-03-03 15:14:34 -06:00
Niklas
f718a3e050 lang: Update main-da.json (#8642)
* Update main-da.json

* Apply suggestions from code review

Co-authored-by: jokjr <69192941+jokjr@users.noreply.github.com>

* Update main-da.json

* Apply suggestions from code review

Co-authored-by: jokjr <69192941+jokjr@users.noreply.github.com>

Co-authored-by: jokjr <69192941+jokjr@users.noreply.github.com>
2021-03-03 14:44:31 -06:00
Steffen Kolmer
899968d3a9 feat: Only show more numbers link if multiple numbers are available (#8702)
* Only show more numbers link if multiple numbers are available

* Fixed some linter errors

* Try to make flow happy

* Fixed another linter error

* Another try to make eslint happy

* Silence eslint
2021-03-03 08:45:26 -06:00
Matthias Nagel
696f509f18 Corrected example config for Apache
- dropped uneccessary rewrite rule
 - corrected number of trailing slashs in proxy directive
 - corrected url for colibri websocket
2021-03-03 08:43:32 -06:00
Calinteodor
430591bd1e feat(shared-video) refactor dialog to use React
Also unify the mobile and web features into one, even though internally they still have separate ways to enable the functionality.
2021-03-03 15:37:38 +01:00
dimitardelchev93
8ee324b37f Add missing translation in main-de.json (#8664) 2021-03-03 08:16:16 -06:00
tmoldovan8x8
399d6b6a4b chore(version) bumps mobile sdkVersion to 3.2.0 2021-03-02 15:21:20 +01:00
Saúl Ibarra Corretgé
ffad21cb59 fix(ios) sync podfile 2021-03-02 10:31:47 +01:00
Steffen Kolmer
ce6debac45 Revert changes dial in numbers link 2021-02-26 23:30:57 -06:00
Steffen Kolmer
5d8bf0c1e7 feat: Add a new setting to remove individual sharing features from UI (#8660)
* Added new config to enable individual sharing features

* make config values url friendly

* Add new setting to whitelist

* Fixed some linter issues

* Fixed more linter issues

* Fixed merge error

* Check if interfaceConfig is defined

* Only show more numbers link if there is more than one number
2021-02-26 19:50:26 -06:00
Steffen Kolmer
7bbd06c9f4 Use logger instead of console 2021-02-26 19:50:02 -06:00
Hristo Terezov
79a67049a9 chore(deps) lib-jitsi-meet@latest
* fix(RTCUtils): Init availableDevices.

e6ef4e7ae9...f1ec966780
2021-02-26 17:59:11 -06:00
Hristo Terezov
b1a3c5cd7b feat(external_api): allow clipboard-write 2021-02-26 15:05:45 -06:00
Hristo Terezov
9573a615b1 chore(deps) lib-jitsi-meet@latest
* fix(RTC) fix device selection not being available
* fix(TPCUtils): undefined is not an object (evaluating 'this.tpcUtils.replaceTrack(e,t).then')

4c668023b3...e6ef4e7ae9
2021-02-26 12:48:23 -06:00
Jaya Allamsetty
5d09102e48 chore(deps) lib-jitsi-meet@latest
* fix(TPC): Remove the existing track instead of overwriting. When a second remote track of the same mediatype is received for an endpoint, remove the existing track before creating the new remote track.

9beb47fe5f...4c668023b3
2021-02-26 10:24:48 -05:00
Tudor D. Pop
cc0ecc1fdd fix(blur) disable blur button if camera is off 2021-02-26 16:03:51 +01:00
Saúl Ibarra Corretgé
cecf324023 fix(deps) bump lodash
Fixes: https://github.com/jitsi/jitsi-meet/issues/8683
2021-02-25 16:16:18 +01:00
Saúl Ibarra Corretgé
943d5dca35 chore(deps) remove Tensorflow
We use TFLite now so this is unused.
2021-02-25 14:14:28 +01:00
Tudor D. Pop
dd1f8339b1 fix(blur-effect) enable blur effect on all platforms supporting canvas filters
That means all browsers except Safari, for now.

In addition, use the 96p model (instead of the 144p one) on browsers without SIMD support.
2021-02-25 13:21:03 +01:00
tudordan7
159f59b665 fix(lint-run-command) 2021-02-25 11:24:03 +01:00
Steffen Kolmer
23bb824731 feat: Added mute video moderation feature (#8630)
* Added mute video feature

* Fixed export

* Fixed some issues

* Added remote video mute notification

* Fixed import

* Fixed conference event handling

* Fixed some linting issues

* Fixed more linter errors

* turn screenshare off on remote video mute

* Fix linter issue

* translations added for mute video feature

* Added video mute button to interface config

* Updated lib-jitsi-meet

* Fix copy paste error

Co-authored-by: nurjinn jafar <nurjin.jafar@nordeck.net>
2021-02-24 15:45:07 -06:00
Saúl Ibarra Corretgé
42d926eef3 chore(deps) lib-jitsi-meet@latest
* fix(e2ee) fix disabling E2EE
* fix(e2ee) fix key index after ratchetting
* fix: Drop caps handling (#1495)
* fix(SendVideoController): Apply the sender constraint only when it changes. There were cases where the bridge was sending the same constraint multiple times causing redundant calls to getParameters/setParameters on the RTCRtpSender.
* feat: Use the new bridge signaling format.
* fix(gum) update permissions prompt detection

c534f74884...6a7b16c33e
2021-02-24 18:17:09 +01:00
Calinteodor
87a110b9c3 fix: improved copy text helper function (#8677) 2021-02-24 09:12:41 -06:00
Mihai-Andrei Uscat
a7db7ecaff fix(LargeVideo): Fix large video not resizing when closing chat. 2021-02-24 14:26:00 +02:00
horymury
79bb98dab3 (feature) - Add support for custom DID numbers page url 2021-02-24 11:37:14 +02:00
Gabriel Imre
d22792c9e3 feat(sip): Added auto-knocking for sip gateway if lobby is enabled
Co-authored-by: Gabriel Imre <gabriel.lucaci@8x8.com>
2021-02-24 11:35:32 +02:00
Avram Tudor
41e6af3464 Merge pull request #8120 from jitsi/tavram/slowgum
fix(gum) add event handling for SLOW_GET_USER_MEDIA
2021-02-23 14:45:36 +02:00
Tudor-Ovidiu Avram
f50fd7b7bd fix(gum) add event handling for SLOW_GET_USER_MEDIA
Show an overlay with a spinner when slow gUM is fired
2021-02-23 13:51:24 +02:00
Mihai-Andrei Uscat
43761fc398 feat(Chat) Improve responsive behaviour further.
* Add buttons to send messages/set nickname.
* Redesign message/nickname inputs.
* Pin messages to the input.
* Add keyboard avoider for Safari.
* Make chat content scrollable on mobile.
2021-02-23 09:39:20 +02:00
damencho
4c39d83ff1 feat(load-test): Fixes audio senders. 2021-02-22 17:48:19 -06:00
Jaya Allamsetty
e525c2b2ec chore(deps) lib-jitsi-meet@latest
* fix(SendVideoController): Apply the sender constraint only when it changes. There were cases where the bridge was sending the same constraint multiple times causing redundant calls to getParameters/setParameters on the RTCRtpSender.
* fix(gum) update permissions prompt detection

beaff3dd02...7f919faacc
2021-02-19 12:04:25 -05:00
Tudor D. Pop
f69a31d9c6 fix(blur) check model response status and catch errors 2021-02-19 15:00:07 +01:00
tmoldovan8x8
67930edae2 chore(ios) remove warnings on JitsiMeetView 2021-02-19 10:40:45 +02:00
Jaya Allamsetty
c11a94f7d7 feat: Add 'useNewBandwidthAllocationStrategy' to config.js. 2021-02-18 14:30:39 -05:00
Jaya Allamsetty
bfd093b0ba chore(deps) lib-jitsi-meet@latest
* feat: Use the new bridge signaling format.

c534f74884...beaff3dd02
2021-02-18 14:30:39 -05:00
Saúl Ibarra Corretgé
861935c9d7 fix(blur) fix model paths 2021-02-18 15:57:01 +01:00
556 changed files with 10732 additions and 6120 deletions

View File

@@ -5,8 +5,9 @@ build/*
# modify as little as possible.
flow-typed/*
libs/*
react/features/stream-effects/blur/vendor/*
resources/*
react/features/stream-effects/virtual-background/vendor/*
load-test/*
# ESLint will by default ignore its own configuration file. However, there does
# not seem to be a reason why we will want to risk being inconsistent with our

View File

@@ -12,5 +12,6 @@ jobs:
with:
node-version: '12.x'
- run: npm install
- run: git status -s --untracked-files=no
- run: npm run lint
- run: make

View File

@@ -5,8 +5,8 @@ LIBJITSIMEET_DIR = node_modules/lib-jitsi-meet/
LIBFLAC_DIR = node_modules/libflacjs/dist/min/
OLM_DIR = node_modules/olm
RNNOISE_WASM_DIR = node_modules/rnnoise-wasm/dist/
TFLITE_WASM = react/features/stream-effects/blur/vendor/tflite
MEET_MODELS_DIR = react/features/stream-effects/blur/vendor/models/
TFLITE_WASM = react/features/stream-effects/virtual-background/vendor/tflite
MEET_MODELS_DIR = react/features/stream-effects/virtual-background/vendor/models/
NODE_SASS = ./node_modules/.bin/sass
NPM = npm
OUTPUT_DIR = .
@@ -51,10 +51,6 @@ deploy-appbundle:
$(OUTPUT_DIR)/analytics-ga.js \
$(BUILD_DIR)/analytics-ga.min.js \
$(BUILD_DIR)/analytics-ga.min.map \
$(BUILD_DIR)/video-blur-effect.min.js \
$(BUILD_DIR)/video-blur-effect.min.map \
$(BUILD_DIR)/rnnoise-processor.min.js \
$(BUILD_DIR)/rnnoise-processor.min.map \
$(BUILD_DIR)/close3.min.js \
$(BUILD_DIR)/close3.min.map \
$(DEPLOY_DIR)

View File

@@ -122,7 +122,7 @@ gradle.projectsEvaluated {
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.getProcessManifestProvider().get().doLast {
def outputDir = manifestOutputDirectory.get().asFile
def outputDir = multiApkManifestOutputDirectory.get().asFile
def manifestPath = new File(outputDir, 'AndroidManifest.xml')
def charset = 'UTF-8'
def text

View File

@@ -26,4 +26,4 @@ android.useAndroidX=true
android.enableJetifier=true
appVersion=21.0.0
sdkVersion=3.1.0
sdkVersion=3.2.0

View File

@@ -70,7 +70,6 @@ dependencies {
implementation project(':react-native-default-preference')
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-linear-gradient')
implementation project(':react-native-sound')
implementation project(':react-native-svg')
implementation project(':react-native-webrtc')

View File

@@ -36,8 +36,17 @@ public class BroadcastAction {
for (String key : this.data.keySet()) {
try {
// TODO add support for different types of objects
nativeMap.putString(key, this.data.get(key).toString());
if (this.data.get(key) instanceof Boolean) {
nativeMap.putBoolean(key, (Boolean) this.data.get(key));
} else if (this.data.get(key) instanceof Integer) {
nativeMap.putInt(key, (Integer) this.data.get(key));
} else if (this.data.get(key) instanceof Double) {
nativeMap.putDouble(key, (Double) this.data.get(key));
} else if (this.data.get(key) instanceof String) {
nativeMap.putString(key, (String) this.data.get(key));
} else {
throw new Exception("Unsupported extra data type");
}
} catch (Exception e) {
JitsiMeetLogger.w(TAG + " invalid extra data in event", e);
}
@@ -66,7 +75,8 @@ public class BroadcastAction {
RETRIEVE_PARTICIPANTS_INFO("org.jitsi.meet.RETRIEVE_PARTICIPANTS_INFO"),
OPEN_CHAT("org.jitsi.meet.OPEN_CHAT"),
CLOSE_CHAT("org.jitsi.meet.CLOSE_CHAT"),
SEND_CHAT_MESSAGE("org.jitsi.meet.SEND_CHAT_MESSAGE");
SEND_CHAT_MESSAGE("org.jitsi.meet.SEND_CHAT_MESSAGE"),
SET_VIDEO_MUTED("org.jitsi.meet.SET_VIDEO_MUTED");
private final String action;

View File

@@ -85,7 +85,9 @@ public class BroadcastEvent {
SCREEN_SHARE_TOGGLED("org.jitsi.meet.SCREEN_SHARE_TOGGLED"),
PARTICIPANTS_INFO_RETRIEVED("org.jitsi.meet.PARTICIPANTS_INFO_RETRIEVED"),
CHAT_MESSAGE_RECEIVED("org.jitsi.meet.CHAT_MESSAGE_RECEIVED"),
CHAT_TOGGLED("org.jitsi.meet.CHAT_TOGGLED");
CHAT_TOGGLED("org.jitsi.meet.CHAT_TOGGLED"),
VIDEO_MUTED_CHANGED("org.jitsi.meet.VIDEO_MUTED_CHANGED");
private static final String CONFERENCE_WILL_JOIN_NAME = "CONFERENCE_WILL_JOIN";
private static final String CONFERENCE_JOINED_NAME = "CONFERENCE_JOINED";
@@ -98,6 +100,7 @@ public class BroadcastEvent {
private static final String PARTICIPANTS_INFO_RETRIEVED_NAME = "PARTICIPANTS_INFO_RETRIEVED";
private static final String CHAT_MESSAGE_RECEIVED_NAME = "CHAT_MESSAGE_RECEIVED";
private static final String CHAT_TOGGLED_NAME = "CHAT_TOGGLED";
private static final String VIDEO_MUTED_CHANGED_NAME = "VIDEO_MUTED_CHANGED";
private final String action;
@@ -142,6 +145,8 @@ public class BroadcastEvent {
return CHAT_MESSAGE_RECEIVED;
case CHAT_TOGGLED_NAME:
return CHAT_TOGGLED;
case VIDEO_MUTED_CHANGED_NAME:
return VIDEO_MUTED_CHANGED;
}
return null;

View File

@@ -40,4 +40,10 @@ public class BroadcastIntentHelper {
intent.putExtra("message", message);
return intent;
}
public static Intent buildSetVideoMutedIntent(boolean muted) {
Intent intent = new Intent(BroadcastAction.Type.SET_VIDEO_MUTED.getAction());
intent.putExtra("muted", muted);
return intent;
}
}

View File

@@ -85,6 +85,7 @@ class ExternalAPIModule
constants.put("OPEN_CHAT", BroadcastAction.Type.OPEN_CHAT.getAction());
constants.put("CLOSE_CHAT", BroadcastAction.Type.CLOSE_CHAT.getAction());
constants.put("SEND_CHAT_MESSAGE", BroadcastAction.Type.SEND_CHAT_MESSAGE.getAction());
constants.put("SET_VIDEO_MUTED", BroadcastAction.Type.SET_VIDEO_MUTED.getAction());
return constants;
}

View File

@@ -32,6 +32,7 @@ import com.facebook.react.modules.core.PermissionListener;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import java.util.HashMap;
import android.app.Activity;
/**
* A base activity for SDK users to embed. It uses {@link JitsiMeetFragment} to do the heavy
@@ -58,6 +59,9 @@ public class JitsiMeetActivity extends FragmentActivity
Intent intent = new Intent(context, JitsiMeetActivity.class);
intent.setAction(ACTION_JITSI_MEET_CONFERENCE);
intent.putExtra(JITSI_MEET_CONFERENCE_OPTIONS, options);
if (!(context instanceof Activity)) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}

View File

@@ -132,6 +132,7 @@ public class JitsiMeetOngoingConferenceService extends Service
public void onCurrentConferenceChanged(String conferenceUrl) {
if (conferenceUrl == null) {
stopSelf();
OngoingNotification.resetStartingtime();
JitsiMeetLogger.i(TAG + "Service stopped");
}
}

View File

@@ -43,6 +43,7 @@ class OngoingNotification {
private static final String CHANNEL_NAME = "Ongoing Conference Notifications";
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
private static long startingTime = 0;
static void createOngoingConferenceNotificationChannel() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
@@ -85,6 +86,10 @@ class OngoingNotification {
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_ID);
if (startingTime == 0) {
startingTime = System.currentTimeMillis();
}
builder
.setCategory(NotificationCompat.CATEGORY_CALL)
.setContentTitle(context.getString(R.string.ongoing_notification_title))
@@ -92,6 +97,8 @@ class OngoingNotification {
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntent)
.setOngoing(true)
.setWhen(startingTime)
.setUsesChronometer(true)
.setAutoCancel(false)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOnlyAlertOnce(true)
@@ -110,6 +117,10 @@ class OngoingNotification {
return builder.build();
}
static void resetStartingtime() {
startingTime = 0;
}
private static NotificationCompat.Action createAction(Context context, JitsiMeetOngoingConferenceService.Action action, @StringRes int titleId) {
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
intent.setAction(action.getName());

View File

@@ -178,7 +178,6 @@ class ReactInstanceManagerHolder {
List<ReactPackage> packages
= new ArrayList<>(Arrays.asList(
new com.BV.LinearGradient.LinearGradientPackage(),
new com.calendarevents.CalendarEventsPackage(),
new com.corbt.keepawake.KCKeepAwakePackage(),
new com.facebook.react.shell.MainReactPackage(),

View File

@@ -19,8 +19,6 @@ include ':react-native-immersive'
project(':react-native-immersive').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-immersive/android')
include ':react-native-keep-awake'
project(':react-native-keep-awake').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keep-awake/android')
include ':react-native-linear-gradient'
project(':react-native-linear-gradient').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-linear-gradient/android')
include ':react-native-sound'
project(':react-native-sound').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-sound/android')
include ':react-native-splash-screen'

1
app.js
View File

@@ -1,7 +1,6 @@
/* application specific logic */
import 'jquery';
import 'jquery-contextmenu';
import 'jQuery-Impromptu';
import 'olm';

View File

@@ -99,6 +99,7 @@ import {
destroyLocalTracks,
getLocalJitsiAudioTrack,
getLocalJitsiVideoTrack,
getLocalTracks,
isLocalCameraTrackMuted,
isLocalTrackMuted,
isUserInteractionRequiredForUnmute,
@@ -115,7 +116,7 @@ import {
submitFeedback
} from './react/features/feedback';
import { showNotification } from './react/features/notifications';
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay';
import { mediaPermissionPromptVisibilityChanged, toggleSlowGUMOverlay } from './react/features/overlay';
import { suspendDetected } from './react/features/power-monitor';
import {
initPrejoin,
@@ -125,7 +126,7 @@ import {
} from './react/features/prejoin';
import { disableReceiver, stopReceiver } from './react/features/remote-control';
import { toggleScreenshotCaptureEffect } from './react/features/screenshot-capture';
import { setSharedVideoStatus } from './react/features/shared-video';
import { setSharedVideoStatus } from './react/features/shared-video/actions';
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
import { createPresenterEffect } from './react/features/stream-effects/presenter';
import { endpointMessageReceived } from './react/features/subtitles';
@@ -308,11 +309,6 @@ class ConferenceConnector {
room.join();
}, 5000);
const { password }
= APP.store.getState()['features/base/conference'];
AuthHandler.requireAuth(room, password);
break;
}
@@ -377,7 +373,6 @@ class ConferenceConnector {
if (this.reconnectTimeout !== null) {
clearTimeout(this.reconnectTimeout);
}
AuthHandler.closeAuth();
}
/**
@@ -473,18 +468,13 @@ export default {
*/
createInitialLocalTracks(options = {}) {
const errors = {};
// Always get a handle on the audio input device so that we have statistics (such as "No audio input" or
// "Are you trying to speak?" ) even if the user joins the conference muted.
const initialDevices = config.disableInitialGUM ? [] : [ 'audio' ];
const requestedAudio = !config.disableInitialGUM;
let requestedVideo = false;
// Always get a handle on the audio input device so that we have statistics even if the user joins the
// conference muted. Previous implementation would only acquire the handle when the user first unmuted,
// which would results in statistics ( such as "No audio input" or "Are you trying to speak?") being available
// only after that point.
if (options.startWithAudioMuted) {
this.muteAudio(true, true);
}
if (!config.disableInitialGUM
&& !options.startWithVideoMuted
&& !options.startAudioOnly
@@ -502,10 +492,15 @@ export default {
);
}
JitsiMeetJS.mediaDevices.addEventListener(
JitsiMediaDevicesEvents.SLOW_GET_USER_MEDIA,
() => APP.store.dispatch(toggleSlowGUMOverlay(true))
);
let tryCreateLocalTracks;
// On Electron there is no permission prompt for granting permissions. That's why we don't need to
// spend much time displaying the overlay screen. If GUM is not resolved withing 15 seconds it will
// spend much time displaying the overlay screen. If GUM is not resolved within 15 seconds it will
// probably never resolve.
const timeout = browser.isElectron() ? 15000 : 60000;
@@ -519,8 +514,10 @@ export default {
return createLocalTracksF({
devices: [ 'audio' ],
timeout
}, true)
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
.then(([ audioStream ]) =>
[ desktopStream, audioStream ])
.catch(error => {
@@ -536,8 +533,10 @@ export default {
return requestedAudio
? createLocalTracksF({
devices: [ 'audio' ],
timeout
}, true)
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
: [];
})
.catch(error => {
@@ -551,8 +550,10 @@ export default {
} else {
tryCreateLocalTracks = createLocalTracksF({
devices: initialDevices,
timeout
}, true)
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
.catch(err => {
if (requestedAudio && requestedVideo) {
@@ -561,7 +562,7 @@ export default {
if (err.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
// In this case we expect that the permission prompt is still visible. There is no point of
// executing GUM with different source. Also at the time of writting the following
// executing GUM with different source. Also at the time of writing the following
// inconsistency have been noticed in some browsers - if the permissions prompt is visible
// and another GUM is executed the prompt does not change its content but if the user
// clicks allow the user action isassociated with the latest GUM call.
@@ -574,8 +575,10 @@ export default {
return (
createLocalTracksF({
devices: [ 'audio' ],
timeout
}, true));
timeout,
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
}));
} else if (requestedAudio && !requestedVideo) {
errors.audioOnlyError = err;
@@ -598,8 +601,9 @@ export default {
return requestedVideo
? createLocalTracksF({
devices: [ 'video' ],
timeout
}, true)
firePermissionPromptIsShownEvent: true,
fireSlowPromiseEvent: true
})
: [];
})
.catch(err => {
@@ -615,10 +619,11 @@ export default {
// Hide the permissions prompt/overlay as soon as the tracks are
// created. Don't wait for the connection to be made, since in some
// cases, when auth is rquired, for instance, that won't happen until
// cases, when auth is required, for instance, that won't happen until
// the user inputs their credentials, but the dialog would be
// overshadowed by the overlay.
tryCreateLocalTracks.then(tracks => {
APP.store.dispatch(toggleSlowGUMOverlay(false));
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
return tracks;
@@ -809,12 +814,16 @@ export default {
return this._setLocalAudioVideoStreams(tracks);
}
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(
roomName, initialOptions);
const [ tracks, con ] = await this.createInitialLocalTracksAndConnect(roomName, initialOptions);
let localTracks = tracks;
this._initDeviceList(true);
return this.startConference(con, tracks);
if (initialOptions.startWithAudioMuted) {
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
}
return this.startConference(con, localTracks);
},
/**
@@ -882,7 +891,7 @@ export default {
showUI && APP.store.dispatch(notifyMicError(error));
};
createLocalTracksF({ devices: [ 'audio' ] }, false)
createLocalTracksF({ devices: [ 'audio' ] })
.then(([ audioTrack ]) => audioTrack)
.catch(error => {
maybeShowErrorDialog(error);
@@ -996,7 +1005,7 @@ export default {
//
// FIXME when local track creation is moved to react/redux
// it should take care of the use case described above
createLocalTracksF({ devices: [ 'video' ] }, false)
createLocalTracksF({ devices: [ 'video' ] })
.then(([ videoTrack ]) => videoTrack)
.catch(error => {
// FIXME should send some feedback to the API on error ?
@@ -1005,7 +1014,11 @@ export default {
// Rollback the video muted status by using null track
return null;
})
.then(videoTrack => this.useVideoStream(videoTrack));
.then(videoTrack => {
logger.debug(`muteVideo: calling useVideoStream for track: ${videoTrack}`);
return this.useVideoStream(videoTrack);
});
} else {
// FIXME show error dialog if it fails (should be handled by react)
muteLocalVideo(mute);
@@ -1305,7 +1318,11 @@ export default {
this._getConferenceOptions());
APP.store.dispatch(conferenceWillJoin(room));
this._setLocalAudioVideoStreams(localTracks);
// Filter out the tracks that are muted.
const tracks = localTracks.filter(track => !track.isMuted());
this._setLocalAudioVideoStreams(tracks);
this._room = room; // FIXME do not use this
sendLocalParticipant(APP.store, room);
@@ -1324,8 +1341,11 @@ export default {
if (track.isAudioTrack()) {
return this.useAudioStream(track);
} else if (track.isVideoTrack()) {
logger.debug(`_setLocalAudioVideoStreams is calling useVideoStream with track: ${track}`);
return this.useVideoStream(track);
}
logger.error(
'Ignored not an audio nor a video track: ', track);
@@ -1345,6 +1365,8 @@ export default {
* @returns {Promise}
*/
useVideoStream(newTrack) {
logger.debug(`useVideoStream: ${newTrack}`);
return new Promise((resolve, reject) => {
_replaceLocalVideoTrackQueue.enqueue(onFinish => {
const state = APP.store.getState();
@@ -1354,24 +1376,30 @@ export default {
if (isPrejoinPageVisible(state)) {
const oldTrack = getLocalJitsiVideoTrack(state);
logger.debug(`useVideoStream on the prejoin screen: Replacing ${oldTrack} with ${newTrack}`);
return APP.store.dispatch(replaceLocalTrack(oldTrack, newTrack))
.then(resolve)
.catch(reject)
.catch(error => {
logger.error(`useVideoStream failed on the prejoin screen: ${error}`);
reject(error);
})
.then(onFinish);
}
logger.debug(`useVideoStream: Replacing ${this.localVideo} with ${newTrack}`);
APP.store.dispatch(
replaceLocalTrack(this.localVideo, newTrack, room))
replaceLocalTrack(this.localVideo, newTrack, room))
.then(() => {
this.localVideo = newTrack;
this._setSharingScreen(newTrack);
if (newTrack) {
APP.UI.addLocalVideoStream(newTrack);
}
this.setVideoMuteStatus(this.isLocalVideoMuted());
})
.then(resolve)
.catch(reject)
.catch(error => {
logger.error(`useVideoStream failed: ${error}`);
reject(error);
})
.then(onFinish);
});
});
@@ -1518,7 +1546,11 @@ export default {
if (didHaveVideo) {
promise = promise.then(() => createLocalTracksF({ devices: [ 'video' ] }))
.then(([ stream ]) => this.useVideoStream(stream))
.then(([ stream ]) => {
logger.debug(`_turnScreenSharingOff using ${stream} for useVideoStream`);
return this.useVideoStream(stream);
})
.catch(error => {
logger.error('failed to switch back to local video', error);
@@ -1529,7 +1561,11 @@ export default {
);
});
} else {
promise = promise.then(() => this.useVideoStream(null));
promise = promise.then(() => {
logger.debug('_turnScreenSharingOff using null for useVideoStream');
return this.useVideoStream(null);
});
}
return promise.then(
@@ -1540,6 +1576,8 @@ export default {
},
error => {
this.videoSwitchInProgress = false;
logger.error(`_turnScreenSharingOff failed: ${error}`);
throw error;
});
},
@@ -1560,6 +1598,7 @@ export default {
* @return {Promise.<T>}
*/
async toggleScreenSharing(toggle = !this._untoggleScreenSharing, options = {}) {
logger.debug(`toggleScreenSharing: ${toggle}`);
if (this.videoSwitchInProgress) {
return Promise.reject('Switch in progress.');
}
@@ -1626,6 +1665,8 @@ export default {
desktopVideoStream.on(
JitsiTrackEvents.LOCAL_TRACK_STOPPED,
() => {
logger.debug(`Local screensharing track stopped. ${this.isSharingScreen}`);
// If the stream was stopped during screen sharing
// session then we should switch back to video.
this.isSharingScreen
@@ -1729,7 +1770,7 @@ export default {
};
}
// Apply the contraints on the desktop track.
// Apply the constraints on the desktop track.
try {
await this.localVideo.track.applyConstraints(desktopResizeConstraints);
} catch (err) {
@@ -1790,6 +1831,7 @@ export default {
const desktopVideoStream = streams.find(stream => stream.getType() === MEDIA_TYPE.VIDEO);
if (desktopVideoStream) {
logger.debug(`_switchToScreenSharing is using ${desktopVideoStream} for useVideoStream`);
await this.useVideoStream(desktopVideoStream);
}
@@ -1919,7 +1961,7 @@ export default {
}
APP.store.dispatch(updateRemoteParticipantFeatures(user));
logger.log(`USER ${id} connnected:`, user);
logger.log(`USER ${id} connected:`, user);
APP.UI.addUser(user);
});
@@ -1993,7 +2035,11 @@ export default {
room.on(JitsiConferenceEvents.TRACK_MUTE_CHANGED, (track, participantThatMutedUs) => {
if (participantThatMutedUs) {
APP.store.dispatch(participantMutedUs(participantThatMutedUs));
APP.store.dispatch(participantMutedUs(participantThatMutedUs, track));
if (this.isSharingScreen && track.isVideoTrack()) {
logger.debug('TRACK_MUTE_CHANGED while screen sharing');
this._turnScreenSharingOff(false);
}
}
});
@@ -2145,8 +2191,26 @@ export default {
}
);
room.on(JitsiConferenceEvents.STARTED_MUTED, () => {
(room.isStartAudioMuted() || room.isStartVideoMuted())
&& APP.UI.notifyInitiallyMuted();
const audioMuted = room.isStartAudioMuted();
const videoMuted = room.isStartVideoMuted();
const localTracks = getLocalTracks(APP.store.getState()['features/base/tracks']);
const promises = [];
APP.store.dispatch(setAudioMuted(audioMuted));
APP.store.dispatch(setVideoMuted(videoMuted));
// Remove the tracks from the peerconnection.
for (const track of localTracks) {
if (audioMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.AUDIO) {
promises.push(this.useAudioStream(null));
}
if (videoMuted && track.jitsiTrack?.getType() === MEDIA_TYPE.VIDEO) {
promises.push(this.useVideoStream(null));
}
}
Promise.allSettled(promises)
.then(() => APP.UI.notifyInitiallyMuted());
});
room.on(
@@ -2172,7 +2236,7 @@ export default {
});
APP.UI.addListener(UIEvents.AUTH_CLICKED, () => {
AuthHandler.authenticate(room);
AuthHandler.authenticateExternal(room);
});
APP.UI.addListener(
@@ -2197,7 +2261,7 @@ export default {
.then(effect => this.localVideo.setEffect(effect))
.then(() => {
this.setVideoMuteStatus(false);
logger.log('switched local video device');
logger.log('Switched local video device while screen sharing and the video is unmuted');
this._updateVideoDeviceId();
})
.catch(err => APP.store.dispatch(notifyCameraError(err)));
@@ -2206,7 +2270,7 @@ export default {
// id for video, dispose the existing presenter track and create a new effect
// that can be applied on un-mute.
} else if (this.isSharingScreen && videoWasMuted) {
logger.log('switched local video device');
logger.log('Switched local video device: while screen sharing and the video is muted');
const { height } = this.localVideo.track.getSettings();
this._updateVideoDeviceId();
@@ -2233,12 +2297,20 @@ export default {
return stream;
})
.then(stream => this.useVideoStream(stream))
.then(stream => {
logger.log('Switching the local video device.');
return this.useVideoStream(stream);
})
.then(() => {
logger.log('switched local video device');
logger.log('Switched local video device.');
this._updateVideoDeviceId();
})
.catch(err => APP.store.dispatch(notifyCameraError(err)));
.catch(error => {
logger.error(`Switching the local video device failed: ${error}`);
return APP.store.dispatch(notifyCameraError(error));
});
}
}
);
@@ -2327,7 +2399,11 @@ export default {
// There is no guarantee another event will trigger the update
// immediately and in all situations, for example because a remote
// participant is having connection trouble so no status changes.
APP.UI.updateAllVideos();
const displayedUserId = APP.UI.getLargeVideoID();
if (displayedUserId) {
APP.UI.updateLargeVideo(displayedUserId, true);
}
});
APP.UI.addListener(
@@ -2590,6 +2666,7 @@ export default {
delete newDevices.videoinput;
// Removing the current video track in order to force the unmute to select the preferred device.
logger.debug('_onDeviceListChanged: Removing the current video track.');
this.useVideoStream(null);
}

View File

@@ -123,7 +123,7 @@ var config = {
// opusMaxAverageBitrate: 20000,
// Enables support for opus-red (redundancy for Opus).
// enableOpusRed: false
// enableOpusRed: false,
// Video
@@ -240,6 +240,12 @@ var config = {
// 90: 2
// },
// Provides a way to translate the legacy bridge signaling messages, 'LastNChangedEvent',
// 'SelectedEndpointsChangedEvent' and 'ReceiverVideoConstraint' into the new 'ReceiverVideoConstraints' message
// that invokes the new bandwidth allocation algorithm in the bridge which is described here
// - https://github.com/jitsi/jitsi-videobridge/blob/master/doc/allocation.md.
// useNewBandwidthAllocationStrategy: false,
// Specify the settings for video quality optimizations on the client.
// videoQuality: {
// // Provides a way to prevent a video codec from being negotiated on the JVB connection. The codec specified
@@ -406,7 +412,26 @@ var config = {
// enableAutomaticUrlCopy: false,
// Base URL for a Gravatar-compatible service. Defaults to libravatar.
// gravatarBaseURL: 'https://seccdn.libravatar.org/avatar/';
// gravatarBaseURL: 'https://seccdn.libravatar.org/avatar/',
// Moved from interfaceConfig(TOOLBAR_BUTTONS).
// The name of the toolbar buttons to display in the toolbar, including the
// "More actions" menu. If present, the button will display. Exceptions are
// "livestreaming" and "recording" which also require being a moderator and
// some other values in config.js to be enabled. Also, the "profile" button will
// not display for users with a JWT.
// Notes:
// - it's impossible to choose which buttons go in the "More actions" menu
// - it's impossible to control the placement of buttons
// - 'desktop' controls the "Share your screen" button
// - if `toolbarButtons` is undefined, we fallback to enabling all buttons on the UI
// toolbarButtons: [
// 'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
// 'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
// 'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
// 'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
// 'tileview', 'select-background', 'download', 'help', 'mute-everyone', 'mute-video-everyone', 'security'
// ],
// Stats
//
@@ -431,6 +456,10 @@ var config = {
// Enables sending participants' emails (if available) to callstats and other analytics
// enableEmailInStats: false,
// Controls the percentage of automatic feedback shown to participants when callstats is enabled.
// The default value is 100%. If set to 0, no automatic feedback will be requested
// feedbackPercentage: 100,
// Privacy
//
@@ -469,7 +498,7 @@ var config = {
// If set to true, it will prefer to use H.264 for P2P calls (if H.264
// is supported). This setting is deprecated, use preferredCodec instead.
// preferH264: true
// preferH264: true,
// Provides a way to set the video codec preference on the p2p connection. Acceptable
// codec values are 'VP8', 'VP9' and 'H264'.
@@ -511,7 +540,7 @@ var config = {
// The interval at which rtcstats will poll getStats, defaults to 1000ms.
// If the value is set to 0 getStats won't be polled and the rtcstats client
// will only send data related to RTCPeerConnection events.
// rtcstatsPolIInterval: 1000
// rtcstatsPolIInterval: 1000,
// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
// scriptURLs: [
@@ -534,6 +563,10 @@ var config = {
// Decides whether the start/stop recording audio notifications should play on record.
// disableRecordAudioNotification: false,
// Disables the sounds that play when other participants join or leave the
// conference (if set to true, these sounds will not be played).
// disableJoinLeaveSounds: false,
// Information for the chrome extension banner
// chromeExtensionBanner: {
// // The chrome extension to be installed address
@@ -593,6 +626,10 @@ var config = {
// the menu has option to flip the locally seen video for local presentations
// disableLocalVideoFlip: false,
// A property used to unset the default flip state of the local video.
// When it is set to 'true', the local(self) video will not be mirrored anymore.
// doNotFlipLocalVideo: false,
// Mainly privacy related settings
// Disables all invite functions from the app (share, invite, dial out...etc)
@@ -640,6 +677,9 @@ var config = {
*/
// dynamicBrandingUrl: '',
// Sets the background transparency level. '0' is fully transparent, '1' is opaque.
// backgroundAlpha: 1,
// The URL of the moderated rooms microservice, if available. If it
// is present, a link to the service will be rendered on the welcome page,
// otherwise the app doesn't render it.
@@ -649,17 +689,22 @@ var config = {
// disableTileView: true,
// Hides the conference subject
// hideConferenceSubject: true
// hideConferenceSubject: true,
// Hides the conference timer.
// hideConferenceTimer: true,
// Hides the participants stats
// hideParticipantsStats: true
// hideParticipantsStats: true,
// Sets the conference subject
// subject: 'Conference Subject',
// This property is related to the use case when jitsi-meet is used via the IFrame API. When the property is true
// jitsi-meet will use the local storage of the host page instead of its own. This option is useful if the browser
// is not persisting the local storage inside the iframe.
// useHostPageLocalStorage: true,
// List of undocumented settings used in jitsi-meet
/**
_immediateReloadThreshold

View File

@@ -3,18 +3,21 @@
import { jitsiLocalStorage } from '@jitsi/js-utils';
import Logger from 'jitsi-meet-logger';
import AuthHandler from './modules/UI/authentication/AuthHandler';
import { redirectToTokenAuthService } from './modules/UI/authentication/AuthHandler';
import { hideLoginDialog } from './react/features/authentication/actions.web';
import { LoginDialog } from './react/features/authentication/components';
import { isTokenAuthEnabled } from './react/features/authentication/functions';
import {
connectionEstablished,
connectionFailed
} from './react/features/base/connection/actions';
import { openDialog } from './react/features/base/dialog/actions';
import {
isFatalJitsiConnectionError,
JitsiConnectionErrors,
JitsiConnectionEvents
} from './react/features/base/lib-jitsi-meet';
import { setPrejoinDisplayNameRequired } from './react/features/prejoin/actions';
const logger = Logger.getLogger(__filename);
/**
@@ -80,7 +83,7 @@ function checkForAttachParametersAndConnect(id, password, connection) {
* @returns {Promise<JitsiConnection>} connection if
* everything is ok, else error.
*/
function connect(id, password, roomName) {
export function connect(id, password, roomName) {
const connectionConfig = Object.assign({}, config);
const { jwt } = APP.store.getState()['features/base/jwt'];
@@ -214,10 +217,39 @@ export function openConnection({ id, password, retry, roomName }) {
const { jwt } = APP.store.getState()['features/base/jwt'];
if (err === JitsiConnectionErrors.PASSWORD_REQUIRED && !jwt) {
return AuthHandler.requestAuth(roomName, connect);
return requestAuth(roomName);
}
}
throw 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
*
* @returns {Promise<JitsiConnection>}
*/
function requestAuth(roomName) {
const config = APP.store.getState()['features/base/config'];
if (isTokenAuthEnabled(config)) {
// This Promise never resolves as user gets redirected to another URL
return new Promise(() => redirectToTokenAuthService(roomName));
}
return new Promise(resolve => {
const onSuccess = connection => {
APP.store.dispatch(hideLoginDialog());
resolve(connection);
};
APP.store.dispatch(
openDialog(LoginDialog, { onSuccess,
roomName })
);
});
}

View File

@@ -1,3 +1,21 @@
/**
* Mixins that mimic the way Atlaskit fills the screen with modals at low screen widths.
*/
@mixin full-size-modal-positioner() {
height: 100%;
left: 0;
position: fixed;
top: 0;
max-width: 100%;
width: 100%;
}
@mixin full-size-modal-dialog() {
height: 100%;
max-height: 100%;
border-radius: 0;
}
/**
* Move the @atlaskit/flag container up a little bit so it does not cover the
* toolbar with the first notification.
@@ -54,6 +72,63 @@
* Keep overflow menu within screen vertical bounds and make it scrollable.
*/
.toolbox-button-wth-dialog > div:nth-child(2) {
background: $menuBG;
max-height: calc(100vh - #{$newToolbarSizeWithPadding} - 46px);
margin-bottom: 4px;
padding: 0;
overflow-y: auto;
}
}
.audio-preview > div:nth-child(2),
.video-preview > div:nth-child(2) {
margin-bottom: 4px;
outline: none;
padding: 0;
}
/**
* The following selectors keep the chat modal full-size anywhere between 100px
* and 580px for desktop or 680px for mobile.
*/
@media (min-width: 100px) and (max-width: 320px) {
.smiley-input {
display: none;
}
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 480px) and (max-width: 580px) {
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (max-width: 580px) {
// Override Atlaskit inline style for the modal background.
// Important is unfortunately needed for that.
.shift-right .focus-lock [role="dialog"][style] {
background-color: $chatBackgroundColor !important;
}
// Remove Atlaskit padding from the chat dialog.
.shift-right .focus-lock [role="dialog"] > div:first-child > div:nth-child(2) {
padding: 0;
}
}
div.Tooltip {
color: #fff;
font-size: 12px;
line-height: 14px;
padding: 8px;
}

View File

@@ -1,26 +1,37 @@
.audio-preview {
display: inline-block;
&-content {
background: #2A3A4B;
font-size: 15px;
background: $menuBG;
border-radius: 3px;
font-size: 14px;
line-height: 24px;
max-height: 456px;
overflow: auto;
width: 328px;
width: 300px;
}
&-header {
color: #fff;
align-items: center;
display: flex;
padding: 16px;
margin-top: 8px;
padding: 8px 16px;
&-icon {
color: #A4B8D1;
display: inline-block;
svg {
fill: #fff;
}
}
&--bordered {
border-bottom: 1px solid #4C4D50;
}
&-text {
font-weight: bold;
margin-left: 8px;
margin-left: 12px;
}
}
@@ -29,19 +40,18 @@
color: #fff;
cursor: pointer;
display: flex;
padding: 12px 0;
padding: 8px 0;
margin-left: 48px;
&--selected {
background: #1C2025;
background: #131519;
cursor: initial;
margin-left: 0;
padding-left: 21px;
padding-left: 18px;
}
&-text {
color: #fff;
font-size: 15px;
display: inline-block;
line-height: 24px;
text-overflow: ellipsis;
@@ -56,12 +66,13 @@
&:hover {
.audio-preview-entry {
background: #3F4E5E;
background: #36383C;
margin-left: 0;
padding-left: 48px;
&--selected {
padding-left: 21px;
padding-left: 18px;
background: $newToolbarBackgroundColor;
}
}
@@ -74,6 +85,10 @@
}
}
&:last-child {
padding-bottom: 8px;
}
.audio-preview-entry-text {
max-width: 256px;
}
@@ -84,18 +99,19 @@
&:hover {
.audio-preview-entry {
background: #3F4E5E;
background: #36383C;
margin-left: 0;
padding-left: 48px;
&--selected {
padding-left: 21px;
background: $newToolbarBackgroundColor;
padding-left: 18px;
}
}
}
.audio-preview-entry-text {
max-width: 196px;
max-width: 178px;
}
}
@@ -110,7 +126,7 @@
&--check {
background: #31B76A;
margin-right: 13px;
margin-right: 16px;
}
&--exclamation {
@@ -121,6 +137,11 @@
}
}
&-hr {
border-top: 1px solid #4C4D50;
border-bottom: 0;
}
&-test-button {
display: none;
background: #FFF;
@@ -129,23 +150,16 @@
color: #1C2025;
cursor: pointer;
font-weight: 600;
font-size: 15px;
line-height: 24px;
padding: 4px 16px;
padding: 2px 16px;
position: absolute;
right: 16px;
top: 8px;
top: 5px;
}
&-meter-mic {
position: absolute;
right: 16px;
top: 18px;
}
// Override @atlaskit/InlineDialog container which is made with styled components
& > div:nth-child(2) {
outline: none;
padding: 0;
top: 14px;
}
}

View File

@@ -55,6 +55,10 @@ body {
fill: white;
}
.disabled .jitsi-icon svg {
fill: #929292;
}
.jitsi-icon.gray svg {
fill: #5E6D7A;
cursor: pointer;

View File

@@ -1,5 +1,5 @@
#sideToolbarContainer {
background-color: $newToolbarBackgroundColor;
background-color: $chatBackgroundColor;
box-sizing: border-box;
color: #FFF;
display: flex;
@@ -32,6 +32,13 @@
width: $sidebarWidth;
word-wrap: break-word;
display: flex;
flex-direction: column;
& > :first-child {
margin-top: auto;
}
a {
display: block;
}
@@ -98,13 +105,12 @@
}
.chat-header {
background-color: $chatHeaderBackgroundColor;
height: 70px;
position: relative;
width: 100%;
z-index: 1;
display: flex;
justify-content: space-between;
justify-content: flex-end;
padding: 16px;
align-items: center;
box-sizing: border-box;
@@ -116,22 +122,85 @@
.jitsi-icon {
cursor: pointer;
}
}
.jitsi-icon > svg {
fill: #A4B8D1;
.chat-input-container {
padding: 0 16px 16px;
&.populated {
#chat-input {
.send-button {
background: #1B67EC;
cursor: pointer;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: #3D82FB;
}
}
&:active {
background: #0852D4;
}
path {
fill: #fff;
}
}
}
}
}
#chat-input {
border-top: 1px solid $chatInputSeparatorColor;
border: 1px solid $chatInputSeparatorColor;
display: flex;
padding: 5px 10px;
padding: 4px;
border-radius: 3px;
&:focus-within {
border: 1px solid #619CF4;
}
* {
background-color: transparent;
}
}
.send-button-container {
display: flex;
align-items: center;
}
.send-button {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
border-radius: 3px;
path {
fill: $chatInputSeparatorColor;
}
}
.smiley-button {
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
border-radius: 3px;
}
#chat-input .smiley-button {
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: #484A4F;
}
}
}
.remoteuser {
color: #B8C7E0;
}
@@ -145,7 +214,7 @@
border-radius:0;
box-shadow: none;
color: white;
font-size: 15px;
font-size: 14px;
padding: 10px;
overflow-y: auto;
resize: none;
@@ -161,10 +230,55 @@
#nickname {
text-align: center;
color: #9d9d9d;
font-size: 18px;
margin-top: 30px;
left: 5px;
right: 5px;
font-size: 16px;
margin: auto 0;
padding: 0 16px;
input {
height: 40px;
}
label {
line-height: 24px;
}
.enter-chat {
display: flex;
align-items: center;
justify-content: center;
margin-top: 16px;
height: 40px;
background: #1B67EC;
border-radius: 3px;
color: #fff;
cursor: pointer;
&.disabled {
color: #757575;
background: #11336E;
pointer-events: none;
}
}
}
.mobile-browser {
#nickname {
input {
height: 48px;
}
.enter-chat {
height: 48px;
}
}
#usermsg {
font-size: 16px;
}
.chatmessage .usermessage {
font-size: 16px;
}
}
.sideToolbarContainer {
@@ -174,8 +288,8 @@
}
.display-name {
font-size: 13px;
font-weight: bold;
font-size: 12px;
font-weight: 600;
margin-bottom: 5px;
white-space: nowrap;
text-overflow: ellipsis;
@@ -203,6 +317,7 @@
.usermessage {
white-space: pre-wrap;
font-size: 14px;
}
&.error {
@@ -225,12 +340,16 @@
}
.messagecontent {
margin: 5px 10px;
margin: 8px;
max-width: 100%;
overflow: hidden;
}
}
.timestamp {
color: #757575;
}
.smiley {
font-size: 14pt;
}
@@ -266,7 +385,9 @@
max-height: 0;
overflow: hidden;
position: absolute;
width: $sidebarWidth;
width: calc(#{$sidebarWidth} - 32px);
margin-bottom: 5px;
margin-left: -5px;
/**
* CSS transitions do not apply for auto dimensions. So to produce the css
@@ -281,9 +402,8 @@
}
#smileysContainer {
background-color: $newToolbarBackgroundColor;
border-bottom: 1px solid;
border-top: 1px solid;
background-color: $chatBackgroundColor;
border-top: 1px solid $chatInputSeparatorColor;
}
}
@@ -389,9 +509,9 @@
&-header {
display: flex;
justify-content: space-between;
justify-content: flex-end;
align-items: center;
margin: 16px 16px 24px;
margin: 16px;
width: calc(100% - 32px);
box-sizing: border-box;
color: #fff;
@@ -402,10 +522,6 @@
.jitsi-icon {
cursor: pointer;
}
.jitsi-icon > svg {
fill: #A4B8D1;
}
}
#chatconversation {
@@ -413,6 +529,12 @@
}
}
.touchmove-hack {
display: flex;
flex: 1;
overflow: auto;
}
/**
* Make header close button more easily tappable on mobile.
*/
@@ -421,6 +543,6 @@
place-items: center;
height: 48px;
width: 48px;
background: #2a3a4b;
background: #36383C;
border-radius: 3px;
}

View File

@@ -7,7 +7,6 @@
}
.drawer-menu {
padding: 0 16px;
max-height: 50vh;
background: #242528;
border-radius: 16px 16px 0 0;
@@ -24,12 +23,6 @@
height: 44px;
cursor: pointer;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $overflowMenuItemHoverBG;
}
}
svg {
fill: none;
}
@@ -67,13 +60,6 @@
align-items: center;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $overflowMenuItemHoverBG;
color: $overflowMenuItemHoverColor;
}
}
&.unclickable {
cursor: default;
}
@@ -88,42 +74,6 @@
}
}
.beta-tag {
background: $overflowMenuItemColor;
border-radius: 2px;
color: $overflowMenuBG;
font-size: 11px;
font-weight: bold;
margin-left: 8px;
padding: 0 6px;
}
.overflow-menu-item-icon {
margin-right: 16px;
i {
display: inline;
font-size: 24px;
}
@media (hover: hover) and (pointer: fine) {
i:hover {
background-color: initial;
}
}
img {
max-width: 24px;
max-height: 24px;
}
svg {
fill: #B8C7E0 !important;
height: 20px;
width: 20px;
}
}
.profile-text {
max-width: 100%;
text-overflow: ellipsis;

View File

@@ -9,7 +9,7 @@
.spinner {
margin: 30px;
}
.joining-message {
margin: 10px;
}
@@ -49,7 +49,7 @@
position: fixed;
top: 20;
transition: top 1s ease;
z-index: 100;
z-index: $toolbarZ + 1;
&.toolbox-visible {
// Same as toolbox subject position
@@ -62,31 +62,6 @@
padding: 15px
}
ul {
list-style-type: none;
padding: 0 15px 15px 15px;
li {
align-items: center;
display: flex;
flex-direction: row;
margin: 8px 0;
.details {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-evenly;
margin: 0 30px 0 10px;
}
button {
align-self: unset;
margin: 0 5px;
}
}
}
button {
align-self: stretch;
margin: 8px 0;
@@ -116,3 +91,50 @@
}
}
}
.knocking-participants-container {
list-style-type: none;
max-height: 600px;
overflow-y: scroll;
padding: 0 15px 15px 15px;
}
.knocking-participant {
align-items: center;
display: flex;
flex-direction: row;
margin: 8px 0;
.details {
display: flex;
flex: 1;
flex-direction: column;
justify-content: space-evenly;
margin: 0 30px 0 10px;
}
button {
align-self: unset;
margin: 0 5px;
}
}
@media (max-width: 300px) {
#knocking-participant-list {
margin: 0;
text-align: center;
width: 100%;
.avatar {
display: none;
}
}
.knocking-participant {
flex-direction: column;
.details {
margin: 0;
}
}
}

View File

@@ -23,44 +23,10 @@
flex-direction: row;
left: 50%;
position: absolute;
top: 10px;
bottom: 10px;
transform: translateX(-50%);
.toolbox-button {
&:first-child {
.toolbox-icon {
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
}
&:nth-child(2) {
svg {
fill: $hangupColor;
}
}
&:last-child {
.toolbox-icon {
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
}
}
}
.filmstrip-toolbox {
flex-direction: column;
.toolbox-button {
&:nth-child(1) {
svg {
fill: $hangupColor;
}
}
.toolbox-icon {
border-radius: 3px;
}
}
}
}

View File

@@ -3,10 +3,11 @@
**/
.popupmenu {
min-width: 75px;
background-color: $menuBG;
border-radius: 3px;
min-width: 150px;
text-align: left;
padding: 0px;
width: 180px;
white-space: nowrap;
&__item {
@@ -39,6 +40,7 @@
&__text {
display: inline-block;
margin-left: 8px;
vertical-align: middle;
}
@@ -110,6 +112,6 @@ ul.popupmenu {
margin: -16px -24px;
}
span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
span.localvideomenu:hover ul.popupmenu, span.remotevideomenu:hover ul.popupmenu, ul.popupmenu:hover {
display:block !important;
}

View File

@@ -25,7 +25,7 @@
text {
fill: black;
font-size: 26px;
font-weight: 400;
font-weight: 400;
}
}
@@ -197,14 +197,6 @@
&> div {
margin: 0 12px;
}
.settings-button-small-icon {
right: -8px;
&--hovered {
right: -10px;
}
}
}
}

View File

@@ -1,73 +1,3 @@
@mixin small-button-size() {
.new-toolbox {
.toolbox-content {
.button-group-center, .button-group-left, .button-group-right {
.toolbox-button {
.toolbox-icon {
width: 28px;
height: 28px;
svg {
width: 18px;
height: 18px;
}
}
&:nth-child(2) {
.toolbox-icon {
width: 30px;
height: 30px;
}
}
}
}
}
}
}
@mixin very-small-button-size() {
.new-toolbox {
.toolbox-content {
.button-group-center, .button-group-left, .button-group-right {
.settings-button-small-icon {
display: none;
}
.toolbox-button {
.toolbox-icon {
width: 18px;
height: 18px;
svg {
width: 12px;
height: 12px;
}
}
&:nth-child(2) {
.toolbox-icon {
width: 20px;
height: 20px;
}
}
}
}
}
}
}
@mixin full-size-modal-positioner() {
height: 100%;
left: 0;
position: fixed;
top: 0;
max-width: 100%;
width: 100%;
}
@mixin full-size-modal-dialog() {
height: 100%;
max-height: 100%;
border-radius: 0;
}
@media only screen and (max-width: $verySmallScreen) {
.welcome {
display: block;
@@ -137,21 +67,9 @@
}
.desktop-browser {
@media only screen and (max-width: $smallScreen) {
@include small-button-size();
}
@media only screen and (max-width: $verySmallScreen) {
@include very-small-button-size();
}
&.shift-right {
@media only screen and (max-width: $smallScreen + $sidebarWidth) {
@include small-button-size()
}
@media only screen and (max-width: $verySmallScreen + $sidebarWidth) {
@include very-small-button-size();
#videoResolutionLabel {
display: none;
@@ -165,25 +83,3 @@
}
}
}
@media (min-width: 480px) and (max-width: 580px) {
.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
@media (min-width: 580px) and (max-width: 680px) {
.mobile-browser {
&.shift-right .focus-lock > div > div {
@include full-size-modal-positioner();
}
&.shift-right .focus-lock [role="dialog"] {
@include full-size-modal-dialog();
}
}
}

View File

@@ -1,84 +1,62 @@
.settings-button {
&-container {
position: relative;
.settings-button-container {
position: relative;
.toolbox-icon {
align-items: center;
cursor: pointer;
display: flex;
background-color: #fff;
border-radius: 50%;
border: 1px solid #d1dbe8;
justify-content: center;
width: 38px;
height: 38px;
.toolbox-icon {
align-items: center;
border-radius: 3px;
cursor: pointer;
display: flex;
justify-content: center;
&.disabled, .disabled & {
cursor: initial;
color: #929292;
background-color: #36383c;
&:hover {
background-color: #daebfa;
border: 1px solid #daebfa;
}
&.toggled {
background: #2a3a4b;
border: 1px solid #5e6d7a;
svg {
fill: #fff;
}
&:hover {
background-color: #5e6d7a;
}
}
&.disabled, .disabled & {
cursor: initial;
color: #fff;
background-color: #a4b8d1;
&:hover {
background-color: #a4b8d1;
}
}
svg {
fill: #5e6d7a;
}
}
}
&-small-icon {
background: #FFF;
border: 1px solid rgba(0, 0, 0, 0.2);
border-radius: 50%;
bottom: 0;
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.25);
cursor: pointer;
height: 16px;
position: absolute;
text-align: center;
right: 4px;
width: 16px;
&> svg {
fill: #5e6d7a;
margin-top: 5px;
}
&--disabled {
background-color: #a4b8d1;
cursor: default;
}
&--hovered {
bottom: -1px;
height: 20px;
right: 2px;
width: 20px;
&> svg {
margin-top: 6px;
background-color: #36383c;
}
}
}
}
.settings-button-small-icon {
background: #36383C;
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
border-radius: 3px;
cursor: pointer;
padding: 4px;
position: absolute;
right: -4px;
top: -3px;
&:hover {
background: #F2F3F4;
box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.1);
&> svg {
fill: #000;
}
&.settings-button-small-icon--disabled {
background: #36383C;
&> svg {
fill: #929292;
}
}
}
&> svg {
fill: #fff;
}
&--disabled {
background-color: #36383c;
cursor: default;
&> svg {
fill: #929292;
}
}
}

View File

@@ -33,9 +33,6 @@
&.visible {
bottom: 0;
.toolbox-background {
bottom: 0px;
}
}
&.no-buttons {
@@ -48,253 +45,233 @@
width: calc(100% - #{$sidebarWidth});
}
}
}
.toolbox-background {
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.6), rgba(0, 0, 0, 0));
transition: bottom .3s ease-in;
height: 160px;
width: 100%;
bottom: -160px;
pointer-events: none;
position: absolute;
z-index: $toolbarBackgroundZ;
.toolbox-content {
align-items: center;
box-sizing: border-box;
display: flex;
margin-bottom: 16px;
position: relative;
z-index: $toolbarZ;
.button-group-center,
.button-group-left,
.button-group-right {
display: flex;
width: 33%;
}
.toolbox-content {
box-sizing: border-box;
.button-group-center {
justify-content: center;
}
.button-group-right {
justify-content: flex-end;
}
.toolbox-button-wth-dialog {
display: inline-block;
}
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
display: inline-block;
line-height: $newToolbarSize;
text-align: center;
}
.toolbar-button-with-badge {
display: inline-block;
position: relative;
.badge-round {
bottom: -5px;
font-size: 12px;
line-height: 20px;
min-width: 20px;
pointer-events: none;
position: absolute;
right: -5px;
}
}
.toolbox-content-wrapper {
display: flex;
flex-direction: column;
margin: 0 auto;
max-width: 100%;
}
.toolbox-content-items {
background: $newToolbarBackgroundColor;
box-shadow: 0px 2px 8px 4px rgba(0, 0, 0, 0.25), 0px 0px 0px 1px rgba(0, 0, 0, 0.15);
border-radius: 6px;
margin: 0 auto;
padding: 6px;
text-align: center;
>div {
margin-left: 8px;
&:first-child {
margin-left: 0;
}
}
}
.overflow-menu {
font-size: 14px;
list-style-type: none;
padding: 8px 0;
background-color: $menuBG;
.profile-text {
max-width: 150px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
.overflow-menu-item {
align-items: center;
color: $overflowMenuItemColor;
cursor: pointer;
display: flex;
font-size: 14px;
font-weight: 400;
height: 40px;
line-height: 24px;
padding: 8px 16px;
box-sizing: border-box;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: $overflowMenuItemBackground;
}
}
div {
display: flex;
justify-content: space-between;
margin-left: auto;
margin-right: auto;
padding: 20px 16px;
position: relative;
width: 100%;
z-index: $toolbarZ;
flex-direction: row;
align-items: center;
}
.button-group-center,
.button-group-left,
.button-group-right {
display: flex;
width: 33%;
&.unclickable {
cursor: default;
}
&.disabled {
cursor: initial;
color: #929292;
&:hover {
background: none;
}
.button-group-center {
justify-content: center;
.toolbox-button {
.toolbox-icon {
background-color: #fff;
border-radius: 50%;
border: 1px solid #d1dbe8;
margin: 0px 4px;
width: 38px;
height: 38px;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: #daebfa;
border: 1px solid #daebfa;
}
}
&.toggled {
background: #2a3a4b;
border: 1px solid #5e6d7a;
svg {
fill: #fff;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: #5e6d7a;
}
}
}
&.disabled, .disabled & {
cursor: initial;
color: #fff;
background-color: #a4b8d1;
}
svg {
fill: #5e6d7a;
}
}
&:nth-child(2) {
.toolbox-icon {
background-color: $hangupColor;
border: 1px solid $hangupColor;
width: 40px;
height: 40px;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $hangupColor;
}
}
svg {
fill: #fff;
}
}
}
}
svg {
fill: #929292;
}
.button-group-right {
justify-content: flex-end;
}
@media (hover: hover) and (pointer: fine) {
&.unclickable:hover {
background: inherit;
}
}
}
.overflow-menu {
font-size: 1.2em;
list-style-type: none;
background-color: $overflowMenuBG;
/**
* Undo atlaskit padding by reducing margins.
*/
margin: -16px -24px;
padding: 4px 0;
.beta-tag {
background: #36383C;
border-radius: 3px;
color: #fff;
font-size: 12px;
margin-left: 8px;
padding: 0 4px;
text-transform: uppercase;
}
.overflow-menu-item {
align-items: center;
color: $overflowMenuItemColor;
cursor: pointer;
display: flex;
font-size: 14px;
height: 40px;
padding: 5px 12px;
box-sizing: border-box;
.overflow-menu-item-icon {
margin-right: 16px;
div {
display: flex;
flex-direction: row;
align-items: center;
}
i {
display: inline;
font-size: 24px;
}
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $overflowMenuItemHoverBG;
color: $overflowMenuItemHoverColor;
}
}
&.unclickable {
cursor: default;
}
@media (hover: hover) and (pointer: fine) {
&.unclickable:hover {
background: inherit;
}
}
&.disabled {
cursor: initial;
color: #3b475c;
}
}
.beta-tag {
background: $overflowMenuItemColor;
border-radius: 2px;
color: $overflowMenuBG;
font-size: 11px;
font-weight: bold;
margin-left: 8px;
padding: 0 6px;
}
.overflow-menu-item-icon {
margin-right: 16px;
i {
display: inline;
font-size: 24px;
}
@media (hover: hover) and (pointer: fine) {
i:hover {
background-color: initial;
}
}
img {
max-width: 24px;
max-height: 24px;
}
svg {
fill: #B8C7E0 !important;
height: 20px;
width: 20px;
}
}
.profile-text {
max-width: 150px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
@media (hover: hover) and (pointer: fine) {
i:hover {
background-color: initial;
}
}
.toolbox-button {
color: $toolbarButtonColor;
cursor: pointer;
display: inline-block;
line-height: $newToolbarSize;
margin: 0 8px;
text-align: center;
img {
max-width: 24px;
max-height: 24px;
}
svg {
fill: #fff;
height: 20px;
width: 20px;
}
}
.overflow-menu-hr {
border-top: 1px solid #4C4D50;
border-bottom: 0;
margin: 8px 0;
}
.toolbox-icon {
display: flex;
border-radius: 3px;
flex-direction: column;
font-size: 24px;
height: $newToolbarSize;
justify-content: center;
width: $newToolbarSize;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: $newToolbarButtonHoverColor;
}
}
.toolbar-button-with-badge {
position: relative;
@media (max-width: 320px) {
height: 36px;
width: 36px;
}
.badge-round {
bottom: -5px;
font-size: 12px;
line-height: 20px;
min-width: 20px;
pointer-events: none;
position: absolute;
right: -5px;
}
&.toggled {
background: $newToolbarButtonToggleColor;
}
&.disabled {
cursor: initial !important;
background-color: #36383c !important;
svg {
fill: #929292 !important;
}
}
}
.toolbox-button-wth-dialog {
display: inline-block;
.hangup-button {
background-color: $hangupColor;
@media (hover: hover) and (pointer: fine) {
&:hover {
background-color: $hangupHoverColor;
}
}
.toolbox-icon {
display: flex;
border-radius: 5px;
flex-direction: column;
font-size: 24px;
height: $newToolbarSize;
justify-content: center;
width: $newToolbarSize;
@media (hover: hover) and (pointer: fine) {
&:hover {
background: $newToolbarButtonHoverColor;
}
}
&.toggled {
background: $newToolbarButtonHoverColor;
}
&.disabled {
cursor: initial !important;
background-color: #a4b8d1 !important;
svg {
fill: #fff !important;
}
}
}
svg {
fill: #fff;
}
}
@@ -312,3 +289,47 @@
@include transition(all .3s ease-out);
}
/**
* Audio and video buttons do not have toggled state.
*/
.audio-preview,
.video-preview {
.toolbox-icon.toggled {
background: none;
&:hover {
background: $newToolbarButtonHoverColor;
}
}
}
/**
* On small mobile devices make the toolbar full width and pad the invite prompt.
*/
.toolbox-content-mobile {
@media (max-width: 500px) {
margin-bottom: 0;
.toolbox-content-wrapper {
width: 100%;
}
.toolbox-content-items {
border-radius: 0;
display: flex;
justify-content: space-evenly;
padding: 6px 0;
width: 100%;
}
.invite-more-container {
margin: 0 16px 8px;
}
.invite-more-container.elevated {
margin-bottom: 52px;
}
}
}

View File

@@ -1,10 +1,11 @@
.transcription-subtitles{
bottom: 10%;
.transcription-subtitles {
bottom: $newToolbarSize + 40px;
font-size: 16px;
font-weight: 1000;
left: 50%;
max-width: 50vw;
opacity: 0.80;
overflow-wrap: break-word;
pointer-events: none;
position: absolute;
text-shadow: 0px 0px 1px rgba(0,0,0,0.3),
@@ -14,6 +15,11 @@
transform: translateX(-50%);
z-index: $subtitlesZ;
&.lifted {
// Lift subtitle above toolbar+invite box.
bottom: $newToolbarSize + 112px + 40px;
}
span {
background: black;
}

View File

@@ -4,7 +4,8 @@
* Style variables
*/
$baseFontFamily: -apple-system, BlinkMacSystemFont, 'open_sanslight', 'Helvetica Neue', Helvetica, Arial, sans-serif;
$hangupColor: #bf2117;
$hangupColor:#DD3849;
$hangupHoverColor: #F25363;
$hangupFontSize: 2em;
/**
@@ -37,20 +38,20 @@ $presence-idle: rgb(172, 172, 172);
/**
* Toolbar
*/
$newToolbarBackgroundColor: rgba(22, 38, 55, 0.8);
$newToolbarButtonHoverColor: rgba(255, 255, 255, 0.15);
$newToolbarButtonToggleColor: rgba(255, 255, 255, 0.2);
$newToolbarBackgroundColor: #131519;
$newToolbarButtonHoverColor: rgba(255, 255, 255, 0.2);
$newToolbarButtonToggleColor: rgba(255, 255, 255, 0.15);
$AOTToolbarButtonHoverColor: rgba(14, 20, 35, 0.6);
$AOTToolbarButtonToggleColor: rgba(14, 20, 35, 1);
$menuBG:#242528;
$newToolbarFontSize: 24px;
$newToolbarHangupFontSize: 32px;
$newToolbarSize: 40px;
$newToolbarSize: 48px;
$newToolbarSizeWithPadding: calc(#{$newToolbarSize} + 24px);
$toolbarTitleFontSize: 19px;
$overflowMenuBG: initial;
$overflowMenuItemHoverBG: #313D52;
$overflowMenuItemHoverColor: #B8C7E0;
$overflowMenuItemColor: #B8C7E0;
$overflowMenuItemColor: #fff;
$overflowMenuItemBackground: #36383C;
/**
* Video layout
@@ -90,12 +91,12 @@ $modalTextColor: #333;
* Chat
*/
$chatActionsSeparatorColor: rgb(173, 105, 112);
$chatHeaderBackgroundColor: rgba(42, 58, 75, 0.9);
$chatBackgroundColor: #131519;
$chatInputSeparatorColor: #A4B8D1;
$chatLocalMessageBackgroundColor: rgb(4, 98, 178);
$chatLocalMessageBackgroundColor: #484A4F;
$chatPrivateMessageBackgroundColor: rgb(153, 69, 77);
$chatRemoteMessageBackgroundColor: rgb(86, 101, 114);
$sidebarWidth: 375px;
$chatRemoteMessageBackgroundColor: #242528;
$sidebarWidth: 315px;
/**
* Misc.
@@ -122,8 +123,8 @@ $zindex10: 10;
$reloadZ: 20;
$poweredByZ: 100;
$ringingZ: 300;
$sideToolbarContainerZ: 300;
$toolbarZ: 350;
$sideToolbarContainerZ: 200;
$toolbarZ: 250;
$drawerZ: 351;
$tooltipsZ: 401;
$dropdownMaskZ: 900;

View File

@@ -1,18 +1,21 @@
.video-preview {
background: none;
max-height: 290px;
display: inline-block;
max-height: 344px;
&-container {
background: $menuBG;
border-radius: 3px;
overflow: auto;
padding: 16px;
padding: 8px;
}
&-entry {
cursor: pointer;
height: 135px;
margin-bottom: 16px;
height: 168px;
margin-bottom: 8px;
position: relative;
width: 240px;
width: 284px;
&:last-child {
margin-bottom: 0;
@@ -20,13 +23,15 @@
&--selected {
border: 3px solid #31B76A;
border-radius: 3px;
cursor: default;
height: 129px;
width: 234px;
height: 162px;
width: 278px;
}
}
&-video {
border-radius: 3px;
height: 100%;
object-fit: cover;
width: 100%;
@@ -50,21 +55,28 @@
}
&-label {
bottom: 8px;
color: #fff;
font-size: 13px;
line-height: 20px;
overflow: hidden;
padding: 8px;
position: absolute;
text-align: center;
text-overflow: ellipsis;
width: 220px;
width: 100%;
z-index: 2;
}
// Override @atlaskit/InlineDialog container which is made with styled components
& > div:nth-child(2) {
outline: none;
padding: 0;
&-container {
margin: 0 16px;
}
&-text {
background-color: #131519;
border-radius: 3px;
padding: 2px 8px;
font-size: 13px;
line-height: 20px;
margin: 0 auto;
max-width: calc(100% - 16px);
overflow: hidden;
text-overflow: ellipsis;
width: fit-content;
white-space: nowrap;
}
}
}

View File

@@ -400,7 +400,9 @@
}
}
.local-video-menu-trigger,
.remote-video-menu-trigger,
.localvideomenu,
.remotevideomenu
{
display: inline-block;
@@ -418,6 +420,7 @@
cursor: hand;
}
}
.local-video-menu-trigger,
.remote-video-menu-trigger {
margin-top: 7px;
}

View File

@@ -208,6 +208,11 @@ body.welcome-page {
cursor: pointer;
font-size: 32px;
}
.toolbox-icon {
height: 24px;
width: 24px;
}
}
.welcome-watermark {
@@ -228,6 +233,10 @@ body.welcome-page {
}
}
&.without-footer {
justify-content: start;
}
.welcome-cards-container {
color:#131519;
padding-top: 40px;

View File

@@ -19,7 +19,7 @@
0 0 3px $videoThumbnailSelected;
}
.remotevideomenu > .icon-menu {
.remotevideomenu > .icon-menu, .localvideomenu > .icon-menu {
display: none;
}
@@ -32,7 +32,7 @@
box-shadow: inset 0 0 3px $videoThumbnailHovered,
0 0 3px $videoThumbnailHovered;
.remotevideomenu > .icon-menu {
.remotevideomenu > .icon-menu, .localvideomenu > .icon-menu {
display: inline-block;
}
}

View File

@@ -121,3 +121,15 @@
align-self: baseline;
}
}
.shift-right #filmstripRemoteVideosContainer {
/**
* Max-width corresponding to the ASPECT_RATIO_BREAKPOINT from features/filmstrip/constants,
* from which we subtract the chat size.
*/
@media only screen and (max-width: calc(500px + #{$sidebarWidth})) {
video {
object-fit: cover;
}
}
}

View File

@@ -43,6 +43,7 @@
* specifically the various status icons.
*/
.remotevideomenu,
.localvideomenu,
.videocontainer__toptoolbar {
z-index: auto;
}

View File

@@ -51,6 +51,7 @@
* and tooltips from getting a new location context due to translate3d.
*/
.connection-indicator,
.local-video-menu-trigger,
.remote-video-menu-trigger,
.indicator-icon-container {
transform: translate3d(0, 0, 0);
@@ -68,7 +69,9 @@
* Move the remote video menu trigger to the bottom left of the video
* thumbnail.
*/
.localvideomenu,
.remotevideomenu,
.local-video-menu-trigger,
.remote-video-menu-trigger {
bottom: 0;
left: 0;
@@ -76,6 +79,7 @@
right: auto;
}
.local-video-menu-trigger,
.remote-video-menu-trigger {
margin-bottom: 7px;
margin-left: $remoteVideoMenuIconMargin;

View File

@@ -43,6 +43,7 @@ $flagsImagePath: "../images/";
@import 'modals/settings/settings';
@import 'modals/speaker_stats/speaker_stats';
@import 'modals/video-quality/video-quality';
@import 'modals/virtual-background/virtual-background';
@import 'modals/local-recording/local-recording';
@import 'videolayout_default';
@import 'notice';

View File

@@ -1,31 +1,42 @@
.invite-more {
&-container {
margin-bottom: 8px;
transition: margin-bottom 0.3s;
&.elevated {
margin-bottom: 36px;
}
}
&-content {
display: flex;
flex-direction: column;
align-items: center;
padding: 16px;
background: rgba(0, 0, 0, 0.7);
border-radius: 8px;
color: #fff;
font-size: 14px;
line-height: 24px;
font-weight: 600;
position: absolute;
width: 100%;
text-align: center;
z-index: $zindex2;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
}
&-header {
font-size: 19px;
line-height: 28px;
margin: 24px 0 16px 0;
max-width: 100%;
margin-bottom: 16px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
&-button {
display: flex;
margin: auto;
max-width: 100%;
height: 40px;
box-sizing: border-box;
padding: 8px 16px;
width: fit-content;
width: -moz-fit-content;
height: 24px;
background: #0376DA;
border-radius: 3px;
font-size: 14px;
line-height: 24px;
cursor: pointer;
@media (hover: hover) and (pointer: fine) {
@@ -36,8 +47,9 @@
&-text {
margin-left: 8px;
font-size: 15px;
line-height: 24px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
}
&-dialog {
@@ -195,3 +207,14 @@
}
}
}
.mobile-browser {
.invite-more-content {
font-size: 16px;
}
.invite-more-button {
height: 48px;
padding: 12px 16px;
}
}

View File

@@ -0,0 +1,93 @@
.virtual-background-dialog {
display: inline-grid;
grid-template-columns: auto auto auto auto auto auto auto;
max-width: 370px;
cursor: pointer;
.thumbnail {
border-radius: 10px;
object-fit: cover;
padding: 5px;
height: 40px;
width: 40px;
}
.thumbnail:hover ~ .delete-image-icon {
display: block;
}
.thumbnail-selected {
border-radius: 10px;
object-fit: cover;
padding: 5px;
height: 40px;
width: 40px;
border: 2px solid #a4b8d1;
}
.blur-selected {
border-radius: 10px;
border: 2px solid #a4b8d1;
}
.virtual-background-none {
font-weight: bold;
padding: 5px;
height: 34px;
width: 34px;
border-radius: 10px;
border: 1px solid #a4b8d1;
text-align: center;
vertical-align: middle;
line-height: 35px;
margin-right: 5px;
}
.none-selected {
font-weight: bold;
padding: 5px;
height: 34px;
width: 34px;
border-radius: 10px;
border: 2px solid #a4b8d1;
text-align: center;
vertical-align: middle;
line-height: 35px;
margin-right: 5px;
}
}
.modal-dialog-form .virtual-background-loading {
overflow: hidden;
}
.file-upload-btn {
display: none;
}
.custom-file-upload {
font-size: x-large;
font-weight: bold;
display: inline-block;
padding: 4px;
height: 35px;
width: 35px;
border-radius: 10px;
border: 1px solid #a4b8d1;
text-align: center;
vertical-align: middle;
line-height: 35px;
margin-left: 5px;
cursor: pointer;
}
.delete-image-icon {
position: absolute;
display: none;
left: 36;
bottom: 36;
}
.delete-image-icon:hover {
display: block;
}
.thumbnail-container {
position: relative;
}
.loading-content-text{
margin-right: 15px;
}

View File

@@ -33,4 +33,12 @@
bottom: 24px;
width: 100%;
}
&__spinner-container {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
}
}

View File

@@ -35,7 +35,7 @@ case "$1" in
db_input critical jitsi-videobridge/jvb-hostname || true
db_go
fi
JVB_HOSTNAME="$RET"
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
db_get jitsi-videobridge/jvbsecret
if [ -z "$RET" ] ; then
@@ -64,7 +64,7 @@ case "$1" in
# detect dpkg-reconfigure, just delete old links
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME_OLD=$RET
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
rm -f /etc/prosody/conf.d/$JVB_HOSTNAME_OLD.cfg.lua
rm -f /etc/prosody/certs/$JVB_HOSTNAME_OLD.key

View File

@@ -31,7 +31,7 @@ case "$1" in
purge)
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME=$RET
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ]; then
rm -f /etc/prosody/conf.avail/$JVB_HOSTNAME.cfg.lua
rm -f /etc/prosody/conf.d/$JVB_HOSTNAME.cfg.lua

View File

@@ -25,7 +25,7 @@ case "$1" in
. /usr/share/debconf/confmodule
db_get jitsi-meet-prosody/jvb-hostname
JVB_HOSTNAME="$RET"
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
db_get jitsi-meet-tokens/appid
if [ "$RET" = "false" ] ; then

View File

@@ -30,7 +30,7 @@ case "$1" in
db_input critical jitsi-videobridge/jvb-hostname || true
db_go
fi
JVB_HOSTNAME="$RET"
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
TURN_CONFIG="/etc/turnserver.conf"
NGINX_CONFIG="/etc/nginx/sites-available/$JVB_HOSTNAME.conf"
@@ -44,7 +44,7 @@ case "$1" in
# detect dpkg-reconfigure, just delete old links
db_get jitsi-meet-turnserver/jvb-hostname
JVB_HOSTNAME_OLD=$RET
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
if [[ -f $TURN_CONFIG ]] && grep -q "jitsi-meet coturn config" "$TURN_CONFIG" ; then
rm -f $TURN_CONFIG

View File

@@ -32,12 +32,12 @@ case "$1" in
db_go
db_get jitsi-videobridge/jvb-hostname
fi
JVB_HOSTNAME="$RET"
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
# detect dpkg-reconfigure
RECONFIGURING="false"
db_get jitsi-meet/jvb-hostname
JVB_HOSTNAME_OLD=$RET
JVB_HOSTNAME_OLD=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ] && [ ! "$JVB_HOSTNAME_OLD" = "$JVB_HOSTNAME" ] ; then
RECONFIGURING="true"
rm -f /etc/jitsi/meet/$JVB_HOSTNAME_OLD-config.js

View File

@@ -33,7 +33,7 @@ case "$1" in
;;
purge)
db_get jitsi-meet/jvb-hostname
JVB_HOSTNAME=$RET
JVB_HOSTNAME=$(echo "$RET" | xargs echo -n)
if [ -n "$RET" ]; then
rm -f /etc/jitsi/meet/$JVB_HOSTNAME-config.js
rm -f /etc/nginx/sites-available/$JVB_HOSTNAME.conf

View File

@@ -2,9 +2,6 @@
<VirtualHost *:80>
ServerName jitsi-meet.example.com
Redirect permanent / https://jitsi-meet.example.com/
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>
<VirtualHost *:443>
@@ -42,11 +39,12 @@
</Location>
ProxyPreserveHost on
ProxyPass /http-bind http://localhost:5280/http-bind/
ProxyPassReverse /http-bind http://localhost:5280/http-bind/
ProxyPass /http-bind http://localhost:5280/http-bind
ProxyPassReverse /http-bind http://localhost:5280/http-bind
ProxyPass /xmpp-websocket ws://localhost:5280/xmpp-websocket
ProxyPassReverse /xmpp-websocket ws://localhost:5280/xmpp-websocket
ProxyPassMatch ^/colibri-ws/default-id ws://localhost:9090
ProxyPass /colibri-ws/default-id ws://localhost:9090/colibri-ws/default-id
ProxyPassReverse /colibri-ws/default-id ws://localhost:9090/colibri-ws/default-id
RewriteEngine on
RewriteRule ^/([a-zA-Z0-9]+)$ /index.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 437 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 KiB

View File

@@ -1,6 +1,13 @@
/* eslint-disable no-unused-vars, no-var, max-len */
/* eslint sort-keys: ["error", "asc", {"caseSensitive": false}] */
/**
* !!!IMPORTANT!!!
*
* This file is considered deprecated. All options will eventually be moved to
* config.js, and no new options should be added here.
*/
var interfaceConfig = {
APP_NAME: 'Jitsi Meet',
AUDIO_LEVEL_PRIMARY_COLOR: 'rgba(255,255,255,0.4)',
@@ -168,6 +175,13 @@ var interfaceConfig = {
REMOTE_THUMBNAIL_RATIO: 1, // 1:1
SETTINGS_SECTIONS: [ 'devices', 'language', 'moderator', 'profile', 'calendar' ],
/**
* Specify which sharing features should be displayed. If the value is not set
* all sharing features will be shown. You can set [] to disable all.
*/
// SHARING_FEATURES: ['email', 'url', 'dial-in', 'embed'],
SHOW_BRAND_WATERMARK: false,
/**
@@ -191,23 +205,16 @@ var interfaceConfig = {
TOOLBAR_ALWAYS_VISIBLE: false,
/**
* The name of the toolbar buttons to display in the toolbar, including the
* "More actions" menu. If present, the button will display. Exceptions are
* "livestreaming" and "recording" which also require being a moderator and
* some values in config.js to be enabled. Also, the "profile" button will
* not display for users with a JWT.
* Notes:
* - it's impossible to choose which buttons go in the "More actions" menu
* - it's impossible to control the placement of buttons
* - 'desktop' controls the "Share your screen" button
* DEPRECATED!
* This config was moved to config.js as `toolbarButtons`.
*/
TOOLBAR_BUTTONS: [
'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
'tileview', 'videobackgroundblur', 'download', 'help', 'mute-everyone', 'security'
],
// TOOLBAR_BUTTONS: [
// 'microphone', 'camera', 'closedcaptions', 'desktop', 'embedmeeting', 'fullscreen',
// 'fodeviceselection', 'hangup', 'profile', 'chat', 'recording',
// 'livestreaming', 'etherpad', 'sharedvideo', 'settings', 'raisehand',
// 'videoquality', 'filmstrip', 'invite', 'feedback', 'stats', 'shortcuts',
// 'tileview', 'select-background', 'download', 'help', 'mute-everyone', 'mute-video-everyone', 'security'
// ],
TOOLBAR_TIMEOUT: 4000,

View File

@@ -61,7 +61,6 @@ target 'JitsiMeetSDK' do
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-async-storage/async-storage'
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-community/google-signin'

View File

@@ -5,8 +5,6 @@ PODS:
- AppAuth/Core (1.2.0)
- AppAuth/ExternalUserAgent (1.2.0)
- boost-for-react-native (1.63.0)
- BVLinearGradient (2.5.6):
- React
- CocoaLumberjack (3.5.3):
- CocoaLumberjack/Core (= 3.5.3)
- CocoaLumberjack/Core (3.5.3)
@@ -292,7 +290,7 @@ PODS:
- React
- react-native-splash-screen (3.2.0):
- React
- react-native-webrtc (1.87.3):
- react-native-webrtc (1.89.1):
- React-Core
- react-native-webview (11.0.2):
- React-Core
@@ -371,7 +369,6 @@ PODS:
- Yoga (1.14.0)
DEPENDENCIES:
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- CocoaLumberjack (~> 3.5.3)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector/`)
@@ -442,8 +439,6 @@ SPEC REPOS:
- PromisesObjC
EXTERNAL SOURCES:
BVLinearGradient:
:path: "../node_modules/react-native-linear-gradient"
DoubleConversion:
:podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
FBLazyVector:
@@ -526,7 +521,6 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
AppAuth: bce82c76043657c99d91e7882e8a9e1a93650cd4
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
CocoaLumberjack: 2f44e60eb91c176d471fdba43b9e3eae6a721947
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
FBLazyVector: ca7f56c8ff6cd8590f7a673d7903b06019805581
@@ -563,7 +557,7 @@ SPEC CHECKSUMS:
react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
react-native-webrtc: dc1208bdca2c4d091f7b57859e69332bff6f1986
react-native-webrtc: ccb0c21eb4fb04326648fbdb4a5d49977e2cf274
react-native-webview: b2542d6fd424bcc3e3b2ec5f854f0abb4ec86c87
React-RCTActionSheet: bcbc311dc3b47bc8efb2737ff0940239a45789a9
React-RCTAnimation: 65f61080ce632f6dea23d52e354ffac9948396c6
@@ -584,6 +578,6 @@ SPEC CHECKSUMS:
RNWatch: a5320c959c75e72845c07985f3e935e58998f1d3
Yoga: 96b469c5e81ff51b917b92e8c3390642d4ded30c
PODFILE CHECKSUM: 5be5132e41831a98362eeed760558227a4df89ae
PODFILE CHECKSUM: d059cebf82da14a53940a16c24c3330752d4b0c8
COCOAPODS: 1.10.0
COCOAPODS: 1.10.1

View File

@@ -8,6 +8,10 @@
<string>applinks:beta.meet.jit.si</string>
<string>applinks:meet.jit.si</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.jitsi.meet.appgroup</string>
</array>
<key>com.apple.developer.siri</key>
<true/>
</dict>

View File

@@ -23,6 +23,12 @@
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
4E51B75E25E4115F0038575A /* DarwinNotificationCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E51B75D25E4115F0038575A /* DarwinNotificationCenter.m */; };
4EC49BB725BEDAC100E76218 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EC49B8625BED71300E76218 /* ReplayKit.framework */; };
4EC49BBB25BEDAC100E76218 /* SampleHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EC49BBA25BEDAC100E76218 /* SampleHandler.m */; };
4EC49BBF25BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 4EC49BB625BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4EC49BCB25BEDB6400E76218 /* SocketConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EC49BCA25BEDB6400E76218 /* SocketConnection.m */; };
4EC49BD125BF19CF00E76218 /* SampleUploader.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EC49BD025BF19CF00E76218 /* SampleUploader.m */; };
55BEDABDA92D47D399A70A5E /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */; };
DE050389256E904600DEE3A5 /* WebRTC.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DE050388256E904600DEE3A5 /* WebRTC.xcframework */; };
DE05038A256E904600DEE3A5 /* WebRTC.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DE050388256E904600DEE3A5 /* WebRTC.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -48,6 +54,13 @@
remoteGlobalIDString = 0BEA5C241F7B8F73000D0AB4;
remoteInfo = JitsiMeetCompanion;
};
4EC49BBD25BEDAC100E76218 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 4EC49BB525BEDAC100E76218;
remoteInfo = "JitsiMeetBroadcast Extension";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -85,6 +98,17 @@
name = "Embed Watch Content";
runOnlyForDeploymentPostprocessing = 0;
};
4EC49B9025BED71300E76218 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
4EC49BBF25BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
@@ -115,6 +139,18 @@
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
4670A512A688E2DC34528282 /* Pods-jitsi-meet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-jitsi-meet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-jitsi-meet/Pods-jitsi-meet.debug.xcconfig"; sourceTree = "<group>"; };
4E51B75C25E4115F0038575A /* DarwinNotificationCenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinNotificationCenter.h; sourceTree = "<group>"; };
4E51B75D25E4115F0038575A /* DarwinNotificationCenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DarwinNotificationCenter.m; sourceTree = "<group>"; };
4EC49B8625BED71300E76218 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
4EC49BB625BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "JitsiMeetBroadcast Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
4EC49BB925BEDAC100E76218 /* SampleHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleHandler.h; sourceTree = "<group>"; };
4EC49BBA25BEDAC100E76218 /* SampleHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleHandler.m; sourceTree = "<group>"; };
4EC49BBC25BEDAC100E76218 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4EC49BC925BEDB6400E76218 /* SocketConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SocketConnection.h; sourceTree = "<group>"; };
4EC49BCA25BEDB6400E76218 /* SocketConnection.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SocketConnection.m; sourceTree = "<group>"; };
4EC49BCF25BF19CF00E76218 /* SampleUploader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SampleUploader.h; sourceTree = "<group>"; };
4EC49BD025BF19CF00E76218 /* SampleUploader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SampleUploader.m; sourceTree = "<group>"; };
4EC49BDB25BF280A00E76218 /* extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = extension.entitlements; sourceTree = "<group>"; };
609CB2080B75F75A89923F3D /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
B3B083EB1D4955FF0069CEE7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = app.entitlements; sourceTree = "<group>"; };
D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -153,6 +189,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EC49BB325BEDAC100E76218 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
4EC49BB725BEDAC100E76218 /* ReplayKit.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -165,6 +209,7 @@
DEFDBBDB25656E3B00344B23 /* WebRTC.xcframework */,
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */,
D878B07B3FBD6E305EAA6B27 /* libPods-JitsiMeet.a */,
4EC49B8625BED71300E76218 /* ReplayKit.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@@ -216,6 +261,24 @@
path = src;
sourceTree = "<group>";
};
4EC49BB825BEDAC100E76218 /* JitsiMeetBroadcast Extension */ = {
isa = PBXGroup;
children = (
4EC49BDB25BF280A00E76218 /* extension.entitlements */,
4EC49BB925BEDAC100E76218 /* SampleHandler.h */,
4EC49BBA25BEDAC100E76218 /* SampleHandler.m */,
4EC49BC925BEDB6400E76218 /* SocketConnection.h */,
4EC49BCA25BEDB6400E76218 /* SocketConnection.m */,
4EC49BCF25BF19CF00E76218 /* SampleUploader.h */,
4EC49BD025BF19CF00E76218 /* SampleUploader.m */,
4EC49BBC25BEDAC100E76218 /* Info.plist */,
4E51B75C25E4115F0038575A /* DarwinNotificationCenter.h */,
4E51B75D25E4115F0038575A /* DarwinNotificationCenter.m */,
);
name = "JitsiMeetBroadcast Extension";
path = "broadcast-extension";
sourceTree = "<group>";
};
5E96ADD5E49F3B3822EF9A52 /* Pods */ = {
isa = PBXGroup;
children = (
@@ -236,6 +299,7 @@
13B07FAE1A68108700A75B9A /* src */,
5E96ADD5E49F3B3822EF9A52 /* Pods */,
0BEA5C261F7B8F73000D0AB4 /* Watch app */,
4EC49BB825BEDAC100E76218 /* JitsiMeetBroadcast Extension */,
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */,
);
indentWidth = 2;
@@ -248,6 +312,7 @@
13B07F961A680F5B00A75B9A /* jitsi-meet.app */,
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */,
0BEA5C311F7B8F73000D0AB4 /* JitsiMeetCompanion Extension.appex */,
4EC49BB625BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex */,
);
name = Products;
sourceTree = "<group>";
@@ -305,17 +370,36 @@
DE11877A21EE09640078D059 /* Setup Google reverse URL handler */,
DE4F6D6E22005C0400DE699E /* Setup Dropbox */,
0BEA5C491F7B8F73000D0AB4 /* Embed Watch Content */,
4EC49B9025BED71300E76218 /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
0BEA5C401F7B8F73000D0AB4 /* PBXTargetDependency */,
4EC49BBE25BEDAC100E76218 /* PBXTargetDependency */,
);
name = JitsiMeet;
productName = "Jitsi Meet";
productReference = 13B07F961A680F5B00A75B9A /* jitsi-meet.app */;
productType = "com.apple.product-type.application";
};
4EC49BB525BEDAC100E76218 /* JitsiMeetBroadcast Extension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 4EC49BC025BEDAC100E76218 /* Build configuration list for PBXNativeTarget "JitsiMeetBroadcast Extension" */;
buildPhases = (
4EC49BB225BEDAC100E76218 /* Sources */,
4EC49BB325BEDAC100E76218 /* Frameworks */,
4EC49BB425BEDAC100E76218 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "JitsiMeetBroadcast Extension";
productName = "JitsiMeetBroadcast Extension";
productReference = 4EC49BB625BEDAC100E76218 /* JitsiMeetBroadcast Extension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -336,8 +420,6 @@
ProvisioningStyle = Automatic;
};
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = FC967L3QRG;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.SafariKeychain = {
enabled = 1;
@@ -347,6 +429,9 @@
};
};
};
4EC49BB525BEDAC100E76218 = {
CreatedOnToolsVersion = 12.2;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */;
@@ -365,6 +450,7 @@
13B07F861A680F5B00A75B9A /* JitsiMeet */,
0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */,
0BEA5C301F7B8F73000D0AB4 /* JitsiMeetCompanion Extension */,
4EC49BB525BEDAC100E76218 /* JitsiMeetBroadcast Extension */,
);
};
/* End PBXProject section */
@@ -397,6 +483,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EC49BB425BEDAC100E76218 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@@ -532,6 +625,17 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
4EC49BB225BEDAC100E76218 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
4EC49BCB25BEDB6400E76218 /* SocketConnection.m in Sources */,
4EC49BBB25BEDAC100E76218 /* SampleHandler.m in Sources */,
4E51B75E25E4115F0038575A /* DarwinNotificationCenter.m in Sources */,
4EC49BD125BF19CF00E76218 /* SampleUploader.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@@ -545,6 +649,11 @@
target = 0BEA5C241F7B8F73000D0AB4 /* JitsiMeetCompanion */;
targetProxy = 0BEA5C3F1F7B8F73000D0AB4 /* PBXContainerItemProxy */;
};
4EC49BBE25BEDAC100E76218 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 4EC49BB525BEDAC100E76218 /* JitsiMeetBroadcast Extension */;
targetProxy = 4EC49BBD25BEDAC100E76218 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
@@ -718,7 +827,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDebug;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEAD_CODE_STRIPPING = NO;
@@ -748,7 +857,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconRelease;
CODE_SIGN_ENTITLEMENTS = app.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = FC967L3QRG;
@@ -770,6 +879,70 @@
};
name = Release;
};
4EC49BC125BEDAC100E76218 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "broadcast-extension/extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = FC967L3QRG;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "broadcast-extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.broadcast.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
4EC49BC225BEDAC100E76218 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_ENTITLEMENTS = "broadcast-extension/extension.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = FC967L3QRG;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "broadcast-extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.broadcast.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
83CBBA201A601CBA00E9B192 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -914,6 +1087,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
4EC49BC025BEDAC100E76218 /* Build configuration list for PBXNativeTarget "JitsiMeetBroadcast Extension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
4EC49BC125BEDAC100E76218 /* Debug */,
4EC49BC225BEDAC100E76218 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "app" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@@ -0,0 +1,31 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
extern NSNotificationName const kBroadcastStartedNotification;
extern NSNotificationName const kBroadcastStoppedNotification;
@interface DarwinNotificationCenter: NSObject
+ (instancetype)sharedInstance;
- (void)postNotificationWithName:(NSNotificationName)name;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,50 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "DarwinNotificationCenter.h"
NSNotificationName const kBroadcastStartedNotification = @"iOS_BroadcastStarted";
NSNotificationName const kBroadcastStoppedNotification = @"iOS_BroadcastStopped";
@implementation DarwinNotificationCenter {
CFNotificationCenterRef _notificationCenter;
}
+ (instancetype)sharedInstance {
static DarwinNotificationCenter *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_notificationCenter = CFNotificationCenterGetDarwinNotifyCenter();
}
return self;
}
- (void)postNotificationWithName:(NSString*)name {
CFNotificationCenterPostNotification(_notificationCenter, (__bridge CFStringRef)name, NULL, NULL, true);
}
@end

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>JitsiMeet Broadcast Extension</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>21.0.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.broadcast-services-upload</string>
<key>NSExtensionPrincipalClass</key>
<string>SampleHandler</string>
<key>RPBroadcastProcessMode</key>
<string>RPBroadcastProcessModeSampleBuffer</string>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,21 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <ReplayKit/ReplayKit.h>
@interface SampleHandler : RPBroadcastSampleHandler
@end

View File

@@ -0,0 +1,123 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "SampleHandler.h"
#import "SocketConnection.h"
#import "SampleUploader.h"
#import "DarwinNotificationCenter.h"
@interface SampleHandler ()
@property (nonatomic, retain) SocketConnection *clientConnection;
@property (nonatomic, retain) SampleUploader *uploader;
@end
@implementation SampleHandler
- (instancetype)init {
self = [super init];
if (self) {
self.clientConnection = [[SocketConnection alloc] initWithFilePath:self.socketFilePath];
[self setupConnection];
self.uploader = [[SampleUploader alloc] initWithConnection:self.clientConnection];
}
return self;
}
- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {
// User has requested to start the broadcast. Setup info from the UI extension can be supplied but optional.
NSLog(@"broadcast started");
[[DarwinNotificationCenter sharedInstance] postNotificationWithName:kBroadcastStartedNotification];
[self openConnection];
}
- (void)broadcastPaused {
// User has requested to pause the broadcast. Samples will stop being delivered.
}
- (void)broadcastResumed {
// User has requested to resume the broadcast. Samples delivery will resume.
}
- (void)broadcastFinished {
// User has requested to finish the broadcast.
[[DarwinNotificationCenter sharedInstance] postNotificationWithName:kBroadcastStoppedNotification];
[self.clientConnection close];
}
- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {
static NSUInteger frameCount = 0;
switch (sampleBufferType) {
case RPSampleBufferTypeVideo:
// adjust frame rate by using every third frame
if (++frameCount%3 == 0 && self.uploader.isReady) {
[self.uploader sendSample:sampleBuffer];
}
break;
default:
break;
}
}
// MARK: Private Methods
- (NSString *)socketFilePath {
// the appGroupIdentifier must match the value provided in the app's info.plist for the RTCAppGroupIdentifier key
NSString *appGroupIdentifier = @"group.org.jitsi.meet.appgroup";
NSURL *sharedContainer = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupIdentifier];
NSString *socketFilePath = [[sharedContainer URLByAppendingPathComponent:@"rtc_SSFD"] path];
return socketFilePath;
}
- (void)setupConnection {
__weak __typeof(self) weakSelf = self;
self.clientConnection.didClose = ^(NSError *error) {
NSLog(@"client connection did close: %@", error);
if (error) {
[weakSelf finishBroadcastWithError:error];
}
else {
NSInteger JMScreenSharingStopped = 10001;
NSError *customError = [NSError errorWithDomain:RPRecordingErrorDomain
code:JMScreenSharingStopped
userInfo:@{NSLocalizedDescriptionKey: @"Screen sharing stopped"}];
[weakSelf finishBroadcastWithError:customError];
}
};
}
- (void)openConnection {
dispatch_queue_t queue = dispatch_queue_create("org.jitsi.meet.broadcast.connectTimer", 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), 0.1 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
BOOL success = [self.clientConnection open];
if (success) {
dispatch_source_cancel(timer);
}
});
dispatch_resume(timer);
}
@end

View File

@@ -0,0 +1,33 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
#import <ReplayKit/ReplayKit.h>
NS_ASSUME_NONNULL_BEGIN
@class SocketConnection;
@interface SampleUploader : NSObject
@property (nonatomic, assign, readonly) BOOL isReady;
- (instancetype)initWithConnection:(SocketConnection *)connection;
- (void)sendSample:(CMSampleBufferRef)sampleBuffer;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,155 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <MessageUI/MessageUI.h>
#import <ReplayKit/ReplayKit.h>
#import "SampleUploader.h"
#import "SocketConnection.h"
static const NSInteger kBufferMaxLenght = 10 * 1024;
@interface SampleUploader ()
@property (nonatomic, assign) BOOL isReady;
@property (nonatomic, strong) dispatch_queue_t serialQueue;
@property (nonatomic, strong) SocketConnection *connection;
@property (nonatomic, strong) CIContext *imageContext;
@property (nonatomic, strong) NSData *dataToSend;
@property (nonatomic, assign) NSUInteger byteIndex;
@end
@implementation SampleUploader
- (instancetype)initWithConnection:(SocketConnection *)connection {
self = [super init];
if (self) {
self.serialQueue = dispatch_queue_create("org.jitsi.meet.broadcast.sampleUploader", DISPATCH_QUEUE_SERIAL);
self.connection = connection;
[self setupConnection];
self.imageContext = [[CIContext alloc] initWithOptions:nil];
self.isReady = false;
}
return self;
}
- (void)sendSample:(CMSampleBufferRef)sampleBuffer {
self.isReady = false;
self.dataToSend = [self prepareSample:sampleBuffer];
self.byteIndex = 0;
dispatch_async(self.serialQueue, ^{
[self sendData];
});
}
// MARK: Private Methods
- (void)setupConnection {
__weak __typeof(self) weakSelf = self;
self.connection.didOpen = ^{
weakSelf.isReady = true;
};
self.connection.streamHasSpaceAvailable = ^{
dispatch_async(weakSelf.serialQueue, ^{
weakSelf.isReady = ![weakSelf sendData];
});
};
}
/**
This function downscales and converts to jpeg the provided sample buffer, then wraps the resulted image data into a CFHTTPMessageRef. Returns the serialized CFHTTPMessageRef.
*/
- (NSData *)prepareSample:(CMSampleBufferRef)sampleBuffer {
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
CGFloat scaleFactor = 2;
size_t width = CVPixelBufferGetWidth(imageBuffer)/scaleFactor;
size_t height = CVPixelBufferGetHeight(imageBuffer)/scaleFactor;
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1/scaleFactor, 1/scaleFactor);
NSData *bufferData = [self jpegDataFromPixelBuffer:imageBuffer withScaling:scaleTransform];
CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
if (bufferData) {
CFHTTPMessageRef httpResponse = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1);
CFHTTPMessageSetHeaderFieldValue(httpResponse, (__bridge CFStringRef)@"Content-Length", (__bridge CFStringRef)[NSString stringWithFormat:@"%ld", bufferData.length]);
CFHTTPMessageSetHeaderFieldValue(httpResponse, (__bridge CFStringRef)@"Buffer-Width", (__bridge CFStringRef)[NSString stringWithFormat:@"%ld", width]);
CFHTTPMessageSetHeaderFieldValue(httpResponse, (__bridge CFStringRef)@"Buffer-Height", (__bridge CFStringRef)[NSString stringWithFormat:@"%ld", height]);
CFHTTPMessageSetBody(httpResponse, (__bridge CFDataRef)bufferData);
CFDataRef serializedMessage = CFHTTPMessageCopySerializedMessage(httpResponse);
CFRelease(httpResponse);
return CFBridgingRelease(serializedMessage);
}
return nil;
}
- (BOOL)sendData {
if (!self.dataToSend) {
NSLog(@"no data to send");
return false;
}
NSUInteger bytesLeft = self.dataToSend.length - self.byteIndex;
NSInteger length = bytesLeft > kBufferMaxLenght ? kBufferMaxLenght : bytesLeft;
uint8_t buffer[length];
[self.dataToSend getBytes:&buffer range:NSMakeRange(self.byteIndex, length)];
length = [self.connection writeBufferToStream:buffer maxLength:length];
if (length > 0) {
self.byteIndex += length;
bytesLeft -= length;
if (bytesLeft == 0) {
NSLog(@"video sample processed successfully");
self.dataToSend = nil;
self.byteIndex = 0;
}
}
else {
NSLog(@"writeBufferToStream failure");
}
return true;
}
- (NSData *)jpegDataFromPixelBuffer:(CVPixelBufferRef)pixelBuffer withScaling:(CGAffineTransform)scaleTransform {
CIImage *image = [[CIImage alloc] initWithCVPixelBuffer:pixelBuffer];
image = [image imageByApplyingTransform:scaleTransform];
NSDictionary *options = @{(NSString *)kCGImageDestinationLossyCompressionQuality: [NSNumber numberWithFloat:1.0]};
NSData *imageData = [self.imageContext JPEGRepresentationOfImage:image
colorSpace:image.colorSpace
options:options];
return imageData;
}
@end

View File

@@ -0,0 +1,34 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SocketConnection : NSObject
@property (nonatomic, copy, nullable) void (^didOpen)(void);
@property (nonatomic, copy, nullable) void (^didClose)(NSError*);
@property (nonatomic, copy, nullable) void (^streamHasSpaceAvailable)(void);
- (instancetype)initWithFilePath:(nonnull NSString *)filePath;
- (BOOL)open;
- (void)close;
- (NSInteger)writeBufferToStream:(const uint8_t*)buffer maxLength:(NSInteger)length;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,189 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <sys/socket.h>
#include <sys/un.h>
#import "SocketConnection.h"
@interface SocketConnection () <NSStreamDelegate>
@property (nonatomic, copy) NSString *filePath;
@property (nonatomic, strong) NSInputStream *inputStream;
@property (nonatomic, strong) NSOutputStream *outputStream;
@property (nonatomic, strong) NSThread *networkThread;
@end
@implementation SocketConnection {
int _socket;
struct sockaddr_un _socketAddr;
}
- (instancetype)initWithFilePath:(NSString *)path {
self = [super init];
if (self) {
self.filePath = path;
[self setupSocketWithFilePath:path];
[self setupNetworkThread];
}
return self;
}
- (BOOL)open {
NSLog(@"Open socket connection");
if (![[NSFileManager defaultManager] fileExistsAtPath:self.filePath]) {
NSLog(@"failure: socket file missing");
return false;
}
int status = connect(_socket, (struct sockaddr *)&_socketAddr, sizeof(_socketAddr));
if (status < 0) {
NSLog(@"failure: socket connect (%d)", status);
return false;
}
[self.networkThread start];
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocket(kCFAllocatorDefault, _socket, &readStream, &writeStream);
self.inputStream = (__bridge_transfer NSInputStream *)readStream;
self.inputStream.delegate = self;
[self.inputStream setProperty:@"kCFBooleanTrue" forKey:@"kCFStreamPropertyShouldCloseNativeSocket"];
self.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
self.outputStream.delegate = self;
[self.outputStream setProperty:@"kCFBooleanTrue" forKey:@"kCFStreamPropertyShouldCloseNativeSocket"];
[self performSelector:@selector(scheduleStreams) onThread:self.networkThread withObject:nil waitUntilDone:true];
[self.inputStream open];
[self.outputStream open];
NSLog(@"read stream status: %ld", CFReadStreamGetStatus(readStream));
NSLog(@"write stream status: %ld", CFWriteStreamGetStatus(writeStream));
return true;
}
- (void)close {
[self performSelector:@selector(unscheduleStreams) onThread:self.networkThread withObject:nil waitUntilDone:true];
self.inputStream.delegate = nil;
self.outputStream.delegate = nil;
[self.inputStream close];
[self.outputStream close];
[self.networkThread cancel];
}
- (NSInteger)writeBufferToStream:(const uint8_t*)buffer maxLength:(NSInteger)length {
return [self.outputStream write:buffer maxLength:length];
}
// MARK: Private Methods
- (BOOL)isOpen {
return self.inputStream.streamStatus == NSStreamStatusOpen && self.outputStream.streamStatus == NSStreamStatusOpen;
}
- (void)setupSocketWithFilePath:(NSString*)path {
_socket = socket(AF_UNIX, SOCK_STREAM, 0);
memset(&_socketAddr, 0, sizeof(_socketAddr));
_socketAddr.sun_family = AF_UNIX;
strncpy(_socketAddr.sun_path, path.UTF8String, sizeof(_socketAddr.sun_path) - 1);
}
- (void)setupNetworkThread {
self.networkThread = [[NSThread alloc] initWithBlock:^{
do {
@autoreleasepool {
[[NSRunLoop currentRunLoop] run];
}
} while (![NSThread currentThread].isCancelled);
}];
self.networkThread.qualityOfService = NSQualityOfServiceUserInitiated;
}
- (void)scheduleStreams {
[self.inputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
[self.outputStream scheduleInRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
}
- (void)unscheduleStreams {
[self.inputStream removeFromRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
[self.outputStream removeFromRunLoop:NSRunLoop.currentRunLoop forMode:NSRunLoopCommonModes];
}
- (void)notifyDidClose:(NSError *)error {
if (self.didClose) {
self.didClose(error);
}
}
@end
#pragma mark - NSStreamDelegate
@implementation SocketConnection (NSStreamDelegate)
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventOpenCompleted:
NSLog(@"client stream open completed");
if (aStream == self.outputStream && self.didOpen) {
self.didOpen();
}
break;
case NSStreamEventHasBytesAvailable:
if (aStream == self.inputStream) {
uint8_t buffer;
NSInteger numberOfBytesRead = [(NSInputStream *)aStream read:&buffer maxLength:sizeof(buffer)];
if (!numberOfBytesRead && aStream.streamStatus == NSStreamStatusAtEnd) {
NSLog(@"server socket closed");
[self close];
[self notifyDidClose:nil];
}
}
break;
case NSStreamEventHasSpaceAvailable:
if (aStream == self.outputStream && self.streamHasSpaceAvailable) {
NSLog(@"client stream has space available");
self.streamHasSpaceAvailable();
}
break;
case NSStreamEventErrorOccurred:
NSLog(@"client stream error occurred: %@", aStream.streamError);
[self close];
[self notifyDidClose:aStream.streamError];
break;
default:
break;
}
}
@end

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.application-groups</key>
<array>
<string>group.org.jitsi.meet.appgroup</string>
</array>
</dict>
</plist>

View File

@@ -51,7 +51,7 @@
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
NSLog(@"Enabling Firebase");
[FIRApp configure];
// Crashlytics defaults to disabled wirth the FirebaseCrashlyticsCollectionEnabled Info.plist key.
// Crashlytics defaults to disabled with the FirebaseCrashlyticsCollectionEnabled Info.plist key.
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:![jitsiMeet isCrashReportingDisabled]];
}

View File

@@ -45,6 +45,8 @@
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>FirebaseCrashlyticsCollectionEnabled</key>
<string>false</string>
<key>FirebaseScreenReportingEnabled</key>
<false/>
<key>ITSAppUsesNonExemptEncryption</key>
@@ -66,14 +68,18 @@
<string>See your scheduled meetings in the app.</string>
<key>NSCameraUsageDescription</key>
<string>Participate in meetings with video.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Participate in meetings with voice.</string>
<key>NSLocalNetworkUsageDescription</key>
<string>Local network is used for establishing Peer-to-Peer connections.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Participate in meetings with voice.</string>
<key>NSUserActivityTypes</key>
<array>
<string>org.jitsi.JitsiMeet.ios.conference</string>
</array>
<key>RTCAppGroupIdentifier</key>
<string>group.org.jitsi.meet.appgroup</string>
<key>RTCScreenSharingExtension</key>
<string>org.jitsi.meet.broadcast.extension</string>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
@@ -99,7 +105,5 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>FirebaseCrashlyticsCollectionEnabled</key>
<string>false</string>
</dict>
</plist>

View File

@@ -131,6 +131,10 @@
NSLog(@"%@%@", @"Chat toggled: ", data);
}
- (void)videoMutedChanged:(NSDictionary *)data {
NSLog(@"%@%@", @"Video muted changed: ", data[@"muted"]);
}
#pragma mark - Helpers
- (void)terminate {

View File

@@ -35,7 +35,7 @@ fi
echo "PR_REPO_SLUG=${PR_REPO_SLUG} PR_BRANCH=${PR_BRANCH}"
# do the marge and git log
# do the merge and git log
if [ $PR_BRANCH != "master" ]; then
echo "Will merge ${PR_REPO_SLUG}/${PR_BRANCH} into master"

View File

@@ -90,7 +90,7 @@ echo "importing dev-key.p12"
security import ${CERT_DIR}/dev-key.p12 -k ios-build.keychain -P $IOS_SIGNING_CERT_PASSWORD -A
echo "will set-key-partition-list"
# Fix for OS X Sierra that hungs in the codesign step
# Fix for OS X Sierra that hangs in the codesign step
security set-key-partition-list -S apple-tool:,apple: -s -k $ENCRYPTION_PASSWORD ios-build.keychain > /dev/null
echo "done set-key-partition-list"

View File

@@ -16,6 +16,20 @@ platform :ios do
app_identifier: "com.atlassian.JitsiMeet.ios"
)
# Set the broadcast extension identifier
update_app_identifier(
xcodeproj: "app/app.xcodeproj",
plist_path: "broadcast-extension/Info.plist",
app_identifier: "com.atlassian.JitsiMeet.ios.broadcast"
)
update_info_plist(
xcodeproj: "app/app.xcodeproj",
plist_path: "src/Info.plist",
block: proc do |plist|
plist["RTCScreenSharingExtension"] = "com.atlassian.JitsiMeet.ios.broadcast"
end
)
# Set the (watch) app identifier
update_app_identifier(
xcodeproj: "app/app.xcodeproj",

View File

@@ -24,6 +24,8 @@
0BCA49601EC4B6C600B793EE /* POSIX.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495D1EC4B6C600B793EE /* POSIX.m */; };
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */ = {isa = PBXBuildFile; fileRef = 0BCA495E1EC4B6C600B793EE /* Proximity.m */; };
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BD906E81EC0C00300C8C18E /* JitsiMeet.h */; settings = {ATTRIBUTES = (Public, ); }; };
4E51B76425E5345E0038575A /* ScheenshareEventEmiter.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */; };
4E51B76525E5345E0038575A /* ScheenshareEventEmiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */; };
6C31EDC820C06D490089C899 /* recordingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC720C06D490089C899 /* recordingOn.mp3 */; };
6C31EDCA20C06D530089C899 /* recordingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 6C31EDC920C06D530089C899 /* recordingOff.mp3 */; };
6F08DF7D4458EE3CF3F36F6D /* libPods-JitsiMeetSDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E4376CA6886DE68FD7A4294B /* libPods-JitsiMeetSDK.a */; };
@@ -85,6 +87,8 @@
0BD906E51EC0C00300C8C18E /* JitsiMeetSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = JitsiMeetSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0BD906E81EC0C00300C8C18E /* JitsiMeet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JitsiMeet.h; sourceTree = "<group>"; };
0BD906E91EC0C00300C8C18E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScheenshareEventEmiter.h; sourceTree = "<group>"; };
4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ScheenshareEventEmiter.m; sourceTree = "<group>"; };
6C31EDC720C06D490089C899 /* recordingOn.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = recordingOn.mp3; path = ../../sounds/recordingOn.mp3; sourceTree = "<group>"; };
6C31EDC920C06D530089C899 /* recordingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = recordingOff.mp3; path = ../../sounds/recordingOff.mp3; sourceTree = "<group>"; };
75635B0820751D6D00F29C9F /* joined.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = joined.wav; path = ../../sounds/joined.wav; sourceTree = "<group>"; };
@@ -231,6 +235,8 @@
C8AFD27D2462C613000293D2 /* InfoPlistUtil.h */,
C8AFD27E2462C613000293D2 /* InfoPlistUtil.m */,
C81E9AB825AC5AD800B134D9 /* ExternalAPI.h */,
4E51B76225E5345E0038575A /* ScheenshareEventEmiter.h */,
4E51B76325E5345E0038575A /* ScheenshareEventEmiter.m */,
);
path = src;
sourceTree = "<group>";
@@ -298,6 +304,7 @@
0B93EF7E1EC9DDCD0030D24D /* RCTBridgeWrapper.h in Headers */,
DE81A2DE2317ED5400AE1940 /* JitsiMeetBaseLogHandler.h in Headers */,
DEA9F284258A5D9900D4CD74 /* JitsiMeetSDK.h in Headers */,
4E51B76425E5345E0038575A /* ScheenshareEventEmiter.h in Headers */,
DE65AACC2318028300290BEC /* JitsiMeetBaseLogHandler+Private.h in Headers */,
0B412F221EDEF6EA00B1A0A6 /* JitsiMeetViewDelegate.h in Headers */,
0BD906EA1EC0C00300C8C18E /* JitsiMeet.h in Headers */,
@@ -466,6 +473,7 @@
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */,
DEFE535621FB2E8300011A3A /* ReactUtils.m in Sources */,
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,
4E51B76525E5345E0038575A /* ScheenshareEventEmiter.m in Sources */,
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */,
C69EFA0D209A0F660027712B /* JMCallKitProxy.swift in Sources */,
DE81A2D52316AC4D00AE1940 /* JitsiMeetLogger.m in Sources */,

View File

@@ -20,11 +20,12 @@
- (void)sendHangUp;
- (void)sendSetAudioMuted:(BOOL)muted;
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)sendEndpointTextMessage:(NSString*)message :(NSString*)to;
- (void)toggleScreenShare;
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completion;
- (void)openChat:(NSString*)to;
- (void)closeChat;
- (void)sendChatMessage:(NSString*)to :(NSString*)message;
- (void)sendChatMessage:(NSString*)message :(NSString*)to ;
- (void)sendSetVideoMuted:(BOOL)muted;
@end

View File

@@ -26,6 +26,7 @@ static NSString * const retrieveParticipantsInfoAction = @"org.jitsi.meet.RETRIE
static NSString * const openChatAction = @"org.jitsi.meet.OPEN_CHAT";
static NSString * const closeChatAction = @"org.jitsi.meet.CLOSE_CHAT";
static NSString * const sendChatMessageAction = @"org.jitsi.meet.SEND_CHAT_MESSAGE";
static NSString * const setVideoMutedAction = @"org.jitsi.meet.SET_VIDEO_MUTED";
@implementation ExternalAPI
@@ -47,7 +48,8 @@ RCT_EXPORT_MODULE();
@"RETRIEVE_PARTICIPANTS_INFO": retrieveParticipantsInfoAction,
@"OPEN_CHAT": openChatAction,
@"CLOSE_CHAT": closeChatAction,
@"SEND_CHAT_MESSAGE": sendChatMessageAction
@"SEND_CHAT_MESSAGE": sendChatMessageAction,
@"SET_VIDEO_MUTED" : setVideoMutedAction
};
};
@@ -70,7 +72,8 @@ RCT_EXPORT_MODULE();
retrieveParticipantsInfoAction,
openChatAction,
closeChatAction,
sendChatMessageAction
sendChatMessageAction,
setVideoMutedAction
];
}
@@ -153,7 +156,7 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:setAudioMutedAction body:data];
}
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message {
- (void)sendEndpointTextMessage:(NSString*)message :(NSString*)to {
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
data[@"to"] = to;
data[@"message"] = message;
@@ -185,7 +188,7 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:closeChatAction body:nil];
}
- (void)sendChatMessage:(NSString*)to :(NSString*)message {
- (void)sendChatMessage:(NSString*)message :(NSString*)to {
NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
data[@"to"] = to;
data[@"message"] = message;
@@ -193,4 +196,11 @@ RCT_EXPORT_METHOD(sendEvent:(NSString *)name
[self sendEventWithName:sendChatMessageAction body:data];
}
- (void)sendSetVideoMuted:(BOOL)muted {
NSDictionary *data = @{ @"muted": [NSNumber numberWithBool:muted]};
[self sendEventWithName:setVideoMutedAction body:data];
}
@end

View File

@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>3.1.0</string>
<string>3.2.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>

View File

@@ -23,6 +23,7 @@
#import "RCTBridgeWrapper.h"
#import "ReactUtils.h"
#import "RNSplashScreen.h"
#import "ScheenshareEventEmiter.h"
#import <RNGoogleSignin/RNGoogleSignin.h>
#import <WebRTC/RTCLogging.h>
@@ -31,6 +32,7 @@
@implementation JitsiMeet {
RCTBridgeWrapper *_bridgeWrapper;
NSDictionary *_launchOptions;
ScheenshareEventEmiter *_screenshareEventEmiter;
}
#pragma mak - This class is a singleton
@@ -50,6 +52,9 @@
if (self = [super init]) {
// Initialize the on and only bridge for interfacing with React Native.
_bridgeWrapper = [[RCTBridgeWrapper alloc] init];
// Initialize the listener for handling start/stop screensharing notifications.
_screenshareEventEmiter = [[ScheenshareEventEmiter alloc] init];
// Register a fatal error handler for React.
registerReactFatalErrorHandler();

View File

@@ -38,11 +38,12 @@
- (void)leave;
- (void)hangUp;
- (void)setAudioMuted:(BOOL)muted;
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message;
- (void)sendEndpointTextMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to;
- (void)toggleScreenShare;
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler;
- (void)openChat:(NSString*)to;
- (void)retrieveParticipantsInfo:(void (^ _Nonnull)(NSArray * _Nullable))completionHandler;
- (void)openChat:(NSString * _Nullable)to;
- (void)closeChat;
- (void)sendChatMessage:(NSString*)to :(NSString*)message;
- (void)sendChatMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to;
- (void)setVideoMuted:(BOOL)muted;
@end

View File

@@ -125,9 +125,9 @@ static void initializeViewsMap() {
[externalAPI sendSetAudioMuted:muted];
}
- (void)sendEndpointTextMessage:(NSString*)to :(NSString*)message {
- (void)sendEndpointTextMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI sendEndpointTextMessage:to :message];
[externalAPI sendEndpointTextMessage:message :to];
}
- (void)toggleScreenShare {
@@ -135,7 +135,7 @@ static void initializeViewsMap() {
[externalAPI toggleScreenShare];
}
- (void)retrieveParticipantsInfo:(void (^)(NSArray*))completionHandler {
- (void)retrieveParticipantsInfo:(void (^ _Nonnull)(NSArray * _Nullable))completionHandler {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI retrieveParticipantsInfo:completionHandler];
}
@@ -150,9 +150,14 @@ static void initializeViewsMap() {
[externalAPI closeChat];
}
- (void)sendChatMessage:(NSString*)to :(NSString*)message {
- (void)sendChatMessage:(NSString * _Nonnull)message :(NSString * _Nullable)to {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI sendChatMessage:to :message];
[externalAPI sendChatMessage:message :to];
}
- (void)setVideoMuted:(BOOL)muted {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI sendSetVideoMuted:muted];
}
#pragma mark Private methods
@@ -184,7 +189,7 @@ static void initializeViewsMap() {
// conference. However, React and, respectively,
// appProperties/initialProperties are declarative expressions i.e. one and
// the same URL will not trigger an automatic re-render in the JavaScript
// source code. The workaround implemented bellow introduces imperativeness
// source code. The workaround implemented below introduces imperativeness
// in React Component props by defining a unique value per invocation.
props[@"timestamp"] = @(mach_absolute_time());

View File

@@ -104,4 +104,11 @@
*/
- (void)chatToggled:(NSDictionary *)data;
/**
* Called when videoMuted state changed.
*
* The `data` dictionary contains a `muted` key with state of the videoMuted for the localParticipant.
*/
- (void)videoMutedChanged:(NSDictionary *)data;
@end

View File

@@ -0,0 +1,25 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface ScheenshareEventEmiter : NSObject
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,63 @@
/*
* Copyright @ 2021-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "ScheenshareEventEmiter.h"
#import "JitsiMeet+Private.h"
#import "ExternalAPI.h"
NSNotificationName const kBroadcastStartedNotification = @"iOS_BroadcastStarted";
NSNotificationName const kBroadcastStoppedNotification = @"iOS_BroadcastStopped";
@implementation ScheenshareEventEmiter {
CFNotificationCenterRef _notificationCenter;
}
- (instancetype)init {
self = [super init];
if (self) {
_notificationCenter = CFNotificationCenterGetDarwinNotifyCenter();
[self setupObserver];
}
return self;
}
- (void)dealloc {
[self clearObserver];
}
// MARK: Private Methods
- (void)setupObserver {
CFNotificationCenterAddObserver(_notificationCenter, (__bridge const void *)(self), broadcastToggleNotificationCallback, (__bridge CFStringRef)kBroadcastStartedNotification, NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(_notificationCenter, (__bridge const void *)(self), broadcastToggleNotificationCallback, (__bridge CFStringRef)kBroadcastStoppedNotification, NULL, CFNotificationSuspensionBehaviorDeliverImmediately);
}
- (void)clearObserver {
CFNotificationCenterRemoveObserver(_notificationCenter, (__bridge const void *)(self), (__bridge CFStringRef)kBroadcastStartedNotification, NULL);
CFNotificationCenterRemoveObserver(_notificationCenter, (__bridge const void *)(self), (__bridge CFStringRef)kBroadcastStoppedNotification, NULL);
}
void broadcastToggleNotificationCallback(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo) {
ExternalAPI *externalAPI = [[JitsiMeet sharedInstance] getExternalAPI];
[externalAPI toggleScreenShare];
}
@end

View File

@@ -76,7 +76,7 @@ internal final class JMCallKitEmitter: NSObject, CXProviderDelegate {
// Avoid mute actions ping-pong: if the mute action was caused by
// the JS side (we requested a transaction) don't call the delegate
// method. If it was called by the provder itself (when the user presses
// method. If it was called by the provider itself (when the user presses
// the mute button in the CallKit view) then call the delegate method.
//
// NOTE: don't try to be clever and remove this. Been there, done that.

View File

@@ -29,7 +29,7 @@ public protocol PiPViewCoordinatorDelegate: class {
/// when is presented in Picure in Picture mode.
public class PiPViewCoordinator {
/// Limits the boundries of view position on screen when minimized
/// Limits the boundaries of view position on screen when minimized
public var dragBoundInsets: UIEdgeInsets = UIEdgeInsets(top: 25,
left: 5,
bottom: 5,

View File

@@ -60,7 +60,7 @@ fi
echo "PR_REPO_SLUG=${PR_REPO_SLUG} PR_BRANCH=${PR_BRANCH}"
# do the marge and git log
# do the merge and git log
if [ $PR_BRANCH != "master" ]; then
echo "Will merge ${PR_REPO_SLUG}/${PR_BRANCH} into master"

View File

@@ -1,27 +1,52 @@
{
"en": "영어",
"af": "",
"af": "아프리칸스어",
"ar": "아랍어",
"az": "아제르바이잔어",
"bg": "불가리어",
"cs": "체코어",
"ca": "카탈루냐어",
"cs": "체코어",
"da": "덴마크어",
"de": "독일어",
"el": "그리스어",
"enGB": "영어(영국)",
"eo": "에스페란토어",
"es": "스페인어",
"esUS": "스페인어(라틴 아메리카)",
"et": "에스토니아어",
"eu": "바스크어",
"fi": "핀란드어",
"fr": "프랑스어",
"frCA": "프랑스어(캐나다)",
"he": "히브리어",
"mr":"마라티어",
"hr": "크로아티아어",
"hu": "헝가리어",
"hy": "아르메니아어",
"id": "인도네시아어",
"it": "이탈리아어",
"ja": "일본어",
"kab": "커바일어",
"ko": "한국어",
"nb": "노르웨이어",
"oc": "",
"lt": "리투아니아어",
"ml": "말라얄람어",
"lv": "라트비아어",
"nl": "네덜란드어",
"oc": "오크어",
"fa": "페르시아어",
"pl": "폴란드어",
"ptBR": "포르투갈어(브라질)",
"ru": "러시아어",
"ro": "루마니아어",
"sc": "사르데냐어",
"sk": "슬로바키아어",
"sl": "슬로베니아어",
"sr": "세르비아어",
"sv": "스웨덴어",
"th": "태국어",
"tr": "터키어",
"uk": "우크라이나어",
"vi": "베트남어",
"zhCN": "중국어(중국)"
}
"zhCN": "중국어(중국)",
"zhTW": "중국어(대만)"
}

View File

@@ -1,6 +1,7 @@
{
"addPeople": {
"add": "Inviter",
"add": "Invitér",
"countryNotSupported": "Vi supporterer ikke dette land endnu.",
"countryReminder": "Ringer du til uden for USA? Benyt venligst landekode!",
"disabled": "Du kan ikke invitere deltagere.",
@@ -15,33 +16,33 @@
"searchPeople": "Søg efter personer",
"searchPeopleAndNumbers": "Søg efter personer eller tilføj deres telefonnummer",
"telephone": "Telefon: {{number}}",
"title": "Inviter personer til dette møde"
"title": "Invitér personer til dette møde"
},
"audioDevices": {
"bluetooth": "Bluetooth",
"headphones": "Høretelefoner",
"phone": "Telefon",
"speaker": "Højtaler",
"none": "Der er ikke nogen lyd enheder tilgængelige"
"none": "Der er ikke nogen lydenheder tilgængelige"
},
"audioOnly": {
"audioOnly": "Kun lyd"
},
"calendarSync": {
"addMeetingURL": "Tilføj et mødelink",
"confirmAddLink": "Ønsker du at tilføj et Jitsi link til denne aftale?",
"confirmAddLink": "Ønsker du at tilføje et Jitsi link til denne aftale?",
"error": {
"appConfiguration": "Kalender integration er ikke sat korrekt op.",
"generic": "Der er sket en fejl. Verificer venligst dine kalenderindstilliinger eller prøv at genopfriske din kalender.",
"notSignedIn": "Der er sket en fejl under log ind for at hente kalenderaftalerne. Kontroller venligst dine kalenderindstilliinger og forsøg at logge ind igen."
"appConfiguration": "Kalenderintegration er ikke sat korrekt op.",
"generic": "Der er sket en fejl. Verificér venligst dine kalenderindstillinger eller prøv at genopfriske din kalender.",
"notSignedIn": "Der er sket en fejl under login for at hente kalenderaftalerne. Kontroller venligst dine kalenderindstillinger og forsøg at logge ind igen."
},
"join": "Deltag",
"joinTooltip": "Deltag i mødet",
"nextMeeting": "næste møde",
"noEvents": "Der er ikke nogen kommande aftaler i kalenderen.",
"ongoingMeeting": "igangværende møde",
"permissionButton": "Åben indstillinger",
"permissionMessage": "Kalender tilladelsen er nødvendig for at kunne se dine aftaler i appen.",
"nextMeeting": "Næste møde",
"noEvents": "Der er ikke nogen kommende aftaler i kalenderen.",
"ongoingMeeting": "Igangværende møde",
"permissionButton": "Åbn indstillinger",
"permissionMessage": "Kalendertilladelsen er nødvendig for at kunne se dine aftaler i appen.",
"refresh": "Genopfrisk aftaler",
"today": "I dag"
},
@@ -57,7 +58,7 @@
},
"privateNotice": "Privat besked til {{recipient}}",
"title": "Chat",
"you": "dig"
"you": "Dig"
},
"chromeExtensionBanner": {
"installExtensionText": "Installér plugin for Google Kalender og Office 365 integration",
@@ -69,8 +70,8 @@
},
"connection": {
"ATTACHED": "Forbundet",
"AUTHENTICATING": "Autoriserer",
"AUTHFAIL": "Autorisation lykkedes ikke",
"AUTHENTICATING": "Godkender",
"AUTHFAIL": "Godkendelse lykkedes ikke",
"CONNECTED": "Forbundet",
"CONNECTING": "Forbinder",
"CONNFAIL": "Forbindelse kunne ikke oprettes",
@@ -96,7 +97,7 @@
"localport": "Lokal port:",
"localport_plural": "Lokale porte:",
"more": "Vis mere",
"packetloss": "Pakke tab:",
"packetloss": "Pakketab:",
"quality": {
"good": "God",
"inactive": "Inaktiv",
@@ -133,9 +134,9 @@
"defaultNickname": "ex. Jane Pink",
"deviceError": {
"cameraError": "Kunne ikke forbinde til dit kamera",
"cameraPermission": "Kamera tilladelse mangler",
"cameraPermission": "Kameratilladelse mangler",
"microphoneError": "Kunne ikke forbinde til din mikrofon",
"microphonePermission": "Mikrofon tilladelse mangler"
"microphonePermission": "Mikrofontilladelse mangler"
},
"deviceSelection": {
"noPermission": "Tilladelse ikke givet",
@@ -145,21 +146,21 @@
},
"dialog": {
"accessibilityLabel": {
"liveStreaming": "Live Stream"
"liveStreaming": "Livestream"
},
"allow": "Tillad",
"alreadySharedVideoMsg": "En anden deltager deler allerede en video. Denne konference tillader kun en delt video af gangen.",
"alreadySharedVideoTitle": "Det er kun muligt at dele en video af gangen",
"applicationWindow": "Applikations vindue",
"alreadySharedVideoTitle": "Det er kun muligt at dele én video ad gangen",
"applicationWindow": "Applikationsvindue",
"Back": "Tilbage",
"cameraConstraintFailedError": "Dit kamera lever ikke op til de nødvendige krav..",
"cameraNotFoundError": "Kamera kunne ikke findes.",
"cameraNotSendingData": "Vi kan ikke tilgå dit kamera. Kontroller venligst om der er en anden applikation der gør brug af dit kamera, eller vælg en andet kamera og genindlæs siden.",
"cameraNotSendingData": "Vi kan ikke tilgå dit kamera. Kontrollér venligst om der er en anden applikation der gør brug af dit kamera, eller vælg et andet kamera og genindlæs siden.",
"cameraNotSendingDataTitle": "Kan ikke tilgå kamera",
"cameraPermissionDeniedError": "Du har ikke givet tilladelse til at bruge dit kamera. Du kan stadig deltage i mødet men de andre deltagere vil ikke kunne se dig. Gør brug af kamera knappen i adressebaren for at give tilladelse.",
"cameraUnknownError": "Kan ikke gør brug af dit kamera, årsag ukendt.",
"cameraUnsupportedResolutionError": "Dit kamera supporterer ikke den nødvendige opløsning.",
"Cancel": "Afbryd",
"cameraPermissionDeniedError": "Du har ikke givet tilladelse til at bruge dit kamera. Du kan stadig deltage i mødet, men de andre deltagere vil ikke kunne se dig. Gør brug af kameraknappen i adressebaren for at give tilladelse.",
"cameraUnknownError": "Kan ikke gøre brug af dit kamera, årsag ukendt.",
"cameraUnsupportedResolutionError": "Dit kamera understøtter ikke den nødvendige opløsning.",
"Cancel": "Annullér",
"close": "Luk",
"conferenceDisconnectMsg": "Kontroller venligst din netværksforbindelse. Forbinder igen om {{seconds}} sekunder…",
"conferenceDisconnectTitle": "Din forbindelse er blevet afbrudt.",
@@ -172,31 +173,31 @@
"connectErrorWithMsg": "Det var ikke muligt at forbinde til mødet: {{msg}}",
"connecting": "Forbinder",
"contactSupport": "Kontakt support",
"copy": "Kopier invitation",
"dismiss": "Afbryd",
"copy": "Kopiér invitation",
"dismiss": "Afvis",
"displayNameRequired": "Navn/alias er påkrævet",
"done": "Gem",
"enterDisplayName": "Indtast venligst dit navn/alias",
"error": "Fejl",
"externalInstallationMsg": "Du skal installerer vores skærmdelings plugin.",
"externalInstallationMsg": "Du skal installere vores skærmdelingsplugin.",
"externalInstallationTitle": "Plugin skal bruges",
"goToStore": "Gå til webstore",
"gracefulShutdown": "Vores service er pt. under vedligeholdese. Forsøg venligst igen senere.",
"gracefulShutdown": "Vores service er pt. under vedligeholdelse. Prøv igen senere.",
"IamHost": "Jeg er vært",
"incorrectRoomLockPassword": "",
"incorrectPassword": "Forkert brugernavn eller adgangskode",
"inlineInstallationMsg": "Du skal installerer vores skærmdelings plugin.",
"inlineInstallExtension": "Installer nu",
"inlineInstallationMsg": "Du skal installere vores skærmdelingsplugin.",
"inlineInstallExtension": "Installér nu",
"internalError": "Der er opstået en fejl: {{error}}",
"internalErrorTitle": "Intern fejl",
"kickMessage": "Du er blevet afbrudt fra mødet!",
"kickParticipantButton": "Afbryd",
"kickParticipantDialog": "Er du sikker på at du vil afbryde den deltager?",
"kickParticipantTitle": "Afbryd denne deltager?",
"kickTitle": "Afbrudt fra møde",
"liveStreaming": "Live Streaming",
"liveStreamingDisabledForGuestTooltip": "Gæster kan ikke starte en live stream.",
"liveStreamingDisabledTooltip": "Live streaming er slået fra.",
"kickParticipantButton": "Smid ud",
"kickParticipantDialog": "Er du sikker på at du vil smide denne deltager ud?",
"kickParticipantTitle": "Smid denne deltager ud?",
"kickTitle": "Smidt ud af mødet",
"liveStreaming": "Livestreaming",
"liveStreamingDisabledForGuestTooltip": "Gæster kan ikke starte en livestream.",
"liveStreamingDisabledTooltip": "Livestreaming er slået fra.",
"lockMessage": "Kunne ikke sikre mødet.",
"lockRoom": "Tilføj adgangskode",
"lockTitle": "Sikring fejlet",
@@ -208,79 +209,79 @@
"micNotFoundError": "Mikrofon ikke fundet.",
"micNotSendingData": "Vi kunne ikke tilgå din mikrofon. Vælg en anden mikrofon under indstillinger eller genindlæs applikationen.",
"micNotSendingDataTitle": "Kunne ikke tilgå din mikrofon",
"micPermissionDeniedError": "Du har ikke givet tilladelse til at bruge din mikrofon. Du kan stadig deltage i mødet men de andre deltagere kan ikke høre dig. Benyt kamera knappen i adressbaren for at give tilladelse.",
"micPermissionDeniedError": "Du har ikke givet tilladelse til at bruge din mikrofon. Du kan stadig deltage i mødet men de andre deltagere kan ikke høre dig. Benyt kameraknappen i adressebaren for at give tilladelse.",
"micUnknownError": "Kan ikke tilgå mikrofon af ukendt årsag.",
"muteEveryoneElseDialog": "Er du sikker på at du vil slå lyden fra for denne deltager? Du kan ikke tænde igen, men de kan selv tænde til enhver tid.",
"muteEveryoneElseDialog": "Er du sikker på at du vil slå lyden fra for alle andre end denne deltager? Du kan ikke tænde lyden igen, men de kan selv tænde til enhver tid.",
"muteEveryoneElseTitle": "Slå lyd fra for alle undtagen {{whom}}?",
"muteEveryoneDialog": "Er du sikker på at du vil slå lyden fra for denne deltager? Du kan ikke tænde igen, men de kan selv tænde til enhver tid.",
"muteEveryoneDialog": "Er du sikker på at du vil slå lyden fra for alle? Du kan ikke tænde lyden igen, men de kan selv tænde til enhver tid.",
"muteEveryoneTitle": "Slå lyd fra for alle?",
"muteEveryoneSelf": "dig selv",
"muteEveryoneStartMuted": "Lyden er slpet fra for alle fra nu af",
"muteEveryoneSelf": "Dig selv",
"muteEveryoneStartMuted": "Lyden er slået fra for alle fra nu af",
"muteParticipantBody": "Du kan ikke tænde for deres mikrofon, men de kan selv tænde for deres mikrofon til enhver tid.",
"muteParticipantButton": "Slå lyd fra",
"muteParticipantDialog": "Er du sikker på at du vil slå lyden fra for denne deltager? Du kan ikke tænde igen, men de kan selv tænde til enhver tid.",
"muteParticipantTitle": "Slå lyd fra for denne deltager?",
"Ok": "Ok",
"muteParticipantTitle": "Slå lyden fra for denne deltager?",
"Ok": "OK",
"passwordLabel": "Adgangskode",
"passwordNotSupported": "Sætte en adgangskode for mødet er ikke understøttet.",
"passwordNotSupported": "Det er ikke understøttet at sætte en adgangskode for mødet",
"passwordNotSupportedTitle": "Adgangskode er ikke understøttet",
"passwordRequired": "Adgangskode påkrævet",
"popupError": "Din browser blockerer for pop-upper fra denne hjemmeside. Slå venligst pop-upper til i din browsers indstillinger og forsøg igen.",
"popupErrorTitle": "Pop-up blokkeret",
"popupError": "Din browser blokerer for pop op-vinduer fra denne hjemmeside. Slå venligst pop op-vinduer til i din browsers indstillinger og forsøg igen.",
"popupErrorTitle": "Pop op-vinduer er blokeret",
"recording": "Optager",
"recordingDisabledForGuestTooltip": "Gæster kan ikke starte en optagelse.",
"recordingDisabledTooltip": "Start optagelse er slået fra.",
"recordingDisabledForGuestTooltip": "Gæster kan ikke starte en optagelse",
"recordingDisabledTooltip": "Optagefunktionalitet er slået fra",
"rejoinNow": "Deltag igen",
"remoteControlAllowedMessage": "{{user}} accepterede din fjernstyring anmodning!",
"remoteControlDeniedMessage": "{{user}} afviste din fjernstyring anmodning!",
"remoteControlAllowedMessage": "{{user}} accepterede din anmodning om fjernstyring!",
"remoteControlDeniedMessage": "{{user}} afviste din anmodning om fjernstyring!",
"remoteControlErrorMessage": "En fejl er opstået ved anmodning om fjernstyring for {{user}}!",
"remoteControlRequestMessage": "Vil du tillade at {{user}} fjerstyrer din computer?",
"remoteControlShareScreenWarning": "Bemærk at hvis du vælger \"Tillad\" så vil du tillade fjernstyring!",
"remoteControlStopMessage": "Fjernstyrings sessionen er afsluttet!",
"remoteControlTitle": "Fjerstyring",
"remoteControlStopMessage": "Fjernstyringssessionen er afsluttet!",
"remoteControlTitle": "Fjernstyring",
"Remove": "Fjern",
"removePassword": "Fjern adgangskode",
"removeSharedVideoMsg": "Er du sikker på at du vil fjerne di delte video?",
"removeSharedVideoMsg": "Er du sikker på at du vil fjerne din delte video?",
"removeSharedVideoTitle": "Fjern delt video",
"reservationError": "Reservation - system fejl",
"reservationErrorMsg": "Fejlkode: {{code}}, fejl: {{msg}}",
"retry": "Forsøg igen",
"screenSharingFailedToInstall": "Skærmdelings-plugin kunne ikke installeres.",
"screenSharingFailedToInstallTitle": "Skærmdelings-plugin kunne ikke installeres.",
"screenSharingFirefoxPermissionDeniedError": "Noget gik galt under skærmdeling. Kontroller venligst at du har givet tilladelse til skærmdeling. ",
"screenSharingFirefoxPermissionDeniedError": "Noget gik galt under skærmdeling. Kontrollér venligst at du har givet tilladelse til skærmdeling. ",
"screenSharingFirefoxPermissionDeniedTitle": "Skærmdeling kunne ikke startes!",
"screenSharingPermissionDeniedError": "Noget gik galt under skærmdeling. Kontroller venligst at du har givet tilladelse til skærmdeling. Genindlæs siden og forsøg igen.",
"sendPrivateMessage": "Du har modtage en privat besked. Ønsker du at svare private eller øsnker du at svare til gruppen?",
"screenSharingPermissionDeniedError": "Noget gik galt under skærmdeling. Kontrollér venligst at du har givet tilladelse til skærmdeling. Genindlæs siden og forsøg igen.",
"sendPrivateMessage": "Du har modtaget en privat besked. Ønsker du at svare privat eller til gruppen?",
"sendPrivateMessageCancel": "Send til gruppen",
"sendPrivateMessageOk": "Send privat",
"sendPrivateMessageTitle": "Send privat?",
"serviceUnavailable": "Service er ikke tilgængelig",
"sessTerminated": "Møde afsluttet",
"Share": "Del",
"shareVideoLinkError": "Angiv venligst et validt Youtube link.",
"shareVideoLinkError": "Angiv venligst et gyldigt YouTube link.",
"shareVideoTitle": "Del en video",
"shareYourScreen": "Del din skærm",
"shareYourScreenDisabled": "Skærmdeling er ikke slået til.",
"shareYourScreenDisabledForGuest": "Gæster kan ikke dele deres skærm.",
"startLiveStreaming": "Start live stream",
"startLiveStreaming": "Start livestream",
"startRecording": "Start optagelse",
"startRemoteControlErrorMessage": "Der er sket en fejl under opstart af fjern kontrol sessionen!",
"stopLiveStreaming": "Stop live stream",
"startRemoteControlErrorMessage": "Der er sket en fejl under opstart af fjernstyringssessionen!",
"stopLiveStreaming": "Stop livestream",
"stopRecording": "Stop optagelse",
"stopRecordingWarning": "Er du sikker på at du ønsker at stoppe optagelesen?",
"stopStreamingWarning": "Er du sikker på at du ønsker at stoppe live streaming?",
"streamKey": "Live stream nøgle",
"stopRecordingWarning": "Er du sikker på at du ønsker at stoppe optagelsen?",
"stopStreamingWarning": "Er du sikker på at du ønsker at stoppe livestreaming?",
"streamKey": "Livestream-nøgle",
"Submit": "Gem",
"thankYou": "Tak for at du har benyttet {{appName}}!",
"token": "token",
"tokenAuthFailed": "Beklager, du kan ikke deltage i dette møde.",
"tokenAuthFailedTitle": "Log ind fejlede",
"transcribing": "Transcribering",
"unlockRoom": "Fjern møde adgangskode",
"userPassword": "bruger adgangskode",
"WaitForHostMsg": "Mødet <b>{{room}}</b> er ikke startet endnu. Hvis du er hosten log venligst ind, ellers vent på at hosten kommer.",
"WaitForHostMsgWOk": "Mødet <b>{{room}}</b> er ikke startet endnu. Hvis du er hosten tryk venligst på OK for at logge ind, ellers vent på at hosten kommer.",
"WaitingForHost": "Venter på host …",
"tokenAuthFailedTitle": "Login fejlede",
"transcribing": "Transskribering",
"unlockRoom": "Fjern mødeadgangskode",
"userPassword": "Brugeradgangskode",
"WaitForHostMsg": "Mødet <b>{{room}}</b> er ikke startet endnu. Hvis du er værten, log venligst ind. Ellers vent på at værten kommer",
"WaitForHostMsgWOk": "Mødet <b>{{room}}</b> er ikke startet endnu. Hvis du er værten, tryk venligst på OK for at logge ind. Ellers vent på at værten kommer.",
"WaitingForHost": "Venter på vært …",
"Yes": "Ja",
"yourEntireScreen": "Hele din skærm"
},
@@ -295,37 +296,37 @@
"bad": "Dårlig",
"detailsLabel": "Uddyb.",
"good": "God",
"rateExperience": "Vurder din oplevelse",
"rateExperience": "Vurdér din oplevelse",
"veryBad": "Meget dårlig",
"veryGood": "Meget god"
},
"incomingCall": {
"answer": "Besvar",
"audioCallTitle": "Indkommende opkald",
"audioCallTitle": "Indende opkald",
"decline": "Afvis",
"productLabel": "fra Appinux skærmbesøg",
"videoCallTitle": "Indkommende videoopkald"
"productLabel": "Fra Appinux skærmbesøg",
"videoCallTitle": "Indende videoopkald"
},
"info": {
"accessibilityLabel": "Vis info",
"addPassword": "Tilføj adgangskode",
"cancelPassword": "Annulé adgangskode",
"cancelPassword": "Annullér adgangskode",
"conferenceURL": "Link:",
"country": "Land",
"dialANumber": "For at deltage i mødet ring til et af følgende telefonnumre og indtast pinkode.",
"dialInConferenceID": "Pinkode:",
"dialInNotSupported": "Deltagelse vis telfonen er pt. ikke understøttet.",
"dialInNotSupported": "Deltagelse via telefonopkald er pt. ikke understøttet.",
"dialInNumber": "Ring ind:",
"dialInSummaryError": "Der er opstået en fejl under hentning af ring ind information. Forsøg venligst igen senere.",
"dialInSummaryError": "Der er opstået en fejl under indhenting af telefonopkaldsdetaljer. Forsøg venligst igen senere.",
"dialInTollFree": "Gratis",
"genericError": "Der er opstået en fejl",
"inviteLiveStream": "For at se en live stream i dette møde klik på dette link: {{url}}",
"inviteLiveStream": "For at se en livestream i dette møde klik på dette link: {{url}}",
"invitePhone": "Ring-ind: {{number}},,{{conferenceID}}#\n",
"invitePhoneAlternatives": "",
"inviteURLFirstPartGeneral": "Der er blevet inviteret til at deltage i et møde.",
"inviteURLFirstPartPersonal": "{{name}} inviterer dig til at deltage i et møde.\n",
"inviteURLSecondPart": "\nDeltag i mødet:\n{{url}}\n",
"liveStreamURL": "Live stream:",
"liveStreamURL": "Livestream:",
"moreNumbers": "Flere telefonnumre",
"noNumbers": "Ring-ind nummer findes ikke.",
"noPassword": "Ingen",
@@ -333,8 +334,8 @@
"numbers": "Ring-ind numre",
"password": "Adgangskode:",
"title": "Del",
"tooltip": "Del link og rind-ind information for dette møde",
"label": "Møde information"
"tooltip": "Del link og ring-ind information for dette møde",
"label": "Mødeinformation"
},
"inviteDialog": {
"alertText": "Kunne ikke invitere nogle af deltagerne.",
@@ -348,54 +349,54 @@
"msg": "Der er opstået en fejl.",
"retry": "Forsøg igen",
"support": "Support",
"supportMsg": "Hvis denne fejl bliver ved, kontakt"
"supportMsg": "Hvis denne fejl bliver ved, kontakt da support"
},
"keyboardShortcuts": {
"focusLocal": "Fokusér på din video",
"focusRemote": "Fokusér på en anden persons video",
"focusLocal": "Sæt fokus din video",
"focusRemote": "Sæt fokus på en anden persons billede",
"fullScreen": "Vis eller annullér fuld skærm",
"keyboardShortcuts": "Tastaturgenveje",
"localRecording": "Vis eller skjul optage kontrolknapper",
"mute": "Slå lyd fra eller til for din mikrofon",
"localRecording": "Vis eller skjul optagelseskontrolknapper",
"mute": "Slå din mikrofon til eller fra",
"pushToTalk": "Tryk for at tale",
"raiseHand": "Lyft eller sænk din hånd",
"showSpeakerStats": "Vis højtaler statistik",
"toggleChat": "Åben eller luk chat",
"toggleFilmstrip": "Vis eller skjul video små billeder",
"toggleScreensharing": "Skift mellem video og skærmdeling",
"raiseHand": "Løft eller sænk din hånd",
"showSpeakerStats": "Vis højtalerstatistik",
"toggleChat": "Åbn eller luk chat",
"toggleFilmstrip": "Vis eller skjul små videobilleder",
"toggleScreensharing": "Skift mellem video- og skærmdeling",
"toggleShortcuts": "Vis eller skjul tastaturgenveje",
"videoMute": "Tænd eller sluk dit kamera",
"videoQuality": "Indstil opkaldskvalitet"
"videoQuality": "Indstil videokvalitet"
},
"liveStreaming": {
"busy": "Der arbejdes på at frigive streamingresourcer, forsøg venligst igen om et par minutter.",
"busyTitle": "Alle streamers er optaget",
"busy": "Der arbejdes på at frigive streamingressourcer, forsøg venligst igen om et par minutter.",
"busyTitle": "Alle streams er optaget",
"changeSignIn": "Skift konto.",
"choose": "Vælg en live stream",
"chooseCTA": "Vælg en stream mulighed. Du er pt. logget ind som {{email}}.",
"enterStreamKey": "Indtast din Youtube live stream her.",
"error": "Fejl under live streaming. Forsøg venligst igen.",
"choose": "Vælg en livestream",
"chooseCTA": "Vælg en stream-mulighed. Du er pt. logget ind som {{email}}.",
"enterStreamKey": "Indtast din livestream-nøgle til Youtube her.",
"error": "Fejl under livestreaming. Forsøg venligst igen.",
"errorAPI": "En fejl opstod ved forsøg på at tilgå din YouTube-broadcast. Forsøg venligst at logge ind igen.",
"errorLiveStreamNotEnabled": "Live Streaming er ikke slpet til for {{email}}. Slå venligst live streaming til eller log ind på en konto der har live streaming slået til.",
"expandedOff": "Live stream er stoppet",
"errorLiveStreamNotEnabled": "Livestreaming er ikke slået til for {{email}}. Slå venligst livestreaming til eller log ind på en konto der har livestreaming slået til.",
"expandedOff": "Livestream er stoppet",
"expandedOn": "Mødet bliver pt. streamet til Youtube.",
"expandedPending": "Live streaming starter…",
"failedToStart": "Kunne ikke starte live streaming",
"getStreamKeyManually": "Vi kunne ikke hente nogle live streams. Forsøg at hente din live stream nøgle fra Youtube.",
"invalidStreamKey": "Live stream nøgle er muligvis forkert.",
"off": "Live Streaming er stoppet",
"offBy": "{{name}} stoppede live streaming",
"on": "Live Streaming",
"onBy": "{{name}} startede live streaming",
"pending": "Starter Live Stream…",
"serviceName": "Live Streaming service",
"expandedPending": "Livestreaming starter…",
"failedToStart": "Kunne ikke starte livestreaming",
"getStreamKeyManually": "Vi kunne ikke hente nogle livestreams. Forsøg at hente din livestream-nøgle fra YouTube.",
"invalidStreamKey": "Livestream-nøgle er muligvis forkert.",
"off": "Livestreaming er stoppet",
"offBy": "{{name}} stoppede livestreaming",
"on": "Livestreaming",
"onBy": "{{name}} startede livestreaming",
"pending": "Starter livestream…",
"serviceName": "Livestreaming-service",
"signedInAs": "Du er pt. logget ind som:",
"signIn": "Log ind med Google",
"signInCTA": "Log ind eller indtast din live stream nøgle fra YouTube.",
"signInCTA": "Log ind eller indtast din livestream-nøgle fra YouTube.",
"signOut": "Log ud",
"start": "Start en live stream",
"start": "Start en livestream",
"streamIdHelp": "Hvad er dette?",
"unavailableTitle": "Live Streaming er ikke tilgængelig"
"unavailableTitle": "Livestreaming er ikke tilgængelig"
},
"localRecording": {
"clientState": {
@@ -403,24 +404,24 @@
"on": "Slået til",
"unknown": "Ukendt"
},
"dialogTitle": "Optage kontrolknapper",
"dialogTitle": "Optagelseskontrolknapper",
"duration": "Varighed",
"durationNA": "Ikke tilgængelig",
"encoding": "Encoding",
"label": "Optager",
"labelToolTip": "Optager er slået til",
"localRecording": "Local Recording",
"labelToolTip": "Optagelse er slået til",
"localRecording": "Lokal optagelse",
"me": "Mig",
"messages": {
"engaged": "Optager er slået til.",
"finished": "Optagelses session {{token}} afsluttet. Send venligst den optagede fil til moderator.",
"finishedModerator": "Optagelses session {{token}} afsluttet. Optagelsen er gemt. Bed deltageren om at sende deres optagelser.",
"engaged": "Optagelse er slået til.",
"finished": "Optagelse {{token}} afsluttet. Send venligst den optagne fil til moderator.",
"finishedModerator": "Optagelse {{token}} afsluttet. Optagelsen er gemt. Bed deltageren om at sende deres optagelser.",
"notModerator": "Du er ikke moderator. Du kan ikke starte eller stoppe optagelser."
},
"moderator": "Moderator",
"no": "Nej",
"participant": "Deltager",
"participantStats": "Deltager statistik",
"participantStats": "Deltagerstatistik",
"sessionToken": "Sessionsnøgle",
"start": "Start optagelse",
"stop": "Stop optagelse",
@@ -433,19 +434,19 @@
"connectedOneMember": "{{name}} deltager nu i mødet",
"connectedThreePlusMembers": "{{name}} og {{count}} andre deltager nu i mødet",
"connectedTwoMembers": "{{first}} og {{second}} deltager nu i mødet",
"disconnected": "afbrudt",
"focus": "Konference fokus",
"disconnected": "Afbrudt",
"focus": "Konferencefokus",
"focusFail": "{{component}} ikke tilgængelig - forsøg igen om {{ms}} sekunder",
"grantedTo": "Moderator rettigheder er givet til {{to}}!",
"grantedTo": "Moderatorrettigheder er givet til {{to}}!",
"invitedOneMember": "{{name}} er blevet inviteret",
"invitedThreePlusMembers": "{{name}} og {{count}} andre er blevet inviteret",
"invitedTwoMembers": "{{first}} og {{second}} er blevet inviteret",
"kickParticipant": "{{kicked}} blev afbrudt fra mødet af {{kicker}}",
"me": "Mig",
"moderator": "Moderator rettigheder givet!",
"moderator": "Moderatorrettigheder givet",
"muted": "Du har startet samtalen med lyden slået fra.",
"mutedTitle": "Din lyd er slået fra!",
"mutedRemotelyTitle": "Din lyd er slået fra af {{participantDisplayName}}!",
"mutedTitle": "Din lyd er slået fra",
"mutedRemotelyTitle": "Din lyd er slået fra af {{participantDisplayName}}",
"mutedRemotelyDescription": "",
"passwordRemovedRemotely": "",
"passwordSetRemotely": "",
@@ -453,16 +454,16 @@
"somebody": "Nogen",
"startSilentTitle": "",
"startSilentDescription": "",
"suboptimalExperienceDescription": "Hmmm... vi er bange for at din oplevelse med {{appName}} ikke vil være optimal. Vi arbejder på at forbedre dette, men indtil da forsøg venligst at bruge en af følgende <a href='{{recommendedBrowserPageLink}}' target='_blank'>fuldt understøttede internet browsere</a>.",
"suboptimalExperienceTitle": "Browser Advarsel",
"suboptimalExperienceDescription": "Hmmm... vi er bange for at din oplevelse med {{appName}} ikke vil være optimal. Vi arbejder på at forbedre dette, men indtil da forsøg venligst at bruge en af følgende <a href='{{recommendedBrowserPageLink}}' target='_blank'>fuldt understøttede internet browsere</a>.",
"suboptimalExperienceTitle": "Browser-advarsel",
"unmute": "",
"newDeviceCameraTitle": "Nyt kamerat fundet",
"newDeviceAudioTitle": "Ny lyd enhed fundet",
"newDeviceCameraTitle": "Nyt kamera fundet",
"newDeviceAudioTitle": "Ny lydenhed fundet",
"newDeviceAction": "Benyt"
},
"passwordSetRemotely": "sat af et andet medlem",
"passwordSetRemotely": "Sat af et andet medlem",
"passwordDigitsOnly": "Op til {{number}} tal",
"poweredby": "powered by",
"poweredby": "Powered by",
"presenceStatus": {
"busy": "Optaget",
"calling": "Ringer op…",
@@ -479,8 +480,8 @@
},
"profile": {
"setDisplayNameLabel": "Vælg navn/alias",
"setEmailInput": "Indtast email",
"setEmailLabel": "Indtast Gravatar-e-post",
"setEmailInput": "Indtast email-adresse",
"setEmailLabel": "Indtast Gravatar-email-adresse",
"title": "Profil"
},
"raisedHand": "Ønsker at tale",
@@ -488,13 +489,13 @@
"authDropboxText": "Upload til Dropbox",
"availableSpace": "Tilgængelig plads: {{spaceLeft}} MB (plads til ca. {{duration}} minutters optagelse)",
"beta": "BETA",
"busy": "Der arbejdes på at frigive optagelsesresourcer. Prøv venligst igen om nogle få minutter.",
"busyTitle": "Alle optagere er pt optaget",
"busy": "Der arbejdes på at frigive optagelsesressourcer. Prøv venligst igen om nogle få minutter.",
"busyTitle": "Alle optagere er pt. optaget",
"error": "Fejl under optagelse, forsøg venligst igen om lidt.",
"expandedOff": "Optagelse er stoppet½",
"expandedOn": "Mødet bliver pt. optaget.",
"expandedOff": "Optagelse er stoppet",
"expandedOn": "Mødet bliver pt. optaget",
"expandedPending": "Optagelse starter…",
"failedToStart": "Kunne ikke start optagelse",
"failedToStart": "Kunne ikke starte optagelse",
"fileSharingdescription": "Del optagelse med deltagere",
"live": "LIVE",
"loggedIn": "Logget ind som {{userName}}",
@@ -504,22 +505,22 @@
"onBy": "{{name}} startede optagelsen",
"pending": "Gør klar til at optage mødet…",
"rec": "REC",
"serviceDescription": "Din optagelse bliver gemt af optager servicen",
"serviceName": "Optager service",
"serviceDescription": "Din optagelse bliver gemt af optagelsesservicen",
"serviceName": "Optagelsesservice",
"signIn": "Log ind",
"signOut": "Log ud",
"unavailable": "Optager service {{serviceName}} er ikke tilgængelig. Der arbejdes på at løse problemet, forsøg igen senere.",
"unavailable": "Optagelsesservice {{serviceName}} er ikke tilgængelig. Der arbejdes på at løse problemet, forsøg igen senere.",
"unavailableTitle": "Optagelse ikke tilgængelig"
},
"sectionList": {
"pullToRefresh": "Træk ned for update"
"pullToRefresh": "Træk ned for at opdatere"
},
"settings": {
"calendar": {
"about": "{{appName}}s kalenderintegration benyttes til at sikkert tilgå din kalender så den kan læse fremtidige aftaler.",
"about": "{{appName}}s kalenderintegration benyttes til sikkert at tilgå din kalender så den kan læse fremtidige aftaler.",
"disconnect": "Afbryd",
"microsoftSignIn": "Log ind med Microsoft",
"signedIn": "Henter kalenderaftaler for {{email}}. Tryk på Afbryd knappen for at afbryde forbindelsen.",
"signedIn": "Henter kalenderaftaler for {{email}}. Tryk på Afbryd for at afbryde forbindelsen.",
"title": "Kalender"
},
"devices": "Enheder",
@@ -530,28 +531,28 @@
"more": "Mere",
"name": "Navn",
"noDevice": "Ingen",
"selectAudioOutput": "Lyd udgang",
"selectAudioOutput": "Lydudgang",
"selectCamera": "Kamera",
"selectMic": "Mikrofon",
"startAudioMuted": "Alle starter med lyden slået fra",
"startVideoMuted": "Alle starter skjult",
"startVideoMuted": "Alle starter med video slået fra",
"title": "Indstillinger"
},
"settingsView": {
"advanced": "Avanceret",
"alertOk": "OK",
"alertTitle": "Advarsel",
"alertURLText": "Den indtastede server url er ikke korrekt",
"alertURLText": "Den indtastede server-URL er ikke korrekt",
"buildInfoSection": "Build Information",
"conferenceSection": "Konference",
"disableCallIntegration": "Slå indbygget opkalds integration fra",
"disableCallIntegration": "Slå indbygget opkaldsintegration fra",
"disableP2P": "Slå Peer-To-Peer fra",
"displayName": "Navn/alias",
"email": "Email",
"header": "Indstillinger",
"profileSection": "Profil",
"serverURL": "Server URL",
"showAdvanced": "Show advanced settings",
"serverURL": "Server-URL",
"showAdvanced": "Vis avancerede indstillinger",
"startWithAudioMuted": "Start med lyden slået fra",
"startWithVideoMuted": "Start med video slået fra",
"version": "Version"
@@ -560,18 +561,18 @@
"dialInfoText": "\n\n=====\n\nØnsker du at ringe ind fra din telefon?\n\n{{defaultDialInNumber}}Klik på dette link for at se telefonnummeret for dette møde\n{{dialInfoPageUrl}}",
"mainText": "Klik på det følgende link for at deltage i mødet:\n{{roomUrl}}"
},
"speaker": "Højtaler",
"speaker": "Deltager",
"speakerStats": {
"hours": "{{count}}t",
"minutes": "{{count}}m",
"name": "Navn",
"seconds": "{{count}}s",
"speakerStats": "Højtaler info",
"speakerTime": "Højtaler tid"
"speakerStats": "Deltagerstatistik",
"speakerTime": "Taletid"
},
"startupoverlay": {
"policyText": " ",
"title": "{{app}} har brug for adgang til din mikrofon og kamera."
"title": "{{app}} har brug for tilladelse til din mikrofon og dit kamera."
},
"suspendedoverlay": {
"rejoinKeyTitle": "Forbind igen",
@@ -582,157 +583,157 @@
"accessibilityLabel": {
"audioOnly": "Tænd/sluk lyd",
"audioRoute": "Vælg lydenhed",
"callQuality": "Indstil møde kvalitet",
"cc": "Slå undertekst fra/til",
"callQuality": "Indstil opkaldskvalitet",
"cc": "Slå undertekster fra/til",
"chat": "Slå chat fra/til",
"document": "Slå delte dokumenter fra/til",
"download": "Hent vores apps",
"feedback": "Giv tilbagemelding",
"feedback": "Giv feedback",
"fullScreen": "Slå fuld skærm fra/til",
"hangup": "Forlad mødet",
"help": "Hjælp",
"invite": "Inviter deltagere",
"kick": "Afbryd deltager",
"localRecording": "Slå optagekontroller fra/til",
"invite": "Invitér deltagere",
"kick": "Smid deltager ud",
"localRecording": "Slå optagelseskontrol fra/til",
"lockRoom": "Slå mødeadgangskode fra/til",
"moreActions": "Slå \"Flere indstillinger\" menu fra/til",
"moreActionsMenu": "Flere indtstillinger",
"moreOptions": "Show more options",
"moreActionsMenu": "Flere indstillinger",
"moreOptions": "Vis flere indstillinger",
"mute": "Slå lyd til/fra",
"muteEveryone": "Mute everyone",
"muteEveryone": "Slå lyd fra for alle",
"pip": "Slå Billede-i-billede fra/til",
"privateMessage": "Send privat besked",
"privateMessage": "Send privatbesked",
"profile": "Redigér profil",
"raiseHand": "Slå løft hånden fra/til",
"recording": "Slå optagelse til/fra",
"remoteMute": "Slå lyd fra for deltager",
"Settings": "Slå indstillinger fra/til",
"sharedvideo": "Slå YouTube video deling fra/til",
"sharedvideo": "Slå YouTube-videodeling fra/til",
"shareRoom": "Invitér nogen",
"shareYourScreen": "Slå skærmdeling fra/til",
"shortcuts": "Slå genveje fra/til",
"show": "Vis",
"speakerStats": "Slå højtaler info fra/til",
"tileView": "Slå tileview fra/til",
"speakerStats": "Slå højtalerinfo fra/til",
"tileView": "Slå gittervisning fra/til",
"toggleCamera": "Slå kamera fra/til",
"videomute": "Slå video fra/til",
"videoblur": "Slå baggrundsløring fra/til"
"videoblur": "Slå baggrundssløring fra/til"
},
"addPeople": "Tilføj deltager til mødet",
"audioOnlyOff": "Slå kun-lyd møder fra",
"audioOnlyOn": "Slå kun-lyd møder til",
"audioRoute": "Vælg lydenhed",
"authenticate": "Log ind",
"callQuality": "Indstil møde kvalitet",
"chat": "Åben / Luk chat",
"callQuality": "Indstil opkaldskvalitet",
"chat": "Åbn/luk chat",
"closeChat": "Luk chat",
"documentClose": "Luk delt dokument",
"documentOpen": "Åben delt dokument",
"download": "Hent vores apps",
"enterFullScreen": "Vis fuld skærm",
"enterTileView": "Tileview",
"enterTileView": "Gittervisning",
"exitFullScreen": "Luk fuld skærm",
"exitTileView": "Luk Tileview",
"feedback": "Giv tilbagemeldign",
"exitTileView": "Luk gittervisning",
"feedback": "Giv feedback",
"hangup": "Forlad",
"help": "Hjælp",
"invite": "Invitér deltagere",
"login": "Log ind",
"logout": "Log ud",
"lowerYourHand": "Ta hånden ned",
"lowerYourHand": "Tag hånden ned",
"moreActions": "Flere handlinger",
"moreOptions": "Flere indstillinger",
"mute": "Slå lyd fra / Slå lyd til",
"mute": "Slå lyd fra/til",
"muteEveryone": "Slå lyd fra for alle",
"noAudioSignalTitle": "Der kommer ingen input fra din mikrofon!",
"noAudioSignalTitle": "Der kommer ingen input fra din mikrofon",
"noAudioSignalDesc": "Hvis du ikke med vilje har slået den fra under systemindstillinger eller hardware, kan du overveje at skifte enhed.",
"noAudioSignalDescSuggestion": "Hvis du ikke med vilje har slået den fra under systemindstillinger eller hardware, skal du overveje at skifte til den foreslåede enhed.",
"noAudioSignalDialInDesc": "Du kan også ringe op ved hjælp af:",
"noAudioSignalDialInLinkDesc": "Opkaldsnumre",
"noisyAudioInputTitle": "Det lyder som om din mikrofon laver støj!",
"noisyAudioInputTitle": "Det lyder som om din mikrofon laver støj",
"noisyAudioInputDesc": "Det lyder som om din mikrofon laver støj. Overvej venligst at slå lyden fra eller skifte enhed.",
"openChat": "Åben chat",
"openChat": "Åbn chat",
"pip": "Benyt Billede-i-billede",
"privateMessage": "Send private message",
"privateMessage": "Send privat besked",
"profile": "Rediger profil",
"raiseHand": "Ræk hånden op / Tag hånden ned",
"raiseYourHand": "Ræk hånden op",
"Settings": "Indstillinger",
"sharedvideo": "Del en Youtube video",
"sharedvideo": "Del en YouTube-video",
"shareRoom": "Invitér deltagere",
"shortcuts": "Vis genveje",
"speakerStats": "Højtaler info",
"speakerStats": "Deltagerstatistik",
"startScreenSharing": "Start skærmdeling",
"startSubtitles": "Vis undertekster",
"stopScreenSharing": "Stop skærmdeling",
"stopSubtitles": "Skjul undertekster",
"stopSharedVideo": "Stop YouTube video",
"stopSharedVideo": "Stop YouTube-video",
"talkWhileMutedPopup": "Forsøger du at sige noget? Din lyd er slået fra.",
"tileViewToggle": "Slå tileview fra/til",
"tileViewToggle": "Slå gittervisning fra/til",
"toggleCamera": "Slå kamera fra/til",
"videomute": "Start / Stop kamera",
"videomute": "Start/stop kamera",
"startvideoblur": "Slå baggrundssløring til",
"stopvideoblur": "Slå baggrundssløring fra"
},
"transcribing": {
"ccButtonTooltip": "Start / Stop undertekster",
"error": "Transkription mislykkedes. Prøv venligst igen.",
"expandLabel": "Transkription er i øjeblikket tændt",
"failedToStart": "Transkription kunne ikke starte",
"ccButtonTooltip": "Start/stop undertekster",
"error": "Transskription mislykkedes. Prøv venligst igen.",
"expandLabel": "Transskription er slået til",
"failedToStart": "Transskription kunne ikke starte",
"labelToolTip": "Mødet transkriberes",
"off": "Transkription stoppet",
"pending": "Forbereder sig til at transkribere mødet …",
"pending": "Forbereder sig til at transskribere mødet…",
"start": "Begynd at vise undertekster",
"stop": "Stop med at vist undertekster",
"stop": "Stop med at vise undertekster",
"tr": "TR"
},
"userMedia": {
"androidGrantPermissions": "Vælg <b><i> Tillad</i> </b>, når din browser beder om tilladelser.",
"chromeGrantPermissions": "Vælg <b><i> Tillad</i> </b>, når din browser beder om tilladelser.",
"edgeGrantPermissions": "Vælg <b><i>Ja</i> </b>, når din browser beder om tilladelser.",
"electronGrantPermissions": "Giv tilladelse til at bruge dit kamera og din mikrofon",
"firefoxGrantPermissions": "Vælg <b> <i> Del valgt enhed </i> </b>, når din browser beder om tilladelser.",
"iexplorerGrantPermissions": "Vælg <b><i>OK</i> </b>, når din browser beder om tilladelser.",
"nwjsGrantPermissions": "Giv tilladelse til at bruge dit kamera og din mikrofon",
"operaGrantPermissions": "Vælg <b><i> Tillad</i> </b>, når din browser beder om tilladelser.",
"react-nativeGrantPermissions": "Vælg <b><i> Tillad</i> </b>, når din browser beder om tilladelser.",
"safariGrantPermissions": "Vælg <b><i>OK</i> </b>, når din browser beder om tilladelser."
"androidGrantPermissions": "Vælg <b><i> Tillad</i> </b>, når din browser beder om tilladelser",
"chromeGrantPermissions": "Vælg <b><i> Tillad</i> </b>, når din browser beder om tilladelser",
"edgeGrantPermissions": "Vælg <b><i>Ja</i> </b>, når din browser beder om tilladelser",
"electronGrantPermissions": "Giv tilladelse til at dit kamera og din mikrofon benyttes",
"firefoxGrantPermissions": "Vælg <b> <i> Del valgt enhed </i> </b>, når din browser beder om tilladelser",
"iexplorerGrantPermissions": "Vælg <b><i>OK</i> </b>, når din browser beder om tilladelser",
"nwjsGrantPermissions": "Giv tilladelse til at dit kamera og din mikrofon benyttes",
"operaGrantPermissions": "Vælg <b><i> Tillad</i> </b>, når din browser beder om tilladelser",
"react-nativeGrantPermissions": "Vælg <b><i> Tillad</i> </b>, når din browser beder om tilladelser",
"safariGrantPermissions": "Vælg <b><i>OK</i> </b>, når din browser beder om tilladelser"
},
"videoSIPGW": {
"busy": "Vi arbejder på at frigøre ressourcer. Prøv igen om et par minutter.",
"busy": "Vi arbejder på at frigøre ressourcer. Prøv igen om et par minutter",
"busyTitle": "Mødeservice er i øjeblikket optaget",
"errorAlreadyInvited": "{{displayName}} allerede inviteret",
"errorInvite": "Mødet er endnu ikke etableret. Prøv igen senere.",
"errorInviteFailed": "Vi arbejder på at løse problemet. Prøv igen senere.",
"errorInviteFailedTitle": "Inviterer {{displayName}} mislykkedes",
"errorInviteTitle": "Fejl ved indbydelse til møde",
"errorInvite": "Mødet er endnu ikke etableret. Prøv igen senere",
"errorInviteFailed": "Vi arbejder på at løse problemet. Prøv igen senere",
"errorInviteFailedTitle": "Invitationen af {{displayName}} mislykkedes",
"errorInviteTitle": "Fejl ved invitation til møde",
"pending": "{{displayName}} er blevet inviteret"
},
"videoStatus": {
"audioOnly": "AUD",
"audioOnlyExpanded": "Du er i kun-lyd tilstand. Denne tilstand sparrer båndbredde, men du kan ikke se andres video.",
"audioOnlyExpanded": "Du er i kun-lyd-tilstand. Denne tilstand sparer båndbredde, men du kan ikke se andres video",
"callQuality": "Opkaldskvalitet",
"hd": "HD",
"hdTooltip": "Viser HD video",
"hdTooltip": "Viser høj opløsning",
"highDefinition": "Høj opløsning",
"labelTooiltipNoVideo": "Ingen video",
"labelTooltipAudioOnly": "Tilstand kun-lyd er slået til",
"labelTooltipAudioOnly": "Kun-lyd er slået til",
"ld": "LD",
"ldTooltip": "Viser lav opløsnings video",
"ldTooltip": "Viser lav opløsning",
"lowDefinition": "Lav opløsning",
"onlyAudioAvailable": "Kun-lyd er tilgængelig",
"onlyAudioSupported": "Vi understøtter kun-lyd i denne browser.",
"sd": "SD",
"sdTooltip": "Vider normal opløsnings video",
"sdTooltip": "Viser standard opløsning",
"standardDefinition": "Standard opløsning"
},
"videothumbnail": {
"domute": "Slå lyd fra",
"domuteOthers": "Slå lyd fra for alle andre",
"flip": "Flip",
"kick": "Afbryd",
"kick": "Smid ud",
"moderator": "Moderator",
"mute": "Medlemmets lyd er slået fra",
"mute": "Deltagerens lyd er slået fra",
"muted": "Lyd slået fra",
"remoteControl": "Fjernbetjening",
"show": "",
@@ -741,9 +742,9 @@
"welcomepage": {
"accessibilityLabel": {
"join": "Tryk for at deltage",
"roomname": "Skriv møde navn"
"roomname": "Skriv mødenavn"
},
"appDescription": "Chat med hele dit team eller inviter alle du kender. {{app}} er en fuldt krypteret, 100% open source videokonference løsning som du kan bruge hele dagen, hver dag, gratis - uden at du behøver en konto. ",
"appDescription": "Chat med hele dit team eller invitér alle du kender. {{app}} er en fuldt krypteret, 100% open source videokonference løsning som du kan bruge hele dagen, hver dag, gratis - uden at du behøver en konto. ",
"audioVideoSwitch": {
"audio": "Lyd",
"video": "Video"
@@ -755,13 +756,13 @@
"go": "Start",
"join": "Deltag",
"info": "Info",
"privacy": "Privatliv",
"privacy": "Privacy",
"recentList": "Seneste",
"recentListDelete": "Slet",
"recentListEmpty": "Din seneste liste er i øjeblikket tom. Chat med dit team, og du finder alle dine seneste møder her.",
"reducedUIText": "",
"roomname": "Indtast mødenavn",
"roomnameHint": "Indtast mødenavnet, du vil deltage i.",
"roomnameHint": "Indtast mødenavnet på det møde, du vil deltage i.",
"sendFeedback": "Giv tilbagemelding",
"betingelser": "Betingelser",
"title": "Skærmbesøg & videomøder"

View File

@@ -239,12 +239,19 @@
"muteEveryoneElseTitle": "Alle außer {{whom}} stummschalten?",
"muteEveryoneDialog": "Wollen Sie wirklich alle stummschalten? Sie können deren Stummschaltung nicht mehr beenden, aber sie können ihre Stummschaltung jederzeit selbst beenden.",
"muteEveryoneTitle": "Alle stummschalten?",
"muteEveryoneElsesVideoDialog": "Sobald die Kamera deaktiviert ist, können Sie sie nicht wieder aktivieren, die Teilnehmer können dies aber jederzeit wieder ändern.",
"muteEveryoneElsesVideoTitle": "Die Kamera von allen außer {{whom}} ausschalten?",
"muteEveryonesVideoDialog": "Sind Sie sicher, dass Sie die Kamera von allen Teilnehmern deaktivieren möchten? Sie können sie nicht wieder aktivieren, die Teilnehmer können dies aber jederzeit wieder ändern.",
"muteEveryonesVideoTitle": "Die Kamera von allen anderen ausschalten?",
"muteEveryoneSelf": "sich selbst",
"muteEveryoneStartMuted": "Alle beginnen von jetzt an stummgeschaltet",
"muteParticipantBody": "Sie können die Stummschaltung anderer Personen nicht aufheben, aber eine Person kann ihre eigene Stummschaltung jederzeit beenden.",
"muteParticipantButton": "Stummschalten",
"muteParticipantDialog": "Wollen Sie diese Person wirklich stummschalten? Sie können die Stummschaltung nicht wieder aufheben, die Person kann dies aber jederzeit selbst tun.",
"muteParticipantTitle": "Person stummschalten?",
"muteParticipantsVideoButton": "Kamera ausschalten",
"muteParticipantsVideoTitle": "Die Kamera von dieser Person ausschalten?",
"muteParticipantsVideoBody": "Sie können die Kamera nicht wieder aktivieren, die Teilnehmer können dies aber jederzeit wieder ändern.",
"Ok": "OK",
"passwordLabel": "Dieses Meeting wurde gesichert. Bitte geben Sie das $t(lockRoomPasswordUppercase) ein, um dem Meeting beizutreten.",
"passwordNotSupported": "Das Festlegen eines Konferenzpassworts wird nicht unterstützt.",
@@ -484,6 +491,8 @@
"mutedTitle": "Stummschaltung aktiv!",
"mutedRemotelyTitle": "Sie wurden von {{participantDisplayName}} stummgeschaltet!",
"mutedRemotelyDescription": "Sie können jederzeit die Stummschaltung aufheben, wenn Sie bereit sind zu sprechen. Wenn Sie fertig sind, können Sie sich wieder stummschalten, um Geräusche vom Meeting fernzuhalten.",
"videoMutedRemotelyTitle": "Ihre Kamera wurde von {{participantDisplayName}} ausgeschaltet!",
"videoMutedRemotelyDescription": "Sie können sie jederzeit wieder einschalten.",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) von einer anderen Person entfernt",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) von einer anderen Person gesetzt",
"raisedHand": "{{name}} möchte sprechen.",
@@ -553,8 +562,8 @@
"linkCopied": "Link in die Zwischenablage kopiert",
"lookGood": "Ihr Mikrofon scheint zu funktionieren.",
"or": "oder",
"premeeting": "Vorraum",
"showScreen": "Konferenzvorraum aktivieren",
"premeeting": "Vorschau",
"showScreen": "Konferenzvorschau aktivieren",
"startWithPhone": "Mit Telefonaudio starten",
"screenSharingError": "Fehler bei Bildschirmfreigabe:",
"videoOnlyError": "Videofehler:",
@@ -682,6 +691,7 @@
},
"startupoverlay": {
"policyText": " ",
"genericTitle": "Die Konferenz muss Ihr Mikrofon und Ihre Kamera verwenden.",
"title": "{{app}} benötigt Kamera und Mikrofon."
},
"suspendedoverlay": {
@@ -714,12 +724,16 @@
"moreOptions": "Menü „Weitere Optionen“",
"mute": "„Audio stummschalten“ ein-/ausschalten",
"muteEveryone": "Alle stummschalten",
"muteEveryoneElse": "Alle anderen stummschalten",
"muteEveryonesVideo": "Alle Kameras ausschalten",
"muteEveryoneElsesVideo": "Alle anderen Kameras ausschalten",
"pip": "Bild-in-Bild-Modus ein-/ausschalten",
"privateMessage": "Private Nachricht senden",
"profile": "Profil bearbeiten",
"raiseHand": "„Melden“ ein-/ausschalten",
"recording": "Aufzeichnung ein-/ausschalten",
"remoteMute": "Personen stummschalten",
"remoteVideoMute": "Kamera von dieser Person ausschalten",
"security": "Sicherheitsoptionen",
"Settings": "Einstellungen ein-/ausschalten",
"sharedvideo": "YouTube-Videofreigabe ein-/ausschalten",
@@ -764,6 +778,7 @@
"moreOptions": "Weitere Optionen",
"mute": "Stummschaltung aktivieren / deaktivieren",
"muteEveryone": "Alle stummschalten",
"muteEveryonesVideo": "Alle Kameras ausschalten",
"noAudioSignalTitle": "Es kommt kein Input von Ihrem Mikrofon!",
"noAudioSignalDesc": "Wenn Sie das Gerät nicht absichtlich über die Systemeinstellungen oder die Hardware stumm geschaltet haben, sollten Sie einen Wechsel des Geräts in Erwägung ziehen.",
"noAudioSignalDescSuggestion": "Wenn Sie das Gerät nicht absichtlich über die Systemeinstellungen oder die Hardware stummgeschaltet haben, sollten Sie einen Wechsel auf das vorgeschlagene Gerät in Erwägung ziehen.",
@@ -849,13 +864,16 @@
},
"videothumbnail": {
"domute": "Stummschalten",
"domuteVideo": "Kamera ausschalten",
"domuteOthers": "Alle anderen stummschalten",
"domuteVideoOfOthers": "Alle anderen Kameras auschalten",
"flip": "Spiegeln",
"grantModerator": "Moderationsrechte vergeben",
"kick": "Hinauswerfen",
"moderator": "Moderation",
"mute": "Person ist stumm geschaltet",
"muted": "Stummgeschaltet",
"videoMuted": "Kamera ausgeschaltet",
"remoteControl": "Fernsteuerung",
"show": "Im Vordergrund anzeigen",
"videomute": "Person hat die Kamera angehalten"

View File

@@ -105,8 +105,8 @@
"bitrate": "Débit :",
"bridgeCount": "Nombre de serveurs :",
"codecs": "Codecs (A/V) :",
"e2e_rtt": "E2E RTT :",
"connectedTo": "Connecté à :",
"e2e_rtt": "E2E RTT :",
"framerate": "Images par seconde :",
"less": "Cacher les détails",
"localaddress": "Adresse locale :",
@@ -251,7 +251,7 @@
"muteParticipantDialog": "Êtes-vous sûr(e) de vouloir couper le micro de ce participant ? Seul le participant pourra ensuite réactiver son micro à tout moment.",
"muteParticipantTitle": "Couper le micro de ce participant ?",
"Ok": "Ok",
"passwordLabel": "La réunion a été verrouillée par un·e participant·e. Veuillez entrer le $t(lockRoomPassword) pour la rejoindre.",
"passwordLabel": "La réunion a été verrouillée par un(e) participant(e). Veuillez entrer le $t(lockRoomPassword) pour la rejoindre.",
"passwordNotSupported": "La définition d'un $t(lockRoomPassword) de réunion n'est pas prise en charge.",
"passwordNotSupportedTitle": "L'ajout d'un $t(lockRoomPassword) n'est pas supporté",
"passwordRequired": "$t(lockRoomPasswordUppercase) requis",
@@ -396,16 +396,16 @@
"focusRemote": "Épingler la vidéo de quelqu'un d'autre",
"fullScreen": "Activer / Désactiver le mode plein écran",
"keyboardShortcuts": "Raccourcis clavier",
"localRecording": "Afficher ou masquer les commandes de l'enregistrement local",
"mute": "Activer ou désactiver le microphone",
"pushToTalk": "Appuyer pour parler",
"raiseHand": "Lever ou baisser la main",
"localRecording": "Afficher / Masquer les commandes de l'enregistrement local",
"mute": "Activer / Désactiver le microphone",
"pushToTalk": "Maintenir la touche pour parler",
"raiseHand": "Lever / Baisser la main",
"showSpeakerStats": "Afficher les statistiques de l'interlocuteur",
"toggleChat": "Ouvrir ou fermer le panneau de conversation",
"toggleFilmstrip": "Afficher ou masquer les vignettes vidéos",
"toggleChat": "Ouvrir / Fermer le panneau de conversation",
"toggleFilmstrip": "Afficher / Masquer les vignettes vidéos",
"toggleScreensharing": "Basculer entre la caméra et le partage d'écran",
"toggleShortcuts": "Afficher ou masquer les raccourcis clavier",
"videoMute": "Démarrer ou arrêter votre caméra",
"toggleShortcuts": "Afficher / Masquer les raccourcis clavier",
"videoMute": "Démarrer / Arrêter votre caméra",
"videoQuality": "Accorder la qualité des appels"
},
"liveStreaming": {
@@ -423,15 +423,15 @@
"expandedOff": "La diffusion en direct a été arrêtée",
"expandedOn": "La conférence est en cours de diffusion sur YouTube.",
"expandedPending": "La diffusion en direct a commencé ...",
"failedToStart": "La diffusion n'as pas réussi à démarrer",
"getStreamKeyManually": "Nous n'avons pu récupérer aucun flux en direct. Essayez d'obtenir votre clé de diffusion en direct sur YouTube.",
"failedToStart": "La diffusion n'a pas réussi à démarrer",
"getStreamKeyManually": "Nous n'avons pas réussi à récupérer un flux de direct. Essayez d'obtenir votre clé de diffusion en direct sur YouTube.",
"invalidStreamKey": "La clé de diffusion en direct n'est peut-être pas correcte.",
"limitNotificationDescriptionWeb": "En raison de la forte demande, votre diffusion sera limitée à {{limit}} min. Pour un streaming illimité, essayez <a href={{url}} rel='noopener noreferrer' target='_blank'> {{app}} </a>.",
"limitNotificationDescriptionWeb": "En raison d'une forte demande, votre diffusion sera limitée à {{limit}} min. Pour un streaming illimité, essayez <a href={{url}} rel='noopener noreferrer' target='_blank'> {{app}} </a>.",
"limitNotificationDescriptionNative": "Votre diffusion sera limitée à {{limit}} min. Pour un streaming illimité, essayez {{app}}.",
"off": "Le Streaming a été arrêté",
"offBy": "{{name}} a arrêté la diffusion en continu",
"off": "La diffusion en direct (streaming) a été arrêté",
"offBy": "{{name}} a arrêté la diffusion en direct",
"on": "En direct",
"onBy": "{{name}} a démarré la diffusion en continu",
"onBy": "{{name}} a démarré la diffusion en direct",
"pending": "Lancement du direct ...",
"serviceName": "Service de diffusion en direct",
"signedInAs": "Vous êtes connecté en tant que :",
@@ -461,12 +461,12 @@
"messages": {
"engaged": "L'enregistrement local a démarré.",
"finished": "L'enregistrement de la session {{token}} s'est terminé. Merci d'envoyer le fichier au modérateur.",
"finishedModerator": "L'enregistrement de la session {{token}} s'est terminé. La piste a bien été sauvegardée. Merci de demander aux autres participants de soumettre leurs enregistrements.",
"finishedModerator": "L'enregistrement de la session {{token}} s'est terminé. L'enregistrement a bien été sauvegardée. Merci de demander aux autres participants de soumettre leurs enregistrements.",
"notModerator": "Vous n'êtes pas le modérateur. Vous ne pouvez pas démarrer ou arrêter un enregistrement local."
},
"moderator": "Modérateur",
"moderator": "Modérateur ",
"no": "Non",
"participant": "Participant·e",
"participant": "Participant(e)",
"participantStats": "Statistiques du participant",
"sessionToken": "Token de la session",
"start": "Démarrer l'enregistrement",
@@ -484,7 +484,7 @@
"focus": "Focus de conférence",
"focusFail": "{{component}} n'est pas disponible - réessayez dans {{ms}} sec",
"grantedTo": "Droits modérateur accordés à {{to}} !",
"invitedOneMember": "{{name}} a été invité·e",
"invitedOneMember": "{{name}} a été invité(e)",
"invitedThreePlusMembers": "{{name}} et {{count}} autres ont été invités",
"invitedTwoMembers": "{{first}} et {{second}} ont été invités",
"kickParticipant": "{{kicked}} a été expulsé par {{kicker}}",
@@ -516,7 +516,8 @@
"poweredby": "produit par",
"prejoin": {
"audioAndVideoError": "Erreur audio et video:",
"audioOnlyError": "Erreur audio:",
"audioDeviceProblem": "Il y a un problème avec votre périphérique audio",
"audioOnlyError": "Erreur audio :",
"audioTrackError": "N'a pas pu créer la piste audio.",
"calling": "Appel",
"callMe": "Appelez-moi",
@@ -602,7 +603,7 @@
"expandedOff": "L'enregistrement a été arrêté",
"expandedOn": "Cette conférence est actuellement en cours d'enregistrement.",
"expandedPending": "Démarrage de l'enregistrement ...",
"failedToStart": "L'enregistrement n'as pas réussi à démarrer",
"failedToStart": "L'enregistrement n'a pas réussi à démarrer",
"fileSharingdescription": "Partager l'enregistrement avec les participants de la réunion",
"limitNotificationDescriptionWeb": "En raison d'une forte demande, votre enregistrement sera limité à {{limit}} min. Pour des enregistrements illimités, essayez <a href={{url}} rel='noopener noreferrer' target='_blank'> {{app}} </a>.",
"limitNotificationDescriptionNative": "En raison d'une forte demande, votre enregistrement sera limité à {{limit}} min. Pour des enregistrements illimités, essayez <3> {{app}} </3>.",
@@ -702,48 +703,48 @@
},
"toolbar": {
"accessibilityLabel": {
"audioOnly": "Activer/désactiver le mode voix uniquement",
"audioOnly": "Activer / Désactiver le mode voix uniquement",
"audioRoute": "Sélectionner la source audio",
"callQuality": "Ajuster la qualité vidéo",
"cc": "Activer/désactiver les sous-titres",
"chat": "Afficher/masquer la discussion instantanée",
"document": "Activer/désactiver le document partagé",
"cc": "Activer / Désactiver les sous-titres",
"chat": "Afficher / Masquer la discussion instantanée",
"document": "Activer / Désactiver le document partagé",
"download": "Télécharger nos applications",
"embedMeeting": "Intégrer la réunion",
"feedback": "Laisser des commentaires",
"fullScreen": "Activer/désactiver le plein écran",
"fullScreen": "Activer / Désactiver le plein écran",
"grantModerator": "Nommer modérateur",
"hangup": "Quitter la conversation",
"help": "Aide",
"invite": "Inviter des participants",
"kick": "Expulser le participant",
"lobbyButton": "Activer / désactiver le mode lobby",
"localRecording": "Activer/désactiver les contrôles d'enregistrement local",
"lockRoom": "Activer/Désactiver le mot de passe de la réunion",
"moreActions": "Activer/désactiver le menu d'actions supplémentaires",
"lobbyButton": "Activer / Désactiver le mode salle d'attente",
"localRecording": "Activer / Désactiver les contrôles d'enregistrement local",
"lockRoom": "Activer / Désactiver le mot de passe de la réunion",
"moreActions": "Activer / Désactiver le menu d'actions supplémentaires",
"moreActionsMenu": "Menu d'actions supplémentaires",
"moreOptions": "Voir plus d'options",
"mute": "Activer/désactiver l'audio",
"mute": "Activer / Désactiver l'audio",
"muteEveryone": "Rendre muet tout le monde",
"pip": "Activer/désactiver le mode Picture in Picture",
"pip": "Activer / Désactiver le mode Picture in Picture",
"privateMessage": "Envoyer un message privé",
"profile": "Éditer votre profil",
"raiseHand": "Lever/baisser la main",
"recording": "Activer/désactiver l'enregistrement",
"raiseHand": "Lever / Baisser la main",
"recording": "Activer / Désactiver l'enregistrement",
"remoteMute": "Désactiver le micro du participant",
"security": "Options de sécurité",
"Settings": "Afficher/masquer le menu des paramètres",
"sharedvideo": "Démarrer/arrêter le partage de vidéo YouTube",
"Settings": "Afficher / Masquer le menu des paramètres",
"sharedvideo": "Démarrer / Arrêter le partage de vidéo YouTube",
"shareRoom": "Inviter quelqu'un",
"shareYourScreen": "Activer/désactiver le partage d'écran",
"shortcuts": "Afficher/masquer les raccourcis",
"shareYourScreen": "Activer / Désactiver le partage d'écran",
"shortcuts": "Afficher / Masquer les raccourcis",
"show": "Afficher en premier plan",
"speakerStats": "Afficher/cacher les statistiques de parole",
"tileView": "Activer/désactiver la vue mosaïque",
"speakerStats": "Afficher / Cacher les statistiques de parole",
"tileView": "Activer / Désactiver la vue mosaïque",
"toggleCamera": "Changer de caméra",
"toggleFilmstrip": "Basculer de pellicule",
"videomute": "Activer/désactiver la vidéo",
"videoblur": "Activer/désactiver le flou de la vidéo"
"videomute": "Activer / Désactiver la vidéo",
"videoblur": "Activer / Désactiver le flou de la vidéo"
},
"addPeople": "Ajouter des personnes à votre appel",
"audioOnlyOff": "Désactiver le mode bande passante réduite",
@@ -766,8 +767,8 @@
"hangup": "Quitter",
"help": "Aide",
"invite": "Inviter des participants",
"lobbyButtonDisable": "Désactiver le contrôle des participant·e·s",
"lobbyButtonEnable": "Activer le contrôle des participant·e·s",
"lobbyButtonDisable": "Désactiver le mode salle d'attente / contrôle des participant(e)s",
"lobbyButtonEnable": "Activer le mode salle d'attente / contrôle des participant(e)s",
"login": "Connexion",
"logout": "Déconnexion",
"lowerYourHand": "Baisser la main",
@@ -800,22 +801,22 @@
"stopSubtitles": "Désactiver les sous-titres",
"stopSharedVideo": "Arrêter la vidéo YouTube",
"talkWhileMutedPopup": "Vous voulez parler ? Votre micro est coupé.",
"tileViewToggle": "Activer/désactiver la vue mosaïque",
"tileViewToggle": "Activer / Désactiver la vue mosaïque",
"toggleCamera": "Changer de caméra",
"videomute": "Démarrer / Arrêter la caméra",
"startvideoblur": "Flouter mon arrière plan",
"stopvideoblur": "Désactiver le flou d'arrière-plan"
},
"transcribing": {
"ccButtonTooltip": "Activer/Désactiver les sous-titres",
"ccButtonTooltip": "Activer / Désactiver les sous-titres",
"error": "Échec de la transcription. Veuillez réessayer.",
"expandedLabel": "La transcription est actuellement activée",
"failedToStart": "Échec de démarrage de la transcription",
"labelToolTip": "La transcription de la réunion est en cours",
"off": "La transcription désactivée",
"pending": "Préparation de la transcription de la réunion ...",
"start": "Afficher/masquer les sous-titres",
"stop": "Désactiver le sous-titrage",
"start": "Activer les sous-titres",
"stop": "Désactiver les sous-titres",
"tr": "TR"
},
"userMedia": {
@@ -939,10 +940,10 @@
"nameField": "Saisissez votre nom",
"notificationLobbyAccessDenied": "{{targetParticipantName}} a été refusé par {{originParticipantName}}",
"notificationLobbyAccessGranted": "{{targetParticipantName}} a été accepté par {{originParticipantName}}",
"notificationLobbyDisabled": "Lobby a été désactivé par {{originParticipantName}}",
"notificationLobbyEnabled": "Lobby a été activé par {{originParticipantName}}",
"notificationTitle": "Lobby",
"passwordField": "Saisissez le mot de passe de la réunion",
"notificationLobbyDisabled": "Le mode salle d'attente a été désactivé par {{originParticipantName}}",
"notificationLobbyEnabled": "Le mode salle d'attente a été activé par {{originParticipantName}}",
"notificationTitle": "Salle d'attente",
"passwordField": "Veuillez saisir le mot de passe de la réunion",
"passwordJoinButton": "Rejoindre",
"reject": "Refuser",
"toggleLabel": "Activer la salle d'attente"

View File

@@ -61,6 +61,7 @@
"today": "Oggi"
},
"chat": {
"enter": "Entra nella conversazione",
"error": "Errore: il tuo messaggio non è stato inviato. Motivo: {{error}}",
"fieldPlaceHolder": "Scrivi qui il tuo messaggio",
"messagebox": "Digitare un messaggio",
@@ -240,12 +241,19 @@
"muteEveryoneElseTitle": "Zittisco tutti eccetto {{whom}}?",
"muteEveryoneDialog": "Sei sicuro di voler zittire tutti? Non potrai riattivar loro il microfono, ma loro potranno farlo in qualsiasi momento.",
"muteEveryoneTitle": "Zittisco tutti?",
"muteEveryoneElsesVideoDialog": "Una volta spente le videocamere, non potrai riaccenderle, ma ogni partecipante potrà farlo in ogni momento.",
"muteEveryoneElsesVideoTitle": "Spegnere tutte le videocamere, tranne quella di {{whom}}?",
"muteEveryonesVideoDialog": "Sei sicuro di voler spegnere le videocamere di tutti? Non potrai riaccenderle, ma ogni partecipante potrà farlo in ogni momento.",
"muteEveryonesVideoTitle": "Vuoi spegnere le videocamere di tutti?",
"muteEveryoneSelf": "te stesso",
"muteEveryoneStartMuted": "Tutti cominciano a microfono spento, d'adesso in avanti",
"muteParticipantBody": "Non sarai in grado di riattivare il loro microfono, ma loro potranno riattivarlo in qualsiasi momento.",
"muteParticipantButton": "Zittisci",
"muteParticipantDialog": "Sei sicuro di voler zittire questo partecipante? Sarà lui a dovere riattivare l'audio, per parlare.",
"muteParticipantTitle": "Zittisco questo partecipante?",
"muteParticipantsVideoButton": "Spegnere videocamera",
"muteParticipantsVideoTitle": "Vuoi spegnere la videocamera di questo partecipante?",
"muteParticipantsVideoBody": "Una volta spenta la videocamera, non potrai riaccenderla, ma lui potrà riattivarla in qualsiasi momento.",
"Ok": "OK",
"passwordLabel": "La riunione è stata bloccata da un partecipante. Immetti la $t(lockRoomPassword) per collegarti, per favore.",
"passwordNotSupported": "Impostare una $t(lockRoomPassword) non è supportato.",
@@ -305,6 +313,7 @@
"unlockRoom": "Togli la $t(lockRoomPassword) alla riunione",
"user": "utente",
"userPassword": "password utente",
"videoLink": "Collegamento video",
"WaitForHostMsg": "La riunione <b>{{room}}</b> non è ancora cominciata. Se sei l'organizzatore, per favore autenticati. Altrimenti, aspetta l'arrivo dell'organizzatore.",
"WaitForHostMsgWOk": "La riunione <b>{{room}}</b> non è ancora cominciata. Se sei l'organizzatore, allora premi OK per autenticarti. Altrimenti, aspetta l'arrivo dell'organizzatore.",
"WaitingForHost": "In attesa dell'organizzatore...",
@@ -323,6 +332,11 @@
"embedMeeting": {
"title": "Incorpora questa riunione"
},
"virtualBackground": {
"title": "Sfondi",
"enableBlur": "Attiva sfocatura",
"removeBackground": "Togli sfondo"
},
"feedback": {
"average": "Media",
"bad": "Scadente",
@@ -483,6 +497,8 @@
"mutedTitle": "Hai l'audio disattivato!",
"mutedRemotelyTitle": "Ti è stato disattivato l'audio da {{participantDisplayName}}!",
"mutedRemotelyDescription": "Puoi sempre attivare il microfono, quando vuoi parlare. Spegni il microfono quando hai finito, per non introdurre rumori di fondo nella riunione.",
"videoMutedRemotelyTitle": "La videocamera ti è stata spenta da {{participantDisplayName}}!",
"videoMutedRemotelyDescription": "Puoi riaccenderla in qualsiasi momento.",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) è stata tolta da un altro partecipante",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) è stata messa da un altro partecipante",
"raisedHand": "{{name}} vorrebbe intervenire.",
@@ -715,12 +731,16 @@
"moreOptions": "Più opzioni",
"mute": "Attiva/disattiva audio",
"muteEveryone": "Zittisci tutti",
"muteEveryoneElse": "Zittisci tutti gli altri",
"muteEveryonesVideo": "Spegni le videocamere di tutti",
"muteEveryoneElsesVideo": "Spegni le videocamere di tutti gli altri",
"pip": "Attiva/disattiva immagine nellimmagine",
"privateMessage": "Invia messaggio privato",
"profile": "Modifica profilo",
"raiseHand": "Attiva/disattiva alzata di mano",
"recording": "Attiva/disattiva registrazione",
"remoteMute": "Zittisci partecipante",
"remoteVideoMute": "Spegni videocamera del partecipante",
"security": "Impostazioni di sicurezza",
"Settings": "Attiva/disattiva impostazioni",
"sharedvideo": "Attiva/disattiva condivisione YouTube",
@@ -733,9 +753,10 @@
"toggleCamera": "Cambia videocamera",
"toggleFilmstrip": "Attiva/disattiva pellicola",
"videomute": "Attiva/disattiva videocamera",
"videoblur": "Attiva/disattiva offuscamento video"
"selectBackground": "Scegli sfondo"
},
"addPeople": "Aggiungi persone alla chiamata",
"audioSettings": "Impostazioni audio",
"audioOnlyOff": "Disabilita modalità per banda limitata",
"audioOnlyOn": "Abilita modalità per banda limitata",
"audioRoute": "Scegli l'uscita audio",
@@ -765,6 +786,7 @@
"moreOptions": "Più opzioni",
"mute": "Attiva / Disattiva microfono",
"muteEveryone": "Zittisci tutti",
"muteEveryonesVideo": "Spegni videocamera di tutti",
"noAudioSignalTitle": "Non arrivano suoni dal tuo microfono!",
"noAudioSignalDesc": "Se non l'hai disabilitato intenzionalmente nelle impostazioni, prova a cambiare dispositivo di input.",
"noAudioSignalDescSuggestion": "Se non l'hai disabilitato intenzionalmente nelle impostazioni, prova a scegliere il dispositivo consigliato.",
@@ -793,7 +815,6 @@
"tileViewToggle": "Vedi tutti i partecipanti insieme, o uno solo",
"toggleCamera": "Cambia videocamera",
"videomute": "Attiva / Disattiva videocamera",
"startvideoblur": "Sfoca lo sfondo del video",
"stopvideoblur": "Non sfocare lo sfondo video"
},
"transcribing": {
@@ -849,13 +870,16 @@
"videothumbnail": {
"connectionInfo": "Info connessione",
"domute": "Disattiva audio",
"domuteOthers": "Zittisci tutti gli altri",
"domuteVideo": "Disattiva video",
"domuteOthers": "Zittisci tutti gli altri",
"domuteVideoOfOthers": "Disattiva video di tutti gli altri",
"flip": "Rifletti",
"grantModerator": "Autorizza moderatore",
"kick": "Espelli",
"moderator": "Moderatore",
"mute": "Il partecipante ha il microfono spento",
"muted": "Audio disattivato",
"videoMuted": "Video disattivato",
"remoteControl": "Avvia/ferma il controllo remoto",
"show": "Mostra in primo piano",
"videomute": "Il partecipante ha la videocamera spenta"

View File

@@ -57,10 +57,11 @@
"ongoingMeeting": "진행중인 회의",
"permissionButton": "설정 열기",
"permissionMessage": "앱에 회의를 나열하려면 캘린더 권한이 필요합니다",
"refresh": "달력 새로고침",
"refresh": "캘린더 새로고침",
"today": "오늘"
},
"chat": {
"enter": "채팅방 입장",
"error": "오류 : 메시지가 전송되지 않았습니다. 이유 : {{error}}",
"fieldPlaceHolder": "메세지를 여기에 입력하세요",
"messagebox": "메시지 입력",
@@ -212,7 +213,7 @@
"lockMessage": "회의를 비공개하지 못했습니다",
"lockRoom": "회의 추가 $t(lockRoomPasswordUppercase)",
"lockTitle": "비공개 실패",
"logoutQuestion": "로그 아웃하고 컨퍼런스를 중지하시겠습니까?",
"logoutQuestion": "로그아웃하고 컨퍼런스를 중지하시겠습니까?",
"logoutTitle": "로그아웃",
"maxUsersLimitReached": "회의의 최대 참가자 수에 도달했습니다. 회의 소유자에게 연락하거나 나중에 다시 시도하십시오!",
"maxUsersLimitReachedTitle": "최대 참가자 수에 도달했습니다.",
@@ -222,10 +223,23 @@
"micNotSendingDataTitle": "시스템 설정에 의해 마이크가 음소거되었습니다.",
"micPermissionDeniedError": "마이크를 사용할 수있는 권한을 부여하지 않았습니다. 회의에 계속 참여할 수는 있지만 다른 사람들은 듣지 않습니다. 검색 주소창의 카메라 버튼을 사용하여 문제를 해결하십시오.",
"micUnknownError": "알 수 없는 이유로 마이크를 사용할 수 없습니다",
"muteEveryoneElseDialog": "당신이 다른 사람들의 음소거를 해제 할 수는 없지만 언제든지 다른 사람들은 스스로 음소거를 해제할 수 있습니다.",
"muteEveryoneElseTitle": "{{whom}} 를 제외하고 전부 음소거 하시겠습니까?",
"muteEveryoneDialog": "모든 참가자를 음소거 하시겠습니까? 당신이 다른 사람들의 음소거를 해제 할 수는 없지만 언제든지 다른 사람들은 스스로 음소거를 해제할 수 있습니다.",
"muteEveryoneTitle": "모두 음소거 하시겠습니까?",
"muteEveryoneElsesVideoDialog": "당신이 다른 사람들의 카메라를 다시 켤 수는 없지만 언제든지 다른 사람들은 스스로 카메라를 켤 수 있습니다.",
"muteEveryoneElsesVideoTitle": "{{whom}} 를 제외하고 전부 카메라를 비활성화 하시겠습니까?",
"muteEveryonesVideoDialog": "모든 참가자의 카메라를 비활성화 하시겠습니까? 당신이 다른 사람들의 카메라를 다시 켤 수는 없지만 언제든지 다른 사람들은 스스로 카메라를 켤 수 있습니다.",
"muteEveryonesVideoDialogOk": "비활성화",
"muteEveryonesVideoTitle": "모든 카메라를 비활성화 하시겠습니까?",
"muteEveryoneStartMuted": "지금부터 모두 음소거 됩니다.",
"muteParticipantBody": "당신이 다른 사람들의 음소거를 해제 할 수는 없지만 언제든지 다른 사람들은 스스로 음소거를 해제할 수 있습니다.",
"muteParticipantButton": "음소거",
"muteParticipantDialog": "",
"muteParticipantDialog": "이 참가자를 음소거 하시겠습니까? 당신이 다른 사람들의 음소거를 해제 할 수는 없지만 언제든지 다른 사람들은 스스로 음소거를 해제할 수 있습니다.",
"muteParticipantTitle": "이 참가자를 음소거 하시겠습니까?",
"muteParticipantsVideoButton": "카메라 비활성화",
"muteParticipantsVideoTitle": "이 참가자의 카메라를 비활성화 하시겠습니까?",
"muteParticipantsVideoBody": "당신이 다른 사람들의 카메라를 다시 켤 수는 없지만 언제든지 다른 사람들은 스스로 카메라를 켤 수 있습니다.",
"Ok": "확인",
"passwordLabel": "잠긴 회의입니다. 회의에 참여하려면 비밀번호를 입력하세요.",
"passwordNotSupported": "회의 비밀번호 설정은 지원되지 않습니다",
@@ -233,7 +247,9 @@
"passwordRequired": "비밀번호 필수",
"popupError": "브라우저가이 사이트의 팝업 창을 차단하고 있습니다. 브라우저의 보안 설정에서 팝업을 활성화하고 다시 시도하십시오.",
"popupErrorTitle": "팝업 차단됨",
"readMore": "더보기",
"recording": "녹화",
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "라이브 스트리밍 중에는 사용하실 수 없습니다.",
"recordingDisabledForGuestTooltip": "게스트는 녹화를 시작할 수 없습니다.",
"recordingDisabledTooltip": "녹화가 비활성화 되었습니다.",
"rejoinNow": "지금 재가입",
@@ -297,6 +313,14 @@
"documentSharing": {
"title": "문서 공유"
},
"virtualBackground": {
"title": "배경",
"enableBlur": "흐린 배경 활성화",
"removeBackground": "배경 제거",
"uploadImage": "이미지 업로드",
"pleaseWait": "잠시만 기다려주세요...",
"none": "없음"
},
"feedback": {
"average": "보통",
"bad": "나쁨",
@@ -322,12 +346,12 @@
"dialANumber": "회의에 참여하려면이 번호 중 하나를 누른 다음 PIN을 입력하십시오.",
"dialInConferenceID": "PIN:",
"dialInNotSupported": "죄송합니다. 현재 전화를 걸 수 없습니다.",
"dialInNumber": "Dial-in:",
"dialInNumber": "전화 접속:",
"dialInSummaryError": "지금 전화 접속 정보를 가져 오는 중에 오류가 발생했습니다. 나중에 다시 시도하십시오.",
"dialInTollFree": "",
"genericError": "일반적인 오류가 발생했습니다",
"inviteLiveStream": "이 회의의 실시간 스트림을 보려면이 링크를 클릭하십시오: {{url}}",
"invitePhone": "",
"invitePhone": "폰으로 참여하려면, 이것을 누르십시오: {{number}},,{{conferenceID}}#\n",
"invitePhoneAlternatives": "",
"inviteURLFirstPartGeneral": "회의에 초대되었습니다.",
"inviteURLFirstPartPersonal": "{{name}}이 회의에 초대하였습니다.\n",
@@ -406,9 +430,9 @@
},
"localRecording": {
"clientState": {
"off": "",
"on": "",
"unknown": ""
"off": "꺼짐",
"on": "켜짐",
"unknown": "알 수 없음"
},
"dialogTitle": "",
"duration": "",
@@ -417,7 +441,7 @@
"label": "",
"labelToolTip": "",
"localRecording": "",
"me": "",
"me": "",
"messages": {
"engaged": "",
"finished": "",
@@ -454,6 +478,8 @@
"mutedTitle": "음소거 상태입니다!",
"mutedRemotelyTitle": "{{participantDisplayName}}에 의해 음소거되었습니다!",
"mutedRemotelyDescription": "말할 준비가되면 언제든지 음소거를 해제 할 수 있습니다.",
"videoMutedRemotelyTitle": "{{participantDisplayName}}에 의해 카메라가 비활성화되었습니다!",
"videoMutedRemotelyDescription": "언제든지 카메라를 다시 켤 수 있습니다.",
"passwordRemovedRemotely": "다른 참가자가 $t(lockRoomPasswordUppercase)를 제거했습니다.",
"passwordSetRemotely": "다른 참가자가 $t(lockRoomPasswordUppercase)를 설정했습니다.",
"raisedHand": "{{name}}님이 말하고 싶어합니다.",
@@ -518,6 +544,12 @@
"sectionList": {
"pullToRefresh": "당겨서 새로고침"
},
"security": {
"about": "회의에 $t(lockRoomPassword)를 추가할 수 있습니다. 참가자는 회의에 참여하기 위해 $t(lockRoomPassword)를 입력해야합니다.",
"aboutReadOnly": "방장은 회의에 $t(lockRoomPassword)를 추가할 수 있습니다. 참가자는 회의에 참여하기 위해 $t(lockRoomPassword)를 입력해야합니다.",
"insecureRoomNameWarning": "원하지 않은 참가자가 회의에 참여할 수 있습니다. 보안 옵션 버튼을 통해 회의를 보호하는 것을 고려하십시오.",
"securityOptions": "보안 옵션"
},
"settings": {
"calendar": {
"about": "{{appName}} 캘린더 통합은 예정된 일정을 읽을 수 있도록 캘린더에 안전하게 액세스하는 데 사용됩니다.",
@@ -582,40 +614,49 @@
},
"toolbar": {
"accessibilityLabel": {
"audioOnly": "",
"audioOnly": "음성 전용 모드 전환",
"audioRoute": "음성 장비 선택하기",
"callQuality": "",
"cc": "",
"chat": "",
"document": "",
"callQuality": "비디오 품질 관리",
"cc": "자막 사용 전환",
"chat": "채팅창 보이기 전환",
"document": "문서 전환",
"feedback": "피드백 남기기",
"fullScreen": "",
"hangup": "",
"invite": "",
"kick": "",
"fullScreen": "전체 화면 전환",
"hangup": "떠나기",
"help": "도움말",
"invite": "사용자 초대",
"kick": "참가자 추방",
"lobbyButton": "로비 모드 활성화/비활성화",
"localRecording": "",
"lockRoom": "",
"lockRoom": "회의 비밀번호 전환",
"moreActions": "",
"moreActionsMenu": "",
"mute": "",
"mute": "음소거 전환",
"muteEveryone": "모두 음소거",
"muteEveryoneElse": "다른 사람 모두 음소거",
"muteEveryonesVideo": "모든 카메라 비활성화",
"muteEveryoneElsesVideo": "다른 사람의 카메라 모두 비활성화",
"pip": "",
"profile": "",
"raiseHand": "",
"recording": "",
"remoteMute": "",
"Settings": "",
"sharedvideo": "",
"shareRoom": "",
"shareYourScreen": "",
"privateMessage": "비공개 메세지 보내기",
"profile": "프로필 수정",
"raiseHand": "손 들기",
"recording": "녹화 전환",
"remoteMute": "참가자 음소거",
"Settings": "설정 전환",
"sharedvideo": "YouTube 비디오 공유 전환",
"shareRoom": "초대하기",
"shareYourScreen": "화면 공유 전환",
"shortcuts": "단축키 전환",
"show": "",
"speakerStats": "",
"tileView": "",
"speakerStats": "접속자 통계 전환",
"tileView": "타일뷰 전환",
"toggleCamera": "카메라 전환",
"videomute": "",
"videoblur": ""
"videomute": "비디오 비활성화 전환",
"videoblur": "",
"selectBackground": "배경 선택"
},
"addPeople": "통화에 사용자 추가",
"audioSettings": "오디오 설정",
"audioOnlyOff": "음성전용 모드 끄기",
"audioOnlyOn": "음성전용 모드 끄기",
"audioRoute": "음성 장비 선택하기",
@@ -632,6 +673,7 @@
"exitTileView": "타일보기 종료",
"feedback": "피드백 남기기",
"hangup": "떠나기",
"help": "도움말",
"invite": "초대",
"login": "로그인",
"logout": "로그아웃",
@@ -646,6 +688,7 @@
"profile": "프로필 수정",
"raiseHand": "말하기 요청/해제",
"raiseYourHand": "손 들어주세요",
"security": "보안 옵션",
"Settings": "설정",
"sharedvideo": "YouTube 비디오 공유",
"shareRoom": "초대하기",
@@ -655,11 +698,13 @@
"startSubtitles": "자막 시작",
"stopScreenSharing": "화면 공유 중지",
"stopSubtitles": "자막 중지",
"stopSharedVideo": "UouTube 비디오 공유 중지",
"stopSharedVideo": "YouTube 비디오 공유 중지",
"talkWhileMutedPopup": "음소거 상태입니다.",
"tileViewToggle": "타일뷰 전환",
"toggleCamera": "카메라 전환",
"videomute": "카메라 시작/중지",
"videoSettings": "비디오 설정",
"selectBackground": "배경 선택",
"startvideoblur": "내 배경을 흐리게",
"stopvideoblur": "배경 흐림 비활성화"
},

View File

@@ -61,6 +61,7 @@
"today": "Vandaag"
},
"chat": {
"enter": "Chat openen",
"error": "Fout: uw bericht \"{{originalText}}\" is niet verzonden. Reden: {{error}}",
"fieldPlaceHolder": "Typ hier uw bericht",
"messagebox": "Typ een bericht",
@@ -101,6 +102,8 @@
"address": "Adres:",
"bandwidth": "Geschatte bandbreedte:",
"bitrate": "Bitrate:",
"audio_ssrc": "Audio SSRC:",
"codecs": "Codecs (A/V): ",
"bridgeCount": "Aantal servers: ",
"connectedTo": "Verbonden met:",
"e2e_rtt": "E2E RTT:",
@@ -125,9 +128,12 @@
"remoteport": "Externe poort:",
"remoteport_plural": "Externe poorten:",
"resolution": "Resolutie:",
"savelogs": "Logs opslaan",
"participant_id": "Deelnemer id:",
"status": "Verbinding:",
"transport": "Transport:",
"transport_plural": "Transporten:"
"transport_plural": "Transporten:",
"video_ssrc": "Video SSRC:"
},
"dateUtils": {
"earlier": "Eerder",
@@ -174,6 +180,7 @@
"cameraNotFoundError": "Camera niet gevonden.",
"cameraNotSendingData": "Er is geen toegang tot uw camera verkregen. Controleer of dit apparaat wordt gebruikt door een andere toepassing, selecteer een ander apparaat vanuit de instellingen of probeer de toepassing te herladen.",
"cameraNotSendingDataTitle": "Geen toegang tot camera",
"cameraTimeoutError": "Er heeft een camera timeout opgetreden.",
"cameraPermissionDeniedError": "U hebt geen toestemming verleend om uw camera te gebruiken. U kunt wel deelnemen aan de vergadering, maar anderen kunnen u niet zien. Gebruik de cameraknop in de adresbalk om dit op te lossen.",
"cameraUnknownError": "Kan de camera om een onbekende reden niet gebruiken.",
"cameraUnsupportedResolutionError": "Uw camera ondersteunt de vereiste videoresolutie niet.",
@@ -190,6 +197,7 @@
"connectErrorWithMsg": "Oeps! Er is iets misgegaan en er kon geen verbinding met de vergadering worden gemaakt: {{msg}}",
"connecting": "Verbinding maken",
"contactSupport": "Contact opnemen met ondersteuning",
"copied": "Gekopieerd",
"copy": "Kopiëren",
"dismiss": "Negeren",
"displayNameRequired": "Hallo! Wat is uw naam?",
@@ -232,6 +240,7 @@
"micNotSendingDataTitle": "Uw microfoon is gedempt door uw systeeminstellingen",
"micPermissionDeniedError": "U hebt geen toestemming verleend om uw microfoon te gebruiken. U kunt wel deelnemen aan de vergadering, maar anderen kunnen u niet horen. Gebruik de cameraknop in de adresbalk om dit op te lossen.",
"micUnknownError": "Kan de microfoon om een onbekende reden niet gebruiken.",
"micTimeoutError": "Kan de microfoon niet gebruiken vanwege een timeout fout.",
"muteEveryoneElseDialog": "Eenmaal gedempt kunt u het dempen niet opheffen, maar zij kunnen dit wel ieder moment zelf doen.",
"muteEveryoneElseTitle": "Iedereen dempen behalve {{whom}}?",
"muteEveryoneDialog": "Weet u zeker dat u iedereen wilt dempen? U kunt het dempen niet opheffen, maar zij kunnen dit wel ieder moment zelf doen.",
@@ -242,6 +251,13 @@
"muteParticipantButton": "Dempen",
"muteParticipantDialog": "Weet u zeker dat u deze deelnemer wilt dempen? U kunt het dempen niet opheffen, maar deze deelnemer kan dit wel ieder moment zelf doen.",
"muteParticipantTitle": "Deze deelnemer dempen?",
"muteEveryoneElsesVideoDialog": "Als u de camera's uitzet kan u hem niet meer aanzetten, maar de andere deelnemers kunnen dit wel ieder moment zelf doen.",
"muteEveryoneElsesVideoTitle": "De camera van iedereen behalve {{whom}} uitzetten?",
"muteEveryonesVideoDialog": "Weet u zeker dat u iedereen zijn camera uit wilt zetten? Als u de camera's uitzet kan u hem niet meer aanzetten, maar de andere deelnemers kunnen dit wel ieder moment zelf doen.",
"muteEveryonesVideoTitle": "Iedereen zijn camera uitzetten?",
"muteParticipantsVideoButton": "Camera uitzetten",
"muteParticipantsVideoTitle": "Camera van deze deelnemer uitzetten?",
"muteParticipantsVideoBody": "Het is niet mogelijk voor u om de camera weer aan te zetten, de deelnemer kan de camera wel weer aanzetten.",
"Ok": "OK",
"passwordLabel": "De vergadering is vergrendeld door een deelnemer. Voer het $t(lockRoomPassword) in om deel te nemen.",
"passwordNotSupported": "Instellen van een $t(lockRoomPassword) voor de vergadering wordt niet ondersteund.",
@@ -279,6 +295,7 @@
"sendPrivateMessageTitle": "Privé versturen?",
"serviceUnavailable": "Service niet beschikbaar",
"sessTerminated": "Gesprek beëindigd",
"sessionRestarted": "Gesprek herstart door de server",
"Share": "Delen",
"shareVideoLinkError": "Geef een juiste YouTube-link op",
"shareVideoTitle": "Een video delen",
@@ -300,7 +317,9 @@
"tokenAuthFailedTitle": "Authenticering mislukt",
"transcribing": "Transcriberen",
"unlockRoom": "$t(lockRoomPasswordUppercase) voor vergadering verwijderen",
"user": "gebruiker",
"userPassword": "gebruikerswachtwoord",
"videoLink": "Video link",
"WaitForHostMsg": "De vergadering <b>{{room}}</b> is nog niet gestart. Authenticeer uzelf als u de host bent. Anders wacht u tot de host aanwezig is.",
"WaitForHostMsgWOk": "De vergadering <b>{{room}}</b> is nog niet gestart. Als u de host bent, drukt u op 'OK' om uzelf te authenticeren. Anders wacht u tot de host aanwezig is.",
"WaitingForHost": "Wachten op de host...",
@@ -316,6 +335,17 @@
"e2ee": {
"labelToolTip": "Audio- en Videocommunicatie in dit gesprek is eind-tot-eind-versleuteld"
},
"embedMeeting": {
"title": "Deze vergadering embedden"
},
"virtualBackground": {
"title": "Achtergronden",
"enableBlur": "Vervagen inschakelen",
"removeBackground": "Verwijder achtergrond",
"uploadImage": "Afbeelding uploaden",
"pleaseWait": "Even geduld a.u.b...",
"none": "Geen"
},
"feedback": {
"average": "Gemiddeld",
"bad": "Slecht",
@@ -477,6 +507,8 @@
"mutedTitle": "U bent gedempt!",
"mutedRemotelyTitle": "U bent gedempt door {{participantDisplayName}}!",
"mutedRemotelyDescription": "U kunt het dempen altijd opheffen wanneer u klaar bent om te spreken. Demp opnieuw wanneer u klaar bent, om ruis buiten de vergadering te houden.",
"videoMutedRemotelyTitle": "Uw camera is uitgezet door {{participantDisplayName}}!",
"videoMutedRemotelyDescription": "U kan hem ten alle tijden weer aanzetten.",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) verwijderd door een andere deelnemer",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) ingesteld door een ander deelnemer",
"raisedHand": "{{name}} zou graag willen spreken.",
@@ -501,6 +533,7 @@
"audioAndVideoError": "Audio- en videofout:",
"audioOnlyError": "Audiofout:",
"audioTrackError": "Kon audiotrack niet aanmaken.",
"audioDeviceProblem": "Er is een probleem met uw microfoon",
"callMe": "Bel me",
"callMeAtNumber": "Bel me op dit nummer:",
"configuringDevices": "Apparaten instellen...",
@@ -746,7 +779,7 @@
"profile": "Uw profiel bewerken",
"raiseHand": "Uw hand opsteken / laten zakken",
"raiseYourHand": "Uw hand opsteken",
"security": "Beveiligingsoptions",
"security": "Beveiligingsopties",
"Settings": "Instellingen",
"sharedvideo": "Een YouTube-video delen",
"shareRoom": "Iemand uitnodigen",

View File

@@ -4,7 +4,7 @@
"addContacts": "Пригласите других людей",
"copyInvite": "Скопировать приглашение на встречу",
"copyLink": "Скопировать ссылку на встречу",
"copyStream": "Скопировать ссылку на прямую транасляцию",
"copyStream": "Скопировать ссылку на прямую трансляцию",
"countryNotSupported": "Эта страна пока не поддерживается.",
"countryReminder": "Вызов не в США? Пожалуйста, убедитесь, что указали код страны!",
"defaultEmail": "Ваш адрес электронной почты",
@@ -472,7 +472,7 @@
"knockingParticipantList": "Список ожидающих участников",
"nameField": "Введите ваше имя",
"notificationLobbyAccessDenied": "{{originParticipantName}} запретил присоединиться {{targetParticipantName}}",
"notificationLobbyAccessGranted": "{{originParticipantName}}разрешил присоединиться {{targetParticipantName}} ",
"notificationLobbyAccessGranted": "{{originParticipantName}} разрешил присоединиться {{targetParticipantName}} ",
"notificationLobbyDisabled": "Лобби отключено пользователем {{originParticipantName}}",
"notificationLobbyEnabled": "Лобби включено пользователем {{originParticipantName}}",
"notificationTitle": "Лобби",

View File

@@ -113,6 +113,7 @@
"maxEnabledResolution": "send max",
"more": "Zobraziť viac",
"packetloss": "Strata paketov:",
"participant_id": "ID účastníka:",
"quality": {
"good": "Dobré",
"inactive": "Neaktívne",
@@ -316,10 +317,13 @@
"e2ee": {
"labelToolTip": "Zvuková a obrazová komunikácia je koncovo šifrovaná"
},
"embedMeeting": {
"title": "Vložiť toto stretnutie"
},
"feedback": {
"average": "Priemerný",
"bad": "Zlý",
"detailsLabel": "Povedzte nám viac.",
"detailsLabel": "Povedzte nám viac",
"good": "Dobrý",
"rateExperience": "Ohodnoťte dojem",
"veryBad": "Veľmi zlý",
@@ -762,7 +766,8 @@
"toggleCamera": "Zmeniť kameru",
"videomute": "Vypnúť / Zapnúť kameru",
"startvideoblur": "Rozmazať pozadie",
"stopvideoblur": "Ukončiť rozmazanie pozadia"
"stopvideoblur": "Ukončiť rozmazanie pozadia",
"selectBackground": "Vybrať pozadie"
},
"transcribing": {
"ccButtonTooltip": "titulky vypnuť/zapnúť",
@@ -827,7 +832,9 @@
"muted": "Vypnutý mikrofón",
"remoteControl": "Vzdialené ovládanie",
"show": "Ukázať v popredí",
"videomute": "Účastník vypol kameru"
"videomute": "Účastník vypol kameru",
"videoMuted": "Vypnutá kamera",
"domuteVideoOfOthers": "Vypnúť kamery ostatným"
},
"welcomepage": {
"accessibilityLabel": {

View File

@@ -28,6 +28,7 @@
"shareInvite": "Share meeting invitation",
"shareLink": "Share the meeting link to invite others",
"shareStream": "Share the live streaming link",
"sip": "SIP: {{address}}",
"telephone": "Telephone: {{number}}",
"title": "Invite people to this meeting",
"yahooEmail": "Yahoo Email"
@@ -61,6 +62,7 @@
"today": "Today"
},
"chat": {
"enter": "Enter chat room",
"error": "Error: your message was not sent. Reason: {{error}}",
"fieldPlaceHolder": "Type your message here",
"messagebox": "Type a message",
@@ -174,6 +176,7 @@
"alreadySharedVideoMsg": "Another participant is already sharing a video. This conference allows only one shared video at a time.",
"alreadySharedVideoTitle": "Only one shared video is allowed at a time",
"applicationWindow": "Application window",
"authenticationRequired": "Authentication required",
"Back": "Back",
"cameraConstraintFailedError": "Your camera does not satisfy some of the required constraints.",
"cameraNotFoundError": "Camera was not found.",
@@ -226,6 +229,7 @@
"lockRoom": "Add meeting $t(lockRoomPasswordUppercase)",
"lockTitle": "Lock failed",
"logoutQuestion": "Are you sure you want to logout and stop the conference?",
"login": "Login",
"logoutTitle": "Logout",
"maxUsersLimitReached": "The limit for maximum number of participants has been reached. The conference is full. Please contact the meeting owner or try again later!",
"maxUsersLimitReachedTitle": "Maximum participants limit reached",
@@ -240,12 +244,20 @@
"muteEveryoneElseTitle": "Mute everyone except {{whom}}?",
"muteEveryoneDialog": "Are you sure you want to mute everyone? You won't be able to unmute them, but they can unmute themselves at any time.",
"muteEveryoneTitle": "Mute everyone?",
"muteEveryoneElsesVideoDialog": "Once the camera is disabled, you won't be able to turn it back on, but they can turn it back on at any time.",
"muteEveryoneElsesVideoTitle": "Disable everyone's camera except {{whom}}?",
"muteEveryonesVideoDialog": "Are you sure you want to disable everyone's camera? You won't be able to turn it back on, but they can turn it back on at any time.",
"muteEveryonesVideoDialogOk": "Disable",
"muteEveryonesVideoTitle": "Disable everyone's camera?",
"muteEveryoneSelf": "yourself",
"muteEveryoneStartMuted": "Everyone starts muted from now on",
"muteParticipantBody": "You won't be able to unmute them, but they can unmute themselves at any time.",
"muteParticipantButton": "Mute",
"muteParticipantDialog": "Are you sure you want to mute this participant? You won't be able to unmute them, but they can unmute themselves at any time.",
"muteParticipantTitle": "Mute this participant?",
"muteParticipantsVideoButton": "Disable camera",
"muteParticipantsVideoTitle": "Disable camera of this participant?",
"muteParticipantsVideoBody": "You won't be able to turn the camera back on, but they can turn it back on at any time.",
"Ok": "OK",
"passwordLabel": "The meeting has been locked by a participant. Please enter the $t(lockRoomPassword) to join.",
"passwordNotSupported": "Setting a meeting $t(lockRoomPassword) is not supported.",
@@ -303,11 +315,13 @@
"tokenAuthFailedTitle": "Authentication failed",
"transcribing": "Transcribing",
"unlockRoom": "Remove meeting $t(lockRoomPassword)",
"user": "user",
"userPassword": "user password",
"user": "User",
"userIdentifier": "User identifier",
"userPassword": "User password",
"videoLink": "Video link",
"WaitForHostMsg": "The conference <b>{{room}}</b> has not yet started. If you are the host then please authenticate. Otherwise, please wait for the host to arrive.",
"WaitForHostMsgWOk": "The conference <b>{{room}}</b> has not yet started. If you are the host then please press Ok to authenticate. Otherwise, please wait for the host to arrive.",
"WaitingForHost": "Waiting for the host ...",
"WaitingForHostTitle": "Waiting for the host ...",
"Yes": "Yes",
"yourEntireScreen": "Your entire screen"
},
@@ -323,6 +337,14 @@
"embedMeeting": {
"title": "Embed this meeting"
},
"virtualBackground": {
"title": "Backgrounds",
"enableBlur": "Enable blur",
"removeBackground": "Remove background",
"uploadImage": "Upload image",
"pleaseWait": "Please wait...",
"none": "None"
},
"feedback": {
"average": "Average",
"bad": "Bad",
@@ -483,6 +505,8 @@
"mutedTitle": "You're muted!",
"mutedRemotelyTitle": "You have been muted by {{participantDisplayName}}!",
"mutedRemotelyDescription": "You can always unmute when you're ready to speak. Mute back when you're done to keep noise away from the meeting.",
"videoMutedRemotelyTitle": "Your camera has been disabled by {{participantDisplayName}}!",
"videoMutedRemotelyDescription": "You can always turn it on again.",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removed by another participant",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) set by another participant",
"raisedHand": "{{name}} would like to speak.",
@@ -715,15 +739,19 @@
"moreOptions": "Show more options",
"mute": "Toggle mute audio",
"muteEveryone": "Mute everyone",
"muteEveryoneElse": "Mute everyone else",
"muteEveryonesVideo": "Disable everyone's camera",
"muteEveryoneElsesVideo": "Disable everyone else's camera",
"pip": "Toggle Picture-in-Picture mode",
"privateMessage": "Send private message",
"profile": "Edit your profile",
"raiseHand": "Toggle raise hand",
"recording": "Toggle recording",
"remoteMute": "Mute participant",
"remoteVideoMute": "Disable camera of participant",
"security": "Security options",
"Settings": "Toggle settings",
"sharedvideo": "Toggle Youtube video sharing",
"sharedvideo": "Toggle YouTube video sharing",
"shareRoom": "Invite someone",
"shareYourScreen": "Toggle screenshare",
"shortcuts": "Toggle shortcuts",
@@ -733,9 +761,10 @@
"toggleCamera": "Toggle camera",
"toggleFilmstrip": "Toggle filmstrip",
"videomute": "Toggle mute video",
"videoblur": "Toggle video blur"
"selectBackground": "Select Background"
},
"addPeople": "Add people to your call",
"audioSettings": "Audio settings",
"audioOnlyOff": "Disable low bandwidth mode",
"audioOnlyOn": "Enable low bandwidth mode",
"audioRoute": "Select the sound device",
@@ -765,6 +794,7 @@
"moreOptions": "More options",
"mute": "Mute / Unmute",
"muteEveryone": "Mute everyone",
"muteEveryonesVideo": "Disable everyone's camera",
"noAudioSignalTitle": "There is no input coming from your mic!",
"noAudioSignalDesc": "If you did not purposely mute it from system settings or hardware, consider switching the device.",
"noAudioSignalDescSuggestion": "If you did not purposely mute it from system settings or hardware, consider switching to the suggested device.",
@@ -793,8 +823,8 @@
"tileViewToggle": "Toggle tile view",
"toggleCamera": "Toggle camera",
"videomute": "Start / Stop camera",
"startvideoblur": "Blur my background",
"stopvideoblur": "Disable background blur"
"videoSettings": "Video settings",
"selectBackground": "Select background"
},
"transcribing": {
"ccButtonTooltip": "Start / Stop subtitles",
@@ -849,13 +879,16 @@
"videothumbnail": {
"connectionInfo": "Connection Info",
"domute": "Mute",
"domuteVideo": "Disable camera",
"domuteOthers": "Mute everyone else",
"domuteVideoOfOthers": "Disable camera of everyone else",
"flip": "Flip",
"grantModerator": "Grant Moderator",
"kick": "Kick out",
"moderator": "Moderator",
"mute": "Participant is muted",
"muted": "Muted",
"videoMuted": "Camera disabled",
"remoteControl": "Start / Stop remote control",
"show": "Show on stage",
"videomute": "Participant has stopped the camera"

View File

@@ -12,9 +12,19 @@ import {
setPassword,
setSubject
} from '../../react/features/base/conference';
import { overwriteConfig, getWhitelistedJSON } from '../../react/features/base/config';
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
import JitsiMeetJS, { JitsiRecordingConstants } from '../../react/features/base/lib-jitsi-meet';
import { pinParticipant, getParticipantById, kickParticipant } from '../../react/features/base/participants';
import { MEDIA_TYPE } from '../../react/features/base/media';
import {
getLocalParticipant,
getParticipantById,
participantUpdated,
pinParticipant,
kickParticipant
} from '../../react/features/base/participants';
import { updateSettings } from '../../react/features/base/settings';
import { isToggleCameraEnabled, toggleCamera } from '../../react/features/base/tracks';
import { setPrivateMessageRecipient } from '../../react/features/chat/actions';
import { openChat } from '../../react/features/chat/actions.web';
import {
@@ -31,8 +41,8 @@ import {
import { toggleLobbyMode } from '../../react/features/lobby/actions.web';
import { RECORDING_TYPES } from '../../react/features/recording/constants';
import { getActiveSession } from '../../react/features/recording/functions';
import { muteAllParticipants } from '../../react/features/remote-video-menu/actions';
import { toggleTileView } from '../../react/features/video-layout';
import { toggleTileView, setTileView } from '../../react/features/video-layout';
import { muteAllParticipants } from '../../react/features/video-menu/actions';
import { setVideoQuality } from '../../react/features/video-quality';
import { getJitsiMeetTransport } from '../transport';
@@ -79,7 +89,9 @@ function initCommands() {
sendAnalytics(createApiEvent('display.name.changed'));
APP.conference.changeLocalDisplayName(displayName);
},
'mute-everyone': () => {
'mute-everyone': mediaType => {
const muteMediaType = mediaType ? mediaType : MEDIA_TYPE.AUDIO;
sendAnalytics(createApiEvent('muted-everyone'));
const participants = APP.store.getState()['features/base/participants'];
const localIds = participants
@@ -87,7 +99,7 @@ function initCommands() {
.filter(participant => participant.role === 'moderator')
.map(participant => participant.id);
APP.store.dispatch(muteAllParticipants(localIds));
APP.store.dispatch(muteAllParticipants(localIds, muteMediaType));
},
'toggle-lobby': isLobbyEnabled => {
APP.store.dispatch(toggleLobbyMode(isLobbyEnabled));
@@ -159,10 +171,40 @@ function initCommands() {
sendAnalytics(createApiEvent('film.strip.toggled'));
APP.UI.toggleFilmstrip();
},
'toggle-camera': () => {
if (!isToggleCameraEnabled(APP.store.getState())) {
return;
}
APP.store.dispatch(toggleCamera());
},
'toggle-camera-mirror': () => {
const state = APP.store.getState();
const { localFlipX: currentFlipX } = state['features/base/settings'];
APP.store.dispatch(updateSettings({ localFlipX: !currentFlipX }));
},
'toggle-chat': () => {
sendAnalytics(createApiEvent('chat.toggled'));
APP.UI.toggleChat();
},
'toggle-raise-hand': () => {
const localParticipant = getLocalParticipant(APP.store.getState());
if (!localParticipant) {
return;
}
const { raisedHand } = localParticipant;
sendAnalytics(createApiEvent('raise-hand.toggled'));
APP.store.dispatch(
participantUpdated({
id: APP.conference.getMyUserId(),
local: true,
raisedHand: !raisedHand
})
);
},
/**
* Callback to invoke when the "toggle-share-screen" command is received.
@@ -182,6 +224,9 @@ function initCommands() {
APP.store.dispatch(toggleTileView());
},
'set-tile-view': enabled => {
APP.store.dispatch(setTileView(enabled));
},
'video-hangup': (showFeedbackDialog = true) => {
sendAnalytics(createApiEvent('video.hangup'));
APP.conference.hangup(showFeedbackDialog);
@@ -353,6 +398,11 @@ function initCommands() {
},
'kick-participant': participantId => {
APP.store.dispatch(kickParticipant(participantId));
},
'overwrite-config': config => {
const whitelistedConfig = getWhitelistedJSON('config', config);
APP.store.dispatch(overwriteConfig(whitelistedConfig));
}
};
transport.on('event', ({ data, name }) => {
@@ -1115,6 +1165,23 @@ class API {
});
}
/**
* Notify external application (if API is enabled) that recording has started or stopped.
*
* @param {boolean} on - True if recording is on, false otherwise.
* @param {string} mode - Stream or file.
* @param {string} error - Error type or null if success.
* @returns {void}
*/
notifyRecordingStatusChanged(on: boolean, mode: string, error?: string) {
this._sendEvent({
name: 'recording-status-changed',
on,
mode,
error
});
}
/**
* Disposes the allocated resources.
*

Some files were not shown because too many files have changed in this diff Show More