mirror of
https://github.com/vector-im/riotX-android
synced 2025-10-06 00:02:48 +02:00
Compare commits
3086 Commits
riot-andro
...
feature/ex
Author | SHA1 | Date | |
---|---|---|---|
|
d932c5598b | ||
|
06770ca010 | ||
|
4b099dfef9 | ||
|
7115676393 | ||
|
6115a469eb | ||
|
9501fd74f0 | ||
|
03735d9213 | ||
|
3ac3f09df0 | ||
|
b534d4660c | ||
|
bec4af7c87 | ||
|
b3a408a34c | ||
|
46615d698e | ||
|
cf0b4d2581 | ||
|
59634753b3 | ||
|
a604e29744 | ||
|
e01899ce8f | ||
|
adea3ab775 | ||
|
68ef369adc | ||
|
11e5df1007 | ||
|
a86405fb01 | ||
|
1d0eb1e926 | ||
|
f3cbc18b50 | ||
|
30e5e15245 | ||
|
6fdbb91ccb | ||
|
96b46af9f5 | ||
|
b3a9e20885 | ||
|
1f92e61d3c | ||
|
a41b4a3621 | ||
|
60041d433e | ||
|
8b862e917a | ||
|
efeb41151c | ||
|
acc03abd03 | ||
|
848ff5b806 | ||
|
3740997b2e | ||
|
099600f665 | ||
|
e43b31ef2b | ||
|
e79657232a | ||
|
9bb216618a | ||
|
eff0a701d8 | ||
|
6c50342535 | ||
|
f4b10d5ed6 | ||
|
e75e48f377 | ||
|
7d4123c955 | ||
|
7c865e1a26 | ||
|
a97614b972 | ||
|
af63c98715 | ||
|
86f0af0ff2 | ||
|
c7241f5755 | ||
|
a708541803 | ||
|
9101c339c5 | ||
|
3bf1e48236 | ||
|
e7a29857c5 | ||
|
daa007b67d | ||
|
2a53f425ec | ||
|
624541af1c | ||
|
f378d46c9a | ||
|
6c7e188439 | ||
|
cc6bd1d2c6 | ||
|
fc0c49e16e | ||
|
1f3ff3e0f2 | ||
|
5618af07bd | ||
|
79dafaf13d | ||
|
7e93d6e5a7 | ||
|
22b8101230 | ||
|
9c5fe034fa | ||
|
17f2ca0f7b | ||
|
e8aca9ee88 | ||
|
ca44a96dc3 | ||
|
15f479b424 | ||
|
9e86b35f8c | ||
|
ebd55ea282 | ||
|
3c0c445ea7 | ||
|
918d820a5c | ||
|
2ac1287924 | ||
|
3b93b28a37 | ||
|
6203c393d7 | ||
|
c7a0ec7157 | ||
|
e22ce6fad5 | ||
|
16ede7b560 | ||
|
290c0358ea | ||
|
e098ed6627 | ||
|
ca09feb2e5 | ||
|
1b04f5f540 | ||
|
302b05515a | ||
|
597d4bf6b1 | ||
|
bfa384ad5b | ||
|
c93fd2a05d | ||
|
cbabbf5c1e | ||
|
ebe9d42780 | ||
|
17ad38f835 | ||
|
9df9bbc6db | ||
|
5fb273a5c8 | ||
|
0571662fe7 | ||
|
7e2f892904 | ||
|
18408377e4 | ||
|
f76b4c06c5 | ||
|
ba24c30d38 | ||
|
80a6823af4 | ||
|
0957ff69c4 | ||
|
476348d961 | ||
|
6a8ef889eb | ||
|
e321e20dc2 | ||
|
1978a180ff | ||
|
463f2a7ad7 | ||
|
1ec4424c0a | ||
|
1b210d42ed | ||
|
e5da026f1f | ||
|
5386271398 | ||
|
2a581bc90a | ||
|
148bbc2017 | ||
|
0902faa24b | ||
|
595ff4bebc | ||
|
aaeca96336 | ||
|
4e32120a41 | ||
|
08b65b57e4 | ||
|
9297c1d191 | ||
|
a8086ceb43 | ||
|
370b9dabff | ||
|
2cbce016bc | ||
|
70513b279b | ||
|
b77c10d3fb | ||
|
f78c72db59 | ||
|
39332e153e | ||
|
5c4cf3f7c9 | ||
|
fade21de57 | ||
|
4d3262ce41 | ||
|
0ed327646a | ||
|
eecb789603 | ||
|
28fad01be7 | ||
|
d2c912e5c4 | ||
|
55f410636f | ||
|
f2619df13d | ||
|
1212bb8d70 | ||
|
30be440774 | ||
|
93890343b6 | ||
|
8363eba32e | ||
|
c46ab4ff29 | ||
|
e9e3c0d011 | ||
|
05458479fa | ||
|
152c76954b | ||
|
d074c55793 | ||
|
7a41f2d79d | ||
|
22ed1dc358 | ||
|
499dc4e9e2 | ||
|
edee2cd640 | ||
|
8294f64687 | ||
|
bec3e63771 | ||
|
624545c631 | ||
|
4ae39611b5 | ||
|
b0e5d5d3e5 | ||
|
af30ff50f0 | ||
|
07220d7a59 | ||
|
ed99b503f5 | ||
|
f6ad67f1c8 | ||
|
6ee6b0cad9 | ||
|
d47ba6bd11 | ||
|
9cf0e1bde7 | ||
|
32b42b46e4 | ||
|
8b4fd7fdc0 | ||
|
a17c662465 | ||
|
e1fdbaee40 | ||
|
35d4eb381e | ||
|
8e71f265fc | ||
|
2b0b2ded5d | ||
|
3bd688c631 | ||
|
815796f2e7 | ||
|
000ccf5d03 | ||
|
c9608d7076 | ||
|
7984d021f6 | ||
|
57cb45d31e | ||
|
d903dfb40b | ||
|
99f5949ee1 | ||
|
4a2557dbcd | ||
|
426729b34c | ||
|
41e4e823fb | ||
|
5e2e6dcfc3 | ||
|
407134a89f | ||
|
60f221dc37 | ||
|
627d3b5b79 | ||
|
ad187f99bf | ||
|
2fdd3a78eb | ||
|
d949e0cced | ||
|
e27c5c4507 | ||
|
bfd974f698 | ||
|
dbe14ce0bb | ||
|
6ecd63bf5d | ||
|
94ea7d322d | ||
|
cf9d99ee8b | ||
|
afd2ecd384 | ||
|
6d53d0e12f | ||
|
557a5c715a | ||
|
b068dc39eb | ||
|
47f1ec78d4 | ||
|
5b3065730e | ||
|
0f55291089 | ||
|
dd0be54b05 | ||
|
8d6136cde1 | ||
|
0c613e36f1 | ||
|
6d5f89b65b | ||
|
34fd5e7191 | ||
|
c4a89a5da1 | ||
|
6cd462f852 | ||
|
04c4485e3e | ||
|
64694a4eda | ||
|
d11ed8c4ef | ||
|
205feeaf10 | ||
|
e51f2b8bc1 | ||
|
2d5f57591f | ||
|
3c06517d9e | ||
|
63fb5809bf | ||
|
a65f846929 | ||
|
4ee6273f2e | ||
|
061f3c6919 | ||
|
9b13381938 | ||
|
bc22647b48 | ||
|
73fccdd6de | ||
|
ad9873c565 | ||
|
e976100f1a | ||
|
289a3ab21f | ||
|
286f00396d | ||
|
cbda0ad37b | ||
|
db6fdcd098 | ||
|
7e3362da61 | ||
|
d9720a5199 | ||
|
3a65037151 | ||
|
424035f56f | ||
|
2a12cf22f5 | ||
|
97daf57b0a | ||
|
697b551b9b | ||
|
0211197c47 | ||
|
3b65761110 | ||
|
cfdfd3a8af | ||
|
6ac2717d8b | ||
|
49aed39711 | ||
|
a820443c56 | ||
|
67aa239398 | ||
|
2a3962265b | ||
|
883a22ba83 | ||
|
2e68c48752 | ||
|
3e87534ddc | ||
|
c6da7b19a7 | ||
|
85293ca2ed | ||
|
ed264382e9 | ||
|
e6fc605b08 | ||
|
882eea75ef | ||
|
8129cd0cd3 | ||
|
0bc203e0d5 | ||
|
6c9b16088f | ||
|
9c9c1fa79c | ||
|
76b425ee8a | ||
|
5b8215a356 | ||
|
9c7df25862 | ||
|
da16ec0af3 | ||
|
1244d00b31 | ||
|
98054815a4 | ||
|
06be3e691d | ||
|
323a0a5aeb | ||
|
d4516080a2 | ||
|
575ab92d4b | ||
|
9878f5475c | ||
|
2d52e9ac23 | ||
|
ee5d26dc63 | ||
|
60d492370f | ||
|
f4fd8af3b4 | ||
|
940563f663 | ||
|
191cef6fff | ||
|
73f9ef4232 | ||
|
c9a124ba59 | ||
|
788406a549 | ||
|
29a5fb3e16 | ||
|
0a4af67be4 | ||
|
d30c3f5073 | ||
|
28ca7dcf8b | ||
|
88e18a8640 | ||
|
1ef9ed5202 | ||
|
c794843bb2 | ||
|
afa3149504 | ||
|
f2f4d325eb | ||
|
05361c13f1 | ||
|
fef0404ac7 | ||
|
d6a5b9fb48 | ||
|
57dba2f29a | ||
|
f64db7f5f3 | ||
|
128d3845b9 | ||
|
602ea3327b | ||
|
e55178612c | ||
|
5a0d62db6f | ||
|
ed62e6a390 | ||
|
25a6b0ddfb | ||
|
15aeccac24 | ||
|
fea86d5885 | ||
|
2df26ee931 | ||
|
8f7c4283ad | ||
|
221bdc112d | ||
|
d2544fdd20 | ||
|
35c59e699a | ||
|
633b80c622 | ||
|
b37c203885 | ||
|
dabac0966c | ||
|
7f97c80485 | ||
|
7aa0899a4c | ||
|
539f1150df | ||
|
82023d5d78 | ||
|
4ef7a215ac | ||
|
41a473ab06 | ||
|
89cf1f3237 | ||
|
b65fc4f46b | ||
|
401b5e2b7a | ||
|
a44d00a31c | ||
|
267ae457ee | ||
|
887da0a3d6 | ||
|
07ffd3ded3 | ||
|
25dbb3e9ea | ||
|
68177a02e1 | ||
|
0a96841336 | ||
|
4dcd7846b0 | ||
|
dc48cd4d16 | ||
|
883a7cecf0 | ||
|
daf019b288 | ||
|
e76aafcfeb | ||
|
5eeb545ae2 | ||
|
d29ab94617 | ||
|
618d1f5de6 | ||
|
277fc4bf61 | ||
|
c75eb050df | ||
|
304b489470 | ||
|
4709002429 | ||
|
226a547f09 | ||
|
89b0b23891 | ||
|
17e2aa91b5 | ||
|
81da03d168 | ||
|
f1390bdd29 | ||
|
e457196795 | ||
|
adbb9ad0f3 | ||
|
faddc4ead7 | ||
|
10cd1b5238 | ||
|
f36bab0a7a | ||
|
0f77c5be90 | ||
|
cbe5d2e884 | ||
|
a3bbcaf48f | ||
|
acb1346aaa | ||
|
594cc26887 | ||
|
f4d707bd87 | ||
|
838d0cff1c | ||
|
55e3fcfccf | ||
|
47da718250 | ||
|
27d60986c1 | ||
|
05afa9a4da | ||
|
892213eacb | ||
|
6aa44a9f63 | ||
|
dd7aadd01c | ||
|
72b9ba4a27 | ||
|
e7e6893920 | ||
|
4d578af2bd | ||
|
5c4f713463 | ||
|
f1961b710c | ||
|
16a7b0bbdb | ||
|
db95e7b0cd | ||
|
b3d102d56e | ||
|
ac7e13a701 | ||
|
77e834238f | ||
|
82c3bd1b8a | ||
|
34491a589f | ||
|
543ec5f185 | ||
|
9f98faea07 | ||
|
84ccfafc1d | ||
|
570dec749b | ||
|
957acd0cd2 | ||
|
0593f2f928 | ||
|
d7e4fd555c | ||
|
68f422e498 | ||
|
2c0b7ce0f4 | ||
|
72ee1ace48 | ||
|
979ffcf227 | ||
|
f0f0aafa1b | ||
|
c2d5ded335 | ||
|
55fd983fd3 | ||
|
1a5291537d | ||
|
d6ef3ea08e | ||
|
3e4a41bd73 | ||
|
b31bb9eb4f | ||
|
fac9a65f54 | ||
|
93fc64ff33 | ||
|
e097c92458 | ||
|
e91dbfbf2c | ||
|
801f2860e2 | ||
|
1ffc3a4f53 | ||
|
844fe2c4cd | ||
|
69efb45fb7 | ||
|
1103d7c112 | ||
|
c88072e55f | ||
|
e041d404f3 | ||
|
5b07af2c12 | ||
|
1f96367286 | ||
|
de73539d2b | ||
|
f7ed94c6e9 | ||
|
36b1a1471a | ||
|
1f1eeccc32 | ||
|
1d449c84fe | ||
|
0750c7763c | ||
|
dbaaa07dad | ||
|
14502573bf | ||
|
7446b12827 | ||
|
d4c8f56c6e | ||
|
2ea45185d4 | ||
|
50ba131350 | ||
|
b2df107f17 | ||
|
2b60affd9a | ||
|
e771b21ea3 | ||
|
b20bbc1295 | ||
|
609ceb7fa4 | ||
|
aac3f379a7 | ||
|
d46ae83dc4 | ||
|
561b89830a | ||
|
b69d8ad71a | ||
|
ec0a04e893 | ||
|
8307245120 | ||
|
5431584b3c | ||
|
426782a001 | ||
|
7eb9941f8c | ||
|
268d740059 | ||
|
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 | ||
|
dd67e8c5b5 | ||
|
8de4b0bb20 | ||
|
e21c8792e6 | ||
|
54f6440bcf | ||
|
819f0c021e | ||
|
bc2f49fa31 | ||
|
d3a3ba8079 | ||
|
1540f13444 | ||
|
245d580825 | ||
|
2578423c91 | ||
|
1762451bc0 | ||
|
38e4984a4a | ||
|
9d7c49306a | ||
|
6b605b2e98 | ||
|
cf0242f23a | ||
|
56e8325efe | ||
|
d91ed2985d | ||
|
5f9f69b4dc | ||
|
da33cbedda | ||
|
19fc4419c3 | ||
|
2d91865277 | ||
|
003f5fab1f | ||
|
2a365d6776 | ||
|
55f5f90c45 | ||
|
bd3bdd6996 | ||
|
0cf485d873 | ||
|
75e06d43c5 | ||
|
922ae5b041 | ||
|
201a346d41 | ||
|
afa1cf7d6c | ||
|
d09a6714af | ||
|
f5bf774126 | ||
|
fae1382429 | ||
|
a6f909b942 | ||
|
ae55ee82a7 | ||
|
037e53f385 | ||
|
a28dfdc48e | ||
|
81bdf506bc | ||
|
f253aa6b37 | ||
|
0702eee179 | ||
|
c4a019f0d3 | ||
|
e948e9d85a | ||
|
22c10f5ada | ||
|
869eb262f3 | ||
|
7249c7d25a | ||
|
6e8d93bc6f | ||
|
963c30a275 | ||
|
474ade01cf | ||
|
18d4b66c97 | ||
|
fa311f4ce2 | ||
|
3a9b80127f | ||
|
78c1a0acf4 | ||
|
4ee34126bd | ||
|
97b9064d29 | ||
|
4f59ec37ca | ||
|
c34fea2932 | ||
|
c11a50f7ff | ||
|
23623b8895 | ||
|
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 | ||
|
e0cd210852 | ||
|
d87beff434 | ||
|
439ea42b54 | ||
|
22c981d8bf | ||
|
8797d7562d | ||
|
9c5fe81792 | ||
|
69cc4f83bb | ||
|
33047b5f64 | ||
|
8734101d87 | ||
|
c53111a85a | ||
|
a16086db6f | ||
|
81f7932cb7 | ||
|
a5736efc75 | ||
|
b1f492de58 | ||
|
629488bbe6 | ||
|
14288b545b | ||
|
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 | ||
|
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 | ||
|
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 | ||
|
afc3c1462e | ||
|
44cc62622d | ||
|
91c86c1a45 | ||
|
5541c2e190 | ||
|
f2ba236130 | ||
|
4cb7754b77 | ||
|
3473a7ef5e | ||
|
c9535509e8 | ||
|
3d578c147c | ||
|
e4cabe9aa8 | ||
|
43ac66feb3 | ||
|
e36059a427 | ||
|
5e2f091ec1 | ||
|
752bde413d | ||
|
e6949c85fb | ||
|
c1cb23d728 | ||
|
4007982db6 | ||
|
a9f5ed3869 | ||
|
08964d8548 | ||
|
8bb98d9ecc | ||
|
fe3c080991 | ||
|
5186ee6e43 | ||
|
c2fc9fe0ee | ||
|
280d3f22a7 | ||
|
a19ca8a820 | ||
|
7ba1116349 | ||
|
e8862b3aaa | ||
|
a96cc19eb6 | ||
|
3d975b7fba | ||
|
d54571d0a6 | ||
|
92fe70c15c | ||
|
75071cf1d9 | ||
|
4bd538e448 | ||
|
0956baecf9 | ||
|
e4968c4119 | ||
|
283e10dfef | ||
|
1c43f92e49 | ||
|
edf4841371 | ||
|
40446c7a31 | ||
|
76ed775f6f | ||
|
ca7796114c | ||
|
ed822becc6 | ||
|
7057b2970b | ||
|
62791e4b36 | ||
|
237cb63fc2 | ||
|
42ab7f1b4f | ||
|
8e11ba21ed | ||
|
24a9ddaa5e | ||
|
6190fb3511 | ||
|
2d9043fbed | ||
|
682dff9c1c | ||
|
9339b7e31d | ||
|
7667ef686d | ||
|
4d4fe687ac | ||
|
7152dead1d | ||
|
40b9f03132 | ||
|
19d421df84 | ||
|
c889deaab1 | ||
|
416f57b1d7 | ||
|
dda2685bd8 | ||
|
b43f3b3b6a | ||
|
a0c8a8e97c | ||
|
28bfea6af0 | ||
|
f3bc39a0c5 | ||
|
be1e7ee9a9 | ||
|
e817844c5d | ||
|
c7efd1feb9 | ||
|
bf6f60c7e5 | ||
|
b998718142 | ||
|
c31d368d0d | ||
|
5237eb0638 | ||
|
7869d731d4 | ||
|
c603ec0b38 | ||
|
555bf1f0ae | ||
|
8bdf384563 | ||
|
19524eaa82 | ||
|
9bbae825e2 | ||
|
3e9cb987a1 | ||
|
dacb9cd86c | ||
|
b9d7333998 | ||
|
e14b507b27 | ||
|
139c3fdd19 | ||
|
431ac5aa2d | ||
|
78fe7e5c16 | ||
|
c2c9e37a36 | ||
|
5d3682cd44 | ||
|
2a19726e49 | ||
|
c08c652080 | ||
|
9089c54990 | ||
|
679d9bae1c | ||
|
19315fc65e | ||
|
770041eceb | ||
|
1161dcb299 | ||
|
fa7b0a24a7 | ||
|
48354c7793 | ||
|
24de6c0101 | ||
|
fcd9fe7d5a | ||
|
a36d5684b8 | ||
|
be20f9b455 | ||
|
dd150c6d7e | ||
|
bd5ac514ef | ||
|
bd926fa74b | ||
|
167144b504 | ||
|
5faaabf2f4 | ||
|
1933fc948c | ||
|
83df430d17 | ||
|
ec60d7d0b6 | ||
|
f9ccb0e8de | ||
|
1109d9f88a | ||
|
32b7cc64fb | ||
|
a6724b5f75 | ||
|
8a35bfcc31 | ||
|
0c037184f8 | ||
|
3e563a37a2 | ||
|
efec711ced | ||
|
e5cbf9e3a3 | ||
|
cafe86e675 | ||
|
a911492a9e | ||
|
d889598b20 | ||
|
c4577f28b2 | ||
|
f5af15454e | ||
|
ee96d5c68f | ||
|
6c56b5f45b | ||
|
1058bfecf4 | ||
|
f0afd5ceea | ||
|
9881c9f61c | ||
|
89a7ec6d4b | ||
|
c426364618 | ||
|
cc5264a587 | ||
|
131afcebf1 | ||
|
42bc4d2445 | ||
|
2cc5d46cd3 | ||
|
97c3e50e7d | ||
|
3feb67ad32 | ||
|
7af82af935 | ||
|
4a3f0c8898 | ||
|
aa6c7afbbd | ||
|
c6ba296028 | ||
|
51b86e21f6 | ||
|
04914be442 | ||
|
3133935063 | ||
|
088608011b | ||
|
6d0f9baba4 | ||
|
3b21400bb8 | ||
|
1c3a279b8a | ||
|
6236b01189 | ||
|
e42906f08a | ||
|
b53ba2b98e | ||
|
7bd8d54d5c | ||
|
8f5a11493b | ||
|
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 | ||
|
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 | ||
|
1a9b0265dc | ||
|
4f5632b916 | ||
|
8e6e6736a3 | ||
|
804afc9a1d | ||
|
bcd86977d2 | ||
|
a8b5a5227f | ||
|
d2398a7abb | ||
|
0e908ad882 | ||
|
7620aa4264 | ||
|
c0a83d1916 | ||
|
920856512e | ||
|
62b703ca88 | ||
|
d7f7aa09fc | ||
|
b125b47366 | ||
|
bc6debea89 | ||
|
d5523b18b9 | ||
|
1f69c7e992 | ||
|
d9757cc660 | ||
|
1cb3522e73 | ||
|
7583b0a358 | ||
|
77863e2e88 | ||
|
564404d4ae | ||
|
e2320cd3b2 | ||
|
fd92d6559c | ||
|
6146925757 | ||
|
baef9f5aa7 | ||
|
ae6de8fdf1 | ||
|
b888d13e62 | ||
|
1070c23608 | ||
|
e8d084b855 | ||
|
5b278f704c | ||
|
a87e44bae4 | ||
|
85bc5f54aa | ||
|
41f46d0810 | ||
|
be3bfe7e5e | ||
|
9ce1222fd0 | ||
|
8fb3c68573 | ||
|
eb7ee49096 | ||
|
f960cf2ce9 | ||
|
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 | ||
|
7d63135cc2 | ||
|
48354721a2 | ||
|
82b21e6a09 | ||
|
9216eed1b8 | ||
|
c81c5c4801 | ||
|
14bf0038a9 | ||
|
a8f2fd3f4b | ||
|
7223959fda | ||
|
cf5d112e31 | ||
|
b24608891e | ||
|
579efb016a | ||
|
10a5b35217 | ||
|
68d0aa7071 | ||
|
69bc13dd77 | ||
|
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 | ||
|
03e89743b4 | ||
|
8dff0b2c5d | ||
|
a713b97e36 | ||
|
b6acc8da70 | ||
|
ba11ca0e9d | ||
|
b8c89325bc | ||
|
b99cdf7367 | ||
|
60ce351a27 | ||
|
413a55623e | ||
|
5b2f95d270 | ||
|
44604c2509 | ||
|
bf2a7c2efd | ||
|
ba5c42cc51 | ||
|
cf2ea0f51c | ||
|
9df002fe4e | ||
|
1a191c7d51 | ||
|
7ca57d918e | ||
|
fe40e74809 | ||
|
daac2e2a1c | ||
|
b88ec407a3 | ||
|
8e9e4215ce | ||
|
4dd83c29fe | ||
|
6020f423f4 | ||
|
99bea8f7c3 | ||
|
d1e2d06538 | ||
|
ccf5d759a4 | ||
|
3ce8deec07 | ||
|
812b1f7baa | ||
|
f2cb6ed82c | ||
|
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 | ||
|
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 | ||
|
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 | ||
|
8c98125755 | ||
|
997101a44b |
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
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
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
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
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,10 +1,10 @@
|
|||||||
### Pull Request Checklist
|
### 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
|
- [ ] UI change has been tested on both light and dark themes
|
||||||
- [ ] Pull request is based on the develop branch
|
- [ ] 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 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)
|
- [ ] 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
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
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
11
.idea/codeStyles/Project.xml
generated
@@ -4,7 +4,16 @@
|
|||||||
<JetCodeStyleSettings>
|
<JetCodeStyleSettings>
|
||||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||||
<value>
|
<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>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
|
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
|
||||||
|
5
.idea/dictionaries/bmarty.xml
generated
5
.idea/dictionaries/bmarty.xml
generated
@@ -14,6 +14,7 @@
|
|||||||
<w>gplay</w>
|
<w>gplay</w>
|
||||||
<w>hmac</w>
|
<w>hmac</w>
|
||||||
<w>homeserver</w>
|
<w>homeserver</w>
|
||||||
|
<w>jitsi</w>
|
||||||
<w>ktlint</w>
|
<w>ktlint</w>
|
||||||
<w>linkified</w>
|
<w>linkified</w>
|
||||||
<w>linkify</w>
|
<w>linkify</w>
|
||||||
@@ -23,12 +24,16 @@
|
|||||||
<w>pbkdf</w>
|
<w>pbkdf</w>
|
||||||
<w>pids</w>
|
<w>pids</w>
|
||||||
<w>pkcs</w>
|
<w>pkcs</w>
|
||||||
|
<w>previewable</w>
|
||||||
|
<w>previewables</w>
|
||||||
<w>riotx</w>
|
<w>riotx</w>
|
||||||
<w>signin</w>
|
<w>signin</w>
|
||||||
<w>signout</w>
|
<w>signout</w>
|
||||||
<w>signup</w>
|
<w>signup</w>
|
||||||
<w>ssss</w>
|
<w>ssss</w>
|
||||||
|
<w>sygnal</w>
|
||||||
<w>threepid</w>
|
<w>threepid</w>
|
||||||
|
<w>unpublish</w>
|
||||||
<w>unwedging</w>
|
<w>unwedging</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
22
AUTHORS.md
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:
|
# 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.
|
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)
|
[@benoit.marty:matrix.org](https://matrix.to/#/@benoit.marty:matrix.org)
|
||||||
- Android team leader and project leader, Android developer, GitHub community manager.
|
- 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.
|
- Reviewing and polishing developed features, code quality manager, PRs reviewer, GitHub community manager.
|
||||||
- Release manager on the Play Store
|
- 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)
|
[@ganfra:matrix.org](https://matrix.to/#/@ganfra:matrix.org)
|
||||||
- Software architect, Android developer
|
- 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.
|
- Work mainly on the global architecture of the project.
|
||||||
- Specialist of the timeline, and lots of other features.
|
- 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)
|
[@valere35:matrix.org](https://matrix.to/#/@valere35:matrix.org)
|
||||||
- Product manager, Android developer
|
- Product manager, Android developer
|
||||||
- Specialist on the crypto implementation.
|
- 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
|
# 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!
|
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)
|
||||||
|
594
CHANGES.md
594
CHANGES.md
@@ -1,12 +1,591 @@
|
|||||||
Changes in RiotX 0.23.0 (2020-XX-XX)
|
Changes in Element 1.0.18 (2021-XX-XX)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
|
Features ✨:
|
||||||
|
- VoIP : support for VoIP V1 protocol, transfer call and dial-pad
|
||||||
|
|
||||||
|
Improvements 🙌:
|
||||||
|
- VoIP : new tiles in timeline
|
||||||
|
- Improve room profile UX
|
||||||
|
- Upgrade Jitsi library from 2.9.3 to 3.1.0
|
||||||
|
- a11y improvements
|
||||||
|
|
||||||
|
Bugfix 🐛:
|
||||||
|
- VoIP : fix audio devices output
|
||||||
|
- Fix crash after initial sync on Dendrite
|
||||||
|
- Fix crash reported by PlayStore (#2707)
|
||||||
|
|
||||||
|
Translations 🗣:
|
||||||
|
-
|
||||||
|
|
||||||
|
SDK API changes ⚠️:
|
||||||
|
-
|
||||||
|
|
||||||
|
Build 🧱:
|
||||||
|
-
|
||||||
|
|
||||||
|
Test:
|
||||||
|
-
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
- New Dev Tools panel for developers
|
||||||
|
- Fix typos in CHANGES.md (#2811)
|
||||||
|
|
||||||
|
Changes in Element 1.0.17 (2021-02-09)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Improvements 🙌:
|
||||||
|
- Create a WidgetItemFactory and use it for better rendering of Jitsi widget change (video conference)
|
||||||
|
- Open image from URL Preview (#2705)
|
||||||
|
|
||||||
|
Bugfix 🐛:
|
||||||
|
- Bug in WidgetContent.computeURL() (#2767)
|
||||||
|
- Duplicate thumbs | Mobile reactions for 👍 and 👎 are not the same as web (#2776)
|
||||||
|
- Join room by alias other federation error (#2778)
|
||||||
|
- HTML unescaping for URL preview (#2766)
|
||||||
|
- URL preview on reply fallback (#2756)
|
||||||
|
- RTL: some arrows should be rotated in RTL (#2757)
|
||||||
|
- Properly delete objects from Realm DB (#2765)
|
||||||
|
|
||||||
|
Build 🧱:
|
||||||
|
- Upgrade build tools
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
- Change app name from "Element (Riot.im)" to "Element"
|
||||||
|
|
||||||
|
Changes in Element 1.0.16 (2021-02-04)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Bugfix 🐛:
|
||||||
|
- Fix crash on API < 30 and light theme (#2774)
|
||||||
|
|
||||||
|
Changes in Element 1.0.15 (2021-02-03)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features ✨:
|
||||||
|
- Social Login support
|
||||||
|
|
||||||
|
Improvements 🙌:
|
||||||
|
- SSO support for cross signing (#1062)
|
||||||
|
- Deactivate account when logged in with SSO (#1264)
|
||||||
|
- SSO UIA doesn't work (#2754)
|
||||||
|
|
||||||
|
Bugfix 🐛:
|
||||||
|
- Fix clear cache issue: sometimes, after a clear cache, there is still a token, so the init sync service is not started.
|
||||||
|
- Sidebar too large in horizontal orientation or tablets (#475)
|
||||||
|
- UrlPreview should be updated when the url is edited and changed (#2678)
|
||||||
|
- When receiving a new pepper from identity server, use it on the next hash lookup (#2708)
|
||||||
|
- Crashes reported by PlayStore (new in 1.0.14) (#2707)
|
||||||
|
- Widgets: Support $matrix_widget_id parameter (#2748)
|
||||||
|
- Data for Worker overload (#2721)
|
||||||
|
- Fix multiple tasks
|
||||||
|
- Object deletion in database is not complete (#2759)
|
||||||
|
|
||||||
|
SDK API changes ⚠️:
|
||||||
|
- Increase targetSdkVersion to 30 (#2600)
|
||||||
|
|
||||||
|
Build 🧱:
|
||||||
|
- Compile with Android SDK 30 (Android 11)
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
- Update Dagger to 2.31 version so we can use the embedded AssistedInject feature
|
||||||
|
|
||||||
|
Changes in Element 1.0.14 (2021-01-15)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
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 ✨:
|
Features ✨:
|
||||||
- Call with WebRTC support (##611)
|
- Call with WebRTC support (##611)
|
||||||
- Add capability to change the display name (#1529)
|
- Add capability to change the display name (#1529)
|
||||||
|
|
||||||
Improvements 🙌:
|
Improvements 🙌:
|
||||||
- "Add Matrix app" menu is now always visible (#1495)
|
- "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 🐛:
|
Bugfix 🐛:
|
||||||
- Fix dark theme issue on login screen (#1097)
|
- Fix dark theme issue on login screen (#1097)
|
||||||
@@ -14,12 +593,8 @@ Bugfix 🐛:
|
|||||||
- User could not redact message that they have sent (#1543)
|
- User could not redact message that they have sent (#1543)
|
||||||
- Use vendor prefix for non merged MSC (#1537)
|
- Use vendor prefix for non merged MSC (#1537)
|
||||||
- Compress images before sending (#1333)
|
- Compress images before sending (#1333)
|
||||||
|
- Searching by displayname is case sensitive (#1468)
|
||||||
Translations 🗣:
|
- Fix layout overlap issue (#1407)
|
||||||
-
|
|
||||||
|
|
||||||
SDK API changes ⚠️:
|
|
||||||
-
|
|
||||||
|
|
||||||
Build 🧱:
|
Build 🧱:
|
||||||
- Enable code optimization (Proguard)
|
- Enable code optimization (Proguard)
|
||||||
@@ -627,7 +1202,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 (2021-XX-XX)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Features ✨:
|
Features ✨:
|
||||||
@@ -648,5 +1223,8 @@ SDK API changes ⚠️:
|
|||||||
Build 🧱:
|
Build 🧱:
|
||||||
-
|
-
|
||||||
|
|
||||||
|
Test:
|
||||||
|
-
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
-
|
||||||
|
@@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md
|
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.
|
Android support can be found in this [](https://matrix.to/#/#element-android:matrix.org) room.
|
||||||
|
|
||||||
Dedicated room for RiotX: [](https://matrix.to/#/#riotx:matrix.org)
|
|
||||||
|
|
||||||
# Specific rules for Matrix Android projects
|
# Specific rules for Matrix Android projects
|
||||||
|
|
||||||
@@ -37,14 +35,12 @@ Note that if the templates are modified, the only things to do is to restart And
|
|||||||
|
|
||||||
## Compilation
|
## 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 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/).
|
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/).
|
||||||
|
|
||||||
For the moment, Strings from Riot will be used, there is no dedicated project in Weblate for RiotX.
|
|
||||||
|
|
||||||
## I want to submit a PR to fix an issue
|
## I want to submit a PR to fix an issue
|
||||||
|
|
||||||
@@ -101,7 +97,7 @@ Make sure the following commands execute without any error:
|
|||||||
|
|
||||||
### Tests
|
### 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.
|
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.
|
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.
|
||||||
@@ -120,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.
|
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).
|
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
|
### Authors
|
||||||
|
|
||||||
|
40
README.md
40
README.md
@@ -1,38 +1,34 @@
|
|||||||
[](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
|
[](https://buildkite.com/matrix-dot-org/element-android/builds?branch=develop)
|
||||||
[](https://translate.riot.im/engage/riot-android/?utm_source=widget)
|
[](https://translate.element.io/engage/element-android/?utm_source=widget)
|
||||||
[](https://matrix.to/#/#riotx:matrix.org)
|
[](https://matrix.to/#/#element-android:matrix.org)
|
||||||
[](https://sonarcloud.io/dashboard?id=vector.android.riotx)
|
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
||||||
[](https://sonarcloud.io/dashboard?id=vector.android.riotx)
|
[](https://sonarcloud.io/dashboard?id=im.vector.app.android)
|
||||||
[](https://sonarcloud.io/dashboard?id=vector.android.riotx)
|
[](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="resources/img/google-play-badge.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=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.riotx)
|
[<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
|
# 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
|
# Roadmap
|
||||||
|
|
||||||
The current target is to release an application out of beta with the same level of features (and even more) as Riot.
|
The version 1.0.0 of Element still misses some features which was previously included in Riot-Android.
|
||||||
The roadmap has 3 phases:
|
The team will work to add them on a regular basis.
|
||||||
|
|
||||||
- [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
|
|
||||||
|
|
||||||
|
|
||||||
## Contributing
|
## 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
1
attachment-viewer/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/build
|
75
attachment-viewer/build.gradle
Normal file
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 30
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 21
|
||||||
|
targetSdkVersion 30
|
||||||
|
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
0
attachment-viewer/consumer-rules.pro
Normal file
21
attachment-viewer/proguard-rules.pro
vendored
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
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,380 @@
|
|||||||
|
/*
|
||||||
|
* 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.Build
|
||||||
|
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.WindowInsets
|
||||||
|
import android.view.WindowInsetsController
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
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)
|
||||||
|
|
||||||
|
setDecorViewFullScreen()
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
private fun setDecorViewFullScreen() {
|
||||||
|
// This is important for the dispatchTouchEvent, if not we must correct
|
||||||
|
// the touch coordinates
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
// New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
|
window.setDecorFitsSystemWindows(false)
|
||||||
|
// New API instead of SYSTEM_UI_FLAG_IMMERSIVE
|
||||||
|
window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
|
||||||
|
// New API instead of FLAG_TRANSLUCENT_STATUS
|
||||||
|
window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
|
||||||
|
// new API instead of FLAG_TRANSLUCENT_NAVIGATION
|
||||||
|
window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
|
||||||
|
} else {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
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
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
// New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
|
window.setDecorFitsSystemWindows(false)
|
||||||
|
// new API instead of SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||||
|
window.decorView.windowInsetsController?.hide(WindowInsets.Type.navigationBars())
|
||||||
|
// New API instead of SYSTEM_UI_FLAG_IMMERSIVE
|
||||||
|
window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
|
||||||
|
// New API instead of FLAG_TRANSLUCENT_STATUS
|
||||||
|
window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
|
||||||
|
// New API instead of FLAG_TRANSLUCENT_NAVIGATION
|
||||||
|
window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
|
||||||
|
} else {
|
||||||
|
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.
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
private fun showSystemUI() {
|
||||||
|
systemUiVisibility = true
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||||
|
// New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
|
window.setDecorFitsSystemWindows(false)
|
||||||
|
} else {
|
||||||
|
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>
|
6
attachment-viewer/src/main/res/values/colors.xml
Normal file
6
attachment-viewer/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<color name="half_transparent_status_bar">#80000000</color>
|
||||||
|
|
||||||
|
</resources>
|
50
build.gradle
50
build.gradle
@@ -1,7 +1,9 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.50'
|
// Ref: https://kotlinlang.org/releases.html
|
||||||
|
ext.kotlin_version = '1.4.21'
|
||||||
|
ext.kotlin_coroutines_version = "1.4.1"
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
@@ -10,12 +12,11 @@ buildscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.5.3'
|
classpath 'com.android.tools.build:gradle:4.1.2'
|
||||||
classpath 'com.google.gms:google-services:4.3.2'
|
classpath 'com.google.gms:google-services:4.3.5'
|
||||||
classpath "com.airbnb.okreplay:gradle-plugin:1.5.0"
|
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
|
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
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
@@ -38,6 +39,14 @@ allprojects {
|
|||||||
includeGroupByRegex "com\\.github\\.yalantis"
|
includeGroupByRegex "com\\.github\\.yalantis"
|
||||||
// JsonViewer
|
// JsonViewer
|
||||||
includeGroupByRegex 'com\\.github\\.BillCarsonFr'
|
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 {
|
maven {
|
||||||
@@ -47,15 +56,21 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
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-3.1.0"
|
||||||
|
// Note: to test Jitsi release you can use a local file like this:
|
||||||
|
// url "file:///Users/bmarty/workspaces/jitsi_libre_maven/android-sdk-3.1.0"
|
||||||
|
}
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
||||||
// Warnings are potential errors, so stop ignoring them
|
// 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) {
|
task clean(type: Delete) {
|
||||||
@@ -70,15 +85,15 @@ apply plugin: 'org.sonarqube'
|
|||||||
|
|
||||||
sonarqube {
|
sonarqube {
|
||||||
properties {
|
properties {
|
||||||
property "sonar.projectName", "RiotX-Android"
|
property "sonar.projectName", "Element-Android"
|
||||||
property "sonar.projectKey", "vector.android.riotx"
|
property "sonar.projectKey", "im.vector.app.android"
|
||||||
property "sonar.host.url", "https://sonarcloud.io"
|
property "sonar.host.url", "https://sonarcloud.io"
|
||||||
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
|
property "sonar.projectVersion", project(":vector").android.defaultConfig.versionName
|
||||||
property "sonar.sourceEncoding", "UTF-8"
|
property "sonar.sourceEncoding", "UTF-8"
|
||||||
property "sonar.links.homepage", "https://github.com/vector-im/riotX-android/"
|
property "sonar.links.homepage", "https://github.com/vector-im/element-android/"
|
||||||
property "sonar.links.ci", "https://buildkite.com/matrix-dot-org/riotx-android"
|
property "sonar.links.ci", "https://buildkite.com/matrix-dot-org/element-android"
|
||||||
property "sonar.links.scm", "https://github.com/vector-im/riotX-android/"
|
property "sonar.links.scm", "https://github.com/vector-im/element-android/"
|
||||||
property "sonar.links.issue", "https://github.com/vector-im/riotX-android/issues"
|
property "sonar.links.issue", "https://github.com/vector-im/element-android/issues"
|
||||||
property "sonar.organization", "new_vector_ltd_organization"
|
property "sonar.organization", "new_vector_ltd_organization"
|
||||||
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
|
property "sonar.login", project.hasProperty("SONAR_LOGIN") ? SONAR_LOGIN : "invalid"
|
||||||
}
|
}
|
||||||
@@ -89,11 +104,18 @@ project(":vector") {
|
|||||||
properties {
|
properties {
|
||||||
property "sonar.sources", project(":vector").android.sourceSets.main.java.srcDirs
|
property "sonar.sources", project(":vector").android.sourceSets.main.java.srcDirs
|
||||||
// exclude source code from analyses separated by a colon (:)
|
// 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") {
|
//project(":matrix-sdk-android") {
|
||||||
// sonarqube {
|
// sonarqube {
|
||||||
// properties {
|
// properties {
|
||||||
|
285
docs/add_threePids.md
Normal file
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)
|
- 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)
|
- 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 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 "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 app can cancel a binding. Current data are erased from DB.
|
||||||
- The API (IdentityService) is improved.
|
- The API (IdentityService) is improved.
|
||||||
@@ -22,7 +22,7 @@ Difference though (list not exhaustive):
|
|||||||
|
|
||||||
Missing features (list not exhaustive):
|
Missing features (list not exhaustive):
|
||||||
- Invite by 3Pid (will be in a dedicated PR)
|
- 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)
|
- List email and phone of the account (could be done in a dedicated PR)
|
||||||
- Search contact (not P1)
|
- Search contact (not P1)
|
||||||
- Logout from identity server when user sign out or deactivate his account.
|
- 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.
|
- Default identity server URL, from Wellknown data is proposed to the user.
|
||||||
- Identity server can be set
|
- 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
|
- 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 when configuring the identity server.
|
||||||
- Terms of service can be accepted after, if they change.
|
- Terms of service can be accepted after, if they change.
|
||||||
|
82
docs/jitsi.md
Normal file
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-3.1.0`.
|
||||||
|
|
||||||
|
### 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-3.1.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
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 Jitsi Meet library in the file `./vector/build.gradle`. Currently we have this line:
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
implementation('org.jitsi.react:jitsi-meet-sdk:3.1.0')
|
||||||
|
```
|
||||||
|
|
||||||
|
- Update the dependency of the WebRTC library in the file `./vector/build.gradle`. Currently we have this line:
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
implementation('com.facebook.react:react-native-webrtc:1.87.3-jitsi-6624067@aar')
|
||||||
|
```
|
||||||
|
|
||||||
|
- 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-3.1.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
- Build the project and perform the sanity tests again.
|
||||||
|
|
||||||
|
- Update the file `/CHANGES.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
|
# Table of Contents
|
||||||
1. [Prerequisites Knowledge](#prerequisites-knowledge)
|
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)
|
* [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)
|
* [Push vs privacy, and mitigation](#push-vs-privacy-and-mitigation)
|
||||||
* [Background processing limitations](#background-processing-limitations)
|
* [Background processing limitations](#background-processing-limitations)
|
||||||
2. [RiotX Notification implementations](#riotx-notification-implementations)
|
2. [Element Notification implementations](#element-notification-implementations)
|
||||||
* [Requirements](#requirements)
|
* [Requirements](#requirements)
|
||||||
* [Foreground sync mode (Gplay & F-Droid)](#foreground-sync-mode-gplay-f-droid)
|
* [Foreground sync mode (Gplay & F-Droid)](#foreground-sync-mode-gplay-f-droid)
|
||||||
* [Push (FCM) received in background](#push-fcm-received-in-background)
|
* [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.
|
**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
|
## 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!
|
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
|
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.
|
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).
|
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?**
|
**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.
|
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)
|
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.
|
It is getting more and more complex to have reliable notifications when FCM is not used.
|
||||||
|
|
||||||
# RiotX Notification implementations
|
# Element Notification implementations
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
RiotX Android must work with and without FCM.
|
Element 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 Element 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)
|
* 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)
|
## 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.
|
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
|
## 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)).
|
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:**
|
**Google recommendations:**
|
||||||
> We recommend using FCM messages in combination with the WorkManager 1 or JobScheduler API
|
> 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
|
> 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
|
(Sync) ----> Homeserver
|
||||||
<----
|
<----
|
||||||
Display notification
|
Display notification
|
||||||
@@ -217,24 +217,24 @@ Homeserver ----> Sygnal ----> FCM ----> RiotX
|
|||||||
|
|
||||||
**Possible outcomes**
|
**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
|
* 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 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 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.
|
* 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
|
## 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:
|
Common errors (amoung several others) that can cause that:
|
||||||
* Google Play Services is outdated
|
* Google Play Services is outdated
|
||||||
* Google Play Service fails in someways with FCM servers (infamous `SERVICE_NOT_AVAILABLE`)
|
* 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.
|
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
|
## 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).
|
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).
|
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).
|
Note that foreground services require to put a notification informing the user that the app is doing something even if not launched).
|
||||||
|
|
||||||
|
@@ -8,7 +8,9 @@ This document describes the flow of signin to a homeserver, and also the flow wh
|
|||||||
|
|
||||||
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`)
|
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
|
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`
|
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
|
```json
|
||||||
{
|
{
|
||||||
@@ -73,14 +77,16 @@ We get credential (200)
|
|||||||
|
|
||||||
If the user has associated an email with its account, he can signin using the email.
|
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
|
```json
|
||||||
{
|
{
|
||||||
"identifier": {
|
"identifier": {
|
||||||
"type": "m.id.thirdparty",
|
"type": "m.id.thirdparty",
|
||||||
"medium": "email",
|
"medium": "email",
|
||||||
"address": "alice@yopmail.com"
|
"address": "alice@email-provider.org"
|
||||||
},
|
},
|
||||||
"password": "weak_password",
|
"password": "weak_password",
|
||||||
"type": "m.login.password",
|
"type": "m.login.password",
|
||||||
@@ -132,11 +138,13 @@ It's worth noting that the response from the homeserver contains the userId of A
|
|||||||
|
|
||||||
### Login with Msisdn
|
### Login with Msisdn
|
||||||
|
|
||||||
Not supported yet in RiotX
|
Not supported yet in Element
|
||||||
|
|
||||||
### Login with SSO
|
### 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
|
200
|
||||||
|
|
||||||
@@ -155,9 +163,9 @@ Not supported yet in RiotX
|
|||||||
|
|
||||||
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
|
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=riotx%3A%2F%2Friotx
|
> https://homeserver.with.sso/_matrix/client/r0/login/sso/redirect?redirectUrl=element%3A%2F%element
|
||||||
|
|
||||||
The parameter `redirectUrl` is set to `riotx://riotx`.
|
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)
|
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)
|
||||||
|
|
||||||
@@ -167,11 +175,13 @@ During the process, user may be asked to validate an email by clicking on a link
|
|||||||
|
|
||||||
Once the process is finished, the web page will call the `redirectUrl` with an extra parameter `loginToken`
|
Once the process is finished, the web page will call the `redirectUrl` with an extra parameter `loginToken`
|
||||||
|
|
||||||
> riotx://riotx?loginToken=MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy
|
> element://connect?loginToken=MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy
|
||||||
|
|
||||||
This navigation is intercepted by RiotX by the `LoginActivity`, which will then ask the homeserver to convert this `loginToken` to an access token
|
This navigation is intercepted by Element by the `LoginActivity`, which will then ask the homeserver to convert this `loginToken` to an access token
|
||||||
|
|
||||||
> curl -X POST --data $'{"type":"m.login.token","token":"MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy"}' 'https://homeserver.with.sso/_matrix/client/r0/login'
|
```shell script
|
||||||
|
curl -X POST --data $'{"type":"m.login.token","token":"MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy"}' 'https://homeserver.with.sso/_matrix/client/r0/login'
|
||||||
|
```
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -214,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
|
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
|
```json
|
||||||
{
|
{
|
||||||
@@ -251,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:
|
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
|
```json
|
||||||
{
|
{
|
||||||
@@ -285,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):
|
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
|
```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`)
|
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
|
```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.
|
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
|
```json
|
||||||
{
|
{
|
||||||
@@ -133,9 +137,11 @@ We get a 400:
|
|||||||
|
|
||||||
### Step 2: entering email
|
### 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
|
```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
|
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
|
```json
|
||||||
{
|
{
|
||||||
"client_secret": "53e679ea-oRED-ACTED-92b8-3012c49c6cfa",
|
"client_secret": "53e679ea-oRED-ACTED-92b8-3012c49c6cfa",
|
||||||
"email": "alice@yopmail.com",
|
"email": "alice@email-provider.org",
|
||||||
"send_attempt": 0
|
"send_attempt": 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -213,7 +221,9 @@ We request a token to the homeserver. The `client_secret` is generated by the ap
|
|||||||
|
|
||||||
And
|
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
|
```json
|
||||||
{
|
{
|
||||||
@@ -239,7 +249,9 @@ We get 401 since the email is not validated yet:
|
|||||||
|
|
||||||
The app is now polling on
|
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
|
```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
|
- A `token` vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ
|
||||||
- The `client_secret`: 53e679ea-oRED-ACTED-92b8-3012c49c6cfa
|
- The `client_secret`: 53e679ea-oRED-ACTED-92b8-3012c49c6cfa
|
||||||
- A `sid`: qlBCREDACTEDEtgxD
|
- 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
|
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
|
```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:
|
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
|
```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.
|
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
|
```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:
|
When we execute the register request, with the received `sid`, we 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'
|
|
||||||
|
|
||||||
|
```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
|
```json
|
||||||
"auth": {
|
"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:
|
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
|
```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
|
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
|
```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
|
```json
|
||||||
{
|
{
|
||||||
|
106
docs/ui-tests.md
Normal file
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)
|
||||||
|
}
|
||||||
|
```
|
@@ -1,3 +1,8 @@
|
|||||||
|
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 ║
|
║A] Placing a call offer ║
|
||||||
@@ -21,7 +26,7 @@
|
|||||||
│ │ │ │ │ mx event │ │ │ │
|
│ │ │ │ │ mx event │ │ │ │
|
||||||
│ │ │ └────────────────────┘ │ │ │ │
|
│ │ │ └────────────────────┘ │ │ │ │
|
||||||
│ │ │ │ │ │ │
|
│ │ │ │ │ │ │
|
||||||
│ Riot.im │ │ │ │ │ Riot.im │
|
│ Element │ │ │ │ │ Element │
|
||||||
┌──│ App │ │ │ │ │ App │
|
┌──│ App │ │ │ │ │ App │
|
||||||
│ │ │ │ │ │ │ │
|
│ │ │ │ │ │ │ │
|
||||||
│ │ │ │ │ │ │ │
|
│ │ │ │ │ │ │ │
|
||||||
@@ -98,7 +103,7 @@
|
|||||||
│ │ ┌────┐ │ │ └────────────────────┘ │ │ │
|
│ │ ┌────┐ │ │ └────────────────────┘ │ │ │
|
||||||
│ │ │ 3 │ │ ┌────────────────────┐ │ │ │ │
|
│ │ │ 3 │ │ ┌────────────────────┐ │ │ │ │
|
||||||
│ │──────┴────┴───────┼──────────────────┼─▶│ m.call.candidates │ │ │ │
|
│ │──────┴────┴───────┼──────────────────┼─▶│ m.call.candidates │ │ │ │
|
||||||
│ Riot.im │ │ │ mx event │ │ │ │ Riot.im │
|
│ Element │ │ │ mx event │ │ │ │ Element │
|
||||||
│ App │ │ │ └────────────────────┘ │ │ App │
|
│ App │ │ │ └────────────────────┘ │ │ App │
|
||||||
│ │ │ │ │ │ │
|
│ │ │ │ │ │ │
|
||||||
│ │ │ │ │ │ │
|
│ │ │ │ │ │ │
|
||||||
@@ -190,9 +195,9 @@
|
|||||||
│ │ │ m.call.invite │───┼────────────────────────────┬────┬───▶│ │
|
│ │ │ m.call.invite │───┼────────────────────────────┬────┬───▶│ │
|
||||||
┌─────────────────┐ │ │ mx event │ │ │ │ 1 │ │ │
|
┌─────────────────┐ │ │ mx event │ │ │ │ 1 │ │ │
|
||||||
│ │ │ │ └────────────────────┘ │ └────┘ │ │
|
│ │ │ │ └────────────────────┘ │ └────┘ │ │
|
||||||
│ │ │ ┌────────────────────┐ │ │ │ Riot.im │
|
│ │ │ ┌────────────────────┐ │ │ │ Element │
|
||||||
│ │ │ │ │ m.call.candidates │ │ │ App │
|
│ │ │ │ │ m.call.candidates │ │ │ App │
|
||||||
│ Riot.im │ │ │ mx event │ │ │ │ │
|
│ Element │ │ │ mx event │ │ │ │ │
|
||||||
│ App │ │ │ └────────────────────┘ │ │ │
|
│ App │ │ │ └────────────────────┘ │ │ │
|
||||||
│ │ │ ┌────────────────────┐◀──┼─────────────────┼───┬────┬───────────┤ │
|
│ │ │ ┌────────────────────┐◀──┼─────────────────┼───┬────┬───────────┤ │
|
||||||
│ │◀──────────────────┼──────────────────┼──│ m.call.answer │ │ │ 4 │ └──┬──────────────┘
|
│ │◀──────────────────┼──────────────────┼──│ m.call.answer │ │ │ 4 │ └──┬──────────────┘
|
||||||
@@ -270,7 +275,7 @@
|
|||||||
│ │ │ │ └────────────────────┘ │ │ │
|
│ │ │ │ └────────────────────┘ │ │ │
|
||||||
│ │ │ ┌────────────────────┐ │ │ │ │
|
│ │ │ ┌────────────────────┐ │ │ │ │
|
||||||
│ │ │ │ │ m.call.candidates │ │ │ │
|
│ │ │ │ │ m.call.candidates │ │ │ │
|
||||||
│ Riot.im │ │ │ mx event │ │ │ │ Riot.im │
|
│ Element │ │ │ mx event │ │ │ │ Element │
|
||||||
│ App │ │ │ └────────────────────┘ │ ┌────┐ │ App │
|
│ App │ │ │ └────────────────────┘ │ ┌────┐ │ App │
|
||||||
│ │ │ ┌────────────────────┐ │ │ │ 3 │ │ │
|
│ │ │ ┌────────────────────┐ │ │ │ 3 │ │ │
|
||||||
│ │◀──────────────────┼┐ │ │ m.call.answer │ │ ┌───────┴────┴────────│ │
|
│ │◀──────────────────┼┐ │ │ m.call.answer │ │ ┌───────┴────┴────────│ │
|
||||||
@@ -365,7 +370,7 @@
|
|||||||
│ │ │ │ │
|
│ │ │ │ │
|
||||||
│ │ │ │ │
|
│ │ │ │ │
|
||||||
│ │ │ │ │
|
│ │ │ │ │
|
||||||
│ Riot.im │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ Riot.im │
|
│ Element │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ Element │
|
||||||
│ App │ │ App │
|
│ App │ │ App │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
│ │ │ │
|
│ │ │ │
|
||||||
|
2
fastlane/metadata/android/ar/changelogs/40100100.txt
Normal file
2
fastlane/metadata/android/ar/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/ar/changelogs/40100110.txt
Normal file
2
fastlane/metadata/android/ar/changelogs/40100110.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
يحتوي هذا الإصدار الجديد بشكل أساسي على تحسينات في واجهة المستخدم وتجربة المستخدم. يُمكنك الآن دعوة الأصدقاء وإنشاء رسالة مُباشرة بسرعة كبيرة عن طريق مسح رموز الاستجابة السريعة.
|
||||||
|
سجل التعديل الكامل: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
2
fastlane/metadata/android/ar/changelogs/40100120.txt
Normal file
2
fastlane/metadata/android/ar/changelogs/40100120.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
التغييرات الرئيسة في هذا الإصدار: مُعاينة URL، لوحة مفاتيح Emoji جديدة، إمكانيات جديدة لإعدادات الغرفة والثلج لميلاد المسيح!
|
||||||
|
سجل التعديل الكامل: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
2
fastlane/metadata/android/ar/changelogs/40100130.txt
Normal file
2
fastlane/metadata/android/ar/changelogs/40100130.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
التغييرات الرئيسة في هذا الإصدار: مُعاينة URL، لوحة مفاتيح Emoji جديدة، إمكانيات جديدة لإعدادات الغرفة والثلج لميلاد المسيح!
|
||||||
|
سجل التعديل الكامل: https://github.com/vector-im/element-android/releases/tag/v1.0.13
|
2
fastlane/metadata/android/ar/changelogs/40100140.txt
Normal file
2
fastlane/metadata/android/ar/changelogs/40100140.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
التغييرات الرئيسة في هذا الإصدار: تحرير أذونات الغُرفة، السِّمة التلقائية الفاتحة/الداكنة، ومجموعة من إصلاحات الأخطاء.
|
||||||
|
سجل التعديل الكامل: https://github.com/vector-im/element-android/releases/tag/v1.0.14
|
2
fastlane/metadata/android/ar/changelogs/40100150.txt
Normal file
2
fastlane/metadata/android/ar/changelogs/40100150.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
التغييرات الرئيسة في هذا الإصدار: دعم تسجيل الدخول الاجتماعي.
|
||||||
|
سجل التعديل الكامل: https://github.com/vector-im/element-android/releases/tag/v1.0.15
|
2
fastlane/metadata/android/ar/changelogs/40100160.txt
Normal file
2
fastlane/metadata/android/ar/changelogs/40100160.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
التغييرات الرئيسة في هذا الإصدار: دعم تسجيل الدخول الاجتماعي.
|
||||||
|
سجل التعديل الكامل: https://github.com/vector-im/element-android/releases/tag/v1.0.15 and https://github.com/vector-im/element-android/releases/tag/v1.0.16
|
2
fastlane/metadata/android/ar/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/ar/changelogs/40100170.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
التغييرات الرئيسة في هذا الإصدار: إصلاحات الأخطاء!
|
||||||
|
سجل التعديل الكامل: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
31
fastlane/metadata/android/ar/full_description.txt
Normal file
31
fastlane/metadata/android/ar/full_description.txt
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
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 أو XMPP.
|
||||||
|
|
||||||
|
<b>الأمان-الخارق</b>: تشفير حقيقي من النهاية إلى النهاية (فقط أطراف المُحادثة مَن يُمكنهم فك تشفير الرسائل)، والتوقيع المُتبادل للتحقق من أجهزة المُشاركين في المُحادثة.
|
||||||
|
|
||||||
|
<b>التواصل الكامل</b>: المُراسلة، المُكالمات الصوتية والمرئية، مُشاركة الملفات، مُشاركة الشاشة، مجموعة كاملة وكبيرة من عمليات التكامُل، الروبوتات والأدوات. بناء الغُرف، المُجتمعات، ابق على اتصال وأنجز المهام.
|
||||||
|
|
||||||
|
<b>أين ما كُنت</b>: ابق على اتصال أينما كنت مع سجل الرسائل المتزامن بالكامل عبر جميع أجهزتك وفي الويب على https://app.element.io.
|
1
fastlane/metadata/android/ar/short_description.txt
Normal file
1
fastlane/metadata/android/ar/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
مُحادثة آمنة لا مركزية و VoIP. حافظ على بياناتك آمنة من الأطراف الثالثة.
|
1
fastlane/metadata/android/ar/title.txt
Normal file
1
fastlane/metadata/android/ar/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Element (سابقاً Riot.im)
|
30
fastlane/metadata/android/bg/full_description.txt
Normal file
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
1
fastlane/metadata/android/bg/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Сигурен децентрализиран чат и VoIP. Пазете данните си от външни лица.
|
1
fastlane/metadata/android/bg/title.txt
Normal file
1
fastlane/metadata/android/bg/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Element (предишен Riot.im)
|
2
fastlane/metadata/android/ca/changelogs/40100100.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Aquesta nova versió principalment conté correccions d'errors i millores. Ara, enviar un missatge és molt més ràpid.
|
||||||
|
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/ca/changelogs/40100110.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40100110.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Aquesta principalment conté millores d'interfície experiència d'usuari. Ara pots convidar amics i crear xats personals ràpidament escanejant codis QR.
|
||||||
|
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
2
fastlane/metadata/android/ca/changelogs/40100120.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40100120.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Canvis principals d'aquesta versió: previsualització d'URL, nou teclat d'emoticones, noves funcions de configuració de les sales i neu pel Nadal!
|
||||||
|
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
2
fastlane/metadata/android/ca/changelogs/40100130.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40100130.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Canvis principals d'aquesta versió: previsualització d'URL, nou teclat d'emoticones, noves funcions de configuració de les sales i neu pel Nadal!
|
||||||
|
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.0.13
|
2
fastlane/metadata/android/ca/changelogs/40100140.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40100140.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Canvis principals d'aquesta versió: modificació dels permisos de sala, tema clar/fosc automàtic, correcció d'errors.
|
||||||
|
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.0.14
|
2
fastlane/metadata/android/ca/changelogs/40100150.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40100150.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Canvis principals d'aquesta versió: inici de sessió amb xarxes socials.
|
||||||
|
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.0.15
|
2
fastlane/metadata/android/ca/changelogs/40100160.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40100160.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Canvis principals d'aquesta versió: inici de sessió amb xarxes socials.
|
||||||
|
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.0.15 i https://github.com/vector-im/element-android/releases/tag/v1.0.16
|
2
fastlane/metadata/android/ca/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/ca/changelogs/40100170.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Canvis principals d'aquesta versió: correcció d'errors!
|
||||||
|
Registre de canvis complet: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
30
fastlane/metadata/android/ca/full_description.txt
Normal file
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
1
fastlane/metadata/android/ca/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Xats i VoIP segurs i descentralitzats. Protegeix les teves dades de tercers.
|
1
fastlane/metadata/android/ca/title.txt
Normal file
1
fastlane/metadata/android/ca/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Element (abans Riot.im)
|
2
fastlane/metadata/android/cs/changelogs/40100100.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Tato nová verze obsahuje hlavně opravy chyb a vylepšení. Odeslání zprávy je nyní mhohem rychlejší.
|
||||||
|
Plné znění změn: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/cs/changelogs/40100110.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40100110.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Tato nová verze obsahuje hlavně vylepšení v uživatelském rozhraní. Nyní můžete pozvat přátele a napsat DM velmi rychle skenem QR kódů.
|
||||||
|
Plné znění změn: https://github.com/vector-im/element-android/releases/tag/v1.0.11
|
2
fastlane/metadata/android/cs/changelogs/40100120.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40100120.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Hlavní změny v této verzi: Náhled URL, nová klávesice s Emoji, nové možnosti nastavení místností a sníh na vánoce!
|
||||||
|
Plné znění změn: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
2
fastlane/metadata/android/cs/changelogs/40100130.txt
Normal file
2
fastlane/metadata/android/cs/changelogs/40100130.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Hlavní změny v této verzi: Náhled URL, nová klávesice s Emoji, nové možnosti nastavení místností a sníh na vánoce!
|
||||||
|
Plné znění změn: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
30
fastlane/metadata/android/cs/full_description.txt
Normal file
30
fastlane/metadata/android/cs/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Element je nový typ aplikace pro výměnu zpráv a kolaboraci, která:
|
||||||
|
|
||||||
|
1. Vám dá moc zachovat si soukromí
|
||||||
|
2. Vás nechá komunikovat s kýmkoli v síti Matrix a dokonce dále integrací s aplikacemi jako Slack
|
||||||
|
3. Vás ochrání před inzercí, těžbou dat a uzavřenými zahradami
|
||||||
|
4. Vás zabezpečí šifrováním end-to-end s křížovým podepisováním pro ověření ostatních
|
||||||
|
|
||||||
|
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.
|
1
fastlane/metadata/android/cs/short_description.txt
Normal file
1
fastlane/metadata/android/cs/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Zabezpečený decentralizovaný chat & VoIP. Uchovejte svá data v bezpečí.
|
1
fastlane/metadata/android/cs/title.txt
Normal file
1
fastlane/metadata/android/cs/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Element (dříve Riot.im)
|
2
fastlane/metadata/android/de/changelogs/40100100.txt
Normal file
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
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
|
2
fastlane/metadata/android/de/changelogs/40100120.txt
Normal file
2
fastlane/metadata/android/de/changelogs/40100120.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Hauptänderungen in dieser Version: URL-Vorschau, neue Emoji-Tastatur, neue Raumeinstellungen und Schnee für Weihnachten!
|
||||||
|
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases/tag/v1.0.12
|
2
fastlane/metadata/android/de/changelogs/40100130.txt
Normal file
2
fastlane/metadata/android/de/changelogs/40100130.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Hauptänderungen in dieser Version: URL-Vorschau, neue Emoji-Tastatur, neue Raumeinstellungen und Schnee für Weihnachten!
|
||||||
|
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases/tag/v1.0.13
|
2
fastlane/metadata/android/de/changelogs/40100140.txt
Normal file
2
fastlane/metadata/android/de/changelogs/40100140.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Hauptänderungen in dieser Version: Bearbeiten von Raumberechtigungen, automatisches Hell/Dunkel-Design und eine Reihe von Fehlerkorrekturen.
|
||||||
|
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases/tag/v1.0.14
|
2
fastlane/metadata/android/de/changelogs/40100150.txt
Normal file
2
fastlane/metadata/android/de/changelogs/40100150.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Hauptänderungen in dieser Version: Unterstützung für soziale Anmeldungen.
|
||||||
|
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases/tag/v1.0.15
|
2
fastlane/metadata/android/de/changelogs/40100160.txt
Normal file
2
fastlane/metadata/android/de/changelogs/40100160.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Hauptänderungen in dieser Version: Unterstützung für soziale Anmeldungen.
|
||||||
|
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases/tag/v1.0.15 and https://github.com/vector-im/element-android/releases/tag/v1.0.16
|
2
fastlane/metadata/android/de/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/de/changelogs/40100170.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Hauptänderungen in dieser Version: Fehlerkorrekturen
|
||||||
|
Vollständiges Änderungsprotokoll: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
30
fastlane/metadata/android/de/full_description.txt
Normal file
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
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
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
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
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
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
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
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
|
2
fastlane/metadata/android/en-US/changelogs/40100150.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40100150.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Main changes in this version: Social Login support.
|
||||||
|
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.15
|
2
fastlane/metadata/android/en-US/changelogs/40100160.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40100160.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Main changes in this version: Social Login support.
|
||||||
|
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.15 and https://github.com/vector-im/element-android/releases/tag/v1.0.16
|
2
fastlane/metadata/android/en-US/changelogs/40100170.txt
Normal file
2
fastlane/metadata/android/en-US/changelogs/40100170.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Main changes in this version: Bug fixes!
|
||||||
|
Full changelog: https://github.com/vector-im/element-android/releases/tag/v1.0.17
|
30
fastlane/metadata/android/en-US/full_description.txt
Normal file
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
BIN
fastlane/metadata/android/en-US/images/featureGraphic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
fastlane/metadata/android/en-US/images/icon.png
Normal file
BIN
fastlane/metadata/android/en-US/images/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
BIN
fastlane/metadata/android/en-US/images/phoneScreenshots/1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 131 KiB |
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user