mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 19:32:27 +00:00
Compare commits
806 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
16c45c15c8 | ||
|
|
5d5d6c3068 | ||
|
|
19399ec123 | ||
|
|
3c27f15490 | ||
|
|
607073c669 | ||
|
|
f92ee57f9c | ||
|
|
32331d7465 | ||
|
|
88685c43fb | ||
|
|
348573b254 | ||
|
|
1a05991b8c | ||
|
|
c3f2390642 | ||
|
|
7cf8902fdd | ||
|
|
3e4fb82d58 | ||
|
|
057dc0e4d2 | ||
|
|
ce4cbacceb | ||
|
|
af4f122602 | ||
|
|
b7f5b8ecd2 | ||
|
|
d15e51adbd | ||
|
|
affef1ac66 | ||
|
|
7f95dbb6d6 | ||
|
|
8065da61c7 | ||
|
|
b6df08f072 | ||
|
|
73752618a3 | ||
|
|
3c7829a457 | ||
|
|
0b0bbcf194 | ||
|
|
3cd29fd63e | ||
|
|
c486dc07db | ||
|
|
b48772f898 | ||
|
|
21533f0261 | ||
|
|
1ecfa3a78e | ||
|
|
921c27165d | ||
|
|
6fa94b0bb4 | ||
|
|
3f3a074e02 | ||
|
|
ecb57774ed | ||
|
|
1e82f1fb1a | ||
|
|
b4b54108c5 | ||
|
|
6903ccf009 | ||
|
|
6e45643cce | ||
|
|
379b26a753 | ||
|
|
e8faa99ff0 | ||
|
|
62d2c9f633 | ||
|
|
311c404a1a | ||
|
|
b17a3a9d86 | ||
|
|
5477e46489 | ||
|
|
7e170fe0d0 | ||
|
|
bbbc9d1f46 | ||
|
|
084905545f | ||
|
|
d542b05bc4 | ||
|
|
58b73d8dbd | ||
|
|
471853ef15 | ||
|
|
a0070c34f7 | ||
|
|
5bc8bc8b64 | ||
|
|
ea04c5e96e | ||
|
|
d4e2f17acc | ||
|
|
4dcc4b3711 | ||
|
|
80081ce31c | ||
|
|
5314d779ed | ||
|
|
cf7c39d3e5 | ||
|
|
4e4f91f184 | ||
|
|
972a13f3fe | ||
|
|
2ec3cfcb9e | ||
|
|
a3d89ea66f | ||
|
|
487fd5de1f | ||
|
|
bed94e6698 | ||
|
|
939fdf6c8e | ||
|
|
0f5412715a | ||
|
|
dd8f2f53f3 | ||
|
|
92df4bfbbb | ||
|
|
b97798e1ca | ||
|
|
f488ef1e5c | ||
|
|
c4fcfb8666 | ||
|
|
0ccb088c05 | ||
|
|
a7f4d9cadd | ||
|
|
716c6cc567 | ||
|
|
153f67d852 | ||
|
|
8745f07052 | ||
|
|
0a467f78ee | ||
|
|
1e8cc9d085 | ||
|
|
65e7fa571a | ||
|
|
68b471ba29 | ||
|
|
c09a3524c7 | ||
|
|
101bd637b0 | ||
|
|
078503b1b3 | ||
|
|
8c4e9f823d | ||
|
|
fe1f858ef9 | ||
|
|
dd7b953a92 | ||
|
|
1f2aaa8dc0 | ||
|
|
80bf228a65 | ||
|
|
62e0f09f98 | ||
|
|
6654feacee | ||
|
|
3d4defd799 | ||
|
|
e15bf2d4dd | ||
|
|
6de935b372 | ||
|
|
3397b9cbc9 | ||
|
|
45626a0d23 | ||
|
|
b7bccb0801 | ||
|
|
475ec6d427 | ||
|
|
a28b155c41 | ||
|
|
5f44c7580d | ||
|
|
3d1eb5282c | ||
|
|
10935ec692 | ||
|
|
95a0a8418f | ||
|
|
0a5e914862 | ||
|
|
02ff359de2 | ||
|
|
fecac0322e | ||
|
|
bd1c3332ea | ||
|
|
5ee0738e45 | ||
|
|
c3518208e1 | ||
|
|
21116c09f4 | ||
|
|
875a9cbaf3 | ||
|
|
5fd050b77f | ||
|
|
fee6ecc82d | ||
|
|
2ba57730cd | ||
|
|
78c304cba8 | ||
|
|
b082354773 | ||
|
|
8bd377098d | ||
|
|
7d6990b3f8 | ||
|
|
a51e97f318 | ||
|
|
bc65d21ce4 | ||
|
|
e9236fd9ff | ||
|
|
c4dff9a75e | ||
|
|
edf0a35392 | ||
|
|
f291dc90f4 | ||
|
|
ea0f9e7934 | ||
|
|
480b6f7cdc | ||
|
|
19f91bea84 | ||
|
|
59420ea1a8 | ||
|
|
d969a5311e | ||
|
|
3e025c9f01 | ||
|
|
1e558b143f | ||
|
|
5cfc0378f7 | ||
|
|
6ad8ad3506 | ||
|
|
c2488f4071 | ||
|
|
a63a344f6e | ||
|
|
53acd386f0 | ||
|
|
4469917d45 | ||
|
|
f967efa3e4 | ||
|
|
dc6ee21b5d | ||
|
|
481e8634e0 | ||
|
|
bca746cfc4 | ||
|
|
29663bcec2 | ||
|
|
bd7b2c6e7a | ||
|
|
eee80941b0 | ||
|
|
06c571cafb | ||
|
|
5c3ea96131 | ||
|
|
e6bf6a09f4 | ||
|
|
6e6a3b2f72 | ||
|
|
cbfa5e38b3 | ||
|
|
94c55f7aa4 | ||
|
|
9843aca00a | ||
|
|
816e991ae5 | ||
|
|
cfbdbd4783 | ||
|
|
f83ad5af27 | ||
|
|
a5afd011a1 | ||
|
|
c88891da5b | ||
|
|
b1af0c800b | ||
|
|
146d2c8b66 | ||
|
|
a18e193611 | ||
|
|
6ae0bc36cc | ||
|
|
b1410c34e0 | ||
|
|
070991d7ef | ||
|
|
874f59f0ff | ||
|
|
fa547b5aac | ||
|
|
d27580c016 | ||
|
|
2093ef1ea2 | ||
|
|
75540a588d | ||
|
|
fe51b4c56a | ||
|
|
c7c42f6983 | ||
|
|
68df1b1281 | ||
|
|
00efcfaae5 | ||
|
|
c6b194a073 | ||
|
|
8ac44dfbb3 | ||
|
|
ea2ab9edc0 | ||
|
|
9d27c705f6 | ||
|
|
ebdd9755ba | ||
|
|
fa2a8c5084 | ||
|
|
ac2d73b57c | ||
|
|
93902e6364 | ||
|
|
42163731b3 | ||
|
|
01ce04fe9b | ||
|
|
5d29363764 | ||
|
|
bfe8bc9b73 | ||
|
|
a6f6235dd0 | ||
|
|
ee6bf011e9 | ||
|
|
bea8a7f984 | ||
|
|
2edca5dacb | ||
|
|
69ac73c556 | ||
|
|
89556ecd66 | ||
|
|
462f91f070 | ||
|
|
d29a77b15f | ||
|
|
c31fe521c4 | ||
|
|
8f6f542e9c | ||
|
|
69d9e7d405 | ||
|
|
5e6748a88a | ||
|
|
8bc70f9c87 | ||
|
|
357d226987 | ||
|
|
6b1f7138c6 | ||
|
|
55219dc51b | ||
|
|
0eb3a9a43c | ||
|
|
4d7136b7a7 | ||
|
|
b7d9e1d85d | ||
|
|
a714058328 | ||
|
|
02ff4a1bac | ||
|
|
7833e1337e | ||
|
|
18e0e64ca0 | ||
|
|
80a3d88359 | ||
|
|
5d72028872 | ||
|
|
e89776848c | ||
|
|
70bc78e765 | ||
|
|
4fceae7733 | ||
|
|
23b7dd4abf | ||
|
|
0216bbd1d9 | ||
|
|
15a4fa45e0 | ||
|
|
f2d9ffd5f6 | ||
|
|
b0ba7c8671 | ||
|
|
e5fa25892e | ||
|
|
ae5fe24556 | ||
|
|
b9ef0aa27a | ||
|
|
f30625acf0 | ||
|
|
66d70305a0 | ||
|
|
9108b7ebec | ||
|
|
9454049220 | ||
|
|
2ce2e01803 | ||
|
|
ab25d6c5ab | ||
|
|
1b0dc0cfb0 | ||
|
|
33e484a847 | ||
|
|
67bebc0491 | ||
|
|
9186a74ae3 | ||
|
|
67d9a9819e | ||
|
|
16b88a29db | ||
|
|
9783793514 | ||
|
|
93de398a09 | ||
|
|
23e97a4284 | ||
|
|
9bb906551e | ||
|
|
b1ad82cef9 | ||
|
|
09c9f2930c | ||
|
|
74efbd7a61 | ||
|
|
1b1e7d9bce | ||
|
|
dc98fc4839 | ||
|
|
a815f97c7e | ||
|
|
8261cf2811 | ||
|
|
f2238935b5 | ||
|
|
5f12f76ada | ||
|
|
5a9464697f | ||
|
|
f44601a82b | ||
|
|
3d3de4a884 | ||
|
|
c02ad56b6d | ||
|
|
ea7c5ccd58 | ||
|
|
7ec3eae72b | ||
|
|
edf7d18308 | ||
|
|
6bf4a4e91d | ||
|
|
5fd966f042 | ||
|
|
e275f20055 | ||
|
|
ff624a34d8 | ||
|
|
c98050224c | ||
|
|
5bee373091 | ||
|
|
db4ab34ddf | ||
|
|
ef138fb5aa | ||
|
|
13bfdaed68 | ||
|
|
ff656f4e6b | ||
|
|
a27b78cef0 | ||
|
|
4fa426ace0 | ||
|
|
ac34f524fa | ||
|
|
31a4f2a4ec | ||
|
|
dc908512f9 | ||
|
|
ae983645d1 | ||
|
|
3514b22191 | ||
|
|
405af3af5f | ||
|
|
a6d333c07a | ||
|
|
0387cdc888 | ||
|
|
f670f39dd2 | ||
|
|
7262465777 | ||
|
|
75b4049529 | ||
|
|
ac6185424c | ||
|
|
9e15df8e3d | ||
|
|
83f83c17eb | ||
|
|
3e1adcd9b7 | ||
|
|
8105127571 | ||
|
|
bc99a72984 | ||
|
|
e10eaaa3d9 | ||
|
|
0e831074c0 | ||
|
|
326b694bf2 | ||
|
|
9e1f3de4e5 | ||
|
|
07a25a1f00 | ||
|
|
d6bbe07cf2 | ||
|
|
e9a8fd5392 | ||
|
|
aea9c5e79e | ||
|
|
b60210d0ad | ||
|
|
f0d2106c1a | ||
|
|
13f1cb13c5 | ||
|
|
c27ca779ab | ||
|
|
aedb43ec5b | ||
|
|
0a68eed294 | ||
|
|
3f51b10245 | ||
|
|
5260cd7e30 | ||
|
|
0d109eaf00 | ||
|
|
75c43fc8f2 | ||
|
|
532b5858c5 | ||
|
|
edc2328fd6 | ||
|
|
a603a8df06 | ||
|
|
703a4d0f34 | ||
|
|
44c1624c61 | ||
|
|
5b5e233734 | ||
|
|
5607e50b8e | ||
|
|
39c942d585 | ||
|
|
1c04f974d8 | ||
|
|
dc5142cb6b | ||
|
|
d563913499 | ||
|
|
4d0642d1a7 | ||
|
|
8d8e83cdfd | ||
|
|
6d0271338e | ||
|
|
1401eb245e | ||
|
|
27eec7b19e | ||
|
|
b0d0b3ac11 | ||
|
|
2c11b1b945 | ||
|
|
2c92ea57f0 | ||
|
|
09b696e95a | ||
|
|
d67054a550 | ||
|
|
05374e292b | ||
|
|
f038099e61 | ||
|
|
da5f2d00d4 | ||
|
|
c8a7877fdd | ||
|
|
d8da660070 | ||
|
|
4e033fff4b | ||
|
|
4861f95368 | ||
|
|
b3ee8fe127 | ||
|
|
95a6001a6f | ||
|
|
a3622a3698 | ||
|
|
4cdc193ac3 | ||
|
|
5c9b8a5a5f | ||
|
|
44bd70179c | ||
|
|
0973081fea | ||
|
|
006c491de4 | ||
|
|
24cfa7b4e1 | ||
|
|
b890aa33c3 | ||
|
|
9846228210 | ||
|
|
445eef97b3 | ||
|
|
298279a956 | ||
|
|
5ebf5adfa2 | ||
|
|
35554533d1 | ||
|
|
fb397db69f | ||
|
|
8fc295b385 | ||
|
|
ee8b62cf73 | ||
|
|
217b803652 | ||
|
|
2442a332e7 | ||
|
|
2e43706a4a | ||
|
|
e7db943b73 | ||
|
|
c1cbd37d87 | ||
|
|
ef56f1d23d | ||
|
|
2ab002650c | ||
|
|
867646da1a | ||
|
|
ff78bfb62f | ||
|
|
1827610fc1 | ||
|
|
0ae8051fb4 | ||
|
|
1b7668bbdc | ||
|
|
4c37e0d761 | ||
|
|
a6ff652a03 | ||
|
|
17f34878db | ||
|
|
37856e0fdb | ||
|
|
7c1de52f6a | ||
|
|
9e3438696b | ||
|
|
9c23cc0b70 | ||
|
|
af8157bc06 | ||
|
|
c21f84c15a | ||
|
|
1edf88e744 | ||
|
|
bad75b488e | ||
|
|
5bb3ba71d0 | ||
|
|
4e0001c9af | ||
|
|
ada6150971 | ||
|
|
62d1ee606a | ||
|
|
1e1de6acf0 | ||
|
|
e1e0fba4ff | ||
|
|
97be3fa399 | ||
|
|
fbdee85c4b | ||
|
|
b71b4c8c45 | ||
|
|
a8d123ede4 | ||
|
|
fb8e451e2e | ||
|
|
5dd7944bdb | ||
|
|
48732c6784 | ||
|
|
97146ed8a7 | ||
|
|
78b17c8d17 | ||
|
|
9732d1be86 | ||
|
|
a836187620 | ||
|
|
a0cad4c595 | ||
|
|
19b9eac84a | ||
|
|
068e33fc0f | ||
|
|
00c6bee2fd | ||
|
|
748ead7e13 | ||
|
|
174c4418fb | ||
|
|
64494cab81 | ||
|
|
50d0092e30 | ||
|
|
fdbd7239ff | ||
|
|
a30958ab23 | ||
|
|
aca55172e4 | ||
|
|
c6cce9253c | ||
|
|
c23684e11c | ||
|
|
30595584a3 | ||
|
|
3d30489cc4 | ||
|
|
7288a6dce4 | ||
|
|
697c41bffa | ||
|
|
0361830122 | ||
|
|
6bb984acc8 | ||
|
|
938d112f6b | ||
|
|
d8cca36181 | ||
|
|
c9add0a9ef | ||
|
|
aabc50da60 | ||
|
|
4aa4382d2b | ||
|
|
6bf1b46609 | ||
|
|
9d7237dc24 | ||
|
|
3745c19857 | ||
|
|
cd6419d826 | ||
|
|
a05e8fd2ef | ||
|
|
239e5743dd | ||
|
|
01a731ab4d | ||
|
|
3d56538c69 | ||
|
|
2dc135b80f | ||
|
|
4e81d4461b | ||
|
|
68b16d7bc8 | ||
|
|
45f6550d30 | ||
|
|
5c65446ef4 | ||
|
|
eee58b2945 | ||
|
|
c7cfb5218d | ||
|
|
b9017176a8 | ||
|
|
cad37306d4 | ||
|
|
83192435e7 | ||
|
|
f85d0e6469 | ||
|
|
3834f1e99c | ||
|
|
79ece5d4e5 | ||
|
|
b0ffc2cd69 | ||
|
|
5a45ebb877 | ||
|
|
dcea5332be | ||
|
|
4e72601bee | ||
|
|
ccd9386184 | ||
|
|
05a930e5f5 | ||
|
|
9bc0e7589c | ||
|
|
c0541c8737 | ||
|
|
c11147b583 | ||
|
|
ef992eaef3 | ||
|
|
0149b5f6e6 | ||
|
|
4d7c051dd0 | ||
|
|
f3324ab165 | ||
|
|
4d483f7846 | ||
|
|
478852c474 | ||
|
|
deb574a154 | ||
|
|
c2f4dd9dea | ||
|
|
67c3a50412 | ||
|
|
b303693198 | ||
|
|
a4a1619dc2 | ||
|
|
c95d1d7f7e | ||
|
|
97310b5ab5 | ||
|
|
e151be48b9 | ||
|
|
91e1007e5b | ||
|
|
8db769b174 | ||
|
|
260e5d11b9 | ||
|
|
b2fbf6d2a3 | ||
|
|
4df9087459 | ||
|
|
e0bf82aad8 | ||
|
|
91c48dfe03 | ||
|
|
a86542d650 | ||
|
|
9e9eac3e38 | ||
|
|
73cba3561e | ||
|
|
63e69c224d | ||
|
|
50e9413aad | ||
|
|
037a7c082c | ||
|
|
6af4d182d0 | ||
|
|
d438292d2c | ||
|
|
d45c108051 | ||
|
|
5cd7b9be38 | ||
|
|
aa1c3c0ad8 | ||
|
|
07810f8c2d | ||
|
|
96d41196e6 | ||
|
|
293a41d4aa | ||
|
|
def9555268 | ||
|
|
71de1d1e2d | ||
|
|
49cf63213d | ||
|
|
86d1bd3c78 | ||
|
|
122f5dffe8 | ||
|
|
da35c96afd | ||
|
|
e52c6e6b35 | ||
|
|
1e43bbbd95 | ||
|
|
2d77bf1da9 | ||
|
|
dc25a8dde4 | ||
|
|
ab51512088 | ||
|
|
956ca27b01 | ||
|
|
d7e2be200a | ||
|
|
459b5372d1 | ||
|
|
1a3dd699b7 | ||
|
|
04bee97682 | ||
|
|
aa506a7607 | ||
|
|
afac97e7d4 | ||
|
|
61a0247f30 | ||
|
|
7b4965f6b2 | ||
|
|
d78b980b35 | ||
|
|
103d1d9f35 | ||
|
|
6d3330a208 | ||
|
|
771f5af59d | ||
|
|
2c96880985 | ||
|
|
3fb968b3cb | ||
|
|
b2059060fc | ||
|
|
6ad2735efb | ||
|
|
e2a933ad92 | ||
|
|
12b682992b | ||
|
|
4f78dee708 | ||
|
|
7ff78313ff | ||
|
|
ac182c18f9 | ||
|
|
b562176062 | ||
|
|
437ed46349 | ||
|
|
f0e01da39a | ||
|
|
755ab2a108 | ||
|
|
c11f5d36ea | ||
|
|
ecf72273af | ||
|
|
960a08c066 | ||
|
|
390431f4d0 | ||
|
|
0636527146 | ||
|
|
66ba41992d | ||
|
|
036d783776 | ||
|
|
1f37e0ba8d | ||
|
|
2d15cc025e | ||
|
|
4b93cbbd8d | ||
|
|
939a9a45d3 | ||
|
|
dd859d2a26 | ||
|
|
39540531ff | ||
|
|
3d85202987 | ||
|
|
9fd6a6c822 | ||
|
|
ae00247632 | ||
|
|
2b719743d3 | ||
|
|
2b8cc89df0 | ||
|
|
b7eae6c0ca | ||
|
|
24ae69348b | ||
|
|
22f315ddfa | ||
|
|
a50d6dc0f4 | ||
|
|
15ba1bb280 | ||
|
|
3438e5d56a | ||
|
|
176e409af5 | ||
|
|
d09243c2c5 | ||
|
|
b0a050b66a | ||
|
|
26e283393f | ||
|
|
d9a0423687 | ||
|
|
39c9c24810 | ||
|
|
d6a42fbe43 | ||
|
|
808bc24d95 | ||
|
|
e04db24d15 | ||
|
|
c24c25849d | ||
|
|
d5269e881a | ||
|
|
5da69192e3 | ||
|
|
2413b8977e | ||
|
|
50b90933dc | ||
|
|
09d57972af | ||
|
|
8f1c63579c | ||
|
|
62856b0f58 | ||
|
|
a3617b042e | ||
|
|
6e13269ddb | ||
|
|
97930bfef2 | ||
|
|
7bb2f1eaad | ||
|
|
acc46c0c5f | ||
|
|
1152073b57 | ||
|
|
e328b15fcd | ||
|
|
bc21a462eb | ||
|
|
8d82c20319 | ||
|
|
574c61d3e5 | ||
|
|
9f73eb76a3 | ||
|
|
b620328861 | ||
|
|
085e6dd3b9 | ||
|
|
936fa55ce9 | ||
|
|
ede26956e8 | ||
|
|
b3742a3438 | ||
|
|
262cb0422c | ||
|
|
756c4afbdd | ||
|
|
4c9234ffec | ||
|
|
5ea2093a40 | ||
|
|
ab57a2999b | ||
|
|
7718c39319 | ||
|
|
01ef23402e | ||
|
|
15ddf04189 | ||
|
|
ac720034ab | ||
|
|
b989307c1e | ||
|
|
0fa02ff6ba | ||
|
|
d2afd5e54d | ||
|
|
7169143942 | ||
|
|
98020163ce | ||
|
|
6aa42f9850 | ||
|
|
d2ff136c15 | ||
|
|
79322f6a1f | ||
|
|
d755b9decb | ||
|
|
ad6e675b18 | ||
|
|
aa122c9652 | ||
|
|
b747fd3483 | ||
|
|
2d56dbe249 | ||
|
|
2364344046 | ||
|
|
32f9f8ba92 | ||
|
|
697ede207b | ||
|
|
c62f2f2790 | ||
|
|
1429e83a21 | ||
|
|
3f7c3b8fd2 | ||
|
|
5b4383d835 | ||
|
|
49fa243ef3 | ||
|
|
e9ca4b009a | ||
|
|
e6ccc35653 | ||
|
|
f59d04586c | ||
|
|
ec22c1fdda | ||
|
|
3441954f8b | ||
|
|
b0a87041da | ||
|
|
42586be533 | ||
|
|
65e94bd173 | ||
|
|
73c836fafb | ||
|
|
d6fa066e4d | ||
|
|
22bbf4939e | ||
|
|
ca195fd708 | ||
|
|
c3c0166731 | ||
|
|
fc94854b72 | ||
|
|
c55eb68cf2 | ||
|
|
80e08a112a | ||
|
|
896fc29af7 | ||
|
|
c88ffab370 | ||
|
|
445515da93 | ||
|
|
f5dbd6780b | ||
|
|
ba06121464 | ||
|
|
7115919206 | ||
|
|
1d95c30893 | ||
|
|
a5cd5e2733 | ||
|
|
8732675162 | ||
|
|
a074437d99 | ||
|
|
d2eb11fa5c | ||
|
|
b35200648c | ||
|
|
a8958019a5 | ||
|
|
200228339b | ||
|
|
ddc64ad687 | ||
|
|
2d2bae6ec1 | ||
|
|
fa6dc292c1 | ||
|
|
b5ac40b32a | ||
|
|
8299aa498b | ||
|
|
ce22adfe64 | ||
|
|
01bcccdd99 | ||
|
|
673a54adb1 | ||
|
|
f48c03e314 | ||
|
|
7641ddad68 | ||
|
|
26021b2dd0 | ||
|
|
a6457db819 | ||
|
|
8bfa65987d | ||
|
|
b1c0cc5322 | ||
|
|
67cbef0d7a | ||
|
|
b2e06c1c94 | ||
|
|
70a05e487e | ||
|
|
c2a446a79b | ||
|
|
56df23af35 | ||
|
|
1c12f5cf2a | ||
|
|
06b727ae1a | ||
|
|
a2aca30d57 | ||
|
|
68106feb57 | ||
|
|
3066fc1d31 | ||
|
|
4834fb7b6f | ||
|
|
1e101afe5a | ||
|
|
4d79bbb5d8 | ||
|
|
e31aff5afd | ||
|
|
7bc9913b29 | ||
|
|
2483d901d6 | ||
|
|
6ff7995cee | ||
|
|
5d563402d0 | ||
|
|
6727004930 | ||
|
|
c04000ea20 | ||
|
|
23be14697c | ||
|
|
ca07eed85f | ||
|
|
72779e5ba5 | ||
|
|
1b3b949218 | ||
|
|
d510390edc | ||
|
|
1de1381847 | ||
|
|
639114f2e1 | ||
|
|
411e9a2372 | ||
|
|
b4e4dd1aa9 | ||
|
|
81ba2331b0 | ||
|
|
50d84bfd2c | ||
|
|
60b4581cb5 | ||
|
|
2514617417 | ||
|
|
b242900619 | ||
|
|
3a40b52832 | ||
|
|
4a25b9722c | ||
|
|
dbbc7b2e89 | ||
|
|
a3c3b38993 | ||
|
|
94b6808ec6 | ||
|
|
1376f5909c | ||
|
|
74b02af318 | ||
|
|
de1e470c68 | ||
|
|
4ee613ed1f | ||
|
|
fb6a44a39b | ||
|
|
bde28105f4 | ||
|
|
782d46b4a6 | ||
|
|
160d6a4c52 | ||
|
|
767101497c | ||
|
|
889b37cedc | ||
|
|
4e727e9093 | ||
|
|
7fbf47c6f3 | ||
|
|
2d61c68615 | ||
|
|
d2ad3473a1 | ||
|
|
67f49815c4 | ||
|
|
2697eb1273 | ||
|
|
491f793530 | ||
|
|
eb0317fb8d | ||
|
|
59da1537be | ||
|
|
9e1e6237ce | ||
|
|
5c0b8467d5 | ||
|
|
b4a5e63d1d | ||
|
|
3ae50b6c4c | ||
|
|
bc9525a908 | ||
|
|
c6dcac47a8 | ||
|
|
f9f5cf87b9 | ||
|
|
b969fba433 | ||
|
|
f0fc63f573 | ||
|
|
d618175074 | ||
|
|
9ebe2c4395 | ||
|
|
e5189a5c1c | ||
|
|
f96592b4dc | ||
|
|
a11a281bf7 | ||
|
|
8ddab7464c | ||
|
|
9076fb3e4a | ||
|
|
d8079a4232 | ||
|
|
c992a8274c | ||
|
|
b5e059a0a9 | ||
|
|
0be3e2b103 | ||
|
|
ae138c1a15 | ||
|
|
0f8de50d26 | ||
|
|
ff7b6010bd | ||
|
|
270cdd017d | ||
|
|
f4cae6350b | ||
|
|
f0126a43f3 | ||
|
|
b5deb65815 | ||
|
|
6d9bbe0376 | ||
|
|
da634c211e | ||
|
|
61d96a5fd5 | ||
|
|
07e46b9399 | ||
|
|
3139111d36 | ||
|
|
205f88ec5a | ||
|
|
c8d6cdf6c8 | ||
|
|
7022243a95 | ||
|
|
b2ae72249d | ||
|
|
8ee6d179d5 | ||
|
|
bebcfa3fd7 | ||
|
|
d0130f9975 | ||
|
|
efd2db70ca | ||
|
|
befffa7e85 | ||
|
|
0368b4d671 | ||
|
|
acccd760d1 | ||
|
|
7696dbc347 | ||
|
|
e25ceebeec | ||
|
|
c7ee6280d2 | ||
|
|
796a2217aa | ||
|
|
e9bf1ada51 | ||
|
|
667b9fba67 | ||
|
|
bbf55e8476 | ||
|
|
11b48a9690 | ||
|
|
3b4554f4cf | ||
|
|
d5dd5e4560 | ||
|
|
46ea1f577c | ||
|
|
be06547cc4 | ||
|
|
bd631f5968 | ||
|
|
bc69a35cd6 | ||
|
|
75e7f64311 | ||
|
|
cdcb4cdbfb | ||
|
|
c31ef2ebc7 | ||
|
|
d49a419284 | ||
|
|
0913554af9 | ||
|
|
9af0003c63 | ||
|
|
3ecc16dc87 | ||
|
|
ef387c939a | ||
|
|
76e3608baf | ||
|
|
68384121cd | ||
|
|
2ed0418bd9 | ||
|
|
5eb4064390 | ||
|
|
3f943feb4a | ||
|
|
861b32367e | ||
|
|
cfca0aea4a | ||
|
|
43ae5915a6 | ||
|
|
7c22bcf827 | ||
|
|
1bb9b261dc | ||
|
|
a95adcdf41 | ||
|
|
6758d13335 | ||
|
|
10ab4df287 | ||
|
|
f3e4a7a9c8 | ||
|
|
854503aec2 | ||
|
|
353c3cdd34 | ||
|
|
8f7ab33508 | ||
|
|
383b534753 | ||
|
|
6691f56d0e | ||
|
|
50d4b6250c | ||
|
|
daa840564c | ||
|
|
2cdf77272c | ||
|
|
53299a19c2 | ||
|
|
e90b270b32 | ||
|
|
24ce8c5831 | ||
|
|
57bd074d00 | ||
|
|
843cdf05f5 | ||
|
|
ede8f7ece9 | ||
|
|
e5b736243d | ||
|
|
1d8a9c11c8 | ||
|
|
72d05bb969 | ||
|
|
2a5fc8cc4a | ||
|
|
aa9bd8c814 | ||
|
|
f279e634e4 | ||
|
|
3f7c8c204b | ||
|
|
375314cbbd | ||
|
|
62d0d25395 | ||
|
|
3047af4df6 | ||
|
|
6682b52a19 | ||
|
|
fee4151f83 | ||
|
|
25f2eb012e | ||
|
|
6976b45789 | ||
|
|
c69962675b |
@@ -3,7 +3,7 @@
|
||||
"image": "mcr.microsoft.com/devcontainers/universal:2",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "16"
|
||||
"version": "20"
|
||||
}
|
||||
},
|
||||
"hostRequirements": {
|
||||
|
||||
@@ -17,3 +17,8 @@ react/features/face-landmarks/resources/*
|
||||
|
||||
# Not worth it.
|
||||
actionTypes.ts
|
||||
|
||||
# It's not complete until all files are copied at build time.
|
||||
react-native-sdk/
|
||||
|
||||
*.d.ts
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
module.exports = {
|
||||
'extends': [
|
||||
extends: [
|
||||
'@jitsi/eslint-config'
|
||||
],
|
||||
'ignorePatterns': [ '*.d.ts' ]
|
||||
]
|
||||
};
|
||||
|
||||
48
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
48
.github/ISSUE_TEMPLATE/1-bug-report.md
vendored
@@ -1,48 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
This issue tracker is only for reporting bugs and tracking issues related to the source code.
|
||||
|
||||
Before posting, please make sure to check if the same or similar bugs have already been discussed: https://github.com/jitsi/jitsi-meet/issues
|
||||
|
||||
General questions regarding usage, installation, etc. should be posted at https://community.jitsi.org. They will be closed if posted here.
|
||||
|
||||
-->
|
||||
|
||||
### Description:
|
||||
|
||||
<!-- Please describe the bug clearly and concisely. -->
|
||||
|
||||
### Steps to reproduce:
|
||||
|
||||
1. <!-- Open '...' -->
|
||||
2. <!-- Click on '...' -->
|
||||
3. <!-- and so on... -->
|
||||
|
||||
### Expected behavior:
|
||||
|
||||
<!-- Please describe what should happen. -->
|
||||
|
||||
### Actual behavior:
|
||||
|
||||
<!-- Please describe what actually happens. -->
|
||||
<!-- Please attach screenshot if possible. -->
|
||||
|
||||
### Server information:
|
||||
|
||||
- Jitsi Meet version:
|
||||
- Operating System:
|
||||
|
||||
### Client information:
|
||||
|
||||
- Browser / app version:
|
||||
- Operating System:
|
||||
|
||||
### Additional information:
|
||||
|
||||
<!-- Please provide additional information about the bug, if any. -->
|
||||
53
.github/ISSUE_TEMPLATE/1-bug.yml
vendored
Normal file
53
.github/ISSUE_TEMPLATE/1-bug.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
name: Bug report
|
||||
description: File a bug report and help us improve
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
This issue tracker is only for reporting bugs and tracking issues related to the source code.
|
||||
|
||||
**Before posting, please make sure to check if the same or similar bugs have already been reported.**
|
||||
|
||||
⚠️ General questions regarding usage, installation, etc. should be posted in our [community forum](https://community.jitsi.org).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Please describe the problem. Be as detailed as possible.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Platform
|
||||
description: On what platforms can you reproduce the problem?
|
||||
options:
|
||||
- label: Chrome (or Chromium based)
|
||||
- label: Firefox
|
||||
- label: Safari
|
||||
- label: Other desktop browser
|
||||
- label: Android browser
|
||||
- label: iOS browser
|
||||
- label: Electron app
|
||||
- label: Android mobile app
|
||||
- label: iOS mobile app
|
||||
- label: Custom app using a mobile SDK
|
||||
- type: input
|
||||
attributes:
|
||||
label: Browser / app / sdk version
|
||||
description: Please provide the version of the browser / app / sdk where the problem manifests.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. The browser console JS logs (if applicable) is a good start. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Reproducibility
|
||||
description: Does the problem reproduce on meet.jit.si using Chrome, Firefox or the official mobile apps?
|
||||
options:
|
||||
- label: The problem is reproducible on meet.jit.si
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: More details?
|
||||
description: Please provide more details in case they apply (such as the Jitsi Meet version you are running, if you are hosting your own server).
|
||||
25
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
25
.github/ISSUE_TEMPLATE/2-feature-request.md
vendored
@@ -1,25 +0,0 @@
|
||||
---
|
||||
name: "Feature request"
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: 'feature-request'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!--
|
||||
Thank you for suggesting an idea to make Jitsi Meet better.
|
||||
|
||||
Please fill in as much of the template below as you're able.
|
||||
|
||||
Note that the ultimate decision for implementing features lies on the Jitsi team, not all feature requests shall be accepted.
|
||||
-->
|
||||
|
||||
**Is your feature request related to a problem you are facing?**
|
||||
Please describe the problem you are trying to solve.
|
||||
|
||||
**Describe the solution you'd like**
|
||||
Please describe the desired behavior.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
Please describe alternative solutions or features you have considered.
|
||||
|
||||
22
.github/ISSUE_TEMPLATE/2-feature.yml
vendored
Normal file
22
.github/ISSUE_TEMPLATE/2-feature.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: Feature request
|
||||
description: Suggest an idea for Jitsi Meet
|
||||
labels: ["feature-request"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for suggesting an idea to make Jitsi Meet better.
|
||||
|
||||
**Note**: the ultimate decision for implementing features lies on the Jitsi team, not all feature requests shall be accepted.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What problem are you trying to solve?
|
||||
description: Tell us what problem your feature request would solve.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What solution would you like to see?
|
||||
description: Please describe the desired behavior or feature.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Is there an alternative?
|
||||
description: Please describe alternative solutions or features you have considered.
|
||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Need help with Jitsi Meet?
|
||||
- name: Need help with your Jitsi Meet installation?
|
||||
url: https://community.jitsi.org
|
||||
about: Please ask it in our community.
|
||||
about: Please ask it in our community forum.
|
||||
|
||||
145
.github/workflows/ci.yml
vendored
145
.github/workflows/ci.yml
vendored
@@ -10,11 +10,15 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Check Node / npm versions
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v41
|
||||
uses: jitsi/changed-files@main
|
||||
- name: Get changed lang files
|
||||
id: lang-files
|
||||
run: echo "all=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | grep -oE 'lang\/\S+' | tr '\n' ' ')" >> "$GITHUB_OUTPUT"
|
||||
@@ -30,66 +34,137 @@ jobs:
|
||||
- name: Check if the git repository is clean
|
||||
run: $(exit $(git status --porcelain --untracked-files=no | head -255 | wc -l)) || (echo "Dirty git tree"; git diff; exit 1)
|
||||
- run: npm run lint:ci && npm run tsc:ci
|
||||
linux-build:
|
||||
name: Build Frontend (Linux)
|
||||
runs-on: ubuntu-latest
|
||||
frontend:
|
||||
name: Build Frontend
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Check Node / npm versions
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- run: npm install
|
||||
- run: make
|
||||
macos-ci:
|
||||
name: Build Frontend (macOS)
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
cache: 'npm'
|
||||
- run: npm install
|
||||
- run: make
|
||||
android-build:
|
||||
- name: Check config.js syntax
|
||||
run: node config.js
|
||||
android-rn-bundle-build:
|
||||
name: Build mobile bundle (Android)
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Check Node / npm versions
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- run: npm install
|
||||
- run: npx react-native bundle --entry-file react/index.native.js --platform android --bundle-output /tmp/android.bundle --reset-cache
|
||||
ios-build:
|
||||
ios-rn-bundle-build:
|
||||
name: Build mobile bundle (iOS)
|
||||
runs-on: macOS-13
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Check Node / npm versions
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- run: npm install
|
||||
- name: setup Xcode
|
||||
run: |
|
||||
uname -a
|
||||
xcode-select -p
|
||||
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
|
||||
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
|
||||
xcodebuild -version
|
||||
- name: setup-cocoapods
|
||||
uses: maxim-lobanov/setup-cocoapods@v1
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
podfile-path: ios/Podfile.lock
|
||||
ruby-version: '3.4'
|
||||
bundler-cache: true
|
||||
- run: npx react-native info
|
||||
- name: Install Pods
|
||||
run: |
|
||||
pod --version
|
||||
cd ios
|
||||
pod install --repo-update
|
||||
- name: Check if the git repository is clean
|
||||
run: $(exit $(git status --porcelain --untracked-files=no | head -255 | wc -l)) || (echo "Dirty git tree"; git diff; exit 1)
|
||||
working-directory: ./ios
|
||||
run: bundle exec pod install --repo-update --deployment
|
||||
- run: npx react-native bundle --entry-file react/index.native.js --platform ios --bundle-output /tmp/ios.bundle --reset-cache
|
||||
android-sdk-build:
|
||||
name: Build mobile SDK (Android)
|
||||
runs-on: ubuntu-latest
|
||||
container: reactnativecommunity/react-native-android:v13.0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Check Node / npm versions
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- run: npm install
|
||||
- run: |
|
||||
cd android
|
||||
./gradlew :sdk:clean
|
||||
./gradlew :sdk:assembleRelease
|
||||
ios-sdk-build:
|
||||
name: Build mobile SDK (iOS)
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Check Node / npm versions
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- run: npm install
|
||||
- name: setup Xcode
|
||||
run: |
|
||||
uname -a
|
||||
xcode-select -p
|
||||
sudo xcode-select -s /Applications/Xcode_16.2.app/Contents/Developer
|
||||
xcodebuild -version
|
||||
- name: setup-cocoapods
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.4'
|
||||
bundler-cache: true
|
||||
- run: npx react-native info
|
||||
- name: Install Pods
|
||||
working-directory: ./ios
|
||||
run: bundle exec pod install --repo-update --deployment
|
||||
- run: |
|
||||
xcodebuild clean \
|
||||
-workspace ios/jitsi-meet.xcworkspace \
|
||||
-scheme JitsiMeetSDK
|
||||
xcodebuild archive \
|
||||
-workspace ios/jitsi-meet.xcworkspace \
|
||||
-scheme JitsiMeetSDK \
|
||||
-configuration Release \
|
||||
-sdk iphoneos \
|
||||
-destination='generic/platform=iOS' \
|
||||
-archivePath ios/sdk/out/ios-device \
|
||||
SKIP_INSTALL=NO \
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
|
||||
xcodebuild -create-xcframework \
|
||||
-framework ios/sdk/out/ios-device.xcarchive/Products/Library/Frameworks/JitsiMeetSDK.framework \
|
||||
-output ios/sdk/out/JitsiMeetSDK.xcframework
|
||||
- run: ls -lR ios/sdk/out
|
||||
debian-build:
|
||||
name: Test Debian packages build
|
||||
runs-on: ubuntu-latest
|
||||
@@ -97,8 +172,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
- name: Check Node / npm versions
|
||||
run: |
|
||||
node -v
|
||||
npm -v
|
||||
- run: npm install
|
||||
- run: make
|
||||
- run: sudo apt-get install -y debhelper
|
||||
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -38,6 +38,7 @@ DerivedData
|
||||
*.dSYM.zip
|
||||
*.xcuserstate
|
||||
project.xcworkspace
|
||||
**/.xcode.env.local
|
||||
|
||||
# Android/IntelliJ
|
||||
#
|
||||
@@ -61,6 +62,7 @@ buck-out/
|
||||
|
||||
# fastlane
|
||||
#
|
||||
.bundle/
|
||||
**/fastlane/report.xml
|
||||
**/fastlane/Preview.html
|
||||
**/fastlane/test_output
|
||||
@@ -100,6 +102,9 @@ tsconfig.json
|
||||
react-native-sdk/*.tgz
|
||||
react-native-sdk/android/src
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JitsiMeetReactNativePackage.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JitsiMeetOngoingConferenceService.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/JMOngoingConferenceModule.java
|
||||
!react-native-sdk/android/src/main/java/org/jitsi/meet/sdk/RNOngoingNotification.java
|
||||
react-native-sdk/images
|
||||
react-native-sdk/ios
|
||||
react-native-sdk/lang
|
||||
@@ -108,3 +113,8 @@ react-native-sdk/node_modules
|
||||
react-native-sdk/react
|
||||
react-native-sdk/service
|
||||
react-native-sdk/sounds
|
||||
|
||||
# tests
|
||||
tests/.env
|
||||
test-results
|
||||
|
||||
|
||||
173
CONTRIBUTING.md
173
CONTRIBUTING.md
@@ -1,171 +1,20 @@
|
||||
# How to contribute
|
||||
We would love to have your help. Before you start working however, please read
|
||||
and follow this short guide.
|
||||
# Follow Our Updated Guide to See How You Can Contribute
|
||||
|
||||
# Reporting Issues
|
||||
Provide as much information as possible. Mention the version of Jitsi Meet,
|
||||
Jicofo and JVB you are using, and explain (as detailed as you can) how the
|
||||
problem can be reproduced.
|
||||
**Hello there! 👋**
|
||||
|
||||
# Code contributions
|
||||
Found a bug and know how to fix it? Great! Please read on.
|
||||
We're thrilled that you're eager to contribute to **Jitsi Meet! ❤️**
|
||||
|
||||
## Contributor License Agreement
|
||||
While the Jitsi projects are released under the
|
||||
[Apache License 2.0](https://github.com/jitsi/jitsi-meet/blob/master/LICENSE), the copyright
|
||||
holder and principal creator is [8x8](https://www.8x8.com/). To
|
||||
ensure that we can continue making these projects available under an Open Source license,
|
||||
we need you to sign our Apache-based contributor
|
||||
license agreement as either a [corporation](https://jitsi.org/ccla) or an
|
||||
[individual](https://jitsi.org/icla). If you cannot accept the terms laid out
|
||||
in the agreement, unfortunately, we cannot accept your contribution.
|
||||
Your interest in improving our platform means a lot to us. To ensure your contributions align seamlessly with our goals and processes, we've recently updated our guide. This guide will provide you with clear instructions on how to get involved effectively.
|
||||
|
||||
## Creating Pull Requests
|
||||
- Make sure your code passes the linter rules beforehand. The linter is executed
|
||||
automatically when committing code.
|
||||
- Perform **one** logical change per pull request.
|
||||
- Maintain a clean list of commits, squash them if necessary.
|
||||
- Rebase your topic branch on top of the master branch before creating the pull
|
||||
request.
|
||||
### 📖 Get Started
|
||||
|
||||
## Coding style
|
||||
Ready to get started? Head over to our [Jitsi Meet Handbook](https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-contributing/) and let's make **Jitsi Meet** even better together!
|
||||
|
||||
### Comments
|
||||
### 💬 Join the Discussion
|
||||
|
||||
* Comments documenting the source code are required.
|
||||
Have questions or need help? Join our community discussions on the [Jitsi Forum](https://community.jitsi.org/) where contributors and maintainers can assist you.
|
||||
|
||||
* Comments from which documentation is automatically generated are **not**
|
||||
subject to case-by-case decisions. Such comments are used, for example, on
|
||||
types and their members. Examples of tools which automatically generate
|
||||
documentation from such comments include JSDoc, Javadoc, Doxygen.
|
||||
### ❗️Additional Note
|
||||
Before sending us your code, double-check that it meets our coding standards. You can do this by running a command: `npm run lint`. If there are any issues, don't worry! You can fix them by running: `npm run lint-fix`. Once your code passes these checks, feel free to submit your pull request.
|
||||
|
||||
* Comments which are not automatically processed are strongly encouraged. They
|
||||
are subject to case-by-case decisions. Such comments are often observed in
|
||||
function bodies.
|
||||
|
||||
* Comments should be formatted as proper English sentences. Such formatting pays
|
||||
attention to, for example, capitalization and punctuation.
|
||||
|
||||
### Duplication
|
||||
|
||||
* Don't copy-paste source code. Reuse it.
|
||||
|
||||
### Formatting
|
||||
|
||||
* Line length is limited to 120 characters.
|
||||
|
||||
* Sort by alphabetical order in order to make the addition of new entities as
|
||||
easy as looking a word up in a dictionary. Otherwise, one risks duplicate
|
||||
entries (with conflicting values in the cases of key-value pairs). For
|
||||
example:
|
||||
|
||||
* Within an `import` of multiple names from a module, sort the names in
|
||||
alphabetical order. (Of course, the default name stays first as required by
|
||||
the `import` syntax.)
|
||||
|
||||
````javascript
|
||||
import {
|
||||
DOMINANT_SPEAKER_CHANGED,
|
||||
JITSI_CLIENT_CONNECTED,
|
||||
JITSI_CLIENT_CREATED,
|
||||
JITSI_CLIENT_DISCONNECTED,
|
||||
JITSI_CLIENT_ERROR,
|
||||
JITSI_CONFERENCE_JOINED,
|
||||
MODERATOR_CHANGED,
|
||||
PEER_JOINED,
|
||||
PEER_LEFT,
|
||||
RTC_ERROR
|
||||
} from './actionTypes';
|
||||
````
|
||||
|
||||
* Within a group of imports (e.g. groups of imports delimited by an empty line
|
||||
may be: third-party modules, then project modules, and eventually the
|
||||
private files of a module), sort the module names in alphabetical order.
|
||||
|
||||
````javascript
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
````
|
||||
|
||||
### Indentation
|
||||
|
||||
* Align `switch` and `case`/`default`. Don't indent the `case`/`default` more
|
||||
than its `switch`.
|
||||
|
||||
````javascript
|
||||
switch (i) {
|
||||
case 0:
|
||||
...
|
||||
break;
|
||||
default:
|
||||
...
|
||||
}
|
||||
````
|
||||
|
||||
### Naming
|
||||
|
||||
* An abstraction should have one name within the project and across multiple
|
||||
projects. For example:
|
||||
|
||||
* The instance of lib-jitsi-meet's `JitsiConnection` type should be named
|
||||
`connection` or `jitsiConnection` in jitsi-meet, not `client`.
|
||||
|
||||
* The class `ReducerRegistry` should be defined in ReducerRegistry.js and its
|
||||
imports in other files should use the same name. Don't define the class
|
||||
`Registry` in ReducerRegistry.js and then import it as `Reducers` in other
|
||||
files.
|
||||
|
||||
* The names of global constants (including ES6 module-global constants) should
|
||||
be written in uppercase with underscores to separate words. For example,
|
||||
`BACKGROUND_COLOR`.
|
||||
|
||||
* The underscore character at the beginning of a name signals that the
|
||||
respective variable, function, property is non-public i.e. private, protected,
|
||||
or internal. In contrast, the lack of an underscore at the beginning of a name
|
||||
signals public API.
|
||||
|
||||
### Feature layout
|
||||
|
||||
When adding a new feature, this would be the usual layout.
|
||||
|
||||
```
|
||||
react/features/sample/
|
||||
├── actionTypes.ts
|
||||
├── actions.js
|
||||
├── components
|
||||
│ ├── AnotherComponent.js
|
||||
│ ├── OneComponent.js
|
||||
│ └── index.js
|
||||
├── middleware.js
|
||||
└── reducer.js
|
||||
```
|
||||
|
||||
The middleware must be imported in `react/features/app/` specifically
|
||||
in `middlewares.any.ts`, `middlewares.native.ts` or `middlewares.web.ts` where appropriate.
|
||||
Likewise for the reducer.
|
||||
|
||||
An `index.js` file must not be provided for exporting actions, action types and
|
||||
component. Features / files requiring those must import them explicitly.
|
||||
|
||||
This has not always been the case and the entire codebase hasn't been migrated to
|
||||
this model but new features should follow this new layout.
|
||||
|
||||
When working on an old feature, adding the necessary changes to migrate to the new
|
||||
model is encouraged.
|
||||
|
||||
|
||||
### Avoiding bundle bloat
|
||||
|
||||
When adding a new feature it's possible that it triggers a build failure due to the increased bundle size. We have safeguards inplace to avoid bundles growing disproportionatelly. While there are legit reasons for increasing the limits, please analyze the bundle first to make sure no unintended dependencies have been included, causing the increase in size.
|
||||
|
||||
First, make a production build with bundle-analysis enabled:
|
||||
|
||||
```
|
||||
npx webpack -p --analyze-bundle
|
||||
```
|
||||
|
||||
Then open the interactive bundle analyzer tool:
|
||||
|
||||
```
|
||||
npx webpack-bundle-analyzer build/app-stats.json
|
||||
```
|
||||
**Happy coding!**
|
||||
|
||||
16
Gemfile
Normal file
16
Gemfile
Normal file
@@ -0,0 +1,16 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
ruby ">= 3.4.0"
|
||||
|
||||
gem "cocoapods", "~> 1.16"
|
||||
|
||||
# (Optional) Fastlane for automation
|
||||
gem "fastlane"
|
||||
gem "abbrev"
|
||||
gem "logger"
|
||||
gem "mutex_m"
|
||||
gem "csv"
|
||||
gem "bigdecimal"
|
||||
|
||||
# (Optional) Bundler itself to ensure consistency
|
||||
gem "bundler"
|
||||
331
Gemfile.lock
Normal file
331
Gemfile.lock
Normal file
@@ -0,0 +1,331 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.7)
|
||||
base64
|
||||
nkf
|
||||
rexml
|
||||
abbrev (0.1.2)
|
||||
activesupport (7.2.2.1)
|
||||
base64
|
||||
benchmark (>= 0.3)
|
||||
bigdecimal
|
||||
concurrent-ruby (~> 1.0, >= 1.3.1)
|
||||
connection_pool (>= 2.2.5)
|
||||
drb
|
||||
i18n (>= 1.6, < 2)
|
||||
logger (>= 1.4.2)
|
||||
minitest (>= 5.1)
|
||||
securerandom (>= 0.3)
|
||||
tzinfo (~> 2.0, >= 2.0.5)
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
algoliasearch (1.27.5)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.1)
|
||||
aws-partitions (1.1050.0)
|
||||
aws-sdk-core (3.218.1)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
base64
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.98.0)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.181.0)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.11.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
base64 (0.2.0)
|
||||
benchmark (0.4.0)
|
||||
bigdecimal (3.1.9)
|
||||
claide (1.1.0)
|
||||
cocoapods (1.16.2)
|
||||
addressable (~> 2.8)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.16.2)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 2.1, < 3.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.6.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (>= 2.3.0, < 3.0)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.8.0)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (>= 2.3.0, < 3.0)
|
||||
xcodeproj (>= 1.27.0, < 2.0)
|
||||
cocoapods-core (1.16.2)
|
||||
activesupport (>= 5.0, < 8)
|
||||
addressable (~> 2.8)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
netrc (~> 0.11)
|
||||
public_suffix (~> 4.0)
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.5)
|
||||
cocoapods-downloader (2.1)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.1)
|
||||
cocoapods-trunk (1.6.0)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.2.0)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.0)
|
||||
csv (3.3.2)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.7.0)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.6.20240107)
|
||||
dotenv (2.8.1)
|
||||
drb (2.2.1)
|
||||
emoji_regex (3.2.3)
|
||||
escape (0.0.4)
|
||||
ethon (0.16.0)
|
||||
ffi (>= 1.15.0)
|
||||
excon (0.112.0)
|
||||
faraday (1.10.4)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
faraday-excon (~> 1.1)
|
||||
faraday-httpclient (~> 1.0)
|
||||
faraday-multipart (~> 1.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
faraday-net_http_persistent (~> 1.0)
|
||||
faraday-patron (~> 1.0)
|
||||
faraday-rack (~> 1.0)
|
||||
faraday-retry (~> 1.0)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-cookie_jar (0.0.7)
|
||||
faraday (>= 0.8.0)
|
||||
http-cookie (~> 1.0.0)
|
||||
faraday-em_http (1.0.0)
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.1.0)
|
||||
multipart-post (~> 2.0)
|
||||
faraday-net_http (1.0.2)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
faraday-rack (1.0.0)
|
||||
faraday-retry (1.0.3)
|
||||
faraday_middleware (1.2.1)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.4.0)
|
||||
fastlane (2.226.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
aws-sdk-s3 (~> 1.0)
|
||||
babosa (>= 1.0.3, < 2.0.0)
|
||||
bundler (>= 1.12.0, < 3.0.0)
|
||||
colored (~> 1.2)
|
||||
commander (~> 4.6)
|
||||
dotenv (>= 2.1.1, < 3.0.0)
|
||||
emoji_regex (>= 0.1, < 4.0)
|
||||
excon (>= 0.71.0, < 1.0.0)
|
||||
faraday (~> 1.0)
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (~> 1.0)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
fastlane-sirp (>= 1.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
google-cloud-env (>= 1.6.0, < 2.0.0)
|
||||
google-cloud-storage (~> 1.31)
|
||||
highline (~> 2.0)
|
||||
http-cookie (~> 1.0.5)
|
||||
json (< 3.0.0)
|
||||
jwt (>= 2.1.0, < 3)
|
||||
mini_magick (>= 4.9.4, < 5.0.0)
|
||||
multipart-post (>= 2.0.0, < 3.0.0)
|
||||
naturally (~> 2.2)
|
||||
optparse (>= 0.1.1, < 1.0.0)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 2.0.0, < 3.0.0)
|
||||
security (= 0.1.5)
|
||||
simctl (~> 1.6.3)
|
||||
terminal-notifier (>= 2.0.0, < 3.0.0)
|
||||
terminal-table (~> 3)
|
||||
tty-screen (>= 0.6.3, < 1.0.0)
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.4.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
|
||||
fastlane-sirp (1.0.0)
|
||||
sysrandom (~> 1.0)
|
||||
ffi (1.17.1)
|
||||
ffi (1.17.1-aarch64-linux-gnu)
|
||||
ffi (1.17.1-aarch64-linux-musl)
|
||||
ffi (1.17.1-arm-linux-gnu)
|
||||
ffi (1.17.1-arm-linux-musl)
|
||||
ffi (1.17.1-arm64-darwin)
|
||||
ffi (1.17.1-x86-linux-gnu)
|
||||
ffi (1.17.1-x86-linux-musl)
|
||||
ffi (1.17.1-x86_64-darwin)
|
||||
ffi (1.17.1-x86_64-linux-gnu)
|
||||
ffi (1.17.1-x86_64-linux-musl)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.54.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-core (0.11.3)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
httpclient (>= 2.8.1, < 3.a)
|
||||
mini_mime (~> 1.0)
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
google-apis-iamcredentials_v1 (0.17.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.13.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-storage_v1 (0.31.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-cloud-core (1.7.1)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-errors (1.4.0)
|
||||
google-cloud-storage (1.47.0)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.31.0)
|
||||
google-cloud-core (~> 1.6)
|
||||
googleauth (>= 0.16.2, < 2.a)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (1.8.1)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.8)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jmespath (1.6.2)
|
||||
json (2.10.1)
|
||||
jwt (2.10.1)
|
||||
base64
|
||||
logger (1.6.6)
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
minitest (5.25.4)
|
||||
molinillo (0.8.0)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
mutex_m (0.3.0)
|
||||
nanaimo (0.4.0)
|
||||
nap (1.1.0)
|
||||
naturally (2.2.1)
|
||||
netrc (0.11.0)
|
||||
nkf (0.2.0)
|
||||
optparse (0.6.0)
|
||||
os (1.1.4)
|
||||
plist (3.7.2)
|
||||
public_suffix (4.0.7)
|
||||
rake (13.2.1)
|
||||
representable (3.2.0)
|
||||
declarative (< 0.1.0)
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.2)
|
||||
rexml (3.4.1)
|
||||
rouge (3.28.0)
|
||||
ruby-macho (2.5.1)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.4.1)
|
||||
securerandom (0.4.1)
|
||||
security (0.1.5)
|
||||
signet (0.19.0)
|
||||
addressable (~> 2.8)
|
||||
faraday (>= 0.17.5, < 3.a)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simctl (1.6.10)
|
||||
CFPropertyList
|
||||
naturally
|
||||
sysrandom (1.0.5)
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
trailblazer-option (0.1.2)
|
||||
tty-cursor (0.7.1)
|
||||
tty-screen (0.8.2)
|
||||
tty-spinner (0.9.3)
|
||||
tty-cursor (~> 0.7)
|
||||
typhoeus (1.4.1)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
uber (0.1.0)
|
||||
unicode-display_width (2.6.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.27.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.4.0)
|
||||
rexml (>= 3.3.6, < 4.0)
|
||||
xcpretty (0.4.0)
|
||||
rouge (~> 3.28.0)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
aarch64-linux-gnu
|
||||
aarch64-linux-musl
|
||||
arm-linux-gnu
|
||||
arm-linux-musl
|
||||
arm64-darwin
|
||||
ruby
|
||||
x86-linux-gnu
|
||||
x86-linux-musl
|
||||
x86_64-darwin
|
||||
x86_64-linux-gnu
|
||||
x86_64-linux-musl
|
||||
|
||||
DEPENDENCIES
|
||||
abbrev
|
||||
bigdecimal
|
||||
bundler
|
||||
cocoapods (~> 1.16)
|
||||
csv
|
||||
fastlane
|
||||
logger
|
||||
mutex_m
|
||||
|
||||
RUBY VERSION
|
||||
ruby 3.4.2p28
|
||||
|
||||
BUNDLED WITH
|
||||
2.6.3
|
||||
16
Makefile
16
Makefile
@@ -17,16 +17,16 @@ STYLES_BUNDLE = css/all.bundle.css
|
||||
STYLES_DESTINATION = css/all.css
|
||||
STYLES_MAIN = css/main.scss
|
||||
ifeq ($(OS),Windows_NT)
|
||||
WEBPACK = .\node_modules\.bin\webpack
|
||||
WEBPACK_DEV_SERVER = .\node_modules\.bin\webpack serve --mode development
|
||||
WEBPACK = .\node_modules\.bin\webpack --progress
|
||||
WEBPACK_DEV_SERVER = .\node_modules\.bin\webpack serve --mode development --progress
|
||||
else
|
||||
WEBPACK = ./node_modules/.bin/webpack
|
||||
WEBPACK_DEV_SERVER = ./node_modules/.bin/webpack serve --mode development
|
||||
WEBPACK = ./node_modules/.bin/webpack --progress
|
||||
WEBPACK_DEV_SERVER = ./node_modules/.bin/webpack serve --mode development --progress
|
||||
endif
|
||||
|
||||
all: compile deploy clean
|
||||
all: compile deploy
|
||||
|
||||
compile:
|
||||
compile: clean
|
||||
NODE_OPTIONS=--max-old-space-size=8192 \
|
||||
$(WEBPACK)
|
||||
|
||||
@@ -48,8 +48,6 @@ deploy-appbundle:
|
||||
$(BUILD_DIR)/external_api.min.js.map \
|
||||
$(BUILD_DIR)/alwaysontop.min.js \
|
||||
$(BUILD_DIR)/alwaysontop.min.js.map \
|
||||
$(BUILD_DIR)/analytics-ga.min.js \
|
||||
$(BUILD_DIR)/analytics-ga.min.js.map \
|
||||
$(BUILD_DIR)/face-landmarks-worker.min.js \
|
||||
$(BUILD_DIR)/face-landmarks-worker.min.js.map \
|
||||
$(BUILD_DIR)/noise-suppressor-worklet.min.js \
|
||||
@@ -122,7 +120,7 @@ deploy-local:
|
||||
dev: deploy-init deploy-css deploy-rnnoise-binary deploy-tflite deploy-meet-models deploy-lib-jitsi-meet deploy-olm deploy-tf-wasm deploy-excalidraw-dev deploy-face-landmarks
|
||||
$(WEBPACK_DEV_SERVER)
|
||||
|
||||
source-package:
|
||||
source-package: compile deploy
|
||||
mkdir -p source_package/jitsi-meet/css && \
|
||||
cp -r *.js *.html resources/*.txt fonts images libs static sounds LICENSE lang source_package/jitsi-meet && \
|
||||
cp css/all.css source_package/jitsi-meet/css && \
|
||||
|
||||
@@ -34,7 +34,7 @@ mobile apps:
|
||||
|
||||
| Android | Android (F-Droid) | iOS |
|
||||
|:-:|:-:|:-:|
|
||||
| [<img src="resources/img/google-play-badge.png" height="50">](https://play.google.com/store/apps/details?id=org.jitsi.meet) | [<img src="resources/img/f-droid-badge.png" height="50">](https://f-droid.org/en/packages/org.jitsi.meet/) | [<img src="resources/img/appstore-badge.png" height="50">](https://itunes.apple.com/us/app/jitsi-meet/id1165103905) |
|
||||
| [<img src="resources/img/google-play-badge.png" height="50">](https://play.google.com/store/apps/details?id=org.jitsi.meet) | [<img src="resources/img/f-droid-badge.png" height="50">](https://f-droid.org/packages/org.jitsi.meet/) | [<img src="resources/img/appstore-badge.png" height="50">](https://itunes.apple.com/us/app/jitsi-meet/id1165103905) |
|
||||
|
||||
If you are feeling adventurous and want to get an early scoop of the features as they are being
|
||||
developed you can also sign up for our open beta testing here:
|
||||
|
||||
@@ -4,6 +4,6 @@
|
||||
|
||||
We take security very seriously and develop all Jitsi projects to be secure and safe.
|
||||
|
||||
If you find (or simply suspect) a security issue in any of the Jitsi projects, please report it to us via [HackerOne](https://hackerone.com/8x8) or send us an email to security@jitsi.org.
|
||||
If you find (or simply suspect) a security issue in any of the Jitsi projects, please report it to us via [HackerOne](https://hackerone.com/8x8-bounty) or send us an email to security@jitsi.org.
|
||||
|
||||
**We encourage responsible disclosure for the sake of our users, so please reach out before posting in a public space.**
|
||||
|
||||
@@ -15,12 +15,6 @@ def vcode = (int) (((new Date().getTime() / 1000) - 1546297200) / 10)
|
||||
android {
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
buildToolsVersion rootProject.ext.buildToolsVersion
|
||||
packagingOptions {
|
||||
jniLibs {
|
||||
excludes += ['lib/*/libhermes*.so']
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'org.jitsi.meet'
|
||||
@@ -48,6 +42,7 @@ android {
|
||||
debug {
|
||||
buildConfigField "boolean", "GOOGLE_SERVICES_ENABLED", "${googleServicesEnabled}"
|
||||
buildConfigField "boolean", "LIBRE_BUILD", "${rootProject.ext.libreBuild}"
|
||||
applicationIdSuffix ".debug"
|
||||
}
|
||||
release {
|
||||
// Uncomment the following line for singing a test release build.
|
||||
|
||||
@@ -30,14 +30,16 @@ import android.view.KeyEvent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.oney.WebRTCModule.WebRTCModuleOptions;
|
||||
|
||||
import org.jitsi.meet.sdk.JitsiMeet;
|
||||
import org.jitsi.meet.sdk.JitsiMeetActivity;
|
||||
import org.jitsi.meet.sdk.JitsiMeetConferenceOptions;
|
||||
import org.webrtc.Logging;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* The one and only Activity that the Jitsi Meet app needs. The
|
||||
@@ -74,13 +76,16 @@ public class MainActivity extends JitsiMeetActivity {
|
||||
*/
|
||||
private String defaultURL;
|
||||
|
||||
|
||||
// JitsiMeetActivity overrides
|
||||
//
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
JitsiMeet.showSplashScreen(this);
|
||||
|
||||
WebRTCModuleOptions options = WebRTCModuleOptions.getInstance();
|
||||
options.loggingSeverity = Logging.Severity.LS_ERROR;
|
||||
|
||||
super.onCreate(null);
|
||||
}
|
||||
|
||||
@@ -146,12 +151,12 @@ public class MainActivity extends JitsiMeetActivity {
|
||||
}
|
||||
|
||||
private void setJitsiMeetConferenceDefaultOptions() {
|
||||
|
||||
// Set default options
|
||||
JitsiMeetConferenceOptions defaultOptions
|
||||
= new JitsiMeetConferenceOptions.Builder()
|
||||
.setServerURL(buildURL(defaultURL))
|
||||
.setFeatureFlag("welcomepage.enabled", true)
|
||||
.setFeatureFlag("resolution", 360)
|
||||
.setFeatureFlag("server-url-change.enabled", !configurationByRestrictions)
|
||||
.build();
|
||||
JitsiMeet.setDefaultConferenceOptions(defaultOptions);
|
||||
@@ -213,11 +218,6 @@ public class MainActivity extends JitsiMeetActivity {
|
||||
super.onPictureInPictureModeChanged(isInPictureInPictureMode);
|
||||
|
||||
Log.d(TAG, "Is in picture-in-picture mode: " + isInPictureInPictureMode);
|
||||
|
||||
if (!isInPictureInPictureMode) {
|
||||
this.startActivity(new Intent(this, getClass())
|
||||
.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
@@ -17,15 +17,13 @@ buildscript {
|
||||
}
|
||||
|
||||
ext {
|
||||
kotlinVersion = "1.7.0"
|
||||
buildToolsVersion = "33.0.2"
|
||||
kotlinVersion = "1.9.24"
|
||||
buildToolsVersion = "34.0.0"
|
||||
compileSdkVersion = 34
|
||||
minSdkVersion = 24
|
||||
minSdkVersion = 26
|
||||
targetSdkVersion = 34
|
||||
supportLibVersion = "28.0.0"
|
||||
|
||||
// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
|
||||
ndkVersion = "23.1.7779620"
|
||||
ndkVersion = "26.1.10909125"
|
||||
|
||||
// The Maven artifact groupId of the third-party react-native modules which
|
||||
// Jitsi Meet SDK for Android depends on and which are not available in
|
||||
@@ -43,14 +41,12 @@ ext {
|
||||
|
||||
googleServicesEnabled = project.file('app/google-services.json').exists() && !libreBuild
|
||||
|
||||
//React Native Version
|
||||
rnVersion = "0.72.9"
|
||||
//React Native and Hermes Version
|
||||
rnVersion = "0.75.5"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
// Android JSC is installed from npm.
|
||||
maven { url("$rootDir/../node_modules/jsc-android/dist") }
|
||||
mavenCentral()
|
||||
google()
|
||||
maven { url 'https://www.jitpack.io' }
|
||||
@@ -73,10 +69,29 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
// Due to a dependency conflict between React Native and the Fresco library used by GiphySDK,
|
||||
// GIFs appear as static images instead of animating
|
||||
// https://github.com/Giphy/giphy-react-native-sdk/commit/7fe466ed6fddfaec95f9cbc959d33bd75ad8f900
|
||||
|
||||
configurations.configureEach {
|
||||
resolutionStrategy {
|
||||
forcedModules = [
|
||||
'com.facebook.fresco:fresco:3.2.0',
|
||||
'com.facebook.fresco:animated-gif:3.2.0',
|
||||
'com.facebook.fresco:animated-base:3.2.0',
|
||||
'com.facebook.fresco:animated-drawable:3.2.0',
|
||||
'com.facebook.fresco:animated-webp:3.2.0',
|
||||
'com.facebook.fresco:webpsupport:3.2.0',
|
||||
'com.facebook.fresco:imagepipeline-okhttp3:3.2.0',
|
||||
'com.facebook.fresco:middleware:3.2.0',
|
||||
'com.facebook.fresco:nativeimagetranscoder:3.2.0'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Third-party react-native modules which Jitsi Meet SDK for Android depends
|
||||
// on and which are not available in third-party Maven repositories need to
|
||||
// be deployed in a Maven repository of ours.
|
||||
//
|
||||
|
||||
if (project.name.startsWith('react-native-')) {
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx1024m -XX:MaxPermSize=256m
|
||||
|
||||
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
org.gradle.jvmargs=-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
@@ -27,4 +27,4 @@ android.enableJetifier=true
|
||||
android.bundle.enableUncompressedNativeLibs=false
|
||||
|
||||
appVersion=99.0.0
|
||||
sdkVersion=99.0.0
|
||||
sdkVersion=0.0.0
|
||||
|
||||
@@ -9,8 +9,6 @@ THE_MVN_REPO=${MVN_REPO:-${1:-$DEFAULT_MVN_REPO}}
|
||||
MVN_HTTP=0
|
||||
DEFAULT_SDK_VERSION=$(grep sdkVersion ${THIS_DIR}/../gradle.properties | cut -d"=" -f2)
|
||||
SDK_VERSION=${OVERRIDE_SDK_VERSION:-${DEFAULT_SDK_VERSION}}
|
||||
JSC_VERSION="r"$(jq -r '.dependencies."jsc-android"' ${THIS_DIR}/../../node_modules/react-native/package.json | cut -d . -f 1 | cut -c 2-)
|
||||
DO_GIT_TAG=${GIT_TAG:-0}
|
||||
|
||||
if [[ $THE_MVN_REPO == http* ]]; then
|
||||
MVN_HTTP=1
|
||||
@@ -24,34 +22,7 @@ export MVN_REPO=$THE_MVN_REPO
|
||||
echo "Releasing Jitsi Meet SDK ${SDK_VERSION}"
|
||||
echo "Using ${MVN_REPO} as the Maven repo"
|
||||
|
||||
if [[ $MVN_HTTP == 1 ]]; then
|
||||
# Push JSC
|
||||
echo "Pushing JSC ${JSC_VERSION} to the Maven repo"
|
||||
pushd ${THIS_DIR}/../../node_modules/jsc-android/dist/org/webkit/android-jsc/${JSC_VERSION}
|
||||
mvn \
|
||||
deploy:deploy-file \
|
||||
-Durl=${MVN_REPO} \
|
||||
-DrepositoryId=${MVN_REPO_ID} \
|
||||
-Dfile=android-jsc-${JSC_VERSION}.aar \
|
||||
-Dpackaging=aar \
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=android-jsc-${JSC_VERSION}.pom || true
|
||||
popd
|
||||
else
|
||||
# Push JSC, if necessary
|
||||
if [[ ! -d ${MVN_REPO}/org/webkit/android-jsc/${JSC_VERSION} ]]; then
|
||||
echo "Pushing JSC ${JSC_VERSION} to the Maven repo"
|
||||
pushd ${THIS_DIR}/../../node_modules/jsc-android/dist/org/webkit/android-jsc/${JSC_VERSION}
|
||||
mvn \
|
||||
deploy:deploy-file \
|
||||
-Durl=${MVN_REPO} \
|
||||
-Dfile=android-jsc-${JSC_VERSION}.aar \
|
||||
-Dpackaging=aar \
|
||||
-DgeneratePom=false \
|
||||
-DpomFile=android-jsc-${JSC_VERSION}.pom
|
||||
popd
|
||||
fi
|
||||
|
||||
if [[ $MVN_HTTP == 0 ]]; then
|
||||
# Check if an SDK with that same version has already been released
|
||||
if [[ -d ${MVN_REPO}/org/jitsi/react/jitsi-meet-sdk/${SDK_VERSION} ]]; then
|
||||
echo "There is already a release with that version in the Maven repo!"
|
||||
@@ -67,15 +38,12 @@ pushd ${THIS_DIR}/../
|
||||
./gradlew publish
|
||||
popd
|
||||
|
||||
if [[ $DO_GIT_TAG == 1 ]]; then
|
||||
# The artifacts are now on the Maven repo, commit them
|
||||
# The artifacts are now on the Maven repo, commit them
|
||||
if [[ $MVN_HTTP == 0 ]]; then
|
||||
pushd ${MVN_REPO_PATH}
|
||||
git add -A .
|
||||
git commit -m "Jitsi Meet SDK + dependencies: ${SDK_VERSION}"
|
||||
popd
|
||||
|
||||
# Tag the release
|
||||
git tag android-sdk-${SDK_VERSION}
|
||||
fi
|
||||
|
||||
# Done!
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
|
||||
|
||||
exec ${THIS_DIR}/../../node_modules/react-native/scripts/launchPackager.command --reset-cache
|
||||
exec ${THIS_DIR}/../../node_modules/react-native/scripts/packager.sh --reset-cache
|
||||
|
||||
@@ -8,6 +8,7 @@ android {
|
||||
defaultConfig {
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
buildConfigField "String", "SDK_VERSION", "\"$sdkVersion\""
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -41,13 +42,14 @@ dependencies {
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
|
||||
|
||||
api "com.facebook.react:react-android:$rootProject.ext.rnVersion"
|
||||
api "com.facebook.react:hermes-android:$rootProject.ext.rnVersion"
|
||||
|
||||
//noinspection GradleDynamicVersion
|
||||
implementation 'org.webkit:android-jsc:+'
|
||||
|
||||
implementation 'com.facebook.fresco:animated-gif:2.5.0'
|
||||
implementation 'com.dropbox.core:dropbox-core-sdk:4.0.1'
|
||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||
implementation 'com.jakewharton.timber:timber:5.0.1'
|
||||
implementation 'com.squareup.duktape:duktape-android:1.3.0'
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation 'androidx.startup:startup-runtime:1.1.0'
|
||||
@@ -56,7 +58,7 @@ dependencies {
|
||||
if (!rootProject.ext.libreBuild) {
|
||||
implementation project(':react-native-amplitude')
|
||||
implementation project(':react-native-giphy')
|
||||
implementation(project(":react-native-google-signin")) {
|
||||
implementation(project(':react-native-google-signin')) {
|
||||
exclude group: 'com.google.android.gms'
|
||||
exclude group: 'androidx'
|
||||
}
|
||||
@@ -87,9 +89,11 @@ dependencies {
|
||||
implementation project(':react-native-splash-screen')
|
||||
implementation project(':react-native-svg')
|
||||
implementation project(':react-native-video')
|
||||
implementation project(':react-native-webrtc')
|
||||
implementation project(':react-native-webview')
|
||||
|
||||
// Use `api` here so consumers can use WebRTCModuleOptions.
|
||||
api project(':react-native-webrtc')
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
@@ -138,8 +142,7 @@ android.libraryVariants.all { def variant ->
|
||||
// Run the bundler
|
||||
commandLine(
|
||||
"node",
|
||||
"node_modules/react-native/local-cli/cli.js",
|
||||
"bundle",
|
||||
"node_modules/react-native/scripts/bundle.js",
|
||||
"--platform", "android",
|
||||
"--dev", "${devEnabled}",
|
||||
"--reset-cache",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
@@ -50,7 +51,7 @@
|
||||
|
||||
<service
|
||||
android:name="org.jitsi.meet.sdk.JitsiMeetOngoingConferenceService"
|
||||
android:foregroundServiceType="mediaPlayback" />
|
||||
android:foregroundServiceType="mediaPlayback|microphone" />
|
||||
|
||||
<provider
|
||||
android:name="com.reactnativecommunity.webview.RNCWebViewFileProvider"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
* Copyright @ 2017-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.
|
||||
@@ -37,6 +37,7 @@ class AppInfoModule
|
||||
public static final String NAME = "AppInfo";
|
||||
public static final boolean GOOGLE_SERVICES_ENABLED = getGoogleServicesEnabled();
|
||||
public static final boolean LIBRE_BUILD = getLibreBuild();
|
||||
public static final String SDK_VERSION = getSdkVersion();
|
||||
|
||||
public AppInfoModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
@@ -79,6 +80,7 @@ class AppInfoModule
|
||||
constants.put(
|
||||
"version",
|
||||
packageInfo == null ? "" : packageInfo.versionName);
|
||||
constants.put("sdkVersion", SDK_VERSION);
|
||||
constants.put("LIBRE_BUILD", LIBRE_BUILD);
|
||||
constants.put("GOOGLE_SERVICES_ENABLED", GOOGLE_SERVICES_ENABLED);
|
||||
|
||||
@@ -116,6 +118,19 @@ class AppInfoModule
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SDK version.
|
||||
*/
|
||||
private static String getSdkVersion() {
|
||||
Object sdkVersion = getBuildConfigValue("SDK_VERSION");
|
||||
|
||||
if (sdkVersion !=null) {
|
||||
return (String) sdkVersion;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets build config value of a certain field.
|
||||
*
|
||||
|
||||
@@ -18,7 +18,6 @@ package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.telecom.CallAudioState;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
@@ -34,7 +33,6 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
* {@link AudioModeModule.AudioDeviceHandlerInterface} module implementing device handling for
|
||||
* Android versions >= O when ConnectionService is enabled.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.O)
|
||||
class AudioDeviceHandlerConnectionService implements
|
||||
AudioModeModule.AudioDeviceHandlerInterface,
|
||||
RNConnectionService.CallAudioStateListener {
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.media.AudioAttributes;
|
||||
import android.media.AudioDeviceInfo;
|
||||
import android.media.AudioFocusRequest;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -227,22 +226,17 @@ class AudioDeviceHandlerGeneric implements
|
||||
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
|
||||
audioManager.setMicrophoneMute(false);
|
||||
|
||||
int gotFocus;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
gotFocus = audioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
|
||||
.setAudioAttributes(
|
||||
new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.build()
|
||||
)
|
||||
.setAcceptsDelayedFocusGain(true)
|
||||
.setOnAudioFocusChangeListener(this)
|
||||
.build()
|
||||
);
|
||||
} else {
|
||||
gotFocus = audioManager.requestAudioFocus(this, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN);
|
||||
}
|
||||
int gotFocus = audioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
|
||||
.setAudioAttributes(
|
||||
new AudioAttributes.Builder()
|
||||
.setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
|
||||
.setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
|
||||
.build()
|
||||
)
|
||||
.setAcceptsDelayedFocusGain(true)
|
||||
.setOnAudioFocusChangeListener(this)
|
||||
.build()
|
||||
);
|
||||
|
||||
if (gotFocus == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
|
||||
JitsiMeetLogger.w(TAG + " Audio focus request failed");
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.Promise;
|
||||
@@ -58,7 +57,6 @@ import java.util.concurrent.Executors;
|
||||
* Before a call has started and after it has ended the
|
||||
* {@code AudioModeModule.DEFAULT} mode should be used.
|
||||
*/
|
||||
@SuppressLint("AnnotateVersionCheck")
|
||||
@ReactModule(name = AudioModeModule.NAME)
|
||||
class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
public static final String NAME = "AudioMode";
|
||||
@@ -84,11 +82,10 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
/**
|
||||
* Whether or not the ConnectionService is used for selecting audio devices.
|
||||
*/
|
||||
private static final boolean supportsConnectionService = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
private static boolean useConnectionService_ = supportsConnectionService;
|
||||
private static boolean useConnectionService_ = true;
|
||||
|
||||
static boolean useConnectionService() {
|
||||
return supportsConnectionService && useConnectionService_;
|
||||
return useConnectionService_;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,6 +136,11 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
private String userSelectedDevice;
|
||||
|
||||
/**
|
||||
* Whether or not audio is disabled.
|
||||
*/
|
||||
private boolean audioDisabled;
|
||||
|
||||
/**
|
||||
* Initializes a new module instance. There shall be a single instance of
|
||||
* this module throughout the lifetime of the application.
|
||||
@@ -239,6 +241,12 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
audioDeviceHandler.stop();
|
||||
}
|
||||
|
||||
audioDeviceHandler = null;
|
||||
|
||||
if (audioDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (useConnectionService()) {
|
||||
audioDeviceHandler = new AudioDeviceHandlerConnectionService(audioManager);
|
||||
} else {
|
||||
@@ -281,6 +289,27 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setDisabled(final boolean disabled, final Promise promise) {
|
||||
if (audioDisabled == disabled) {
|
||||
promise.resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
JitsiMeetLogger.i(TAG + " audio disabled: " + disabled);
|
||||
|
||||
audioDisabled = disabled;
|
||||
setAudioDeviceHandler();
|
||||
|
||||
if (disabled) {
|
||||
mode = -1;
|
||||
availableDevices.clear();
|
||||
resetSelectedDevice();
|
||||
}
|
||||
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method to set the current audio mode.
|
||||
*
|
||||
@@ -290,7 +319,12 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
@ReactMethod
|
||||
public void setMode(final int mode, final Promise promise) {
|
||||
if (mode != DEFAULT && mode != AUDIO_CALL && mode != VIDEO_CALL) {
|
||||
if (audioDisabled) {
|
||||
promise.resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode < DEFAULT || mode > VIDEO_CALL) {
|
||||
promise.reject("setMode", "Invalid audio mode " + mode);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,6 @@ package org.jitsi.meet.sdk;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Wraps the name and extra data for events that were broadcasted locally.
|
||||
*/
|
||||
@@ -16,57 +10,21 @@ public class BroadcastAction {
|
||||
private static final String TAG = BroadcastAction.class.getSimpleName();
|
||||
|
||||
private final Type type;
|
||||
private final HashMap<String, Object> data;
|
||||
private final Bundle data;
|
||||
|
||||
public BroadcastAction(Intent intent) {
|
||||
this.type = Type.buildTypeFromAction(intent.getAction());
|
||||
this.data = buildDataFromBundle(intent.getExtras());
|
||||
this.data = intent.getExtras();
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public HashMap<String, Object> getData() {
|
||||
public Bundle getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public WritableNativeMap getDataAsWritableNativeMap() {
|
||||
WritableNativeMap nativeMap = new WritableNativeMap();
|
||||
|
||||
for (String key : this.data.keySet()) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return nativeMap;
|
||||
}
|
||||
|
||||
private static HashMap<String, Object> buildDataFromBundle(Bundle bundle) {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
|
||||
if (bundle != null) {
|
||||
for (String key : bundle.keySet()) {
|
||||
map.put(key, bundle.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
enum Type {
|
||||
SET_AUDIO_MUTED("org.jitsi.meet.SET_AUDIO_MUTED"),
|
||||
HANG_UP("org.jitsi.meet.HANG_UP"),
|
||||
@@ -78,7 +36,13 @@ public class BroadcastAction {
|
||||
SEND_CHAT_MESSAGE("org.jitsi.meet.SEND_CHAT_MESSAGE"),
|
||||
SET_VIDEO_MUTED("org.jitsi.meet.SET_VIDEO_MUTED"),
|
||||
SET_CLOSED_CAPTIONS_ENABLED("org.jitsi.meet.SET_CLOSED_CAPTIONS_ENABLED"),
|
||||
TOGGLE_CAMERA("org.jitsi.meet.TOGGLE_CAMERA");
|
||||
TOGGLE_CAMERA("org.jitsi.meet.TOGGLE_CAMERA"),
|
||||
SHOW_NOTIFICATION("org.jitsi.meet.SHOW_NOTIFICATION"),
|
||||
HIDE_NOTIFICATION("org.jitsi.meet.HIDE_NOTIFICATION"),
|
||||
START_RECORDING("org.jitsi.meet.START_RECORDING"),
|
||||
STOP_RECORDING("org.jitsi.meet.STOP_RECORDING"),
|
||||
OVERWRITE_CONFIG("org.jitsi.meet.OVERWRITE_CONFIG"),
|
||||
SEND_CAMERA_FACING_MODE_MESSAGE("org.jitsi.meet.SEND_CAMERA_FACING_MODE_MESSAGE");
|
||||
|
||||
private final String action;
|
||||
|
||||
|
||||
@@ -91,7 +91,9 @@ public class BroadcastEvent {
|
||||
VIDEO_MUTED_CHANGED("org.jitsi.meet.VIDEO_MUTED_CHANGED"),
|
||||
READY_TO_CLOSE("org.jitsi.meet.READY_TO_CLOSE"),
|
||||
TRANSCRIPTION_CHUNK_RECEIVED("org.jitsi.meet.TRANSCRIPTION_CHUNK_RECEIVED"),
|
||||
CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED("org.jitsi.meet.CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED");
|
||||
CUSTOM_BUTTON_PRESSED("org.jitsi.meet.CUSTOM_BUTTON_PRESSED"),
|
||||
CONFERENCE_UNIQUE_ID_SET("org.jitsi.meet.CONFERENCE_UNIQUE_ID_SET"),
|
||||
RECORDING_STATUS_CHANGED("org.jitsi.meet.RECORDING_STATUS_CHANGED");
|
||||
|
||||
private static final String CONFERENCE_BLURRED_NAME = "CONFERENCE_BLURRED";
|
||||
private static final String CONFERENCE_FOCUSED_NAME = "CONFERENCE_FOCUSED";
|
||||
@@ -109,7 +111,9 @@ public class BroadcastEvent {
|
||||
private static final String VIDEO_MUTED_CHANGED_NAME = "VIDEO_MUTED_CHANGED";
|
||||
private static final String READY_TO_CLOSE_NAME = "READY_TO_CLOSE";
|
||||
private static final String TRANSCRIPTION_CHUNK_RECEIVED_NAME = "TRANSCRIPTION_CHUNK_RECEIVED";
|
||||
private static final String CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED_NAME = "CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED";
|
||||
private static final String CUSTOM_BUTTON_PRESSED_NAME = "CUSTOM_BUTTON_PRESSED";
|
||||
private static final String CONFERENCE_UNIQUE_ID_SET_NAME = "CONFERENCE_UNIQUE_ID_SET";
|
||||
private static final String RECORDING_STATUS_CHANGED_NAME = "RECORDING_STATUS_CHANGED";
|
||||
|
||||
private final String action;
|
||||
|
||||
@@ -164,8 +168,12 @@ public class BroadcastEvent {
|
||||
return READY_TO_CLOSE;
|
||||
case TRANSCRIPTION_CHUNK_RECEIVED_NAME:
|
||||
return TRANSCRIPTION_CHUNK_RECEIVED;
|
||||
case CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED_NAME:
|
||||
return CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED;
|
||||
case CUSTOM_BUTTON_PRESSED_NAME:
|
||||
return CUSTOM_BUTTON_PRESSED;
|
||||
case CONFERENCE_UNIQUE_ID_SET_NAME:
|
||||
return CONFERENCE_UNIQUE_ID_SET;
|
||||
case RECORDING_STATUS_CHANGED_NAME:
|
||||
return RECORDING_STATUS_CHANGED;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class BroadcastIntentHelper {
|
||||
public static Intent buildSetAudioMutedIntent(boolean muted) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SET_AUDIO_MUTED.getAction());
|
||||
intent.putExtra("muted", muted);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -17,18 +19,21 @@ public class BroadcastIntentHelper {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SEND_ENDPOINT_TEXT_MESSAGE.getAction());
|
||||
intent.putExtra("to", to);
|
||||
intent.putExtra("message", message);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildToggleScreenShareIntent(boolean enabled) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.TOGGLE_SCREEN_SHARE.getAction());
|
||||
intent.putExtra("enabled", enabled);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildOpenChatIntent(String participantId) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.OPEN_CHAT.getAction());
|
||||
intent.putExtra("to", participantId);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -40,28 +45,113 @@ public class BroadcastIntentHelper {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SEND_CHAT_MESSAGE.getAction());
|
||||
intent.putExtra("to", participantId);
|
||||
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;
|
||||
}
|
||||
|
||||
public static Intent buildSetClosedCaptionsEnabledIntent(boolean enabled) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SET_CLOSED_CAPTIONS_ENABLED.getAction());
|
||||
intent.putExtra("enabled", enabled);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
||||
public static Intent buildRetrieveParticipantsInfo(String requestId) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.RETRIEVE_PARTICIPANTS_INFO.getAction());
|
||||
intent.putExtra("requestId", requestId);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildToggleCameraIntent() {
|
||||
return new Intent(BroadcastAction.Type.TOGGLE_CAMERA.getAction());
|
||||
}
|
||||
|
||||
public static Intent buildShowNotificationIntent(
|
||||
String appearance, String description, String timeout, String title, String uid) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SHOW_NOTIFICATION.getAction());
|
||||
intent.putExtra("appearance", appearance);
|
||||
intent.putExtra("description", description);
|
||||
intent.putExtra("timeout", timeout);
|
||||
intent.putExtra("title", title);
|
||||
intent.putExtra("uid", uid);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildHideNotificationIntent(String uid) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.HIDE_NOTIFICATION.getAction());
|
||||
intent.putExtra("uid", uid);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public enum RecordingMode {
|
||||
FILE("file"),
|
||||
STREAM("stream");
|
||||
|
||||
private final String mode;
|
||||
|
||||
RecordingMode(String mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String getMode() {
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
|
||||
public static Intent buildStartRecordingIntent(
|
||||
RecordingMode mode,
|
||||
String dropboxToken,
|
||||
boolean shouldShare,
|
||||
String rtmpStreamKey,
|
||||
String rtmpBroadcastID,
|
||||
String youtubeStreamKey,
|
||||
String youtubeBroadcastID,
|
||||
Bundle extraMetadata,
|
||||
boolean transcription) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.START_RECORDING.getAction());
|
||||
intent.putExtra("mode", mode.getMode());
|
||||
intent.putExtra("dropboxToken", dropboxToken);
|
||||
intent.putExtra("shouldShare", shouldShare);
|
||||
intent.putExtra("rtmpStreamKey", rtmpStreamKey);
|
||||
intent.putExtra("rtmpBroadcastID", rtmpBroadcastID);
|
||||
intent.putExtra("youtubeStreamKey", youtubeStreamKey);
|
||||
intent.putExtra("youtubeBroadcastID", youtubeBroadcastID);
|
||||
intent.putExtra("extraMetadata", extraMetadata);
|
||||
intent.putExtra("transcription", transcription);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildStopRecordingIntent(RecordingMode mode, boolean transcription) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.STOP_RECORDING.getAction());
|
||||
intent.putExtra("mode", mode.getMode());
|
||||
intent.putExtra("transcription", transcription);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildOverwriteConfigIntent(Bundle config) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.OVERWRITE_CONFIG.getAction());
|
||||
intent.putExtra("config", config);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent buildSendCameraFacingModeMessageIntent(String to, String facingMode) {
|
||||
Intent intent = new Intent(BroadcastAction.Type.SEND_CAMERA_FACING_MODE_MESSAGE.getAction());
|
||||
intent.putExtra("to", to);
|
||||
intent.putExtra("facingMode", facingMode);
|
||||
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,9 @@ package org.jitsi.meet.sdk;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
@@ -28,7 +31,14 @@ public class BroadcastReceiver extends android.content.BroadcastReceiver {
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
BroadcastAction action = new BroadcastAction(intent);
|
||||
String actionName = action.getType().getAction();
|
||||
|
||||
ReactInstanceManagerHolder.emitEvent(actionName, action.getDataAsWritableNativeMap());
|
||||
Bundle data = action.getData();
|
||||
|
||||
// For actions without data bundle (like hangup), we create an empty map
|
||||
// instead of attempting to convert a null bundle to avoid crashes.
|
||||
if (data != null) {
|
||||
ReactInstanceManagerHolder.emitEvent(actionName, Arguments.fromBundle(data));
|
||||
} else {
|
||||
ReactInstanceManagerHolder.emitEvent(actionName, Arguments.createMap());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ import java.util.Objects;
|
||||
*
|
||||
* @author Pawel Domas
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
public class ConnectionService extends android.telecom.ConnectionService {
|
||||
|
||||
/**
|
||||
|
||||
@@ -97,6 +97,12 @@ class ExternalAPIModule extends ReactContextBaseJavaModule {
|
||||
constants.put("SET_VIDEO_MUTED", BroadcastAction.Type.SET_VIDEO_MUTED.getAction());
|
||||
constants.put("SET_CLOSED_CAPTIONS_ENABLED", BroadcastAction.Type.SET_CLOSED_CAPTIONS_ENABLED.getAction());
|
||||
constants.put("TOGGLE_CAMERA", BroadcastAction.Type.TOGGLE_CAMERA.getAction());
|
||||
constants.put("SHOW_NOTIFICATION", BroadcastAction.Type.SHOW_NOTIFICATION.getAction());
|
||||
constants.put("HIDE_NOTIFICATION", BroadcastAction.Type.HIDE_NOTIFICATION.getAction());
|
||||
constants.put("START_RECORDING", BroadcastAction.Type.START_RECORDING.getAction());
|
||||
constants.put("STOP_RECORDING", BroadcastAction.Type.STOP_RECORDING.getAction());
|
||||
constants.put("OVERWRITE_CONFIG", BroadcastAction.Type.OVERWRITE_CONFIG.getAction());
|
||||
constants.put("SEND_CAMERA_FACING_MODE_MESSAGE", BroadcastAction.Type.SEND_CAMERA_FACING_MODE_MESSAGE.getAction());
|
||||
|
||||
return constants;
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
private static final String ACTION_JITSI_MEET_CONFERENCE = "org.jitsi.meet.CONFERENCE";
|
||||
private static final String JITSI_MEET_CONFERENCE_OPTIONS = "JitsiMeetConferenceOptions";
|
||||
|
||||
private boolean isReadyToClose;
|
||||
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@@ -124,6 +126,8 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
JitsiMeetLogger.i("onDestroy()");
|
||||
|
||||
// Here we are trying to handle the following corner case: an application using the SDK
|
||||
// is using this Activity for displaying meetings, but there is another "main" Activity
|
||||
// with other content. If this Activity is "swiped out" from the recent list we will get
|
||||
@@ -131,7 +135,10 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
// current meeting, but when our view is detached from React the JS <-> Native bridge won't
|
||||
// be operational so the external API won't be able to notify the native side that the
|
||||
// conference terminated. Thus, try our best to clean up.
|
||||
leave();
|
||||
if (!isReadyToClose) {
|
||||
JitsiMeetLogger.i("onDestroy(): leaving...");
|
||||
leave();
|
||||
}
|
||||
|
||||
this.jitsiView = null;
|
||||
|
||||
@@ -149,8 +156,12 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
leave();
|
||||
if (!isReadyToClose) {
|
||||
JitsiMeetLogger.i("finish(): leaving...");
|
||||
leave();
|
||||
}
|
||||
|
||||
JitsiMeetLogger.i("finish(): finishing...");
|
||||
super.finish();
|
||||
}
|
||||
|
||||
@@ -170,8 +181,8 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
}
|
||||
|
||||
public void join(JitsiMeetConferenceOptions options) {
|
||||
if (this.jitsiView != null) {
|
||||
this.jitsiView .join(options);
|
||||
if (this.jitsiView != null) {
|
||||
this.jitsiView.join(options);
|
||||
} else {
|
||||
JitsiMeetLogger.w("Cannot join, view is null");
|
||||
}
|
||||
@@ -252,6 +263,7 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
|
||||
protected void onReadyToClose() {
|
||||
JitsiMeetLogger.i("SDK is ready to close");
|
||||
isReadyToClose = true;
|
||||
finish();
|
||||
}
|
||||
|
||||
@@ -259,9 +271,17 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
// JitsiMeetLogger.i("Transcription chunk received: " + extraData);
|
||||
// }
|
||||
|
||||
// protected void onCustomOverflowMenuButtonPressed(HashMap<String, Object> extraData) {
|
||||
// JitsiMeetLogger.i("Custom overflow menu button pressed: " + extraData);
|
||||
// }
|
||||
// protected void onCustomButtonPressed(HashMap<String, Object> extraData) {
|
||||
// JitsiMeetLogger.i("Custom button pressed: " + extraData);
|
||||
// }
|
||||
|
||||
// protected void onConferenceUniqueIdSet(HashMap<String, Object> extraData) {
|
||||
// JitsiMeetLogger.i("Conference unique id set: " + extraData);
|
||||
// }
|
||||
|
||||
// protected void onRecordingStatusChanged(HashMap<String, Object> extraData) {
|
||||
// JitsiMeetLogger.i("Recording status changed: " + extraData);
|
||||
// }
|
||||
|
||||
// Activity lifecycle methods
|
||||
//
|
||||
@@ -294,8 +314,8 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
|
||||
@Override
|
||||
protected void onUserLeaveHint() {
|
||||
if (this.jitsiView != null) {
|
||||
this.jitsiView .enterPictureInPicture();
|
||||
if (this.jitsiView != null) {
|
||||
this.jitsiView.enterPictureInPicture();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,12 +366,18 @@ public class JitsiMeetActivity extends AppCompatActivity
|
||||
case READY_TO_CLOSE:
|
||||
onReadyToClose();
|
||||
break;
|
||||
// case TRANSCRIPTION_CHUNK_RECEIVED:
|
||||
// onTranscriptionChunkReceived(event.getData());
|
||||
// break;
|
||||
// case CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED:
|
||||
// onCustomOverflowMenuButtonPressed(event.getData());
|
||||
// break;
|
||||
// case TRANSCRIPTION_CHUNK_RECEIVED:
|
||||
// onTranscriptionChunkReceived(event.getData());
|
||||
// break;
|
||||
// case CUSTOM_BUTTON_PRESSED:
|
||||
// onCustomButtonPressed(event.getData());
|
||||
// break;
|
||||
// case CONFERENCE_UNIQUE_ID_SET:
|
||||
// onConferenceUniqueIdSet(event.getData());
|
||||
// break;
|
||||
// case RECORDING_STATUS_CHANGED:
|
||||
// onRecordingStatusChanged(event.getData());
|
||||
// break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class JitsiMeetActivityDelegate {
|
||||
/**
|
||||
* Tells whether or not the permissions request is currently in progress.
|
||||
*
|
||||
* @return {@code true} if the permssions are being requested or {@code false} otherwise.
|
||||
* @return {@code true} if the permissions are being requested or {@code false} otherwise.
|
||||
*/
|
||||
static boolean arePermissionsBeingRequested() {
|
||||
return permissionListener != null;
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
@@ -229,6 +230,12 @@ public class JitsiMeetConferenceOptions implements Parcelable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder setConfigOverride(String config, ArrayList<Bundle> arrayList) {
|
||||
this.config.putParcelableArrayList(config, arrayList);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the immutable {@link JitsiMeetConferenceOptions} object with the configuration
|
||||
* that this {@link Builder} instance specified.
|
||||
@@ -263,11 +270,6 @@ public class JitsiMeetConferenceOptions implements Parcelable {
|
||||
Bundle asProps() {
|
||||
Bundle props = new Bundle();
|
||||
|
||||
// Android always has the PiP flag set by default.
|
||||
if (!featureFlags.containsKey("pip.enabled")) {
|
||||
featureFlags.putBoolean("pip.enabled", true);
|
||||
}
|
||||
|
||||
props.putBundle("flags", featureFlags);
|
||||
|
||||
Bundle urlProps = new Bundle();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import static android.Manifest.permission.POST_NOTIFICATIONS;
|
||||
import static android.Manifest.permission.RECORD_AUDIO;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
@@ -38,7 +39,9 @@ import com.facebook.react.modules.core.PermissionListener;
|
||||
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
@@ -48,39 +51,39 @@ import java.util.Random;
|
||||
*
|
||||
* See: https://developer.android.com/guide/components/services
|
||||
*/
|
||||
public class JitsiMeetOngoingConferenceService extends Service
|
||||
implements OngoingConferenceTracker.OngoingConferenceListener {
|
||||
public class JitsiMeetOngoingConferenceService extends Service implements OngoingConferenceTracker.OngoingConferenceListener {
|
||||
private static final String TAG = JitsiMeetOngoingConferenceService.class.getSimpleName();
|
||||
private static final String ACTIVITY_DATA_KEY = "activityDataKey";
|
||||
private static final String EXTRA_DATA_KEY = "extraDataKey";
|
||||
private static final String EXTRA_DATA_BUNDLE_KEY = "extraDataBundleKey";
|
||||
private static final String IS_AUDIO_MUTED_KEY = "isAudioMuted";
|
||||
|
||||
private static final int PERMISSIONS_REQUEST_CODE = (int) (Math.random() * Short.MAX_VALUE);
|
||||
|
||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver();
|
||||
|
||||
private static final int POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE = (int) (Math.random() * Short.MAX_VALUE);
|
||||
|
||||
private boolean isAudioMuted;
|
||||
private Class tapBackActivity;
|
||||
|
||||
static final int NOTIFICATION_ID = new Random().nextInt(99999) + 10000;
|
||||
|
||||
private static void doLaunch(Context context, HashMap<String, Object> extraData) {
|
||||
Activity activity = (Activity) context;
|
||||
|
||||
OngoingNotification.createNotificationChannel((Activity) context);
|
||||
OngoingNotification.createNotificationChannel(activity);
|
||||
|
||||
Intent intent = new Intent(context, JitsiMeetOngoingConferenceService.class);
|
||||
|
||||
Bundle extraDataBundle = new Bundle();
|
||||
extraDataBundle.putSerializable(EXTRA_DATA_KEY, extraData);
|
||||
|
||||
intent.putExtra(EXTRA_DATA_BUNDLE_KEY, extraDataBundle);
|
||||
intent.putExtra(ACTIVITY_DATA_KEY, activity.getClass().getCanonicalName());
|
||||
|
||||
ComponentName componentName;
|
||||
|
||||
try {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
componentName = context.startForegroundService(intent);
|
||||
} else {
|
||||
componentName = context.startService(intent);
|
||||
}
|
||||
componentName = context.startForegroundService(intent);
|
||||
} catch (RuntimeException e) {
|
||||
// Avoid crashing due to ForegroundServiceStartNotAllowedException (API level 31).
|
||||
// See: https://developer.android.com/guide/components/foreground-services#background-start-restrictions
|
||||
@@ -95,26 +98,50 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
|
||||
|
||||
public static void launch(Context context, HashMap<String, Object> extraData) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
PermissionListener listener = new PermissionListener() {
|
||||
@Override
|
||||
public boolean onRequestPermissionsResult(int i, String[] strings, int[] results) {
|
||||
if (results.length > 0 && results[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
doLaunch(context, extraData);
|
||||
List<String> permissionsList = new ArrayList<>();
|
||||
|
||||
PermissionListener listener = new PermissionListener() {
|
||||
@Override
|
||||
public boolean onRequestPermissionsResult(int i, String[] strings, int[] results) {
|
||||
int counter = 0;
|
||||
|
||||
if (results.length > 0) {
|
||||
for (int result : results) {
|
||||
if (result == PackageManager.PERMISSION_GRANTED) {
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
if (counter == results.length){
|
||||
doLaunch(context, extraData);
|
||||
JitsiMeetLogger.w(TAG + " Service launched, permissions were granted");
|
||||
} else {
|
||||
JitsiMeetLogger.w(TAG + " Couldn't launch service, permissions were not granted");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
permissionsList.add(POST_NOTIFICATIONS);
|
||||
permissionsList.add(RECORD_AUDIO);
|
||||
}
|
||||
|
||||
String[] permissionsArray = new String[ permissionsList.size() ];
|
||||
permissionsArray = permissionsList.toArray( permissionsArray );
|
||||
|
||||
if (permissionsArray.length > 0) {
|
||||
JitsiMeetActivityDelegate.requestPermissions(
|
||||
(Activity) context,
|
||||
new String[]{POST_NOTIFICATIONS},
|
||||
POST_NOTIFICATIONS_PERMISSION_REQUEST_CODE,
|
||||
permissionsArray,
|
||||
PERMISSIONS_REQUEST_CODE,
|
||||
listener
|
||||
);
|
||||
} else {
|
||||
doLaunch(context, extraData);
|
||||
JitsiMeetLogger.w(TAG + " Service launched");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,12 +154,14 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, this);
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, this, tapBackActivity);
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
} else {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK | ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
|
||||
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
|
||||
startForeground(NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
|
||||
} else {
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
@@ -161,13 +190,28 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
final String actionName = intent.getAction();
|
||||
final Action action = Action.fromName(actionName);
|
||||
|
||||
Boolean isAudioMuted = tryParseIsAudioMuted(intent);
|
||||
if (action != Action.HANGUP) {
|
||||
Boolean isAudioMuted = tryParseIsAudioMuted(intent);
|
||||
|
||||
if (isAudioMuted != null) {
|
||||
this.isAudioMuted = Boolean.parseBoolean(intent.getStringExtra("muted"));
|
||||
if (isAudioMuted != null) {
|
||||
this.isAudioMuted = Boolean.parseBoolean(intent.getStringExtra("muted"));
|
||||
}
|
||||
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, this);
|
||||
if (tapBackActivity == null) {
|
||||
String targetActivityName = intent.getExtras().getString(ACTIVITY_DATA_KEY);
|
||||
Class<? extends Activity> targetActivity = null;
|
||||
try {
|
||||
targetActivity = Class.forName(targetActivityName).asSubclass(Activity.class);
|
||||
tapBackActivity = targetActivity;
|
||||
} catch (ClassNotFoundException e) {
|
||||
JitsiMeetLogger.w(TAG + " Could not find target Activity: " + targetActivityName);
|
||||
}
|
||||
}
|
||||
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(this.isAudioMuted, this, tapBackActivity);
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't start service, notification is null");
|
||||
@@ -177,9 +221,6 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
}
|
||||
}
|
||||
|
||||
final String actionName = intent.getAction();
|
||||
final Action action = Action.fromName(actionName);
|
||||
|
||||
// When starting the service, there is no action passed in the intent
|
||||
if (action != null) {
|
||||
switch (action) {
|
||||
@@ -252,8 +293,9 @@ public class JitsiMeetOngoingConferenceService extends Service
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Class tapBackActivity = JitsiMeetOngoingConferenceService.this.tapBackActivity;
|
||||
isAudioMuted = Boolean.parseBoolean(intent.getStringExtra("muted"));
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, context);
|
||||
Notification notification = OngoingNotification.buildOngoingConferenceNotification(isAudioMuted, context, tapBackActivity);
|
||||
if (notification == null) {
|
||||
stopSelf();
|
||||
JitsiMeetLogger.w(TAG + " Couldn't update service, notification is null");
|
||||
|
||||
@@ -33,10 +33,9 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
public class JitsiMeetView extends FrameLayout {
|
||||
|
||||
/**
|
||||
* Background color used by {@code BaseReactView} and the React Native root
|
||||
* view.
|
||||
* Background color. Should match the background color set in JS.
|
||||
*/
|
||||
private static final int BACKGROUND_COLOR = 0xFF111111;
|
||||
private static final int BACKGROUND_COLOR = 0xFF040404;
|
||||
|
||||
/**
|
||||
* React Native root view.
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
/*
|
||||
* Copyright 2017 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.oney.WebRTCModule.webrtcutils.SoftwareVideoDecoderFactoryProxy;
|
||||
|
||||
import org.webrtc.EglBase;
|
||||
import org.webrtc.HardwareVideoDecoderFactory;
|
||||
import org.webrtc.PlatformSoftwareVideoDecoderFactory;
|
||||
import org.webrtc.VideoCodecInfo;
|
||||
import org.webrtc.VideoDecoder;
|
||||
import org.webrtc.VideoDecoderFactory;
|
||||
import org.webrtc.VideoDecoderFallback;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
/**
|
||||
* Custom decoder factory which uses HW decoders and falls back to SW.
|
||||
*/
|
||||
public class JitsiVideoDecoderFactory implements VideoDecoderFactory {
|
||||
private final VideoDecoderFactory hardwareVideoDecoderFactory;
|
||||
private final VideoDecoderFactory softwareVideoDecoderFactory = new SoftwareVideoDecoderFactoryProxy();
|
||||
private final @Nullable VideoDecoderFactory platformSoftwareVideoDecoderFactory;
|
||||
|
||||
/**
|
||||
* Create decoder factory using default hardware decoder factory.
|
||||
*/
|
||||
public JitsiVideoDecoderFactory(@Nullable EglBase.Context eglContext) {
|
||||
this.hardwareVideoDecoderFactory = new HardwareVideoDecoderFactory(eglContext);
|
||||
this.platformSoftwareVideoDecoderFactory = new PlatformSoftwareVideoDecoderFactory(eglContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create decoder factory using explicit hardware decoder factory.
|
||||
*/
|
||||
JitsiVideoDecoderFactory(VideoDecoderFactory hardwareVideoDecoderFactory) {
|
||||
this.hardwareVideoDecoderFactory = hardwareVideoDecoderFactory;
|
||||
this.platformSoftwareVideoDecoderFactory = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable VideoDecoder createDecoder(VideoCodecInfo codecType) {
|
||||
VideoDecoder softwareDecoder = softwareVideoDecoderFactory.createDecoder(codecType);
|
||||
final VideoDecoder hardwareDecoder = hardwareVideoDecoderFactory.createDecoder(codecType);
|
||||
if (softwareDecoder == null && platformSoftwareVideoDecoderFactory != null) {
|
||||
softwareDecoder = platformSoftwareVideoDecoderFactory.createDecoder(codecType);
|
||||
}
|
||||
if (hardwareDecoder != null && softwareDecoder != null) {
|
||||
// Both hardware and software supported, wrap it in a software fallback
|
||||
return new VideoDecoderFallback(
|
||||
/* fallback= */ softwareDecoder, /* primary= */ hardwareDecoder);
|
||||
}
|
||||
return hardwareDecoder != null ? hardwareDecoder : softwareDecoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoCodecInfo[] getSupportedCodecs() {
|
||||
LinkedHashSet<VideoCodecInfo> supportedCodecInfos = new LinkedHashSet<>();
|
||||
|
||||
supportedCodecInfos.addAll(Arrays.asList(softwareVideoDecoderFactory.getSupportedCodecs()));
|
||||
supportedCodecInfos.addAll(Arrays.asList(hardwareVideoDecoderFactory.getSupportedCodecs()));
|
||||
if (platformSoftwareVideoDecoderFactory != null) {
|
||||
supportedCodecInfos.addAll(
|
||||
Arrays.asList(platformSoftwareVideoDecoderFactory.getSupportedCodecs()));
|
||||
}
|
||||
|
||||
return supportedCodecInfos.toArray(new VideoCodecInfo[supportedCodecInfos.size()]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoEncoderFactory;
|
||||
|
||||
import org.webrtc.EglBase;
|
||||
|
||||
/**
|
||||
* Custom encoder factory which uses HW for H.264 and SW for everything else.
|
||||
*/
|
||||
public class JitsiVideoEncoderFactory extends H264AndSoftwareVideoEncoderFactory {
|
||||
public JitsiVideoEncoderFactory(@Nullable EglBase.Context eglContext) {
|
||||
super(eglContext);
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,6 @@ import android.content.Intent;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import android.os.Build;
|
||||
|
||||
|
||||
/**
|
||||
* Helper class for creating the ongoing notification which is used with
|
||||
@@ -45,10 +43,6 @@ class OngoingNotification {
|
||||
static final String ONGOING_CONFERENCE_CHANNEL_ID = "JitsiOngoingConferenceChannel";
|
||||
|
||||
static void createNotificationChannel(Activity context) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (context == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification channel: no current context");
|
||||
return;
|
||||
@@ -73,14 +67,13 @@ class OngoingNotification {
|
||||
notificationManager.createNotificationChannel(channel);
|
||||
}
|
||||
|
||||
static Notification buildOngoingConferenceNotification(Boolean isMuted, Context context) {
|
||||
|
||||
static Notification buildOngoingConferenceNotification(Boolean isMuted, Context context, Class tapBackActivity) {
|
||||
if (context == null) {
|
||||
JitsiMeetLogger.w(TAG + " Cannot create notification: no current context");
|
||||
return null;
|
||||
}
|
||||
|
||||
Intent notificationIntent = new Intent(context, context.getClass());
|
||||
Intent notificationIntent = new Intent(context, tapBackActivity == null ? context.getClass() : tapBackActivity);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
|
||||
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, ONGOING_CONFERENCE_CHANNEL_ID);
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.PictureInPictureParams;
|
||||
import android.os.Build;
|
||||
import android.util.Rational;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
@@ -53,7 +52,7 @@ class PictureInPictureModule extends ReactContextBaseJavaModule {
|
||||
// Android Go devices don't support PiP. There doesn't seem to be a better way to detect it than
|
||||
// to use ActivityManager.isLowRamDevice().
|
||||
// https://stackoverflow.com/questions/58340558/how-to-detect-android-go
|
||||
isSupported = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !am.isLowRamDevice();
|
||||
isSupported = !am.isLowRamDevice();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +81,6 @@ class PictureInPictureModule extends ReactContextBaseJavaModule {
|
||||
* including when the activity is not visible (paused or stopped), if the
|
||||
* screen is locked or if the user has an activity pinned.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public void enterPictureInPicture() {
|
||||
if (!isEnabled) {
|
||||
return;
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.jitsi.meet.sdk;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.telecom.DisconnectCause;
|
||||
import android.telecom.PhoneAccount;
|
||||
@@ -32,7 +31,6 @@ import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
*
|
||||
* @author Pawel Domas
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
@ReactModule(name = RNConnectionService.NAME)
|
||||
class RNConnectionService extends ReactContextBaseJavaModule {
|
||||
|
||||
@@ -53,7 +51,6 @@ class RNConnectionService extends ReactContextBaseJavaModule {
|
||||
* @param audioRoute the new audio route to be set. See
|
||||
* {@link android.telecom.CallAudioState} constants prefixed with "ROUTE_".
|
||||
*/
|
||||
@RequiresApi(api = Build.VERSION_CODES.O)
|
||||
static void setAudioRoute(int audioRoute) {
|
||||
for (ConnectionService.ConnectionImpl c
|
||||
: ConnectionService.getConnections()) {
|
||||
|
||||
@@ -16,28 +16,26 @@
|
||||
|
||||
package org.jitsi.meet.sdk;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.facebook.hermes.reactexecutor.HermesExecutorFactory;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.bridge.NativeModule;
|
||||
import com.facebook.react.bridge.ReactApplicationContext;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.common.LifecycleState;
|
||||
import com.facebook.react.jscexecutor.JSCExecutorFactory;
|
||||
import com.facebook.react.modules.core.DeviceEventManagerModule;
|
||||
import com.facebook.react.uimanager.ViewManager;
|
||||
import com.oney.WebRTCModule.EglUtils;
|
||||
import com.oney.WebRTCModule.WebRTCModuleOptions;
|
||||
import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoDecoderFactory;
|
||||
import com.oney.WebRTCModule.webrtcutils.H264AndSoftwareVideoEncoderFactory;
|
||||
|
||||
import org.devio.rn.splashscreen.SplashScreenModule;
|
||||
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
|
||||
import org.webrtc.EglBase;
|
||||
import org.webrtc.Logging;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
@@ -126,41 +124,36 @@ class ReactInstanceManagerHolder {
|
||||
// AmplitudeReactNativePackage
|
||||
try {
|
||||
Class<?> amplitudePackageClass = Class.forName("com.amplitude.reactnative.AmplitudeReactNativePackage");
|
||||
Constructor constructor = amplitudePackageClass.getConstructor();
|
||||
Constructor<?> constructor = amplitudePackageClass.getConstructor();
|
||||
packages.add((ReactPackage)constructor.newInstance());
|
||||
} catch (Exception e) {
|
||||
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
|
||||
Log.d(TAG, "Not loading AmplitudeReactNativePackage");
|
||||
JitsiMeetLogger.d(TAG, "Not loading AmplitudeReactNativePackage");
|
||||
}
|
||||
|
||||
// GiphyReactNativeSdkPackage
|
||||
try {
|
||||
Class<?> giphyPackageClass = Class.forName("com.giphyreactnativesdk.GiphyReactNativeSdkPackage");
|
||||
Constructor constructor = giphyPackageClass.getConstructor();
|
||||
Constructor<?> constructor = giphyPackageClass.getConstructor();
|
||||
packages.add((ReactPackage)constructor.newInstance());
|
||||
} catch (Exception e) {
|
||||
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
|
||||
Log.d(TAG, "Not loading GiphyReactNativeSdkPackage");
|
||||
JitsiMeetLogger.d(TAG, "Not loading GiphyReactNativeSdkPackage");
|
||||
}
|
||||
|
||||
// RNGoogleSignInPackage
|
||||
try {
|
||||
Class<?> googlePackageClass = Class.forName("com.reactnativegooglesignin.RNGoogleSigninPackage");
|
||||
Constructor constructor = googlePackageClass.getConstructor();
|
||||
Constructor<?> constructor = googlePackageClass.getConstructor();
|
||||
packages.add((ReactPackage)constructor.newInstance());
|
||||
} catch (Exception e) {
|
||||
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
|
||||
Log.d(TAG, "Not loading RNGoogleSignInPackage");
|
||||
JitsiMeetLogger.d(TAG, "Not loading RNGoogleSignInPackage");
|
||||
}
|
||||
|
||||
return packages;
|
||||
}
|
||||
|
||||
static JSCExecutorFactory getReactNativeJSFactory() {
|
||||
// Keep on using JSC, the jury is out on Hermes.
|
||||
return new JSCExecutorFactory("", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to send an event to JavaScript.
|
||||
*
|
||||
@@ -174,7 +167,7 @@ class ReactInstanceManagerHolder {
|
||||
= ReactInstanceManagerHolder.getReactInstanceManager();
|
||||
|
||||
if (reactInstanceManager != null) {
|
||||
ReactContext reactContext
|
||||
@SuppressLint("VisibleForTests") ReactContext reactContext
|
||||
= reactInstanceManager.getCurrentReactContext();
|
||||
|
||||
if (reactContext != null) {
|
||||
@@ -197,7 +190,7 @@ class ReactInstanceManagerHolder {
|
||||
*/
|
||||
static <T extends NativeModule> T getNativeModule(
|
||||
Class<T> nativeModuleClass) {
|
||||
ReactContext reactContext
|
||||
@SuppressLint("VisibleForTests") ReactContext reactContext
|
||||
= reactInstanceManager != null
|
||||
? reactInstanceManager.getCurrentReactContext() : null;
|
||||
|
||||
@@ -205,18 +198,6 @@ class ReactInstanceManagerHolder {
|
||||
? reactContext.getNativeModule(nativeModuleClass) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current {@link Activity} linked to React Native.
|
||||
*
|
||||
* @return An activity attached to React Native.
|
||||
*/
|
||||
static Activity getCurrentActivity() {
|
||||
ReactContext reactContext
|
||||
= reactInstanceManager != null
|
||||
? reactInstanceManager.getCurrentReactContext() : null;
|
||||
return reactContext != null ? reactContext.getCurrentActivity() : null;
|
||||
}
|
||||
|
||||
static ReactInstanceManager getReactInstanceManager() {
|
||||
return reactInstanceManager;
|
||||
}
|
||||
@@ -236,15 +217,18 @@ class ReactInstanceManagerHolder {
|
||||
|
||||
// Initialize the WebRTC module options.
|
||||
WebRTCModuleOptions options = WebRTCModuleOptions.getInstance();
|
||||
|
||||
EglBase.Context eglContext = EglUtils.getRootEglBaseContext();
|
||||
|
||||
options.videoDecoderFactory = new H264AndSoftwareVideoDecoderFactory(eglContext);
|
||||
options.videoEncoderFactory = new H264AndSoftwareVideoEncoderFactory(eglContext);
|
||||
options.enableMediaProjectionService = true;
|
||||
// options.loggingSeverity = Logging.Severity.LS_INFO;
|
||||
if (options.videoDecoderFactory == null || options.videoEncoderFactory == null) {
|
||||
EglBase.Context eglContext = EglUtils.getRootEglBaseContext();
|
||||
if (options.videoDecoderFactory == null) {
|
||||
options.videoDecoderFactory = new JitsiVideoDecoderFactory(eglContext);
|
||||
}
|
||||
if (options.videoEncoderFactory == null) {
|
||||
options.videoEncoderFactory = new JitsiVideoEncoderFactory(eglContext);
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "initializing RN with Activity");
|
||||
JitsiMeetLogger.d(TAG, "initializing RN");
|
||||
|
||||
reactInstanceManager
|
||||
= ReactInstanceManager.builder()
|
||||
@@ -252,7 +236,7 @@ class ReactInstanceManagerHolder {
|
||||
.setCurrentActivity(activity)
|
||||
.setBundleAssetName("index.android.bundle")
|
||||
.setJSMainModulePath("index.android")
|
||||
.setJavaScriptExecutorFactory(getReactNativeJSFactory())
|
||||
.setJavaScriptExecutorFactory(new HermesExecutorFactory())
|
||||
.addPackages(getReactNativePackages())
|
||||
.setUseDeveloperSupport(BuildConfig.DEBUG)
|
||||
.setInitialLifecycleState(LifecycleState.RESUMED)
|
||||
|
||||
@@ -11,7 +11,7 @@ project(':react-native-background-timer').projectDir = new File(rootProject.proj
|
||||
include ':react-native-calendar-events'
|
||||
project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
|
||||
include ':react-native-community_clipboard'
|
||||
project(':react-native-community_clipboard').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/clipboard/android')
|
||||
project(':react-native-community_clipboard').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-clipboard/clipboard/android')
|
||||
include ':react-native-community_netinfo'
|
||||
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
|
||||
include ':react-native-default-preference'
|
||||
|
||||
28
app.js
28
app.js
@@ -1,4 +1,4 @@
|
||||
/* application specific logic */
|
||||
/* Jitsi Meet app main entrypoint. */
|
||||
|
||||
// Re-export jQuery
|
||||
// FIXME: Remove this requirement from torture tests.
|
||||
@@ -10,6 +10,32 @@ import '@matrix-org/olm';
|
||||
|
||||
import 'focus-visible';
|
||||
|
||||
/*
|
||||
* Safari polyfill for createImageBitmap
|
||||
* https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/createImageBitmap
|
||||
*
|
||||
* Support source image types: Canvas.
|
||||
*/
|
||||
if (!('createImageBitmap' in window)) {
|
||||
window.createImageBitmap = function(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let dataURL;
|
||||
|
||||
if (data instanceof HTMLCanvasElement) {
|
||||
dataURL = data.toDataURL();
|
||||
} else {
|
||||
reject(new Error('createImageBitmap does not handle the provided image source type'));
|
||||
}
|
||||
const img = document.createElement('img');
|
||||
|
||||
img.addEventListener('load', () => {
|
||||
resolve(img);
|
||||
});
|
||||
img.src = dataURL;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// We need to setup the jitsi-local-storage as early as possible so that we can start using it.
|
||||
// NOTE: If jitsi-local-storage is used before the initial setup is performed this will break the use case when we use
|
||||
// the local storage from the parent page when the localStorage is disabled. Also the setup is relying that
|
||||
|
||||
@@ -5,5 +5,12 @@ module.exports = {
|
||||
plugins: [ 'react-native-paper/babel' ]
|
||||
}
|
||||
},
|
||||
plugins: [ 'optional-require' ]
|
||||
|
||||
// This happens because react native has conflict with @babel/plugin-transform-private-methods plugin
|
||||
// https://github.com/ethers-io/ethers.js/discussions/4309#discussioncomment-6694524
|
||||
plugins: [ 'optional-require',
|
||||
[ '@babel/plugin-transform-private-methods', {
|
||||
'loose': true
|
||||
} ]
|
||||
]
|
||||
};
|
||||
|
||||
475
conference.js
475
conference.js
@@ -4,7 +4,6 @@ import { jitsiLocalStorage } from '@jitsi/js-utils';
|
||||
import Logger from '@jitsi/logger';
|
||||
|
||||
import { ENDPOINT_TEXT_MESSAGE_NAME } from './modules/API/constants';
|
||||
import { AUDIO_ONLY_SCREEN_SHARE_NO_TRACK } from './modules/UI/UIErrors';
|
||||
import mediaDeviceHelper from './modules/devices/mediaDeviceHelper';
|
||||
import Recorder from './modules/recorder/Recorder';
|
||||
import { createTaskQueue } from './modules/util/helpers';
|
||||
@@ -17,7 +16,6 @@ import {
|
||||
import { sendAnalytics } from './react/features/analytics/functions';
|
||||
import {
|
||||
maybeRedirectToWelcomePage,
|
||||
redirectToStaticPage,
|
||||
reloadWithStoredParams
|
||||
} from './react/features/app/actions';
|
||||
import { showModeratedNotification } from './react/features/av-moderation/actions';
|
||||
@@ -29,6 +27,7 @@ import {
|
||||
conferenceJoinInProgress,
|
||||
conferenceJoined,
|
||||
conferenceLeft,
|
||||
conferencePropertiesChanged,
|
||||
conferenceSubjectChanged,
|
||||
conferenceTimestampChanged,
|
||||
conferenceUniqueIdSet,
|
||||
@@ -55,7 +54,7 @@ import {
|
||||
getConferenceOptions,
|
||||
sendLocalParticipant
|
||||
} from './react/features/base/conference/functions';
|
||||
import { getReplaceParticipant } from './react/features/base/config/functions';
|
||||
import { getReplaceParticipant, getSsrcRewritingFeatureFlag } from './react/features/base/config/functions';
|
||||
import { connect } from './react/features/base/connection/actions.web';
|
||||
import {
|
||||
checkAndNotifyForNewDevice,
|
||||
@@ -77,7 +76,6 @@ import {
|
||||
JitsiConferenceEvents,
|
||||
JitsiE2ePingEvents,
|
||||
JitsiMediaDevicesEvents,
|
||||
JitsiTrackErrors,
|
||||
JitsiTrackEvents,
|
||||
browser
|
||||
} from './react/features/base/lib-jitsi-meet';
|
||||
@@ -86,6 +84,7 @@ import {
|
||||
setAudioAvailable,
|
||||
setAudioMuted,
|
||||
setAudioUnmutePermissions,
|
||||
setInitialGUMPromise,
|
||||
setVideoAvailable,
|
||||
setVideoMuted,
|
||||
setVideoUnmutePermissions
|
||||
@@ -113,13 +112,17 @@ import {
|
||||
import {
|
||||
getLocalParticipant,
|
||||
getNormalizedDisplayName,
|
||||
getParticipantByIdOrUndefined,
|
||||
getVirtualScreenshareParticipantByOwnerId
|
||||
} from './react/features/base/participants/functions';
|
||||
import { updateSettings } from './react/features/base/settings/actions';
|
||||
import {
|
||||
addLocalTrack,
|
||||
createInitialAVTracks,
|
||||
destroyLocalTracks,
|
||||
displayErrorsForCreateInitialLocalTracks,
|
||||
replaceLocalTrack,
|
||||
setGUMPendingStateOnFailedTracks,
|
||||
toggleScreensharing as toggleScreensharingA,
|
||||
trackAdded,
|
||||
trackRemoved
|
||||
@@ -134,11 +137,11 @@ import {
|
||||
isUserInteractionRequiredForUnmute
|
||||
} from './react/features/base/tracks/functions';
|
||||
import { downloadJSON } from './react/features/base/util/downloadJSON';
|
||||
import { getJitsiMeetGlobalNSConnectionTimes } from './react/features/base/util/helpers';
|
||||
import { openLeaveReasonDialog } from './react/features/conference/actions.web';
|
||||
import { showDesktopPicker } from './react/features/desktop-picker/actions';
|
||||
import { appendSuffix } from './react/features/display-name/functions';
|
||||
import { maybeOpenFeedbackDialog, submitFeedback } from './react/features/feedback/actions';
|
||||
import { initKeyboardShortcuts } from './react/features/keyboard-shortcuts/actions';
|
||||
import { maybeSetLobbyChatMessageListener } from './react/features/lobby/actions.any';
|
||||
import { setNoiseSuppressionEnabled } from './react/features/noise-suppression/actions';
|
||||
import {
|
||||
@@ -152,10 +155,8 @@ import {
|
||||
NOTIFICATION_TIMEOUT_TYPE
|
||||
} from './react/features/notifications/constants';
|
||||
import { isModerationNotificationDisplayed } from './react/features/notifications/functions';
|
||||
import { mediaPermissionPromptVisibilityChanged } from './react/features/overlay/actions';
|
||||
import { suspendDetected } from './react/features/power-monitor/actions';
|
||||
import { initPrejoin } from './react/features/prejoin/actions';
|
||||
import { isPrejoinPageVisible } from './react/features/prejoin/functions';
|
||||
import { initPrejoin, isPrejoinPageVisible } from './react/features/prejoin/functions';
|
||||
import { disableReceiver, stopReceiver } from './react/features/remote-control/actions';
|
||||
import { setScreenAudioShareState } from './react/features/screen-share/actions.web';
|
||||
import { isScreenAudioShared } from './react/features/screen-share/functions';
|
||||
@@ -163,15 +164,17 @@ import { toggleScreenshotCaptureSummary } from './react/features/screenshot-capt
|
||||
import { AudioMixerEffect } from './react/features/stream-effects/audio-mixer/AudioMixerEffect';
|
||||
import { createRnnoiseProcessor } from './react/features/stream-effects/rnnoise';
|
||||
import { handleToggleVideoMuted } from './react/features/toolbox/actions.any';
|
||||
import { transcriberJoined, transcriberLeft } from './react/features/transcribing/actions';
|
||||
import { muteLocal } from './react/features/video-menu/actions.any';
|
||||
|
||||
const logger = Logger.getLogger(__filename);
|
||||
|
||||
let room;
|
||||
|
||||
/*
|
||||
* Logic to open a desktop picker put on the window global for
|
||||
* lib-jitsi-meet to detect and invoke
|
||||
* lib-jitsi-meet to detect and invoke.
|
||||
*
|
||||
* TODO: remove once the Electron SDK supporting gDM has been out for a while.
|
||||
*/
|
||||
window.JitsiMeetScreenObtainer = {
|
||||
openDesktopPicker(options, onSourceChoose) {
|
||||
@@ -276,12 +279,6 @@ class ConferenceConnector {
|
||||
|
||||
switch (err) {
|
||||
|
||||
case JitsiConferenceErrors.NOT_ALLOWED_ERROR: {
|
||||
// let's show some auth not allowed page
|
||||
APP.store.dispatch(redirectToStaticPage('static/authError.html'));
|
||||
break;
|
||||
}
|
||||
|
||||
case JitsiConferenceErrors.RESERVATION_ERROR: {
|
||||
const [ code, msg ] = params;
|
||||
|
||||
@@ -292,7 +289,7 @@ class ConferenceConnector {
|
||||
},
|
||||
descriptionKey: 'dialog.reservationErrorMsg',
|
||||
titleKey: 'dialog.reservationError'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -300,7 +297,7 @@ class ConferenceConnector {
|
||||
APP.store.dispatch(showErrorNotification({
|
||||
descriptionKey: 'dialog.gracefulShutdown',
|
||||
titleKey: 'dialog.serviceUnavailable'
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}));
|
||||
break;
|
||||
|
||||
// FIXME FOCUS_DISCONNECTED is a confusing event name.
|
||||
@@ -391,27 +388,6 @@ function disconnect() {
|
||||
return APP.connection.disconnect().then(onDisconnected, onDisconnected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GUM pending state for the tracks that have failed.
|
||||
*
|
||||
* NOTE: Some of the track that we will be setting to GUM pending state NONE may not have failed but they may have
|
||||
* been requested. This won't be a problem because their current GUM pending state will be NONE anyway.
|
||||
* @param {JitsiLocalTrack} tracks - The tracks that have been created.
|
||||
* @returns {void}
|
||||
*/
|
||||
function setGUMPendingStateOnFailedTracks(tracks) {
|
||||
const tracksTypes = tracks.map(track => {
|
||||
if (track.getVideoType() === VIDEO_TYPE.DESKTOP) {
|
||||
return MEDIA_TYPE.SCREENSHARE;
|
||||
}
|
||||
|
||||
return track.getType();
|
||||
});
|
||||
const nonPendingTracks = [ MEDIA_TYPE.AUDIO, MEDIA_TYPE.VIDEO ].filter(type => !tracksTypes.includes(type));
|
||||
|
||||
APP.store.dispatch(gumPending(nonPendingTracks, IGUMPendingState.NONE));
|
||||
}
|
||||
|
||||
export default {
|
||||
/**
|
||||
* Flag used to delay modification of the muted status of local media tracks
|
||||
@@ -440,9 +416,10 @@ export default {
|
||||
* without any audio tracks.
|
||||
* @param {boolean} options.startWithVideoMuted - will start the conference
|
||||
* without any video tracks.
|
||||
* @param {boolean} recordTimeMetrics - If true time metrics will be recorded.
|
||||
* @returns {Promise<JitsiLocalTrack[]>, Object}
|
||||
*/
|
||||
createInitialLocalTracks(options = {}) {
|
||||
createInitialLocalTracks(options = {}, recordTimeMetrics = false) {
|
||||
const errors = {};
|
||||
|
||||
// Always get a handle on the audio input device so that we have statistics (such as "No audio input" or
|
||||
@@ -459,15 +436,6 @@ export default {
|
||||
requestedVideo = true;
|
||||
}
|
||||
|
||||
if (!config.disableInitialGUM) {
|
||||
JitsiMeetJS.mediaDevices.addEventListener(
|
||||
JitsiMediaDevicesEvents.PERMISSION_PROMPT_IS_SHOWN,
|
||||
browserName =>
|
||||
APP.store.dispatch(
|
||||
mediaPermissionPromptVisibilityChanged(true, browserName))
|
||||
);
|
||||
}
|
||||
|
||||
let tryCreateLocalTracks = Promise.resolve([]);
|
||||
|
||||
// On Electron there is no permission prompt for granting permissions. That's why we don't need to
|
||||
@@ -476,8 +444,7 @@ export default {
|
||||
const timeout = browser.isElectron() ? 15000 : 60000;
|
||||
const audioOptions = {
|
||||
devices: [ MEDIA_TYPE.AUDIO ],
|
||||
timeout,
|
||||
firePermissionPromptIsShownEvent: true
|
||||
timeout
|
||||
};
|
||||
|
||||
// Spot uses the _desktopSharingSourceDevice config option to use an external video input device label as
|
||||
@@ -510,113 +477,22 @@ export default {
|
||||
return [];
|
||||
});
|
||||
} else if (requestedAudio || requestedVideo) {
|
||||
APP.store.dispatch(gumPending(initialDevices, IGUMPendingState.PENDING_UNMUTE));
|
||||
tryCreateLocalTracks = createLocalTracksF({
|
||||
tryCreateLocalTracks = APP.store.dispatch(createInitialAVTracks({
|
||||
devices: initialDevices,
|
||||
timeout,
|
||||
firePermissionPromptIsShownEvent: true
|
||||
})
|
||||
.catch(async error => {
|
||||
if (error.name === JitsiTrackErrors.TIMEOUT && !browser.isElectron()) {
|
||||
errors.audioAndVideoError = error;
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// Retry with separate gUM calls.
|
||||
const gUMPromises = [];
|
||||
const tracks = [];
|
||||
|
||||
if (requestedAudio) {
|
||||
gUMPromises.push(createLocalTracksF(audioOptions));
|
||||
}
|
||||
|
||||
if (requestedVideo) {
|
||||
gUMPromises.push(createLocalTracksF({
|
||||
devices: [ MEDIA_TYPE.VIDEO ],
|
||||
timeout,
|
||||
firePermissionPromptIsShownEvent: true
|
||||
}));
|
||||
}
|
||||
|
||||
const results = await Promise.allSettled(gUMPromises);
|
||||
let errorMsg;
|
||||
|
||||
results.forEach((result, idx) => {
|
||||
if (result.status === 'fulfilled') {
|
||||
tracks.push(result.value[0]);
|
||||
} else {
|
||||
errorMsg = result.reason;
|
||||
const isAudio = idx === 0;
|
||||
|
||||
logger.error(`${isAudio ? 'Audio' : 'Video'} track creation failed with error ${errorMsg}`);
|
||||
if (isAudio) {
|
||||
errors.audioOnlyError = errorMsg;
|
||||
} else {
|
||||
errors.videoOnlyError = errorMsg;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.audioOnlyError && errors.videoOnlyError) {
|
||||
errors.audioAndVideoError = errorMsg;
|
||||
}
|
||||
timeout
|
||||
}, recordTimeMetrics)).then(({ tracks, errors: pErrors }) => {
|
||||
Object.assign(errors, pErrors);
|
||||
|
||||
return tracks;
|
||||
});
|
||||
}
|
||||
|
||||
// Hide the permissions prompt/overlay as soon as the tracks are created. Don't wait for the connection to
|
||||
// be established, as in some cases like when auth is required, connection won't be established until the user
|
||||
// inputs their credentials, but the dialog would be overshadowed by the overlay.
|
||||
tryCreateLocalTracks.then(tracks => {
|
||||
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
|
||||
|
||||
return tracks;
|
||||
});
|
||||
|
||||
return {
|
||||
tryCreateLocalTracks,
|
||||
errors
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays error notifications according to the state carried by {@code errors} object returned
|
||||
* by {@link createInitialLocalTracks}.
|
||||
* @param {Object} errors - the errors (if any) returned by {@link createInitialLocalTracks}.
|
||||
*
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
_displayErrorsForCreateInitialLocalTracks(errors) {
|
||||
const {
|
||||
audioAndVideoError,
|
||||
audioOnlyError,
|
||||
screenSharingError,
|
||||
videoOnlyError
|
||||
} = errors;
|
||||
|
||||
// FIXME If there will be microphone error it will cover any screensharing dialog, but it's still better than in
|
||||
// the reverse order where the screensharing dialog will sometimes be closing the microphone alert
|
||||
// ($.prompt.close(); is called). Need to figure out dialogs chaining to fix that.
|
||||
if (screenSharingError) {
|
||||
this._handleScreenSharingError(screenSharingError);
|
||||
}
|
||||
if (audioAndVideoError || audioOnlyError) {
|
||||
if (audioOnlyError || videoOnlyError) {
|
||||
// If both requests for 'audio' + 'video' and 'audio' only failed, we assume that there are some
|
||||
// problems with user's microphone and show corresponding dialog.
|
||||
APP.store.dispatch(notifyMicError(audioOnlyError));
|
||||
APP.store.dispatch(notifyCameraError(videoOnlyError));
|
||||
} else {
|
||||
// If request for 'audio' + 'video' failed, but request for 'audio' only was OK, we assume that we had
|
||||
// problems with camera and show corresponding dialog.
|
||||
APP.store.dispatch(notifyCameraError(audioAndVideoError));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
startConference(tracks) {
|
||||
tracks.forEach(track => {
|
||||
if ((track.isAudioTrack() && this.isLocalAudioMuted())
|
||||
@@ -668,10 +544,10 @@ export default {
|
||||
* If prejoin page is enabled open an new connection in the background
|
||||
* and create local tracks.
|
||||
*
|
||||
* @param {{ roomName: string }} options
|
||||
* @param {{ roomName: string, shouldDispatchConnect }} options
|
||||
* @returns {Promise}
|
||||
*/
|
||||
async init({ roomName }) {
|
||||
async init({ roomName, shouldDispatchConnect }) {
|
||||
const state = APP.store.getState();
|
||||
const initialOptions = {
|
||||
startAudioOnly: config.startAudioOnly,
|
||||
@@ -679,8 +555,12 @@ export default {
|
||||
startWithAudioMuted: getStartWithAudioMuted(state) || isUserInteractionRequiredForUnmute(state),
|
||||
startWithVideoMuted: getStartWithVideoMuted(state) || isUserInteractionRequiredForUnmute(state)
|
||||
};
|
||||
const connectionTimes = getJitsiMeetGlobalNSConnectionTimes();
|
||||
const startTime = window.performance.now();
|
||||
|
||||
logger.debug(`Executed conference.init with roomName: ${roomName}`);
|
||||
connectionTimes['conference.init.start'] = startTime;
|
||||
|
||||
logger.debug(`Executed conference.init with roomName: ${roomName} (performance.now=${startTime})`);
|
||||
|
||||
this.roomName = roomName;
|
||||
|
||||
@@ -700,7 +580,7 @@ export default {
|
||||
const handleInitialTracks = (options, tracks) => {
|
||||
let localTracks = tracks;
|
||||
|
||||
if (options.startWithAudioMuted || room?.isStartAudioMuted()) {
|
||||
if (options.startWithAudioMuted) {
|
||||
// Always add the track on Safari because of a known issue where audio playout doesn't happen
|
||||
// if the user joins audio and video muted, i.e., if there is no local media capture.
|
||||
if (browser.isWebKitBased()) {
|
||||
@@ -709,58 +589,71 @@ export default {
|
||||
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.AUDIO);
|
||||
}
|
||||
}
|
||||
if (room?.isStartVideoMuted()) {
|
||||
localTracks = localTracks.filter(track => track.getType() !== MEDIA_TYPE.VIDEO);
|
||||
}
|
||||
|
||||
return localTracks;
|
||||
};
|
||||
const { dispatch, getState } = APP.store;
|
||||
const createLocalTracksStart = window.performance.now();
|
||||
|
||||
if (isPrejoinPageVisible(state)) {
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
|
||||
const localTracks = await tryCreateLocalTracks;
|
||||
connectionTimes['conference.init.createLocalTracks.start'] = createLocalTracksStart;
|
||||
|
||||
logger.debug(`(TIME) createInitialLocalTracks: ${createLocalTracksStart} `);
|
||||
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions, true);
|
||||
|
||||
tryCreateLocalTracks.then(tr => {
|
||||
const createLocalTracksEnd = window.performance.now();
|
||||
|
||||
connectionTimes['conference.init.createLocalTracks.end'] = createLocalTracksEnd;
|
||||
logger.debug(`(TIME) createInitialLocalTracks finished: ${createLocalTracksEnd} `);
|
||||
const tracks = handleInitialTracks(initialOptions, tr);
|
||||
|
||||
// Initialize device list a second time to ensure device labels get populated in case of an initial gUM
|
||||
// acceptance; otherwise they may remain as empty strings.
|
||||
this._initDeviceList(true);
|
||||
|
||||
if (isPrejoinPageVisible(state)) {
|
||||
APP.store.dispatch(gumPending([ MEDIA_TYPE.AUDIO, MEDIA_TYPE.VIDEO ], IGUMPendingState.NONE));
|
||||
const { initialGUMPromise } = getState()['features/base/media'];
|
||||
|
||||
return APP.store.dispatch(initPrejoin(localTracks, errors));
|
||||
if (isPrejoinPageVisible(getState())) {
|
||||
dispatch(gumPending([ MEDIA_TYPE.AUDIO, MEDIA_TYPE.VIDEO ], IGUMPendingState.NONE));
|
||||
|
||||
// Since the conference is not yet created in redux this function will execute synchronous
|
||||
// which will guarantee us that the local tracks are added to redux before we proceed.
|
||||
initPrejoin(tracks, errors, dispatch);
|
||||
|
||||
connectionTimes['conference.init.end'] = window.performance.now();
|
||||
|
||||
// resolve the initialGUMPromise in case connect have finished so that we can proceed to join.
|
||||
if (initialGUMPromise) {
|
||||
logger.debug('Resolving the initialGUM promise! (prejoinVisible=true)');
|
||||
initialGUMPromise.resolve({
|
||||
tracks,
|
||||
errors
|
||||
});
|
||||
}
|
||||
|
||||
logger.debug('Clear the initialGUM promise! (prejoinVisible=true)');
|
||||
|
||||
// For prejoin we don't need the initial GUM promise since the tracks are already added to the store
|
||||
// via initPrejoin
|
||||
dispatch(setInitialGUMPromise());
|
||||
} else {
|
||||
APP.store.dispatch(displayErrorsForCreateInitialLocalTracks(errors));
|
||||
setGUMPendingStateOnFailedTracks(tracks, APP.store.dispatch);
|
||||
|
||||
connectionTimes['conference.init.end'] = window.performance.now();
|
||||
if (initialGUMPromise) {
|
||||
logger.debug('Resolving the initialGUM promise!');
|
||||
initialGUMPromise.resolve({
|
||||
tracks,
|
||||
errors
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug('Prejoin screen no longer displayed at the time when tracks were created');
|
||||
|
||||
this._displayErrorsForCreateInitialLocalTracks(errors);
|
||||
|
||||
const tracks = handleInitialTracks(initialOptions, localTracks);
|
||||
|
||||
setGUMPendingStateOnFailedTracks(tracks);
|
||||
|
||||
return this._setLocalAudioVideoStreams(tracks);
|
||||
}
|
||||
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(initialOptions);
|
||||
|
||||
return Promise.all([
|
||||
tryCreateLocalTracks.then(tr => {
|
||||
this._displayErrorsForCreateInitialLocalTracks(errors);
|
||||
|
||||
return tr;
|
||||
}).then(tr => {
|
||||
this._initDeviceList(true);
|
||||
|
||||
const filteredTracks = handleInitialTracks(initialOptions, tr);
|
||||
|
||||
setGUMPendingStateOnFailedTracks(filteredTracks);
|
||||
|
||||
return filteredTracks;
|
||||
}),
|
||||
APP.store.dispatch(connect())
|
||||
]).then(([ tracks, _ ]) => {
|
||||
this.startConference(tracks).catch(logger.error);
|
||||
});
|
||||
|
||||
if (shouldDispatchConnect) {
|
||||
logger.info('Dispatching connect from init since prejoin is not visible.');
|
||||
dispatch(connect());
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -814,11 +707,13 @@ export default {
|
||||
|
||||
/**
|
||||
* Simulates toolbar button click for audio mute. Used by shortcuts and API.
|
||||
*
|
||||
* @param {boolean} mute true for mute and false for unmute.
|
||||
* @param {boolean} [showUI] when set to false will not display any error
|
||||
* dialogs in case of media permissions error.
|
||||
* @returns {Promise}
|
||||
*/
|
||||
muteAudio(mute, showUI = true) {
|
||||
async muteAudio(mute, showUI = true) {
|
||||
const state = APP.store.getState();
|
||||
|
||||
if (!mute
|
||||
@@ -858,7 +753,8 @@ export default {
|
||||
};
|
||||
|
||||
APP.store.dispatch(gumPending([ MEDIA_TYPE.AUDIO ], IGUMPendingState.PENDING_UNMUTE));
|
||||
createLocalTracksF({ devices: [ 'audio' ] })
|
||||
|
||||
await createLocalTracksF({ devices: [ 'audio' ] })
|
||||
.then(([ audioTrack ]) => audioTrack)
|
||||
.catch(error => {
|
||||
maybeShowErrorDialog(error);
|
||||
@@ -1118,7 +1014,7 @@ export default {
|
||||
},
|
||||
|
||||
/**
|
||||
* Will be filled with values only when config.debug is enabled.
|
||||
* Will be filled with values only when config.testing.testMode is true.
|
||||
* Its used by torture to check audio levels.
|
||||
*/
|
||||
audioLevelsMap: {},
|
||||
@@ -1164,6 +1060,14 @@ export default {
|
||||
downloadJSON(logs, filename);
|
||||
},
|
||||
|
||||
/**
|
||||
* Download app state, a function that can be called from console while debugging.
|
||||
* @param filename (optional) specify target filename
|
||||
*/
|
||||
saveState(filename = 'meet-state.json') {
|
||||
downloadJSON(APP.store.getState(), filename);
|
||||
},
|
||||
|
||||
/**
|
||||
* Exposes a Command(s) API on this instance. It is necessitated by (1) the
|
||||
* desire to keep room private to this instance and (2) the need of other
|
||||
@@ -1234,7 +1138,7 @@ export default {
|
||||
const { tryCreateLocalTracks, errors } = this.createInitialLocalTracks(options);
|
||||
const localTracks = await tryCreateLocalTracks;
|
||||
|
||||
this._displayErrorsForCreateInitialLocalTracks(errors);
|
||||
APP.store.dispatch(displayErrorsForCreateInitialLocalTracks(errors));
|
||||
localTracks.forEach(track => {
|
||||
if ((track.isAudioTrack() && this.isLocalAudioMuted())
|
||||
|| (track.isVideoTrack() && this.isLocalVideoMuted())) {
|
||||
@@ -1271,11 +1175,12 @@ export default {
|
||||
APP.store.dispatch(gumPending(mutedTrackTypes, IGUMPendingState.NONE));
|
||||
}
|
||||
|
||||
this._setLocalAudioVideoStreams(tracks);
|
||||
this._room = room; // FIXME do not use this
|
||||
|
||||
APP.store.dispatch(_conferenceWillJoin(room));
|
||||
|
||||
this._setLocalAudioVideoStreams(tracks);
|
||||
|
||||
sendLocalParticipant(APP.store, room);
|
||||
|
||||
this._setupListeners();
|
||||
@@ -1386,8 +1291,7 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
APP.store.dispatch(
|
||||
replaceLocalTrack(oldTrack, newTrack, room))
|
||||
APP.store.dispatch(replaceLocalTrack(oldTrack, newTrack, room))
|
||||
.then(() => {
|
||||
this.updateAudioIconEnabled();
|
||||
})
|
||||
@@ -1505,28 +1409,19 @@ export default {
|
||||
/**
|
||||
* Creates desktop (screensharing) {@link JitsiLocalTrack}
|
||||
*
|
||||
* @param {Object} [options] - Screen sharing options that will be passed to
|
||||
* createLocalTracks.
|
||||
* @param {Object} [options.desktopSharing]
|
||||
* @param {Object} [options.desktopStream] - An existing desktop stream to
|
||||
* use instead of creating a new desktop stream.
|
||||
* @return {Promise.<JitsiLocalTrack>} - A Promise resolved with
|
||||
* {@link JitsiLocalTrack} for the screensharing or rejected with
|
||||
* {@link JitsiTrackError}.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_createDesktopTrack(options = {}) {
|
||||
_createDesktopTrack() {
|
||||
const didHaveVideo = !this.isLocalVideoMuted();
|
||||
|
||||
const getDesktopStreamPromise = options.desktopStream
|
||||
? Promise.resolve([ options.desktopStream ])
|
||||
: createLocalTracksF({
|
||||
desktopSharingSourceDevice: options.desktopSharingSources
|
||||
? null : config._desktopSharingSourceDevice,
|
||||
desktopSharingSources: options.desktopSharingSources,
|
||||
devices: [ 'desktop' ]
|
||||
});
|
||||
const getDesktopStreamPromise = createLocalTracksF({
|
||||
desktopSharingSourceDevice: config._desktopSharingSourceDevice,
|
||||
devices: [ 'desktop' ]
|
||||
});
|
||||
|
||||
return getDesktopStreamPromise.then(desktopStreams => {
|
||||
// Stores the "untoggle" handler which remembers whether was
|
||||
@@ -1574,50 +1469,6 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles {@link JitsiTrackError} returned by the lib-jitsi-meet when
|
||||
* trying to create screensharing track. It will either do nothing if
|
||||
* the dialog was canceled on user's request or display an error if
|
||||
* screensharing couldn't be started.
|
||||
* @param {JitsiTrackError} error - The error returned by
|
||||
* {@link _createDesktopTrack} Promise.
|
||||
* @private
|
||||
*/
|
||||
_handleScreenSharingError(error) {
|
||||
if (error.name === JitsiTrackErrors.SCREENSHARING_USER_CANCELED) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.error('failed to share local desktop', error);
|
||||
|
||||
// Handling:
|
||||
// JitsiTrackErrors.CONSTRAINT_FAILED
|
||||
// JitsiTrackErrors.PERMISSION_DENIED
|
||||
// JitsiTrackErrors.SCREENSHARING_GENERIC_ERROR
|
||||
// and any other
|
||||
let descriptionKey;
|
||||
let titleKey;
|
||||
|
||||
if (error.name === JitsiTrackErrors.PERMISSION_DENIED) {
|
||||
descriptionKey = 'dialog.screenSharingPermissionDeniedError';
|
||||
titleKey = 'dialog.screenSharingFailedTitle';
|
||||
} else if (error.name === JitsiTrackErrors.CONSTRAINT_FAILED) {
|
||||
descriptionKey = 'dialog.cameraConstraintFailedError';
|
||||
titleKey = 'deviceError.cameraError';
|
||||
} else if (error.name === JitsiTrackErrors.SCREENSHARING_GENERIC_ERROR) {
|
||||
descriptionKey = 'dialog.screenSharingFailed';
|
||||
titleKey = 'dialog.screenSharingFailedTitle';
|
||||
} else if (error === AUDIO_ONLY_SCREEN_SHARE_NO_TRACK) {
|
||||
descriptionKey = 'notify.screenShareNoAudio';
|
||||
titleKey = 'notify.screenShareNoAudioTitle';
|
||||
}
|
||||
|
||||
APP.store.dispatch(showErrorNotification({
|
||||
descriptionKey,
|
||||
titleKey
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup interaction between conference and UI.
|
||||
*/
|
||||
@@ -1705,7 +1556,6 @@ export default {
|
||||
}
|
||||
|
||||
APP.store.dispatch(localParticipantRoleChanged(role));
|
||||
APP.API.notifyUserRoleChanged(id, role);
|
||||
} else {
|
||||
APP.store.dispatch(participantRoleChanged(id, role));
|
||||
}
|
||||
@@ -1747,9 +1597,9 @@ export default {
|
||||
newLvl = 0;
|
||||
}
|
||||
|
||||
if (config.debug) {
|
||||
if (config.testing?.testMode) {
|
||||
this.audioLevelsMap[id] = newLvl;
|
||||
if (config.debugAudioLevels) {
|
||||
if (config.testing?.debugAudioLevels) {
|
||||
logger.log(`AudioLevel:${id}/${newLvl}`);
|
||||
}
|
||||
}
|
||||
@@ -1790,7 +1640,11 @@ export default {
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.CONFERENCE_CREATED_TIMESTAMP,
|
||||
conferenceTimestamp => APP.store.dispatch(conferenceTimestampChanged(conferenceTimestamp)));
|
||||
conferenceTimestamp => {
|
||||
APP.store.dispatch(conferenceTimestampChanged(conferenceTimestamp));
|
||||
APP.API.notifyConferenceCreatedTimestamp(conferenceTimestamp);
|
||||
}
|
||||
);
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.DISPLAY_NAME_CHANGED,
|
||||
@@ -1825,6 +1679,18 @@ export default {
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.SILENT_STATUS_CHANGED,
|
||||
(id, isSilent) => {
|
||||
APP.store.dispatch(participantUpdated({
|
||||
conference: room,
|
||||
id,
|
||||
isSilent
|
||||
}));
|
||||
}
|
||||
);
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.BOT_TYPE_CHANGED,
|
||||
(id, botType) => {
|
||||
@@ -1837,6 +1703,16 @@ export default {
|
||||
}
|
||||
);
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.TRANSCRIPTION_STATUS_CHANGED,
|
||||
(status, id, abruptly) => {
|
||||
if (status === JitsiMeetJS.constants.transcriptionStatus.ON) {
|
||||
APP.store.dispatch(transcriberJoined(id));
|
||||
} else if (status === JitsiMeetJS.constants.transcriptionStatus.OFF) {
|
||||
APP.store.dispatch(transcriberLeft(id, abruptly));
|
||||
}
|
||||
});
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.ENDPOINT_MESSAGE_RECEIVED,
|
||||
(participant, data) => {
|
||||
@@ -1863,6 +1739,10 @@ export default {
|
||||
JitsiConferenceEvents.LOCK_STATE_CHANGED,
|
||||
(...args) => APP.store.dispatch(lockStateChanged(room, ...args)));
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.PROPERTIES_CHANGED,
|
||||
properties => APP.store.dispatch(conferencePropertiesChanged(properties)));
|
||||
|
||||
room.on(JitsiConferenceEvents.KICKED, (participant, reason, isReplaced) => {
|
||||
if (isReplaced) {
|
||||
// this event triggers when the local participant is kicked, `participant`
|
||||
@@ -1929,12 +1809,17 @@ export default {
|
||||
room.addCommandListener(
|
||||
this.commands.defaults.AVATAR_URL,
|
||||
(data, from) => {
|
||||
APP.store.dispatch(
|
||||
participantUpdated({
|
||||
conference: room,
|
||||
id: from,
|
||||
avatarURL: data.value
|
||||
}));
|
||||
const participant = getParticipantByIdOrUndefined(APP.store, from);
|
||||
|
||||
// if already set from presence(jwt), skip the command processing
|
||||
if (!participant?.avatarURL) {
|
||||
APP.store.dispatch(
|
||||
participantUpdated({
|
||||
conference: room,
|
||||
id: from,
|
||||
avatarURL: data.value
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
room.on(
|
||||
@@ -1983,14 +1868,43 @@ export default {
|
||||
|
||||
room.on(
|
||||
JitsiConferenceEvents.DATA_CHANNEL_CLOSED, ev => {
|
||||
APP.store.dispatch(dataChannelClosed(ev.code, ev.reason));
|
||||
APP.store.dispatch(showWarningNotification({
|
||||
descriptionKey: 'notify.dataChannelClosedDescription',
|
||||
titleKey: 'notify.dataChannelClosed',
|
||||
uid: DATA_CHANNEL_CLOSED_NOTIFICATION_ID
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||
const state = APP.store.getState();
|
||||
const { dataChannelOpen } = state['features/base/conference'];
|
||||
const timeout = typeof dataChannelOpen === 'undefined' ? 15000 : 60000;
|
||||
|
||||
// Show the notification only when the data channel connection doesn't get re-established in 60 secs if
|
||||
// it was already established at the beginning of the call, show it sooner otherwise. This notification
|
||||
// can be confusing and alarming to users even when there is no significant impact to user experience
|
||||
// if the the reconnect happens immediately.
|
||||
setTimeout(() => {
|
||||
const { dataChannelOpen: open } = APP.store.getState()['features/base/conference'];
|
||||
|
||||
if (!open) {
|
||||
const descriptionKey = getSsrcRewritingFeatureFlag(state)
|
||||
? 'notify.dataChannelClosedDescriptionWithAudio' : 'notify.dataChannelClosedDescription';
|
||||
const titleKey = getSsrcRewritingFeatureFlag(state)
|
||||
? 'notify.dataChannelClosedWithAudio' : 'notify.dataChannelClosed';
|
||||
|
||||
APP.store.dispatch(dataChannelClosed(ev.code, ev.reason));
|
||||
APP.store.dispatch(showWarningNotification({
|
||||
descriptionKey,
|
||||
titleKey,
|
||||
uid: DATA_CHANNEL_CLOSED_NOTIFICATION_ID
|
||||
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||
}
|
||||
}, timeout);
|
||||
}
|
||||
);
|
||||
|
||||
room.on(JitsiConferenceEvents.PERMISSIONS_RECEIVED, p => {
|
||||
const localParticipant = getLocalParticipant(APP.store.getState());
|
||||
|
||||
APP.store.dispatch(participantUpdated({
|
||||
id: localParticipant.id,
|
||||
local: true,
|
||||
features: p
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -2134,7 +2048,6 @@ export default {
|
||||
|
||||
APP.UI.initConference();
|
||||
|
||||
dispatch(initKeyboardShortcuts());
|
||||
dispatch(conferenceJoined(room));
|
||||
|
||||
const jwt = APP.store.getState()['features/base/jwt'];
|
||||
@@ -2169,8 +2082,9 @@ export default {
|
||||
const { dispatch } = APP.store;
|
||||
|
||||
return dispatch(getAvailableDevices())
|
||||
.then(devices => {
|
||||
APP.UI.onAvailableDevicesChanged(devices);
|
||||
.then(() => {
|
||||
this.updateAudioIconEnabled();
|
||||
this.updateVideoIconEnabled();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2335,7 +2249,8 @@ export default {
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(() => {
|
||||
APP.UI.onAvailableDevicesChanged(filteredDevices);
|
||||
this.updateAudioIconEnabled();
|
||||
this.updateVideoIconEnabled();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -2380,8 +2295,10 @@ export default {
|
||||
* @param {boolean} [requestFeedback=false] if user feedback should be
|
||||
* @param {string} [hangupReason] the reason for leaving the meeting
|
||||
* requested
|
||||
* @param {boolean} [notifyOnConferenceTermination] whether to notify
|
||||
* the user on conference termination
|
||||
*/
|
||||
hangup(requestFeedback = false, hangupReason) {
|
||||
hangup(requestFeedback = false, hangupReason, notifyOnConferenceTermination) {
|
||||
APP.store.dispatch(disableReceiver());
|
||||
|
||||
this._stopProxyConnection();
|
||||
@@ -2400,7 +2317,7 @@ export default {
|
||||
|
||||
if (requestFeedback) {
|
||||
const feedbackDialogClosed = (feedbackResult = {}) => {
|
||||
if (!feedbackResult.wasDialogShown && hangupReason) {
|
||||
if (!feedbackResult.wasDialogShown && hangupReason && notifyOnConferenceTermination) {
|
||||
return APP.store.dispatch(
|
||||
openLeaveReasonDialog(hangupReason)).then(() => feedbackResult);
|
||||
}
|
||||
|
||||
312
config.js
312
config.js
@@ -49,7 +49,9 @@ var config = {
|
||||
bosh: 'https://jitsi-meet.example.com/' + subdir + 'http-bind',
|
||||
|
||||
// Websocket URL (XMPP)
|
||||
// websocket: 'wss://jitsi-meet.example.com/' + subdir + 'xmpp-websocket',
|
||||
websocket: 'wss://jitsi-meet.example.com/' + subdir + 'xmpp-websocket',
|
||||
|
||||
// websocketKeepAliveUrl: 'https://jitsi-meet.example.com/' + subdir + '_unlock',
|
||||
|
||||
// Whether BOSH should be preferred over WebSocket if both are configured.
|
||||
// preferBosh: false,
|
||||
@@ -84,15 +86,14 @@ var config = {
|
||||
// Allows the setting of a custom bandwidth value from the UI.
|
||||
// assumeBandwidth: true,
|
||||
|
||||
// Disables the End to End Encryption feature. Useful for debugging
|
||||
// issues related to insertable streams.
|
||||
// disableE2EE: false,
|
||||
// Enables use of getDisplayMedia in electron
|
||||
// electronUseGetDisplayMedia: false,
|
||||
|
||||
// Enables supports for AV1 codec.
|
||||
// enableAv1Support: false,
|
||||
// Enables AV1 codec for FF. Note: By default it is disabled.
|
||||
// enableAV1ForFF: false,
|
||||
|
||||
// Enables XMPP WebSocket (as opposed to BOSH) for the given amount of users.
|
||||
// mobileXmppWsThreshold: 10, // enable XMPP WebSockets on mobile for 10% of the users
|
||||
// Enables the use of the codec selection API supported by the browsers .
|
||||
// enableCodecSelectionAPI: false,
|
||||
|
||||
// P2P test mode disables automatic switching to P2P when there are 2
|
||||
// participants in the conference.
|
||||
@@ -110,6 +111,12 @@ var config = {
|
||||
|
||||
// Dump transcripts to a <transcript> element for debugging.
|
||||
// dumpTranscript: false,
|
||||
|
||||
// Log the audio levels.
|
||||
// debugAudioLevels: true,
|
||||
|
||||
// Will replace ice candidates IPs with invalid ones in order to fail ice.
|
||||
// failICE: true,
|
||||
},
|
||||
|
||||
// Disables moderator indicators.
|
||||
@@ -124,6 +131,9 @@ var config = {
|
||||
// Disables polls feature.
|
||||
// disablePolls: false,
|
||||
|
||||
// Disables demote button from self-view
|
||||
// disableSelfDemote: false,
|
||||
|
||||
// Disables self-view tile. (hides it from tile view and from filmstrip)
|
||||
// disableSelfView: false,
|
||||
|
||||
@@ -213,14 +223,45 @@ var config = {
|
||||
// installation. Specifically, these files are needed:
|
||||
// - https://meet.example.com/libs/krisp/krisp.mjs
|
||||
// - https://meet.example.com/libs/krisp/models/model_8.kw
|
||||
// - https://meet.example.com/libs/krisp/models/model_16.kw
|
||||
// - https://meet.example.com/libs/krisp/models/model_32.kw
|
||||
// NOTE: Krisp JS SDK v1.0.9 was tested.
|
||||
// - https://meet.example.com/libs/krisp/models/model_nc.kw
|
||||
// - https://meet.example.com/libs/krisp/models/model_bvc.kw
|
||||
// - https://meet.example.com/libs/krisp/assets/bvc-allowed.txt
|
||||
// In case when you have known BVC supported devices and you want to extend allowed devices list
|
||||
// - https://meet.example.com/libs/krisp/assets/bvc-allowed-ext.txt
|
||||
// In case when you have known BVC supported devices and you want to extend allowed devices list
|
||||
// - https://meet.example.com/libs/krisp/models/model_inbound_8.kw
|
||||
// - https://meet.example.com/libs/krisp/models/model_inbound_16.kw
|
||||
// In case when you want to use inbound noise suppression models
|
||||
// NOTE: Krisp JS SDK v2.0.0 was tested.
|
||||
// noiseSuppression: {
|
||||
// krisp: {
|
||||
// enabled: false,
|
||||
// logProcessStats: false,
|
||||
// debugLogs: false,
|
||||
// useBVC: false,
|
||||
// bufferOverflowMS: 1000,
|
||||
// inboundModels: {
|
||||
// modelInbound8: 'model_inbound_8.kef',
|
||||
// modelInbound16: 'model_inbound_16.kef',
|
||||
// },
|
||||
// preloadInboundModels: {
|
||||
// modelInbound8: 'model_inbound_8.kef',
|
||||
// modelInbound16: 'model_inbound_16.kef',
|
||||
// },
|
||||
// preloadModels: {
|
||||
// modelBVC: 'model_bvc.kef',
|
||||
// model8: 'model_8.kef',
|
||||
// modelNC: 'model_nc_mq.kef',
|
||||
// },
|
||||
// models: {
|
||||
// modelBVC: 'model_bvc.kef',
|
||||
// model8: 'model_8.kef',
|
||||
// modelNV: 'model_nc_mq.kef',
|
||||
// },
|
||||
// bvc: {
|
||||
// allowedDevices: 'bvc-allowed.txt',
|
||||
// allowedDevicesExt: 'bvc-allowed-ext.txt',
|
||||
// }
|
||||
// },
|
||||
// },
|
||||
|
||||
@@ -232,9 +273,26 @@ var config = {
|
||||
// Sets the preferred resolution (height) for local video. Defaults to 720.
|
||||
// resolution: 720,
|
||||
|
||||
// DEPRECATED. Please use raisedHands.disableRemoveRaisedHandOnFocus instead.
|
||||
// Specifies whether the raised hand will hide when someone becomes a dominant speaker or not
|
||||
// disableRemoveRaisedHandOnFocus: false,
|
||||
|
||||
// Specifies which raised hand related config should be set.
|
||||
// raisedHands: {
|
||||
// // Specifies whether the raised hand can be lowered by moderator.
|
||||
// disableLowerHandByModerator: false,
|
||||
|
||||
// // Specifies whether there is a notification before hiding the raised hand
|
||||
// // when someone becomes the dominant speaker.
|
||||
// disableLowerHandNotification: true,
|
||||
|
||||
// // Specifies whether there is a notification when you are the next speaker in line.
|
||||
// disableNextSpeakerNotification: false,
|
||||
|
||||
// // Specifies whether the raised hand will hide when someone becomes a dominant speaker or not.
|
||||
// disableRemoveRaisedHandOnFocus: false,
|
||||
// },
|
||||
|
||||
// speakerStats: {
|
||||
// // Specifies whether the speaker stats is enable or not.
|
||||
// disabled: false,
|
||||
@@ -318,9 +376,6 @@ var config = {
|
||||
|
||||
// Recording
|
||||
|
||||
// DEPRECATED. Use recordingService.enabled instead.
|
||||
// fileRecordingsEnabled: false,
|
||||
|
||||
// Enable the dropbox integration.
|
||||
// dropbox: {
|
||||
// appKey: '<APP_KEY>', // Specify your app key here.
|
||||
@@ -341,6 +396,11 @@ var config = {
|
||||
// // If true, shows a warning label in the prejoin screen to point out the possibility that
|
||||
// // the call you're joining might be recorded.
|
||||
// // showPrejoinWarning: true,
|
||||
// // If true, the notification for recording start will display a link to download the cloud recording.
|
||||
// // showRecordingLink: true,
|
||||
// // If true, mutes audio and video when a recording begins and displays a dialog
|
||||
// // explaining the effect of unmuting.
|
||||
// // requireConsent: true,
|
||||
// },
|
||||
|
||||
// recordingService: {
|
||||
@@ -413,7 +473,7 @@ var config = {
|
||||
|
||||
// // Translation languages.
|
||||
// // Available languages can be found in
|
||||
// // ./src/react/features/transcribing/translation-languages.json.
|
||||
// // ./lang/translation-languages.json.
|
||||
// translationLanguages: ['en', 'es', 'fr', 'ro'],
|
||||
|
||||
// // Important languages to show on the top of the language list.
|
||||
@@ -434,6 +494,10 @@ var config = {
|
||||
|
||||
// // Enables automatic turning on transcribing when recording is started
|
||||
// autoTranscribeOnRecord: false,
|
||||
|
||||
// // Enables automatic request of subtitles when transcriber is present in the meeting, uses the default
|
||||
// // language that is set
|
||||
// autoCaptionOnTranscribe: false,
|
||||
// },
|
||||
|
||||
// Misc
|
||||
@@ -459,7 +523,16 @@ var config = {
|
||||
// videoQuality: {
|
||||
//
|
||||
// // Provides a way to set the codec preference on desktop based endpoints.
|
||||
// codecPreferenceOrder: [ 'VP9', 'VP8', 'H264' ],
|
||||
// codecPreferenceOrder: [ 'AV1', 'VP9', 'VP8', 'H264' ],
|
||||
//
|
||||
// // Provides a way to set the codec for screenshare.
|
||||
// screenshareCodec: 'AV1',
|
||||
// mobileScreenshareCodec: 'VP8',
|
||||
//
|
||||
// // Enables the adaptive mode in the client that will make runtime adjustments to selected codecs and received
|
||||
// // videos for a better user experience. This mode will kick in only when CPU overuse is reported in the
|
||||
// // WebRTC statistics for the outbound video streams.
|
||||
// enableAdaptiveMode: false,
|
||||
//
|
||||
// // Codec specific settings for scalability modes and max bitrates.
|
||||
// av1: {
|
||||
@@ -509,30 +582,6 @@ var config = {
|
||||
// scalabilityModeEnabled: true,
|
||||
// useSimulcast: false,
|
||||
// useKSVC: true
|
||||
// }
|
||||
//
|
||||
// DEPRECATED! Use `codec specific settings` instead.
|
||||
// // Provides a way to configure the maximum bitrates that will be enforced on the simulcast streams for
|
||||
// // video tracks. The keys in the object represent the type of the stream (LD, SD or HD) and the values
|
||||
// // are the max.bitrates to be set on that particular type of stream. The actual send may vary based on
|
||||
// // the available bandwidth calculated by the browser, but it will be capped by the values specified here.
|
||||
// // This is currently not implemented on app based clients on mobile.
|
||||
// maxBitratesVideo: {
|
||||
// H264: {
|
||||
// low: 200000,
|
||||
// standard: 500000,
|
||||
// high: 1500000,
|
||||
// },
|
||||
// VP8 : {
|
||||
// low: 200000,
|
||||
// standard: 500000,
|
||||
// high: 1500000,
|
||||
// },
|
||||
// VP9: {
|
||||
// low: 100000,
|
||||
// standard: 300000,
|
||||
// high: 1200000,
|
||||
// },
|
||||
// },
|
||||
//
|
||||
// // The options can be used to override default thresholds of video thumbnail heights corresponding to
|
||||
@@ -551,23 +600,7 @@ var config = {
|
||||
// },
|
||||
//
|
||||
// // Provides a way to set the codec preference on mobile devices, both on RN and mobile browser based endpoint
|
||||
// mobileCodecPreferenceOrder: [ 'VP8', 'VP9', 'H264' ],
|
||||
//
|
||||
// // DEPRECATED! Use `codecPreferenceOrder/mobileCodecPreferenceOrder` instead.
|
||||
// // Provides a way to prevent a video codec from being negotiated on the JVB connection. The codec specified
|
||||
// // here will be removed from the list of codecs present in the SDP answer generated by the client. If the
|
||||
// // same codec is specified for both the disabled and preferred option, the disable settings will prevail.
|
||||
// // Note that 'VP8' cannot be disabled since it's a mandatory codec, the setting will be ignored in this case.
|
||||
// disabledCodec: 'H264',
|
||||
//
|
||||
// // DEPRECATED! Use `codecPreferenceOrder/mobileCodecPreferenceOrder` instead.
|
||||
// // Provides a way to set a preferred video codec for the JVB connection. If 'H264' is specified here,
|
||||
// // simulcast will be automatically disabled since JVB doesn't support H264 simulcast yet. This will only
|
||||
// // rearrange the the preference order of the codecs in the SDP answer generated by the browser only if the
|
||||
// // preferred codec specified here is present. Please ensure that the JVB offers the specified codec for this
|
||||
// // to take effect.
|
||||
// preferredCodec: 'VP8',
|
||||
//
|
||||
// mobileCodecPreferenceOrder: [ 'VP8', 'VP9', 'H264', 'AV1' ],
|
||||
// },
|
||||
|
||||
// Notification timeouts
|
||||
@@ -575,6 +608,7 @@ var config = {
|
||||
// short: 2500,
|
||||
// medium: 5000,
|
||||
// long: 10000,
|
||||
// extraLong: 60000,
|
||||
// },
|
||||
|
||||
// // Options for the recording limit notification.
|
||||
@@ -604,14 +638,6 @@ var config = {
|
||||
// Disables or enables REMB support in this client (default: enabled).
|
||||
// enableRemb: true,
|
||||
|
||||
// Enables ICE restart logic in LJM and displays the page reload overlay on
|
||||
// ICE failure. Current disabled by default because it's causing issues with
|
||||
// signaling when Octo is enabled. Also when we do an "ICE restart"(which is
|
||||
// not a real ICE restart), the client maintains the TCC sequence number
|
||||
// counter, but the bridge resets it. The bridge sends media packets with
|
||||
// TCC sequence numbers starting from 0.
|
||||
// enableIceRestart: false,
|
||||
|
||||
// Enables forced reload of the client when the call is migrated as a result of
|
||||
// the bridge going down.
|
||||
// enableForcedReload: true,
|
||||
@@ -734,6 +760,12 @@ var config = {
|
||||
// and microsoftApiApplicationClientID
|
||||
// enableCalendarIntegration: false,
|
||||
|
||||
// Whether to notify when the conference is terminated because it was destroyed.
|
||||
// notifyOnConferenceDestruction: true,
|
||||
|
||||
// The client id for the google APIs used for the calendar integration, youtube livestreaming, etc.
|
||||
// googleApiApplicationClientID: '<client_id>',
|
||||
|
||||
// Configs for prejoin page.
|
||||
// prejoinConfig: {
|
||||
// // When 'true', it shows an intermediate page before joining, where the user can configure their devices.
|
||||
@@ -745,6 +777,11 @@ var config = {
|
||||
// hideDisplayName: false,
|
||||
// // List of buttons to hide from the extra join options dropdown.
|
||||
// hideExtraJoinButtons: ['no-audio', 'by-phone'],
|
||||
// // Configuration for pre-call test
|
||||
// // By setting preCallTestEnabled, you enable the pre-call test in the prejoin page.
|
||||
// // ICE server credentials need to be provided over the preCallTestICEUrl
|
||||
// preCallTestEnabled: false,
|
||||
// preCallTestICEUrl: ''
|
||||
// },
|
||||
|
||||
// When 'true', the user cannot edit the display name.
|
||||
@@ -763,10 +800,6 @@ var config = {
|
||||
// set or the lobby is not enabled.
|
||||
// enableInsecureRoomNameWarning: false,
|
||||
|
||||
// Whether to automatically copy invitation URL after creating a room.
|
||||
// Document should be focused for this option to work
|
||||
// enableAutomaticUrlCopy: false,
|
||||
|
||||
// Array with avatar URL prefixes that need to use CORS.
|
||||
// corsAvatarURLs: [ 'https://www.gravatar.com/avatar/' ],
|
||||
|
||||
@@ -848,6 +881,22 @@ var config = {
|
||||
// autoHideWhileChatIsOpen: false,
|
||||
// },
|
||||
|
||||
// Overrides the buttons displayed in the main toolbar. Depending on the screen size the number of displayed
|
||||
// buttons varies from 2 buttons to 8 buttons. Every array in the mainToolbarButtons array will replace the
|
||||
// corresponding default buttons configuration matched by the number of buttons specified in the array. Arrays with
|
||||
// more than 8 buttons or less then 2 buttons will be ignored. When there there isn't an override for a certain
|
||||
// configuration (for example when 3 buttons are displayed) the default jitsi-meet configuration will be used.
|
||||
// The order of the buttons in the array is preserved.
|
||||
// mainToolbarButtons: [
|
||||
// [ 'microphone', 'camera', 'desktop', 'chat', 'raisehand', 'reactions', 'participants-pane', 'tileview' ],
|
||||
// [ 'microphone', 'camera', 'desktop', 'chat', 'raisehand', 'participants-pane', 'tileview' ],
|
||||
// [ 'microphone', 'camera', 'desktop', 'chat', 'raisehand', 'participants-pane' ],
|
||||
// [ 'microphone', 'camera', 'desktop', 'chat', 'participants-pane' ],
|
||||
// [ 'microphone', 'camera', 'chat', 'participants-pane' ],
|
||||
// [ 'microphone', 'camera', 'chat' ],
|
||||
// [ 'microphone', 'camera' ]
|
||||
// ],
|
||||
|
||||
// Toolbar buttons which have their click/tap event exposed through the API on
|
||||
// `toolbarButtonClicked`. Passing a string for the button key will
|
||||
// prevent execution of the click/tap routine; passing an object with `key` and
|
||||
@@ -1029,10 +1078,14 @@ var config = {
|
||||
|
||||
// Provides a way to set the codec preference on mobile devices, both on RN and mobile browser based
|
||||
// endpoints.
|
||||
// mobileCodecPreferenceOrder: [ 'H264', 'VP8', 'VP9' ],
|
||||
// mobileCodecPreferenceOrder: [ 'H264', 'VP8', 'VP9', 'AV1' ],
|
||||
//
|
||||
// Provides a way to set the codec preference on desktop based endpoints.
|
||||
// codecPreferenceOrder: [ 'VP9', 'VP8', 'H264 ],
|
||||
// codecPreferenceOrder: [ 'AV1', 'VP9', 'VP8', 'H264 ],
|
||||
|
||||
// Provides a way to set the codec for screenshare.
|
||||
// screenshareCodec: 'AV1',
|
||||
// mobileScreenshareCodec: 'VP8',
|
||||
|
||||
// How long we're going to wait, before going back to P2P after the 3rd
|
||||
// participant has left the conference (to filter out page reload).
|
||||
@@ -1044,24 +1097,12 @@ var config = {
|
||||
// { urls: 'stun:jitsi-meet.example.com:3478' },
|
||||
{ urls: 'stun:meet-jit-si-turnrelay.jitsi.net:443' },
|
||||
],
|
||||
|
||||
// DEPRECATED! Use `codecPreferenceOrder/mobileCodecPreferenceOrder` instead.
|
||||
// Provides a way to set the video codec preference on the p2p connection. Acceptable
|
||||
// codec values are 'VP8', 'VP9' and 'H264'.
|
||||
// preferredCodec: 'H264',
|
||||
|
||||
// DEPRECATED! Use `codecPreferenceOrder/mobileCodecPreferenceOrder` instead.
|
||||
// Provides a way to prevent a video codec from being negotiated on the p2p connection.
|
||||
// disabledCodec: '',
|
||||
},
|
||||
|
||||
analytics: {
|
||||
// True if the analytics should be disabled
|
||||
// disabled: false,
|
||||
|
||||
// The Google Analytics Tracking ID:
|
||||
// googleAnalyticsTrackingId: 'your-tracking-id-UA-123456-1',
|
||||
|
||||
// Matomo configuration:
|
||||
// matomoEndpoint: 'https://your-matomo-endpoint/',
|
||||
// matomoSiteID: '42',
|
||||
@@ -1099,7 +1140,6 @@ var config = {
|
||||
|
||||
// Array of script URLs to load as lib-jitsi-meet "analytics handlers".
|
||||
// scriptURLs: [
|
||||
// "libs/analytics-ga.min.js", // google-analytics
|
||||
// "https://example.com/my-custom-analytics.js",
|
||||
// ],
|
||||
|
||||
@@ -1185,6 +1225,7 @@ var config = {
|
||||
// warning: '',
|
||||
// },
|
||||
// externallyManagedKey: false,
|
||||
// disabled: false,
|
||||
// },
|
||||
|
||||
// Options related to end-to-end (participant to participant) ping.
|
||||
@@ -1342,8 +1383,12 @@ var config = {
|
||||
The config file should be in JSON.
|
||||
None of the fields are mandatory and the response must have the shape:
|
||||
{
|
||||
// Whether participant can only send group chat message if `send-groupchat` feature is enabled in jwt.
|
||||
groupChatRequiresPermission: false,
|
||||
// Whether participant can only create polls if `create-polls` feature is enabled in jwt.
|
||||
pollCreationRequiresPermission: false,
|
||||
// The domain url to apply (will replace the domain in the sharing conference link/embed section)
|
||||
inviteDomain: 'example-company.org,
|
||||
inviteDomain: 'example-company.org',
|
||||
// The hex value for the colour used as background
|
||||
backgroundColor: '#fff',
|
||||
// The url for the image used as background
|
||||
@@ -1402,6 +1447,13 @@ var config = {
|
||||
*/
|
||||
// dynamicBrandingUrl: '',
|
||||
|
||||
// A list of allowed URL domains for shared video.
|
||||
//
|
||||
// NOTE:
|
||||
// '*' is allowed value and it will allow any URL to be used for shared video. We do not recommend using '*',
|
||||
// use it at your own risk!
|
||||
// sharedVideoAllowedURLDomains: [ ],
|
||||
|
||||
// Options related to the participants pane.
|
||||
// participantsPane: {
|
||||
// // Enables feature
|
||||
@@ -1524,26 +1576,64 @@ var config = {
|
||||
// You can enable tokenAuthUrlAutoRedirect which will detect that you have logged in successfully before
|
||||
// and will automatically redirect to the token service to get the token for the meeting.
|
||||
// tokenAuthUrlAutoRedirect: false
|
||||
// An option to respect the context.tenant jwt field compared to the current tenant from the url
|
||||
// tokenRespectTenant: false,
|
||||
|
||||
// You can put an array of values to target different entity types in the invite dialog.
|
||||
// Valid values are "phone", "room", "sip", "user", "videosipgw" and "email"
|
||||
// peopleSearchQueryTypes: ["user", "email"],
|
||||
// Directory endpoint which is called for invite dialog autocomplete
|
||||
// peopleSearchUrl: "https://myservice.com/api/people",
|
||||
// Endpoint which is called to send invitation requests
|
||||
// inviteServiceUrl: "https://myservice.com/api/invite",
|
||||
|
||||
// For external entities (e. g. email), the localStorage key holding the token value for directory authentication
|
||||
// peopleSearchTokenLocation: "mytoken",
|
||||
|
||||
|
||||
// Options related to visitors.
|
||||
// visitors: {
|
||||
// // Starts audio/video when the participant is promoted from visitor.
|
||||
// enableMediaOnPromote: {
|
||||
// audio: true,
|
||||
// video: true
|
||||
// },
|
||||
// },
|
||||
// The default type of desktop sharing sources that will be used in the electron app.
|
||||
// desktopSharingSources: ['screen', 'window'],
|
||||
|
||||
// Disables the echo cancelation for local audio tracks.
|
||||
// disableAEC: true,
|
||||
|
||||
// Disables the auto gain control for local audio tracks.
|
||||
// disableAGC: true,
|
||||
|
||||
// Disables the audio processing (echo cancelation, auto gain control and noise suppression) for local audio tracks.
|
||||
// disableAP: true,
|
||||
|
||||
// Disables the anoise suppression for local audio tracks.
|
||||
// disableNS: true,
|
||||
|
||||
// Replaces the display name with the JID of the participants.
|
||||
// displayJids: true,
|
||||
|
||||
// Enables disables talk while muted detection.
|
||||
// enableTalkWhileMuted: true,
|
||||
|
||||
// Sets the peer connection ICE transport policy to "relay".
|
||||
// forceTurnRelay: true,
|
||||
|
||||
// List of undocumented settings used in jitsi-meet
|
||||
/**
|
||||
_immediateReloadThreshold
|
||||
debug
|
||||
debugAudioLevels
|
||||
deploymentInfo
|
||||
dialOutAuthUrl
|
||||
dialOutCodesUrl
|
||||
dialOutRegionUrl
|
||||
disableRemoteControl
|
||||
displayJids
|
||||
firefox_fake_device
|
||||
googleApiApplicationClientID
|
||||
iAmRecorder
|
||||
iAmSipGateway
|
||||
microsoftApiApplicationClientID
|
||||
peopleSearchQueryTypes
|
||||
peopleSearchUrl
|
||||
requireDisplayName
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -1559,14 +1649,7 @@ var config = {
|
||||
_peerConnStatusRtcMuteTimeout
|
||||
avgRtpStatsN
|
||||
desktopSharingSources
|
||||
disableAEC
|
||||
disableAGC
|
||||
disableAP
|
||||
disableHPF
|
||||
disableLocalStats
|
||||
disableNS
|
||||
enableTalkWhileMuted
|
||||
forceTurnRelay
|
||||
hiddenDomain
|
||||
hiddenFromRecorderFeatureEnabled
|
||||
ignoreStartMuted
|
||||
@@ -1643,7 +1726,7 @@ var config = {
|
||||
// 'notify.participantsWantToJoin', // shown when lobby is enabled and participants request to join meeting
|
||||
// 'notify.passwordRemovedRemotely', // shown when a password has been removed remotely
|
||||
// 'notify.passwordSetRemotely', // shown when a password has been set remotely
|
||||
// 'notify.raisedHand', // shown when a partcipant used raise hand,
|
||||
// 'notify.raisedHand', // shown when a participant used raise hand,
|
||||
// 'notify.screenShareNoAudio', // shown when the audio could not be shared for the selected screen
|
||||
// 'notify.screenSharingAudioOnlyTitle', // shown when the best performance has been affected by screen sharing
|
||||
// 'notify.selfViewTitle', // show "You can always un-hide the self-view from settings"
|
||||
@@ -1664,7 +1747,7 @@ var config = {
|
||||
// 'toolbar.noAudioSignalTitle', // shown when a broken mic is detected
|
||||
// 'toolbar.noisyAudioInputTitle', // shown when noise is detected for the current microphone
|
||||
// 'toolbar.talkWhileMutedPopup', // shown when user tries to speak while muted
|
||||
// 'transcribing.failedToStart', // shown when transcribing fails to start
|
||||
// 'transcribing.failed', // shown when transcribing fails
|
||||
// ],
|
||||
|
||||
// List of notifications to be disabled. Works in tandem with the above setting.
|
||||
@@ -1674,7 +1757,7 @@ var config = {
|
||||
// disableFilmstripAutohiding: false,
|
||||
|
||||
// filmstrip: {
|
||||
// // Disable the vertical/horizonal filmstrip.
|
||||
// // Disable the vertical/horizontal filmstrip.
|
||||
// disabled: false,
|
||||
// // Disables user resizable filmstrip. Also, allows configuration of the filmstrip
|
||||
// // (width, tiles aspect ratios) through the interfaceConfig options.
|
||||
@@ -1723,8 +1806,6 @@ var config = {
|
||||
// tileTime: 5000,
|
||||
// // Limit results by rating: g, pg, pg-13, r. Default value: g.
|
||||
// rating: 'pg',
|
||||
// // The proxy server url for giphy requests in the web app.
|
||||
// proxyUrl: 'https://giphy-proxy.example.com',
|
||||
// },
|
||||
|
||||
// Logging
|
||||
@@ -1735,9 +1816,10 @@ var config = {
|
||||
// //disableLogCollector: true,
|
||||
// // Individual loggers are customizable.
|
||||
// loggers: {
|
||||
// // The following are too verbose in their logging with the default level.
|
||||
// 'modules/RTC/TraceablePeerConnection.js': 'info',
|
||||
// 'modules/xmpp/strophe.util.js': 'log',
|
||||
// // The following are too verbose in their logging with the default level.
|
||||
// 'modules/RTC/TraceablePeerConnection.js': 'info',
|
||||
// 'modules/xmpp/strophe.util.js': 'log',
|
||||
// },
|
||||
// },
|
||||
|
||||
// Application logo url
|
||||
@@ -1754,7 +1836,7 @@ var config = {
|
||||
// // to control the performance.
|
||||
// userLimit: 25,
|
||||
// // The url for more info about the whiteboard and its usage limitations.
|
||||
// limitUrl: 'https://example.com/blog/whiteboard-limits,
|
||||
// limitUrl: 'https://example.com/blog/whiteboard-limits',
|
||||
// },
|
||||
|
||||
// The watchRTC initialize config params as described :
|
||||
@@ -1790,13 +1872,13 @@ var config = {
|
||||
// collectionInterval?: number;
|
||||
// logGetStats?: boolean;
|
||||
// },
|
||||
};
|
||||
|
||||
// Temporary backwards compatibility with old mobile clients.
|
||||
config.flags = config.flags || {};
|
||||
config.flags.sourceNameSignaling = true;
|
||||
config.flags.sendMultipleVideoStreams = true;
|
||||
config.flags.receiveMultipleVideoStreams = true;
|
||||
// Hide login button on auth dialog, you may want to enable this if you are using JWT tokens to authenticate users
|
||||
// hideLoginButton: true,
|
||||
|
||||
// If true remove the tint foreground on focused user camera in filmstrip
|
||||
// disableCameraTintForeground: false,
|
||||
};
|
||||
|
||||
// Set the default values for JaaS customers
|
||||
if (enableJaaS) {
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
text-align: center;
|
||||
|
||||
h2 {
|
||||
font-size: 48px;
|
||||
font-size: 3rem;
|
||||
color : #f2f2f2;
|
||||
}
|
||||
|
||||
&__message {
|
||||
font-size: 24px;
|
||||
font-size: 1.5rem;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ body {
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 400;
|
||||
overflow: hidden;
|
||||
color: #F1F1F1;
|
||||
@@ -111,7 +111,7 @@ form {
|
||||
height: $watermarkHeight;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
z-index: $zindex2;
|
||||
z-index: $watermarkZ;
|
||||
}
|
||||
|
||||
.leftwatermark {
|
||||
@@ -139,10 +139,10 @@ form {
|
||||
position: absolute;
|
||||
left: 25;
|
||||
bottom: 7;
|
||||
font-size: 11pt;
|
||||
font-size: 0.875rem;
|
||||
color: rgba(255,255,255,.50);
|
||||
text-decoration: none;
|
||||
z-index: 100;
|
||||
z-index: $watermarkZ;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
@use './variables';
|
||||
|
||||
#chat-conversation-container {
|
||||
// extract message input height
|
||||
box-sizing: border-box;
|
||||
height: calc(100% - 64px);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
@@ -8,9 +11,9 @@
|
||||
#chatconversation {
|
||||
box-sizing: border-box;
|
||||
flex: 1;
|
||||
font-size: 10pt;
|
||||
height: 100%;
|
||||
line-height: 20px;
|
||||
font-size: 0.75rem;
|
||||
height: calc(100% - 10px);
|
||||
line-height: 1.25rem;
|
||||
overflow: auto;
|
||||
padding: 16px;
|
||||
text-align: left;
|
||||
@@ -19,6 +22,13 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
&.focus-visible {
|
||||
outline: 0;
|
||||
margin: 4px;
|
||||
border-radius: 0 0 variables.$borderRadius variables.$borderRadius;
|
||||
box-shadow: 0px 0px 0px 2px #4687ed; // focus01/primary07
|
||||
}
|
||||
|
||||
& > :first-child {
|
||||
margin-top: auto;
|
||||
}
|
||||
@@ -62,7 +72,7 @@
|
||||
#nickname {
|
||||
text-align: center;
|
||||
color: #9d9d9d;
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
margin: auto 0;
|
||||
padding: 0 16px;
|
||||
|
||||
@@ -76,7 +86,7 @@
|
||||
}
|
||||
|
||||
label {
|
||||
line-height: 24px;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +98,7 @@
|
||||
}
|
||||
|
||||
.chatmessage .usermessage {
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +124,7 @@
|
||||
}
|
||||
|
||||
#smileys {
|
||||
font-size: 20pt;
|
||||
font-size: 1.625rem;
|
||||
margin: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -158,7 +168,7 @@
|
||||
}
|
||||
|
||||
#smileysContainer .smiley {
|
||||
font-size: 20pt;
|
||||
font-size: 1.625rem;
|
||||
}
|
||||
|
||||
.smileyContainer {
|
||||
@@ -209,8 +219,8 @@
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
|
||||
.jitsi-icon {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
}
|
||||
|
||||
&__checkbox-label {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.125rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
letter-spacing: -0.006em;
|
||||
@@ -51,8 +51,8 @@
|
||||
}
|
||||
|
||||
&__text-container {
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.125rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
letter-spacing: -0.006em;
|
||||
@@ -84,8 +84,8 @@
|
||||
|
||||
&__button-text {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 40px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 2.5rem;
|
||||
text-align: center;
|
||||
letter-spacing: -0.006em;
|
||||
color: #FFFFFF;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
margin: 17px 0;
|
||||
padding-bottom: 17px;
|
||||
color: #ffffff;
|
||||
font-size: 21px;
|
||||
font-size: 1.25rem;
|
||||
letter-spacing: 0.3px;
|
||||
border-bottom: 1px solid lighten(#FFFFFF, 10%);
|
||||
}
|
||||
@@ -19,12 +19,12 @@
|
||||
color: #ffffff;
|
||||
display: block;
|
||||
margin-top: 22px;
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
margin: 0 10px;
|
||||
font-size: 50px;
|
||||
font-size: 3.125rem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
.meetings-list {
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
color: #253858;
|
||||
line-height: 20px;
|
||||
line-height: 1.25rem;
|
||||
text-align: left;
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
|
||||
.meetings-list-empty {
|
||||
text-align: center;
|
||||
@@ -19,11 +19,11 @@
|
||||
flex-direction: column;
|
||||
|
||||
.description {
|
||||
color: #2f3237;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
margin-bottom: 16px;
|
||||
max-width: 436px;
|
||||
color: #2f3237;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.125rem;
|
||||
margin-bottom: 16px;
|
||||
max-width: 436px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
color: #0163FF;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.125rem;
|
||||
margin: 24px 0 32px 0;
|
||||
}
|
||||
|
||||
@@ -101,17 +101,17 @@
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
line-height: 1rem;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #5E6D7A;
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,8 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.with-click-handler:hover {
|
||||
&.with-click-handler:hover,
|
||||
&.with-click-handler:focus {
|
||||
background-color: #c7ddff;
|
||||
}
|
||||
|
||||
@@ -155,14 +156,30 @@
|
||||
margin-right: 16px;
|
||||
position: absolute;
|
||||
|
||||
&> svg {
|
||||
&>svg {
|
||||
fill: #0074e0;
|
||||
}
|
||||
}
|
||||
|
||||
.item:hover, .item:focus, .item:focus-within {
|
||||
.item:hover,
|
||||
.item:focus,
|
||||
.item:focus-within {
|
||||
.delete-meeting {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.delete-meeting:hover {
|
||||
&>svg {
|
||||
fill: #4687ED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) { /* Targets iPads and smaller devices */
|
||||
.item {
|
||||
.delete-meeting {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
%navigate-section-list-text {
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
color: $welcomePageTitleColor;
|
||||
text-align: left;
|
||||
font-family: 'open_sanslight', Helvetica, sans-serif;
|
||||
@@ -52,7 +52,7 @@
|
||||
.navigate-section-tile-body {
|
||||
@extend %navigate-section-list-tile-text;
|
||||
font-weight: normal;
|
||||
line-height: 24px;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
.navigate-section-list-tile-info {
|
||||
flex: 1;
|
||||
@@ -61,7 +61,7 @@
|
||||
.navigate-section-tile-title {
|
||||
@extend %navigate-section-list-tile-text;
|
||||
font-weight: bold;
|
||||
line-height: 24px;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
.navigate-section-section-header {
|
||||
@extend %navigate-section-list-text;
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
&__text {
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
line-height: 21px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 300;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
@use 'sass:math';
|
||||
|
||||
.reactions-menu {
|
||||
width: 280px;
|
||||
width: 330px;
|
||||
background: #242528;
|
||||
box-shadow: 0px 3px 16px rgba(0, 0, 0, 0.6), 0px 0px 4px 1px rgba(0, 0, 0, 0.25);
|
||||
border-radius: 6px;
|
||||
padding: 16px;
|
||||
|
||||
&.with-gif {
|
||||
width: 328px;
|
||||
width: 380px;
|
||||
|
||||
.reactions-row .toolbox-button:last-of-type {
|
||||
top: 3px;
|
||||
@@ -55,7 +55,7 @@
|
||||
span.emoji {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 22px;
|
||||
font-size: 1.375rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
@for $i from 1 through 12 {
|
||||
&.increase-#{$i}{
|
||||
font-size: calc(20px + #{$i}px);
|
||||
font-size: calc(1.25rem + #{$i}px);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,8 +96,8 @@
|
||||
span.text {
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5rem;
|
||||
margin-left: 8px;
|
||||
}
|
||||
}
|
||||
@@ -132,8 +132,8 @@ $reactionCount: 20;
|
||||
|
||||
.reaction-emoji {
|
||||
position: absolute;
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
top: 0;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
.recording-title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
margin-left: 16px;
|
||||
max-width: 70%;
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
.local-recording-warning {
|
||||
margin-top: 8px;
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
padding: 8px 16px;
|
||||
|
||||
&.text {
|
||||
@@ -126,7 +126,7 @@
|
||||
|
||||
.recording-info-title {
|
||||
display: inline-flex;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
width: 290px
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
/**
|
||||
* Set font-size to be consistent with Atlaskit FieldText.
|
||||
*/
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
|
||||
.broadcast-dropdown {
|
||||
text-align: left;
|
||||
@@ -194,6 +194,6 @@
|
||||
|
||||
.warning-text {
|
||||
color:#FFD740;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
width: 30%;
|
||||
margin: 20% auto;
|
||||
text-align: center;
|
||||
font-size: 24px;
|
||||
font-size: 1.5rem;
|
||||
|
||||
.thanks-msg {
|
||||
border-bottom: 1px solid #FFFFFF;
|
||||
@@ -10,16 +10,16 @@
|
||||
padding-right: 30px;
|
||||
p {
|
||||
margin: 30px auto;
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
}
|
||||
.hint-msg {
|
||||
p {
|
||||
margin: 26px auto;
|
||||
font-weight: 600;
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
font-size: 1rem;
|
||||
line-height: 1.125rem;
|
||||
.hint-msg__holder{
|
||||
font-weight: 200;
|
||||
}
|
||||
@@ -33,7 +33,7 @@
|
||||
}
|
||||
.forbidden-msg {
|
||||
p {
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ input[type="reset"] {
|
||||
body {
|
||||
color: #333;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.42857142857143;
|
||||
}
|
||||
/* International Font Stacks*/
|
||||
@@ -113,7 +113,7 @@ pre:first-child {
|
||||
/* Headings: desired line height in px / font size = unitless line height */
|
||||
h1 {
|
||||
color: #333;
|
||||
font-size: 32px;
|
||||
font-size: 2rem;
|
||||
font-weight: normal;
|
||||
line-height: 1.25;
|
||||
text-transform: none;
|
||||
@@ -121,7 +121,7 @@ h1 {
|
||||
}
|
||||
h2 {
|
||||
color: #333;
|
||||
font-size: 24px;
|
||||
font-size: 1.5rem;
|
||||
font-weight: normal;
|
||||
line-height: 1.25;
|
||||
text-transform: none;
|
||||
@@ -129,14 +129,14 @@ h2 {
|
||||
}
|
||||
h3 {
|
||||
color: #333;
|
||||
font-size: 20px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: normal;
|
||||
line-height: 1.5;
|
||||
text-transform: none;
|
||||
margin: 30px 0 0 0;
|
||||
}
|
||||
h4 {
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.25;
|
||||
text-transform: none;
|
||||
@@ -144,7 +144,7 @@ h4 {
|
||||
}
|
||||
h5 {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.42857143;
|
||||
text-transform: none;
|
||||
@@ -152,7 +152,7 @@ h5 {
|
||||
}
|
||||
h6 {
|
||||
color: #707070;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
line-height: 1.66666667;
|
||||
text-transform: uppercase;
|
||||
@@ -179,7 +179,7 @@ h5 + h6 {
|
||||
/* Other typographical elements */
|
||||
small {
|
||||
color: #707070;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.33333333333333;
|
||||
}
|
||||
code,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#enter_room {
|
||||
.welcome-page-button {
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
@@ -53,7 +53,10 @@
|
||||
}
|
||||
|
||||
.welcome-footer-row-block {
|
||||
display: block;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap:12px;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
// Do not inherit the font-family from the toolbar button, because it's an
|
||||
// icon style.
|
||||
font-family: $baseFontFamily;
|
||||
font-size: 9px;
|
||||
font-size: 0.5rem;
|
||||
font-weight: 700;
|
||||
line-height: 13px;
|
||||
line-height: 0.75rem;
|
||||
min-width: 13px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
@@ -69,8 +69,8 @@
|
||||
|
||||
.badge-round {
|
||||
bottom: -5px;
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.25rem;
|
||||
min-width: 20px;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
.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),
|
||||
0px 1px 1px rgba(0,0,0,0.3),
|
||||
1px 0px 1px rgba(0,0,0,0.3),
|
||||
0px 0px 1px rgba(0,0,0,0.3);
|
||||
transform: translateX(-50%);
|
||||
z-index: 7;
|
||||
|
||||
&.lifted {
|
||||
// Lift subtitle above toolbar+dominant speaker box.
|
||||
bottom: $newToolbarSize + 36px + 40px;
|
||||
}
|
||||
|
||||
span {
|
||||
background: black;
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,8 @@ $zindex1: 1;
|
||||
$zindex2: 2;
|
||||
$zindex3: 3;
|
||||
$toolbarZ: 250;
|
||||
$watermarkZ: 253;
|
||||
|
||||
// Place filmstrip videos over toolbar in order
|
||||
// to make connection info visible.
|
||||
$filmstripVideosZ: $toolbarZ + 1;
|
||||
@@ -48,11 +50,11 @@ $filmstripVideosZ: $toolbarZ + 1;
|
||||
$primaryUnsupportedBrowserButtonBgColor: #0052CC;
|
||||
$unsupportedBrowserButtonBgColor: rgba(9, 30, 66, 0.04);
|
||||
$unsupportedBrowserTextColor: #4a4a4a;
|
||||
$unsupportedBrowserTextSmallFontSize: 17px;
|
||||
$unsupportedBrowserTextSmallFontSize: 1rem;
|
||||
$unsupportedBrowserTitleColor: #fff;
|
||||
$unsupportedBrowserTitleFontSize: 24px;
|
||||
$unsupportedBrowserTitleFontSize: 1.5rem;
|
||||
$unsupportedDesktopBrowserTextColor: rgba(255, 255, 255, 0.7);
|
||||
$unsupportedDesktopBrowserTextFontSize: 21px;
|
||||
$unsupportedDesktopBrowserTextFontSize: 1.25rem;
|
||||
|
||||
/**
|
||||
* The size of the default watermark.
|
||||
@@ -75,16 +77,19 @@ $welcomePageHeaderBackground: linear-gradient(0deg, rgba(0, 0, 0, 0.2), rgba(0,
|
||||
$welcomePageHeaderBackgroundPosition: center;
|
||||
$welcomePageHeaderBackgroundRepeat: none;
|
||||
$welcomePageHeaderBackgroundSize: cover;
|
||||
$welcomePageHeaderPaddingBottom: 15px;
|
||||
$welcomePageHeaderPadding: 1rem;
|
||||
$welcomePageHeaderTitleMaxWidth: initial;
|
||||
$welcomePageHeaderTextAlign: center;
|
||||
$welcomePageButtonBg: #0074E0;
|
||||
$welcomePageButtonHoverBg: #4687ED;
|
||||
$welcomePageButtonFocusOutline: #00225A;
|
||||
|
||||
$welcomePageHeaderContainerMarginTop: 104px;
|
||||
$welcomePageHeaderContainerDisplay: flex;
|
||||
$welcomePageHeaderContainerMargin: $welcomePageHeaderContainerMarginTop auto 0;
|
||||
|
||||
$welcomePageHeaderTextTitleMarginBottom: 0;
|
||||
$welcomePageHeaderTextTitleFontSize: 42px;
|
||||
$welcomePageHeaderTextTitleFontSize: 2.625rem;
|
||||
$welcomePageHeaderTextTitleFontWeight: normal;
|
||||
$welcomePageHeaderTextTitleLineHeight: 50px;
|
||||
$welcomePageHeaderTextTitleOpacity: 1;
|
||||
|
||||
@@ -160,7 +160,7 @@
|
||||
}
|
||||
|
||||
#alwaysOnTop .displayname {
|
||||
font-size: 15px;
|
||||
font-size: 0.875rem;
|
||||
position: inherit;
|
||||
width: 100%;
|
||||
left: 0px;
|
||||
@@ -294,7 +294,7 @@
|
||||
width: auto;
|
||||
z-index: $zindex2;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
text-align: center;
|
||||
color: #FFF;
|
||||
left: 50%;
|
||||
@@ -340,7 +340,7 @@
|
||||
|
||||
.presence-label {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 100;
|
||||
left: 0;
|
||||
margin: 0 auto;
|
||||
|
||||
@@ -18,7 +18,7 @@ body.welcome-page {
|
||||
background-position: $welcomePageHeaderBackgroundPosition;
|
||||
background-repeat: $welcomePageHeaderBackgroundRepeat;
|
||||
background-size: $welcomePageHeaderBackgroundSize;
|
||||
padding-bottom: $welcomePageHeaderPaddingBottom;
|
||||
padding: $welcomePageHeaderPadding;
|
||||
background-color: #131519;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
@@ -53,9 +53,9 @@ body.welcome-page {
|
||||
|
||||
.header-text-subtitle {
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
line-height: 26px;
|
||||
line-height: 1.625rem;
|
||||
margin: 16px 0 32px 0;
|
||||
text-align: $welcomePageHeaderTextAlign;
|
||||
|
||||
@@ -64,7 +64,7 @@ body.welcome-page {
|
||||
.not-allow-title-character-div {
|
||||
color: #f03e3e;
|
||||
background-color: #fff;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
margin: 10px 0px 5px 0px;
|
||||
text-align: $welcomePageHeaderTextAlign;
|
||||
@@ -147,7 +147,7 @@ body.welcome-page {
|
||||
display: inline-block;
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
padding-left: 10px;
|
||||
|
||||
&.focus-visible {
|
||||
@@ -172,7 +172,7 @@ body.welcome-page {
|
||||
}
|
||||
|
||||
.tab-container {
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
display: $welcomePageTabContainerDisplay;
|
||||
@@ -191,8 +191,8 @@ body.welcome-page {
|
||||
background-color: #c7ddff;
|
||||
border-radius: 6px;
|
||||
color: #0163FF;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.125rem;
|
||||
margin: 4px;
|
||||
display: $welcomePageTabButtonsDisplay;
|
||||
|
||||
@@ -218,15 +218,19 @@ body.welcome-page {
|
||||
|
||||
.welcome-page-button {
|
||||
border: 0;
|
||||
font-size: 14px;
|
||||
background: #0074E0;
|
||||
font-size: 0.875rem;
|
||||
background: $welcomePageButtonBg;
|
||||
border-radius: 3px;
|
||||
color: #FFFFFF;
|
||||
cursor: pointer;
|
||||
padding: 16px 20px;
|
||||
|
||||
transition: all 0.2s;
|
||||
&:focus-within {
|
||||
outline: auto 2px #022e61;
|
||||
outline: auto 2px $welcomePageButtonFocusOutline;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: $welcomePageButtonHoverBg;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +246,7 @@ body.welcome-page {
|
||||
|
||||
* {
|
||||
cursor: pointer;
|
||||
font-size: 32px;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.toolbox-icon {
|
||||
@@ -264,8 +268,7 @@ body.welcome-page {
|
||||
|
||||
&.without-content {
|
||||
.welcome-card {
|
||||
min-width: 500px;
|
||||
max-width: 580px;
|
||||
max-width: 100dvw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,6 +349,6 @@ body.welcome-page {
|
||||
|
||||
.welcome-footer-row-1-text {
|
||||
max-width: 200px;
|
||||
margin-right: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
*/
|
||||
#dominantSpeaker,
|
||||
#largeVideoElementsContainer,
|
||||
#sharedVideo,
|
||||
.stage-participant-label {
|
||||
#sharedVideo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,6 @@ $flagsImagePath: "../images/";
|
||||
@import 'filmstrip/vertical_filmstrip_overrides';
|
||||
@import 'unsupported-browser/main';
|
||||
@import 'deep-linking/main';
|
||||
@import 'transcription-subtitles';
|
||||
@import '_meetings_list.scss';
|
||||
@import 'navigate_section_list';
|
||||
@import 'third-party-branding/google';
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
width: 28px;
|
||||
|
||||
i {
|
||||
line-height: 28px;
|
||||
line-height: 1.75rem;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
padding-left: 10px;
|
||||
|
||||
i {
|
||||
line-height: 20px;
|
||||
line-height: 1.25rem;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.info-dialog {
|
||||
cursor: default;
|
||||
display: flex;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
|
||||
.info-dialog-column {
|
||||
margin-right: 10px;
|
||||
@@ -53,8 +53,8 @@
|
||||
max-width: 334px;
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
font-size: 12px;
|
||||
line-height: 24px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.5rem;
|
||||
border-collapse: collapse;
|
||||
|
||||
* {
|
||||
@@ -107,7 +107,7 @@
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 12px;
|
||||
font-size: 0.75rem;
|
||||
max-height: 100%;
|
||||
overflow: auto;
|
||||
padding: 15pt;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
.invite-more {
|
||||
&-dialog {
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5rem;
|
||||
|
||||
&.separator {
|
||||
margin: 24px 0 24px -20px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.share-screen-warn-dialog {
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
|
||||
.separator-line {
|
||||
margin: 24px 0 24px -20px;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
.security {
|
||||
&-dialog {
|
||||
color: #fff;
|
||||
font-size: 15px;
|
||||
line-height: 24px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.5rem;
|
||||
|
||||
&.password-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.description {
|
||||
font-size: 13px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.password {
|
||||
@@ -24,7 +24,7 @@
|
||||
button {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
color: #6FB1EA;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.lobby-screen {
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 26px;
|
||||
line-height: 1.625rem;
|
||||
|
||||
&-content {
|
||||
align-items: center;
|
||||
@@ -43,7 +43,7 @@
|
||||
flex-direction: column;
|
||||
|
||||
.description {
|
||||
font-size: 13px;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.control-row {
|
||||
@@ -53,7 +53,7 @@
|
||||
margin-top: 15px;
|
||||
|
||||
label {
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
@@ -191,9 +191,9 @@
|
||||
.title {
|
||||
flex: 1;
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
line-height: 28px;
|
||||
line-height: 1.75rem;
|
||||
letter-spacing: -1.2%;
|
||||
}
|
||||
}
|
||||
@@ -214,8 +214,8 @@
|
||||
border-radius: 6px;
|
||||
box-sizing: border-box;
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1rem;
|
||||
margin-bottom: 16px;
|
||||
margin-top: -8px;
|
||||
padding: 4px;
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
line-height: 24px;
|
||||
line-height: 1.5rem;
|
||||
margin-bottom: 16px;
|
||||
padding: 7px 16px;
|
||||
position: relative;
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
&.text {
|
||||
width: auto;
|
||||
font-size: 13px;
|
||||
font-size: 0.75rem;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
@@ -98,7 +98,7 @@
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
font-size: 16px;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 8px;
|
||||
padding: 11px 16px;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
.reload_overlay_title {
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
.reload_overlay_text {
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
line-height: 30px;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.875rem;
|
||||
}
|
||||
|
||||
#reloadProgressBar {
|
||||
|
||||
@@ -34,12 +34,12 @@
|
||||
|
||||
&__status{
|
||||
margin-top: 15px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
&__name {
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
font-size: 1.5rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
font-family: Roboto, arial, sans-serif;
|
||||
font-size: 14px;
|
||||
font-size: 0.875rem;
|
||||
padding: 1px;
|
||||
|
||||
.google-cta {
|
||||
@@ -17,7 +17,7 @@
|
||||
/**
|
||||
* Hack the line height for vertical centering of text.
|
||||
*/
|
||||
line-height: 32px;
|
||||
line-height: 2rem;
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
.microsoft-cta {
|
||||
display: inline-block;
|
||||
color: #5E5E5E;
|
||||
font-size: 15px;
|
||||
line-height: 41px;
|
||||
font-size: 0.875rem;
|
||||
line-height: 2.5rem;
|
||||
}
|
||||
|
||||
.microsoft-logo {
|
||||
|
||||
9
debian/control
vendored
9
debian/control
vendored
@@ -3,7 +3,7 @@ Section: net
|
||||
Priority: extra
|
||||
Maintainer: Jitsi Team <dev@jitsi.org>
|
||||
Uploaders: Emil Ivov <emcho@jitsi.org>, Damian Minkov <damencho@jitsi.org>
|
||||
Build-Depends: debhelper (>= 8.0.0), nodejs
|
||||
Build-Depends: debhelper (>= 8.0.0)
|
||||
Standards-Version: 3.9.6
|
||||
Homepage: https://jitsi.org/meet
|
||||
|
||||
@@ -20,7 +20,8 @@ Description: WebRTC JavaScript video conferences
|
||||
|
||||
Package: jitsi-meet-web-config
|
||||
Architecture: all
|
||||
Depends: openssl, nginx | nginx-full | nginx-extras | openresty | apache2, curl
|
||||
Pre-Depends: nginx | nginx-full | nginx-extras | openresty | apache2
|
||||
Depends: openssl, curl
|
||||
Description: Configuration for web serving of Jitsi Meet
|
||||
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi
|
||||
Videobridge to provide high quality, scalable video conferences.
|
||||
@@ -33,7 +34,7 @@ Description: Configuration for web serving of Jitsi Meet
|
||||
|
||||
Package: jitsi-meet-prosody
|
||||
Architecture: all
|
||||
Depends: openssl, prosody (>= 0.11.7) | prosody-trunk | prosody-0.12 | prosody-0.11, lua-sec, lua-basexx, lua-luaossl, lua-cjson, lua-inspect
|
||||
Depends: openssl, prosody (>= 0.12.0) | prosody-trunk | prosody-0.12 | prosody-13.0, lua-sec, lua-basexx, lua-luaossl, lua-cjson, lua-inspect
|
||||
Replaces: jitsi-meet-tokens
|
||||
Description: Prosody configuration for Jitsi Meet
|
||||
Jitsi Meet is a WebRTC JavaScript application that uses Jitsi
|
||||
@@ -47,7 +48,7 @@ Description: Prosody configuration for Jitsi Meet
|
||||
|
||||
Package: jitsi-meet-tokens
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends}, prosody-trunk | prosody-0.11 | prosody-0.12 | prosody (>= 0.11.7), jitsi-meet-prosody
|
||||
Depends: ${misc:Depends}, prosody-trunk | prosody-0.12 | prosody-13.0 | prosody (>= 0.12.0), jitsi-meet-prosody
|
||||
Description: Prosody token authentication plugin for Jitsi Meet
|
||||
|
||||
Package: jitsi-meet-turnserver
|
||||
|
||||
45
debian/jitsi-meet-prosody.postinst
vendored
45
debian/jitsi-meet-prosody.postinst
vendored
@@ -131,16 +131,6 @@ case "$1" in
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$PROSODY_CREATE_JICOFO_USER" = "true" ]; then
|
||||
# create 'focus@auth.domain' prosody user
|
||||
prosodyctl register $JICOFO_AUTH_USER $JICOFO_AUTH_DOMAIN $JICOFO_AUTH_PASSWORD
|
||||
# trigger a restart
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
# creates the user if it does not exist
|
||||
echo -e "$JVB_SECRET\n$JVB_SECRET" | prosodyctl adduser jvb@$JICOFO_AUTH_DOMAIN > /dev/null || true
|
||||
|
||||
# Check whether prosody config has the internal muc, if not add it,
|
||||
# as we are migrating configs
|
||||
if [ -f $PROSODY_HOST_CONFIG ] && ! grep -q "internal.$JICOFO_AUTH_DOMAIN" $PROSODY_HOST_CONFIG; then
|
||||
@@ -184,6 +174,12 @@ case "$1" in
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
# Since prosody 13 admins are not automatically room owners and we expect that for jicofo
|
||||
if ! grep -q -- 'component_admins_as_room_owners = ' $PROSODY_HOST_CONFIG ;then
|
||||
sed -i "1s/^/component_admins_as_room_owners = true\n/" $PROSODY_HOST_CONFIG
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
JAAS_HOST_CONFIG="/etc/prosody/conf.avail/jaas.cfg.lua"
|
||||
if [ "${JAAS_INPUT}" = "true" ] && [ ! -f $JAAS_HOST_CONFIG ]; then
|
||||
sed -i "s/enabled = false -- Jitsi meet components/enabled = true -- Jitsi meet components/g" $PROSODY_HOST_CONFIG
|
||||
@@ -207,9 +203,6 @@ case "$1" in
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make sure the focus@auth user's roster includes the proxy component (this is idempotent)
|
||||
prosodyctl mod_roster_command subscribe focus.$JVB_HOSTNAME $JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN
|
||||
|
||||
if [ ! -f /var/lib/prosody/$JVB_HOSTNAME.crt ]; then
|
||||
# prosodyctl takes care for the permissions
|
||||
# echo for using all default values
|
||||
@@ -252,9 +245,33 @@ case "$1" in
|
||||
if [ "$PROSODY_CONFIG_PRESENT" = "false" ]; then
|
||||
invoke-rc.d prosody restart || true
|
||||
|
||||
# In case we had updated the certificates and restarted prosody, let's restart and the bridge if possible
|
||||
# give it some time to warm up
|
||||
sleep 10
|
||||
|
||||
if [ "$PROSODY_CREATE_JICOFO_USER" = "true" ]; then
|
||||
# create 'focus@auth.domain' prosody user
|
||||
echo -e "$JICOFO_AUTH_PASSWORD\n$JICOFO_AUTH_PASSWORD" | prosodyctl adduser $JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN > /dev/null || true
|
||||
|
||||
# trigger a restart
|
||||
PROSODY_CONFIG_PRESENT="false"
|
||||
fi
|
||||
|
||||
# creates the user if it does not exist
|
||||
echo -e "$JVB_SECRET\n$JVB_SECRET" | prosodyctl adduser jvb@$JICOFO_AUTH_DOMAIN > /dev/null || true
|
||||
|
||||
# Make sure the focus@auth user's roster includes the proxy component (this is idempotent)
|
||||
prosodyctl mod_roster_command subscribe focus.$JVB_HOSTNAME $JICOFO_AUTH_USER@$JICOFO_AUTH_DOMAIN
|
||||
|
||||
# To make sure the roster command is loaded
|
||||
# Once we have https://issues.prosody.im/1908 we can start using prosodyctl shell roster subscribe
|
||||
# and drop the wait and the prosody restart
|
||||
sleep 1
|
||||
invoke-rc.d prosody restart || true
|
||||
|
||||
# In case we had updated the certificates and restarted prosody, let's restart and the bridge and jicofo if possible
|
||||
if [ -d /run/systemd/system ] && [ "$CERT_ADDED_TO_TRUST" = "true" ]; then
|
||||
systemctl restart jitsi-videobridge2.service >/dev/null || true
|
||||
systemctl restart jicofo.service >/dev/null || true
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
16
debian/jitsi-meet-web-config.postinst
vendored
16
debian/jitsi-meet-web-config.postinst
vendored
@@ -175,22 +175,6 @@ case "$1" in
|
||||
fi
|
||||
fi
|
||||
|
||||
# Fixes multi-stream flags to workaround problem with mobile joining a multi-stream call with multi-stream disabled
|
||||
FIX_MSG="// Temporary backwards compatibility with old mobile clients."
|
||||
if ! grep -q "^${FIX_MSG}" $JITSI_MEET_CONFIG; then
|
||||
echo $FIX_MSG >> $JITSI_MEET_CONFIG
|
||||
echo "config.flags = config.flags || {};" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
if ! grep -q "^config.flags.sourceNameSignaling*" $JITSI_MEET_CONFIG; then
|
||||
echo "config.flags.sourceNameSignaling = true;" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
if ! grep -q "^config.flags.sendMultipleVideoStreams*" $JITSI_MEET_CONFIG; then
|
||||
echo "config.flags.sendMultipleVideoStreams = true;" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
if ! grep -q "^config.flags.receiveMultipleVideoStreams*" $JITSI_MEET_CONFIG; then
|
||||
echo "config.flags.receiveMultipleVideoStreams = true;" >> $JITSI_MEET_CONFIG
|
||||
fi
|
||||
|
||||
if [[ "$FORCE_OPENRESTY" = "true" ]]; then
|
||||
NGX_COMMON_CONF_PATH="/usr/local/openresty/nginx/conf/$JVB_HOSTNAME.conf"
|
||||
NGX_SVC_NAME=openresty
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
-- We need this for prosody 13.0
|
||||
component_admins_as_room_owners = true
|
||||
|
||||
plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }
|
||||
|
||||
-- domain mapper options, must at least have domain base set to use the mapper
|
||||
@@ -12,6 +15,7 @@ external_services = {
|
||||
|
||||
cross_domain_bosh = false;
|
||||
consider_bosh_secure = true;
|
||||
consider_websocket_secure = true;
|
||||
-- https_ports = { }; -- Remove this line to prevent listening on port 5284
|
||||
|
||||
-- by default prosody 0.12 sends cors headers, if you want to disable it uncomment the following (the config is available on 0.12.1)
|
||||
@@ -35,6 +39,11 @@ unlimited_jids = {
|
||||
"jvb@auth.jitmeet.example.com"
|
||||
}
|
||||
|
||||
-- https://prosody.im/doc/modules/mod_smacks
|
||||
smacks_max_unacked_stanzas = 5;
|
||||
smacks_hibernation_time = 60;
|
||||
smacks_max_old_sessions = 1;
|
||||
|
||||
VirtualHost "jitmeet.example.com"
|
||||
authentication = "jitsi-anonymous" -- do not delete me
|
||||
-- Properties below are modified by jitsi-meet-tokens package config
|
||||
@@ -55,6 +64,8 @@ VirtualHost "jitmeet.example.com"
|
||||
-- we need bosh
|
||||
modules_enabled = {
|
||||
"bosh";
|
||||
"websocket";
|
||||
"smacks";
|
||||
"ping"; -- Enable mod_ping
|
||||
"speakerstats";
|
||||
"external_services";
|
||||
@@ -119,8 +130,17 @@ Component "internal.auth.jitmeet.example.com" "muc"
|
||||
VirtualHost "auth.jitmeet.example.com"
|
||||
modules_enabled = {
|
||||
"limits_exception";
|
||||
"smacks";
|
||||
}
|
||||
authentication = "internal_hashed"
|
||||
smacks_hibernation_time = 15;
|
||||
|
||||
VirtualHost "recorder.jitmeet.example.com"
|
||||
modules_enabled = {
|
||||
"smacks";
|
||||
}
|
||||
authentication = "internal_hashed"
|
||||
smacks_max_old_sessions = 2000;
|
||||
|
||||
-- Proxy to jicofo's user JID, so that it doesn't have to register as a component.
|
||||
Component "focus.jitmeet.example.com" "client_proxy"
|
||||
|
||||
@@ -150,10 +150,18 @@ server {
|
||||
# alias /usr/share/jitsi-meet/load-test/libs/$1;
|
||||
#}
|
||||
|
||||
location = /_unlock {
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header Strict-Transport-Security 'max-age=63072000; includeSubDomains';
|
||||
add_header "Cache-Control" "no-cache, no-store";
|
||||
}
|
||||
|
||||
location ~ ^/conference-request/v1(\/.*)?$ {
|
||||
proxy_pass http://127.0.0.1:8888/conference-request/v1$1;
|
||||
add_header "Cache-Control" "no-cache, no-store";
|
||||
add_header 'Access-Control-Allow-Origin' '*';
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
|
||||
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Content-Type';
|
||||
}
|
||||
location ~ ^/([^/?&:'"]+)/conference-request/v1(\/.*)?$ {
|
||||
rewrite ^/([^/?&:'"]+)/conference-request/v1(\/.*)?$ /conference-request/v1$2;
|
||||
|
||||
1
globals.d.ts
vendored
1
globals.d.ts
vendored
@@ -18,7 +18,6 @@ declare global {
|
||||
JITSI_MEET_LITE_SDK?: boolean;
|
||||
interfaceConfig?: any;
|
||||
JitsiMeetJS?: any;
|
||||
JitsiMeetElectron?: any;
|
||||
PressureObserver?: any;
|
||||
PressureRecord?: any;
|
||||
ReactNativeWebView?: any;
|
||||
|
||||
1
globals.native.d.ts
vendored
1
globals.native.d.ts
vendored
@@ -40,6 +40,7 @@ interface IWindow {
|
||||
|
||||
interface INavigator {
|
||||
product: string;
|
||||
userAgent: string;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -36,7 +36,7 @@
|
||||
Component: JitsiMeetJS.app.entryPoints.APP
|
||||
})
|
||||
|
||||
const inIframe = () => {
|
||||
const isEmbedded = () => {
|
||||
try {
|
||||
return window.self !== window.top;
|
||||
} catch (e) {
|
||||
@@ -45,7 +45,7 @@
|
||||
};
|
||||
|
||||
const isElectron = navigator.userAgent.includes('Electron');
|
||||
const shouldRegisterWorker = !isElectron && !inIframe() && 'serviceWorker' in navigator;
|
||||
const shouldRegisterWorker = !isElectron && !isEmbedded() && 'serviceWorker' in navigator;
|
||||
|
||||
if (shouldRegisterWorker) {
|
||||
navigator.serviceWorker
|
||||
@@ -69,6 +69,11 @@
|
||||
|
||||
window.indexLoadedTime = window.performance.now();
|
||||
console.log("(TIME) index.html loaded:\t", indexLoadedTime);
|
||||
window.addEventListener('load', function() {
|
||||
window.loadedEventTime = window.performance.now();
|
||||
console.log("(TIME) window loaded event:\t", loadedEventTime);
|
||||
});
|
||||
|
||||
// XXX the code below listeners for errors and displays an error message
|
||||
// in the document body when any of the required files fails to load.
|
||||
// The intention is to prevent from displaying broken page.
|
||||
|
||||
@@ -41,14 +41,6 @@ var interfaceConfig = {
|
||||
*/
|
||||
DISABLE_PRESENCE_STATUS: false,
|
||||
|
||||
/**
|
||||
* Whether the ringing sound in the call/ring overlay is disabled. If
|
||||
* {@code undefined}, defaults to {@code false}.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
DISABLE_RINGING: false,
|
||||
|
||||
/**
|
||||
* Whether the speech to text transcription subtitles panel is disabled.
|
||||
* If {@code undefined}, defaults to {@code false}.
|
||||
@@ -70,9 +62,6 @@ var interfaceConfig = {
|
||||
|
||||
ENABLE_DIAL_OUT: true,
|
||||
|
||||
// DEPRECATED. Animation no longer supported.
|
||||
// ENABLE_FEEDBACK_ANIMATION: false,
|
||||
|
||||
FILM_STRIP_MAX_HEIGHT: 120,
|
||||
|
||||
GENERATE_ROOMNAMES_ON_WELCOME_PAGE: true,
|
||||
@@ -227,7 +216,7 @@ var interfaceConfig = {
|
||||
/**
|
||||
* Specify custom URL for downloading f droid app.
|
||||
*/
|
||||
// MOBILE_DOWNLOAD_LINK_F_DROID: 'https://f-droid.org/en/packages/org.jitsi.meet/',
|
||||
// MOBILE_DOWNLOAD_LINK_F_DROID: 'https://f-droid.org/packages/org.jitsi.meet/',
|
||||
|
||||
// Connection indicators (
|
||||
// CONNECTION_INDICATOR_AUTO_HIDE_ENABLED,
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
THIS_DIR=$(cd -P "$(dirname "$(readlink "${BASH_SOURCE[0]}" || echo "${BASH_SOURCE[0]}")")" && pwd)
|
||||
|
||||
. ${THIS_DIR}/../node_modules/react-native/scripts/find-node-for-xcode.sh
|
||||
|
||||
export NODE_BINARY=$(command -v node)
|
||||
export ENTRY_FILE="${PROJECT_DIR}/../../index.ios.js"
|
||||
|
||||
21
ios/Podfile
21
ios/Podfile
@@ -5,11 +5,15 @@ require Pod::Executable.execute_command('node', ['-p',
|
||||
{paths: [process.argv[1]]},
|
||||
)', __dir__]).strip
|
||||
|
||||
platform :ios, '13.4'
|
||||
platform :ios, '15.1'
|
||||
workspace 'jitsi-meet'
|
||||
|
||||
install! 'cocoapods', :deterministic_uuids => false
|
||||
|
||||
def cocoa_utilities
|
||||
pod 'CocoaLumberjack', '3.7.4'
|
||||
end
|
||||
|
||||
target 'JitsiMeet' do
|
||||
project 'app/app.xcodeproj'
|
||||
|
||||
@@ -28,7 +32,7 @@ target 'JitsiMeetSDK' do
|
||||
flags = get_default_flags()
|
||||
use_react_native!(
|
||||
:path => config[:reactNativePath],
|
||||
:hermes_enabled => false,
|
||||
:hermes_enabled => true,
|
||||
:fabric_enabled => false,
|
||||
# An absolute path to your application root.
|
||||
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
||||
@@ -45,7 +49,7 @@ target 'JitsiMeetSDK' do
|
||||
# Native pod dependencies
|
||||
#
|
||||
|
||||
pod 'CocoaLumberjack', '3.7.2'
|
||||
cocoa_utilities
|
||||
pod 'ObjectiveDropboxOfficial', '6.2.3'
|
||||
end
|
||||
|
||||
@@ -61,7 +65,7 @@ target 'JitsiMeetSDKLite' do
|
||||
config = use_native_modules!
|
||||
use_react_native!(
|
||||
:path => config[:reactNativePath],
|
||||
:hermes_enabled => false,
|
||||
:hermes_enabled => true,
|
||||
:fabric_enabled => false,
|
||||
# An absolute path to your application root.
|
||||
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
||||
@@ -70,7 +74,7 @@ target 'JitsiMeetSDKLite' do
|
||||
# Native pod dependencies
|
||||
#
|
||||
|
||||
pod 'CocoaLumberjack', '3.7.2'
|
||||
cocoa_utilities
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
@@ -79,7 +83,6 @@ post_install do |installer|
|
||||
use_native_modules![:reactNativePath],
|
||||
:mac_catalyst_enabled => false
|
||||
)
|
||||
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
||||
installer.pods_project.targets.each do |target|
|
||||
# https://github.com/CocoaPods/CocoaPods/issues/11402
|
||||
if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
|
||||
@@ -87,10 +90,14 @@ post_install do |installer|
|
||||
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
|
||||
end
|
||||
end
|
||||
|
||||
target.build_configurations.each do |config|
|
||||
config.build_settings['SUPPORTS_MACCATALYST'] = 'NO'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.4'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.1'
|
||||
config.build_settings['OTHER_SWIFT_FLAGS'] = '$(inherited) -no-verify-emitted-module-interface'
|
||||
end
|
||||
end
|
||||
|
||||
# Patch SocketRocket to support TLS 1.3
|
||||
%x(patch Pods/SocketRocket/SocketRocket/SRSecurityPolicy.m -N < patches/ws-tls13.diff)
|
||||
end
|
||||
|
||||
2265
ios/Podfile.lock
2265
ios/Podfile.lock
File diff suppressed because it is too large
Load Diff
39
ios/app/PrivacyInfo.xcprivacy
Normal file
39
ios/app/PrivacyInfo.xcprivacy
Normal file
@@ -0,0 +1,39 @@
|
||||
<?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>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>C617.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>1C8F.1</string>
|
||||
<string>C56D.1</string>
|
||||
<string>CA92.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategorySystemBootTime</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>35F9.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>NSPrivacyCollectedDataTypes</key>
|
||||
<array/>
|
||||
<key>NSPrivacyTracking</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -3,12 +3,10 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objectVersion = 60;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */; };
|
||||
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0B412F201EDEE95300B1A0A6 /* Main.storyboard */; };
|
||||
0B5418471F7C5D8C00A2DD86 /* MeetingRowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */; };
|
||||
0B7001701F7C51CC005944F4 /* InCallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B70016F1F7C51CC005944F4 /* InCallController.swift */; };
|
||||
0BEA5C291F7B8F73000D0AB4 /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C271F7B8F73000D0AB4 /* Interface.storyboard */; };
|
||||
@@ -19,11 +17,12 @@
|
||||
0BEA5C3B1F7B8F73000D0AB4 /* ComplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0BEA5C3A1F7B8F73000D0AB4 /* ComplicationController.swift */; };
|
||||
0BEA5C3D1F7B8F73000D0AB4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */; };
|
||||
0BEA5C411F7B8F73000D0AB4 /* JitsiMeetCompanion.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
|
||||
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 */; };
|
||||
2681BB562C7A0B42CFBA6719 /* libPods-JitsiMeet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D6152FF9E9F7B0E86F70A21D /* libPods-JitsiMeet.a */; };
|
||||
361974E2A13624D7735D619D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 5C1BE20ECD5DEEB48FED90B5 /* PrivacyInfo.xcprivacy */; };
|
||||
4341A9062CF0D63200940D93 /* hermes.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4341A9052CF0D63200940D93 /* hermes.xcframework */; };
|
||||
4341A9072CF0D63200940D93 /* hermes.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4341A9052CF0D63200940D93 /* hermes.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
4E90F9402632D1AB001102D4 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E90F93F2632D1AB001102D4 /* Atomic.swift */; };
|
||||
4EB06024260E026600F524C5 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4EC49B8625BED71300E76218 /* ReplayKit.framework */; };
|
||||
4EB06027260E026600F524C5 /* SampleHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB06026260E026600F524C5 /* SampleHandler.swift */; };
|
||||
@@ -31,7 +30,8 @@
|
||||
4EB0603C260E09D000F524C5 /* SocketConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB06039260E09D000F524C5 /* SocketConnection.swift */; };
|
||||
4EB0603D260E09D000F524C5 /* DarwinNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0603A260E09D000F524C5 /* DarwinNotificationCenter.swift */; };
|
||||
4EB0603E260E09D000F524C5 /* SampleUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0603B260E09D000F524C5 /* SampleUploader.swift */; };
|
||||
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */; };
|
||||
DEA0B7122D7EF16E0062A9F6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEA0B7112D7EF16E0062A9F6 /* ViewController.swift */; };
|
||||
DEA0B7142D7EF7590062A9F6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEA0B7132D7EF7590062A9F6 /* AppDelegate.swift */; };
|
||||
DEA9F289258A6EA800D4CD74 /* JitsiMeetSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; };
|
||||
DEA9F28A258A6EA800D4CD74 /* JitsiMeetSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
DED016F128ECBC9D009D5E8D /* WebRTC.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = DED016F028ECBC9D009D5E8D /* WebRTC.xcframework */; };
|
||||
@@ -74,6 +74,7 @@
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
DEA9F28A258A6EA800D4CD74 /* JitsiMeetSDK.framework in Embed Frameworks */,
|
||||
4341A9072CF0D63200940D93 /* hermes.xcframework in Embed Frameworks */,
|
||||
FD572B9927EDF32300A800FB /* GiphyUISDK.xcframework in Embed Frameworks */,
|
||||
DED016F228ECBC9D009D5E8D /* WebRTC.xcframework in Embed Frameworks */,
|
||||
);
|
||||
@@ -117,12 +118,8 @@
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0B26BE6D1EC5BC3C00EEFB41 /* JitsiMeet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
|
||||
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
|
||||
0B412F201EDEE95300B1A0A6 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||
0B5418461F7C5D8C00A2DD86 /* MeetingRowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeetingRowController.swift; sourceTree = "<group>"; };
|
||||
0B70016F1F7C51CC005944F4 /* InCallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InCallController.swift; sourceTree = "<group>"; };
|
||||
0BBD021F212EB69D00CCB19F /* Types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = "<group>"; };
|
||||
0BD6B4361EF82A6B00D1F4CD /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.framework"; sourceTree = "<group>"; };
|
||||
0BEA5C251F7B8F73000D0AB4 /* JitsiMeetCompanion.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = JitsiMeetCompanion.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0BEA5C281F7B8F73000D0AB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = "<group>"; };
|
||||
@@ -135,13 +132,11 @@
|
||||
0BEA5C3C1F7B8F73000D0AB4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
0BEA5C3E1F7B8F73000D0AB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* jitsi-meet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "jitsi-meet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
3E0F4ED943C0B12BE77F6B45 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
|
||||
4341A9052CF0D63200940D93 /* hermes.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = hermes.xcframework; path = "../Pods/hermes-engine/destroot/Library/Frameworks/universal/hermes.xcframework"; sourceTree = "<group>"; };
|
||||
4E90F93F2632D1AB001102D4 /* Atomic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = "<group>"; };
|
||||
4EB06023260E026600F524C5 /* JitsiMeetBroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = JitsiMeetBroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4EB06026260E026600F524C5 /* SampleHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleHandler.swift; sourceTree = "<group>"; };
|
||||
@@ -151,18 +146,19 @@
|
||||
4EB0603A260E09D000F524C5 /* DarwinNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarwinNotificationCenter.swift; sourceTree = "<group>"; };
|
||||
4EB0603B260E09D000F524C5 /* SampleUploader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SampleUploader.swift; sourceTree = "<group>"; };
|
||||
4EC49B8625BED71300E76218 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
|
||||
5C1BE20ECD5DEEB48FED90B5 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
|
||||
756FCE06C08D9B947653C98A /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "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>"; };
|
||||
D6152FF9E9F7B0E86F70A21D /* libPods-JitsiMeet.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-JitsiMeet.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DE050388256E904600DEE3A5 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/apple/WebRTC.xcframework"; sourceTree = "<group>"; };
|
||||
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FIRUtilities.m; sourceTree = "<group>"; };
|
||||
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FIRUtilities.h; sourceTree = "<group>"; };
|
||||
DEA0B7112D7EF16E0062A9F6 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
|
||||
DEA0B7132D7EF7590062A9F6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = JitsiMeetSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DED016F028ECBC9D009D5E8D /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = ../Pods/JitsiWebRTC/WebRTC.xcframework; sourceTree = "<group>"; };
|
||||
DEFDBBDB25656E3B00344B23 /* WebRTC.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = WebRTC.xcframework; path = "../../node_modules/react-native-webrtc/ios/WebRTC.xcframework"; sourceTree = "<group>"; };
|
||||
E58801132278944E008B0561 /* JitsiMeetContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetContext.swift; sourceTree = "<group>"; };
|
||||
E5C97B62227A1EB400199214 /* JitsiMeetCommands.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JitsiMeetCommands.swift; sourceTree = "<group>"; };
|
||||
FD572B9727EDF32300A800FB /* GiphyUISDK.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = GiphyUISDK.xcframework; path = ../Pods/Giphy/GiphySDK/GiphyUISDK.xcframework; sourceTree = "<group>"; };
|
||||
FD572B9727EDF32300A800FB /* GiphyUISDK.xcframework */ = {isa = PBXFileReference; expectedSignature = "AppleDeveloperProgram:925PGC4MV7:Giphy, Inc."; lastKnownFileType = wrapper.xcframework; name = GiphyUISDK.xcframework; path = ../Pods/Giphy/GiphySDK/GiphyUISDK.xcframework; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -181,6 +177,7 @@
|
||||
DEA9F289258A6EA800D4CD74 /* JitsiMeetSDK.framework in Frameworks */,
|
||||
FD572B9827EDF32300A800FB /* GiphyUISDK.xcframework in Frameworks */,
|
||||
2681BB562C7A0B42CFBA6719 /* libPods-JitsiMeet.a in Frameworks */,
|
||||
4341A9062CF0D63200940D93 /* hermes.xcframework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -205,6 +202,7 @@
|
||||
0B26BE711EC5BC4D00EEFB41 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4341A9052CF0D63200940D93 /* hermes.xcframework */,
|
||||
DED016F028ECBC9D009D5E8D /* WebRTC.xcframework */,
|
||||
FD572B9727EDF32300A800FB /* GiphyUISDK.xcframework */,
|
||||
DEA9F288258A6EA800D4CD74 /* JitsiMeetSDK.framework */,
|
||||
@@ -249,18 +247,11 @@
|
||||
13B07FAE1A68108700A75B9A /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.m */,
|
||||
DE4C456021DE1E4E00EA0709 /* FIRUtilities.h */,
|
||||
DE4C455F21DE1E4E00EA0709 /* FIRUtilities.m */,
|
||||
DEA0B7132D7EF7590062A9F6 /* AppDelegate.swift */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
0B412F201EDEE95300B1A0A6 /* Main.storyboard */,
|
||||
0BBD021F212EB69D00CCB19F /* Types.h */,
|
||||
0B412F1D1EDEE6E800B1A0A6 /* ViewController.h */,
|
||||
0B412F1E1EDEE6E800B1A0A6 /* ViewController.m */,
|
||||
DEA0B7112D7EF16E0062A9F6 /* ViewController.swift */,
|
||||
);
|
||||
path = src;
|
||||
sourceTree = "<group>";
|
||||
@@ -293,6 +284,7 @@
|
||||
0BEA5C351F7B8F73000D0AB4 /* WatchKit extension */,
|
||||
4EB06025260E026600F524C5 /* JitsiMeetBroadcast Extension */,
|
||||
CDD71F5E1157E9F283DF92A8 /* Pods */,
|
||||
5C1BE20ECD5DEEB48FED90B5 /* PrivacyInfo.xcprivacy */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
@@ -373,6 +365,7 @@
|
||||
DE11877A21EE09640078D059 /* Setup Google reverse URL handler */,
|
||||
0BB7DA181EC9E695007AAE98 /* Adjust ATS */,
|
||||
DE4F6D6E22005C0400DE699E /* Setup Dropbox */,
|
||||
E9D850368D253EFA8AB3B8D1 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -410,7 +403,7 @@
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1240;
|
||||
LastUpgradeCheck = 1020;
|
||||
ORGANIZATIONNAME = Facebook;
|
||||
ORGANIZATIONNAME = Jitsi;
|
||||
TargetAttributes = {
|
||||
0BEA5C241F7B8F73000D0AB4 = {
|
||||
CreatedOnToolsVersion = 9.0;
|
||||
@@ -423,6 +416,7 @@
|
||||
ProvisioningStyle = Automatic;
|
||||
};
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
LastSwiftMigration = 1620;
|
||||
SystemCapabilities = {
|
||||
com.apple.SafariKeychain = {
|
||||
enabled = 1;
|
||||
@@ -480,9 +474,9 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0B412F211EDEE95300B1A0A6 /* Main.storyboard in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
|
||||
361974E2A13624D7735D619D /* PrivacyInfo.xcprivacy in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -503,7 +497,7 @@
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH",
|
||||
$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH,
|
||||
);
|
||||
name = "Adjust ATS";
|
||||
outputPaths = (
|
||||
@@ -536,7 +530,7 @@
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$PROJECT_DIR/app.entitlements",
|
||||
$PROJECT_DIR/app.entitlements,
|
||||
);
|
||||
name = "Update App Entitlements";
|
||||
outputFileListPaths = (
|
||||
@@ -578,7 +572,7 @@
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH",
|
||||
$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH,
|
||||
);
|
||||
name = "Setup Google reverse URL handler";
|
||||
outputFileListPaths = (
|
||||
@@ -598,7 +592,7 @@
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH",
|
||||
$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH,
|
||||
);
|
||||
name = "Setup Dropbox";
|
||||
outputFileListPaths = (
|
||||
@@ -609,6 +603,23 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "INFO_PLIST=\"$BUILT_PRODUCTS_DIR/$INFOPLIST_PATH\"\nDROPBOX_KEY_FILE=\"$PROJECT_DIR/dropbox.key\"\n\nif [[ -f $DROPBOX_KEY_FILE ]]; then\n /usr/libexec/PlistBuddy -c \"Delete :LSApplicationQueriesSchemes\" $INFO_PLIST\n /usr/libexec/PlistBuddy -c \"Add :LSApplicationQueriesSchemes array\" $INFO_PLIST\n /usr/libexec/PlistBuddy -c \"Add :LSApplicationQueriesSchemes:0 string 'dbapi-2'\" $INFO_PLIST\n /usr/libexec/PlistBuddy -c \"Add :LSApplicationQueriesSchemes:1 string 'dbapi-8-emm'\" $INFO_PLIST\n\n DROPBOX_KEY=$(head -n 1 $DROPBOX_KEY_FILE)\n /usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:2:CFBundleURLName string dropbox\" $INFO_PLIST\n /usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:2:CFBundleURLSchemes array\" $INFO_PLIST\n /usr/libexec/PlistBuddy -c \"Add :CFBundleURLTypes:2:CFBundleURLSchemes:0 string $DROPBOX_KEY\" $INFO_PLIST\nfi\n";
|
||||
};
|
||||
E9D850368D253EFA8AB3B8D1 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
@@ -630,10 +641,8 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0B412F1F1EDEE6E800B1A0A6 /* ViewController.m in Sources */,
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
|
||||
DE4C456121DE1E4E00EA0709 /* FIRUtilities.m in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
DEA0B7122D7EF16E0062A9F6 /* ViewController.swift in Sources */,
|
||||
DEA0B7142D7EF7590062A9F6 /* AppDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -838,8 +847,8 @@
|
||||
baseConfigurationReference = 756FCE06C08D9B947653C98A /* Pods-JitsiMeet.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconDebug;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = app.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
@@ -860,6 +869,13 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet;
|
||||
PRODUCT_NAME = "jitsi-meet";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 6.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -868,8 +884,8 @@
|
||||
baseConfigurationReference = 3E0F4ED943C0B12BE77F6B45 /* Pods-JitsiMeet.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
|
||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIconRelease;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = app.entitlements;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
@@ -889,6 +905,12 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet;
|
||||
PRODUCT_NAME = "jitsi-meet";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_VERSION = 6.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -920,6 +942,10 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.broadcast.extension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -955,6 +981,10 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = org.jitsi.meet.broadcast.extension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||
SUPPORTS_MACCATALYST = NO;
|
||||
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -965,8 +995,9 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CC = "";
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -991,6 +1022,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CXX = "";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||
@@ -1014,19 +1046,19 @@
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD = "";
|
||||
LDPLUSPLUS = "";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CFLAGS = "$(inherited)";
|
||||
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-Wl",
|
||||
"-ld_classic",
|
||||
);
|
||||
OTHER_LDFLAGS = "$(inherited)";
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
USE_HERMES = true;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -1034,8 +1066,9 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CC = "";
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++20";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
@@ -1060,6 +1093,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
CXX = "";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||
@@ -1079,19 +1113,18 @@
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.4;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.1;
|
||||
LD = "";
|
||||
LDPLUSPLUS = "";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CFLAGS = "$(inherited)";
|
||||
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-Wl",
|
||||
"-ld_classic",
|
||||
);
|
||||
OTHER_LDFLAGS = "$(inherited)";
|
||||
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
|
||||
SDKROOT = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
USE_HERMES = true;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2017-present Atlassian Pty Ltd
|
||||
*
|
||||
* 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 <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||
|
||||
@property (nonatomic, strong) UIWindow *window;
|
||||
|
||||
@end
|
||||
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* Copyright @ 2018-present 8x8, Inc.
|
||||
* Copyright @ 2017-2018 Atlassian Pty Ltd
|
||||
*
|
||||
* 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 "AppDelegate.h"
|
||||
#import "FIRUtilities.h"
|
||||
#import "Types.h"
|
||||
#import "ViewController.h"
|
||||
|
||||
@import Firebase;
|
||||
@import JitsiMeetSDK;
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||
JitsiMeet *jitsiMeet = [JitsiMeet sharedInstance];
|
||||
|
||||
jitsiMeet.conferenceActivityType = JitsiMeetConferenceActivityType;
|
||||
jitsiMeet.customUrlScheme = @"org.jitsi.meet";
|
||||
jitsiMeet.universalLinkDomains = @[@"meet.jit.si", @"alpha.jitsi.net", @"beta.meet.jit.si"];
|
||||
|
||||
jitsiMeet.defaultConferenceOptions = [JitsiMeetConferenceOptions fromBuilder:^(JitsiMeetConferenceOptionsBuilder *builder) {
|
||||
[builder setFeatureFlag:@"welcomepage.enabled" withBoolean:YES];
|
||||
[builder setFeatureFlag:@"resolution" withValue:@(360)];
|
||||
[builder setFeatureFlag:@"ios.screensharing.enabled" withBoolean:YES];
|
||||
[builder setFeatureFlag:@"ios.recording.enabled" withBoolean:YES];
|
||||
}];
|
||||
|
||||
[jitsiMeet application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
|
||||
// Initialize Crashlytics and Firebase if a valid GoogleService-Info.plist file was provided.
|
||||
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
|
||||
NSLog(@"Enabling Firebase");
|
||||
[FIRApp configure];
|
||||
// Crashlytics defaults to disabled with the FirebaseCrashlyticsCollectionEnabled Info.plist key.
|
||||
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:![jitsiMeet isCrashReportingDisabled]];
|
||||
}
|
||||
|
||||
ViewController *rootController = (ViewController *)self.window.rootViewController;
|
||||
[jitsiMeet showSplashScreen:rootController.view];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void) applicationWillTerminate:(UIApplication *)application {
|
||||
NSLog(@"Application will terminate!");
|
||||
// Try to leave the current meeting graceefully.
|
||||
ViewController *rootController = (ViewController *)self.window.rootViewController;
|
||||
[rootController terminate];
|
||||
}
|
||||
|
||||
#pragma mark Linking delegate methods
|
||||
|
||||
- (BOOL)application:(UIApplication *)application
|
||||
continueUserActivity:(NSUserActivity *)userActivity
|
||||
restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring>> *restorableObjects))restorationHandler {
|
||||
|
||||
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
|
||||
// 1. Attempt to handle Universal Links through Firebase in order to support
|
||||
// its Dynamic Links (which we utilize for the purposes of deferred deep
|
||||
// linking).
|
||||
BOOL handled
|
||||
= [[FIRDynamicLinks dynamicLinks]
|
||||
handleUniversalLink:userActivity.webpageURL
|
||||
completion:^(FIRDynamicLink * _Nullable dynamicLink, NSError * _Nullable error) {
|
||||
NSURL *firebaseUrl = [FIRUtilities extractURL:dynamicLink];
|
||||
if (firebaseUrl != nil) {
|
||||
userActivity.webpageURL = firebaseUrl;
|
||||
[[JitsiMeet sharedInstance] application:application
|
||||
continueUserActivity:userActivity
|
||||
restorationHandler:restorationHandler];
|
||||
}
|
||||
}];
|
||||
|
||||
if (handled) {
|
||||
return handled;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Default to plain old, non-Firebase-assisted Universal Links.
|
||||
return [[JitsiMeet sharedInstance] application:application
|
||||
continueUserActivity:userActivity
|
||||
restorationHandler:restorationHandler];
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)app
|
||||
openURL:(NSURL *)url
|
||||
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
|
||||
|
||||
// This shows up during a reload in development, skip it.
|
||||
// https://github.com/firebase/firebase-ios-sdk/issues/233
|
||||
if ([[url absoluteString] containsString:@"google/link/?dismiss=1&is_weak_match=1"]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSURL *openUrl = url;
|
||||
|
||||
if ([FIRUtilities appContainsRealServiceInfoPlist]) {
|
||||
// Process Firebase Dynamic Links
|
||||
FIRDynamicLink *dynamicLink = [[FIRDynamicLinks dynamicLinks] dynamicLinkFromCustomSchemeURL:url];
|
||||
NSURL *firebaseUrl = [FIRUtilities extractURL:dynamicLink];
|
||||
if (firebaseUrl != nil) {
|
||||
openUrl = firebaseUrl;
|
||||
}
|
||||
}
|
||||
|
||||
return [[JitsiMeet sharedInstance] application:app
|
||||
openURL:openUrl
|
||||
options:options];
|
||||
}
|
||||
|
||||
- (UIInterfaceOrientationMask)application:(UIApplication *)application
|
||||
supportedInterfaceOrientationsForWindow:(UIWindow *)window {
|
||||
return [[JitsiMeet sharedInstance] application:application
|
||||
supportedInterfaceOrientationsForWindow:window];
|
||||
}
|
||||
|
||||
@end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user