Compare commits
3040 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7c013de7b9 | ||
|
f0f0aafa1b | ||
|
c2d5ded335 | ||
|
1a5291537d | ||
|
d6ef3ea08e | ||
|
fac9a65f54 | ||
|
93fc64ff33 | ||
|
e097c92458 | ||
|
e91dbfbf2c | ||
|
801f2860e2 | ||
|
1ffc3a4f53 | ||
|
844fe2c4cd | ||
|
69efb45fb7 | ||
|
1103d7c112 | ||
|
c88072e55f | ||
|
e041d404f3 | ||
|
5b07af2c12 | ||
|
de73539d2b | ||
|
f7ed94c6e9 | ||
|
1f1eeccc32 | ||
|
1d449c84fe | ||
|
0750c7763c | ||
|
dbaaa07dad | ||
|
7446b12827 | ||
|
d4c8f56c6e | ||
|
2ea45185d4 | ||
|
50ba131350 | ||
|
b2df107f17 | ||
|
2b60affd9a | ||
|
e771b21ea3 | ||
|
b20bbc1295 | ||
|
609ceb7fa4 | ||
|
aac3f379a7 | ||
|
d46ae83dc4 | ||
|
561b89830a | ||
|
b69d8ad71a | ||
|
ec0a04e893 | ||
|
8307245120 | ||
|
5431584b3c | ||
|
426782a001 | ||
|
7eb9941f8c | ||
|
f585deb1d7 | ||
|
26c4c7e467 | ||
|
b2b1bebc32 | ||
|
793c0ababb | ||
|
cf1628228a | ||
|
7f433ac4a0 | ||
|
48f03c0953 | ||
|
e75d25f00c | ||
|
e22e70c5ba | ||
|
a8e4be9146 | ||
|
a9ee94e3f0 | ||
|
cdaddb15af | ||
|
a724f844f7 | ||
|
2546061933 | ||
|
f4db593009 | ||
|
ce92533525 | ||
|
6d5e1b2285 | ||
|
6388d6b91b | ||
|
54e501127c | ||
|
6bcd96d629 | ||
|
996fe71de9 | ||
|
08b38cd6ad | ||
|
d649cb4aa5 | ||
|
61be2dd3df | ||
|
b6dda73cb1 | ||
|
0c77f49ffd | ||
|
76f4a1b4f1 | ||
|
466f9bd532 | ||
|
992edb2ee2 | ||
|
8de4b0bb20 | ||
|
e21c8792e6 | ||
|
54f6440bcf | ||
|
819f0c021e | ||
|
bc2f49fa31 | ||
|
d3a3ba8079 | ||
|
1540f13444 | ||
|
245d580825 | ||
|
2578423c91 | ||
|
1762451bc0 | ||
|
38e4984a4a | ||
|
9d7c49306a | ||
|
6b605b2e98 | ||
|
cf0242f23a | ||
|
56e8325efe | ||
|
d91ed2985d | ||
|
5f9f69b4dc | ||
|
da33cbedda | ||
|
2d91865277 | ||
|
003f5fab1f | ||
|
2a365d6776 | ||
|
55f5f90c45 | ||
|
bd3bdd6996 | ||
|
0cf485d873 | ||
|
75e06d43c5 | ||
|
afa1cf7d6c | ||
|
a6f909b942 | ||
|
ae55ee82a7 | ||
|
037e53f385 | ||
|
a28dfdc48e | ||
|
81bdf506bc | ||
|
f253aa6b37 | ||
|
0702eee179 | ||
|
c4a019f0d3 | ||
|
22c10f5ada | ||
|
7249c7d25a | ||
|
6e8d93bc6f | ||
|
963c30a275 | ||
|
474ade01cf | ||
|
18d4b66c97 | ||
|
3a9b80127f | ||
|
78c1a0acf4 | ||
|
4ee34126bd | ||
|
4f59ec37ca | ||
|
c34fea2932 | ||
|
c11a50f7ff | ||
|
b475f36b5a | ||
|
11367488e6 | ||
|
a7d8e74468 | ||
|
a25b93197d | ||
|
83f2ff5d82 | ||
|
868c056ddd | ||
|
0106adf36c | ||
|
b6a93be611 | ||
|
61291f7337 | ||
|
05013d2559 | ||
|
3240cadb94 | ||
|
594ee61a99 | ||
|
c85b0124e3 | ||
|
61bc19fc96 | ||
|
3ea3d0fc91 | ||
|
f1f1613f00 | ||
|
68dd206140 | ||
|
17e8581ef0 | ||
|
7ff45738e0 | ||
|
c9eacec449 | ||
|
3e78098c43 | ||
|
cbdacc199a | ||
|
cc01f25d8f | ||
|
9f3176c49c | ||
|
7ae2b34a9e | ||
|
d1bec21759 | ||
|
073e6227d6 | ||
|
761d8d89b0 | ||
|
f203fa5c58 | ||
|
9ccb22015a | ||
|
6d1c53c7ed | ||
|
855e7e02ce | ||
|
df3bb5b212 | ||
|
5768e45809 | ||
|
83584fab44 | ||
|
c234e12302 | ||
|
4645a8c633 | ||
|
cfb54f7608 | ||
|
7195ee9a69 | ||
|
ba6dffc0bf | ||
|
d3acf7e862 | ||
|
5c6d710f2d | ||
|
fa22a4a747 | ||
|
94aa0a02fe | ||
|
ab23d9b715 | ||
|
c5ce208d07 | ||
|
e7f7c0ba78 | ||
|
b082a009a7 | ||
|
cdeb2663fe | ||
|
a5e979b763 | ||
|
be0cadb3c7 | ||
|
6c4836e27e | ||
|
36a553a886 | ||
|
13938f2ab3 | ||
|
a755536a2f | ||
|
4a5dbde8d3 | ||
|
5744939c05 | ||
|
8c68126ed9 | ||
|
3c37d4c1b0 | ||
|
a9316b2f7e | ||
|
3e420033c5 | ||
|
571f05bcfb | ||
|
4e73705378 | ||
|
611e1185c8 | ||
|
b90d8e6238 | ||
|
ad3573226c | ||
|
1cc0825b54 | ||
|
87ac4ec5d4 | ||
|
8344506b05 | ||
|
9da3eec64f | ||
|
621c6c8773 | ||
|
d5e76c515e | ||
|
9fcf7263b5 | ||
|
0059fdf174 | ||
|
3d291c04c9 | ||
|
ca4b91a98f | ||
|
b0ba62aa31 | ||
|
abf763f454 | ||
|
15597eb041 | ||
|
00b16db7cc | ||
|
ff8a208012 | ||
|
7732bd47ce | ||
|
42a5680374 | ||
|
5d8f365520 | ||
|
938cd32ddd | ||
|
80396fcd39 | ||
|
7b97981bb5 | ||
|
b263273c87 | ||
|
427dc784fe | ||
|
7e4725c091 | ||
|
9b332f7a32 | ||
|
2b780a8b76 | ||
|
0518e5f18d | ||
|
0412b87ad1 | ||
|
2fe7caa580 | ||
|
d53650c8ae | ||
|
930b8da3b3 | ||
|
c48f153b0d | ||
|
68cd06f1fb | ||
|
c7afcf4ff2 | ||
|
3491774e7b | ||
|
ea6fde3ed0 | ||
|
267a7a36ff | ||
|
9a69bb9656 | ||
|
28aef1067b | ||
|
690a9eaa21 | ||
|
24d76b1d32 | ||
|
173458ed6c | ||
|
cebef970d3 | ||
|
4aa349ddd6 | ||
|
a918d28ded | ||
|
b1660c077e | ||
|
38075b4e8d | ||
|
174ecb10d9 | ||
|
5ef1fd62a7 | ||
|
d095784bfc | ||
|
1ac1d32b3a | ||
|
518b207f63 | ||
|
16ba5d2416 | ||
|
ac6e7652bd | ||
|
cc3e090855 | ||
|
30e4fdebd7 | ||
|
27e5626fcf | ||
|
8878cb41ee | ||
|
10575698de | ||
|
451750f08a | ||
|
6f04f4109d | ||
|
929d711149 | ||
|
b52f8b1dbf | ||
|
aa0a851b35 | ||
|
4ddc8e706d | ||
|
da2a0abf45 | ||
|
53a0e0ce10 | ||
|
7f02c0596e | ||
|
e081c3b249 | ||
|
8db4da5473 | ||
|
d389581d96 | ||
|
018574a21e | ||
|
9e3eb993ee | ||
|
6c64fb2169 | ||
|
2e70808bbd | ||
|
18bf9856fe | ||
|
f09ee5016a | ||
|
4d3c4b5afc | ||
|
7de2494af2 | ||
|
409d7e50bb | ||
|
c1222737d6 | ||
|
d02da1b97e | ||
|
a8c6b1cdf7 | ||
|
dba65dcd22 | ||
|
706736273c | ||
|
838340bbc8 | ||
|
75ec9ba3d9 | ||
|
876359539f | ||
|
6cdb192955 | ||
|
1946058c8e | ||
|
2927f1ff1c | ||
|
e230cd8ee3 | ||
|
45225e883e | ||
|
bb9a08d429 | ||
|
6ddcd046d4 | ||
|
88a4dfd094 | ||
|
7828e3f501 | ||
|
b4b302c1f2 | ||
|
487ef870f9 | ||
|
6957768567 | ||
|
7da8b13cde | ||
|
a027ef29e5 | ||
|
211c158e23 | ||
|
338650cea7 | ||
|
2d4eeb64c5 | ||
|
4f98031c6d | ||
|
3813f6d659 | ||
|
6687a74f5c | ||
|
545e13c843 | ||
|
995ec25990 | ||
|
09040b7095 | ||
|
5a69b33600 | ||
|
c8c4e10822 | ||
|
2f616cb6c5 | ||
|
776d7699bc | ||
|
f3578e2538 | ||
|
8022430f0d | ||
|
eb72d0c6d3 | ||
|
ae29cbdc34 | ||
|
cf59c7db95 | ||
|
924fac84b2 | ||
|
db0a958708 | ||
|
b31dfcfe4f | ||
|
bba2daf0fc | ||
|
23e05200b5 | ||
|
0fd8641cf6 | ||
|
26c01d46a7 | ||
|
42d1bf57f6 | ||
|
351793d456 | ||
|
03428ea9f5 | ||
|
b321838502 | ||
|
b915c91c86 | ||
|
f83b478008 | ||
|
2bdb425085 | ||
|
45a0586329 | ||
|
74283e7d50 | ||
|
6f4c307854 | ||
|
69cd0e3ea2 | ||
|
a5094f97d5 | ||
|
163c05d5cf | ||
|
903936368d | ||
|
3eba43f3fa | ||
|
d8a1939c69 | ||
|
5b74eb3bca | ||
|
071611b81c | ||
|
5461fd4060 | ||
|
5203d15409 | ||
|
989f1c6268 | ||
|
544345bbf3 | ||
|
bd9da8eaa6 | ||
|
68a5ba9a01 | ||
|
ed9ae07e52 | ||
|
9b0c2e420d | ||
|
60aaa2a39c | ||
|
8d30658fa5 | ||
|
32fd3be732 | ||
|
705b6176f1 | ||
|
d996c77c03 | ||
|
49cad8feec | ||
|
ca75eae0aa | ||
|
21271b6510 | ||
|
439029467a | ||
|
eb30b9fae9 | ||
|
38843f74ab | ||
|
91c86c1a45 | ||
|
5541c2e190 | ||
|
f2ba236130 | ||
|
4cb7754b77 | ||
|
3473a7ef5e | ||
|
c9535509e8 | ||
|
3d578c147c | ||
|
43ac66feb3 | ||
|
5e2f091ec1 | ||
|
752bde413d | ||
|
e6949c85fb | ||
|
c1cb23d728 | ||
|
4007982db6 | ||
|
a9f5ed3869 | ||
|
08964d8548 | ||
|
5186ee6e43 | ||
|
c2fc9fe0ee | ||
|
280d3f22a7 | ||
|
a19ca8a820 | ||
|
7ba1116349 | ||
|
e8862b3aaa | ||
|
a96cc19eb6 | ||
|
3d975b7fba | ||
|
d54571d0a6 | ||
|
75071cf1d9 | ||
|
4bd538e448 | ||
|
0956baecf9 | ||
|
e4968c4119 | ||
|
283e10dfef | ||
|
1c43f92e49 | ||
|
ca7796114c | ||
|
ed822becc6 | ||
|
7057b2970b | ||
|
62791e4b36 | ||
|
237cb63fc2 | ||
|
42ab7f1b4f | ||
|
8e11ba21ed | ||
|
24a9ddaa5e | ||
|
6190fb3511 | ||
|
2d9043fbed | ||
|
682dff9c1c | ||
|
9339b7e31d | ||
|
7667ef686d | ||
|
4d4fe687ac | ||
|
7152dead1d | ||
|
40b9f03132 | ||
|
19d421df84 | ||
|
c889deaab1 | ||
|
416f57b1d7 | ||
|
dda2685bd8 | ||
|
b43f3b3b6a | ||
|
a0c8a8e97c | ||
|
28bfea6af0 | ||
|
f3bc39a0c5 | ||
|
c7efd1feb9 | ||
|
c31d368d0d | ||
|
5237eb0638 | ||
|
7869d731d4 | ||
|
c603ec0b38 | ||
|
555bf1f0ae | ||
|
8bdf384563 | ||
|
19524eaa82 | ||
|
9bbae825e2 | ||
|
3e9cb987a1 | ||
|
dacb9cd86c | ||
|
b9d7333998 | ||
|
e14b507b27 | ||
|
431ac5aa2d | ||
|
78fe7e5c16 | ||
|
c2c9e37a36 | ||
|
5d3682cd44 | ||
|
2a19726e49 | ||
|
c08c652080 | ||
|
9089c54990 | ||
|
679d9bae1c | ||
|
19315fc65e | ||
|
770041eceb | ||
|
1161dcb299 | ||
|
fa7b0a24a7 | ||
|
48354c7793 | ||
|
fcd9fe7d5a | ||
|
a36d5684b8 | ||
|
be20f9b455 | ||
|
dd150c6d7e | ||
|
bd5ac514ef | ||
|
bd926fa74b | ||
|
167144b504 | ||
|
5faaabf2f4 | ||
|
1933fc948c | ||
|
83df430d17 | ||
|
ec60d7d0b6 | ||
|
f9ccb0e8de | ||
|
1109d9f88a | ||
|
32b7cc64fb | ||
|
a6724b5f75 | ||
|
8a35bfcc31 | ||
|
0c037184f8 | ||
|
3e563a37a2 | ||
|
e5cbf9e3a3 | ||
|
cafe86e675 | ||
|
a911492a9e | ||
|
d889598b20 | ||
|
c4577f28b2 | ||
|
f5af15454e | ||
|
ee96d5c68f | ||
|
6c56b5f45b | ||
|
1058bfecf4 | ||
|
f0afd5ceea | ||
|
9881c9f61c | ||
|
89a7ec6d4b | ||
|
c426364618 | ||
|
cc5264a587 | ||
|
42bc4d2445 | ||
|
2cc5d46cd3 | ||
|
3feb67ad32 | ||
|
aa6c7afbbd | ||
|
c6ba296028 | ||
|
51b86e21f6 | ||
|
04914be442 | ||
|
3133935063 | ||
|
088608011b | ||
|
6d0f9baba4 | ||
|
3b21400bb8 | ||
|
1c3a279b8a | ||
|
6236b01189 | ||
|
e42906f08a | ||
|
b53ba2b98e | ||
|
7bd8d54d5c | ||
|
c785ea63e7 | ||
|
b78f1dbb93 | ||
|
056b9df65e | ||
|
589c301606 | ||
|
476f721f5e | ||
|
a813610c04 | ||
|
41dd67f1c1 | ||
|
63b068f426 | ||
|
637c54073a | ||
|
4171311095 | ||
|
bb5d5ffc92 | ||
|
d07a95204b | ||
|
2736247d09 | ||
|
93ffb116b7 | ||
|
396dd5e36e | ||
|
096abd7ebf | ||
|
694397efc1 | ||
|
ffe9a03d3e | ||
|
b2556cb293 | ||
|
c029564590 | ||
|
0cfea40b24 | ||
|
9c53f0f881 | ||
|
50ddd3cf31 | ||
|
6c7eb6ea8c | ||
|
412fc78c9a | ||
|
0da0857970 | ||
|
90e0006cae | ||
|
a570528f6c | ||
|
2d4cbde72c | ||
|
f5ae95d7f1 | ||
|
c5e6e004dd | ||
|
d9c209aa87 | ||
|
8f80f375f0 | ||
|
2cf2233643 | ||
|
36564f0c75 | ||
|
8dbb984ead | ||
|
74ffbd4679 | ||
|
82b23d9a13 | ||
|
0a9b234272 | ||
|
3a06ef3959 | ||
|
ed4676bb6c | ||
|
893ebd9690 | ||
|
3c069f8b79 | ||
|
93580c902f | ||
|
e1abd5a051 | ||
|
27fc5f265f | ||
|
5b618ba1f3 | ||
|
a6f56ace24 | ||
|
0d93105bcd | ||
|
7c2fea8623 | ||
|
e2a89c22da | ||
|
03715e0939 | ||
|
4d9b9cb959 | ||
|
d759636d95 | ||
|
c8a8e0f2da | ||
|
b004dfbdf2 | ||
|
40ea91cce4 | ||
|
abcb02d4aa | ||
|
cd983de058 | ||
|
f6cc05634f | ||
|
f14b390849 | ||
|
431f5d76ce | ||
|
dd50399a21 | ||
|
eb17463b68 | ||
|
88e05ffd05 | ||
|
a5079f5243 | ||
|
422c681e55 | ||
|
9531a38486 | ||
|
493cd2a0e3 | ||
|
f7f7e808f2 | ||
|
217c88f342 | ||
|
cf70916764 | ||
|
b84d7f0834 | ||
|
dffdcfe1e4 | ||
|
11deaa049e | ||
|
7b969ebd74 | ||
|
245aa6e9e7 | ||
|
163f4cfaf2 | ||
|
33a5cc1488 | ||
|
9a8f45fc6f | ||
|
e3ca89a81b | ||
|
8696650f20 | ||
|
942f050579 | ||
|
89e7e28bfa | ||
|
221eddd995 | ||
|
32d42794dd | ||
|
14c71d6c07 | ||
|
cce4d7d4d9 | ||
|
708cdad38b | ||
|
bc889cbcf4 | ||
|
7c9b943733 | ||
|
e3b88d1162 | ||
|
d80927a8f9 | ||
|
27050b911b | ||
|
a3a2c0a9a8 | ||
|
92ceb0e8fb | ||
|
835a36986d | ||
|
4c599d3d40 | ||
|
67057bfac4 | ||
|
fbc3f47eeb | ||
|
79caa4e510 | ||
|
fa191136cc | ||
|
15d93c8aeb | ||
|
4f5632b916 | ||
|
8e6e6736a3 | ||
|
804afc9a1d | ||
|
bcd86977d2 | ||
|
a8b5a5227f | ||
|
d2398a7abb | ||
|
0e908ad882 | ||
|
c0a83d1916 | ||
|
920856512e | ||
|
62b703ca88 | ||
|
b125b47366 | ||
|
bc6debea89 | ||
|
d5523b18b9 | ||
|
1f69c7e992 | ||
|
d9757cc660 | ||
|
1cb3522e73 | ||
|
7583b0a358 | ||
|
77863e2e88 | ||
|
564404d4ae | ||
|
e2320cd3b2 | ||
|
fd92d6559c | ||
|
6146925757 | ||
|
baef9f5aa7 | ||
|
ae6de8fdf1 | ||
|
b888d13e62 | ||
|
1070c23608 | ||
|
e8d084b855 | ||
|
5b278f704c | ||
|
a87e44bae4 | ||
|
85bc5f54aa | ||
|
41f46d0810 | ||
|
9ce1222fd0 | ||
|
8fb3c68573 | ||
|
eb7ee49096 | ||
|
084b2e8e04 | ||
|
675e4579ac | ||
|
d2880432da | ||
|
6daae83c3a | ||
|
f9e4b689b7 | ||
|
2c30050f3d | ||
|
13530abdeb | ||
|
5eb50750e2 | ||
|
9ef873526a | ||
|
0046fe25c5 | ||
|
fdb13f0b77 | ||
|
029d8574f1 | ||
|
a552c57d67 | ||
|
d5f83acaf5 | ||
|
c50c028c9e | ||
|
465b33b006 | ||
|
4df68479ac | ||
|
3ec25f3634 | ||
|
c29e4648ea | ||
|
9ed8f26d7c | ||
|
b82b378cfe | ||
|
1eac90e5b1 | ||
|
206e68b1d2 | ||
|
1de5cd2e61 | ||
|
264bc52bcc | ||
|
2626a761ea | ||
|
1359c6be1d | ||
|
ca0da2c509 | ||
|
57d55e05e7 | ||
|
702d21fbc3 | ||
|
796ba72bde | ||
|
92a6e9ea5a | ||
|
822ce41b54 | ||
|
0c7f4c2af5 | ||
|
4e1783f856 | ||
|
f6aee3d64e | ||
|
514263ae12 | ||
|
507d5d3758 | ||
|
16b6678aa2 | ||
|
af8b400bf4 | ||
|
a32d7f78bb | ||
|
94b135ae95 | ||
|
e42cad68b4 | ||
|
8a44ee9d50 | ||
|
5bf4fffd2f | ||
|
82b21e6a09 | ||
|
9216eed1b8 | ||
|
c81c5c4801 | ||
|
14bf0038a9 | ||
|
a8f2fd3f4b | ||
|
7223959fda | ||
|
cf5d112e31 | ||
|
b24608891e | ||
|
579efb016a | ||
|
2b1b9d35a2 | ||
|
3d970737d1 | ||
|
75c105a400 | ||
|
0a318f618b | ||
|
574d5055bd | ||
|
0022777a4f | ||
|
4c6996bc09 | ||
|
6ff12b3a88 | ||
|
babbb82a49 | ||
|
ae5331cf40 | ||
|
d67029c42c | ||
|
4dff9316c2 | ||
|
a056cbd19f | ||
|
032d46d8e6 | ||
|
b739aa35f2 | ||
|
fa3035f9cf | ||
|
daf1362d28 | ||
|
8e7d5ddfd4 | ||
|
71a70ffafa | ||
|
d9ceb32e2f | ||
|
13f716a395 | ||
|
b9375a1b4e | ||
|
38a98a51cb | ||
|
64c612dea0 | ||
|
f2e8a9e0c7 | ||
|
8ae0501c22 | ||
|
8dff0b2c5d | ||
|
a713b97e36 | ||
|
b6acc8da70 | ||
|
b8c89325bc | ||
|
b99cdf7367 | ||
|
60ce351a27 | ||
|
413a55623e | ||
|
5b2f95d270 | ||
|
44604c2509 | ||
|
bf2a7c2efd | ||
|
ba5c42cc51 | ||
|
cf2ea0f51c | ||
|
9df002fe4e | ||
|
1a191c7d51 | ||
|
7ca57d918e | ||
|
fe40e74809 | ||
|
daac2e2a1c | ||
|
b88ec407a3 | ||
|
8e9e4215ce | ||
|
4dd83c29fe | ||
|
6020f423f4 | ||
|
99bea8f7c3 | ||
|
d1e2d06538 | ||
|
ccf5d759a4 | ||
|
3ce8deec07 | ||
|
812b1f7baa | ||
|
d1848fd5f7 | ||
|
f57fc827fe | ||
|
45e534bbf5 | ||
|
bfcd4b8250 | ||
|
510f8ae0f5 | ||
|
a1941bf609 | ||
|
c9defec75d | ||
|
a2a2015af6 | ||
|
ca70ddb810 | ||
|
bf9d80c14c | ||
|
83467b8597 | ||
|
816301bf8d | ||
|
345e8a0679 | ||
|
bcd384c31c | ||
|
bbbaa60ddd | ||
|
dc17e5c3fa | ||
|
0150d3961b | ||
|
ae3e1f3a9f | ||
|
13ddc28d05 | ||
|
cedeea13e6 | ||
|
8f78c4a0fb | ||
|
a37af307f4 | ||
|
be3bc175bf | ||
|
6207aab19d | ||
|
01a5ec4c41 | ||
|
b09d45718a | ||
|
07c805a019 | ||
|
ea4e9b8e5e | ||
|
fd4b56572d | ||
|
16448c0bc5 | ||
|
c34750bdab | ||
|
dee6f35888 | ||
|
62ca9a2a84 | ||
|
ad64651532 | ||
|
edc47b56a4 | ||
|
f39b3365db | ||
|
0da4ff7b02 | ||
|
983e02888c | ||
|
35768ff7e8 | ||
|
6dfdc77ebd | ||
|
0753ba3495 | ||
|
ffd3b9a7a7 | ||
|
428062e1e4 | ||
|
cb49c7d060 | ||
|
2a22d71e7c | ||
|
eaa7fb7100 | ||
|
9755dd73eb | ||
|
4c2e62031a | ||
|
51a95554d7 | ||
|
12d8bd1743 | ||
|
458b4259fe | ||
|
e7714da8e8 | ||
|
b4f9d40767 | ||
|
a0e074043b | ||
|
9068168378 | ||
|
de39a17247 | ||
|
5c7a5fab94 | ||
|
c9e0aff839 | ||
|
61ed436c44 | ||
|
b7a1f96294 | ||
|
15ad351579 | ||
|
6cb4645514 | ||
|
eb1fa0919f | ||
|
45edf6025e | ||
|
17fed39b27 | ||
|
bba167d4ea | ||
|
9ebda42d34 | ||
|
619ec4faa4 | ||
|
49beae431f | ||
|
f3b8bb066c | ||
|
b879be2b02 | ||
|
52e699e125 | ||
|
8a86b2c940 | ||
|
b15fa7c0d7 | ||
|
6cd50cfaf1 | ||
|
9ed529b944 | ||
|
bbc3dc0504 | ||
|
d1d2c5f117 | ||
|
9f3f5d8053 | ||
|
f24b593349 | ||
|
0db1095373 | ||
|
997cd68344 | ||
|
b40334f7db | ||
|
a216f82b35 | ||
|
5eb2f14375 | ||
|
d4963dfb31 | ||
|
3c7f61e45c | ||
|
10eef60f45 | ||
|
cb70757790 | ||
|
ac0418c796 | ||
|
86b0094cdb | ||
|
c0f07bc0a5 | ||
|
c3b8ed223d | ||
|
3947a78b56 | ||
|
51ae2ce1e0 | ||
|
9ff78051a9 | ||
|
a50bd7421c | ||
|
0f21d80154 | ||
|
734602f4f7 | ||
|
3364dd3380 | ||
|
bd36c67bf2 | ||
|
856ae33fd5 | ||
|
fd4bfaea1f | ||
|
3dfdb9cba0 | ||
|
812181c435 | ||
|
9f3d59711f | ||
|
438060dfa2 | ||
|
f527dcf1fc | ||
|
ae05305e52 | ||
|
386546dd21 | ||
|
88021dbf5e | ||
|
a99de88709 | ||
|
3fe677986e | ||
|
8990089c65 | ||
|
f70efa2852 | ||
|
caa29bf7da | ||
|
d05a394134 | ||
|
18cc689209 | ||
|
7a11ab5bca | ||
|
aa2a24e68a | ||
|
e3eccf48a3 | ||
|
1db120a963 | ||
|
fca0aa2cc4 | ||
|
0bcf42dbb8 | ||
|
14e7e5e9fd | ||
|
1fcbf7ed42 | ||
|
a639ac42c4 | ||
|
c38a8599f1 | ||
|
0d8a845a21 | ||
|
588c2cad15 | ||
|
4b2fbd4344 | ||
|
d654771fcf | ||
|
1de1ddd496 | ||
|
33a962b721 | ||
|
4791eb85af | ||
|
47a9074695 | ||
|
819722f47a | ||
|
8b7c2b3607 | ||
|
78170b7052 | ||
|
46e5d23f7e | ||
|
316f26ec82 | ||
|
6e801d5f4d | ||
|
225a5d4e59 | ||
|
4f41d8b21b | ||
|
5f99eb8c97 | ||
|
403e18c1b7 | ||
|
239ead7ccb | ||
|
077bcb3f2a | ||
|
41e3ff381f | ||
|
e8dcdc7182 | ||
|
909ee2cc85 | ||
|
04126fb0c6 | ||
|
479f10a28e | ||
|
d46452c580 | ||
|
18f87924ad | ||
|
f6ec7bc323 | ||
|
f48d4c021a | ||
|
f190356934 | ||
|
ef140f28c8 | ||
|
1bc726abff | ||
|
794a0bb14b | ||
|
a1ed9bb377 | ||
|
c2027be0ee | ||
|
5a111af2fe | ||
|
bb000f77f8 | ||
|
6d2b3a6940 | ||
|
dbb14e6313 | ||
|
2144879e73 | ||
|
e149be9e0f | ||
|
9e921d8b50 | ||
|
9bf5059631 | ||
|
b9fdc14e18 | ||
|
f39938d17d | ||
|
aa238775c6 | ||
|
7e7a953345 | ||
|
9ec68fa5be | ||
|
a393c4dfae | ||
|
d9723387eb | ||
|
4433436416 | ||
|
f127a75e38 | ||
|
802f4ea5d8 | ||
|
6ed77e276b | ||
|
fffc8addcf | ||
|
489bddec5b | ||
|
f5e46df309 | ||
|
4887f678c5 | ||
|
be2c4597de | ||
|
cd56059a77 | ||
|
03d925b5ab | ||
|
487e82df3f | ||
|
72bf2f9c1a | ||
|
1555c06b21 | ||
|
7bebd6151e | ||
|
2f7c7badc1 | ||
|
1e60d6f6e8 | ||
|
b9795786c3 | ||
|
8091e224f7 | ||
|
e84eba23a1 | ||
|
16af59153e | ||
|
042c8abac1 | ||
|
5c62f29c6f | ||
|
7a37db84d8 | ||
|
b78dac20c0 | ||
|
de33f7b3f5 | ||
|
89fa345140 | ||
|
5be1c447a2 | ||
|
555b9854ef | ||
|
616a9cee1f | ||
|
ec3c386028 | ||
|
3c4b88db0a | ||
|
3ca9c769c6 | ||
|
4c03a2e98a | ||
|
013cc53cc0 | ||
|
50fcf0731b | ||
|
7e06fb474e | ||
|
0399677a01 | ||
|
fc1b6a4d38 | ||
|
c0c8c67228 | ||
|
00a64bce45 | ||
|
08f1dc7f9e | ||
|
0a627e9d0f | ||
|
ba9908e777 | ||
|
10060b35c8 | ||
|
d86190404d | ||
|
d764540526 | ||
|
2963828a07 | ||
|
1ff3969cfb | ||
|
8d73e8c905 | ||
|
5a6683574c | ||
|
e246c58424 | ||
|
c9748cb46f | ||
|
385f2db038 | ||
|
636f419be1 | ||
|
8b6a8b45ed | ||
|
89b6de0323 | ||
|
445dfceb2a | ||
|
788d1ed7b0 | ||
|
0df4cf70de | ||
|
83925322cb | ||
|
36cef26ab5 | ||
|
60556d0fa0 | ||
|
6a1238d2c5 | ||
|
6b04e25954 | ||
|
723a833845 | ||
|
f567f92d8f | ||
|
613573931e | ||
|
dc8668b222 | ||
|
d20fae2593 | ||
|
def6758aaa | ||
|
c2a81c528f | ||
|
4b8c31d806 | ||
|
1f9712d8a2 | ||
|
3276da3912 | ||
|
a969aef582 | ||
|
77c5b320d1 | ||
|
02d3893b6b | ||
|
aaa772c749 | ||
|
99e8f9c6cd | ||
|
0667c0ce49 | ||
|
fa32770e96 | ||
|
0a2b0842b0 | ||
|
f26f169973 | ||
|
b826e318a5 | ||
|
e5320688ba | ||
|
8b4721cc3e | ||
|
ea4325c498 | ||
|
dc4d2d6ccb | ||
|
06bcd1654c | ||
|
f71f717e51 | ||
|
191fbf1c9e | ||
|
434b4b5b13 | ||
|
5a2df8e038 | ||
|
2ac2711210 | ||
|
a213ecdc43 | ||
|
b49d9ff9c6 | ||
|
0e0588665d | ||
|
95786dc9d6 | ||
|
7bb2899414 | ||
|
94f5b7b987 | ||
|
f8762da246 | ||
|
f3685701ac | ||
|
f1e545ad49 | ||
|
c88c2a17ca | ||
|
dc8a6cc745 | ||
|
d319a353d4 | ||
|
89458a49b5 | ||
|
464ce16d63 | ||
|
6cca87da49 | ||
|
ace412f9e3 | ||
|
41e168a519 | ||
|
47746d6997 | ||
|
42fc47685c | ||
|
9a5e71f391 | ||
|
c05147a019 | ||
|
a59c92f55a | ||
|
151f361954 | ||
|
6d3a659362 | ||
|
2026d93934 | ||
|
1a9f06681f | ||
|
85747d2ed4 | ||
|
e1b8405c8b | ||
|
51c9208952 | ||
|
c0cea9448f | ||
|
1b7158a61d | ||
|
9298ca9c15 | ||
|
3c8f999468 | ||
|
ff84319e59 | ||
|
dc7e0a5f88 | ||
|
0ffe20d863 | ||
|
f3340f9789 | ||
|
ca0af0f342 | ||
|
aa91c41082 | ||
|
16579348f4 | ||
|
b07e7a4a36 | ||
|
dea994c1fb | ||
|
3bf11d1a0b | ||
|
dce60d0061 | ||
|
31e73b2f8c | ||
|
d314c8ae58 | ||
|
e19af47b77 | ||
|
94f7cfeb86 | ||
|
6531ba6a13 | ||
|
9bf615e90c | ||
|
003bffe463 | ||
|
021c23cd19 | ||
|
821b9dc187 | ||
|
72a7bf9e23 | ||
|
5cb46dba6c | ||
|
ba3500baf6 | ||
|
f82ee5efdd | ||
|
ab8c9bd269 | ||
|
1692a52e0a | ||
|
28df01b184 | ||
|
843d1d57cf | ||
|
a086b2001b | ||
|
98086f1b6b | ||
|
c1f08e8f22 | ||
|
e7a8679383 | ||
|
284babfeaa | ||
|
c1ea4bc1a7 | ||
|
7f48604820 | ||
|
572b0942ba | ||
|
63dff842f6 | ||
|
f83a0d027a | ||
|
93683d026b | ||
|
6fcfd259b7 | ||
|
6c335c7df1 | ||
|
9c451ffdd1 | ||
|
6a3eed49fc | ||
|
95142274fa | ||
|
f68eb449bd | ||
|
990b885aa9 | ||
|
f64a6d4ca4 | ||
|
d31a047467 | ||
|
7158f49fcb | ||
|
bfee82312c | ||
|
95df786227 | ||
|
ea57697215 | ||
|
2b026b6bc6 | ||
|
7f5c7c3bed | ||
|
79d7032e3a | ||
|
17d1a4b6fb | ||
|
afe55ae57e | ||
|
7bee558e01 | ||
|
d8f2deb5d9 | ||
|
cf98252bdb | ||
|
35b94d70e2 | ||
|
55a94d9888 | ||
|
ede5bb0e90 | ||
|
ff56414695 | ||
|
ca99a52545 | ||
|
0345ca47dd | ||
|
86b4e34031 | ||
|
db1f129034 | ||
|
9dc1034891 | ||
|
68947588d7 | ||
|
0fc92889c1 | ||
|
778c5aee32 | ||
|
63eb119df6 | ||
|
e6d5d0f9c6 | ||
|
67f1fe69fa | ||
|
b1625838ed | ||
|
4ac62bcf51 | ||
|
5ef97362cb | ||
|
d0cb5f4212 | ||
|
a58ad3a871 | ||
|
17e7aedcba | ||
|
648462f7f4 | ||
|
cb40485aad | ||
|
52924d38bf | ||
|
10d905472c | ||
|
dff7f24187 | ||
|
a6817e8281 | ||
|
19b6898568 | ||
|
9c6ea95df8 | ||
|
ecdec83c37 | ||
|
8d49121266 | ||
|
2b2a263ba6 | ||
|
087711f1f7 | ||
|
1b0049aaf7 | ||
|
5d59b445fd | ||
|
5ad46d251d | ||
|
c0a5402684 | ||
|
741f3f4066 | ||
|
d6b94802d8 | ||
|
d8e9d363fa | ||
|
840c8e0b91 | ||
|
69e624df41 | ||
|
a9f7fb46b3 | ||
|
40aa012588 | ||
|
6f709a1e7c | ||
|
ff78f378b5 | ||
|
ea5bcc7c77 | ||
|
17f0c29264 | ||
|
f8f091fa28 | ||
|
f82aee6089 | ||
|
7e5ee8f951 | ||
|
0ae7242e17 | ||
|
b00fa69585 | ||
|
e6a8fd5b73 | ||
|
cb1addd5e3 | ||
|
c9223ff74c | ||
|
b12c4f854c | ||
|
beeb840436 | ||
|
c3a423fdbe | ||
|
4f92db7651 | ||
|
3714e4e787 | ||
|
ab9bbe9a48 | ||
|
dbb77d9dc1 | ||
|
5e45f5c3ea | ||
|
be62d65c98 | ||
|
f860cfd8a3 | ||
|
5397700ab4 | ||
|
48ca1384f8 | ||
|
d1fb1614a3 | ||
|
e926326fca | ||
|
02f1dab9b2 | ||
|
7d53dfeca4 | ||
|
3133cbcc3e | ||
|
cb33b9f158 | ||
|
cee5f8a0fb | ||
|
50cf5b5322 | ||
|
7b89f1bea7 | ||
|
bc339191ea | ||
|
44114e66c2 | ||
|
bd69fd5815 | ||
|
1dfc739f19 | ||
|
e33bc7146b | ||
|
6325ee9310 | ||
|
7952e205b9 | ||
|
1fd24e746c | ||
|
6872a488de | ||
|
2e5e072631 | ||
|
acbd4c3aba | ||
|
e846e30905 | ||
|
efa7c66d98 | ||
|
573ec29829 | ||
|
f7e040efd2 | ||
|
e67fe1476c | ||
|
e224ae62b4 | ||
|
a80f1538c7 | ||
|
29d25c377b | ||
|
c53f79ca8b | ||
|
ff0f42900d | ||
|
05950ec1c8 | ||
|
a7f034f500 | ||
|
3182850e19 | ||
|
182158c3af | ||
|
7722e6d8e7 | ||
|
dd1c9976e3 | ||
|
32434703d8 | ||
|
3877b2f58e | ||
|
7e3acaa987 | ||
|
250ac42fa3 | ||
|
9e0ebc94c5 | ||
|
e708b0f01b | ||
|
1a0dba7422 | ||
|
282a3f8ee3 | ||
|
ebfee5868e | ||
|
7a146327ca | ||
|
5056615eb0 | ||
|
72a412904d | ||
|
74cae47902 | ||
|
2125047ca5 | ||
|
cac3475281 | ||
|
038e6613c0 | ||
|
bcc64fb276 | ||
|
3b8a0f8671 | ||
|
211a8dc272 | ||
|
dfbe1188f0 | ||
|
91b81af5a8 | ||
|
1f4a360a0c | ||
|
f9c35e6bcb | ||
|
aa0520d47d | ||
|
8d05ef703a | ||
|
26b8ef8af9 | ||
|
0a31cf2c44 | ||
|
19def67a9a | ||
|
88dd6ae5da | ||
|
cae7510a77 | ||
|
015678ca20 | ||
|
85c8092e65 | ||
|
724c1132b6 | ||
|
ae3c453f35 | ||
|
6f2736566e | ||
|
5fa281dd3a | ||
|
b203093073 | ||
|
1b3a5097c1 | ||
|
44d850e78f | ||
|
8170f523e0 | ||
|
c0842d4da7 | ||
|
6147a87e46 | ||
|
50f6a4732c | ||
|
f5580212ea | ||
|
9df3de2afb | ||
|
78ed184f60 | ||
|
85417eb24c | ||
|
f030e098a8 | ||
|
c996bcb23c | ||
|
61a41493ac | ||
|
a2334c3fb0 | ||
|
92e021a3d7 | ||
|
3705fa14bd | ||
|
4649b2ac1d | ||
|
ae346646e4 | ||
|
6e81467808 | ||
|
08cc439306 | ||
|
0838cbaf03 | ||
|
d4a0659483 | ||
|
4dbeaeb465 | ||
|
5d190a8137 | ||
|
0d16fe019e | ||
|
88ca909689 | ||
|
da344fae51 | ||
|
4683dc3f21 | ||
|
e21f306635 | ||
|
430a0d2492 | ||
|
70be853acd | ||
|
0df3a8ad98 | ||
|
62449ee543 | ||
|
5e56e7cf82 | ||
|
6c6d0dbc3d | ||
|
d6fcf63230 | ||
|
8759bcca84 | ||
|
86b46d1442 | ||
|
f54504e871 | ||
|
fc18a7b877 | ||
|
f1a979caa1 | ||
|
7c954d220c | ||
|
8bff468c7c | ||
|
c46f0a7430 | ||
|
2eb60213b4 | ||
|
05f48255a3 | ||
|
d599cab017 | ||
|
b521f36569 | ||
|
051b431f1d | ||
|
04b41fce30 | ||
|
5fcabca87c | ||
|
28b039fde3 | ||
|
762bfc4fcc | ||
|
39532fc2aa | ||
|
b6b73f2361 | ||
|
37d6a9b722 | ||
|
2a2187196f | ||
|
881ebff015 | ||
|
f0272fd283 | ||
|
0a0330a48c | ||
|
c09d308df8 | ||
|
482bb51640 | ||
|
ee56307ccc | ||
|
18950a6b46 | ||
|
a4e163885d | ||
|
108a31eca3 | ||
|
7f26dbe260 | ||
|
b6bbe19316 | ||
|
d744dea46e | ||
|
29f8c18b09 | ||
|
6f29d38047 | ||
|
5e2f65ab7a | ||
|
c5459cdde4 | ||
|
f58829130a | ||
|
42a3a64b0d | ||
|
1986de36a6 | ||
|
84202adc5b | ||
|
07446d2d41 | ||
|
14162ecaa0 | ||
|
2f054cd438 | ||
|
b5311aa3df | ||
|
3642ca5b4a | ||
|
2908a5d345 | ||
|
d225fb7df0 | ||
|
5d18a7cc82 | ||
|
07976988d9 | ||
|
2a96b2c68e | ||
|
3a9e6fa97f | ||
|
24fcb3f58f | ||
|
5beaa93437 | ||
|
415fb3a432 | ||
|
1e3bdd6a2e | ||
|
68907ff6c0 | ||
|
9f26d015ba | ||
|
c20517599e | ||
|
0bb75eed1f | ||
|
2b90f1395f | ||
|
51f225056c | ||
|
7a494db40b | ||
|
487bbe42a9 | ||
|
ab74f6c1a8 | ||
|
2def7f3910 | ||
|
11a4704161 | ||
|
8bc0afa75e | ||
|
3f5b1083f3 | ||
|
435724ffa9 | ||
|
b14d22550b | ||
|
f79784bc8c | ||
|
6ac401db9b | ||
|
bc2c345e21 | ||
|
577f0e0d9a | ||
|
a3570a69dd | ||
|
6a67c0fd0d | ||
|
7bf510880f | ||
|
77f06b962d | ||
|
d0ec5a13f3 | ||
|
d6d9ece045 | ||
|
c14bf80b40 | ||
|
667ea844f2 | ||
|
ae84a0bbe9 | ||
|
67eff0583c | ||
|
1ed0ef0948 | ||
|
21f1848499 | ||
|
6958d114a9 | ||
|
34760a00be | ||
|
1bc42959d0 | ||
|
22cfb64348 | ||
|
056405939b | ||
|
2dcaabe4c4 | ||
|
bbd86661a4 | ||
|
d684c11c65 | ||
|
a2fb6d5664 | ||
|
31029e90cc | ||
|
2e95c78f4e | ||
|
62f620f79b | ||
|
f271968238 | ||
|
c2a938a17c | ||
|
e02b0aad6f | ||
|
32e8caab03 | ||
|
be2c629590 | ||
|
63718ab4f2 | ||
|
5b7bfe5302 | ||
|
8aae5b2599 | ||
|
ebc1725f5b | ||
|
27d3a36c1b | ||
|
dfa0308db6 | ||
|
299bcc2bc7 | ||
|
03c66315cb | ||
|
9f154748ae | ||
|
5eb66c4617 | ||
|
44b2673848 | ||
|
a6cf2b0685 | ||
|
b8c350488b | ||
|
fb74628aa8 | ||
|
fdedfc954c | ||
|
b8cbafa75d | ||
|
9ab053d702 | ||
|
6e2c733319 | ||
|
ad2191a76e | ||
|
ecc189aeac | ||
|
34d2c3d391 | ||
|
1699a57850 | ||
|
ea9b99b38b | ||
|
8edecf5937 | ||
|
cede7b1dc1 | ||
|
1464f5aa02 | ||
|
5ab7ec0bc8 | ||
|
7f85331448 | ||
|
7c063972ac | ||
|
bd72c0ca8d | ||
|
91fe308113 | ||
|
78a76a8038 | ||
|
759974d9a8 | ||
|
00a3e802fc | ||
|
160c1b49a1 | ||
|
5b1737ae46 | ||
|
fee7701d26 | ||
|
1e5122f741 | ||
|
d6ba653c21 | ||
|
51b1d1fa87 | ||
|
4249d9d906 | ||
|
a7e33e9c0a | ||
|
7a2e70ee2d | ||
|
416c153d2e | ||
|
23d911cc2c | ||
|
d868ef0168 | ||
|
48b10e6d08 | ||
|
4d9bd57336 | ||
|
30ab6d5ee7 | ||
|
622faf5471 | ||
|
4d558c5f95 | ||
|
a29ca2ae09 | ||
|
84df86df37 | ||
|
22e03b14d1 | ||
|
d1fed08764 | ||
|
bca24c0198 | ||
|
822c47d15f | ||
|
03b3b82e0a | ||
|
8279191339 | ||
|
6486b9e5cd | ||
|
4d7b0e3e68 | ||
|
66b0e6c68f | ||
|
69a4312613 | ||
|
293f867988 | ||
|
8d2c0dcb48 | ||
|
bdaecc5b2e | ||
|
fa9ff86ab2 | ||
|
f8e3e33e49 | ||
|
73778f8669 | ||
|
cd5a146f1a | ||
|
3c45b84474 | ||
|
d4682e504c | ||
|
2717cca267 | ||
|
28d37f0106 | ||
|
30b51449ce | ||
|
4b66ffcd5b | ||
|
0e85a3d59f | ||
|
72f8c8ef72 | ||
|
b227dc3e5c | ||
|
144d0e56cc | ||
|
d29d1ead9b | ||
|
216138394f | ||
|
d0d4a19033 | ||
|
719189bd90 | ||
|
01af5115a2 | ||
|
7761376306 | ||
|
43f34f6330 | ||
|
a77069297d | ||
|
36899af36b | ||
|
bfa4e00fe7 | ||
|
4c6bb93eaf | ||
|
7e62e8e2cd | ||
|
762fd02eb7 | ||
|
825592e443 | ||
|
4c6234796d | ||
|
d6dd2a02b5 | ||
|
b97aed0723 | ||
|
1614707943 | ||
|
88b806326e | ||
|
82bf0dcae9 | ||
|
0ada12e646 | ||
|
a7ae66e0de | ||
|
a1f98eb6bf | ||
|
f882986f7d | ||
|
9b8bcc4464 | ||
|
487a90fba5 | ||
|
abb9a0839a | ||
|
7a01be9c0d | ||
|
23aaa58834 | ||
|
0077091175 | ||
|
624a8ff04c | ||
|
94a7db26f5 | ||
|
58edc83e11 | ||
|
653d6c6050 | ||
|
5e39d3c6fb | ||
|
ebde029cce | ||
|
dd4391941e | ||
|
6e1fc4d84e | ||
|
86603ed1a6 | ||
|
a246993df3 | ||
|
2e88275766 | ||
|
eb2166dd4c | ||
|
b088c23ea2 | ||
|
95eb6926d4 | ||
|
b6454b70a6 | ||
|
a61b9ce1e1 | ||
|
a265ff3fbe | ||
|
fc993cb724 | ||
|
808eb9a12a | ||
|
d429800162 | ||
|
709e9daf40 | ||
|
82a1b8b4c0 | ||
|
fbe6a2ac80 | ||
|
89af162c5a | ||
|
1e0bc51fa2 | ||
|
21a42e310f | ||
|
ba163dbf5c | ||
|
236f7f8e28 | ||
|
ab2a55d417 | ||
|
2c96a79a08 | ||
|
61b91f4015 | ||
|
c274f9b23c | ||
|
2148411307 | ||
|
0c34521791 | ||
|
ad969b999d | ||
|
3bb2034254 | ||
|
ef16485eac | ||
|
8abff412d0 | ||
|
b26d379d20 | ||
|
2ed7be243b | ||
|
7efc58cb42 | ||
|
da09df0e42 | ||
|
e997610ef2 | ||
|
c2be97741e | ||
|
db977b8109 | ||
|
6f1875c13a | ||
|
4dc28a9d62 | ||
|
23f13b092f | ||
|
f4c4e84ffe | ||
|
8ac3af327b | ||
|
3ff475af7a | ||
|
43c24e55ab | ||
|
971b425e17 | ||
|
b9e8d7187c | ||
|
926ff80525 | ||
|
0cba8f3aa1 | ||
|
11fb2bcdfa | ||
|
94e43475e2 | ||
|
01a4905dc8 | ||
|
8cb7260375 | ||
|
dc04d2848d | ||
|
c2880a5832 | ||
|
979c0832cf | ||
|
fa381cc06d | ||
|
f1d902b9ad | ||
|
b97d922808 | ||
|
18dcd6b9b1 | ||
|
c6178e504f | ||
|
0ff28c4f50 | ||
|
73ab32fd92 | ||
|
925d4d077f | ||
|
4581efa4c3 | ||
|
09ccf7cdde | ||
|
d1fedcac7c | ||
|
a7ee451705 | ||
|
11fc0fed75 | ||
|
f932100388 | ||
|
f0b582fef0 | ||
|
bf0b6d738a | ||
|
0da106ba36 | ||
|
83a06b9657 | ||
|
9b5bd3e226 | ||
|
135fcab558 | ||
|
f990600aea | ||
|
22cd6ae239 | ||
|
00b53ee577 | ||
|
f65e96e7b4 | ||
|
f98844db02 | ||
|
c59665e017 | ||
|
7fe4148384 | ||
|
a544ae264b | ||
|
c895f87e26 | ||
|
e65558958d | ||
|
eb5088c699 | ||
|
3755d866b1 | ||
|
8291dfc188 | ||
|
c41c91b0e7 | ||
|
3367ed6765 | ||
|
4654e39417 | ||
|
6dd4d4d906 | ||
|
cf3fecd425 | ||
|
be9a91e3fe | ||
|
fc51097ed8 | ||
|
751c870a4a | ||
|
de8e325193 | ||
|
e2feac3dde | ||
|
d7b0b2f785 | ||
|
326c863148 | ||
|
c42920d9aa | ||
|
fb5c1bb163 | ||
|
4f695a6d8f | ||
|
bc389d371d | ||
|
3756c3a191 | ||
|
9e3caf603d | ||
|
74e2ffc4c4 | ||
|
6e019dbd44 | ||
|
4d7cd7319b | ||
|
edf7761d49 | ||
|
a590bc96cd | ||
|
6c6bba68ff | ||
|
5fbcf348f5 | ||
|
58f5baa5f6 | ||
|
398dcb1036 | ||
|
30e7b761ae | ||
|
4d105c278b | ||
|
f019e4a246 | ||
|
4499e34f44 | ||
|
fd1bb84770 | ||
|
ac4c111ad3 | ||
|
254eb26211 | ||
|
f689871fc0 | ||
|
8ead371603 | ||
|
8045d61e1f | ||
|
e790c35270 | ||
|
914ec895ee | ||
|
bd05484b2d | ||
|
7872838056 | ||
|
b89b3db077 | ||
|
8e3d83579b | ||
|
96845d31db | ||
|
89fa2ece43 | ||
|
82e3adebbc | ||
|
2490d4d638 | ||
|
55f04906ac | ||
|
3442ebc1c3 | ||
|
f186a00515 | ||
|
0bd7e40a22 | ||
|
ad984b26fb | ||
|
3a659a9f3b | ||
|
0217e79324 | ||
|
544bff9f4f | ||
|
a4fdf1802b | ||
|
2c4f7d38a2 | ||
|
48a9e1ff9f | ||
|
c4b6d52657 | ||
|
43b291d2d0 | ||
|
b31178683c | ||
|
38631eb70e | ||
|
6246fd98c3 | ||
|
71aa315f2a | ||
|
af6a94d08e | ||
|
f6c7f3eed1 | ||
|
e0c5377968 | ||
|
8aada10f0d | ||
|
0c39495e3f | ||
|
7c638798c7 | ||
|
05ec5bde93 | ||
|
d2d372d140 | ||
|
e9b3ab91a0 | ||
|
633b12f66d | ||
|
2efe5a420c | ||
|
96c7f57ea0 | ||
|
6af879fe2a | ||
|
b935a6557f | ||
|
8340d5e71f | ||
|
8103081e0e | ||
|
be3157b6f5 | ||
|
ae9afcc393 | ||
|
e73480c0ef | ||
|
e02b9b7736 | ||
|
8c801ae078 | ||
|
a151f42495 | ||
|
40f7dc4824 | ||
|
3b8c61a87e | ||
|
4ef1f9c4d9 | ||
|
93cb6bd26e | ||
|
7c33bf2742 | ||
|
e5e67fbcbb | ||
|
95219c7934 | ||
|
53744982f0 | ||
|
6d24aa75d0 | ||
|
76c79f9f75 | ||
|
28081aa7d2 | ||
|
d0532bb9a9 | ||
|
9389cfe7a3 | ||
|
484fd61706 | ||
|
6c943571fc | ||
|
29123ac726 | ||
|
44cb8cdeca | ||
|
9e20f7db1a | ||
|
971320a56c | ||
|
4290d22465 | ||
|
96a3b25adb | ||
|
3dc69b60c4 | ||
|
bdde638967 | ||
|
8157644ff8 | ||
|
4008339963 | ||
|
c6bd6c17fc | ||
|
1a452a6cd7 | ||
|
35f854de5d | ||
|
99343294c6 | ||
|
56261bd741 | ||
|
1d53b48c8a | ||
|
5594489b69 | ||
|
ddb858380e | ||
|
bf5c1e9d8f | ||
|
931eeac548 | ||
|
f34c5d6674 | ||
|
9c05efa15d | ||
|
bd12c89a3c | ||
|
bf4f869524 | ||
|
dd09c4a72d | ||
|
55dcba6f36 | ||
|
4e7790966f | ||
|
bfcbb9ff4f | ||
|
cc57a73f23 | ||
|
d6f96e3d64 | ||
|
5f76f182f6 | ||
|
31eccf5f1c | ||
|
9d2ea19d7d | ||
|
a888e1e80e | ||
|
8b8855d2d5 | ||
|
de53166193 | ||
|
caf0ac1c9f | ||
|
299cd9ced3 | ||
|
11c8da3717 | ||
|
e309b30203 | ||
|
5a21249022 | ||
|
3c3c51e6fd | ||
|
ee3e10a4b0 | ||
|
e92cf38cde | ||
|
dbd080ca6c | ||
|
aedcf3006a | ||
|
6a475ae85c | ||
|
0ad637fa16 | ||
|
ee98a2da03 | ||
|
183d928e21 | ||
|
807c6f0cb5 | ||
|
72bb140b70 | ||
|
a5678a752b | ||
|
58938a239e | ||
|
da4695ff2a | ||
|
9fecc1b992 | ||
|
e8e1330cd5 | ||
|
1af45ede62 | ||
|
f6f9373aeb | ||
|
36a9b80040 | ||
|
175a5ab824 | ||
|
46d3608ccb | ||
|
b11eced4f1 | ||
|
66dfcbc2f8 | ||
|
71de2d9adc | ||
|
3f30636808 | ||
|
ee9c73fde1 | ||
|
7d76264b25 | ||
|
22771a84f1 | ||
|
a107bdd849 | ||
|
9fbf97f4cb | ||
|
812563f68b | ||
|
d3f50ee6c3 | ||
|
9dbe9c7286 | ||
|
fbcc7aa211 | ||
|
a0af769d7c | ||
|
ef4f930ba2 | ||
|
8369003bdf | ||
|
02145eaa06 | ||
|
a857d8e306 | ||
|
cb64f472fe | ||
|
cd28ad4c07 | ||
|
b69616117f | ||
|
59fa2e28c2 | ||
|
0f1e348ac4 | ||
|
67bde947f9 | ||
|
d9009540dd | ||
|
28a1cf6982 | ||
|
9c1c9f96e1 | ||
|
7657c0f905 | ||
|
d8a0142aee | ||
|
eddc681d64 | ||
|
87a97bc8ec | ||
|
ae81ea2bbc | ||
|
90e580245a | ||
|
8372c9e3ed | ||
|
1fcb8d712b | ||
|
9761566b28 | ||
|
f26c58fa22 | ||
|
6d73f7b767 | ||
|
3c0177c2dd | ||
|
dc4135b506 | ||
|
cefdbe1d08 | ||
|
95e80f0263 | ||
|
013f51f0c4 | ||
|
75911ba4c0 | ||
|
b3edc439cf | ||
|
7ef08579ef | ||
|
b39a86edbd | ||
|
9c151417a8 | ||
|
5d8d9cb19c | ||
|
b986bfd509 | ||
|
28ae10a4aa | ||
|
39fa7d850a | ||
|
25ea221d47 | ||
|
a4e495edd3 | ||
|
8b009304ad | ||
|
249f268fb5 | ||
|
9f3f981ab0 | ||
|
ef912e066b | ||
|
d014872e3b | ||
|
776d892d27 | ||
|
9970398cf2 | ||
|
a5f537f251 | ||
|
6376ba2516 | ||
|
5e0fc3e17f | ||
|
1a068ee191 | ||
|
8226f60fad | ||
|
2e618999d9 | ||
|
bf7a096a18 | ||
|
0d9885a1e0 | ||
|
aca8fd7f3d | ||
|
f5ea4fb6ac | ||
|
7b5c74f81c | ||
|
558e11a364 | ||
|
3d5b3c65de | ||
|
ed9e590498 | ||
|
70fda1009b | ||
|
ceae1f1ad8 | ||
|
8f1eff8782 | ||
|
c1c8c04567 | ||
|
31b4785a4d | ||
|
8e5656729b | ||
|
51893fff09 | ||
|
25d8ba2699 | ||
|
fd5e4b78da | ||
|
f45d0122b0 | ||
|
01cfa4496c | ||
|
82c8b532c0 | ||
|
ee7f79b40c | ||
|
cb7a1bc9c3 | ||
|
52cf4d24d3 | ||
|
ed98613b2d | ||
|
252df0f7a9 | ||
|
116e6fb3c0 | ||
|
efa3aa5cf8 | ||
|
69e9a79ac1 | ||
|
96cf5d2105 | ||
|
f745e22a52 | ||
|
50495ef604 | ||
|
84854d9382 | ||
|
328dc9ea5b | ||
|
30b92efcc6 | ||
|
e87bd16b6b | ||
|
8b41b014ee | ||
|
601cf10fb4 | ||
|
f02ee2af27 | ||
|
c490d6bcd1 | ||
|
64b6b069a4 | ||
|
edd455a772 | ||
|
a54c1af7cc | ||
|
9e1fe22c19 | ||
|
bd033ed5f4 | ||
|
2fd9333fb0 | ||
|
6249d5a85e | ||
|
385de03f40 | ||
|
5bfb2c211a | ||
|
7ee4a8fc0a | ||
|
c73f544a01 | ||
|
370d57cfbc | ||
|
4380d34645 | ||
|
471497e721 | ||
|
16809a53ab | ||
|
6ad0098767 | ||
|
eea17f0905 | ||
|
bd238dcbfa | ||
|
20e2b3beb8 | ||
|
1f890324b4 | ||
|
04fa7d9628 | ||
|
19f9c94d60 | ||
|
7fd7970ec1 | ||
|
81dece5516 | ||
|
52e66b09dc | ||
|
06f4b95dc0 | ||
|
008bc0116d | ||
|
de728f6c36 | ||
|
a8c6678efc | ||
|
35dbab2ff5 | ||
|
a732d8856b | ||
|
80f7ffd7a6 | ||
|
d86536c949 | ||
|
f84ea0ad5b | ||
|
28ed6cb3b6 | ||
|
927c3e7e94 | ||
|
5416f4194c | ||
|
b09c1e3cbf | ||
|
66ac03a021 | ||
|
43d0a11cba | ||
|
a27b22a972 | ||
|
338c569c0b | ||
|
f7db14fb02 | ||
|
cfd0e00c0c | ||
|
7c4afd922c | ||
|
bd1a0361be | ||
|
a7ee7d5bad | ||
|
29e4a64475 | ||
|
f07bf43ada | ||
|
80551fc0c2 | ||
|
2acda2c5da | ||
|
9582b9c0fb | ||
|
cbe093fe77 | ||
|
112a7913d4 | ||
|
cab447e44e | ||
|
fde2bdf304 | ||
|
2c90e33ceb | ||
|
af10344b6b | ||
|
187edbd32a | ||
|
3bce0be96e | ||
|
828bf44b2b | ||
|
c6c8ef07a6 | ||
|
a6150beed2 | ||
|
b090468109 | ||
|
4cba1388f9 | ||
|
61caa3474b | ||
|
cd08c919e9 | ||
|
45ca480de1 | ||
|
95d05a9c28 | ||
|
db9c418622 | ||
|
e860062553 | ||
|
80fc66e097 | ||
|
6b89dfdc8d | ||
|
97fa087496 | ||
|
312a5855c6 | ||
|
c8d95f701d | ||
|
9b6c45e112 | ||
|
482a8f1fb8 | ||
|
eb109aa755 | ||
|
4a4a544860 | ||
|
72f5f8b64b | ||
|
0a296908a8 | ||
|
08292c874b | ||
|
e76c32b74e | ||
|
7613073373 | ||
|
2b0051887a | ||
|
413c21505c | ||
|
8581d06931 | ||
|
9385bd2a10 | ||
|
131f4d1757 | ||
|
861b379992 | ||
|
87bc0c6c7a | ||
|
5f3d6a6905 | ||
|
ce367f6e17 | ||
|
9660e147d4 | ||
|
5c2b4309cf | ||
|
788d72d6ca | ||
|
c982ebaca9 | ||
|
570f5ac375 | ||
|
a9ad3ac4f3 | ||
|
8c7956d935 | ||
|
bde77784b9 | ||
|
f012e23fa9 | ||
|
112f77c4e0 | ||
|
c11c28b406 | ||
|
189d2b2c06 | ||
|
497b07b156 | ||
|
d74dc2053b | ||
|
1b9b18851d | ||
|
ac32d6bb29 | ||
|
1c48ba6b99 | ||
|
35a5d9e454 | ||
|
550dcde9b8 | ||
|
7049c6e8ac | ||
|
9b1c01351c | ||
|
204db7b19b | ||
|
93294be53e | ||
|
b06a72f944 | ||
|
abd478ad3c | ||
|
f91b99ec5e | ||
|
cfee0e4797 | ||
|
f9faf9c4d8 | ||
|
e3b7f167ff | ||
|
553e5e7aa0 | ||
|
6016e8f526 | ||
|
b2cd350115 | ||
|
12a1828f04 | ||
|
133fd29a33 | ||
|
9b8caf4f83 | ||
|
bbcd02a4c4 | ||
|
2cdea80fef | ||
|
023caf57d1 | ||
|
8ae3ffba32 | ||
|
8b994a1401 | ||
|
00615c9882 | ||
|
e90d18a86b | ||
|
05ecbf0f86 | ||
|
85734e3581 | ||
|
4f8fd7b994 | ||
|
68d128133c | ||
|
157f22ac2d | ||
|
050ef659b3 | ||
|
8c150aa3e8 | ||
|
c911d9c7ff | ||
|
3ce1e3e5d9 | ||
|
42a24300a1 | ||
|
5a3894036c | ||
|
15c9d68175 | ||
|
4f0111f331 | ||
|
81a4b5edbc | ||
|
87c903a0fa | ||
|
3103fe970a | ||
|
5fa22fedbb | ||
|
e6f89b0b22 | ||
|
d1b6cff663 | ||
|
3c8a4b80d2 | ||
|
7a2454d816 | ||
|
c9c787b11d | ||
|
76788892c0 | ||
|
cdc60cd453 | ||
|
894f5b9ed3 | ||
|
8f1adf6316 | ||
|
11b5512cb8 | ||
|
e3bf4c1e7b | ||
|
2d3359b70e | ||
|
a92e9040bf | ||
|
c8e5cde101 | ||
|
617558a1ca | ||
|
753518fdc5 | ||
|
95e998b652 | ||
|
dc17156024 | ||
|
7299f938b5 | ||
|
6bf6c53969 | ||
|
c1b40442fa | ||
|
d8850e046a | ||
|
fb09f58ac8 | ||
|
482c9ad451 | ||
|
0702d3593c | ||
|
7efccab2af | ||
|
e364c78cc7 | ||
|
e27632e253 | ||
|
93f2724f68 | ||
|
1e56c70d6a | ||
|
d836f9d1f8 | ||
|
d82d14c629 | ||
|
547f5634e5 | ||
|
9dd61c2004 | ||
|
bc3d7bdfc4 | ||
|
80d5368d75 | ||
|
ab9950ee73 | ||
|
11ec53bcfc | ||
|
ca38d4ce70 | ||
|
311eeb9260 | ||
|
98aeee9c5a | ||
|
7b017e4328 | ||
|
b18a8744b2 | ||
|
247a34438b | ||
|
ebc7db2bc2 | ||
|
0f0f6b90dc | ||
|
c17297ad15 | ||
|
40f8e6061f | ||
|
0ab2f62e28 | ||
|
9bca325e07 | ||
|
eb01c0c016 | ||
|
a76e222cb5 | ||
|
ebe43497d5 | ||
|
f181f4e449 | ||
|
d144dcf7d9 | ||
|
0e6d296c87 | ||
|
6dbefb212e | ||
|
e11bd9436b | ||
|
61373e6e8e | ||
|
aa7a0abad7 | ||
|
c9d7559f03 | ||
|
a6b7a65dfb | ||
|
a0ecb6ecc2 | ||
|
3eb12ab116 | ||
|
84a6d4a592 | ||
|
66a7802e1b | ||
|
fc510e86f7 | ||
|
0901075c9f | ||
|
6bb5835bea | ||
|
0dd4563217 | ||
|
2b91482ec4 | ||
|
4ca0a5acae | ||
|
b90be98679 | ||
|
2c16fc467b | ||
|
87084e5065 | ||
|
f0f0fcf9ba | ||
|
8ef97e9dc6 | ||
|
dedc183e75 | ||
|
d301a3e5d3 | ||
|
199e3165f2 | ||
|
1c66705c5a | ||
|
ac86a8948e | ||
|
2e8f87b80d | ||
|
a708a93f3e | ||
|
2ef4e9c378 | ||
|
b8b8a12035 | ||
|
087c5cb77c | ||
|
02baf824f9 | ||
|
b833198a3a | ||
|
06d927a911 | ||
|
7ab55d46c0 | ||
|
8e81d6fe01 | ||
|
85e6ef40a1 | ||
|
e1db7630d9 | ||
|
a343e25785 | ||
|
0ad059359f | ||
|
20336af84e | ||
|
0a775444dd | ||
|
7fe30e464d | ||
|
9c1e61992a | ||
|
d41036f861 | ||
|
159881645c | ||
|
5e711f6c57 | ||
|
16f80f35dd | ||
|
188aec9fc4 | ||
|
deeb0d3303 | ||
|
7a215d94d8 | ||
|
cf7770e47e | ||
|
6a8ac72b6a | ||
|
95bbdba141 | ||
|
1ddeeba561 | ||
|
e95735c491 | ||
|
fa49e5cb4f | ||
|
a48302f433 | ||
|
ad1b2b4511 | ||
|
0127339eac | ||
|
ab4a517ae0 | ||
|
8931fd314d | ||
|
05b849de13 | ||
|
a1f90abcd2 | ||
|
67fc2feacb | ||
|
d28c091f0a | ||
|
b4af59728c | ||
|
025d5f7b4c | ||
|
d531e88666 | ||
|
ac845ad8c9 | ||
|
ace7ff464b | ||
|
562c6fbcce | ||
|
8cc12fb8d4 | ||
|
4cbb2f7d9d | ||
|
18c0f53764 | ||
|
64d000ec53 | ||
|
8e84c099fa | ||
|
707b69e3e2 | ||
|
33f6e7e337 | ||
|
ee1d5faf0d | ||
|
9178fd2b5c | ||
|
69e499e497 | ||
|
7308c4a15c | ||
|
1370ca7082 | ||
|
db6045778e | ||
|
2810923519 | ||
|
7f326abcd0 | ||
|
acf977577f | ||
|
995c552f2a | ||
|
99ae1655f5 | ||
|
7e45fe4509 | ||
|
531623178a | ||
|
7fddfa45e8 | ||
|
2b2fd3a356 | ||
|
258acaf814 | ||
|
a883d3ecdd | ||
|
2f6cdc6529 | ||
|
1f226ca6c7 | ||
|
9475cb3b39 | ||
|
eb0d350097 | ||
|
c90f5ed370 | ||
|
ccb466edbe | ||
|
1204f6d9ce | ||
|
efa1263c35 | ||
|
06bd353d44 | ||
|
562cfce9e2 | ||
|
bb066b7c65 | ||
|
37521d2d4f | ||
|
b732ea6c69 | ||
|
5426e43cbb | ||
|
a048f79b37 | ||
|
3214f7d3d5 | ||
|
06ef665f66 | ||
|
e1a07f1da6 | ||
|
5c32c7388a | ||
|
c04f22d3bf | ||
|
cbf43ea7b3 | ||
|
9197275343 | ||
|
ecdef52829 | ||
|
cc4298209b | ||
|
f26ce64914 | ||
|
e3f5b7cab3 | ||
|
cd38aa42aa | ||
|
dde9cdd8ac | ||
|
0d0308d584 | ||
|
a47ff99be7 | ||
|
e619217687 | ||
|
6f5b3371fe | ||
|
f7b9fc3bb1 | ||
|
700a2e9ce3 | ||
|
5176a3e2aa | ||
|
4631cd0e80 | ||
|
60c6512418 | ||
|
12bc821ef3 | ||
|
c82e910c38 | ||
|
7ae0620b20 | ||
|
de32cdb703 | ||
|
12e2a8ffc8 | ||
|
833f64fcec | ||
|
73c051d2b1 | ||
|
da06695ab7 | ||
|
984ffc4fb9 | ||
|
a19a3f2a7f | ||
|
d7b44ba0cf | ||
|
e90fe5cf28 | ||
|
20c7d80bb1 | ||
|
25f8a9418a | ||
|
21b609420b | ||
|
794b89c041 | ||
|
407595e613 | ||
|
cac8099117 | ||
|
4cc3e87d64 | ||
|
3e429490e7 | ||
|
e23b02f2e2 | ||
|
aa5ae45a0c | ||
|
d7558902f7 | ||
|
aa5de1896f | ||
|
e5596f6a97 | ||
|
d638306b04 | ||
|
dba9356472 | ||
|
fb247f8bea | ||
|
c880e2b848 | ||
|
1436477a14 | ||
|
35fe4f7268 | ||
|
a488e88f93 | ||
|
0d51c160eb | ||
|
f5b584ddb8 | ||
|
27207a27ae | ||
|
5082defddf | ||
|
c5f06386bd | ||
|
6e0095edb0 | ||
|
f5fbb2bc4f | ||
|
d78cd81c6f | ||
|
ef93ef57f9 | ||
|
a600e896a0 | ||
|
993c340c4f | ||
|
87f506f23b | ||
|
44fb53ce6b | ||
|
1d2e374526 | ||
|
5c423d2897 | ||
|
6d0a1ee824 | ||
|
978ab76644 | ||
|
da4e3f3b9c | ||
|
f6d2d05e70 | ||
|
d747d96e77 | ||
|
484b69165b | ||
|
0159e6dc00 | ||
|
8f7aae4980 | ||
|
0f9e26efc5 | ||
|
53f0b77fb0 | ||
|
fca669ff98 | ||
|
e910fc60fe | ||
|
1d2e62fed7 | ||
|
7651eb5c3c | ||
|
a06484c260 | ||
|
9b49e6a817 | ||
|
bef0c7725b | ||
|
7237ec7310 | ||
|
3abe5b8467 | ||
|
0406854fa5 | ||
|
ca6a398a72 | ||
|
5e81ce8e3e | ||
|
8658090736 | ||
|
614ac88567 | ||
|
797dcdb48b | ||
|
3a696ea9a1 | ||
|
1b19cb7449 | ||
|
ea81a5298b | ||
|
ae65eb6a3e | ||
|
67e07a7932 | ||
|
6ef15f3c1c | ||
|
0e3be83da2 | ||
|
8b5b7db241 | ||
|
1fd8a5fa91 | ||
|
34d7a86175 | ||
|
21f1f89a4b | ||
|
159f286b2c | ||
|
06454cc3e0 | ||
|
be27b580d6 | ||
|
f91b6938f5 | ||
|
a7fea8d012 | ||
|
18bc40fb66 | ||
|
1dec4bc96b | ||
|
0e28214b63 | ||
|
ca61751a8b | ||
|
cce1c2252d | ||
|
6a4d887941 | ||
|
4de1759321 | ||
|
139cd051ab | ||
|
33b2abc3b9 | ||
|
c63128cfbd | ||
|
5063188b25 | ||
|
b9f0c176d9 | ||
|
d09c03bff3 | ||
|
f444595845 | ||
|
eedf545409 | ||
|
aba8a3fed1 | ||
|
68d475dc55 | ||
|
ece9fbd3bb | ||
|
602d67155f | ||
|
75ef491e3e | ||
|
0f327fc75f | ||
|
a456f4c6a5 | ||
|
e097bd8117 | ||
|
ded8acc836 | ||
|
d8a0a1d38e | ||
|
e8f28d7ce4 | ||
|
a58bb776f3 | ||
|
4ba1a34f38 | ||
|
3d68b15e60 | ||
|
c78bba803c | ||
|
863c09142f | ||
|
3142442e5c | ||
|
4c1d50d554 | ||
|
25e7bbcd79 | ||
|
4b3a6a883d | ||
|
6c0bb2a949 | ||
|
f714566200 | ||
|
327a596de5 | ||
|
cc4603b61f | ||
|
f51568b331 | ||
|
6ceac578a3 | ||
|
1c733e6661 | ||
|
3842ec6bb0 | ||
|
ab1d652f17 | ||
|
70e90d8542 | ||
|
39e185576c | ||
|
9c402d4d40 | ||
|
37378ca5a6 | ||
|
a35749964c | ||
|
bbbd45efcd | ||
|
246f6bb0d0 | ||
|
a08a1d4f74 | ||
|
7acbd42a45 | ||
|
c6a5d05ffb | ||
|
36b17e9b8c | ||
|
c2cccd8b11 | ||
|
e7804af2f7 | ||
|
0412fabbd2 | ||
|
22959cddb2 | ||
|
7193db8344 | ||
|
352662d19a | ||
|
1afabb69c1 | ||
|
6f4ea83fa9 | ||
|
1c17bd9f5a | ||
|
de5f182f29 | ||
|
aa1843774a | ||
|
9e1c30ec5d | ||
|
31984a57d6 | ||
|
2f0645a94e | ||
|
c57d41863f | ||
|
25bbe9c3d6 | ||
|
c5c3592a4c | ||
|
5a8008a4dc | ||
|
2c5d2ea179 | ||
|
4387fd3327 | ||
|
1f2d5b0d00 | ||
|
253582219c | ||
|
3fc9fe3017 | ||
|
e07a584d66 | ||
|
150d44aafd | ||
|
179474b975 | ||
|
825e21362b | ||
|
0bc51b2ed8 | ||
|
4741169cc7 | ||
|
a8ad57a9b0 | ||
|
8582ad6015 | ||
|
51898a8109 | ||
|
d63f00851a | ||
|
f179fc523d | ||
|
eda29e3fef | ||
|
633548f190 | ||
|
811cbb2e20 | ||
|
6569ee5d10 | ||
|
5f60d7fd3b | ||
|
10f8aebde2 | ||
|
ea771476cc | ||
|
08bc487f17 | ||
|
1b6b71ed98 | ||
|
9f2631110e | ||
|
e8b1e418fa | ||
|
44563e73e2 | ||
|
d3595173b4 | ||
|
14d4b34cee | ||
|
538149233b | ||
|
bcb203f8e0 | ||
|
3c6937ff5a | ||
|
6c0f775c4b | ||
|
ea3e467dc4 | ||
|
5a65eddf59 | ||
|
e979bee920 | ||
|
eff08955f1 | ||
|
9310073c07 | ||
|
28869f4382 | ||
|
cd949e9d38 | ||
|
541e1fc4cc | ||
|
93fe00a299 | ||
|
8814364497 | ||
|
0d9ff4bde3 | ||
|
9c595b6c02 | ||
|
d49d0295a2 | ||
|
da7c971927 | ||
|
548879bd9f | ||
|
0c2516ccf8 | ||
|
332f227bc1 | ||
|
a98b2ecce3 | ||
|
195e2703b9 | ||
|
c1f1620624 | ||
|
f5284e8447 | ||
|
347cf08861 | ||
|
540317639a | ||
|
bdcd96544e | ||
|
8237c949f1 | ||
|
e38cb7c1a6 | ||
|
868d9cf55c | ||
|
aa3e68f3fd | ||
|
bf2d937ad6 | ||
|
e24d5b3ca4 | ||
|
e9778d6feb | ||
|
8c4c909f44 | ||
|
a1db8653ab | ||
|
cc5df1e1d5 | ||
|
87b1394e98 | ||
|
e3c2af2c59 | ||
|
a618a9214e | ||
|
76133ab55e | ||
|
2d4a728af4 | ||
|
4a2a6d34ae | ||
|
75c2dfcd48 | ||
|
6ebedaf540 | ||
|
85e8e652f1 | ||
|
f025811025 | ||
|
3aabb17ea5 | ||
|
f1e5129acb | ||
|
e8dbed1642 | ||
|
6d270dc5f4 | ||
|
2afe642e8b | ||
|
680e62cb98 | ||
|
c5ba746904 | ||
|
702711fc5e | ||
|
0855806ae2 | ||
|
a2c75e7c71 | ||
|
6f996f1f09 | ||
|
ac7a929a1a | ||
|
8313e45737 | ||
|
09ca2361d7 | ||
|
bcfd322b85 | ||
|
9dc831d8e5 | ||
|
9514835232 | ||
|
e93a2d7c5d | ||
|
b2f6476f78 | ||
|
b7d86c3fa4 | ||
|
89506b9e81 | ||
|
51abdb6066 | ||
|
9e60f73bcf | ||
|
1e6d98a121 | ||
|
98d56cb556 | ||
|
8b1a07b8a8 | ||
|
92e809fa6d | ||
|
a0998e4aff | ||
|
804d712848 | ||
|
08cda2ee10 | ||
|
bf03b367f1 | ||
|
c1da4aecd7 | ||
|
38c54e0f2c | ||
|
9ebf87df62 | ||
|
32d2cea7f8 | ||
|
f998cb6b18 | ||
|
9d4e903c4a | ||
|
cfdf5cb552 | ||
|
e859357c6a | ||
|
e7f13c9efe | ||
|
2a68c8d08b | ||
|
b1c088a03b | ||
|
04f0146afd | ||
|
92ecfafa0d | ||
|
f74ab2dfd4 | ||
|
a1dc383148 | ||
|
b853397c0a | ||
|
0cfd33fc8b | ||
|
51e63c5d1d | ||
|
e9ba7342d5 | ||
|
7434aed43f | ||
|
283f32479d | ||
|
f4057ea3fa | ||
|
a7480c1860 | ||
|
c4ad90696f | ||
|
85ee183e4f | ||
|
586b0fe6e2 | ||
|
bdfce35d9a | ||
|
3648d6292a | ||
|
b8f88d323d | ||
|
b8f66a36d5 | ||
|
d4050a7b9d | ||
|
bfb8b6203c | ||
|
15223ecfe4 | ||
|
e098b87d0a | ||
|
e878821df2 | ||
|
596fcf94ba | ||
|
332041e13b | ||
|
5008bfd6a9 | ||
|
2ef82f1b82 | ||
|
2f6b38eb39 | ||
|
69eaf2695e | ||
|
542d11d7f1 | ||
|
1de819b0a3 | ||
|
5713fa4f59 | ||
|
93fb40f323 | ||
|
f4314ebdae | ||
|
7b075f138d | ||
|
c62a7c4051 | ||
|
3e97e03ccc | ||
|
74a3d7619b | ||
|
fc88892ee6 | ||
|
01e42838ef | ||
|
192c6db03e | ||
|
a98bd0940f | ||
|
c0623726ae | ||
|
ba8ec97f6a | ||
|
fb1c01c37c | ||
|
f8e35da533 | ||
|
53053d8f4a | ||
|
9eab1acf1e | ||
|
7aa9f88ceb | ||
|
310517ece4 | ||
|
8adb36c7c4 | ||
|
057f6fdf26 | ||
|
b8b79de91c | ||
|
f86fa6cb5d | ||
|
693c980414 | ||
|
faeeec0e37 | ||
|
3db26bcae1 | ||
|
f0dbb92d76 | ||
|
73ce38c6a9 | ||
|
901cf15a79 | ||
|
4e3a948513 | ||
|
1ed8ff8711 | ||
|
4b74c7320b | ||
|
7ed9f535e6 | ||
|
f5c1ad8f2a | ||
|
174084a256 | ||
|
1e718bb44f | ||
|
f0fe10a11d | ||
|
ae1da6b9f5 | ||
|
04b6b3674d | ||
|
4254db5cc0 | ||
|
86e5a45621 | ||
|
397d4f0be5 | ||
|
01fdc6d1bb | ||
|
33698abfb2 | ||
|
80e8cd4191 | ||
|
2932e05851 | ||
|
19f16c9e56 | ||
|
cec5cd864c | ||
|
ba26aee54c | ||
|
6721e33c7e | ||
|
c14b226c92 | ||
|
4bb804fbf7 | ||
|
6cb82421e4 | ||
|
6e66c31911 | ||
|
a1ce245e3a | ||
|
668967546c | ||
|
5bd448405b | ||
|
fe235e0791 | ||
|
a9191b8fad | ||
|
63499c2f48 | ||
|
3fa2647e92 | ||
|
cdb1b8d8f8 | ||
|
c7c35399e5 | ||
|
102b8f88d0 | ||
|
4ca0c23e2a | ||
|
36de891451 | ||
|
f9d931960b | ||
|
dbe78f160b | ||
|
a6f4cd74d5 | ||
|
87a087c0b5 | ||
|
962e11a740 | ||
|
e658ef184d | ||
|
da472ea858 | ||
|
ff0b92272a | ||
|
cca6d0e967 | ||
|
e0ea0c195b | ||
|
b3d4d20195 | ||
|
5f788d962e | ||
|
2650453d4b | ||
|
4d6ba5a491 | ||
|
32721caf5a | ||
|
ad084e1fec | ||
|
512e4f0ce3 | ||
|
56f8e52352 | ||
|
a93cbf3548 | ||
|
e0e4cf3df1 | ||
|
16bd642ae8 | ||
|
a03f69fb98 | ||
|
8787f5d920 | ||
|
ef1ae4105b | ||
|
7f2ce91c82 | ||
|
1f30cf468a | ||
|
762dd1d0a5 | ||
|
f5790e5dc2 | ||
|
e1a12f4c77 | ||
|
52eec06110 | ||
|
a6e4a328b3 | ||
|
bfebaa5c6c | ||
|
05e848244e | ||
|
08710978c5 | ||
|
cba9109206 | ||
|
482621e86f | ||
|
c23819bfcf | ||
|
b0034f91b0 | ||
|
caa7709090 | ||
|
51b7a0aeae | ||
|
51228a3a5c | ||
|
5c091339f0 | ||
|
6643923981 | ||
|
4ce2478e44 | ||
|
6131c10d31 | ||
|
8c5ec2c57f | ||
|
e046d17bf2 | ||
|
8e7166662b | ||
|
3aaa425714 | ||
|
a66010a1d8 | ||
|
e9706a3b64 | ||
|
a6e61f4de8 | ||
|
e758ede706 | ||
|
957fe189dc | ||
|
12a4f6f05b | ||
|
bcd78a96bf | ||
|
f3b464b88a | ||
|
369f40c804 | ||
|
bddd7f4005 | ||
|
5434c39453 | ||
|
e4ac28877c | ||
|
8df7797f6d | ||
|
aa2b62976e | ||
|
e3dc6e307f | ||
|
48a30a7b82 | ||
|
1365240f69 | ||
|
1cd27d7f67 | ||
|
84c8f9d351 | ||
|
7e703e4788 | ||
|
fb13b402af | ||
|
e599abc6ba | ||
|
5784c4c8b3 | ||
|
cec79fed44 | ||
|
31a7563de5 | ||
|
0ad2058a1a | ||
|
44365d70fe | ||
|
bbf0b1e3ba | ||
|
8972319a85 | ||
|
85f713c8c7 | ||
|
6e020cada2 | ||
|
d436a7bad7 | ||
|
16a275529d | ||
|
0ad493d860 | ||
|
30774957ba | ||
|
8a1a772ab7 | ||
|
0d9a10f5fa | ||
|
1c9907c5d2 | ||
|
050530a991 | ||
|
f984cff5b4 | ||
|
ad7297c7e3 | ||
|
17d90a32e1 | ||
|
89a20eafd8 | ||
|
a2be821d2f | ||
|
39022b3b66 | ||
|
fe8f79698c | ||
|
a0a8f95d37 | ||
|
7247b4471a | ||
|
6bce62a598 | ||
|
629c73e630 | ||
|
fb0d262336 | ||
|
28df09a8d4 | ||
|
2e93b7c4c9 | ||
|
4125baf066 | ||
|
1fb2569a39 | ||
|
19ed5a2d3d | ||
|
84272f5b5d | ||
|
90804f7625 | ||
|
824dafb525 | ||
|
3fcf77e214 | ||
|
c5d2a34ebd | ||
|
a04a0e7175 | ||
|
9aa0d38116 | ||
|
f8452429a4 | ||
|
4349331ee7 | ||
|
1d3dbdf989 | ||
|
60c873aa66 | ||
|
674fa0e5ce | ||
|
f28e3ca504 | ||
|
96d6a72b97 | ||
|
7b3fa501c6 | ||
|
16dbcc43b0 | ||
|
c0c300925d | ||
|
0a02a08ed4 | ||
|
95c05f6107 | ||
|
e24785015d | ||
|
554c37febe | ||
|
dbb9dc4458 | ||
|
c6dba21212 | ||
|
94b5e4e2f8 | ||
|
0d891b1c93 | ||
|
2f77deb0a8 | ||
|
fa0adb17b8 | ||
|
36bd2290e9 | ||
|
372a5ba1ec | ||
|
25f45da195 | ||
|
9d191a783d | ||
|
0dc3593660 | ||
|
f609cc7042 | ||
|
360666a758 | ||
|
3f44056243 | ||
|
d075cbf69b | ||
|
6b13c00d56 | ||
|
6e95c6c200 | ||
|
35fed2676a | ||
|
9754e26e5f | ||
|
af9295723c | ||
|
55993aff04 | ||
|
66c5a35f36 | ||
|
c1260dcb9b | ||
|
f4e7405d92 | ||
|
c15cc34bfd | ||
|
16f32da647 | ||
|
4c34d73501 | ||
|
df1bd62f47 | ||
|
3ced179fbb | ||
|
957ceff87c | ||
|
85fcc2eab7 | ||
|
e7143b53d5 | ||
|
b728e10616 | ||
|
8ffa0061e9 | ||
|
b767c2fa54 | ||
|
aeb41bc516 | ||
|
178bdff62a | ||
|
3e79da6a79 | ||
|
f762c4c7a2 | ||
|
8de0bdca93 | ||
|
ef2fcd60d7 | ||
|
55b61775e8 | ||
|
07e57b1498 | ||
|
b522c9f62f | ||
|
04a7c57d64 | ||
|
367da0c78f | ||
|
057c21f7d0 | ||
|
af8ab57e60 | ||
|
409b6b807e | ||
|
4a454f0817 | ||
|
6b806922ee | ||
|
64a67b57b8 | ||
|
76bcf9dcf7 | ||
|
234dfa18d3 | ||
|
ba0823f4d0 | ||
|
9d401512d3 | ||
|
464e99505b | ||
|
17cf3fd7ad | ||
|
60998c9146 | ||
|
bd19225219 | ||
|
2868d62185 | ||
|
2a3d20d300 | ||
|
30dee07a3b | ||
|
96ecb1d07e | ||
|
99056a7807 | ||
|
374790176f | ||
|
f3e2a55869 | ||
|
666f3ea152 | ||
|
25fe56116c | ||
|
b27eead016 | ||
|
77a01f0cd4 | ||
|
5dfa08ace6 | ||
|
4c61dfef62 | ||
|
9653f082a3 | ||
|
3e2d892fb5 | ||
|
30d47b4fa6 | ||
|
fd3f591541 | ||
|
c85ba51274 | ||
|
843da1d48d | ||
|
d8cf44fdc9 | ||
|
8662797cf8 | ||
|
eabb0bb41d | ||
|
4966bef9c3 | ||
|
0f625c27a1 | ||
|
248b9ff1e1 | ||
|
39f3a1c697 | ||
|
c6100fc26c | ||
|
84b474d070 | ||
|
c4b977c6e1 | ||
|
a1907aaddb | ||
|
56ed56a986 | ||
|
91f28bfb8a | ||
|
46d7db8214 | ||
|
b5cdb44642 | ||
|
cb964c6dcd | ||
|
e79a4771c1 | ||
|
9006acb66a | ||
|
435a6b2f1a | ||
|
4d288ddd55 | ||
|
24cea5110e | ||
|
79f804b2d4 | ||
|
4b85e39e3e | ||
|
8f5918de4d | ||
|
ae762aa928 | ||
|
928da82dde | ||
|
94ea857738 | ||
|
0bb92e9e91 | ||
|
df4aab1d73 | ||
|
d3f93984d4 | ||
|
125d61eb68 | ||
|
c0988ba6d9 | ||
|
03b9904b07 | ||
|
24a9931abd | ||
|
2581a3433e | ||
|
8c9ca1e0f2 | ||
|
dcae051e85 | ||
|
3d03bf6f91 | ||
|
54b154f85f | ||
|
37c926d178 | ||
|
f50f81d321 | ||
|
743ace7e60 | ||
|
5d476e7259 | ||
|
fb6bcc8470 | ||
|
bda1633979 | ||
|
4169f580b8 | ||
|
4a4edcf82a | ||
|
a1fc0db8a2 | ||
|
dc19652c2b | ||
|
d2f1488934 | ||
|
bbdf6c6eaf | ||
|
f532d28fb3 | ||
|
0135368328 | ||
|
af81a52746 | ||
|
86b4c9ac73 | ||
|
1df3b4e18f | ||
|
fa204eca3b | ||
|
2c34fe2dc3 | ||
|
9c34187391 | ||
|
10d78a3102 | ||
|
46378845e9 | ||
|
ff39b22686 | ||
|
601e11980f | ||
|
8cef299878 | ||
|
914bfb105c | ||
|
8c98125755 | ||
|
076ecca5a9 | ||
|
840648b750 | ||
|
29fd4c4bd2 | ||
|
905fa7dd86 | ||
|
e8af71f641 | ||
|
6901d368d2 | ||
|
e89a340fae | ||
|
c3d6135fb3 | ||
|
6611defd87 | ||
|
5c449a9e30 | ||
|
415ac6a748 | ||
|
7ddafa098f | ||
|
177f7b9cb3 | ||
|
fb1704b717 | ||
|
ade1f1b911 | ||
|
344a9836d2 | ||
|
2c1487d303 | ||
|
e1e505e695 | ||
|
c5cd68416f | ||
|
45f757e157 | ||
|
de77c8a210 | ||
|
54b3af2c88 | ||
|
171a945de9 | ||
|
d845d10d73 | ||
|
98d91a746e | ||
|
1be1b5b263 | ||
|
dafb0c8d5c | ||
|
6ca69a9947 | ||
|
ff171a39c6 | ||
|
8acee57118 | ||
|
d03ab989e6 | ||
|
4f5b1d9646 | ||
|
f8dca1237a | ||
|
c382f706a6 | ||
|
23cbed310a | ||
|
1786ba30f7 | ||
|
530ce0952c | ||
|
262f10af9a | ||
|
3430a8f3ea | ||
|
959be3a23d | ||
|
15306fc116 | ||
|
fb5013db88 | ||
|
ab4780c9b9 | ||
|
e6a71ab7de | ||
|
6aecf68098 | ||
|
dc54c6139f | ||
|
71f158c526 | ||
|
dc7067baff | ||
|
ced226777f | ||
|
579d4f7a5b | ||
|
60b91d4d50 | ||
|
917042c48c | ||
|
ed27c35bb4 | ||
|
c35c94b7b7 | ||
|
d8317f7439 | ||
|
9a3813f883 | ||
|
0a7f77ea16 | ||
|
d6329a1ab6 | ||
|
0ba120356a | ||
|
d402b49f07 | ||
|
d4ba9fa09a | ||
|
62f352243d | ||
|
1ad19b5e93 | ||
|
e7ba0a5c60 | ||
|
050407f7c7 | ||
|
dffe096c59 | ||
|
bf5ad2cf18 | ||
|
a8ae4ddde8 | ||
|
2596a9ef7e | ||
|
f74989ac1d | ||
|
d3bc4017a5 | ||
|
ab8480d983 | ||
|
50dcc24900 | ||
|
a66470f93b | ||
|
d2dba1826d | ||
|
7f02195377 | ||
|
0002cddd67 | ||
|
19e1683106 | ||
|
5c538c7865 | ||
|
ee23967afe | ||
|
86dd8f3fd8 | ||
|
f19e2a0995 | ||
|
afd1002fdb | ||
|
07c7ed0a4e | ||
|
b48eb6e9cc | ||
|
e5da5a34cb | ||
|
f3a2c467ed | ||
|
a1fd35aa67 | ||
|
ad8ed37ff6 | ||
|
088e8bc9f9 | ||
|
3714323d74 | ||
|
d70b19fa93 | ||
|
08693a6875 | ||
|
73eca2407b | ||
|
ae7a52cecf | ||
|
2e244dd448 | ||
|
1ad77530aa | ||
|
e44963728f | ||
|
9075371145 | ||
|
3b256a708e | ||
|
aea517515c | ||
|
f28889284d | ||
|
240f1f51b9 | ||
|
05efd7423e | ||
|
fce8a3bc18 | ||
|
2adb5af051 | ||
|
8b7e5e527a | ||
|
c3d8916802 | ||
|
532f5e58ea | ||
|
57a5714fb5 | ||
|
a3fd49499b | ||
|
3dc2cd4d7a | ||
|
0b738e3d9e | ||
|
b29c2b2de4 | ||
|
40f2d19f81 | ||
|
2e997f2c67 | ||
|
0fd50892af | ||
|
55bd346cb2 | ||
|
0724ac133b | ||
|
0507fa5b0e | ||
|
617e945afa | ||
|
870c4bf765 | ||
|
9a592e9c7e | ||
|
53592ac404 | ||
|
d8848a6062 | ||
|
173c1d3a6e | ||
|
c815c4080d | ||
|
c09626182c | ||
|
65c6ce3033 | ||
|
06cc2f527e | ||
|
9da5061689 | ||
|
82b4415f7d | ||
|
3f1e5b9b1e | ||
|
1b95d98ccd | ||
|
e2e1925796 | ||
|
52c8f24df5 | ||
|
ca855da8ae | ||
|
a39d35e54c | ||
|
3bd2b24b10 | ||
|
12448426d4 | ||
|
a043d7cac7 | ||
|
4d88111d48 | ||
|
34d6610bf8 | ||
|
4bfc52327b | ||
|
15d5f7ff55 | ||
|
91ecd1aeeb | ||
|
342f871916 | ||
|
18d51de0b9 | ||
|
4dc6cae854 | ||
|
5fb160e1ac | ||
|
f1589314c2 | ||
|
7fb9a550c8 | ||
|
46f7f4814c | ||
|
c002cc104c | ||
|
492128a621 | ||
|
fff0f09684 | ||
|
64054d13a3 | ||
|
ae8d7096c3 | ||
|
13e04b6362 | ||
|
89e557bcef | ||
|
fdf4749c1b | ||
|
a63608bf97 | ||
|
5c101e9466 | ||
|
4b25ebc731 | ||
|
8e88fcb462 | ||
|
fd19b345a1 | ||
|
4a7bba047b | ||
|
440c21e9f3 | ||
|
959b679086 | ||
|
64cfd4d81a | ||
|
c742ca3b41 | ||
|
2002252f72 | ||
|
7df8b3a9bf | ||
|
3fea2173f4 | ||
|
d125cb5c01 | ||
|
86c9264ed9 | ||
|
00f2d0249f | ||
|
4465e6eea3 | ||
|
b87fb8c396 | ||
|
d4706b38b8 | ||
|
31c82b4ba6 | ||
|
cb80d8d349 | ||
|
7be3434136 | ||
|
b0a6eaaa96 | ||
|
d35905787d | ||
|
1fe0c8a3e9 | ||
|
e32716aa48 | ||
|
ba46f10e3f | ||
|
4b37ede8c2 | ||
|
dbe4c0c8e4 | ||
|
4f4afd6840 | ||
|
7409fde650 | ||
|
cfa31e6332 | ||
|
df973a6275 | ||
|
00fd067c6b | ||
|
3faf42be53 | ||
|
dea903bcb5 | ||
|
22e3b370e3 | ||
|
8f5589d3e1 | ||
|
03389fc040 | ||
|
996aa9ef66 | ||
|
9778999a7f | ||
|
91301197ea | ||
|
01d6b52a60 | ||
|
ce884ac577 | ||
|
b047f36e86 | ||
|
4fdd2f4eed | ||
|
182753e4ec | ||
|
29c9d3070c |
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve Element
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Smartphone (please complete the following information):**
|
||||
- Device: [e.g. Samsung S6]
|
||||
- OS: [e.g. Android 6.0]
|
||||
|
||||
**Additional context**
|
||||
- App version and store [e.g. 1.0.0 - F-Droid]
|
||||
- Homeserver: [e.g. matrix.org]
|
||||
|
||||
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: type:suggestion
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
10
.github/ISSUE_TEMPLATE/matrix-sdk.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Matrix SDK
|
||||
about: Report issue or ask for a feature regarding the Android Matrix SDK
|
||||
title: "[SDK] "
|
||||
labels: matrix-sdk
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- This issue template should be used by third party application maintainers, to report a bug or to request a feature on the SDK module of the application Element Android-->
|
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,10 +1,10 @@
|
||||
### Pull Request Checklist
|
||||
|
||||
<!-- Please read [CONTRIBUTING.md](https://github.com/vector-im/riotX-android/blob/develop/CONTRIBUTING.md) before submitting your pull request -->
|
||||
<!-- Please read [CONTRIBUTING.md](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md) before submitting your pull request -->
|
||||
|
||||
- [ ] Changes has been tested on an Android device or Android emulator with API 16
|
||||
- [ ] Changes has been tested on an Android device or Android emulator with API 21
|
||||
- [ ] UI change has been tested on both light and dark themes
|
||||
- [ ] Pull request is based on the develop branch
|
||||
- [ ] Pull request updates [CHANGES.md](https://github.com/vector-im/riotX-android/blob/develop/CHANGES.md)
|
||||
- [ ] Pull request updates [CHANGES.md](https://github.com/vector-im/element-android/blob/develop/CHANGES.md)
|
||||
- [ ] Pull request includes screenshots or videos if containing UI changes
|
||||
- [ ] Pull request includes a [sign off](https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md#sign-off)
|
||||
|
10
.github/workflows/gradle-wrapper-validation.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
name: "Validate Gradle Wrapper"
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
validation:
|
||||
name: "Validation"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: gradle/wrapper-validation-action@v1
|
18
.github/workflows/update-gradle-wrapper.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
name: Update Gradle Wrapper
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *"
|
||||
|
||||
jobs:
|
||||
update-gradle-wrapper:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Update Gradle Wrapper
|
||||
uses: gradle-update/update-gradle-wrapper-action@v1
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
target-branch: develop
|
11
.idea/codeStyles/Project.xml
generated
@@ -4,7 +4,16 @@
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
|
||||
|
6
.idea/dictionaries/bmarty.xml
generated
@@ -7,12 +7,14 @@
|
||||
<w>ciphertext</w>
|
||||
<w>coroutine</w>
|
||||
<w>decryptor</w>
|
||||
<w>displayname</w>
|
||||
<w>emoji</w>
|
||||
<w>emojis</w>
|
||||
<w>fdroid</w>
|
||||
<w>gplay</w>
|
||||
<w>hmac</w>
|
||||
<w>homeserver</w>
|
||||
<w>jitsi</w>
|
||||
<w>ktlint</w>
|
||||
<w>linkified</w>
|
||||
<w>linkify</w>
|
||||
@@ -22,12 +24,16 @@
|
||||
<w>pbkdf</w>
|
||||
<w>pids</w>
|
||||
<w>pkcs</w>
|
||||
<w>previewable</w>
|
||||
<w>previewables</w>
|
||||
<w>riotx</w>
|
||||
<w>signin</w>
|
||||
<w>signout</w>
|
||||
<w>signup</w>
|
||||
<w>ssss</w>
|
||||
<w>sygnal</w>
|
||||
<w>threepid</w>
|
||||
<w>unpublish</w>
|
||||
<w>unwedging</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
22
AUTHORS.md
@@ -1,10 +1,10 @@
|
||||
A full developer contributors list can be found [here](https://github.com/vector-im/riotX-android/graphs/contributors).
|
||||
A full developer contributors list can be found [here](https://github.com/vector-im/element-android/graphs/contributors).
|
||||
|
||||
# Core team:
|
||||
|
||||
Even if we try to be able to work on all the functionalities, we have more knowledge about what we have developed ourselves.
|
||||
|
||||
## Benoit: Android team leader
|
||||
## [Benoit](https://github.com/bmarty): Android team leader
|
||||
|
||||
[@benoit.marty:matrix.org](https://matrix.to/#/@benoit.marty:matrix.org)
|
||||
- Android team leader and project leader, Android developer, GitHub community manager.
|
||||
@@ -12,7 +12,7 @@ Even if we try to be able to work on all the functionalities, we have more knowl
|
||||
- Reviewing and polishing developed features, code quality manager, PRs reviewer, GitHub community manager.
|
||||
- Release manager on the Play Store
|
||||
|
||||
## François: Software architect
|
||||
## [Ganfra](https://github.com/ganfra) (aka François): Software architect
|
||||
|
||||
[@ganfra:matrix.org](https://matrix.to/#/@ganfra:matrix.org)
|
||||
- Software architect, Android developer
|
||||
@@ -20,16 +20,26 @@ Even if we try to be able to work on all the functionalities, we have more knowl
|
||||
- Work mainly on the global architecture of the project.
|
||||
- Specialist of the timeline, and lots of other features.
|
||||
|
||||
## Valere: Product manager, Android developer
|
||||
## [Valere](https://github.com/BillCarsonFr): Product manager, Android developer
|
||||
|
||||
[@valere35:matrix.org](https://matrix.to/#/@valere35:matrix.org)
|
||||
- Product manager, Android developer
|
||||
- Specialist on the crypto implementation.
|
||||
|
||||
## [Onuray](https://github.com/onurays): Android developer
|
||||
|
||||
[@onurays:matrix.org](https://matrix.to/#/@onurays:matrix.org)
|
||||
- Android developer
|
||||
|
||||
# Other contributors
|
||||
|
||||
First of all, we thank all contributors who use RiotX and report problems on this GitHub project or via the integrated rageshake function.
|
||||
First of all, we thank all contributors who use Element and report problems on this GitHub project or via the integrated rageshake function.
|
||||
|
||||
We do not forget all translators, for their work of translating RiotX into many languages. They are also the authors of RiotX.
|
||||
We do not forget all translators, for their work of translating Element into many languages. They are also the authors of Element.
|
||||
|
||||
Feel free to add your name below, when you contribute to the project!
|
||||
|
||||
Name | Matrix ID | GitHub
|
||||
----------|-----------------------------|--------------------------------------
|
||||
gjpower | @gjpower:matrix.org | [gjpower](https://github.com/gjpower)
|
||||
TR_SLimey | @tr_slimey:an-atom-in.space | [TR-SLimey](https://github.com/TR-SLimey)
|
||||
|
555
CHANGES.md
@@ -1,3 +1,553 @@
|
||||
Changes in Element 1.0.14 (2020-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Enable url previews for notices (#2562)
|
||||
- Edit room permissions (#2471)
|
||||
|
||||
Improvements 🙌:
|
||||
- Add System theme option and set as default (#904, #2387)
|
||||
- Store megolm outbound session to improve send time of first message after app launch.
|
||||
- Warn user when they are leaving a not public room (#1460)
|
||||
- Option to disable emoji keyboard (#2563)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Unspecced msgType field in m.sticker (#2580)
|
||||
- Wait for all room members to be known before sending a message to a e2e room (#2518)
|
||||
- Url previews sometimes attached to wrong message (#2561)
|
||||
- Room Topic not displayed correctly after visiting a link (#2551)
|
||||
- Hiding membership events works the exact opposite (#2603)
|
||||
- Tapping drawer having more than 1 room in notifications gives "malformed link" error (#2605)
|
||||
- Sent image not displayed when opened immediately after sending (#409)
|
||||
- Initial sync is not retried correctly when there is some network error. (#2632)
|
||||
- Fix switch theme issue, and white field issue (#2599, #2528)
|
||||
- Fix request too large Uri error when joining a room
|
||||
|
||||
Translations 🗣:
|
||||
- New language supported: Hebrew
|
||||
|
||||
Build 🧱:
|
||||
- Remove dependency to org.greenrobot.eventbus library
|
||||
|
||||
Other changes:
|
||||
- Migrate to ViewBindings (#1072)
|
||||
|
||||
Changes in Element 1.0.13 (2020-12-18)
|
||||
===================================================
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix MSC2858 implementation details (#2540)
|
||||
|
||||
Changes in Element 1.0.12 (2020-12-15)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Add room aliases management, and room directory visibility management in a dedicated screen (#1579, #2428)
|
||||
- Room setting: update join rules and guest access (#2442)
|
||||
- Url preview (#481)
|
||||
- Store encrypted file in cache and cleanup decrypted file at each app start (#2512)
|
||||
- Emoji Keyboard (#2520)
|
||||
- Social login (#2452)
|
||||
- Support for chat effects in timeline (confetti, snow) (#2535)
|
||||
|
||||
Improvements 🙌:
|
||||
- Add Setting Item to Change PIN (#2462)
|
||||
- Improve room history visibility setting UX (#1579)
|
||||
- Matrix.to deeplink custom scheme support
|
||||
- Homeserver history (#1933)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix cancellation of sending event (#2438)
|
||||
- Double bottomsheet effect after verify with passphrase
|
||||
- EditText cursor jumps to the start while typing fast (#2469)
|
||||
- UTD for events before invitation if member state events are hidden (#2486)
|
||||
- No known servers error is given when joining rooms on new Gitter bridge (#2516)
|
||||
- Show preview when sending attachment from the keyboard (#2440)
|
||||
- Do not compress GIFs (#1616, #1254)
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- StateService now exposes suspendable function instead of using MatrixCallback.
|
||||
- RawCacheStrategy has been moved and renamed to CacheStrategy
|
||||
- FileService: remove useless FileService.DownloadMode
|
||||
|
||||
Build 🧱:
|
||||
- Upgrade some dependencies and Kotlin version
|
||||
- Use fragment-ktx and preference-ktx dependencies (fix lint issue KtxExtensionAvailable)
|
||||
- Upgrade Realm dependency to 10.1.2
|
||||
|
||||
Other changes:
|
||||
- Remove "Status.im" theme #2424
|
||||
- Log HTTP requests and responses in production (level BASIC, i.e. without any private data)
|
||||
|
||||
Changes in Element 1.0.11 (2020-11-27)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Create DMs with users by scanning their QR code (#2025)
|
||||
- Add Invite friends quick invite actions (#2348)
|
||||
- Add friend by scanning QR code, show your code to friends (#2025)
|
||||
|
||||
Improvements 🙌:
|
||||
- New room creation tile with quick action (#2346)
|
||||
- Open an existing DM instead of creating a new one (#2319)
|
||||
- Use RoomMember instead of User in the context of a Room.
|
||||
- Ask for explicit user consent to send their contact details to the identity server (#2375)
|
||||
- Handle events of type "m.room.server_acl" (#890)
|
||||
- Room creation form: add advanced section to disable federation (#1314)
|
||||
- Move "Enable Encryption" from room setting screen to room profile screen (#2394)
|
||||
- Home empty screens quick design update (#2347)
|
||||
- Improve Invite user screen (seamless search for matrix ID)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix crash on AttachmentViewer (#2365)
|
||||
- Exclude yourself when decorating rooms which are direct or don't have more than 2 users (#2370)
|
||||
- F-Droid version: ensure timeout of sync request can be more than 60 seconds (#2169)
|
||||
- Fix issue when restoring draft after sharing (#2287)
|
||||
- Fix issue when updating the avatar of a room (new avatar vanishing)
|
||||
- Discard change dialog displayed by mistake when avatar has been updated
|
||||
- Try to fix cropped image in timeline (#2126)
|
||||
- Registration: annoying error message scares every new user when they add an email (#2391)
|
||||
- Fix jitsi integration for those with non-vanilla dialler frameworks
|
||||
- Update profile has no effect if user is in zero rooms
|
||||
- Fix issues with matrix.to deep linking (#2349)
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- AccountService now exposes suspendable function instead of using MatrixCallback (#2354).
|
||||
Note: We will incrementally migrate all the SDK API in a near future (#2449)
|
||||
|
||||
Test:
|
||||
- Add `allScreensTest` to cover all screens of the app
|
||||
|
||||
Other changes:
|
||||
- Upgrade Realm dependency to 10.0.0
|
||||
|
||||
Changes in Element 1.0.10 (2020-11-04)
|
||||
===================================================
|
||||
|
||||
Improvements 🙌:
|
||||
- Rework sending Event management (#154)
|
||||
- New room creation screen: set topic and avatar in the room creation form (#2078)
|
||||
- Toggle Low priority tag (#1490)
|
||||
- Add option to send with enter (#1195)
|
||||
- Use Hardware keyboard enter to send message (use shift-enter for new line) (#1881, #1440)
|
||||
- Edit and remove icons are now visible on image attachment preview screen (#2294)
|
||||
- Room profile: BigImageViewerActivity now only display the image. Use the room setting to change or delete the room Avatar
|
||||
- Better visibility of text reactions in dark theme (#1118)
|
||||
- Room member profile: Add action to create (or open) a DM (#2310)
|
||||
- Prepare changelog for F-Droid (#2296)
|
||||
- Add graphic resources for F-Droid (#812, #2220)
|
||||
- Highlight text in the body of the displayed result (#2200)
|
||||
- Considerably faster QR-code bitmap generation (#2331)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fixed ringtone handling (#2100 & #2246)
|
||||
- Messages encrypted with no way to decrypt after SDK update from 0.18 to 1.0.0 (#2252)
|
||||
- Incoming call continues to ring if call is answered on another device (#1921)
|
||||
- Search Result | scroll jumps after pagination (#2238)
|
||||
- Badly formatted mentions in body (#1506)
|
||||
- KeysBackup: Avoid using `!!` (#2262)
|
||||
- Two elements in the task switcher (#2299)
|
||||
|
||||
Changes in Element 1.0.9 (2020-10-16)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Search messages in a room - phase 1 (#2110)
|
||||
- Hide encrypted history (before user is invited). Can be shown if wanted in developer settings
|
||||
- Changed rainbow algorithm
|
||||
|
||||
Improvements 🙌:
|
||||
- Wording differentiation for direct rooms (#2176)
|
||||
- PIN code: request PIN code if phone has been locked
|
||||
- Small optimisation of scrolling experience in timeline (#2114)
|
||||
- Allow user to reset cross signing if he has no way to recover (#2052)
|
||||
- Ability to share text
|
||||
- Create home shortcut for any room (#1525)
|
||||
- Can't confirm email due to killing by Android (#2021)
|
||||
- Add a menu item to open the setting in room list and in room (#2171)
|
||||
- Add a menu item in the timeline as a shortcut to invite user (#2171)
|
||||
- Drawer: move settings access and add sign out action (#2171)
|
||||
- Filter room member (and banned users) by name (#2184)
|
||||
- Implement "Jump to read receipt" and "Mention" actions on the room member profile screen
|
||||
- Direct share (#2029)
|
||||
- Add FAB to room members list (#2226)
|
||||
- Add Sygnal API implementation to test is Push are correctly received
|
||||
- Add PushGateway API implementation to test if Push are correctly received
|
||||
- Cross signing: shouldn't offer to verify with other session when there is not. (#2227)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Improve support for image/audio/video/file selection with intent changes (#1376)
|
||||
- Fix Splash layout on small screens
|
||||
- Invalid popup when pressing back (#1635)
|
||||
- Simplifies draft management and should fix bunch of draft issues (#952, #683)
|
||||
- Very long topic cannot be fully visible (#1957)
|
||||
- Properly detect cross signing keys reset
|
||||
- Don't set presence when handling a push notification or polling (#2156)
|
||||
- Be robust against `StrandHogg` task injection
|
||||
- Clear alerts if user sign out
|
||||
- Fix rows are hidden in Textinput (#2234)
|
||||
- Uploading a file to a room caused it to have a info.size of -1 (#2141)
|
||||
|
||||
Translations 🗣:
|
||||
- Move store data to `/fastlane/metadata/android` (#812)
|
||||
- Weblate is now hosted at https://translate.element.io
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- Search messages in a room by using Session.searchService() or Room.search()
|
||||
|
||||
Build 🧱:
|
||||
- Use Update Gradle Wrapper Action
|
||||
- Updates Gradle Wrapper from 5.6.4 to 6.6.1. (#2193)
|
||||
- Upgrade kotlin version from `1.3.72` to `1.4.10` and kotlin coroutines version from `1.3.8` to `1.3.9`
|
||||
- Upgrade build tools from `3.5.3` to `4.0.1`, then to `4.1.0`
|
||||
- Upgrade com.google.gms:google-services from `4.3.2` to `4.3.4`
|
||||
- Upgrade Moshi to `1.11.0`, Dagger to `2.29.1`, Epoxy to `4.1.0`
|
||||
|
||||
Other changes:
|
||||
- Added registration/verification automated UI tests
|
||||
- Create a script to help getting public information form any homeserver
|
||||
|
||||
Changes in Element 1.0.8 (2020-09-25)
|
||||
===================================================
|
||||
|
||||
Improvements 🙌:
|
||||
- Add "show password" in import Megolm keys dialog
|
||||
- Visually disable call buttons in menu and prohibit calling when permissions are insufficient (#2112)
|
||||
- Better management of requested permissions (#2048)
|
||||
- Add a setting to show timestamp for all messages (#2123)
|
||||
- Use cache for user color
|
||||
- Allow using an outdated homeserver, at user's risk (#1972)
|
||||
- Restore small logo on login screens and fix scrolling issue on those screens
|
||||
- PIN Code Improvements: Add more settings: biometrics, grace period, notification content (#1985)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Long message cannot be sent/takes infinite time & blocks other messages (#1397)
|
||||
- Fix crash when wellknown are malformed, or redirect to some HTML content (reported by rageshakes)
|
||||
- User Verification in DM not working
|
||||
- Manual import of Megolm keys does back up the imported keys
|
||||
- Auto scrolling to the latest message when sending (#2094)
|
||||
- Fix incorrect permission check when creating widgets (#2137)
|
||||
- Pin code: user has to enter pin code twice (#2005)
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- Rename `tryThis` to `tryOrNull`
|
||||
|
||||
Other changes:
|
||||
- Add an advanced action to reset an account data entry
|
||||
|
||||
Changes in Element 1.0.7 (2020-09-17)
|
||||
===================================================
|
||||
|
||||
Improvements 🙌:
|
||||
- Handle date formatting properly (show time am/pm if needed, display year when needed)
|
||||
- Improve F-Droid Notification (#2055)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Clear the notification when the event is read elsewhere (#1822)
|
||||
- Speakerphone is not used for ringback tone (#1644, #1645)
|
||||
- Back camera preview is not mirrored anymore (#1776)
|
||||
- Various report of people that cannot play video (#2107)
|
||||
- Rooms incorrectly marked as unread (#588)
|
||||
- Allow users to show/hide room member state events (#1231)
|
||||
- Fix stuck on loader when launching home
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- Create a new RawService to get plain data from the server.
|
||||
|
||||
Other changes:
|
||||
- Performance: share Realm instance used on UI thread and improve SharedPreferences reading time.
|
||||
|
||||
Changes in Element 1.0.6 (2020-09-08)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- List phone numbers and emails added to the Matrix account, and add emails and phone numbers to account (#44, #45)
|
||||
|
||||
Improvements 🙌:
|
||||
- You can now join room through permalink and within room directory search
|
||||
- Add long click gesture to copy userId, user display name, room name, room topic and room alias (#1774)
|
||||
- Fix several issues when uploading big files (#1889)
|
||||
- Do not propose to verify session if there is only one session and 4S is not configured (#1901)
|
||||
- Call screen does not use proximity sensor (#1735)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Display name not shown under Settings/General (#1926)
|
||||
- Editing message forgets line breaks and markdown (#1939)
|
||||
- Words containing my name should not trigger notifications (#1781)
|
||||
- Fix changing language issue
|
||||
- Fix FontSize issue (#1483, #1787)
|
||||
- Fix bad color for settings icon on Android < 24 (#1786)
|
||||
- Change user or room avatar: when selecting Gallery, I'm not proposed to crop the selected image (#1590)
|
||||
- Loudspeaker is always used (#1685)
|
||||
- Fix uploads still don't work with room v6 (#1879)
|
||||
- Can't handle ongoing call events in background (#1992)
|
||||
- Handle room, user and group links by the Element app (#1795)
|
||||
- Update associated site domain (#1833)
|
||||
- Crash / Attachment viewer: Cannot draw a recycled Bitmap #2034
|
||||
- Login with Matrix-Id | Autodiscovery fails if identity server is invalid and Homeserver ok (#2027)
|
||||
- Support for image compression on Android 10
|
||||
- Verification popup won't show
|
||||
- Android 6: App crash when read Contact permission is granted (#2064)
|
||||
- JSON for verification events leaks in to the room list (#1246)
|
||||
- Replies to poll appears in timeline as unsupported events during sending (#1004)
|
||||
|
||||
Translations 🗣:
|
||||
- The SDK is now using SAS string translations from [Weblate Matrix-doc project](https://translate.element.io/projects/matrix-doc/) (#1909)
|
||||
- New translation to kabyle
|
||||
|
||||
Build 🧱:
|
||||
- Some dependencies have been upgraded (coroutine, recyclerView, appCompat, core-ktx, firebase-messaging)
|
||||
- Buildkite:
|
||||
New pipeline location: https://github.com/matrix-org/pipelines/blob/master/element-android/pipeline.yml
|
||||
New build location: https://buildkite.com/matrix-dot-org/element-android
|
||||
|
||||
Other changes:
|
||||
- Use File extension functions to make code more concise (#1996)
|
||||
- Create a script to import SAS strings (#1909)
|
||||
- Support `data-mx-[bg-]color` attributes on `<font>` tags.
|
||||
|
||||
Changes in Element 1.0.5 (2020-08-21)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Protect access to the app by a pin code (#1700)
|
||||
- Conference with Jitsi support (#43)
|
||||
|
||||
Improvements 🙌:
|
||||
- Share button in rooms gives room ID link without via parameters (#1927)
|
||||
- Give user the possibility to prevent accidental call (#1869)
|
||||
- Display device information (name, id and key) in Cryptography setting screen (#1784)
|
||||
- Ensure users do not accidentally ignore other users (#1890)
|
||||
- Better handling DM creation when invitees cannot be inviting due to denied federation
|
||||
- Support new config.json format and config.domain.json files (#1682)
|
||||
- Increase Font size on Calling screen (#1643)
|
||||
- Make the user's Avatar live in the general settings
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix incorrect date format for some Asian languages (#1928)
|
||||
- Fix invisible toolbar (Status.im theme) (#1746)
|
||||
- Fix relative date time formatting (#822)
|
||||
- Fix crash reported by RageShake
|
||||
- Fix refreshing of sessions list when another session is logged out
|
||||
- Fix IllegalArgumentException: Receiver not registered: NetworkInfoReceiver (#1960)
|
||||
- Failed to build unique file (#1954)
|
||||
- Highlighted Event when opening a permalink from another room (#1033)
|
||||
- A Kick appears has "someone has made no change" (#1959)
|
||||
- Avoid NetworkOnMainThreadException when setting a user avatar
|
||||
- Renew turnserver credentials when ttl runs out
|
||||
|
||||
Translations 🗣:
|
||||
- Add PlayStore description resources in the Triple-T format, to let Weblate handle them
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- Rename package `im.vector.matrix.android` to `org.matrix.android.sdk`
|
||||
- Rename package `im.vector.matrix.rx` to `org.matrix.android.sdk.rx`
|
||||
|
||||
Build 🧱:
|
||||
- Fix RtlHardcoded issues (use `Start` and `End` instead of `Left` and `Right` layout attributes)
|
||||
|
||||
Other changes:
|
||||
- Use `Context#getSystemService` extension function provided by `core-ktx` (#1702)
|
||||
- Hide Flair settings, this is not implemented yet.
|
||||
- Rename package `im.vector.riotx.attachmentviewer` to `im.vector.lib.attachmentviewer`
|
||||
- Rename package `im.vector.riotx.multipicker` to `im.vector.lib.multipicker`
|
||||
- Rename package `im.vector.riotx` to `im.vector.app`
|
||||
- Remove old code that was used on devices with api level <21
|
||||
- Add Official Gradle Wrapper Validation Action
|
||||
|
||||
Changes in Element 1.0.4 (2020-08-03)
|
||||
===================================================
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix Crash when opening invite to room user screen
|
||||
|
||||
Changes in Element 1.0.3 (2020-07-31)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Support server admin option to disable E2EE for DMs / private rooms [users can still enable] (#1794)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Crash reported on playstore for HomeActivity launch (151 reports)
|
||||
|
||||
Changes in Element 1.0.2 (2020-07-29)
|
||||
===================================================
|
||||
|
||||
Improvements 🙌:
|
||||
- Added Session Database migration to avoid unneeded initial syncs
|
||||
|
||||
Changes in Element 1.0.1 (2020-07-28)
|
||||
===================================================
|
||||
|
||||
Improvements 🙌:
|
||||
- Sending events is now retried only 3 times, so we avoid blocking the sending queue too long.
|
||||
- Display warning when fail to send events in room list
|
||||
- Improve UI of edit role action in member profile
|
||||
- Moderation | New screen to display list of banned users in room settings, with unban action
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix theme issue on Room directory screen (#1613)
|
||||
- Fix notification not dismissing when entering a room
|
||||
- Fix uploads don't work with Room v6 (#1558)
|
||||
- Fix Requesting avatar thumbnails in Element uses wrong http "user-agent" string (#1725)
|
||||
- Fix 404 on EMS (#1761)
|
||||
- Fix Infinite loop at startup when migrating account from Riot (#1699)
|
||||
- Fix Element crashes in loop after initial sync (#1709)
|
||||
- Remove inner mx-reply tags before replying
|
||||
- Fix timeline items not loading when there are only filtered events
|
||||
- Fix "Voice & Video" grayed out in Settings (#1733)
|
||||
- Fix Allow VOIP call in all rooms with 2 participants (even if not DM)
|
||||
- Migration from old client does not enable notifications (#1723)
|
||||
|
||||
Other changes:
|
||||
- i18n deactivated account error
|
||||
|
||||
Changes in Element 1.0.0 (2020-07-15)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Re-branding: The app is now called Element. New name, new themes, new icons, etc. More details here: https://element.io/blog/welcome-to-element/ (#1691)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Video calls are shown as a voice ones in the timeline (#1676)
|
||||
- Fix regression: not able to create a room without IS configured (#1679)
|
||||
|
||||
Changes in Riot.imX 0.91.5 (2020-07-11)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- 3pid invite: it is now possible to invite people by email. An Identity Server has to be configured (#548)
|
||||
|
||||
Improvements 🙌:
|
||||
- Cleaning chunks with lots of events as long as a threshold has been exceeded (35_000 events in DB) (#1634)
|
||||
- Creating and listening to EventInsertEntity. (#1634)
|
||||
- Handling (almost) properly the groups fetching (#1634)
|
||||
- Improve fullscreen media display (#327)
|
||||
- Setup server recovery banner (#1648)
|
||||
- Set up SSSS from security settings (#1567)
|
||||
- New lab setting to add 'unread notifications' tab to main screen
|
||||
- Render third party invite event (#548)
|
||||
- Display three pid invites in the room members list (#548)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Integration Manager: Wrong URL to review terms if URL in config contains path (#1606)
|
||||
- Regression Composer does not grow, crops out text (#1650)
|
||||
- Bug / Unwanted draft (#698)
|
||||
- All users seems to be able to see the enable encryption option in room settings (#1341)
|
||||
- Leave room only leaves the current version (#1656)
|
||||
- Regression | Share action menu do not work (#1647)
|
||||
- verification issues on transition (#1555)
|
||||
- Fix issue when restoring keys backup using recovery key
|
||||
|
||||
SDK API changes ⚠️:
|
||||
- CreateRoomParams has been updated
|
||||
|
||||
Build 🧱:
|
||||
- Upgrade some dependencies
|
||||
- Revert to build-tools 3.5.3
|
||||
|
||||
Other changes:
|
||||
- Use Intent.ACTION_CREATE_DOCUMENT to save megolm key or recovery key in a txt file
|
||||
- Use `Context#withStyledAttributes` extension function (#1546)
|
||||
|
||||
Changes in Riot.imX 0.91.4 (2020-07-06)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Re-activate Wellknown support with updated UI (#1614)
|
||||
|
||||
Improvements 🙌:
|
||||
- Upload device keys only once to the homeserver and fix crash when no network (#1629)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix crash when coming from a notification (#1601)
|
||||
- Fix Exception when importing keys (#1576)
|
||||
- File isn't downloaded when another file with the same name already exists (#1578)
|
||||
- saved images don't show up in gallery (#1324)
|
||||
- Fix reply fallback leaking sender locale (#429)
|
||||
|
||||
Build 🧱:
|
||||
- Fix lint false-positive about WorkManager (#1012)
|
||||
- Upgrade build-tools from 3.5.3 to 3.6.3
|
||||
- Upgrade gradle from 5.4.1 to 5.6.4
|
||||
|
||||
Changes in Riot.imX 0.91.3 (2020-07-01)
|
||||
===================================================
|
||||
|
||||
Notes:
|
||||
- This version is the third beta version of RiotX codebase published as Riot-Android on the PlayStore.
|
||||
- Changelog below includes changes of v0.91.0, v0.91.1, and v0.91.2, because the first beta versions have been tagged and
|
||||
published from the branch feature/migration_from_legacy.
|
||||
- This version uses temporary name `Riot.imX`, to distinguish the app with RiotX app.
|
||||
|
||||
Features ✨:
|
||||
- Call with WebRTC support (##611)
|
||||
- Add capability to change the display name (#1529)
|
||||
|
||||
Improvements 🙌:
|
||||
- "Add Matrix app" menu is now always visible (#1495)
|
||||
- Handle `/op`, `/deop`, and `/nick` commands (#12)
|
||||
- Prioritising Recovery key over Recovery passphrase (#1463)
|
||||
- Room Settings: Name, Topic, Photo, Aliases, History Visibility (#1455)
|
||||
- Update user avatar (#1054)
|
||||
- Allow self-signed certificate (#1564)
|
||||
- Improve file download and open in timeline
|
||||
- Catchup tab is removed temporarily (#1565)
|
||||
- Render room avatar change (#1319)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Fix dark theme issue on login screen (#1097)
|
||||
- Incomplete predicate in RealmCryptoStore#getOutgoingRoomKeyRequest (#1519)
|
||||
- User could not redact message that they have sent (#1543)
|
||||
- Use vendor prefix for non merged MSC (#1537)
|
||||
- Compress images before sending (#1333)
|
||||
- Searching by displayname is case sensitive (#1468)
|
||||
- Fix layout overlap issue (#1407)
|
||||
|
||||
Build 🧱:
|
||||
- Enable code optimization (Proguard)
|
||||
- SDK is now API level 21 minimum, and so RiotX (#405)
|
||||
|
||||
Other changes:
|
||||
- Use `SharedPreferences#edit` extension function consistently (#1545)
|
||||
- Use `retrofit2.Call.awaitResponse` extension provided by Retrofit 2. (#1526)
|
||||
- Fix minor typo in contribution guide (#1512)
|
||||
- Fix self-assignment of callback in `DefaultRoomPushRuleService#setRoomNotificationState` (#1520)
|
||||
- Random housekeeping clean-ups indicated by Lint (#1520, #1541)
|
||||
- Keys Backup API now use the unstable prefix (#1503)
|
||||
- Remove deviceId from /keys/upload/{deviceId} as not spec-compliant (#1502)
|
||||
|
||||
Changes in RiotX 0.22.0 (2020-06-15)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
- Integration Manager and Widget support (#48)
|
||||
- Send stickers (#51)
|
||||
|
||||
Improvements 🙌:
|
||||
- New wording for notice when current user is the sender
|
||||
- Hide "X made no changes" event by default in timeline (#1430)
|
||||
- Hide left rooms in breadcrumbs (#766)
|
||||
- Handle PowerLevel properly (#627)
|
||||
- Correctly handle SSO login redirection
|
||||
- SSO login is now performed in the default browser, or in Chrome Custom tab if available (#1400)
|
||||
- Improve checking of homeserver version support (#1442)
|
||||
- Add capability to add and remove a room from the favorites (#1217)
|
||||
|
||||
Bugfix 🐛:
|
||||
- Switch theme is not fully taken into account without restarting the app
|
||||
- Temporary fix to show error when user is creating an account on matrix.org with userId containing only digits (#1410)
|
||||
- Reply composer overlay stays on screen too long after send (#1169)
|
||||
- Fix navigation bar icon contrast on API in [21,27[ (#1342)
|
||||
- Fix status bar icon contrast on API in [21,23[
|
||||
- Wrong /query request (#1444)
|
||||
- Make Credentials.homeServer optional because it is deprecated (#1443)
|
||||
- Fix issue on dark themes, after alert popup dismiss
|
||||
|
||||
Other changes:
|
||||
- Send plain text in the body of events containing formatted body, as per https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes
|
||||
- Update link to Modular url from "https://modular.im/" to "https://modular.im/services/matrix-hosting-riot" and open it using ChromeCustomTab
|
||||
|
||||
Changes in RiotX 0.21.0 (2020-05-28)
|
||||
===================================================
|
||||
|
||||
@@ -560,7 +1110,7 @@ Mode details here: https://medium.com/@RiotChat/introducing-the-riotx-beta-for-a
|
||||
=======================================================
|
||||
|
||||
|
||||
Changes in RiotX 0.X.0 (2020-XX-XX)
|
||||
Changes in Element 1.X.X (2020-XX-XX)
|
||||
===================================================
|
||||
|
||||
Features ✨:
|
||||
@@ -581,5 +1131,8 @@ SDK API changes ⚠️:
|
||||
Build 🧱:
|
||||
-
|
||||
|
||||
Test:
|
||||
-
|
||||
|
||||
Other changes:
|
||||
-
|
||||
|
@@ -2,9 +2,7 @@
|
||||
|
||||
Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md
|
||||
|
||||
Android support can be found in this [](https://matrix.to/#/#riot-android:matrix.org) room.
|
||||
|
||||
Dedicated room for RiotX: [](https://matrix.to/#/#riotx:matrix.org)
|
||||
Android support can be found in this [](https://matrix.to/#/#element-android:matrix.org) room.
|
||||
|
||||
# Specific rules for Matrix Android projects
|
||||
|
||||
@@ -19,7 +17,11 @@ An Android Studio template has been added to the project to help creating all fi
|
||||
|
||||
To install the template (to be done only once):
|
||||
- Go to folder `./tools/template`.
|
||||
- Run the script `./configure.sh`.
|
||||
- Mac OSX: Run the script `./configure.sh`.
|
||||
|
||||
Linux: Run `ANDROID_STUDIO=/path/to/android-studio ./configure`
|
||||
- e.g. `ANDROID_STUDIO=/usr/local/android-studio ./configure`
|
||||
|
||||
- Restart Android Studio.
|
||||
|
||||
To create a new screen:
|
||||
@@ -27,20 +29,18 @@ To create a new screen:
|
||||
- Then right click on the package, and select `New/New Vector/RiotX Feature`.
|
||||
- Follow the Wizard, especially replace `Main` by something more relevant to your feature.
|
||||
- Click on `Finish`.
|
||||
- Remainning steps are described as TODO in the generated files, or will be pointed out by the compilator, or at runtime :)
|
||||
- Remaining steps are described as TODO in the generated files, or will be pointed out by the compilator, or at runtime :)
|
||||
|
||||
Note that if the templates are modified, the only things to do is to restart Android Studio for the change to take effect.
|
||||
|
||||
## Compilation
|
||||
|
||||
For now, the Matrix SDK and the RiotX application are in the same project. So there is no specific thing to do, this project should compile without any special action.
|
||||
For now, the Matrix SDK and the Element application are in the same project. So there is no specific thing to do, this project should compile without any special action.
|
||||
|
||||
## I want to help translating RiotX
|
||||
## I want to help translating Element
|
||||
|
||||
If you want to fix an issue with an English string, please submit a PR.
|
||||
If you want to fix an issue in other languages, or add a missing translation, or even add a new language, please use [Weblate](https://translate.riot.im/projects/riot-android/).
|
||||
|
||||
For the moment, Strings from Riot will be used, there is no dedicated project in Weblate for RiotX.
|
||||
If you want to fix an issue in other languages, or add a missing translation, or even add a new language, please use [Weblate](https://translate.element.io/projects/element-android/).
|
||||
|
||||
## I want to submit a PR to fix an issue
|
||||
|
||||
@@ -97,7 +97,7 @@ Make sure the following commands execute without any error:
|
||||
|
||||
### Tests
|
||||
|
||||
RiotX is currently supported on Android KitKat (API 19+): please test your change on an Android device (or Android emulator) running with API 19. Many issues can happen (including crashes) on older devices.
|
||||
Element is currently supported on Android Lollipop (API 21+): please test your change on an Android device (or Android emulator) running with API 21. Many issues can happen (including crashes) on older devices.
|
||||
Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient.
|
||||
|
||||
You should consider adding Unit tests with your PR, and also integration tests (AndroidTest). Please refer to [this document](./docs/integration_tests.md) to install and run the integration test environment.
|
||||
@@ -116,7 +116,7 @@ Please consider accessibility as an important point. As a minimum requirement, i
|
||||
When adding or editing layouts, make sure the layout will render correctly if device uses a RTL (Right To Left) language.
|
||||
You can check this in the layout editor preview by selecting any RTL language (ex: Arabic).
|
||||
|
||||
Also please check that the colors are ok for all the current themes of RiotX. Please use `?attr` instead of `@color` to reference colors in the layout. You can check this in the layout editor preview by selecting all the main themes (`AppTheme.Status`, `AppTheme.Dark`, etc.).
|
||||
Also please check that the colors are ok for all the current themes of Element. Please use `?attr` instead of `@color` to reference colors in the layout. You can check this in the layout editor preview by selecting all the main themes (`AppTheme.Status`, `AppTheme.Dark`, etc.).
|
||||
|
||||
### Authors
|
||||
|
||||
|
40
README.md
@@ -1,38 +1,34 @@
|
||||
[](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
|
||||
[](https://translate.riot.im/engage/riot-android/?utm_source=widget)
|
||||
[](https://matrix.to/#/#riotx:matrix.org)
|
||||
[](https://sonarcloud.io/dashboard?id=vector.android.riotx)
|
||||
[](https://sonarcloud.io/dashboard?id=vector.android.riotx)
|
||||
[](https://sonarcloud.io/dashboard?id=vector.android.riotx)
|
||||
[](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
|
||||
[](https://translate.element.io/engage/element-android/?utm_source=widget)
|
||||
[](https://matrix.to/#/#element-android:matrix.org)
|
||||
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
||||
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
||||
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
||||
|
||||
# RiotX Android
|
||||
# Element Android
|
||||
|
||||
RiotX is an Android Matrix Client currently in beta but in active development.
|
||||
Element Android is an Android Matrix Client provided by [Element](https://element.io/).
|
||||
|
||||
It is a total rewrite of [Riot-Android](https://github.com/vector-im/riot-android) with a new user experience. RiotX will become the official replacement as soon as all features are implemented.
|
||||
It is a total rewrite of [Riot-Android](https://github.com/vector-im/riot-android) with a new user experience.
|
||||
|
||||
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=im.vector.riotx)
|
||||
[<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/app/im.vector.riotx)
|
||||
[<img src="resources/img/google-play-badge.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=im.vector.app)
|
||||
[<img src="resources/img/f-droid-badge.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/app/im.vector.app)
|
||||
|
||||
Nightly build: [](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
|
||||
Nightly build: [](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
|
||||
|
||||
# New Android SDK
|
||||
|
||||
RiotX is based on a new Android SDK fully written in Kotlin (like RiotX). In order to make the early development as fast as possible, RiotX and the new SDK currently share the same git repository. We will make separate repos once the SDK is stable enough.
|
||||
Element is based on a new Android SDK fully written in Kotlin (like Element). In order to make the early development as fast as possible, Element and the new SDK currently share the same git repository.
|
||||
|
||||
At each Element release, the SDK module is copied to a dedicated repository: https://github.com/matrix-org/matrix-android-sdk2. That way, third party apps can add a regular gradle dependency to use it. So more details on how to do that here: https://github.com/matrix-org/matrix-android-sdk2.
|
||||
|
||||
# Roadmap
|
||||
|
||||
The current target is to release an application out of beta with the same level of features (and even more) as Riot.
|
||||
The roadmap has 3 phases:
|
||||
|
||||
- [phase 0](https://github.com/vector-im/riotX-android/labels/phase0): Prototyping / Project setup
|
||||
- [phase 1](https://github.com/vector-im/riotX-android/labels/phase1): Beta release to the Play Store
|
||||
- [phase 2](https://github.com/vector-im/riotX-android/labels/phase2): Out of beta
|
||||
|
||||
The version 1.0.0 of Element still misses some features which was previously included in Riot-Android.
|
||||
The team will work to add them on a regular basis.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please refer to [CONTRIBUTING.md](https://github.com/vector-im/riotX-android/blob/develop/CONTRIBUTING.md) if you want to contribute on Matrix Android projects!
|
||||
Please refer to [CONTRIBUTING.md](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md) if you want to contribute on Matrix Android projects!
|
||||
|
||||
Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#riotx:matrix.org).
|
||||
Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#element-android:matrix.org).
|
||||
|
1
attachment-viewer/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
75
attachment-viewer/build.gradle
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
maven {
|
||||
url 'https://jitpack.io'
|
||||
content {
|
||||
// PhotoView
|
||||
includeGroupByRegex 'com\\.github\\.chrisbanes'
|
||||
}
|
||||
}
|
||||
jcenter()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.1.4'
|
||||
|
||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation 'androidx.core:core-ktx:1.3.2'
|
||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||
|
||||
implementation 'com.google.android.material:material:1.2.1'
|
||||
}
|
0
attachment-viewer/consumer-rules.pro
Normal file
21
attachment-viewer/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
2
attachment-viewer/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="im.vector.lib.attachmentviewer" />
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.view.View
|
||||
import im.vector.lib.attachmentviewer.databinding.ItemAnimatedImageAttachmentBinding
|
||||
|
||||
class AnimatedImageViewHolder constructor(itemView: View) :
|
||||
BaseViewHolder(itemView) {
|
||||
|
||||
val views = ItemAnimatedImageAttachmentBinding.bind(itemView)
|
||||
|
||||
internal val target = DefaultImageLoaderTarget(this, views.imageView)
|
||||
|
||||
override fun onRecycled() {
|
||||
super.onRecycled()
|
||||
views.imageView.setImageDrawable(null)
|
||||
}
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
sealed class AttachmentEvents {
|
||||
data class VideoEvent(val isPlaying: Boolean, val progress: Int, val duration: Int) : AttachmentEvents()
|
||||
}
|
||||
|
||||
interface AttachmentEventListener {
|
||||
fun onEvent(event: AttachmentEvents)
|
||||
}
|
||||
|
||||
sealed class AttachmentCommands {
|
||||
object PauseVideo : AttachmentCommands()
|
||||
object StartVideo : AttachmentCommands()
|
||||
data class SeekTo(val percentProgress: Int) : AttachmentCommands()
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
|
||||
sealed class AttachmentInfo(open val uid: String) {
|
||||
data class Image(override val uid: String, val url: String, val data: Any?) : AttachmentInfo(uid)
|
||||
data class AnimatedImage(override val uid: String, val url: String, val data: Any?) : AttachmentInfo(uid)
|
||||
data class Video(override val uid: String, val url: String, val data: Any, val thumbnail: Image?) : AttachmentInfo(uid)
|
||||
// data class Audio(override val uid: String, val url: String, val data: Any) : AttachmentInfo(uid)
|
||||
// data class File(override val uid: String, val url: String, val data: Any) : AttachmentInfo(uid)
|
||||
}
|
||||
|
||||
interface AttachmentSourceProvider {
|
||||
|
||||
fun getItemCount(): Int
|
||||
|
||||
fun getAttachmentInfoAt(position: Int): AttachmentInfo
|
||||
|
||||
fun loadImage(target: ImageLoaderTarget, info: AttachmentInfo.Image)
|
||||
|
||||
fun loadImage(target: ImageLoaderTarget, info: AttachmentInfo.AnimatedImage)
|
||||
|
||||
fun loadVideo(target: VideoLoaderTarget, info: AttachmentInfo.Video)
|
||||
|
||||
fun overlayViewAtPosition(context: Context, position: Int): View?
|
||||
|
||||
fun clear(id: String)
|
||||
}
|
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
* Copyright (C) 2018 stfalcon.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.GestureDetector
|
||||
import android.view.MotionEvent
|
||||
import android.view.ScaleGestureDetector
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.ImageView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.GestureDetectorCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.transition.TransitionManager
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import im.vector.lib.attachmentviewer.databinding.ActivityAttachmentViewerBinding
|
||||
|
||||
import java.lang.ref.WeakReference
|
||||
import kotlin.math.abs
|
||||
|
||||
abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventListener {
|
||||
|
||||
protected val pager2: ViewPager2
|
||||
get() = views.attachmentPager
|
||||
protected val imageTransitionView: ImageView
|
||||
get() = views.transitionImageView
|
||||
protected val transitionImageContainer: ViewGroup
|
||||
get() = views.transitionImageContainer
|
||||
|
||||
private var topInset = 0
|
||||
private var bottomInset = 0
|
||||
private var systemUiVisibility = true
|
||||
|
||||
private var overlayView: View? = null
|
||||
set(value) {
|
||||
if (value == overlayView) return
|
||||
overlayView?.let { views.rootContainer.removeView(it) }
|
||||
views.rootContainer.addView(value)
|
||||
value?.updatePadding(top = topInset, bottom = bottomInset)
|
||||
field = value
|
||||
}
|
||||
|
||||
private lateinit var views: ActivityAttachmentViewerBinding
|
||||
|
||||
private lateinit var swipeDismissHandler: SwipeToDismissHandler
|
||||
private lateinit var directionDetector: SwipeDirectionDetector
|
||||
private lateinit var scaleDetector: ScaleGestureDetector
|
||||
private lateinit var gestureDetector: GestureDetectorCompat
|
||||
|
||||
var currentPosition = 0
|
||||
private set
|
||||
|
||||
private var swipeDirection: SwipeDirection? = null
|
||||
|
||||
private fun isScaled() = attachmentsAdapter.isScaled(currentPosition)
|
||||
|
||||
private val attachmentsAdapter = AttachmentsAdapter()
|
||||
|
||||
private var wasScaled: Boolean = false
|
||||
private var isSwipeToDismissAllowed: Boolean = true
|
||||
private var isOverlayWasClicked = false
|
||||
|
||||
// private val shouldDismissToBottom: Boolean
|
||||
// get() = e == null
|
||||
// || !externalTransitionImageView.isRectVisible
|
||||
// || !isAtStartPosition
|
||||
|
||||
private var isImagePagerIdle = true
|
||||
|
||||
fun setSourceProvider(sourceProvider: AttachmentSourceProvider) {
|
||||
attachmentsAdapter.attachmentSourceProvider = sourceProvider
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
// This is important for the dispatchTouchEvent, if not we must correct
|
||||
// the touch coordinates
|
||||
window.decorView.systemUiVisibility = (
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
or View.SYSTEM_UI_FLAG_IMMERSIVE)
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
|
||||
|
||||
views = ActivityAttachmentViewerBinding.inflate(layoutInflater)
|
||||
setContentView(views.root)
|
||||
views.attachmentPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
|
||||
views.attachmentPager.adapter = attachmentsAdapter
|
||||
directionDetector = createSwipeDirectionDetector()
|
||||
gestureDetector = createGestureDetector()
|
||||
|
||||
views.attachmentPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||
override fun onPageScrollStateChanged(state: Int) {
|
||||
isImagePagerIdle = state == ViewPager2.SCROLL_STATE_IDLE
|
||||
}
|
||||
|
||||
override fun onPageSelected(position: Int) {
|
||||
onSelectedPositionChanged(position)
|
||||
}
|
||||
})
|
||||
|
||||
swipeDismissHandler = createSwipeToDismissHandler()
|
||||
views.rootContainer.setOnTouchListener(swipeDismissHandler)
|
||||
views.rootContainer.viewTreeObserver.addOnGlobalLayoutListener { swipeDismissHandler.translationLimit = views.dismissContainer.height / 4 }
|
||||
|
||||
scaleDetector = createScaleGestureDetector()
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(views.rootContainer) { _, insets ->
|
||||
overlayView?.updatePadding(top = insets.systemWindowInsetTop, bottom = insets.systemWindowInsetBottom)
|
||||
topInset = insets.systemWindowInsetTop
|
||||
bottomInset = insets.systemWindowInsetBottom
|
||||
insets
|
||||
}
|
||||
}
|
||||
|
||||
fun onSelectedPositionChanged(position: Int) {
|
||||
attachmentsAdapter.recyclerView?.findViewHolderForAdapterPosition(currentPosition)?.let {
|
||||
(it as? BaseViewHolder)?.onSelected(false)
|
||||
}
|
||||
attachmentsAdapter.recyclerView?.findViewHolderForAdapterPosition(position)?.let {
|
||||
(it as? BaseViewHolder)?.onSelected(true)
|
||||
if (it is VideoViewHolder) {
|
||||
it.eventListener = WeakReference(this)
|
||||
}
|
||||
}
|
||||
currentPosition = position
|
||||
overlayView = attachmentsAdapter.attachmentSourceProvider?.overlayViewAtPosition(this@AttachmentViewerActivity, position)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
attachmentsAdapter.onPause(currentPosition)
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
attachmentsAdapter.onResume(currentPosition)
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
|
||||
// The zoomable view is configured to disallow interception when image is zoomed
|
||||
|
||||
// Check if the overlay is visible, and wants to handle the click
|
||||
if (overlayView?.isVisible == true && overlayView?.dispatchTouchEvent(ev) == true) {
|
||||
return true
|
||||
}
|
||||
|
||||
// Log.v("ATTACHEMENTS", "================\ndispatchTouchEvent $ev")
|
||||
handleUpDownEvent(ev)
|
||||
|
||||
// Log.v("ATTACHEMENTS", "scaleDetector is in progress ${scaleDetector.isInProgress}")
|
||||
// Log.v("ATTACHEMENTS", "pointerCount ${ev.pointerCount}")
|
||||
// Log.v("ATTACHEMENTS", "wasScaled $wasScaled")
|
||||
if (swipeDirection == null && (scaleDetector.isInProgress || ev.pointerCount > 1 || wasScaled)) {
|
||||
wasScaled = true
|
||||
// Log.v("ATTACHEMENTS", "dispatch to pager")
|
||||
return views.attachmentPager.dispatchTouchEvent(ev)
|
||||
}
|
||||
|
||||
// Log.v("ATTACHEMENTS", "is current item scaled ${isScaled()}")
|
||||
return (if (isScaled()) super.dispatchTouchEvent(ev) else handleTouchIfNotScaled(ev)).also {
|
||||
// Log.v("ATTACHEMENTS", "\n================")
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUpDownEvent(event: MotionEvent) {
|
||||
// Log.v("ATTACHEMENTS", "handleUpDownEvent $event")
|
||||
if (event.action == MotionEvent.ACTION_UP) {
|
||||
handleEventActionUp(event)
|
||||
}
|
||||
|
||||
if (event.action == MotionEvent.ACTION_DOWN) {
|
||||
handleEventActionDown(event)
|
||||
}
|
||||
|
||||
scaleDetector.onTouchEvent(event)
|
||||
gestureDetector.onTouchEvent(event)
|
||||
}
|
||||
|
||||
private fun handleEventActionDown(event: MotionEvent) {
|
||||
swipeDirection = null
|
||||
wasScaled = false
|
||||
views.attachmentPager.dispatchTouchEvent(event)
|
||||
|
||||
swipeDismissHandler.onTouch(views.rootContainer, event)
|
||||
isOverlayWasClicked = dispatchOverlayTouch(event)
|
||||
}
|
||||
|
||||
private fun handleEventActionUp(event: MotionEvent) {
|
||||
// wasDoubleTapped = false
|
||||
swipeDismissHandler.onTouch(views.rootContainer, event)
|
||||
views.attachmentPager.dispatchTouchEvent(event)
|
||||
isOverlayWasClicked = dispatchOverlayTouch(event)
|
||||
}
|
||||
|
||||
private fun handleSingleTap(event: MotionEvent, isOverlayWasClicked: Boolean) {
|
||||
// TODO if there is no overlay, we should at least toggle system bars?
|
||||
if (overlayView != null && !isOverlayWasClicked) {
|
||||
toggleOverlayViewVisibility()
|
||||
super.dispatchTouchEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun toggleOverlayViewVisibility() {
|
||||
if (systemUiVisibility) {
|
||||
// we hide
|
||||
TransitionManager.beginDelayedTransition(views.rootContainer)
|
||||
hideSystemUI()
|
||||
overlayView?.isVisible = false
|
||||
} else {
|
||||
// we show
|
||||
TransitionManager.beginDelayedTransition(views.rootContainer)
|
||||
showSystemUI()
|
||||
overlayView?.isVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleTouchIfNotScaled(event: MotionEvent): Boolean {
|
||||
// Log.v("ATTACHEMENTS", "handleTouchIfNotScaled $event")
|
||||
directionDetector.handleTouchEvent(event)
|
||||
|
||||
return when (swipeDirection) {
|
||||
SwipeDirection.Up, SwipeDirection.Down -> {
|
||||
if (isSwipeToDismissAllowed && !wasScaled && isImagePagerIdle) {
|
||||
swipeDismissHandler.onTouch(views.rootContainer, event)
|
||||
} else true
|
||||
}
|
||||
SwipeDirection.Left, SwipeDirection.Right -> {
|
||||
views.attachmentPager.dispatchTouchEvent(event)
|
||||
}
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSwipeViewMove(translationY: Float, translationLimit: Int) {
|
||||
val alpha = calculateTranslationAlpha(translationY, translationLimit)
|
||||
views.backgroundView.alpha = alpha
|
||||
views.dismissContainer.alpha = alpha
|
||||
overlayView?.alpha = alpha
|
||||
}
|
||||
|
||||
private fun dispatchOverlayTouch(event: MotionEvent): Boolean =
|
||||
overlayView
|
||||
?.let { it.isVisible && it.dispatchTouchEvent(event) }
|
||||
?: false
|
||||
|
||||
private fun calculateTranslationAlpha(translationY: Float, translationLimit: Int): Float =
|
||||
1.0f - 1.0f / translationLimit.toFloat() / 4f * abs(translationY)
|
||||
|
||||
private fun createSwipeToDismissHandler()
|
||||
: SwipeToDismissHandler = SwipeToDismissHandler(
|
||||
swipeView = views.dismissContainer,
|
||||
shouldAnimateDismiss = { shouldAnimateDismiss() },
|
||||
onDismiss = { animateClose() },
|
||||
onSwipeViewMove = ::handleSwipeViewMove)
|
||||
|
||||
private fun createSwipeDirectionDetector() =
|
||||
SwipeDirectionDetector(this) { swipeDirection = it }
|
||||
|
||||
private fun createScaleGestureDetector() =
|
||||
ScaleGestureDetector(this, ScaleGestureDetector.SimpleOnScaleGestureListener())
|
||||
|
||||
private fun createGestureDetector() =
|
||||
GestureDetectorCompat(this, object : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
|
||||
if (isImagePagerIdle) {
|
||||
handleSingleTap(e, isOverlayWasClicked)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onDoubleTap(e: MotionEvent?): Boolean {
|
||||
return super.onDoubleTap(e)
|
||||
}
|
||||
})
|
||||
|
||||
override fun onEvent(event: AttachmentEvents) {
|
||||
if (overlayView is AttachmentEventListener) {
|
||||
(overlayView as? AttachmentEventListener)?.onEvent(event)
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun shouldAnimateDismiss(): Boolean = true
|
||||
|
||||
protected open fun animateClose() {
|
||||
window.statusBarColor = Color.TRANSPARENT
|
||||
finish()
|
||||
}
|
||||
|
||||
fun handle(commands: AttachmentCommands) {
|
||||
(attachmentsAdapter.recyclerView?.findViewHolderForAdapterPosition(currentPosition) as? BaseViewHolder)
|
||||
?.handleCommand(commands)
|
||||
}
|
||||
|
||||
private fun hideSystemUI() {
|
||||
systemUiVisibility = false
|
||||
// Enables regular immersive mode.
|
||||
// For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE.
|
||||
// Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
|
||||
// Set the content to appear under the system bars so that the
|
||||
// content doesn't resize when the system bars hide and show.
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
// Hide the nav bar and status bar
|
||||
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
or View.SYSTEM_UI_FLAG_FULLSCREEN)
|
||||
}
|
||||
|
||||
// Shows the system bars by removing all the flags
|
||||
// except for the ones that make the content appear under the system bars.
|
||||
private fun showSystemUI() {
|
||||
systemUiVisibility = true
|
||||
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
|
||||
}
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
class AttachmentsAdapter : RecyclerView.Adapter<BaseViewHolder>() {
|
||||
|
||||
var attachmentSourceProvider: AttachmentSourceProvider? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
var recyclerView: RecyclerView? = null
|
||||
|
||||
override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
|
||||
this.recyclerView = recyclerView
|
||||
}
|
||||
|
||||
override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
|
||||
this.recyclerView = null
|
||||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder {
|
||||
val inflater = LayoutInflater.from(parent.context)
|
||||
val itemView = inflater.inflate(viewType, parent, false)
|
||||
return when (viewType) {
|
||||
R.layout.item_image_attachment -> ZoomableImageViewHolder(itemView)
|
||||
R.layout.item_animated_image_attachment -> AnimatedImageViewHolder(itemView)
|
||||
R.layout.item_video_attachment -> VideoViewHolder(itemView)
|
||||
else -> UnsupportedViewHolder(itemView)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int {
|
||||
val info = attachmentSourceProvider!!.getAttachmentInfoAt(position)
|
||||
return when (info) {
|
||||
is AttachmentInfo.Image -> R.layout.item_image_attachment
|
||||
is AttachmentInfo.Video -> R.layout.item_video_attachment
|
||||
is AttachmentInfo.AnimatedImage -> R.layout.item_animated_image_attachment
|
||||
// is AttachmentInfo.Audio -> TODO()
|
||||
// is AttachmentInfo.File -> TODO()
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return attachmentSourceProvider?.getItemCount() ?: 0
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: BaseViewHolder, position: Int) {
|
||||
attachmentSourceProvider?.getAttachmentInfoAt(position)?.let {
|
||||
holder.bind(it)
|
||||
when (it) {
|
||||
is AttachmentInfo.Image -> {
|
||||
attachmentSourceProvider?.loadImage((holder as ZoomableImageViewHolder).target, it)
|
||||
}
|
||||
is AttachmentInfo.AnimatedImage -> {
|
||||
attachmentSourceProvider?.loadImage((holder as AnimatedImageViewHolder).target, it)
|
||||
}
|
||||
is AttachmentInfo.Video -> {
|
||||
attachmentSourceProvider?.loadVideo((holder as VideoViewHolder).target, it)
|
||||
}
|
||||
// else -> {
|
||||
// // }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewAttachedToWindow(holder: BaseViewHolder) {
|
||||
holder.onAttached()
|
||||
}
|
||||
|
||||
override fun onViewRecycled(holder: BaseViewHolder) {
|
||||
holder.onRecycled()
|
||||
}
|
||||
|
||||
override fun onViewDetachedFromWindow(holder: BaseViewHolder) {
|
||||
holder.onDetached()
|
||||
}
|
||||
|
||||
fun isScaled(position: Int): Boolean {
|
||||
val holder = recyclerView?.findViewHolderForAdapterPosition(position)
|
||||
if (holder is ZoomableImageViewHolder) {
|
||||
return holder.views.touchImageView.attacher.scale > 1f
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun onPause(position: Int) {
|
||||
val holder = recyclerView?.findViewHolderForAdapterPosition(position) as? BaseViewHolder
|
||||
holder?.entersBackground()
|
||||
}
|
||||
|
||||
fun onResume(position: Int) {
|
||||
val holder = recyclerView?.findViewHolderForAdapterPosition(position) as? BaseViewHolder
|
||||
holder?.entersForeground()
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
||||
abstract class BaseViewHolder constructor(itemView: View) :
|
||||
RecyclerView.ViewHolder(itemView) {
|
||||
|
||||
open fun onRecycled() {
|
||||
boundResourceUid = null
|
||||
}
|
||||
|
||||
open fun onAttached() {}
|
||||
open fun onDetached() {}
|
||||
open fun entersBackground() {}
|
||||
open fun entersForeground() {}
|
||||
open fun onSelected(selected: Boolean) {}
|
||||
|
||||
open fun handleCommand(commands: AttachmentCommands) {}
|
||||
|
||||
var boundResourceUid: String? = null
|
||||
|
||||
open fun bind(attachmentInfo: AttachmentInfo) {
|
||||
boundResourceUid = attachmentInfo.uid
|
||||
}
|
||||
}
|
||||
|
||||
class UnsupportedViewHolder constructor(itemView: View) :
|
||||
BaseViewHolder(itemView)
|
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
|
||||
interface ImageLoaderTarget {
|
||||
|
||||
fun contextView(): ImageView
|
||||
|
||||
fun onResourceLoading(uid: String, placeholder: Drawable?)
|
||||
|
||||
fun onLoadFailed(uid: String, errorDrawable: Drawable?)
|
||||
|
||||
fun onResourceCleared(uid: String, placeholder: Drawable?)
|
||||
|
||||
fun onResourceReady(uid: String, resource: Drawable)
|
||||
}
|
||||
|
||||
internal class DefaultImageLoaderTarget(val holder: AnimatedImageViewHolder, private val contextView: ImageView)
|
||||
: ImageLoaderTarget {
|
||||
override fun contextView(): ImageView {
|
||||
return contextView
|
||||
}
|
||||
|
||||
override fun onResourceLoading(uid: String, placeholder: Drawable?) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.imageLoaderProgress.isVisible = true
|
||||
}
|
||||
|
||||
override fun onLoadFailed(uid: String, errorDrawable: Drawable?) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.imageLoaderProgress.isVisible = false
|
||||
holder.views.imageView.setImageDrawable(errorDrawable)
|
||||
}
|
||||
|
||||
override fun onResourceCleared(uid: String, placeholder: Drawable?) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.imageView.setImageDrawable(placeholder)
|
||||
}
|
||||
|
||||
override fun onResourceReady(uid: String, resource: Drawable) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.imageLoaderProgress.isVisible = false
|
||||
// Glide mess up the view size :/
|
||||
holder.views.imageView.updateLayoutParams {
|
||||
width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
height = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
}
|
||||
holder.views.imageView.setImageDrawable(resource)
|
||||
if (resource is Animatable) {
|
||||
resource.start()
|
||||
}
|
||||
}
|
||||
|
||||
internal class ZoomableImageTarget(val holder: ZoomableImageViewHolder, private val contextView: ImageView) : ImageLoaderTarget {
|
||||
override fun contextView() = contextView
|
||||
|
||||
override fun onResourceLoading(uid: String, placeholder: Drawable?) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.imageLoaderProgress.isVisible = true
|
||||
holder.views.touchImageView.setImageDrawable(placeholder)
|
||||
}
|
||||
|
||||
override fun onLoadFailed(uid: String, errorDrawable: Drawable?) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.imageLoaderProgress.isVisible = false
|
||||
holder.views.touchImageView.setImageDrawable(errorDrawable)
|
||||
}
|
||||
|
||||
override fun onResourceCleared(uid: String, placeholder: Drawable?) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.touchImageView.setImageDrawable(placeholder)
|
||||
}
|
||||
|
||||
override fun onResourceReady(uid: String, resource: Drawable) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.imageLoaderProgress.isVisible = false
|
||||
// Glide mess up the view size :/
|
||||
holder.views.touchImageView.updateLayoutParams {
|
||||
width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
height = LinearLayout.LayoutParams.MATCH_PARENT
|
||||
}
|
||||
holder.views.touchImageView.setImageDrawable(resource)
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
* Copyright (C) 2018 stfalcon.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
sealed class SwipeDirection {
|
||||
object NotDetected : SwipeDirection()
|
||||
object Up : SwipeDirection()
|
||||
object Down : SwipeDirection()
|
||||
object Left : SwipeDirection()
|
||||
object Right : SwipeDirection()
|
||||
|
||||
companion object {
|
||||
fun fromAngle(angle: Double): SwipeDirection {
|
||||
return when (angle) {
|
||||
in 0.0..45.0 -> Right
|
||||
in 45.0..135.0 -> Up
|
||||
in 135.0..225.0 -> Left
|
||||
in 225.0..315.0 -> Down
|
||||
in 315.0..360.0 -> Right
|
||||
else -> NotDetected
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
* Copyright (C) 2018 stfalcon.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.content.Context
|
||||
import android.view.MotionEvent
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class SwipeDirectionDetector(
|
||||
context: Context,
|
||||
private val onDirectionDetected: (SwipeDirection) -> Unit
|
||||
) {
|
||||
|
||||
private val touchSlop: Int = android.view.ViewConfiguration.get(context).scaledTouchSlop
|
||||
private var startX: Float = 0f
|
||||
private var startY: Float = 0f
|
||||
private var isDetected: Boolean = false
|
||||
|
||||
fun handleTouchEvent(event: MotionEvent) {
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
startX = event.x
|
||||
startY = event.y
|
||||
}
|
||||
MotionEvent.ACTION_CANCEL, MotionEvent.ACTION_UP -> {
|
||||
if (!isDetected) {
|
||||
onDirectionDetected(SwipeDirection.NotDetected)
|
||||
}
|
||||
startY = 0.0f
|
||||
startX = startY
|
||||
isDetected = false
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> if (!isDetected && getEventDistance(event) > touchSlop) {
|
||||
isDetected = true
|
||||
onDirectionDetected(getDirection(startX, startY, event.x, event.y))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two points in the plane p1=(x1, x2) and p2=(y1, y1), this method
|
||||
* returns the direction that an arrow pointing from p1 to p2 would have.
|
||||
*
|
||||
* @param x1 the x position of the first point
|
||||
* @param y1 the y position of the first point
|
||||
* @param x2 the x position of the second point
|
||||
* @param y2 the y position of the second point
|
||||
* @return the direction
|
||||
*/
|
||||
private fun getDirection(x1: Float, y1: Float, x2: Float, y2: Float): SwipeDirection {
|
||||
val angle = getAngle(x1, y1, x2, y2)
|
||||
return SwipeDirection.fromAngle(angle)
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the angle between two points in the plane (x1,y1) and (x2, y2)
|
||||
* The angle is measured with 0/360 being the X-axis to the right, angles
|
||||
* increase counter clockwise.
|
||||
*
|
||||
* @param x1 the x position of the first point
|
||||
* @param y1 the y position of the first point
|
||||
* @param x2 the x position of the second point
|
||||
* @param y2 the y position of the second point
|
||||
* @return the angle between two points
|
||||
*/
|
||||
private fun getAngle(x1: Float, y1: Float, x2: Float, y2: Float): Double {
|
||||
val rad = Math.atan2((y1 - y2).toDouble(), (x2 - x1).toDouble()) + Math.PI
|
||||
return (rad * 180 / Math.PI + 180) % 360
|
||||
}
|
||||
|
||||
private fun getEventDistance(ev: MotionEvent): Float {
|
||||
val dx = ev.getX(0) - startX
|
||||
val dy = ev.getY(0) - startY
|
||||
return sqrt((dx * dx + dy * dy).toDouble()).toFloat()
|
||||
}
|
||||
}
|
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
* Copyright (C) 2018 stfalcon.com
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.animation.Animator
|
||||
import android.animation.AnimatorListenerAdapter
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Rect
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewPropertyAnimator
|
||||
import android.view.animation.AccelerateInterpolator
|
||||
|
||||
class SwipeToDismissHandler(
|
||||
private val swipeView: View,
|
||||
private val onDismiss: () -> Unit,
|
||||
private val onSwipeViewMove: (translationY: Float, translationLimit: Int) -> Unit,
|
||||
private val shouldAnimateDismiss: () -> Boolean
|
||||
) : View.OnTouchListener {
|
||||
|
||||
companion object {
|
||||
private const val ANIMATION_DURATION = 200L
|
||||
}
|
||||
|
||||
var translationLimit: Int = swipeView.height / 4
|
||||
private var isTracking = false
|
||||
private var startY: Float = 0f
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
if (swipeView.hitRect.contains(event.x.toInt(), event.y.toInt())) {
|
||||
isTracking = true
|
||||
}
|
||||
startY = event.y
|
||||
return true
|
||||
}
|
||||
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||
if (isTracking) {
|
||||
isTracking = false
|
||||
onTrackingEnd(v.height)
|
||||
}
|
||||
return true
|
||||
}
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
if (isTracking) {
|
||||
val translationY = event.y - startY
|
||||
swipeView.translationY = translationY
|
||||
onSwipeViewMove(translationY, translationLimit)
|
||||
}
|
||||
return true
|
||||
}
|
||||
else -> {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun initiateDismissToBottom() {
|
||||
animateTranslation(swipeView.height.toFloat())
|
||||
}
|
||||
|
||||
private fun onTrackingEnd(parentHeight: Int) {
|
||||
val animateTo = when {
|
||||
swipeView.translationY < -translationLimit -> -parentHeight.toFloat()
|
||||
swipeView.translationY > translationLimit -> parentHeight.toFloat()
|
||||
else -> 0f
|
||||
}
|
||||
|
||||
if (animateTo != 0f && !shouldAnimateDismiss()) {
|
||||
onDismiss()
|
||||
} else {
|
||||
animateTranslation(animateTo)
|
||||
}
|
||||
}
|
||||
|
||||
private fun animateTranslation(translationTo: Float) {
|
||||
swipeView.animate()
|
||||
.translationY(translationTo)
|
||||
.setDuration(ANIMATION_DURATION)
|
||||
.setInterpolator(AccelerateInterpolator())
|
||||
.setUpdateListener { onSwipeViewMove(swipeView.translationY, translationLimit) }
|
||||
.setAnimatorListener(onAnimationEnd = {
|
||||
if (translationTo != 0f) {
|
||||
onDismiss()
|
||||
}
|
||||
|
||||
// remove the update listener, otherwise it will be saved on the next animation execution:
|
||||
swipeView.animate().setUpdateListener(null)
|
||||
})
|
||||
.start()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun ViewPropertyAnimator.setAnimatorListener(
|
||||
onAnimationEnd: ((Animator?) -> Unit)? = null,
|
||||
onAnimationStart: ((Animator?) -> Unit)? = null
|
||||
) = this.setListener(
|
||||
object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationEnd(animation: Animator?) {
|
||||
onAnimationEnd?.invoke(animation)
|
||||
}
|
||||
|
||||
override fun onAnimationStart(animation: Animator?) {
|
||||
onAnimationStart?.invoke(animation)
|
||||
}
|
||||
})
|
||||
|
||||
internal val View?.hitRect: Rect
|
||||
get() = Rect().also { this?.getHitRect(it) }
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.widget.ImageView
|
||||
import androidx.core.view.isVisible
|
||||
import java.io.File
|
||||
|
||||
interface VideoLoaderTarget {
|
||||
fun contextView(): ImageView
|
||||
|
||||
fun onThumbnailResourceLoading(uid: String, placeholder: Drawable?)
|
||||
|
||||
fun onThumbnailLoadFailed(uid: String, errorDrawable: Drawable?)
|
||||
|
||||
fun onThumbnailResourceCleared(uid: String, placeholder: Drawable?)
|
||||
|
||||
fun onThumbnailResourceReady(uid: String, resource: Drawable)
|
||||
|
||||
fun onVideoFileLoading(uid: String)
|
||||
fun onVideoFileLoadFailed(uid: String)
|
||||
fun onVideoFileReady(uid: String, file: File)
|
||||
fun onVideoURLReady(uid: String, path: String)
|
||||
}
|
||||
|
||||
internal class DefaultVideoLoaderTarget(val holder: VideoViewHolder, private val contextView: ImageView) : VideoLoaderTarget {
|
||||
override fun contextView(): ImageView = contextView
|
||||
|
||||
override fun onThumbnailResourceLoading(uid: String, placeholder: Drawable?) {
|
||||
}
|
||||
|
||||
override fun onThumbnailLoadFailed(uid: String, errorDrawable: Drawable?) {
|
||||
}
|
||||
|
||||
override fun onThumbnailResourceCleared(uid: String, placeholder: Drawable?) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.videoThumbnailImage.setImageDrawable(placeholder)
|
||||
}
|
||||
|
||||
override fun onThumbnailResourceReady(uid: String, resource: Drawable) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.videoThumbnailImage.setImageDrawable(resource)
|
||||
}
|
||||
|
||||
override fun onVideoFileLoading(uid: String) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.views.videoThumbnailImage.isVisible = true
|
||||
holder.views.videoLoaderProgress.isVisible = true
|
||||
holder.views.videoView.isVisible = false
|
||||
}
|
||||
|
||||
override fun onVideoFileLoadFailed(uid: String) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
holder.videoFileLoadError()
|
||||
}
|
||||
|
||||
override fun onVideoFileReady(uid: String, file: File) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
arrangeForVideoReady()
|
||||
holder.videoReady(file)
|
||||
}
|
||||
|
||||
override fun onVideoURLReady(uid: String, path: String) {
|
||||
if (holder.boundResourceUid != uid) return
|
||||
arrangeForVideoReady()
|
||||
holder.videoReady(path)
|
||||
}
|
||||
|
||||
private fun arrangeForVideoReady() {
|
||||
holder.views.videoThumbnailImage.isVisible = false
|
||||
holder.views.videoLoaderProgress.isVisible = false
|
||||
holder.views.videoView.isVisible = true
|
||||
}
|
||||
}
|
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import im.vector.lib.attachmentviewer.databinding.ItemVideoAttachmentBinding
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import java.io.File
|
||||
import java.lang.ref.WeakReference
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// TODO, it would be probably better to use a unique media player
|
||||
// for better customization and control
|
||||
// But for now VideoView is enough, it released player when detached, we use a timer to update progress
|
||||
class VideoViewHolder constructor(itemView: View) :
|
||||
BaseViewHolder(itemView) {
|
||||
|
||||
private var isSelected = false
|
||||
private var mVideoPath: String? = null
|
||||
private var progressDisposable: Disposable? = null
|
||||
private var progress: Int = 0
|
||||
private var wasPaused = false
|
||||
|
||||
var eventListener: WeakReference<AttachmentEventListener>? = null
|
||||
|
||||
val views = ItemVideoAttachmentBinding.bind(itemView)
|
||||
|
||||
internal val target = DefaultVideoLoaderTarget(this, views.videoThumbnailImage)
|
||||
|
||||
override fun onRecycled() {
|
||||
super.onRecycled()
|
||||
progressDisposable?.dispose()
|
||||
progressDisposable = null
|
||||
mVideoPath = null
|
||||
}
|
||||
|
||||
fun videoReady(file: File) {
|
||||
mVideoPath = file.path
|
||||
if (isSelected) {
|
||||
startPlaying()
|
||||
}
|
||||
}
|
||||
|
||||
fun videoReady(path: String) {
|
||||
mVideoPath = path
|
||||
if (isSelected) {
|
||||
startPlaying()
|
||||
}
|
||||
}
|
||||
|
||||
fun videoFileLoadError() {
|
||||
}
|
||||
|
||||
override fun entersBackground() {
|
||||
if (views.videoView.isPlaying) {
|
||||
progress = views.videoView.currentPosition
|
||||
progressDisposable?.dispose()
|
||||
progressDisposable = null
|
||||
views.videoView.stopPlayback()
|
||||
views.videoView.pause()
|
||||
}
|
||||
}
|
||||
|
||||
override fun entersForeground() {
|
||||
onSelected(isSelected)
|
||||
}
|
||||
|
||||
override fun onSelected(selected: Boolean) {
|
||||
if (!selected) {
|
||||
if (views.videoView.isPlaying) {
|
||||
progress = views.videoView.currentPosition
|
||||
views.videoView.stopPlayback()
|
||||
} else {
|
||||
progress = 0
|
||||
}
|
||||
progressDisposable?.dispose()
|
||||
progressDisposable = null
|
||||
} else {
|
||||
if (mVideoPath != null) {
|
||||
startPlaying()
|
||||
}
|
||||
}
|
||||
isSelected = true
|
||||
}
|
||||
|
||||
private fun startPlaying() {
|
||||
views.videoThumbnailImage.isVisible = false
|
||||
views.videoLoaderProgress.isVisible = false
|
||||
views.videoView.isVisible = true
|
||||
|
||||
views.videoView.setOnPreparedListener {
|
||||
progressDisposable?.dispose()
|
||||
progressDisposable = Observable.interval(100, TimeUnit.MILLISECONDS)
|
||||
.timeInterval()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe {
|
||||
val duration = views.videoView.duration
|
||||
val progress = views.videoView.currentPosition
|
||||
val isPlaying = views.videoView.isPlaying
|
||||
// Log.v("FOO", "isPlaying $isPlaying $progress/$duration")
|
||||
eventListener?.get()?.onEvent(AttachmentEvents.VideoEvent(isPlaying, progress, duration))
|
||||
}
|
||||
}
|
||||
try {
|
||||
views.videoView.setVideoPath(mVideoPath)
|
||||
} catch (failure: Throwable) {
|
||||
// Couldn't open
|
||||
Log.v(VideoViewHolder::class.java.name, "Failed to start video")
|
||||
}
|
||||
|
||||
if (!wasPaused) {
|
||||
views.videoView.start()
|
||||
if (progress > 0) {
|
||||
views.videoView.seekTo(progress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleCommand(commands: AttachmentCommands) {
|
||||
if (!isSelected) return
|
||||
when (commands) {
|
||||
AttachmentCommands.StartVideo -> {
|
||||
wasPaused = false
|
||||
views.videoView.start()
|
||||
}
|
||||
AttachmentCommands.PauseVideo -> {
|
||||
wasPaused = true
|
||||
views.videoView.pause()
|
||||
}
|
||||
is AttachmentCommands.SeekTo -> {
|
||||
val duration = views.videoView.duration
|
||||
if (duration > 0) {
|
||||
val seekDuration = duration * (commands.percentProgress / 100f)
|
||||
views.videoView.seekTo(seekDuration.toInt())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun bind(attachmentInfo: AttachmentInfo) {
|
||||
super.bind(attachmentInfo)
|
||||
progress = 0
|
||||
wasPaused = false
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2020 New Vector 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.
|
||||
*/
|
||||
|
||||
package im.vector.lib.attachmentviewer
|
||||
|
||||
import android.view.View
|
||||
import im.vector.lib.attachmentviewer.databinding.ItemImageAttachmentBinding
|
||||
|
||||
class ZoomableImageViewHolder constructor(itemView: View) :
|
||||
BaseViewHolder(itemView) {
|
||||
|
||||
val views = ItemImageAttachmentBinding.bind(itemView)
|
||||
|
||||
init {
|
||||
views.touchImageView.setAllowParentInterceptOnEdge(false)
|
||||
views.touchImageView.setOnScaleChangeListener { scaleFactor, _, _ ->
|
||||
// Log.v("ATTACHEMENTS", "scaleFactor $scaleFactor")
|
||||
// It's a bit annoying but when you pitch down the scaling
|
||||
// is not exactly one :/
|
||||
views.touchImageView.setAllowParentInterceptOnEdge(scaleFactor <= 1.0008f)
|
||||
}
|
||||
views.touchImageView.setScale(1.0f, true)
|
||||
views.touchImageView.setAllowParentInterceptOnEdge(true)
|
||||
}
|
||||
|
||||
internal val target = DefaultImageLoaderTarget.ZoomableImageTarget(this, views.touchImageView)
|
||||
|
||||
override fun onRecycled() {
|
||||
super.onRecycled()
|
||||
views.touchImageView.setImageDrawable(null)
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/rootContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".AttachmentViewerActivity">
|
||||
|
||||
<View
|
||||
android:id="@+id/backgroundView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="1"
|
||||
android:background="@android:color/black" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/dismissContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/transitionImageContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:ignore="UselessParent"
|
||||
tools:visibility="invisible">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/transitionImageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/attachmentPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="visible" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</FrameLayout>
|
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:visibility="visible"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<ProgressBar
|
||||
android:layout_centerInParent="true"
|
||||
android:id="@+id/imageLoaderProgress"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:visibility="visible"
|
||||
tools:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<com.github.chrisbanes.photoview.PhotoView
|
||||
android:id="@+id/touchImageView"
|
||||
android:visibility="visible"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<ProgressBar
|
||||
android:layout_centerInParent="true"
|
||||
android:id="@+id/imageLoaderProgress"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:visibility="visible"
|
||||
tools:visibility="gone" />
|
||||
|
||||
</RelativeLayout>
|
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/videoThumbnailImage"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:scaleType="centerInside" />
|
||||
|
||||
<VideoView
|
||||
android:id="@+id/videoView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerInParent="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/videoControlIcon"
|
||||
android:layout_centerInParent="true"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
android:layout_width="44dp"
|
||||
android:layout_height="44dp"
|
||||
/>
|
||||
|
||||
<ProgressBar
|
||||
android:layout_centerInParent="true"
|
||||
android:id="@+id/videoLoaderProgress"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:visibility="invisible"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/videoMediaViewerErrorView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_margin="16dp"
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone"
|
||||
tools:text="Error"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</RelativeLayout>
|
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/design_default_color_primary">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/testPage"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="1"
|
||||
android:textSize="80sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
50
build.gradle
@@ -1,7 +1,9 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.50'
|
||||
// Ref: https://kotlinlang.org/releases.html
|
||||
ext.kotlin_version = '1.4.20'
|
||||
ext.kotlin_coroutines_version = "1.4.1"
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
@@ -10,12 +12,11 @@ buildscript {
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||
classpath 'com.google.gms:google-services:4.3.2'
|
||||
classpath "com.airbnb.okreplay:gradle-plugin:1.5.0"
|
||||
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||
classpath 'com.google.gms:google-services:4.3.4'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
|
||||
classpath 'com.google.android.gms:oss-licenses-plugin:0.9.5'
|
||||
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.2'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
@@ -38,6 +39,14 @@ allprojects {
|
||||
includeGroupByRegex "com\\.github\\.yalantis"
|
||||
// JsonViewer
|
||||
includeGroupByRegex 'com\\.github\\.BillCarsonFr'
|
||||
// PhotoView
|
||||
includeGroupByRegex 'com\\.github\\.chrisbanes'
|
||||
// PFLockScreen-Android
|
||||
includeGroupByRegex 'com\\.github\\.vector-im'
|
||||
|
||||
//Chat effects
|
||||
includeGroupByRegex 'com\\.github\\.jetradarmobile'
|
||||
includeGroupByRegex 'nl\\.dionsegijn'
|
||||
}
|
||||
}
|
||||
maven {
|
||||
@@ -47,15 +56,21 @@ allprojects {
|
||||
}
|
||||
}
|
||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||
// Jitsi repo
|
||||
maven {
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-2.9.3"
|
||||
// Note: to test Jitsi release you can use a local file like this:
|
||||
// url "file:///Users/bmarty/workspaces/jitsi_libre_maven/android-sdk-2.9.3"
|
||||
}
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
|
||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
||||
// Warnings are potential errors, so stop ignoring them
|
||||
kotlinOptions.allWarningsAsErrors = true
|
||||
// You can override by passing `-PallWarningsAsErrors=false` in the command line
|
||||
kotlinOptions.allWarningsAsErrors = project.getProperties().getOrDefault("allWarningsAsErrors", "true").toBoolean()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
@@ -70,15 +85,15 @@ apply plugin: 'org.sonarqube'
|
||||
|
||||
sonarqube {
|
||||
properties {
|
||||
property "sonar.projectName", "RiotX-Android"
|
||||
property "sonar.projectKey", "vector.android.riotx"
|
||||
property "sonar.projectName", "Element-Android"
|
||||
property "sonar.projectKey", "im.vector.app.android"
|
||||
property "sonar.host.url", "https://sonarcloud.io"
|
||||
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
|
||||
property "sonar.sourceEncoding", "UTF-8"
|
||||
property "sonar.links.homepage", "https://github.com/vector-im/riotX-android/"
|
||||
property "sonar.links.ci", "https://buildkite.com/matrix-dot-org/riotx-android"
|
||||
property "sonar.links.scm", "https://github.com/vector-im/riotX-android/"
|
||||
property "sonar.links.issue", "https://github.com/vector-im/riotX-android/issues"
|
||||
property "sonar.links.homepage", "https://github.com/vector-im/element-android/"
|
||||
property "sonar.links.ci", "https://buildkite.com/matrix-dot-org/element-android"
|
||||
property "sonar.links.scm", "https://github.com/vector-im/element-android/"
|
||||
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
|
||||
property "sonar.organization", "new_vector_ltd_organization"
|
||||
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
|
||||
}
|
||||
@@ -89,11 +104,18 @@ project(":vector") {
|
||||
properties {
|
||||
property "sonar.sources", project(":vector").android.sourceSets.main.java.srcDirs
|
||||
// exclude source code from analyses separated by a colon (:)
|
||||
// property "sonar.exclusions", "**/*.*"
|
||||
// Exclude Java source
|
||||
property "sonar.exclusions", "**/BugReporterMultipartBody.java"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
project(":diff-match-patch") {
|
||||
sonarqube {
|
||||
skipProject = true
|
||||
}
|
||||
}
|
||||
|
||||
//project(":matrix-sdk-android") {
|
||||
// sonarqube {
|
||||
// properties {
|
||||
|
285
docs/add_threePids.md
Normal file
@@ -0,0 +1,285 @@
|
||||
# Adding and removing ThreePids to an account
|
||||
|
||||
## Add email
|
||||
|
||||
### User enter the email
|
||||
|
||||
> POST https://homeserver.org/_matrix/client/r0/account/3pid/email/requestToken
|
||||
|
||||
```json
|
||||
{
|
||||
"email": "alice@email-provider.org",
|
||||
"client_secret": "TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh",
|
||||
"send_attempt": 1
|
||||
}
|
||||
```
|
||||
|
||||
#### The email is already added to an account
|
||||
|
||||
400
|
||||
|
||||
```json
|
||||
{
|
||||
"errcode": "M_THREEPID_IN_USE",
|
||||
"error": "Email is already in use"
|
||||
}
|
||||
```
|
||||
|
||||
#### The email is free
|
||||
|
||||
Wording: "We've sent you an email to verify your address. Please follow the instructions there and then click the button below."
|
||||
|
||||
200
|
||||
|
||||
```json
|
||||
{
|
||||
"sid": "bxyDHuJKsdkjMlTJ"
|
||||
}
|
||||
```
|
||||
|
||||
## User receive an e-mail
|
||||
|
||||
> [homeserver.org] Validate your email
|
||||
>
|
||||
> A request to add an email address to your Matrix account has been received. If this was you, please click the link below to confirm adding this email:
|
||||
https://homeserver.org/_matrix/client/unstable/add_threepid/email/submit_token?token=WUnEhQAmJrXupdEbXgdWvnVIKaGYZFsU&client_secret=TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh&sid=bxyDHuJKsdkjMlTJ
|
||||
>
|
||||
> If this was not you, you can safely ignore this email. Thank you.
|
||||
|
||||
### User clicks on the link
|
||||
|
||||
The browser displays the following message:
|
||||
|
||||
> Your email has now been validated, please return to your client. You may now close this window.
|
||||
|
||||
### User returns on Element
|
||||
|
||||
User clicks on CONTINUE
|
||||
|
||||
> POST https://homeserver.org/_matrix/client/r0/account/3pid/add
|
||||
|
||||
```json
|
||||
{
|
||||
"sid": "bxyDHuJKsdkjMlTJ",
|
||||
"client_secret": "TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh"
|
||||
}
|
||||
```
|
||||
|
||||
401 User Interactive Authentication
|
||||
|
||||
```json
|
||||
{
|
||||
"session": "ppvvnozXCQZFaggUBlHJYPjA",
|
||||
"flows": [
|
||||
{
|
||||
"stages": [
|
||||
"m.login.password"
|
||||
]
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### User enters his password
|
||||
|
||||
POST https://homeserver.org/_matrix/client/r0/account/3pid/add
|
||||
|
||||
```json
|
||||
{
|
||||
"sid": "bxyDHuJKsdkjMlTJ",
|
||||
"client_secret": "TixzvOnw7nLEUdiQEmkHzkXKrY4HhiGh",
|
||||
"auth": {
|
||||
"session": "ppvvnozXCQZFaggUBlHJYPjA",
|
||||
"type": "m.login.password",
|
||||
"user": "@benoitx:matrix.org",
|
||||
"password": "weak_password"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### The link has not been clicked
|
||||
|
||||
400
|
||||
|
||||
```json
|
||||
{
|
||||
"errcode": "M_THREEPID_AUTH_FAILED",
|
||||
"error": "No validated 3pid session found"
|
||||
}
|
||||
```
|
||||
|
||||
#### Wrong password
|
||||
|
||||
401
|
||||
|
||||
```json
|
||||
{
|
||||
"session": "fXHOvoQsPMhEebVqTnIrzZJN",
|
||||
"flows": [
|
||||
{
|
||||
"stages": [
|
||||
"m.login.password"
|
||||
]
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
},
|
||||
"completed":[
|
||||
],
|
||||
"error": "Invalid password",
|
||||
"errcode": "M_FORBIDDEN"
|
||||
}
|
||||
```
|
||||
|
||||
#### The link has been clicked and the account password is correct
|
||||
|
||||
200
|
||||
|
||||
```json
|
||||
{}
|
||||
```
|
||||
|
||||
## Remove email
|
||||
|
||||
### User want to remove an email from his account
|
||||
|
||||
> POST https://homeserver.org/_matrix/client/r0/account/3pid/delete
|
||||
|
||||
```json
|
||||
{
|
||||
"medium": "email",
|
||||
"address": "alice@email-provider.org"
|
||||
}
|
||||
```
|
||||
|
||||
#### Email was not bound to an identity server
|
||||
|
||||
200
|
||||
|
||||
```json
|
||||
{
|
||||
"id_server_unbind_result": "no-support"
|
||||
}
|
||||
```
|
||||
|
||||
#### Email was bound to an identity server
|
||||
|
||||
200
|
||||
|
||||
```json
|
||||
{
|
||||
"id_server_unbind_result": "success"
|
||||
}
|
||||
```
|
||||
|
||||
## Add phone number
|
||||
|
||||
> POST https://homeserver.org/_matrix/client/r0/account/3pid/msisdn/requestToken
|
||||
|
||||
```json
|
||||
{
|
||||
"country": "FR",
|
||||
"phone_number": "611223344",
|
||||
"client_secret": "f1K29wFZBEr4RZYatu7xj8nEbXiVpr7J",
|
||||
"send_attempt": 1
|
||||
}
|
||||
```
|
||||
|
||||
Note that the phone number is sent without `+` and without the country code
|
||||
|
||||
#### The phone number is already added to an account
|
||||
|
||||
400
|
||||
|
||||
```json
|
||||
{
|
||||
"errcode": "M_THREEPID_IN_USE",
|
||||
"error": "MSISDN is already in use"
|
||||
}
|
||||
```
|
||||
|
||||
#### The phone number is free
|
||||
|
||||
Wording: "A text message has been sent to +33611223344. Please enter the verification code it contains."
|
||||
|
||||
200
|
||||
|
||||
```json
|
||||
{
|
||||
"msisdn": "33651547677",
|
||||
"intl_fmt": "+33 6 51 54 76 77",
|
||||
"success": true,
|
||||
"sid": "253299954",
|
||||
"submit_url": "https://homeserver.org/_matrix/client/unstable/add_threepid/msisdn/submit_token"
|
||||
}
|
||||
```
|
||||
|
||||
## User receive a text message
|
||||
|
||||
> Riot
|
||||
|
||||
> Your Riot validation code is 892541, please enter this into the app
|
||||
|
||||
### User enter the code to the app
|
||||
|
||||
#### Wrong code
|
||||
|
||||
> POST https://homeserver.org/_matrix/client/unstable/add_threepid/msisdn/submit_token
|
||||
|
||||
```json
|
||||
{
|
||||
"sid": "253299954",
|
||||
"client_secret": "f1K29wFZBEr4RZYatu7xj8nEbXiVpr7J",
|
||||
"token": "111111"
|
||||
}
|
||||
```
|
||||
|
||||
400
|
||||
|
||||
```json
|
||||
{
|
||||
"errcode": "M_UNKNOWN",
|
||||
"error": "Error contacting the identity server"
|
||||
}
|
||||
```
|
||||
|
||||
This is not an ideal, but the client will display a hint to check the entered code to the user.
|
||||
|
||||
#### Correct code
|
||||
|
||||
> POST https://homeserver.org/_matrix/client/unstable/add_threepid/msisdn/submit_token
|
||||
|
||||
```json
|
||||
{
|
||||
"sid": "253299954",
|
||||
"client_secret": "f1K29wFZBEr4RZYatu7xj8nEbXiVpr7J",
|
||||
"token": "892541"
|
||||
}
|
||||
```
|
||||
|
||||
200
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true
|
||||
}
|
||||
```
|
||||
|
||||
Then the app call `https://homeserver.org/_matrix/client/r0/account/3pid/add` as per adding an email and follow the same UIS flow
|
||||
|
||||
## Remove phone number
|
||||
|
||||
### User wants to remove a phone number from his account
|
||||
|
||||
This is the same request and response than to remove email, but with this body:
|
||||
|
||||
```json
|
||||
{
|
||||
"medium": "msisdn",
|
||||
"address": "33611223344"
|
||||
}
|
||||
```
|
||||
|
||||
Note that the phone number is provided without `+`, but with the country code.
|
@@ -14,7 +14,7 @@ Difference though (list not exhaustive):
|
||||
- Only API v2 is supported (see https://matrix.org/docs/spec/identity_service/latest)
|
||||
- Homeserver has to be up to date to support binding (Versions.isLoginAndRegistrationSupportedBySdk() has to return true)
|
||||
- The SDK managed the session and client secret when binding ThreePid. Those data are not exposed to the client.
|
||||
- The SDK supports incremental sendAttempt (this is not used by RiotX)
|
||||
- The SDK supports incremental sendAttempt (this is not used by Element)
|
||||
- The "Continue" button is now under the information, and not as the same place that the checkbox
|
||||
- The app can cancel a binding. Current data are erased from DB.
|
||||
- The API (IdentityService) is improved.
|
||||
@@ -22,7 +22,7 @@ Difference though (list not exhaustive):
|
||||
|
||||
Missing features (list not exhaustive):
|
||||
- Invite by 3Pid (will be in a dedicated PR)
|
||||
- Add email or phone to account (not P1, can be done on Riot-Web)
|
||||
- Add email or phone to account (not P1, can be done on Element-Web)
|
||||
- List email and phone of the account (could be done in a dedicated PR)
|
||||
- Search contact (not P1)
|
||||
- Logout from identity server when user sign out or deactivate his account.
|
||||
@@ -55,7 +55,7 @@ The list can be found here: https://matrix.org/blog/2019/09/27/privacy-improveme
|
||||
|
||||
- Default identity server URL, from Wellknown data is proposed to the user.
|
||||
- Identity server can be set
|
||||
- Identity server can be changed on another user's device, so when the change is detected (thanks to account data sync) RiotX should properly disconnect from a previous identity server (I think it was not the case in Riot-Android, where we keep the token forever)
|
||||
- Identity server can be changed on another user's device, so when the change is detected (thanks to account data sync) Element should properly disconnect from a previous identity server (I think it was not the case in Riot-Android, where we keep the token forever)
|
||||
- Registration to the identity server is managed with an openId token
|
||||
- Terms of service can be accepted when configuring the identity server.
|
||||
- Terms of service can be accepted after, if they change.
|
||||
|
@@ -59,6 +59,12 @@ It's recommended to run tests using an Android Emulator and not a real device. F
|
||||
|
||||
You can run all the tests in the `androidTest` folders.
|
||||
|
||||
It can be done using this command:
|
||||
|
||||
```bash
|
||||
./gradlew vector:connectedAndroidTest matrix-sdk-android:connectedAndroidTest
|
||||
```
|
||||
|
||||
## Stop Synapse
|
||||
|
||||
To stop Synapse, you can run the following commands:
|
||||
|
82
docs/jitsi.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Jitsi in Element Android
|
||||
|
||||
Native Jitsi support has been added to Element Android by the PR [#1914](https://github.com/vector-im/element-android/pull/1914). The description of the PR contains some documentation about the behaviour in each possible room configuration.
|
||||
|
||||
Also, ensure to have a look on [the documentation from Element Web](https://github.com/vector-im/element-web/blob/develop/docs/jitsi.md)
|
||||
|
||||
The official documentation about how to integrate the Jitsi SDK in an Android app is available here: https://jitsi.github.io/handbook/docs/dev-guide/dev-guide-android-sdk.
|
||||
|
||||
# Native Jitsi SDK
|
||||
|
||||
The Jitsi SDK is built by ourselves with the flag LIBRE_BUILD, to be able to be integrated on the F-Droid version of Element Android.
|
||||
|
||||
The generated maven repository is then host in the project https://github.com/vector-im/jitsi_libre_maven
|
||||
|
||||
## How to build the Jitsi Meet SDK
|
||||
|
||||
### Jitsi version
|
||||
|
||||
Update the script `./tools/jitsi/build_jisti_libs.sh` with the tag of the project `https://github.com/jitsi/jitsi-meet`.
|
||||
|
||||
Currently we are building the version with the tag `android-sdk-2.9.3`.
|
||||
|
||||
### Run the build script
|
||||
|
||||
At the root of the Element Android, run the following script:
|
||||
|
||||
```shell script
|
||||
./tools/jitsi/build_jisti_libs.sh
|
||||
```
|
||||
|
||||
It will build the Jitsi Meet Android library and put every generated files in the folder `/tmp/jitsi`
|
||||
|
||||
### Link with the new generated library
|
||||
|
||||
- Update the file `./build.gradle` to use the previously created local Maven repository. Currently we have this line:
|
||||
|
||||
```groovy
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-2.9.3"
|
||||
```
|
||||
|
||||
You can uncomment and update the line starting with `// url "file://...` and comment the line starting with `url`, to test the library using the locally generated Maven repository.
|
||||
|
||||
- Update the dependency of the WebRTC library in the file `./matrix-sdk-android/build.gradle`. Currently we have this line:
|
||||
|
||||
```groovy
|
||||
implementation('com.facebook.react:react-native-webrtc:1.84.0-jitsi-5112273@aar')
|
||||
```
|
||||
|
||||
- Update the dependency of the Jitsi Meet library in the file `./vector/build.gradle`. Currently we have this line:
|
||||
|
||||
```groovy
|
||||
implementation('org.jitsi.react:jitsi-meet-sdk:2.9.3') { transitive = true }
|
||||
```
|
||||
|
||||
- Perform a gradle sync and build the project
|
||||
- Perform test
|
||||
|
||||
### Sanity tests
|
||||
|
||||
In order to validate that the upgrade of the Jitsi and WebRTC dependency does not break anything, the following sanity tests have to be performed, using two devices:
|
||||
- Make 1-1 audio call (so using WebRTC)
|
||||
- Make 1-1 video call (so using WebRTC)
|
||||
- Create and join a conference call with audio only (so using Jitsi library). Leave the conference. Join it again.
|
||||
- Create and join a conference call with audio and video (so using Jitsi library) Leave the conference. Join it again.
|
||||
|
||||
### Export the build library
|
||||
|
||||
If all the tests are passed, you can export the generated Jitsi library to our Maven repository.
|
||||
|
||||
- Clone the project https://github.com/vector-im/jitsi_libre_maven.
|
||||
- Create a new folder with the version name.
|
||||
- Copy every generated files form `/tmp/jitsi` to the folder you have just created.
|
||||
- Commit and push the change on https://github.com/vector-im/jitsi_libre_maven.
|
||||
- Update the file `./build.gradle` to use the previously created Maven repository. Currently we have this line:
|
||||
|
||||
```groovy
|
||||
url "https://github.com/vector-im/jitsi_libre_maven/raw/master/android-sdk-2.9.3"
|
||||
```
|
||||
|
||||
- Build the project and perform the sanity tests again.
|
||||
|
||||
- Update the file `/CANGES.md` to notify about the library upgrade, and create a regular PR for project Element Android.
|
@@ -1,4 +1,4 @@
|
||||
This document aims to describe how RiotX android displays notifications to the end user. It also clarifies notifications and background settings in the app.
|
||||
This document aims to describe how Element android displays notifications to the end user. It also clarifies notifications and background settings in the app.
|
||||
|
||||
# Table of Contents
|
||||
1. [Prerequisites Knowledge](#prerequisites-knowledge)
|
||||
@@ -9,7 +9,7 @@ This document aims to describe how RiotX android displays notifications to the e
|
||||
* [How does the Home Server knows when to notify a client?](#how-does-the-home-server-knows-when-to-notify-a-client)
|
||||
* [Push vs privacy, and mitigation](#push-vs-privacy-and-mitigation)
|
||||
* [Background processing limitations](#background-processing-limitations)
|
||||
2. [RiotX Notification implementations](#riotx-notification-implementations)
|
||||
2. [Element Notification implementations](#element-notification-implementations)
|
||||
* [Requirements](#requirements)
|
||||
* [Foreground sync mode (Gplay & F-Droid)](#foreground-sync-mode-gplay-f-droid)
|
||||
* [Push (FCM) received in background](#push-fcm-received-in-background)
|
||||
@@ -50,7 +50,7 @@ By default, this is 0, so the server will return immediately even if the respons
|
||||
|
||||
**delay** is a client preference. When the server responds to a sync request, the client waits for `delay`before calling a new sync.
|
||||
|
||||
When the RiotX Android app is open (i.e in foreground state), the default timeout is 30 seconds, and delay is 0.
|
||||
When the Element Android app is open (i.e in foreground state), the default timeout is 30 seconds, and delay is 0.
|
||||
|
||||
## How does a mobile app receives push notification
|
||||
|
||||
@@ -86,7 +86,7 @@ This need some disambiguation, because it is the source of common confusion:
|
||||
In order to send a push to a mobile, App developers need to have a server that will use the FCM APIs, and these APIs requires authentication!
|
||||
This server is called a **Push Gateway** in the matrix world
|
||||
|
||||
That means that RiotX Android, a matrix client created by New Vector, is using a **Push Gateway** with the needed credentials (FCM API secret Key) in order to send push to the New Vector client.
|
||||
That means that Element Android, a matrix client created by New Vector, is using a **Push Gateway** with the needed credentials (FCM API secret Key) in order to send push to the New Vector client.
|
||||
|
||||
If you create your own matrix client, you will also need to deploy an instance of a **Push Gateway** with the credentials needed to use FCM for your app.
|
||||
|
||||
@@ -132,7 +132,7 @@ A Home Server can be configured with default rules (for Direct messages, group m
|
||||
|
||||
There are different kind of push rules, it can be per room (each new message on this room should be notified), it can also define a pattern that a message should match (when you are mentioned, or key word based).
|
||||
|
||||
Notifications have 2 'levels' (`highlighted = true/false sound = default/custom`). In RiotX these notifications level are reflected as Noisy/Silent.
|
||||
Notifications have 2 'levels' (`highlighted = true/false sound = default/custom`). In Element these notifications level are reflected as Noisy/Silent.
|
||||
|
||||
**What about encrypted messages?**
|
||||
|
||||
@@ -158,7 +158,7 @@ In a nutshell, apps can't do much in background now.
|
||||
|
||||
If the devices is not plugged and stays IDLE for a certain amount of time, radio (mobile connectivity) and CPU can/will be turned off.
|
||||
|
||||
For an application like RiotX, where users can receive important information at anytime, the best option is to rely on a push system (Google's Firebase Message a.k.a FCM). FCM high priority push can wake up the device and whitelist an application to perform background task (for a limited but unspecified amount of time).
|
||||
For an application like Element, where users can receive important information at anytime, the best option is to rely on a push system (Google's Firebase Message a.k.a FCM). FCM high priority push can wake up the device and whitelist an application to perform background task (for a limited but unspecified amount of time).
|
||||
|
||||
Notice that this is still evolving, and in future versions application that has been 'background restricted' by users won't be able to wake up even when a high priority push is received. Also high priority notifications could be rate limited (not defined anywhere)
|
||||
|
||||
@@ -167,41 +167,41 @@ The documentation on this subject is vague, and as per our experiments not alway
|
||||
|
||||
It is getting more and more complex to have reliable notifications when FCM is not used.
|
||||
|
||||
# RiotX Notification implementations
|
||||
# Element Notification implementations
|
||||
|
||||
## Requirements
|
||||
|
||||
RiotX Android must work with and without FCM.
|
||||
* The RiotX android app published on F-Droid do not rely on FCM (all related dependencies are not present)
|
||||
* The RiotX android app published on google play rely on FCM, with a fallback mode when FCM registration has failed (e.g outdated or missing Google Play Services)
|
||||
Element Android must work with and without FCM.
|
||||
* The Element android app published on F-Droid do not rely on FCM (all related dependencies are not present)
|
||||
* The Element android app published on google play rely on FCM, with a fallback mode when FCM registration has failed (e.g outdated or missing Google Play Services)
|
||||
|
||||
## Foreground sync mode (Gplay & F-Droid)
|
||||
|
||||
When in foreground, RiotX performs sync continuously with a timeout value set to 10 seconds (see HttpPooling).
|
||||
When in foreground, Element performs sync continuously with a timeout value set to 10 seconds (see HttpPooling).
|
||||
|
||||
As this mode does not need to live beyond the scope of the application, and as per Google recommendation, RiotX uses the internal app resources (Thread and Timers) to perform the syncs.
|
||||
As this mode does not need to live beyond the scope of the application, and as per Google recommendation, Element uses the internal app resources (Thread and Timers) to perform the syncs.
|
||||
|
||||
This mode is turned on when the app enters foreground, and off when enters background.
|
||||
|
||||
In background, and depending on wether push is available or not, RiotX will use different methods to perform the syncs (Workers / Alarms / Service)
|
||||
In background, and depending on wether push is available or not, Element will use different methods to perform the syncs (Workers / Alarms / Service)
|
||||
|
||||
## Push (FCM) received in background
|
||||
|
||||
In order to enable Push, RiotX must first get a push token from the firebase SDK, then register a pusher with this token on the HomeServer.
|
||||
In order to enable Push, Element must first get a push token from the firebase SDK, then register a pusher with this token on the HomeServer.
|
||||
|
||||
When a message should be notified to a user, the user's homeserver notifies the registered `push gateway` for RiotX, that is [sygnal](https://github.com/matrix-org/sygnal) _- The reference implementation for push gateways -_ hosted by matrix.org.
|
||||
When a message should be notified to a user, the user's homeserver notifies the registered `push gateway` for Element, that is [sygnal](https://github.com/matrix-org/sygnal) _- The reference implementation for push gateways -_ hosted by matrix.org.
|
||||
|
||||
This sygnal instance is configured with the required FCM API authentication token, and will then use the FCM API in order to notify the user's device running riotX.
|
||||
This sygnal instance is configured with the required FCM API authentication token, and will then use the FCM API in order to notify the user's device running Element.
|
||||
|
||||
```
|
||||
Homeserver ----> Sygnal (configured for RiotX) ----> FCM ----> RiotX
|
||||
Homeserver ----> Sygnal (configured for Element) ----> FCM ----> Element
|
||||
```
|
||||
|
||||
The push gateway is configured to only send `(eventId,roomId)` in the push payload (for better [privacy](#push-vs-privacy-and-mitigation)).
|
||||
|
||||
RiotX needs then to synchronise with the user's HomeServer, in order to resolve the event and create a notification.
|
||||
Element needs then to synchronise with the user's HomeServer, in order to resolve the event and create a notification.
|
||||
|
||||
As per [Google recommendation](https://android-developers.googleblog.com/2018/09/notifying-your-users-with-fcm.html), RiotX will then use the WorkManager API in order to trigger a background sync.
|
||||
As per [Google recommendation](https://android-developers.googleblog.com/2018/09/notifying-your-users-with-fcm.html), Element will then use the WorkManager API in order to trigger a background sync.
|
||||
|
||||
**Google recommendations:**
|
||||
> We recommend using FCM messages in combination with the WorkManager 1 or JobScheduler API
|
||||
@@ -209,7 +209,7 @@ As per [Google recommendation](https://android-developers.googleblog.com/2018/09
|
||||
> Avoid background services. One common pitfall is using a background service to fetch data in the FCM message handler, since background service will be stopped by the system per recent changes to Google Play Policy
|
||||
|
||||
```
|
||||
Homeserver ----> Sygnal ----> FCM ----> RiotX
|
||||
Homeserver ----> Sygnal ----> FCM ----> Element
|
||||
(Sync) ----> Homeserver
|
||||
<----
|
||||
Display notification
|
||||
@@ -217,24 +217,24 @@ Homeserver ----> Sygnal ----> FCM ----> RiotX
|
||||
|
||||
**Possible outcomes**
|
||||
|
||||
Upon reception of the FCM push, RiotX will perform a sync call to the Home Server, during this process it is possible that:
|
||||
Upon reception of the FCM push, Element will perform a sync call to the Home Server, during this process it is possible that:
|
||||
* Happy path, the sync is performed, the message resolved and displayed in the notification drawer
|
||||
* The notified message is not in the sync. Can happen if a lot of things did happen since the push (`gappy sync`)
|
||||
* The sync generates additional notifications (e.g an encrypted message where the user is mentioned detected locally)
|
||||
* The sync takes too long and the process is killed before completion, or network is not reliable and the sync fails.
|
||||
|
||||
RiotX implements several strategies in these cases (TODO document)
|
||||
Element implements several strategies in these cases (TODO document)
|
||||
|
||||
## FCM Fallback mode
|
||||
|
||||
It is possible that RiotX is not able to get a FCM push token.
|
||||
It is possible that Element is not able to get a FCM push token.
|
||||
Common errors (amoung several others) that can cause that:
|
||||
* Google Play Services is outdated
|
||||
* Google Play Service fails in someways with FCM servers (infamous `SERVICE_NOT_AVAILABLE`)
|
||||
|
||||
If RiotX is able to detect one of this cases, it will notifies it to the users and when possible help him fix it via a dedicated troubleshoot screen.
|
||||
If Element is able to detect one of this cases, it will notifies it to the users and when possible help him fix it via a dedicated troubleshoot screen.
|
||||
|
||||
Meanwhile, in order to offer a minimal service, and as per Google's recommendation for background activities, RiotX will launch periodic background sync in order to stays in sync with servers.
|
||||
Meanwhile, in order to offer a minimal service, and as per Google's recommendation for background activities, Element will launch periodic background sync in order to stays in sync with servers.
|
||||
|
||||
The fallback mode is impacted by all the battery life saving mechanism implemented by android. Meaning that if the app is not used for a certain amount of time (`App-Standby`), or the device stays still and unplugged (`Light Doze`) , the sync will become less frequent.
|
||||
|
||||
@@ -248,7 +248,7 @@ The fallback mode is supposed to be a temporary state waiting for the user to fi
|
||||
|
||||
## F-Droid background Mode
|
||||
|
||||
The F-Droid RiotX flavor has no dependencies to FCM, therefore cannot relies on Push.
|
||||
The F-Droid Element flavor has no dependencies to FCM, therefore cannot relies on Push.
|
||||
|
||||
Also Google's recommended background processing method cannot be applied. This is because all of these methods are affected by IDLE modes, and will result on the user not being notified at all when the app is in a Doze mode (only in maintenance windows that could happens only after hours).
|
||||
|
||||
@@ -262,7 +262,7 @@ F-Droid version will schedule alarms that will then trigger a Broadcast Receiver
|
||||
|
||||
Depending on the system status (or device make), it is still possible that the app is not given enough time to launch the service, or that the radio is still turned off thus preventing the sync to success (that's why Alarms are not recommended for network related tasks).
|
||||
|
||||
That is why on RiotX F-Droid, the broadcast receiver will acquire a temporary WAKE_LOCK for several seconds (thus securing cpu/network), and launch the service in foreground. The service performs the sync.
|
||||
That is why on Element F-Droid, the broadcast receiver will acquire a temporary WAKE_LOCK for several seconds (thus securing cpu/network), and launch the service in foreground. The service performs the sync.
|
||||
|
||||
Note that foreground services require to put a notification informing the user that the app is doing something even if not launched).
|
||||
|
||||
|
@@ -2,13 +2,15 @@
|
||||
|
||||
This document describes the flow of signin to a homeserver, and also the flow when user want to reset his password. Examples come from the `matrix.org` homeserver.
|
||||
|
||||
## Sign up flows
|
||||
## Sign in flows
|
||||
|
||||
### Get the flow
|
||||
|
||||
Client request the sign-in flows, once the homeserver is chosen by the user and its url is known (in the example it's `https://matrix.org`)
|
||||
|
||||
> curl -X GET 'https://matrix.org/_matrix/client/r0/login'
|
||||
```shell script
|
||||
curl -X GET 'https://matrix.org/_matrix/client/r0/login'
|
||||
```
|
||||
|
||||
200
|
||||
|
||||
@@ -26,7 +28,9 @@ Client request the sign-in flows, once the homeserver is chosen by the user and
|
||||
|
||||
The user is able to connect using `m.login.password`
|
||||
|
||||
> curl -X POST --data $'{"identifier":{"type":"m.id.user","user":"alice"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
|
||||
```shell script
|
||||
curl -X POST --data $'{"identifier":{"type":"m.id.user","user":"alice"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -58,7 +62,7 @@ We get credential (200)
|
||||
```json
|
||||
{
|
||||
"user_id": "@alice:matrix.org",
|
||||
"access_token": "MDAxOGxvY2F0aW9uIG1hdHREDACTEDb2l0MDgxNjptYXRyaXgub3JnCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lkIG5vbmNlID0gfnYrSypfdTtkNXIuNWx1KgowMDJmc2lnbmF0dXJlIOsh1XqeAkXexh4qcofl_aR4kHJoSOWYGOhE7-ubX-DZCg",
|
||||
"access_token": "MDAxOGxvY2F0aW9uIG1hdHREDACTEDb2l0MDgxNjptYXRyaXgub3JnCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lr",
|
||||
"home_server": "matrix.org",
|
||||
"device_id": "GTVREDALBF",
|
||||
"well_known": {
|
||||
@@ -73,14 +77,16 @@ We get credential (200)
|
||||
|
||||
If the user has associated an email with its account, he can signin using the email.
|
||||
|
||||
> curl -X POST --data $'{"identifier":{"type":"m.id.thirdparty","medium":"email","address":"alice@yopmail.com"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
|
||||
```shell script
|
||||
curl -X POST --data $'{"identifier":{"type":"m.id.thirdparty","medium":"email","address":"alice@email-provider.org"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"identifier": {
|
||||
"type": "m.id.thirdparty",
|
||||
"medium": "email",
|
||||
"address": "alice@yopmail.com"
|
||||
"address": "alice@email-provider.org"
|
||||
},
|
||||
"password": "weak_password",
|
||||
"type": "m.login.password",
|
||||
@@ -117,7 +123,7 @@ We get the credentials (200)
|
||||
```json
|
||||
{
|
||||
"user_id": "@alice:matrix.org",
|
||||
"access_token": "MDAxOGxvY2F0aW9uIG1hdHJpeC5vcmREDACTEDZXJfaWQgPSBAYmVub2l0MDgxNjptYXRyaXgub3JnCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lkIG5vbmNlID0gNjtDY0MwRlNPSFFoOC5wOgowMDJmc2lnbmF0dXJlIGiTRm1mYLLxQywxOh3qzQVT8HoEorSokEP2u-bAwtnYCg",
|
||||
"access_token": "MDAxOGxvY2F0aW9uIG1hdHJpeC5vcmREDACTEDZXJfaWQgPSBAYmVub2l0MDgxNjptYXRyaXgub3Jnfrfdegfszsefddvf",
|
||||
"home_server": "matrix.org",
|
||||
"device_id": "WBSREDASND",
|
||||
"well_known": {
|
||||
@@ -132,11 +138,13 @@ It's worth noting that the response from the homeserver contains the userId of A
|
||||
|
||||
### Login with Msisdn
|
||||
|
||||
Not supported yet in RiotX
|
||||
Not supported yet in Element
|
||||
|
||||
### Login with SSO
|
||||
|
||||
> curl -X GET 'https://homeserver.with.sso/_matrix/client/r0/login'
|
||||
```shell script
|
||||
curl -X GET 'https://homeserver.with.sso/_matrix/client/r0/login'
|
||||
```
|
||||
|
||||
200
|
||||
|
||||
@@ -145,12 +153,61 @@ Not supported yet in RiotX
|
||||
"flows": [
|
||||
{
|
||||
"type": "m.login.sso"
|
||||
},
|
||||
{
|
||||
"type": "m.login.token"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
In this case, the user can click on "Sign in with SSO" and the web screen will be displayed on the page `https://homeserver.with.sso/_matrix/static/client/login/` and the credentials will be passed back to the native code through the JS bridge
|
||||
In this case, the user can click on "Sign in with SSO" and the native web browser, or a ChromeCustomTab if the device supports it, will be launched on the page
|
||||
|
||||
> https://homeserver.with.sso/_matrix/client/r0/login/sso/redirect?redirectUrl=element%3A%2F%element
|
||||
|
||||
The parameter `redirectUrl` is set to `element://connect`.
|
||||
|
||||
ChromeCustomTabs are an intermediate way to display a WebPage, between a WebView and using the external browser. More info can be found [here](https://developer.chrome.com/multidevice/android/customtabs)
|
||||
|
||||
The browser will then take care of the SSO login, which may include creating a third party account, entering an email, settings a display name, or any other possibilities.
|
||||
|
||||
During the process, user may be asked to validate an email by clicking on a link it contains. The link has to be opened in the browser which initiates the authentication. This is why we cannot use WebView anymore.
|
||||
|
||||
Once the process is finished, the web page will call the `redirectUrl` with an extra parameter `loginToken`
|
||||
|
||||
> element://connect?loginToken=MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy
|
||||
|
||||
This navigation is intercepted by Element by the `LoginActivity`, which will then ask the homeserver to convert this `loginToken` to an access token
|
||||
|
||||
```shell script
|
||||
curl -X POST --data $'{"type":"m.login.token","token":"MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy"}' 'https://homeserver.with.sso/_matrix/client/r0/login'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "m.login.token",
|
||||
"token": "MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy"
|
||||
}
|
||||
```
|
||||
|
||||
We get the credentials (200)
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": "@alice:homeserver.with.sso",
|
||||
"access_token": "MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVyIGtleQowMDEwY2lkIGdlbiA9IDEKMDAyY2NpZCB1c2",
|
||||
"home_server": "homeserver.with.sso",
|
||||
"device_id": "DETBTVAHCH",
|
||||
"well_known": {
|
||||
"m.homeserver": {
|
||||
"base_url": "https:\/\/homeserver.with.sso\/"
|
||||
},
|
||||
"m.identity_server": {
|
||||
"base_url": "https:\/\/vector.im"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Reset password
|
||||
|
||||
@@ -167,7 +224,9 @@ We display a warning regarding e2e.
|
||||
|
||||
At the first step, we do not send the password, only the email and a client secret, generated by the application
|
||||
|
||||
> curl -X POST --data $'{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","send_attempt":0,"email":"user@domain.com"}' 'https://matrix.org/_matrix/client/r0/account/password/email/requestToken'
|
||||
```shell script
|
||||
curl -X POST --data $'{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","send_attempt":0,"email":"user@domain.com"}' 'https://matrix.org/_matrix/client/r0/account/password/email/requestToken'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -204,7 +263,9 @@ During this step, the new password is sent to the homeserver.
|
||||
|
||||
If the user confirms before the link is clicked, we get an error:
|
||||
|
||||
> curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -238,7 +299,9 @@ It contains the client secret, a token and the sid
|
||||
|
||||
When the user click the link, if validate his ownership and the new password can now be ent by the application (on user demand):
|
||||
|
||||
> curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
|
@@ -10,7 +10,9 @@ This document describes the flow of registration to a homeserver. Examples come
|
||||
|
||||
Client request the sign-up flows, once the homeserver is chosen by the user and its url is known (in the example it's `https://matrix.org`)
|
||||
|
||||
> curl -X POST --data $'{}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```shell script
|
||||
curl -X POST --data $'{}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -70,7 +72,9 @@ If the registration is not possible, we get a 403
|
||||
|
||||
The app is displaying a form to enter username and password.
|
||||
|
||||
> curl -X POST --data $'{"initial_device_display_name":"Mobile device","username":"alice","password": "weak_password"}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```shell script
|
||||
curl -X POST --data $'{"initial_device_display_name":"Mobile device","username":"alice","password": "weak_password"}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -133,9 +137,11 @@ We get a 400:
|
||||
|
||||
### Step 2: entering email
|
||||
|
||||
User is proposed to enter an email. We skip this step.
|
||||
User is proposed to enter an email. User skips this step.
|
||||
|
||||
> curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.dummy"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.dummy"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -189,16 +195,18 @@ User is proposed to enter an email. We skip this step.
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2 bis: we enter an email
|
||||
### Step 2 bis: user enters an email
|
||||
|
||||
We request a token to the homeserver. The `client_secret` is generated by the application
|
||||
|
||||
> curl -X POST --data $'{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","email":"alice@yopmail.com","send_attempt":0}' 'https://matrix.org/_matrix/client/r0/register/email/requestToken'
|
||||
```shell script
|
||||
curl -X POST --data $'{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","email":"alice@email-provider.org","send_attempt":0}' 'https://matrix.org/_matrix/client/r0/register/email/requestToken'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"client_secret": "53e679ea-oRED-ACTED-92b8-3012c49c6cfa",
|
||||
"email": "alice@yopmail.com",
|
||||
"email": "alice@email-provider.org",
|
||||
"send_attempt": 0
|
||||
}
|
||||
```
|
||||
@@ -213,7 +221,9 @@ We request a token to the homeserver. The `client_secret` is generated by the ap
|
||||
|
||||
And
|
||||
|
||||
> curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -239,7 +249,9 @@ We get 401 since the email is not validated yet:
|
||||
|
||||
The app is now polling on
|
||||
|
||||
> curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -254,7 +266,7 @@ The app is now polling on
|
||||
}
|
||||
```
|
||||
|
||||
We click on the link received by email `https://matrix.org/_matrix/client/unstable/registration/email/submit_token?token=vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ&client_secret=53e679ea-oRED-ACTED-92b8-3012c49c6cfa&sid=qlBCREDACTEDEtgxD` which contains:
|
||||
User clicks on the link received by email `https://matrix.org/_matrix/client/unstable/registration/email/submit_token?token=vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ&client_secret=53e679ea-oRED-ACTED-92b8-3012c49c6cfa&sid=qlBCREDACTEDEtgxD` which contains:
|
||||
- A `token` vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ
|
||||
- The `client_secret`: 53e679ea-oRED-ACTED-92b8-3012c49c6cfa
|
||||
- A `sid`: qlBCREDACTEDEtgxD
|
||||
@@ -306,7 +318,9 @@ Once the link is clicked, the registration request (polling) returns a 401 with
|
||||
|
||||
User is proposed to accept T&C and he accepts them
|
||||
|
||||
> curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.terms"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.terms"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -365,7 +379,9 @@ User is proposed to accept T&C and he accepts them
|
||||
|
||||
User is proposed to prove he is not a robot and he does it:
|
||||
|
||||
> curl -X POST --data $'{"auth":{"response":"03AOLTBLSiGS9GhFDpAMblJ2nlXOmHXqAYJ5OvHCPUjiVLBef3k9snOYI_BDC32-t4D2jv-tpvkaiEI_uloobFd9RUTPpJ7con2hMddbKjSCYqXqcUQFhzhbcX6kw8uBnh2sbwBe80_ihrHGXEoACXQkL0ki1Q0uEtOeW20YBRjbNABsZPpLNZhGIWC0QVXnQ4FouAtZrl3gOAiyM-oG3cgP6M9pcANIAC_7T2P2amAHbtsTlSR9CsazNyS-rtDR9b5MywdtnWN9Aw8fTJb8cXQk_j7nvugMxzofPjSOrPKcr8h5OqPlpUCyxxnFtag6cuaPSUwh43D2L0E-ZX7djzaY2Yh_U2n6HegFNPOQ22CJmfrKwDlodmAfMPvAXyq77n3HpoREDACTEDo3830RHF4BfkGXUaZjctgg-A1mvC17hmQmQpkG7IhDqyw0onU-0vF_-ehCjq_CcQEDpS_O3uiHJaG5xGf-0rhLm57v_wA3deugbsZuO4uTuxZZycN_mKxZ97jlDVBetl9hc_5REPbhcT1w3uzTCSx7Q","session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.recaptcha"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"response":"03AOLTBLSiGS9GhFDpAMblJ2nlXOmHXqAYJ5OvHCPUjiVLBef3k9snOYI_BDC32-t4D2jv-tpvkaiEI_uloobFd9RUTPpJ7con2hMddbKjSCYqXqcUQFhzhbcX6kw8uBnh2sbwBe80_ihrHGXEoACXQkL0ki1Q0uEtOeW20YBRjbNABsZPpLNZhGIWC0QVXnQ4FouAtZrl3gOAiyM-oG3cgP6M9pcANIAC_7T2P2amAHbtsTlSR9CsazNyS-rtDR9b5MywdtnWN9Aw8fTJb8cXQk_j7nvugMxzofPjSOrPKcr8h5OqPlpUCyxxnFtag6cuaPSUwh43D2L0E-ZX7djzaY2Yh_U2n6HegFNPOQ22CJmfrKwDlodmAfMPvAXyq77n3HpoREDACTEDo3830RHF4BfkGXUaZjctgg-A1mvC17hmQmQpkG7IhDqyw0onU-0vF_-ehCjq_CcQEDpS_O3uiHJaG5xGf-0rhLm57v_wA3deugbsZuO4uTuxZZycN_mKxZ97jlDVBetl9hc_5REPbhcT1w3uzTCSx7Q","session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.recaptcha"}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -396,9 +412,11 @@ Some homeservers may require the user to enter MSISDN.
|
||||
|
||||
On matrix.org, it's not required, and not even optional, but it's still possible for the app to add a MSISDN during the registration.
|
||||
|
||||
The user enter a phone number and select a country, the `client_secret` is generated by the application
|
||||
The user enters a phone number and selects a country, the `client_secret` is generated by the application
|
||||
|
||||
> curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","send_attempt":1,"country":"FR","phone_number":"+33611223344"}' 'https://matrix.org/_matrix/client/r0/register/msisdn/requestToken'
|
||||
```shell script
|
||||
curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","send_attempt":1,"country":"FR","phone_number":"+33611223344"}' 'https://matrix.org/_matrix/client/r0/register/msisdn/requestToken'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -430,10 +448,11 @@ If it is not the case, the homeserver send the SMS and returns some data, especi
|
||||
}
|
||||
```
|
||||
|
||||
When you execute the register request, with the received `sid`, you get an error since the MSISDN is not validated yet:
|
||||
|
||||
> curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
When we execute the register request, with the received `sid`, we get an error since the MSISDN is not validated yet:
|
||||
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
"auth": {
|
||||
@@ -492,7 +511,9 @@ There is an issue on Synapse, which return a 401, it sends too much data along w
|
||||
|
||||
The user receive the SMS, he can enter the SMS code in the app, which is sent using the "submit_url" received ie the response of the `requestToken` request:
|
||||
|
||||
> curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798","token":"123456"}' 'https://matrix.org/_matrix/client/unstable/add_threepid/msisdn/submit_token'
|
||||
```shell script
|
||||
curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798","token":"123456"}' 'https://matrix.org/_matrix/client/unstable/add_threepid/msisdn/submit_token'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -520,7 +541,9 @@ And if the code is correct we get a 200 with:
|
||||
|
||||
We can now execute the registration request, to the homeserver
|
||||
|
||||
> curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```shell script
|
||||
curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -535,7 +558,7 @@ We can now execute the registration request, to the homeserver
|
||||
}
|
||||
```
|
||||
|
||||
Now the homeserver consider that the `m.login.msisdn` step is completed (401):
|
||||
Now the homeserver considers that the `m.login.msisdn` step is completed (401):
|
||||
|
||||
```json
|
||||
{
|
||||
|
106
docs/ui-tests.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Automate user interface tests
|
||||
|
||||
Element Android ensures that some fundamental flows are properly working by running automated user interface tests.
|
||||
Ui tests are using the android [Espresso](https://developer.android.com/training/testing/espresso) library.
|
||||
|
||||
Tests can be run on a real device, or on a virtual device (such as the emulator in Android Studio).
|
||||
|
||||
Currently the test are covering a small set of application flows:
|
||||
- Registration
|
||||
- Self verification via emoji
|
||||
- Self verification via passphrase
|
||||
|
||||
## Prerequisites:
|
||||
|
||||
Out of the box, the tests use one of the homeservers (located at http://localhost:8080) of the "Demo Federation of Homeservers" (https://github.com/matrix-org/synapse#running-a-demo-federation-of-synapses).
|
||||
|
||||
You first need to follow instructions to set up Synapse in development mode at https://github.com/matrix-org/synapse#synapse-development. If you have already installed all dependencies, the steps are:
|
||||
|
||||
```shell script
|
||||
$ git clone https://github.com/matrix-org/synapse.git
|
||||
$ cd synapse
|
||||
$ virtualenv -p python3 env
|
||||
$ source env/bin/activate
|
||||
(env) $ python -m pip install --no-use-pep517 -e .
|
||||
```
|
||||
|
||||
Every time you want to launch these test homeservers, type:
|
||||
|
||||
```shell script
|
||||
$ source env/bin/activate
|
||||
(env) $ demo/start.sh --no-rate-limit
|
||||
```
|
||||
|
||||
**Emulator/Device set up**
|
||||
|
||||
When running the test via android studio on a device, you have to disable system animations in order for the test to work properly.
|
||||
|
||||
First, ensure developer mode is enabled:
|
||||
|
||||
- To enable developer options, tap the **Build Number** option 7 times. You can find this option in one of the following locations, depending on your Android version:
|
||||
|
||||
- Android 9 (API level 28) and higher: **Settings > About Phone > Build Number**
|
||||
- Android 8.0.0 (API level 26) and Android 8.1.0 (API level 26): **Settings > System > About Phone > Build Number**
|
||||
- Android 7.1 (API level 25) and lower: **Settings > About Phone > Build Number**
|
||||
|
||||
On your device, under **Settings > Developer options**, disable the following 3 settings:
|
||||
|
||||
- Window animation scale
|
||||
- Transition animation scale
|
||||
- Animator duration scale
|
||||
|
||||
## Run the tests
|
||||
|
||||
Once Synapse is running, and an emulator is running, you can run the UI tests.
|
||||
|
||||
### From the source code
|
||||
|
||||
Click on the green arrow in front of each test. Clicking on the arrow in front of the test class, or from the package directory does not always work (Tests not found issue).
|
||||
|
||||
### From command line
|
||||
|
||||
````shell script
|
||||
./gradlew vector:connectedGplayDebugAndroidTest
|
||||
````
|
||||
|
||||
To run all the tests from the `vector` module.
|
||||
|
||||
In case of trouble, you can try to uninstall the previous installed test APK first with this command:
|
||||
|
||||
```shell script
|
||||
adb uninstall im.vector.app.debug.test
|
||||
```
|
||||
## Recipes
|
||||
|
||||
We added some specific Espresso IdlingResources, and other utilities for matrix related tests
|
||||
|
||||
### Wait for initial sync
|
||||
|
||||
```kotlin
|
||||
// Wait for initial sync and check room list is there
|
||||
withIdlingResource(initialSyncIdlingResource(uiSession)) {
|
||||
onView(withId(R.id.roomListContainer))
|
||||
.check(matches(isDisplayed()))
|
||||
}
|
||||
```
|
||||
|
||||
### Accessing current activity
|
||||
|
||||
```kotlin
|
||||
val activity = EspressoHelper.getCurrentActivity()!!
|
||||
val uiSession = (activity as HomeActivity).activeSessionHolder.getActiveSession()
|
||||
```
|
||||
|
||||
### Interact with other session
|
||||
|
||||
It's possible to create a session via the SDK, and then use this session to interact with the one that the emulator is using (to check verifications for example)
|
||||
|
||||
```kotlin
|
||||
@Before
|
||||
fun initAccount() {
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
val matrix = Matrix.getInstance(context)
|
||||
val userName = "foobar_${System.currentTimeMillis()}"
|
||||
existingSession = createAccountAndSync(matrix, userName, password, true)
|
||||
}
|
||||
```
|
425
docs/voip_signaling.md
Normal file
@@ -0,0 +1,425 @@
|
||||
Useful links:
|
||||
- https://codelabs.developers.google.com/codelabs/webrtc-web/#0
|
||||
- http://webrtc.github.io/webrtc-org/native-code/android/
|
||||
|
||||
|
||||
╔════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║A] Placing a call offer ║
|
||||
║ ║
|
||||
╚════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
|
||||
┌───────────────┐
|
||||
│ Matrix │
|
||||
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
||||
│
|
||||
│
|
||||
│
|
||||
┌─────────────────┐ │ ┌───────────────────────────┐ ┌─────────────────┐
|
||||
│ Caller │ │ Signaling Room │ │ │ Callee │
|
||||
└─────────────────┘ │ ├───────────────────────────┤ └─────────────────┘
|
||||
┌────┐ │ │ │
|
||||
│ 3 │ │ │ ┌────────────────────┐ │
|
||||
┌─────────────────┐──────┴────┴──────────────────────────┼─▶│ m.call.invite │ │ │ ┌─────────────────┐
|
||||
│ │ │ │ │ mx event │ │ │ │
|
||||
│ │ │ └────────────────────┘ │ │ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ Element │ │ │ │ │ Element │
|
||||
┌──│ App │ │ │ │ │ App │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ └─────────────────┘ │ │ │ └─────────────────┘
|
||||
┌────┤ ▲ │ │ │
|
||||
│ 1 │ ├────┐ │ └───────────────────────────┘
|
||||
└────┤ │ 2 │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
|
||||
│ ┌──┴────┴─────────┐ ┌─────────────────┐
|
||||
│ │ │ │ │
|
||||
│ │ │ │ │
|
||||
│ │ WebRtc │ │ WebRtc │
|
||||
└─▶│ │ │ │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
┌────┐
|
||||
│ 1 │ The Caller app get access to system resources (camera, mic), eventually stun/turn servers, define some
|
||||
└────┘ constrains (video quality, format) and pass it to WebRtc in order to create a Peer Call offer
|
||||
|
||||
┌────┐
|
||||
│ 2 │ The WebRtc layer creates a call Offer (sdp) that needs to be sent to callee
|
||||
└────┘
|
||||
|
||||
┌────┐ The app layer, takes the webrtc offer, encapsulate it in a matrix event adds a callId and send it to the other
|
||||
│ 3 │ user via the room
|
||||
└────┘
|
||||
┌──────────────┐
|
||||
│ mx event │
|
||||
├──────────────┴────────┐
|
||||
│ type: m.call.invite │
|
||||
│ + callId │
|
||||
│ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ webrtc sdp │ │
|
||||
│ └──────────────────┘ │
|
||||
└───────────────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╔════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║B] Sending connection establishment info ║
|
||||
║ ║
|
||||
╚════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
|
||||
┌───────────────┐
|
||||
│ Matrix │
|
||||
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
||||
│
|
||||
│
|
||||
│
|
||||
┌─────────────────┐ │ ┌───────────────────────────┐ ┌─────────────────┐
|
||||
│ Caller │ │ Signaling Room │ │ │ Callee │
|
||||
└─────────────────┘ │ ├───────────────────────────┤ └─────────────────┘
|
||||
│ ┌────────────────────┐ │ │
|
||||
│ │ │ m.call.invite │ │
|
||||
┌─────────────────┐ │ │ mx event │ │ │ ┌─────────────────┐
|
||||
│ │ ┌────┐ │ │ └────────────────────┘ │ │ │
|
||||
│ │ │ 3 │ │ ┌────────────────────┐ │ │ │ │
|
||||
│ │──────┴────┴───────┼──────────────────┼─▶│ m.call.candidates │ │ │ │
|
||||
│ Element │ │ │ mx event │ │ │ │ Element │
|
||||
│ App │ │ │ └────────────────────┘ │ │ App │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ │ │ │ │ │
|
||||
└─────────────────┘ │ │ │ └─────────────────┘
|
||||
▲ │ │ │
|
||||
├────┐ │ └───────────────────────────┘
|
||||
│ 2 │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
|
||||
┌───────┴────┴────┐ ┌─────────────────┐
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
│ WebRtc │ ┌───────────────┐ │ WebRtc │
|
||||
│ │ │ Stun / Turn │ │ │
|
||||
│ │ ├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │
|
||||
│ │ │ │ │
|
||||
└─────────────────┘ │ └─────────────────┘
|
||||
▲ │
|
||||
│ │
|
||||
└──────────┬────┬───────────▶ │
|
||||
┌───────────────┐ │ 1 │ │
|
||||
│ │ └────┘ │
|
||||
│ Network Stack │ │
|
||||
│ │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
|
||||
│ │
|
||||
└───────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
┌────┐
|
||||
│ 1 │ The WebRtc layer gathers information on how it can be reach by the other peer directly (Ice candidates)
|
||||
└────┘
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│candidate:1 1 tcp 1518149375 127.0.0.1 35990 typ host │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│candidate:2 1 UDP 2130706431 192.168.1.102 1816 typ host │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌────┐
|
||||
│ 2 │ The WebRTC layer notifies the App layer when it finds new Ice Candidates
|
||||
└────┘
|
||||
|
||||
|
||||
|
||||
┌────┐ The app layer, takes the ice candidates, encapsulate them in one or several matrix event adds the callId and
|
||||
│ 3 │ send it to the other user via the room
|
||||
└────┘
|
||||
┌──────────────┐
|
||||
│ mx event │
|
||||
├──────────────┴────────────────────────┐
|
||||
│ type: m.call.candidates │
|
||||
│ │
|
||||
│ +CallId │
|
||||
│ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ice candidate sdp │ │
|
||||
│ └──────────────────┘ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ice candidate sdp │ │
|
||||
│ └──────────────────┘ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ice candidate sdp │ │
|
||||
│ └──────────────────┘ │
|
||||
└───────────────────────────────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╔════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║C] Receiving a call offer ║
|
||||
║ ║
|
||||
╚════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
|
||||
┌───────────────┐
|
||||
│ Matrix │
|
||||
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
||||
│
|
||||
│ ┌─────────────────┐
|
||||
│ │ Callee │
|
||||
┌─────────────────┐ │ ┌───────────────────────────┐ └─────────────────┘
|
||||
│ Caller │ │ Signaling Room │ │
|
||||
└─────────────────┘ │ ├───────────────────────────┤
|
||||
│ ┌────────────────────┐ │ │ ┌─────────────────┐
|
||||
│ │ │ m.call.invite │───┼────────────────────────────┬────┬───▶│ │
|
||||
┌─────────────────┐ │ │ mx event │ │ │ │ 1 │ │ │
|
||||
│ │ │ │ └────────────────────┘ │ └────┘ │ │
|
||||
│ │ │ ┌────────────────────┐ │ │ │ Element │
|
||||
│ │ │ │ │ m.call.candidates │ │ │ App │
|
||||
│ Element │ │ │ mx event │ │ │ │ │
|
||||
│ App │ │ │ └────────────────────┘ │ │ │
|
||||
│ │ │ ┌────────────────────┐◀──┼─────────────────┼───┬────┬───────────┤ │
|
||||
│ │◀──────────────────┼──────────────────┼──│ m.call.answer │ │ │ 4 │ └──┬──────────────┘
|
||||
│ │ │ │ mx event │ │ │ └────┘ ├────┐ ▲
|
||||
└────┬────────────┘ │ │ └────────────────────┘ │ │ 2 │ ├────┐
|
||||
│ │ │ │ ├────┘ │ 3 │
|
||||
│ │ └───────────────────────────┘ ┌──▼─────────┴────┤
|
||||
┌────▼────────────┐ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ │
|
||||
│ │ │ │
|
||||
│ │ │ WebRtc │
|
||||
│ WebRtc │ │ ┌──┴─────────────────┐
|
||||
│ │ │ │ caller offer │
|
||||
┌──────────┴─────────┐ │ │ └──┬─────────────────┘
|
||||
│ callee answer │ │ └─────────────────┘
|
||||
└────────────────────┴───────┘
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
┌────┐
|
||||
│ 1 │ Bob receives a call.invite event in a room, then creates a WebRTC peer connection object
|
||||
└────┘
|
||||
|
||||
┌────┐
|
||||
│ 2 │ The encapsulated call offer sdp from the mx event is transmitted to WebRTC
|
||||
└────┘
|
||||
|
||||
┌────┐
|
||||
│ 3 │ WebRTC then creates a call answer for the offer and send it back to app layer
|
||||
└────┘
|
||||
|
||||
|
||||
┌────┐ The app layer, takes the webrtc answer, encapsulate it in a matrix event adds a callId and send it to the
|
||||
│ 3 │ other user via the room
|
||||
└────┘
|
||||
┌──────────────┐
|
||||
│ mx event │
|
||||
├──────────────┴────────┐
|
||||
│ type: m.call.answer │
|
||||
│ + callId │
|
||||
│ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ webrtc sdp │ │
|
||||
│ └──────────────────┘ │
|
||||
└───────────────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╔════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║D] Callee sends connection establishment info ║
|
||||
║ ║
|
||||
╚════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
|
||||
┌───────────────┐
|
||||
│ Matrix │
|
||||
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
||||
│
|
||||
│
|
||||
│
|
||||
┌─────────────────┐ │ ┌───────────────────────────┐ ┌─────────────────┐
|
||||
│ Caller │ │ Signaling Room │ │ │ Callee │
|
||||
└─────────────────┘ │ ├───────────────────────────┤ └─────────────────┘
|
||||
│ ┌────────────────────┐ │ │
|
||||
│ │ │ m.call.invite │ │
|
||||
┌─────────────────┐ │ │ mx event │ │ │ ┌─────────────────┐
|
||||
│ │ │ │ └────────────────────┘ │ │ │
|
||||
│ │ │ ┌────────────────────┐ │ │ │ │
|
||||
│ │ │ │ │ m.call.candidates │ │ │ │
|
||||
│ Element │ │ │ mx event │ │ │ │ Element │
|
||||
│ App │ │ │ └────────────────────┘ │ ┌────┐ │ App │
|
||||
│ │ │ ┌────────────────────┐ │ │ │ 3 │ │ │
|
||||
│ │◀──────────────────┼┐ │ │ m.call.answer │ │ ┌───────┴────┴────────│ │
|
||||
│ │ │ │ │ mx event │ │ ││ │ │
|
||||
└─────────────────┘ ││ │ └────────────────────┘ │ │ └─────────────────┘
|
||||
│ │ │ ┌────────────────────┐ │ ││ ▲
|
||||
│ │└─────────────────┼──│ m.call.candidates │ │ │ ├────┐
|
||||
▼ │ │ mx event │◀──┼────────────────┘│ │ 2 │
|
||||
┌─────────────────┐ │ │ └────────────────────┘ │ ┌────┴────┴───────┐
|
||||
│ │ └───────────────────────────┘ │ │ │
|
||||
│ │ │ │ │
|
||||
│ WebRtc │ │ │ WebRtc │
|
||||
│ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ ┌───┴────────────────┐
|
||||
│ │ │ │ caller offer │
|
||||
┌────────┴───────────┐ │ │ └───┬────────────────┘
|
||||
│ callee answer ├─────┘ ┌───────────────┐ └─────────────────┘
|
||||
├────────────────────┤ │ Stun / Turn │ ▲
|
||||
│ callee ice │ ├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ┌────┐ │
|
||||
│ candidates │ │ │ 1 │ │
|
||||
└────────────────────┘ │ ├────┴──┴───────┐
|
||||
│ │ │
|
||||
│ │ Network Stack │
|
||||
│◀─────────────────────┤ │
|
||||
│ │ │
|
||||
│ └───────────────┘
|
||||
│
|
||||
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
|
||||
|
||||
|
||||
┌────┐
|
||||
│ 1 │ The WebRtc layer gathers information on how it can be reach by the other peer directly (Ice candidates)
|
||||
└────┘
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│candidate:1 1 tcp 1518149375 127.0.0.1 35990 typ host │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
┌──────────────────────────────────────────────────────────────────┐
|
||||
│candidate:2 1 UDP 2130706431 192.168.1.102 1816 typ host │
|
||||
└──────────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌────┐
|
||||
│ 2 │ The WebRTC layer notifies the App layer when it finds new Ice Candidates
|
||||
└────┘
|
||||
|
||||
|
||||
|
||||
┌────┐ The app layer, takes the ice candidates, encapsulate them in one or several matrix event adds the callId and
|
||||
│ 3 │ send it to the other user via the room
|
||||
└────┘
|
||||
┌──────────────┐
|
||||
│ mx event │
|
||||
├──────────────┴────────────────────────┐
|
||||
│ type: m.call.candidates │
|
||||
│ │
|
||||
│ +CallId │
|
||||
│ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ice candidate sdp │ │
|
||||
│ └──────────────────┘ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ice candidate sdp │ │
|
||||
│ └──────────────────┘ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │ice candidate sdp │ │
|
||||
│ └──────────────────┘ │
|
||||
└───────────────────────────────────────┘
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
╔════════════════════════════════════════════════╗
|
||||
║ ║
|
||||
║D] Caller Callee connection ║
|
||||
║ ║
|
||||
╚════════════════════════════════════════════════╝
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
┌───────────────┐
|
||||
┌─────────────────┐ │ Matrix │ ┌─────────────────┐
|
||||
│ Caller │ ├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ Callee │
|
||||
└─────────────────┘ │ └─────────────────┘
|
||||
│
|
||||
│
|
||||
┌─────────────────┐ │ ┌─────────────────┐
|
||||
│ │ │ │ │
|
||||
│ │ │ │ │
|
||||
│ │ │ │ │
|
||||
│ Element │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ Element │
|
||||
│ App │ │ App │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
│ │ │ │
|
||||
└─────────────────┘ └─────────────────┘
|
||||
┌───────────────┐
|
||||
│ Internet │
|
||||
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
||||
┌─────────────────┐ │ ┌─────────────────┐
|
||||
│ │ │ │ │
|
||||
│ ├───────────────────────────────────────────────────────────────────────────────────┴─────────────────────┤ │
|
||||
│ WebRtc │█████████████████████████████████████████████████████████████████████████████████████████████████████████│ WebRtc │
|
||||
┌─────────────┴──────┐ ├────────────────────────────────────────┬──────────────────────────┬───────────────┬─────────────────────┤ ┌─────┴──────────────┐
|
||||
│ callee answer │ │ │ │ Video / Audio Stream │ │ │ caller offer │
|
||||
├────────────────────┤ │ └──────────────────────────┘ │ │ ├────────────────────┤
|
||||
│ callee ice ├──────────┘ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ └───────────┤ caller ice │
|
||||
│ candidates │ │ candidates │
|
||||
└────────────────────┘ └────────────────────┘
|
||||
|
||||
|
||||
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ │░
|
||||
│ If connection is impossible (firewall), and a turn │░
|
||||
│server is available, connection could happen through │░
|
||||
│ a relay │░
|
||||
│ │░
|
||||
└─────────────────────────────────────────────────────┘░
|
||||
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
|
||||
|
||||
|
||||
┌───────────────┐
|
||||
│ Internet │
|
||||
└─┬─────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
||||
┌─────────────────┐ │ ┌─────────────────┐
|
||||
│ │ │ ┌─────────────────────────┐ │ │
|
||||
│ ├───────────────────────────────────────┐│ │ │ │ │
|
||||
│ WebRtc │███████████████████████████████████████││ │ │ WebRtc │
|
||||
│ ├───────────────────────────────────────┘│ │ │ │ │
|
||||
│ │ ┌────────┴─────────────────┐ │ Relay │┌─────────────────────────────────────┤ │
|
||||
┌───────────────┴────┐ │ │ Video / Audio Stream │ │ ││█████████████████████████████████████│ ┌───────┴────────────┐
|
||||
│ callee answer ├────────────┘ └────────┬─────────────────┘ │ │└─────────────────────────────────────┴─────────┤ caller offer │
|
||||
├────────────────────┤ │ │ │ ├────────────────────┤
|
||||
│ callee ice │ │ │ │ │ caller ice │
|
||||
│ candidates │ └─────────────────────────┘ │ │ candidates │
|
||||
└────────────────────┘ │ └────────────────────┘
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
│
|
||||
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
|
30
fastlane/metadata/android/bg/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element е приложение от нов тип за съобщения и сътрудничество:
|
||||
|
||||
1. Дава Ви контрол, за да запазите поверителността си
|
||||
2. Позволява ви да комуникирате с всеки в мрежата на Matrix и дори извън него, като се интегрира с приложения като Slack
|
||||
3. Предпазва ви от реклами, изтичане на данни и търговско следене
|
||||
4. Защитава ви чрез шифроване от край до край, с кръстосано подписване, за да проверите другите
|
||||
|
||||
Element е напълно различен от другите приложения за съобщения и сътрудничество, понеже е децентрализиран и с отворен код.
|
||||
|
||||
Element ви позволява да го хоствате самостоятелно - или да изберете хост - така че да имате поверителност, собственост и контрол върху Вашите данни и разговори. Дава ви достъп до отворена мрежа, така че комуникацията Ви не е ограничена до потребителите на Element. И е много сигурно.
|
||||
|
||||
Element е в състояние да направи всичко това, защото работи върху Matrix - стандартът за отворена, децентрализирана комуникация.
|
||||
|
||||
Element ви дава контрол, като ви позволява да изберете кой да хоства Вашите разговори. От приложението Element можете да изберете хостване по различни начини:
|
||||
|
||||
1. Вземете безплатен профил на публичния сървър на matrix.org, хостван от разработчиците на Matrix, или изберете от хиляди публични сървъри, хоствани от доброволци
|
||||
2. Самостоятелно хоствайте профила си, като пуснете сървър на собствен хардуер
|
||||
3. Регистрирайте се за профил на персонализиран сървър, като се абонирате за хостинг платформата Element Matrix Services
|
||||
|
||||
<b>Защо да изберете Element?</b>
|
||||
|
||||
<b>ПРИТЕЖАВАЙТЕ ДАННИТЕ СИ</b>: Вие решавате къде да съхранявате вашите данни и съобщения. Вие ги притежавате и контролирате, а не някаква МЕГАКОРПОРАЦИЯ, която складира вашите данни или дава достъп на трети страни.
|
||||
|
||||
<b>ОТВОРЕНИ СЪОБЩЕНИЯ И СЪТРУДНИЧЕСТВО</b>: Можете да разговаряте с всеки друг в мрежата на Matrix, независимо дали използва Element или друго приложение на Matrix и дори ако използва различна система за съобщения като Slack, IRC or XMPP.
|
||||
|
||||
<b>СВРЪХ СИГУРНО</b>: Реално шифроване от край до край (само тези в разговора могат да дешифрират съобщения) и кръстосано подписване за проверка на устройствата на участниците в разговора.
|
||||
|
||||
<b>ПЪЛНА КОМУНИКАЦИЯ</b>: Съобщения, гласови и видео разговори, споделяне на файлове, споделяне на екран и цял куп интеграции, ботове и джаджи. Изграждайте стаи, общности, поддържайте връзка и направете нещата завършени.
|
||||
|
||||
<b>НАВСЯКЪДЕ КЪДЕТО СТЕ</b>: Поддържайте връзка, където и да сте, с напълно синхронизирана история на съобщенията на всичките ви устройства и чрез web на https://app.element.io.
|
1
fastlane/metadata/android/bg/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Сигурен децентрализиран чат и VoIP. Пазете данните си от външни лица.
|
1
fastlane/metadata/android/bg/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (предишен Riot.im)
|
1
fastlane/metadata/android/ca/changelogs/40100100.txt
Normal file
@@ -0,0 +1 @@
|
||||
// TODO
|
30
fastlane/metadata/android/ca/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element és un nou tipus d'aplicació de missatgeria i col·laboració que:
|
||||
|
||||
1. Et dóna a tu el control per preservar la teva privadesa
|
||||
2. Et permet comunicar-te amb qualsevol persona de la xarxa Matrix i, fins i tot més enllà gràcies a integracions amb altres aplicacions com Slack
|
||||
3. Et protegeix de la publicitat, l'obtenció no desitjada de dades i dels navegadors amb accés controlat
|
||||
4. T'assegura a tu mitjançant l'encriptació d'extrem a extrem i amb signatures creuades per verificar els altres
|
||||
|
||||
Element és completament diferent a les altres aplicacions de missatgeria i col·laboració ja que és descentralitzat i de codi obert.
|
||||
|
||||
Element et deixa triar l'allotjament perquè disposis de privadesa, propietat i control de les teves dades i converses. Et dóna accés a una xarxa oberta perquè no et quedis únicament parlant amb els usuaris d'Element.
|
||||
|
||||
Element pot fer tot això ja que opera sobre Matrix - l'estàndard per a les comunicacions obertes i descentralitzades.
|
||||
|
||||
Element et dóna el control perquè et deixa escollir qui vols que allotgi les teves converses. Des de l'aplicació d'Element, pots triar l'allotjament de diferents maneres:
|
||||
|
||||
1. Crea un compte gratuït al servidor públic de matrix.org allotjat pels desenvolupadors de Matrix o tria'n un entre els milers de servidors públics creats per voluntaris
|
||||
2. Allotja tu mateix el teu compte en el teu propi servidor
|
||||
3. Registra el compte en un servidor personalitzat subscrivint-te a la plataforma d'Element Matrix Services (EMS)
|
||||
|
||||
<b>Per què escollir Element?</b>
|
||||
|
||||
<b>PROPIETAT DE LES TEVES DADES</b>: Tu decideixes a on desar les teves dades i missatges. Tu les controles i n'ets el propietari, no una mega-corporació que s'aprofita de les teves dades o les cedeix a tercers.
|
||||
|
||||
<b>MISSATGERIA I COL·LABORACIÓ OBERTA</b>: Pots parlar amb qualsevol que estigui a la xarxa Matrix, ja sigui amb Element o amb qualsevol altre aplicació Matrix, fins i tot encara que utilitzin sistemes de missatgeria diferents com Slack, IRC o XMPP.
|
||||
|
||||
<b>SUPER-SEGUR</b>: Encriptació d'extrem a extrem real (només qui està conversant pot desxifrar els missatges), i amb signatures creuades per a verificar els dispositius dels participants en les converses.
|
||||
|
||||
<b>COMUNICACIÓ COMPLETA</b>: Missatgeria, veu i video-trucades, compartició de fitxers, compartició de pantalla i un munt d'integracions, bots i ginys. Crea sales, comunitats, mantén-te en contacte i enllesteix el que et proposes.
|
||||
|
||||
<b>A TOT ARREU</b>: Mantingues el contacte des de qualsevol lloc on siguis, amb un historial de missatges totalment sincronitzat entre tots els teus dispositius i també a la web: https://app.element.io.
|
1
fastlane/metadata/android/ca/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Xat i VoIP segurs i descentralitzats. Protegeix les teves dades de tercers.
|
1
fastlane/metadata/android/ca/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (anteriorment Riot.im)
|
2
fastlane/metadata/android/de/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Diese neue Version enthält hauptsächlich Fehlerkorrekturen und Verbesserungen. Nachrichten verschicken geht jetzt viel schneller.
|
||||
Vollständige Versionshinweise: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/de/changelogs/40100110.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Diese neue Version enthält hauptsächlich Verbesserungen der Benutzer*innenoberfläche und der Handhabung. Du kannst jetzt ganz schnell Freund*innen einladen und DMs erstellen, indem du schlicht einen QR-Code scannst.
|
||||
Vollständige Versionshinweise: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
30
fastlane/metadata/android/de/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element ist eine neuartige Messaging- und Kollaborationsapp:
|
||||
|
||||
1. Volle Kontrolle über deine Privatssphäre
|
||||
2. Kommuniziere mit jedem aus dem Matrix-Netzwerk und mit der Integration von z.B. Slack sogar über Matrix hinaus
|
||||
3. Schutz vor Werbung, Datamining und geschlossenen Platformen
|
||||
4. Absicherung durch Ende-zu-Ende-Verschlüsselung, und Cross Signing um andere zu verifizieren
|
||||
|
||||
Element unterscheidet sich durch Dezentralität und Open Source deutlich von anderen Messaging- und Kollaborationsapps.
|
||||
|
||||
Element ermöglicht es einen eigenen Server zu betreiben - oder einen beliebigen auszuwählen, sodass du nicht nur Privatssphäre gewinnst, sondern auch deine Daten und Konversationen in deiner Hand sind und du sie kontrollieren kannst. Du hast Zugriff auf ein offenes Netzwerk, und kannst daher nicht nur mit Element-Nutzern schreiben. Und es ist sehr sicher.
|
||||
|
||||
Element ist zu all diesem in der Lage, weil es Matrix nutzt - einen Standard für offene, dezentrale Kommunikation.
|
||||
|
||||
Element gibt dir die Kontrolle, indem es dir die Wahl darüber lässt, wer deine Konversationen hostet. In der Element App kannst du zwischen verschiedenen Möglichkeiten auswählen:
|
||||
|
||||
1. Kostenlos auf dem öffentlichen matrix.org Server registrieren, der von den Matrix-Entwicklern gehostet wird, oder wähle aus Tausenden von öffentlichen Servern, die von Freiwilligen gehostet werden
|
||||
2. Einen Account auf einem eigenen Server auf eigener Hardware betreiben
|
||||
3. Einen Account auf einem benutzerdefinierten Server erstellen, zum Beispiel durch ein Abonnment bei der Element Matrix Services Hosting-Platform
|
||||
|
||||
<b>Wieso Element nutzen?</b>
|
||||
|
||||
<b>BESITZE DEINE DATEN</b>: Du entscheidest wo deine Daten und Nachrichten gespeichert werden. Du besitzt und kontrollierst sie, anstatt ein Großkonzern, der deine Daten analysiert und Dritten Zugriff gibt.
|
||||
|
||||
<b>OFFENE KOMMUNIKATION UND KOLLABORATION</b>: Du kannst mit jedem im Matrix-Netzwerk schreiben, ob sie nun Element oder eine andere Matrix-App nutzen, oder gar ein anderes Kommunikationssystem wie z.B. Slack, IRC oder XMPP.
|
||||
|
||||
<b>SUPER SICHER</b>: Echte Ende-zu-Ende-Verschlüsselung (nur Personen in der Konversation können die Nachrichten entschlüsseln), und Cross Signing um die Geräte der anderen Personen zu verifizieren.
|
||||
|
||||
<b>VOLLSTÄNDIGE KOMMUNIKATION</b>: Nachrichten, Telefonate und Videoanrufe, Teilen von Dateien oder dem eigenen Bildschirm und viele andere Integrationen, Bots und Widgets. Erstelle Räume, Communities, bleib in Kontakt und sei produktiv.
|
||||
|
||||
<b>ÜBERALL WO DU BIST</b>: Bleib in Kontakt wo auch immer du bist - mit einem vollständig synchronisierten Nachrichtenverlauf über alle Geräte und im Web auf https://app.element.io.
|
1
fastlane/metadata/android/de/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Sicherer dezentraler Chat & Telefonie. Schütze deine Daten vor Dritten.
|
1
fastlane/metadata/android/de/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (zuvor Riot.im)
|
2
fastlane/metadata/android/en-US/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
This new version mainly contains bug fixes and improvements. Sending a message is now much faster.
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/en-US/changelogs/40100110.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
This new version mainly contains user interface and user experience improvements. Now you can invite friends, and create DM very fast by scanning QR codes.
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
2
fastlane/metadata/android/en-US/changelogs/40100120.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Main changes in this version: URL Preview, new Emoji keyboard, new room settings capabilities, and snow for Christmas!
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
2
fastlane/metadata/android/en-US/changelogs/40100130.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Main changes in this version: URL Preview, new Emoji keyboard, new room settings capabilities, and snow for Christmas!
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.13
|
2
fastlane/metadata/android/en-US/changelogs/40100140.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Main changes in this version: Edit room permissions, automatic light/dark theme, and a bunch of bug fixes.
|
||||
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.14
|
30
fastlane/metadata/android/en-US/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element is a new type of messenger and collaboration app that:
|
||||
|
||||
1. Puts you in control to preserve your privacy
|
||||
2. Lets you communicate with anyone in the Matrix network, and even beyond by integrating with apps such as Slack
|
||||
3. Protects you from advertising, datamining and walled gardens
|
||||
4. Secures you through end-to-end encryption, with cross-signing to verify others
|
||||
|
||||
Element is completely different from other messaging and collaboration apps because it is decentralised and open source.
|
||||
|
||||
Element lets you self-host - or choose a host - so that you have privacy, ownership and control of your data and conversations. It gives you access to an open network; so you’re not just stuck speaking to other Element users only. And it is very secure.
|
||||
|
||||
Element is able to do all this because it operates on Matrix - the standard for open, decentralised communication.
|
||||
|
||||
Element puts you in control by letting you choose who hosts your conversations. From the Element app, you can choose to host in different ways:
|
||||
|
||||
1. Get a free account on the matrix.org public server hosted by the Matrix developers, or choose from thousands of public servers hosted by volunteers
|
||||
2. Self-host your account by running a server on your own hardware
|
||||
3. Sign up for an account on a custom server by simply subscribing to the Element Matrix Services hosting platform
|
||||
|
||||
<b>Why choose Element?</b>
|
||||
|
||||
<b>OWN YOUR DATA</b>: You decide where to keep your data and messages. You own it and control it, not some MEGACORP that mines your data or gives access to third parties.
|
||||
|
||||
<b>OPEN MESSAGING AND COLLABORATION</b>: You can chat with anyone else in the Matrix network, whether they’re using Element or another Matrix app, and even if they are using a different messaging system of the likes of Slack, IRC or XMPP.
|
||||
|
||||
<b>SUPER-SECURE</b>: Real end-to-end encryption (only those in the conversation can decrypt messages), and cross-signing to verify the devices of conversation participants.
|
||||
|
||||
<b>COMPLETE COMMUNICATION</b>: Messaging, voice and video calls, file sharing, screen sharing and a whole bunch of integrations, bots and widgets. Build rooms, communities, stay in touch and get things done.
|
||||
|
||||
<b>EVERYWHERE YOU ARE</b>: Stay in touch wherever you are with fully synchronised message history across all your devices and on the web at https://app.element.io.
|
BIN
fastlane/metadata/android/en-US/images/featureGraphic.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
fastlane/metadata/android/en-US/images/icon.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
After Width: | Height: | Size: 131 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/2.png
Normal file
After Width: | Height: | Size: 316 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/3.png
Normal file
After Width: | Height: | Size: 310 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/4.png
Normal file
After Width: | Height: | Size: 543 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/5.png
Normal file
After Width: | Height: | Size: 341 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/6.png
Normal file
After Width: | Height: | Size: 334 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/7.png
Normal file
After Width: | Height: | Size: 551 KiB |
1
fastlane/metadata/android/en-US/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Secure decentralised chat & VoIP. Keep your data safe from third parties.
|
1
fastlane/metadata/android/en-US/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (previously Riot.im)
|
30
fastlane/metadata/android/eo/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element estas nova speco de mesaĝilo kaj kunlaborilo, kiu:
|
||||
|
||||
1. Lasas vin regi vian komunikadon por protekti vian privatecon
|
||||
2. Lasas vin komuniki kun ĉiu ajn en la reto de Matrix, kaj eĉ pliaj, per interkompreno kun aplikaĵoj kiel ekzemple Slack
|
||||
3. Protektas vin de reklamoj, kolektado de datumoj, kaj muritaj ĝardenoj
|
||||
4. Sekurigas vian komunikadon per tutvoja ĉifrado, kun la eblo kontroli aliajn per delegaj subskriboj
|
||||
|
||||
Element malsamas al aliaj mesaĝiloj kaj kunlaboriloj, ĉar ĝi estas sencentra kaj malfermitkoda.
|
||||
|
||||
Element lasas vin gastigi vian propran servilon, aŭ elekti servilon, kiu plaĉas al vi, por ke vi ne perdu privatecon, kaj por ke vi daŭre regu kaj posedu viajn datumojn kaj interparolojn. Ĝi donas al vi aliron al malfermita reto; por ke via interparolado ne estu limigita nur al aliaj uzantoj de Element. Kaj ĝi estas tre sekura.
|
||||
|
||||
Element povas fari ĉi ĉion, ĉar ĝi funkcias per Matrix – publika normo por malfermita, sencentra komunikado.
|
||||
|
||||
Element lasas vi elekti, kiu gastigos viajn interparolojn. Per la aplikaĵo Element, vi povas elekti diversajn specojn de gastigado:
|
||||
|
||||
1. Akiri senpagan konton ĉe la publika servilo matrix.org, gastigata de la programistoj de Matrix, aŭ elekti unu el miloj da publikaj serviloj, gastigataj de volontuloj
|
||||
2. Memgastiĝi per via propra servilo ĉe via propra aparato
|
||||
3. Registriĝi ĉe propra servilo per simpla pagaliĝo al la gastiga platformo «Element Matrix Services»
|
||||
|
||||
<b>Kial Element?</b>
|
||||
|
||||
<b>POSEDU VIAJN DATUMOJN</b>: Vi decidu, kie vi tenu viajn datumojn kaj mesaĝojn. Vi posedas kaj regas ilin, ne iu granda komerca firmao, kiu kolektas viajn datumojn aŭ donas aliron al aliuloj.
|
||||
|
||||
<b>MALFERMAJ MESAĜADO KAJ KUNLABORADO</b>: Vi povas babili kun ĉiu alia en la reto de Matrix, ĉu ĝi uzas Elementon aŭ alian aplikaĵon de Matrix, kaj eĉ se ĝi uzas tute alian mesaĝilon, kiel ekzemple Slack, IRC, aŭ XMPP.
|
||||
|
||||
<b>TRE SEKURA</b>: Vera tutvoja ĉifrado (nur la interparolantoj povas malĉifri siajn mesaĝojn), kaj delegaj subskriboj por kontroli la aparatojn de partoprenantoj.
|
||||
|
||||
<b>SENMANKA KOMUNIKADO</b>: Mesaĝoj, voĉvokoj kaj vidvokoj, havigado de dosieroj, ekrano, kaj multaj diversaj kunigoj, robotoj kaj fenestraĵoj. Kreu ĉambrojn, komunumojn, komuniku kaj kunlaboru.
|
||||
|
||||
<b>ĈIE KUN VI</b>: Tenu vin ĝisdata per historio de mesaĝoj plene spegulita trans ĉiuj viaj aparatoj, kaj sur la reto per https://app.element.io.
|
1
fastlane/metadata/android/eo/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Sekura kaj sencentrigita vokado kaj babilado. Tenu viajn datumojn sekuraj.
|
1
fastlane/metadata/android/eo/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (antaŭe Riot.im)
|
1
fastlane/metadata/android/es/changelogs/40100100.txt
Normal file
@@ -0,0 +1 @@
|
||||
// TODO
|
30
fastlane/metadata/android/es/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element es un nuevo tipo de aplicación de mensajería y colaboración que:
|
||||
|
||||
1. Te da el control para preservar su privacidad
|
||||
2. Te permite comunicarse con cualquier persona en la red Matrix e incluso más allá al integrarse con aplicaciones como Slack
|
||||
3. Te protege de la publicidad, la minería de datos y los jardines vallados
|
||||
4. Te protege a través de encriptación de Extremo-a-Extremo, con firma cruzada para verificar a otros
|
||||
|
||||
Element es completamente diferente de otras aplicaciones de mensajería y colaboración porque es descentralizado y de código abierto.
|
||||
|
||||
Element te permite tener su propio servidor privado, o elegir uno público, para que tenga privacidad, posesión, y control de sus datos y conversaciones. Te da acceso a una red abierta; para que no se quede atrapado hablando solo con otros usuarios de Element. Y es muy seguro.
|
||||
|
||||
Element puede hacer todo esto porque opera en Matrix, el estándar para la comunicación abierta y descentralizada.
|
||||
|
||||
Element te da el control permitiéndote elegir quién aloja tus conversaciones. Desde la aplicación Element, puedes elegir hospedar de diferentes maneras:
|
||||
|
||||
1. Obtén una cuenta gratuita en el servidor público de matrix.org alojado por los desarrolladores de Matrix, o elije entre miles de servidores públicos alojados por voluntarios
|
||||
2. Autohospeda tu cuenta con un servidor en tu propio hardware
|
||||
3. Regístrate para obtener una cuenta en un servidor personalizado simplemente suscribiéndote a la plataforma de alojamiento de Element Matrix Services
|
||||
|
||||
<b>¿Por qué elegir Element?</b>
|
||||
|
||||
<b>TOMA POSESIÓN DE TUS DATOS</b>: Tú decides dónde guardar tus datos y mensajes. Tú eres el propietario y quien lo controla, no alguna MEGACORP que extrae tu datos o da acceso a terceros.
|
||||
|
||||
<b>MENSAJERÍA ABIERTA Y COLABORACIÓN</b>: Puede chatear con cualquier otra persona en la red de Matrix, tanto si usan Element u otra aplicación de Matrix, e incluso si están usando un sistema de mensajería diferente como Slack, IRC o XMPP.
|
||||
|
||||
<b>SUPER SEGURO</b>: Encriptación de Extremo-a-Extremo real (solo aquellos en la conversación pueden descifrar mensajes) y firma cruzada para verificar los dispositivos de los participantes de la conversación.
|
||||
|
||||
<b>COMUNICACIÓN COMPLETA</b>: Mensajería, llamadas de voz y video, uso compartido de archivos, uso compartido de pantalla y un montón de integraciones, bots y widgets. Crea salas, comunidades, mantente en contacto y organízate con eficacia.
|
||||
|
||||
<b>EN TODAS PARTES</b>: Mantente en contacto donde quiera que estés con un historial de mensajes totalmente sincronizado en todos sus dispositivos y en la web en https://app.element.io.
|
1
fastlane/metadata/android/es/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Chat y VoIP descentralizados y seguros. Mantén tus datos a salvo de terceros.
|
1
fastlane/metadata/android/es/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (previamente Riot.im)
|
2
fastlane/metadata/android/et/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Selles uues versioonis leidub põhiliselt veaparandusi ja pisikohendusi. Sõnumite saatmine on nüüd märkatavalt kiirem.
|
||||
Kogu ingliskeelne muudatuste logi: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/et/changelogs/40100110.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Uues versioonis leidub põhiliselt kasutajaliidese ning kasutajakogemuse parandusi. Nüüd saad sõpradele kutseid saata ning otsevestlusi alustada QR-koodi lugemise abil.
|
||||
Kõik muudatused: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
30
fastlane/metadata/android/et/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element on uut tüüpi suhtlus- ja koostöörakendus, mis:
|
||||
|
||||
1. Võimaldab täielikku kontrolli privaatsuse üle
|
||||
2. Võimaldab suhelda kõigiga Matrixi võrgus ja isegi väljaspool seda, olles integreeritud selliste rakendustega nagu Slack
|
||||
3. Kaitseb sind reklaamide ja andmekogumise eest
|
||||
4. Tagab turvalisuse läbiva krüptimise abil, kasutades risttunnustamist vestlejate tuvastamiseks
|
||||
|
||||
Element erineb täielikult teistest sõnumside- ja koostöörakendustest, kuna see on detsentraliseeritud ja avatud lähtekoodiga.
|
||||
|
||||
Element võimaldab ise hostida - või valida hosti -, et oleks tagatud privaatsus ja kontroll oma andmete ja vestluste üle. Element annab ka juurdepääsu avatud võrgule, nii et te ei pea vaid Elemendi kasutajatega rääkima. Ning kogu süsteem on väga turvaline.
|
||||
|
||||
Element töötab Matrixil - avatud, detsentraliseeritud suhtlus-standardil.
|
||||
|
||||
Võimaldades valida, kes vestlusi korraldab, annab Element annab kontrolli sinule. Rakendust Element saad kasutada mitmel viisil.
|
||||
|
||||
1. Tasuta konto Matrixi arendajate hostitud avalikus serveris matrix.org või vali tuhandete avalike serverite hulgast, mida haldavad vabatahtlikud
|
||||
2. Hosti oma kontot ise, paigaldades serveri oma riistvarale
|
||||
3. Registreeruge serveris olevale kontole, tellides Element Matrix Services teenuseplatvormi
|
||||
|
||||
<b> Miks valida element? </b>
|
||||
|
||||
<b> KONTROLL ANDMETE ÜLE</b>: otsustad ise, kus oma andmeid ja sõnumeid hoida. Need kuuluvad sulle ja sinu käes on kontroll, mitte mõne MEGAFIRMA käes, mis andmeid oma kasuks kaevandab või kolmandatele isikutele juurdepääsu annab.
|
||||
|
||||
<b> AVATUD SUHTLUS JA KOOSTÖÖ </b>: saad vestelda kõigi teistega Matrixi võrgus, olenemata sellest, kas nad kasutavad Elementi või mõnda muud Matrixi rakendust, ja isegi kui nad kasutavad teistsugust suhtlussüsteemi nagu Slack, IRC või XMPP.
|
||||
|
||||
<b> ÜLITURVALINE </b>: tõeline läbiv krüptimine (ainult vestluses osalejad saavad sõnumeid lugeda) ja risttunnustamine vestluses osalejate tuvastamiseks.
|
||||
|
||||
<b> KÕIK SUHTLUSVÕIMALUSED</b>: sõnumid, hääl- ja videokõned, failide jagamine, ekraani jagamine ja terve hulk lõiminguid, roboteid ja vidinaid. Loo tubasid, kogukondi, hoia ühendust ja saa asjad aetud.
|
||||
|
||||
<b> KÕIKJAL, KUS VIIBITE</b>: saad suhelda kõigis oma seadmetes ja ka veebis aadressil https://app.element.io ning sealjuures täielikult sünkroonitud sõnumite ajalooga.
|
1
fastlane/metadata/android/et/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Turvalised ning hajutatud vestlused ja VoIP-kõned. Sinu suhtlus on üliturvaline.
|
1
fastlane/metadata/android/et/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (varem Riot.im)
|
2
fastlane/metadata/android/fa/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
این نگارش جدید به طور عمده شامل رفع اشکالها و بهبودها است. ارسال پیام اکنون بسیار سریعتر است.
|
||||
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/fa/changelogs/40100110.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
این نگارش جدید به طور عمده شامل رابط کاربری و بهبود تجربه کاربر است. اکنون میتوانید با پویش کدهای QR دوستانتان را دعوت کرده و بسیار سریع پیام مستقیم ایجاد کنید.
|
||||
گزارش دگرگونی کامل: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
30
fastlane/metadata/android/fa/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
المنت گونهای جدید از کارههای پیامرسانی و همکاری است که:
|
||||
|
||||
۱. کنترل محرمانگیتان را در دست خودتان میگذارد
|
||||
۲. میگذارد با هرکسی در شبکهٔ ماتریکس و حتا فراتر از آن، ارتباط برقرار کنید
|
||||
۳. از شما در برابر تبلیغات، دادهکاوری و دیوارهای پرداختی، محافظت میکند
|
||||
۴. با رمزنگاری سرتاسری با ورود چندگانه، امنتان میکند
|
||||
|
||||
المنت به خاطر نامتمرکز و نرمافزار آزاد بودن، کاملاً با دیگر کارههای پیامرسانی و همکاری، فرق دارد.
|
||||
|
||||
المنت میگذارد خودمیزبانی کرده یا میزبانی برگزینید که امنیت، مالکیت و واپایش دادهها و گفتوگوهایتان را در اختیار داشته باشید. این کاره شما را به شبکهای باز و شدیداً امن وصل کرده تا مجبور نباشید فقط با دیگر کاربران المنت صحبت کنید.
|
||||
|
||||
المنت میتواند همهٔ این کارها را بکند، چرا که روی ماتریکس، استانداردی برای گفتوگوی باز و نامتمرکز عمل میکند.
|
||||
|
||||
المنت با اجازه برای گزینش کسی که گفتوگوهایتان را میزبانی میکند، کنترل را به شما میدهد. با کارهٔ المنت، میتوانید برگزینید که به روشهای مختلفی میزبانی شوید:
|
||||
|
||||
۱. گرفتن حسابی رایگان روی کارساز عمومی matrix.org که به دست توسعهدهندگان ماتریکس میزبانی میشود، یا گرینش از میان هزاران کارساز عمومی میزبانیشده به دست داوطلبان
|
||||
۲. خودمیزبانی حسابتان با اجرای کراسازی روی سختافزار خودتان
|
||||
۳. ثبتنام برای حسابی روی یک کارساز سفارشی با اشتراک در بنیازهٔ میزبانی خدمات ماتریکس المنت
|
||||
|
||||
<b>چرا المنت را برگزینیم؟</b>
|
||||
|
||||
<b>مالک دادههایتان باشید</b>: خوتان تصمیم میگیرید که دادهها و پیامهایتان را کجا نگه دارید. شما صاحبشان هستید و واپایششان میکنید، نه شرکتهای بزرگی که دادههایتان را کاویده و به شرکتهای دیگر دسترسی میدهند.
|
||||
|
||||
<b>پیامرسانی و همکاری باز</b>: میتوانید با هرکسی در شبکهٔ ماتریکس گپ بزنید، چه از المنت استفاده کنند و چه از هر کارهٔ ماتریکس دیگری؛ و حتا اگر از سامانهٔ پیامرسانی متفاوتی مثل اسلک، آیآرسی یا جبر استفاده کنند.
|
||||
|
||||
<b>فوق امن</b>: رمزنگاری سرتاسری واقعی (فقط کسانی که در گفتوگو هستند،میتوانند پیامها را رمزگشایی کنند) و ورود چندگانه برای تأیید هویت افزارههای شرکتکنندگان در گفتوگو.
|
||||
|
||||
<b>ارتباط کامل</b>: پیامرسانی، تماسهای صوتی و تصویری،همرسانی پرونده، همرسانی صفحه و یه عالمه یکپارچگی، بات و ابزارک. اتاق و اجتماع ساخته، در دسترس بوده و کارها را انجام دهید.
|
||||
|
||||
<b>هرجا که هستید</b>: هر کجا که هستید، با همگام سازی کامل تاریخچهٔ پیامها بین همهٔ افزارههایتان و وب روی https://app.element.io در دسترس باشید.
|
1
fastlane/metadata/android/fa/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
گپ و تماس نامتمرکز امن. دادههایتان را از اشخاص سوم امن نگه دارید.
|
1
fastlane/metadata/android/fa/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (پیشتر Riot.im)
|
2
fastlane/metadata/android/fi/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Tämä versio sisältää virheenkorjauksia ja muita parannuksia. Viestien lähettäminen on nyt paljon nopeampaa.
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/fi/changelogs/40100110.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Tämä versio sisältää pääosin käyttöliittymä- ja käyttökokemusparannuksia. Voit nyt kutsua kavereita ja luoda yksityisviestejä nopeasti QR-koodeja lukemalla.
|
||||
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
30
fastlane/metadata/android/fi/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element on uudenlainen viestinsovellus, joka:
|
||||
|
||||
1. Antaa sinun päättää yksityisyydestäsi
|
||||
2. Antaa sinun kommunikoida kenen tahansa kanssa Matrix-verkossa ja jopa sen ulkopuolella siltaamalla sovelluksiin, kuten Slack
|
||||
3. Suojaa sinua mainonnalta, tietojen keräämiseltä ja suljetuilta alustoilta
|
||||
4. Suojaa sinut päästä päähän -salauksella sekä ristiin varmentamisella muiden todentamiseksi
|
||||
|
||||
Element eroaa täysin muista viestintäsovelluksista, koska se on hajautettu ja avointa lähdekoodia.
|
||||
|
||||
Element antaa sinun isännöidä itse - tai valita palveluntarjoajan - jotta sinulla on yksityisyys ja voit hallita tietojasi sekä keskustelujasi. Se antaa sinulle pääsyn avoimeen verkkoon, joten et jää juttelemaan vain toisten Elementin käyttäjien kanssa. Se on myös hyvin turvallinen.
|
||||
|
||||
Element pystyy tekemään kaiken tämän, koska se toimii Matrixilla - avoimella, hajautetun viestinnän standardilla.
|
||||
|
||||
Element antaa sinulle päätösvallan antamalla sinun valita, kuka isännöi keskustelujasi. Element-sovelluksessa voit valita isännän eri tavoin:
|
||||
|
||||
1. Hanki ilmainen tili Matrix-kehittäjien ylläpitämällä matrix.org-palvelimella tai valitse tuhansista vapaaehtoisten ylläpitämistä julkisista palvelimista.
|
||||
2. Isännöi tiliäsi itse ylläpitämällä palvelinta omalla laitteellasi
|
||||
3. Luo tili sinua varten tehdyllä palvelimella tilaamalla Element Matrix Services -palvelu
|
||||
|
||||
<b>Miksi valita Element?</b>
|
||||
|
||||
<b>OMAT TIEDOT</b>: Sinä päätät, missä tietosi ja viestisi säilytetään. Sinä määräät, ei jokin jättiyhtiö, joka tutkii tietojasi tai antaa niitä kolmansille osapuolille.
|
||||
|
||||
<b>AVOINTA VIESTINTÄÄ JA YHTEISTYÖTÄ</b>: Voit keskustella kaikkien muiden Matrix-verkon käyttäjien kanssa, riippumatta siitä käyttävätkö he Elementiä tai muuta Matrix-sovellusta, ja vaikka he käyttäisivät eri viestijärjestelmiä, kuten Slack, IRC tai XMPP.
|
||||
|
||||
<b>ERITTÄIN TURVALLINEN</b>: Vahva päästä päähän -salaus (vain keskustelussa olevat voivat purkaa viestien salauksen), ja ristiin varmentaminen keskustelun osallistujien laitteiden tarkistamiseksi.
|
||||
|
||||
<b>KATTAVAA VIESTINTÄÄ</b>: Viestit, ääni- ja videopuhelut, tiedostojen jakaminen, näytön jakaminen ja koko joukko integraatioita, botteja ja sovelmia. Rakenna huoneita ja yhteisöjä, pidä yhteyttä ja hoida asiasi.
|
||||
|
||||
<b>MISSÄ TAHANSA OLETKIN</b>: Pidä yhteyttä missä tahansa, täysin synkronoidun viestihistorian kautta kaikilla laitteillasi ja verkossa osoitteessa https://app.element.io.
|
1
fastlane/metadata/android/fi/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Turvallista, hajautettua keskustelua ja VoIP-puheluita. Pidä tietosi turvassa.
|
1
fastlane/metadata/android/fi/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (aiemmin Riot.im)
|
2
fastlane/metadata/android/fr/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
Cette nouvelle version contient principalement des corrections de bogues et des améliorations. Envoyer un message est maintenant plus rapide.
|
||||
Liste complète des changements : https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
30
fastlane/metadata/android/fr/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
Element est une nouvelle application de messagerie et de collaboration qui :
|
||||
|
||||
1) Vous place aux commandes de votre vie privée
|
||||
2) Vous permet de communiquer avec n'importe qui du réseau Matrix, et plus encore par des intégrations d'autres applications comme Slack ou Discord
|
||||
3) Vous protège de la publicité et de la collecte de données
|
||||
4) Vous sécurise grâce à du chiffrement bout-à-bout, avec de la signature croisée pour authentifier les autres utilisateurs
|
||||
|
||||
Element est complètement différent des autres applications de messagerie et de collaboration puisque l'application est décentralisée et open-source.
|
||||
|
||||
Element vous permet d'héberger vous-même -ou de choisir un hôte- vous permettant d'assurer votre vie privée, la propriété et le contrôle de vos données et de vos conversations. Cela vous offre l'accès à un réseau ouvert, vous n'êtes donc pas condamné à parler à d'autres utilisateurs d'Element seulement. Et c'est très sécurisé.
|
||||
|
||||
Element peut faire tout ça car il est basé sur Matrix, le protocole standard pour la communication ouverte et décentralisée.
|
||||
|
||||
Element vous donne le contrôle en vous laissant choisir qui héberge vos conversations. Depuis l'application Element, vous pouvez choisir votre hôte de différentes manières :
|
||||
|
||||
1) Créer un compte gratuit sur le serveur public matrix.org hébergé par les développeurs de Matrix, ou choisir parler les milliers de serveurs public hébergés par des bénévoles
|
||||
2) Héberger vous-même votre compte en installant un serveur sur votre propre machine
|
||||
3) Créer un compte sur un serveur personnalisé en souscrivant sur la plateforme d'hébergement « Element Matrix Services » (EMS)
|
||||
|
||||
<b>Pourquoi choisir Element ?</b>
|
||||
|
||||
<b>POSSÉDEZ VOS DONNÉES</b> : Vous décidez où conserver vos données et vos messages. Vous les possédez et vous les contrôlez, et non une MEGACORP qui mine vos données ou les donnent à des tiers
|
||||
|
||||
<b>UNE MESSAGERIE OUVERTE ET COLLABORATIVE</b> : Vous pouvez discuter avec n'importe qui sur le réseau Matrix, qu'ils utilisent Element ou une autre application basée sur Matrix, et même s'ils utilisent un système de messagerie différent comment Slack, Discord, IRC ou XMPP.
|
||||
|
||||
<b>SUPER SÉCURISÉ</b> : Un réel chiffrement bout-à-bout (seulement ceux deux la conversation peuvent déchiffrer les messages), et une signature croisée pour vérifier les appareils des participants de la conversation.
|
||||
|
||||
<b>COMMUNICATION COMPLÈTE</b> : Messagerie, appels vocaux et vidéo, transfert de fichiers, partage d'écran et un tas d'intégrations, robots et widgets. Construisez des salons, des communautés, restez en contact et accomplissez de grandes choses.
|
||||
|
||||
<b>PARTOUT OÙ VOUS ÊTES</b> : Restez connectés peu import où vous êtes avec la synchronisation complète de l'historique des messages sur tous vos appareils et sur le web sur https://app.element.io.
|
1
fastlane/metadata/android/fr/short_description.txt
Normal file
@@ -0,0 +1 @@
|
||||
Chat & VoIP sûr et décentralisé. Gardez vos données en sécurité.
|
1
fastlane/metadata/android/fr/title.txt
Normal file
@@ -0,0 +1 @@
|
||||
Element (anciennement Riot.im)
|