mirror of
https://github.com/vector-im/riotX-android
synced 2025-10-06 00:02:48 +02:00
Compare commits
612 Commits
v1.0.10
...
feature/fi
Author | SHA1 | Date | |
---|---|---|---|
|
6c91fa54e7 | ||
|
7249c7d25a | ||
|
6e8d93bc6f | ||
|
78c1a0acf4 | ||
|
4f59ec37ca | ||
|
c34fea2932 | ||
|
c11a50f7ff | ||
|
b475f36b5a | ||
|
11367488e6 | ||
|
a7d8e74468 | ||
|
a25b93197d | ||
|
05013d2559 | ||
|
3240cadb94 | ||
|
3ea3d0fc91 | ||
|
f1f1613f00 | ||
|
68dd206140 | ||
|
17e8581ef0 | ||
|
7ff45738e0 | ||
|
c9eacec449 | ||
|
3e78098c43 | ||
|
cc01f25d8f | ||
|
9f3176c49c | ||
|
7ae2b34a9e | ||
|
d1bec21759 | ||
|
073e6227d6 | ||
|
6c4836e27e | ||
|
36a553a886 | ||
|
13938f2ab3 | ||
|
a755536a2f | ||
|
526320f4e3 | ||
|
5c67b3b216 | ||
|
4a5dbde8d3 | ||
|
5744939c05 | ||
|
9da3eec64f | ||
|
621c6c8773 | ||
|
d5e76c515e | ||
|
9fcf7263b5 | ||
|
0059fdf174 | ||
|
3d291c04c9 | ||
|
ca4b91a98f | ||
|
b0ba62aa31 | ||
|
abf763f454 | ||
|
15597eb041 | ||
|
00b16db7cc | ||
|
ff8a208012 | ||
|
7732bd47ce | ||
|
42a5680374 | ||
|
5d8f365520 | ||
|
938cd32ddd | ||
|
80396fcd39 | ||
|
7b97981bb5 | ||
|
b263273c87 | ||
|
427dc784fe | ||
|
7e4725c091 | ||
|
9b332f7a32 | ||
|
2b780a8b76 | ||
|
d03521d153 | ||
|
d520f7a5d4 | ||
|
0518e5f18d | ||
|
2fe7caa580 | ||
|
d53650c8ae | ||
|
930b8da3b3 | ||
|
c48f153b0d | ||
|
68cd06f1fb | ||
|
c7afcf4ff2 | ||
|
3491774e7b | ||
|
ea6fde3ed0 | ||
|
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 | ||
|
91c86c1a45 | ||
|
5541c2e190 | ||
|
f2ba236130 | ||
|
4cb7754b77 | ||
|
3473a7ef5e | ||
|
c9535509e8 | ||
|
3d578c147c | ||
|
43ac66feb3 | ||
|
5e2f091ec1 | ||
|
752bde413d | ||
|
e6949c85fb | ||
|
c1cb23d728 | ||
|
4007982db6 | ||
|
a9f5ed3869 | ||
|
08964d8548 | ||
|
5186ee6e43 | ||
|
c2fc9fe0ee | ||
|
280d3f22a7 | ||
|
a19ca8a820 | ||
|
7ba1116349 | ||
|
e8862b3aaa | ||
|
a96cc19eb6 | ||
|
3d975b7fba | ||
|
d54571d0a6 | ||
|
75071cf1d9 | ||
|
4bd538e448 | ||
|
0956baecf9 | ||
|
e4968c4119 | ||
|
283e10dfef | ||
|
1c43f92e49 | ||
|
ca7796114c | ||
|
ed822becc6 | ||
|
7057b2970b | ||
|
62791e4b36 | ||
|
237cb63fc2 | ||
|
42ab7f1b4f | ||
|
8e11ba21ed | ||
|
24a9ddaa5e | ||
|
6190fb3511 | ||
|
2d9043fbed | ||
|
682dff9c1c | ||
|
9339b7e31d | ||
|
7667ef686d | ||
|
4d4fe687ac | ||
|
7152dead1d | ||
|
40b9f03132 | ||
|
19d421df84 | ||
|
c889deaab1 | ||
|
416f57b1d7 | ||
|
dda2685bd8 | ||
|
b43f3b3b6a | ||
|
a0c8a8e97c | ||
|
28bfea6af0 | ||
|
f3bc39a0c5 | ||
|
c7efd1feb9 | ||
|
c31d368d0d | ||
|
5237eb0638 | ||
|
7869d731d4 | ||
|
c603ec0b38 | ||
|
555bf1f0ae | ||
|
8bdf384563 | ||
|
19524eaa82 | ||
|
9bbae825e2 | ||
|
3e9cb987a1 | ||
|
dacb9cd86c | ||
|
b9d7333998 | ||
|
e14b507b27 | ||
|
431ac5aa2d | ||
|
78fe7e5c16 | ||
|
c2c9e37a36 | ||
|
5d3682cd44 | ||
|
2a19726e49 | ||
|
c08c652080 | ||
|
9089c54990 | ||
|
679d9bae1c | ||
|
19315fc65e | ||
|
770041eceb | ||
|
1161dcb299 | ||
|
fa7b0a24a7 | ||
|
48354c7793 | ||
|
fcd9fe7d5a | ||
|
a36d5684b8 | ||
|
be20f9b455 | ||
|
dd150c6d7e | ||
|
bd5ac514ef | ||
|
bd926fa74b | ||
|
167144b504 | ||
|
5faaabf2f4 | ||
|
1933fc948c | ||
|
83df430d17 | ||
|
ec60d7d0b6 | ||
|
f9ccb0e8de | ||
|
1109d9f88a | ||
|
32b7cc64fb | ||
|
a6724b5f75 | ||
|
8a35bfcc31 | ||
|
0c037184f8 | ||
|
3e563a37a2 | ||
|
e5cbf9e3a3 | ||
|
cafe86e675 | ||
|
a911492a9e | ||
|
d889598b20 | ||
|
c4577f28b2 | ||
|
f5af15454e | ||
|
ee96d5c68f | ||
|
6c56b5f45b | ||
|
1058bfecf4 | ||
|
f0afd5ceea | ||
|
9881c9f61c | ||
|
89a7ec6d4b | ||
|
c426364618 | ||
|
cc5264a587 | ||
|
42bc4d2445 | ||
|
2cc5d46cd3 | ||
|
3feb67ad32 | ||
|
aa6c7afbbd | ||
|
c6ba296028 | ||
|
51b86e21f6 | ||
|
04914be442 | ||
|
3133935063 | ||
|
088608011b | ||
|
6d0f9baba4 | ||
|
3b21400bb8 | ||
|
1c3a279b8a | ||
|
6236b01189 | ||
|
e42906f08a | ||
|
b53ba2b98e | ||
|
7bd8d54d5c | ||
|
c785ea63e7 | ||
|
b78f1dbb93 | ||
|
056b9df65e | ||
|
589c301606 | ||
|
476f721f5e | ||
|
a813610c04 | ||
|
41dd67f1c1 | ||
|
63b068f426 | ||
|
637c54073a | ||
|
4171311095 | ||
|
bb5d5ffc92 | ||
|
d07a95204b | ||
|
2736247d09 | ||
|
93ffb116b7 | ||
|
396dd5e36e | ||
|
096abd7ebf | ||
|
694397efc1 | ||
|
ffe9a03d3e | ||
|
b2556cb293 | ||
|
c029564590 | ||
|
0cfea40b24 | ||
|
9c53f0f881 | ||
|
50ddd3cf31 | ||
|
6c7eb6ea8c | ||
|
412fc78c9a | ||
|
0da0857970 | ||
|
90e0006cae | ||
|
a570528f6c | ||
|
2d4cbde72c | ||
|
f5ae95d7f1 | ||
|
c5e6e004dd | ||
|
d9c209aa87 | ||
|
8f80f375f0 | ||
|
2cf2233643 | ||
|
36564f0c75 | ||
|
8dbb984ead | ||
|
74ffbd4679 | ||
|
82b23d9a13 | ||
|
0a9b234272 | ||
|
3a06ef3959 | ||
|
ed4676bb6c | ||
|
893ebd9690 | ||
|
3c069f8b79 | ||
|
93580c902f | ||
|
e1abd5a051 | ||
|
27fc5f265f | ||
|
5b618ba1f3 | ||
|
a6f56ace24 | ||
|
0d93105bcd | ||
|
7c2fea8623 | ||
|
e2a89c22da | ||
|
03715e0939 | ||
|
4d9b9cb959 | ||
|
d759636d95 | ||
|
c8a8e0f2da | ||
|
b004dfbdf2 | ||
|
40ea91cce4 | ||
|
abcb02d4aa | ||
|
cd983de058 | ||
|
f6cc05634f | ||
|
f14b390849 | ||
|
431f5d76ce | ||
|
dd50399a21 | ||
|
eb17463b68 | ||
|
88e05ffd05 | ||
|
a5079f5243 | ||
|
422c681e55 | ||
|
9531a38486 | ||
|
493cd2a0e3 | ||
|
f7f7e808f2 | ||
|
217c88f342 | ||
|
cf70916764 | ||
|
b84d7f0834 | ||
|
11deaa049e | ||
|
7b969ebd74 | ||
|
245aa6e9e7 | ||
|
163f4cfaf2 | ||
|
33a5cc1488 | ||
|
9a8f45fc6f | ||
|
e3ca89a81b | ||
|
8696650f20 | ||
|
942f050579 | ||
|
89e7e28bfa | ||
|
221eddd995 | ||
|
32d42794dd | ||
|
14c71d6c07 | ||
|
cce4d7d4d9 | ||
|
708cdad38b | ||
|
bc889cbcf4 | ||
|
7c9b943733 | ||
|
e3b88d1162 | ||
|
d80927a8f9 | ||
|
27050b911b | ||
|
a3a2c0a9a8 | ||
|
92ceb0e8fb | ||
|
835a36986d | ||
|
4c599d3d40 | ||
|
67057bfac4 | ||
|
fbc3f47eeb | ||
|
79caa4e510 | ||
|
fa191136cc | ||
|
15d93c8aeb | ||
|
4f5632b916 | ||
|
8e6e6736a3 | ||
|
804afc9a1d | ||
|
bcd86977d2 | ||
|
a8b5a5227f | ||
|
d2398a7abb | ||
|
0e908ad882 | ||
|
c0a83d1916 | ||
|
920856512e | ||
|
62b703ca88 | ||
|
b125b47366 | ||
|
bc6debea89 | ||
|
d5523b18b9 | ||
|
1f69c7e992 | ||
|
d9757cc660 | ||
|
1cb3522e73 | ||
|
7583b0a358 | ||
|
77863e2e88 | ||
|
564404d4ae | ||
|
e2320cd3b2 | ||
|
fd92d6559c | ||
|
6146925757 | ||
|
baef9f5aa7 | ||
|
ae6de8fdf1 | ||
|
b888d13e62 | ||
|
1070c23608 | ||
|
e8d084b855 | ||
|
5b278f704c | ||
|
a87e44bae4 | ||
|
85bc5f54aa | ||
|
41f46d0810 | ||
|
9ce1222fd0 | ||
|
8fb3c68573 | ||
|
eb7ee49096 | ||
|
084b2e8e04 | ||
|
675e4579ac | ||
|
d2880432da | ||
|
6daae83c3a | ||
|
f9e4b689b7 | ||
|
2c30050f3d | ||
|
13530abdeb | ||
|
5eb50750e2 | ||
|
9ef873526a | ||
|
0046fe25c5 | ||
|
fdb13f0b77 | ||
|
029d8574f1 | ||
|
a552c57d67 | ||
|
d5f83acaf5 | ||
|
c50c028c9e | ||
|
465b33b006 | ||
|
4df68479ac | ||
|
3ec25f3634 | ||
|
c29e4648ea | ||
|
9ed8f26d7c | ||
|
b82b378cfe | ||
|
1eac90e5b1 | ||
|
206e68b1d2 | ||
|
1de5cd2e61 | ||
|
264bc52bcc | ||
|
2626a761ea | ||
|
1359c6be1d | ||
|
ca0da2c509 | ||
|
57d55e05e7 | ||
|
702d21fbc3 | ||
|
796ba72bde | ||
|
92a6e9ea5a | ||
|
822ce41b54 | ||
|
0c7f4c2af5 | ||
|
4e1783f856 | ||
|
f6aee3d64e | ||
|
514263ae12 | ||
|
507d5d3758 | ||
|
16b6678aa2 | ||
|
af8b400bf4 | ||
|
a32d7f78bb | ||
|
94b135ae95 | ||
|
e42cad68b4 | ||
|
8a44ee9d50 | ||
|
5bf4fffd2f | ||
|
82b21e6a09 | ||
|
9216eed1b8 | ||
|
c81c5c4801 | ||
|
14bf0038a9 | ||
|
a8f2fd3f4b | ||
|
7223959fda | ||
|
cf5d112e31 | ||
|
b24608891e | ||
|
579efb016a | ||
|
2b1b9d35a2 | ||
|
3d970737d1 | ||
|
75c105a400 | ||
|
0a318f618b | ||
|
574d5055bd | ||
|
0022777a4f | ||
|
4c6996bc09 | ||
|
6ff12b3a88 | ||
|
babbb82a49 | ||
|
ae5331cf40 | ||
|
d67029c42c | ||
|
4dff9316c2 | ||
|
a056cbd19f | ||
|
032d46d8e6 | ||
|
b739aa35f2 | ||
|
fa3035f9cf | ||
|
daf1362d28 | ||
|
8e7d5ddfd4 | ||
|
71a70ffafa | ||
|
d9ceb32e2f | ||
|
13f716a395 | ||
|
b9375a1b4e | ||
|
38a98a51cb | ||
|
64c612dea0 | ||
|
f2e8a9e0c7 | ||
|
8ae0501c22 | ||
|
8dff0b2c5d | ||
|
a713b97e36 | ||
|
b6acc8da70 | ||
|
b8c89325bc | ||
|
b99cdf7367 | ||
|
60ce351a27 | ||
|
413a55623e | ||
|
5b2f95d270 | ||
|
44604c2509 | ||
|
bf2a7c2efd | ||
|
ba5c42cc51 | ||
|
cf2ea0f51c | ||
|
9df002fe4e | ||
|
1a191c7d51 | ||
|
7ca57d918e | ||
|
fe40e74809 | ||
|
daac2e2a1c | ||
|
b88ec407a3 | ||
|
8e9e4215ce | ||
|
4dd83c29fe | ||
|
6020f423f4 | ||
|
99bea8f7c3 | ||
|
d1e2d06538 | ||
|
ccf5d759a4 | ||
|
3ce8deec07 | ||
|
812b1f7baa | ||
|
d1848fd5f7 | ||
|
f57fc827fe | ||
|
45e534bbf5 | ||
|
bfcd4b8250 | ||
|
510f8ae0f5 | ||
|
a1941bf609 | ||
|
c9defec75d | ||
|
a2a2015af6 | ||
|
ca70ddb810 | ||
|
bf9d80c14c | ||
|
83467b8597 | ||
|
816301bf8d | ||
|
345e8a0679 | ||
|
bcd384c31c | ||
|
bbbaa60ddd | ||
|
dc17e5c3fa | ||
|
0150d3961b | ||
|
ae3e1f3a9f | ||
|
13ddc28d05 | ||
|
cedeea13e6 | ||
|
8f78c4a0fb | ||
|
a37af307f4 | ||
|
be3bc175bf | ||
|
6207aab19d | ||
|
01a5ec4c41 | ||
|
b09d45718a | ||
|
07c805a019 | ||
|
ea4e9b8e5e | ||
|
fd4b56572d | ||
|
16448c0bc5 | ||
|
c34750bdab | ||
|
dee6f35888 | ||
|
62ca9a2a84 | ||
|
ad64651532 | ||
|
edc47b56a4 | ||
|
f39b3365db | ||
|
0da4ff7b02 | ||
|
983e02888c | ||
|
35768ff7e8 | ||
|
6dfdc77ebd | ||
|
0753ba3495 | ||
|
ffd3b9a7a7 | ||
|
428062e1e4 | ||
|
cb49c7d060 | ||
|
2a22d71e7c | ||
|
eaa7fb7100 | ||
|
9755dd73eb | ||
|
4c2e62031a | ||
|
51a95554d7 | ||
|
12d8bd1743 | ||
|
458b4259fe | ||
|
e7714da8e8 | ||
|
b4f9d40767 | ||
|
a0e074043b | ||
|
9068168378 | ||
|
de39a17247 | ||
|
5c7a5fab94 | ||
|
c9e0aff839 | ||
|
61ed436c44 | ||
|
b7a1f96294 | ||
|
15ad351579 | ||
|
6cb4645514 | ||
|
eb1fa0919f | ||
|
45edf6025e | ||
|
17fed39b27 | ||
|
9ebda42d34 | ||
|
9f3f5d8053 | ||
|
cfe7852ffd |
3
.idea/dictionaries/bmarty.xml
generated
3
.idea/dictionaries/bmarty.xml
generated
@@ -24,6 +24,8 @@
|
|||||||
<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>
|
||||||
@@ -31,6 +33,7 @@
|
|||||||
<w>ssss</w>
|
<w>ssss</w>
|
||||||
<w>sygnal</w>
|
<w>sygnal</w>
|
||||||
<w>threepid</w>
|
<w>threepid</w>
|
||||||
|
<w>unpublish</w>
|
||||||
<w>unwedging</w>
|
<w>unwedging</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
|
19
AUTHORS.md
19
AUTHORS.md
@@ -4,7 +4,7 @@ A full developer contributors list can be found [here](https://github.com/vector
|
|||||||
|
|
||||||
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,12 +20,17 @@ 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 Element 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.
|
||||||
@@ -34,7 +39,7 @@ We do not forget all translators, for their work of translating Element into man
|
|||||||
|
|
||||||
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
|
Name | Matrix ID | GitHub
|
||||||
--------|---------------------|--------------------------------------
|
----------|-----------------------------|--------------------------------------
|
||||||
gjpower | @gjpower:matrix.org | [gjpower](https://github.com/gjpower)
|
gjpower | @gjpower:matrix.org | [gjpower](https://github.com/gjpower)
|
||||||
|
TR_SLimey | @tr_slimey:an-atom-in.space | [TR-SLimey](https://github.com/TR-SLimey)
|
||||||
|
125
CHANGES.md
125
CHANGES.md
@@ -1,3 +1,125 @@
|
|||||||
|
Changes in Element 1.0.14 (2020-XX-XX)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features ✨:
|
||||||
|
- Enable url previews for notices (#2562)
|
||||||
|
|
||||||
|
Improvements 🙌:
|
||||||
|
- Add System theme option and set as default (#904) (#2387)
|
||||||
|
|
||||||
|
Bugfix 🐛:
|
||||||
|
- Fix Canvas: trying to draw too large bitmap (#1951)
|
||||||
|
- Url previews sometimes attached to wrong message (#2561)
|
||||||
|
- 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)
|
||||||
|
- Hiding membership events works the exact opposite (#2603)
|
||||||
|
- Tapping drawer having more than 1 room in notifications gives "malformed link" error (#2605)
|
||||||
|
|
||||||
|
Translations 🗣:
|
||||||
|
-
|
||||||
|
|
||||||
|
SDK API changes ⚠️:
|
||||||
|
-
|
||||||
|
|
||||||
|
Build 🧱:
|
||||||
|
-
|
||||||
|
|
||||||
|
Test:
|
||||||
|
-
|
||||||
|
|
||||||
|
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)
|
Changes in Element 1.0.10 (2020-11-04)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
@@ -1008,5 +1130,8 @@ SDK API changes ⚠️:
|
|||||||
Build 🧱:
|
Build 🧱:
|
||||||
-
|
-
|
||||||
|
|
||||||
|
Test:
|
||||||
|
-
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
-
|
||||||
|
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
@@ -55,6 +54,10 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '1.8'
|
jvmTarget = '1.8'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buildFeatures {
|
||||||
|
viewBinding true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -66,7 +69,6 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
implementation 'androidx.core:core-ktx:1.3.2'
|
implementation 'androidx.core:core-ktx:1.3.2'
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
|
||||||
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
implementation "androidx.recyclerview:recyclerview:1.1.0"
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.2.1'
|
implementation 'com.google.android.material:material:1.2.1'
|
||||||
|
@@ -17,19 +17,17 @@
|
|||||||
package im.vector.lib.attachmentviewer
|
package im.vector.lib.attachmentviewer
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
import im.vector.lib.attachmentviewer.databinding.ItemAnimatedImageAttachmentBinding
|
||||||
import android.widget.ProgressBar
|
|
||||||
|
|
||||||
class AnimatedImageViewHolder constructor(itemView: View) :
|
class AnimatedImageViewHolder constructor(itemView: View) :
|
||||||
BaseViewHolder(itemView) {
|
BaseViewHolder(itemView) {
|
||||||
|
|
||||||
val touchImageView: ImageView = itemView.findViewById(R.id.imageView)
|
val views = ItemAnimatedImageAttachmentBinding.bind(itemView)
|
||||||
val imageLoaderProgress: ProgressBar = itemView.findViewById(R.id.imageLoaderProgress)
|
|
||||||
|
|
||||||
internal val target = DefaultImageLoaderTarget(this, this.touchImageView)
|
internal val target = DefaultImageLoaderTarget(this, views.imageView)
|
||||||
|
|
||||||
override fun onRecycled() {
|
override fun onRecycled() {
|
||||||
super.onRecycled()
|
super.onRecycled()
|
||||||
touchImageView.setImageDrawable(null)
|
views.imageView.setImageDrawable(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -33,43 +33,51 @@ import androidx.core.view.isVisible
|
|||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.transition.TransitionManager
|
import androidx.transition.TransitionManager
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import kotlinx.android.synthetic.main.activity_attachment_viewer.*
|
import im.vector.lib.attachmentviewer.databinding.ActivityAttachmentViewerBinding
|
||||||
|
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
|
|
||||||
abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventListener {
|
abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventListener {
|
||||||
|
|
||||||
lateinit var pager2: ViewPager2
|
protected val pager2: ViewPager2
|
||||||
lateinit var imageTransitionView: ImageView
|
get() = views.attachmentPager
|
||||||
lateinit var transitionImageContainer: ViewGroup
|
protected val imageTransitionView: ImageView
|
||||||
|
get() = views.transitionImageView
|
||||||
|
protected val transitionImageContainer: ViewGroup
|
||||||
|
get() = views.transitionImageContainer
|
||||||
|
|
||||||
var topInset = 0
|
private var topInset = 0
|
||||||
var bottomInset = 0
|
private var bottomInset = 0
|
||||||
var systemUiVisibility = true
|
private var systemUiVisibility = true
|
||||||
|
|
||||||
private var overlayView: View? = null
|
private var overlayView: View? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value == overlayView) return
|
if (value == overlayView) return
|
||||||
overlayView?.let { rootContainer.removeView(it) }
|
overlayView?.let { views.rootContainer.removeView(it) }
|
||||||
rootContainer.addView(value)
|
views.rootContainer.addView(value)
|
||||||
value?.updatePadding(top = topInset, bottom = bottomInset)
|
value?.updatePadding(top = topInset, bottom = bottomInset)
|
||||||
field = value
|
field = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private lateinit var views: ActivityAttachmentViewerBinding
|
||||||
|
|
||||||
private lateinit var swipeDismissHandler: SwipeToDismissHandler
|
private lateinit var swipeDismissHandler: SwipeToDismissHandler
|
||||||
private lateinit var directionDetector: SwipeDirectionDetector
|
private lateinit var directionDetector: SwipeDirectionDetector
|
||||||
private lateinit var scaleDetector: ScaleGestureDetector
|
private lateinit var scaleDetector: ScaleGestureDetector
|
||||||
private lateinit var gestureDetector: GestureDetectorCompat
|
private lateinit var gestureDetector: GestureDetectorCompat
|
||||||
|
|
||||||
var currentPosition = 0
|
var currentPosition = 0
|
||||||
|
private set
|
||||||
|
|
||||||
private var swipeDirection: SwipeDirection? = null
|
private var swipeDirection: SwipeDirection? = null
|
||||||
|
|
||||||
private fun isScaled() = attachmentsAdapter.isScaled(currentPosition)
|
private fun isScaled() = attachmentsAdapter.isScaled(currentPosition)
|
||||||
|
|
||||||
|
private val attachmentsAdapter = AttachmentsAdapter()
|
||||||
|
|
||||||
private var wasScaled: Boolean = false
|
private var wasScaled: Boolean = false
|
||||||
private var isSwipeToDismissAllowed: Boolean = true
|
private var isSwipeToDismissAllowed: Boolean = true
|
||||||
private lateinit var attachmentsAdapter: AttachmentsAdapter
|
|
||||||
private var isOverlayWasClicked = false
|
private var isOverlayWasClicked = false
|
||||||
|
|
||||||
// private val shouldDismissToBottom: Boolean
|
// private val shouldDismissToBottom: Boolean
|
||||||
@@ -95,17 +103,14 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
|||||||
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
|
||||||
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
|
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
|
||||||
|
|
||||||
setContentView(R.layout.activity_attachment_viewer)
|
views = ActivityAttachmentViewerBinding.inflate(layoutInflater)
|
||||||
attachmentPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
|
setContentView(views.root)
|
||||||
attachmentsAdapter = AttachmentsAdapter()
|
views.attachmentPager.orientation = ViewPager2.ORIENTATION_HORIZONTAL
|
||||||
attachmentPager.adapter = attachmentsAdapter
|
views.attachmentPager.adapter = attachmentsAdapter
|
||||||
imageTransitionView = transitionImageView
|
|
||||||
transitionImageContainer = findViewById(R.id.transitionImageContainer)
|
|
||||||
pager2 = attachmentPager
|
|
||||||
directionDetector = createSwipeDirectionDetector()
|
directionDetector = createSwipeDirectionDetector()
|
||||||
gestureDetector = createGestureDetector()
|
gestureDetector = createGestureDetector()
|
||||||
|
|
||||||
attachmentPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
views.attachmentPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
|
||||||
override fun onPageScrollStateChanged(state: Int) {
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
isImagePagerIdle = state == ViewPager2.SCROLL_STATE_IDLE
|
isImagePagerIdle = state == ViewPager2.SCROLL_STATE_IDLE
|
||||||
}
|
}
|
||||||
@@ -116,12 +121,12 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
|||||||
})
|
})
|
||||||
|
|
||||||
swipeDismissHandler = createSwipeToDismissHandler()
|
swipeDismissHandler = createSwipeToDismissHandler()
|
||||||
rootContainer.setOnTouchListener(swipeDismissHandler)
|
views.rootContainer.setOnTouchListener(swipeDismissHandler)
|
||||||
rootContainer.viewTreeObserver.addOnGlobalLayoutListener { swipeDismissHandler.translationLimit = dismissContainer.height / 4 }
|
views.rootContainer.viewTreeObserver.addOnGlobalLayoutListener { swipeDismissHandler.translationLimit = views.dismissContainer.height / 4 }
|
||||||
|
|
||||||
scaleDetector = createScaleGestureDetector()
|
scaleDetector = createScaleGestureDetector()
|
||||||
|
|
||||||
ViewCompat.setOnApplyWindowInsetsListener(rootContainer) { _, insets ->
|
ViewCompat.setOnApplyWindowInsetsListener(views.rootContainer) { _, insets ->
|
||||||
overlayView?.updatePadding(top = insets.systemWindowInsetTop, bottom = insets.systemWindowInsetBottom)
|
overlayView?.updatePadding(top = insets.systemWindowInsetTop, bottom = insets.systemWindowInsetBottom)
|
||||||
topInset = insets.systemWindowInsetTop
|
topInset = insets.systemWindowInsetTop
|
||||||
bottomInset = insets.systemWindowInsetBottom
|
bottomInset = insets.systemWindowInsetBottom
|
||||||
@@ -170,7 +175,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
|||||||
if (swipeDirection == null && (scaleDetector.isInProgress || ev.pointerCount > 1 || wasScaled)) {
|
if (swipeDirection == null && (scaleDetector.isInProgress || ev.pointerCount > 1 || wasScaled)) {
|
||||||
wasScaled = true
|
wasScaled = true
|
||||||
// Log.v("ATTACHEMENTS", "dispatch to pager")
|
// Log.v("ATTACHEMENTS", "dispatch to pager")
|
||||||
return attachmentPager.dispatchTouchEvent(ev)
|
return views.attachmentPager.dispatchTouchEvent(ev)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log.v("ATTACHEMENTS", "is current item scaled ${isScaled()}")
|
// Log.v("ATTACHEMENTS", "is current item scaled ${isScaled()}")
|
||||||
@@ -196,16 +201,16 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
|||||||
private fun handleEventActionDown(event: MotionEvent) {
|
private fun handleEventActionDown(event: MotionEvent) {
|
||||||
swipeDirection = null
|
swipeDirection = null
|
||||||
wasScaled = false
|
wasScaled = false
|
||||||
attachmentPager.dispatchTouchEvent(event)
|
views.attachmentPager.dispatchTouchEvent(event)
|
||||||
|
|
||||||
swipeDismissHandler.onTouch(rootContainer, event)
|
swipeDismissHandler.onTouch(views.rootContainer, event)
|
||||||
isOverlayWasClicked = dispatchOverlayTouch(event)
|
isOverlayWasClicked = dispatchOverlayTouch(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleEventActionUp(event: MotionEvent) {
|
private fun handleEventActionUp(event: MotionEvent) {
|
||||||
// wasDoubleTapped = false
|
// wasDoubleTapped = false
|
||||||
swipeDismissHandler.onTouch(rootContainer, event)
|
swipeDismissHandler.onTouch(views.rootContainer, event)
|
||||||
attachmentPager.dispatchTouchEvent(event)
|
views.attachmentPager.dispatchTouchEvent(event)
|
||||||
isOverlayWasClicked = dispatchOverlayTouch(event)
|
isOverlayWasClicked = dispatchOverlayTouch(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,12 +225,12 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
|||||||
private fun toggleOverlayViewVisibility() {
|
private fun toggleOverlayViewVisibility() {
|
||||||
if (systemUiVisibility) {
|
if (systemUiVisibility) {
|
||||||
// we hide
|
// we hide
|
||||||
TransitionManager.beginDelayedTransition(rootContainer)
|
TransitionManager.beginDelayedTransition(views.rootContainer)
|
||||||
hideSystemUI()
|
hideSystemUI()
|
||||||
overlayView?.isVisible = false
|
overlayView?.isVisible = false
|
||||||
} else {
|
} else {
|
||||||
// we show
|
// we show
|
||||||
TransitionManager.beginDelayedTransition(rootContainer)
|
TransitionManager.beginDelayedTransition(views.rootContainer)
|
||||||
showSystemUI()
|
showSystemUI()
|
||||||
overlayView?.isVisible = true
|
overlayView?.isVisible = true
|
||||||
}
|
}
|
||||||
@@ -238,11 +243,11 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
|||||||
return when (swipeDirection) {
|
return when (swipeDirection) {
|
||||||
SwipeDirection.Up, SwipeDirection.Down -> {
|
SwipeDirection.Up, SwipeDirection.Down -> {
|
||||||
if (isSwipeToDismissAllowed && !wasScaled && isImagePagerIdle) {
|
if (isSwipeToDismissAllowed && !wasScaled && isImagePagerIdle) {
|
||||||
swipeDismissHandler.onTouch(rootContainer, event)
|
swipeDismissHandler.onTouch(views.rootContainer, event)
|
||||||
} else true
|
} else true
|
||||||
}
|
}
|
||||||
SwipeDirection.Left, SwipeDirection.Right -> {
|
SwipeDirection.Left, SwipeDirection.Right -> {
|
||||||
attachmentPager.dispatchTouchEvent(event)
|
views.attachmentPager.dispatchTouchEvent(event)
|
||||||
}
|
}
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
@@ -250,8 +255,8 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
|||||||
|
|
||||||
private fun handleSwipeViewMove(translationY: Float, translationLimit: Int) {
|
private fun handleSwipeViewMove(translationY: Float, translationLimit: Int) {
|
||||||
val alpha = calculateTranslationAlpha(translationY, translationLimit)
|
val alpha = calculateTranslationAlpha(translationY, translationLimit)
|
||||||
backgroundView.alpha = alpha
|
views.backgroundView.alpha = alpha
|
||||||
dismissContainer.alpha = alpha
|
views.dismissContainer.alpha = alpha
|
||||||
overlayView?.alpha = alpha
|
overlayView?.alpha = alpha
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,7 +270,7 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
|
|||||||
|
|
||||||
private fun createSwipeToDismissHandler()
|
private fun createSwipeToDismissHandler()
|
||||||
: SwipeToDismissHandler = SwipeToDismissHandler(
|
: SwipeToDismissHandler = SwipeToDismissHandler(
|
||||||
swipeView = dismissContainer,
|
swipeView = views.dismissContainer,
|
||||||
shouldAnimateDismiss = { shouldAnimateDismiss() },
|
shouldAnimateDismiss = { shouldAnimateDismiss() },
|
||||||
onDismiss = { animateClose() },
|
onDismiss = { animateClose() },
|
||||||
onSwipeViewMove = ::handleSwipeViewMove)
|
onSwipeViewMove = ::handleSwipeViewMove)
|
||||||
|
@@ -98,7 +98,7 @@ class AttachmentsAdapter : RecyclerView.Adapter<BaseViewHolder>() {
|
|||||||
fun isScaled(position: Int): Boolean {
|
fun isScaled(position: Int): Boolean {
|
||||||
val holder = recyclerView?.findViewHolderForAdapterPosition(position)
|
val holder = recyclerView?.findViewHolderForAdapterPosition(position)
|
||||||
if (holder is ZoomableImageViewHolder) {
|
if (holder is ZoomableImageViewHolder) {
|
||||||
return holder.touchImageView.attacher.scale > 1f
|
return holder.views.touchImageView.attacher.scale > 1f
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@@ -44,29 +44,29 @@ internal class DefaultImageLoaderTarget(val holder: AnimatedImageViewHolder, pri
|
|||||||
|
|
||||||
override fun onResourceLoading(uid: String, placeholder: Drawable?) {
|
override fun onResourceLoading(uid: String, placeholder: Drawable?) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.imageLoaderProgress.isVisible = true
|
holder.views.imageLoaderProgress.isVisible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoadFailed(uid: String, errorDrawable: Drawable?) {
|
override fun onLoadFailed(uid: String, errorDrawable: Drawable?) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.imageLoaderProgress.isVisible = false
|
holder.views.imageLoaderProgress.isVisible = false
|
||||||
holder.touchImageView.setImageDrawable(errorDrawable)
|
holder.views.imageView.setImageDrawable(errorDrawable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceCleared(uid: String, placeholder: Drawable?) {
|
override fun onResourceCleared(uid: String, placeholder: Drawable?) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.touchImageView.setImageDrawable(placeholder)
|
holder.views.imageView.setImageDrawable(placeholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceReady(uid: String, resource: Drawable) {
|
override fun onResourceReady(uid: String, resource: Drawable) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.imageLoaderProgress.isVisible = false
|
holder.views.imageLoaderProgress.isVisible = false
|
||||||
// Glide mess up the view size :/
|
// Glide mess up the view size :/
|
||||||
holder.touchImageView.updateLayoutParams {
|
holder.views.imageView.updateLayoutParams {
|
||||||
width = LinearLayout.LayoutParams.MATCH_PARENT
|
width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||||
height = LinearLayout.LayoutParams.MATCH_PARENT
|
height = LinearLayout.LayoutParams.MATCH_PARENT
|
||||||
}
|
}
|
||||||
holder.touchImageView.setImageDrawable(resource)
|
holder.views.imageView.setImageDrawable(resource)
|
||||||
if (resource is Animatable) {
|
if (resource is Animatable) {
|
||||||
resource.start()
|
resource.start()
|
||||||
}
|
}
|
||||||
@@ -77,30 +77,30 @@ internal class DefaultImageLoaderTarget(val holder: AnimatedImageViewHolder, pri
|
|||||||
|
|
||||||
override fun onResourceLoading(uid: String, placeholder: Drawable?) {
|
override fun onResourceLoading(uid: String, placeholder: Drawable?) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.imageLoaderProgress.isVisible = true
|
holder.views.imageLoaderProgress.isVisible = true
|
||||||
holder.touchImageView.setImageDrawable(placeholder)
|
holder.views.touchImageView.setImageDrawable(placeholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onLoadFailed(uid: String, errorDrawable: Drawable?) {
|
override fun onLoadFailed(uid: String, errorDrawable: Drawable?) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.imageLoaderProgress.isVisible = false
|
holder.views.imageLoaderProgress.isVisible = false
|
||||||
holder.touchImageView.setImageDrawable(errorDrawable)
|
holder.views.touchImageView.setImageDrawable(errorDrawable)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceCleared(uid: String, placeholder: Drawable?) {
|
override fun onResourceCleared(uid: String, placeholder: Drawable?) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.touchImageView.setImageDrawable(placeholder)
|
holder.views.touchImageView.setImageDrawable(placeholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResourceReady(uid: String, resource: Drawable) {
|
override fun onResourceReady(uid: String, resource: Drawable) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.imageLoaderProgress.isVisible = false
|
holder.views.imageLoaderProgress.isVisible = false
|
||||||
// Glide mess up the view size :/
|
// Glide mess up the view size :/
|
||||||
holder.touchImageView.updateLayoutParams {
|
holder.views.touchImageView.updateLayoutParams {
|
||||||
width = LinearLayout.LayoutParams.MATCH_PARENT
|
width = LinearLayout.LayoutParams.MATCH_PARENT
|
||||||
height = LinearLayout.LayoutParams.MATCH_PARENT
|
height = LinearLayout.LayoutParams.MATCH_PARENT
|
||||||
}
|
}
|
||||||
holder.touchImageView.setImageDrawable(resource)
|
holder.views.touchImageView.setImageDrawable(resource)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -49,19 +49,19 @@ internal class DefaultVideoLoaderTarget(val holder: VideoViewHolder, private val
|
|||||||
|
|
||||||
override fun onThumbnailResourceCleared(uid: String, placeholder: Drawable?) {
|
override fun onThumbnailResourceCleared(uid: String, placeholder: Drawable?) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.thumbnailImage.setImageDrawable(placeholder)
|
holder.views.videoThumbnailImage.setImageDrawable(placeholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onThumbnailResourceReady(uid: String, resource: Drawable) {
|
override fun onThumbnailResourceReady(uid: String, resource: Drawable) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.thumbnailImage.setImageDrawable(resource)
|
holder.views.videoThumbnailImage.setImageDrawable(resource)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onVideoFileLoading(uid: String) {
|
override fun onVideoFileLoading(uid: String) {
|
||||||
if (holder.boundResourceUid != uid) return
|
if (holder.boundResourceUid != uid) return
|
||||||
holder.thumbnailImage.isVisible = true
|
holder.views.videoThumbnailImage.isVisible = true
|
||||||
holder.loaderProgressBar.isVisible = true
|
holder.views.videoLoaderProgress.isVisible = true
|
||||||
holder.videoView.isVisible = false
|
holder.views.videoView.isVisible = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onVideoFileLoadFailed(uid: String) {
|
override fun onVideoFileLoadFailed(uid: String) {
|
||||||
@@ -82,8 +82,8 @@ internal class DefaultVideoLoaderTarget(val holder: VideoViewHolder, private val
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun arrangeForVideoReady() {
|
private fun arrangeForVideoReady() {
|
||||||
holder.thumbnailImage.isVisible = false
|
holder.views.videoThumbnailImage.isVisible = false
|
||||||
holder.loaderProgressBar.isVisible = false
|
holder.views.videoLoaderProgress.isVisible = false
|
||||||
holder.videoView.isVisible = true
|
holder.views.videoView.isVisible = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -18,11 +18,8 @@ package im.vector.lib.attachmentviewer
|
|||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.ProgressBar
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.VideoView
|
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
|
import im.vector.lib.attachmentviewer.databinding.ItemVideoAttachmentBinding
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
@@ -44,13 +41,9 @@ class VideoViewHolder constructor(itemView: View) :
|
|||||||
|
|
||||||
var eventListener: WeakReference<AttachmentEventListener>? = null
|
var eventListener: WeakReference<AttachmentEventListener>? = null
|
||||||
|
|
||||||
val thumbnailImage: ImageView = itemView.findViewById(R.id.videoThumbnailImage)
|
val views = ItemVideoAttachmentBinding.bind(itemView)
|
||||||
val videoView: VideoView = itemView.findViewById(R.id.videoView)
|
|
||||||
val loaderProgressBar: ProgressBar = itemView.findViewById(R.id.videoLoaderProgress)
|
|
||||||
val videoControlIcon: ImageView = itemView.findViewById(R.id.videoControlIcon)
|
|
||||||
val errorTextView: TextView = itemView.findViewById(R.id.videoMediaViewerErrorView)
|
|
||||||
|
|
||||||
internal val target = DefaultVideoLoaderTarget(this, thumbnailImage)
|
internal val target = DefaultVideoLoaderTarget(this, views.videoThumbnailImage)
|
||||||
|
|
||||||
override fun onRecycled() {
|
override fun onRecycled() {
|
||||||
super.onRecycled()
|
super.onRecycled()
|
||||||
@@ -77,12 +70,12 @@ class VideoViewHolder constructor(itemView: View) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun entersBackground() {
|
override fun entersBackground() {
|
||||||
if (videoView.isPlaying) {
|
if (views.videoView.isPlaying) {
|
||||||
progress = videoView.currentPosition
|
progress = views.videoView.currentPosition
|
||||||
progressDisposable?.dispose()
|
progressDisposable?.dispose()
|
||||||
progressDisposable = null
|
progressDisposable = null
|
||||||
videoView.stopPlayback()
|
views.videoView.stopPlayback()
|
||||||
videoView.pause()
|
views.videoView.pause()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,9 +85,9 @@ class VideoViewHolder constructor(itemView: View) :
|
|||||||
|
|
||||||
override fun onSelected(selected: Boolean) {
|
override fun onSelected(selected: Boolean) {
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
if (videoView.isPlaying) {
|
if (views.videoView.isPlaying) {
|
||||||
progress = videoView.currentPosition
|
progress = views.videoView.currentPosition
|
||||||
videoView.stopPlayback()
|
views.videoView.stopPlayback()
|
||||||
} else {
|
} else {
|
||||||
progress = 0
|
progress = 0
|
||||||
}
|
}
|
||||||
@@ -109,34 +102,34 @@ class VideoViewHolder constructor(itemView: View) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startPlaying() {
|
private fun startPlaying() {
|
||||||
thumbnailImage.isVisible = false
|
views.videoThumbnailImage.isVisible = false
|
||||||
loaderProgressBar.isVisible = false
|
views.videoLoaderProgress.isVisible = false
|
||||||
videoView.isVisible = true
|
views.videoView.isVisible = true
|
||||||
|
|
||||||
videoView.setOnPreparedListener {
|
views.videoView.setOnPreparedListener {
|
||||||
progressDisposable?.dispose()
|
progressDisposable?.dispose()
|
||||||
progressDisposable = Observable.interval(100, TimeUnit.MILLISECONDS)
|
progressDisposable = Observable.interval(100, TimeUnit.MILLISECONDS)
|
||||||
.timeInterval()
|
.timeInterval()
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe {
|
.subscribe {
|
||||||
val duration = videoView.duration
|
val duration = views.videoView.duration
|
||||||
val progress = videoView.currentPosition
|
val progress = views.videoView.currentPosition
|
||||||
val isPlaying = videoView.isPlaying
|
val isPlaying = views.videoView.isPlaying
|
||||||
// Log.v("FOO", "isPlaying $isPlaying $progress/$duration")
|
// Log.v("FOO", "isPlaying $isPlaying $progress/$duration")
|
||||||
eventListener?.get()?.onEvent(AttachmentEvents.VideoEvent(isPlaying, progress, duration))
|
eventListener?.get()?.onEvent(AttachmentEvents.VideoEvent(isPlaying, progress, duration))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
videoView.setVideoPath(mVideoPath)
|
views.videoView.setVideoPath(mVideoPath)
|
||||||
} catch (failure: Throwable) {
|
} catch (failure: Throwable) {
|
||||||
// Couldn't open
|
// Couldn't open
|
||||||
Log.v(VideoViewHolder::class.java.name, "Failed to start video")
|
Log.v(VideoViewHolder::class.java.name, "Failed to start video")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wasPaused) {
|
if (!wasPaused) {
|
||||||
videoView.start()
|
views.videoView.start()
|
||||||
if (progress > 0) {
|
if (progress > 0) {
|
||||||
videoView.seekTo(progress)
|
views.videoView.seekTo(progress)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,17 +139,17 @@ class VideoViewHolder constructor(itemView: View) :
|
|||||||
when (commands) {
|
when (commands) {
|
||||||
AttachmentCommands.StartVideo -> {
|
AttachmentCommands.StartVideo -> {
|
||||||
wasPaused = false
|
wasPaused = false
|
||||||
videoView.start()
|
views.videoView.start()
|
||||||
}
|
}
|
||||||
AttachmentCommands.PauseVideo -> {
|
AttachmentCommands.PauseVideo -> {
|
||||||
wasPaused = true
|
wasPaused = true
|
||||||
videoView.pause()
|
views.videoView.pause()
|
||||||
}
|
}
|
||||||
is AttachmentCommands.SeekTo -> {
|
is AttachmentCommands.SeekTo -> {
|
||||||
val duration = videoView.duration
|
val duration = views.videoView.duration
|
||||||
if (duration > 0) {
|
if (duration > 0) {
|
||||||
val seekDuration = duration * (commands.percentProgress / 100f)
|
val seekDuration = duration * (commands.percentProgress / 100f)
|
||||||
videoView.seekTo(seekDuration.toInt())
|
views.videoView.seekTo(seekDuration.toInt())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,31 +17,29 @@
|
|||||||
package im.vector.lib.attachmentviewer
|
package im.vector.lib.attachmentviewer
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.ProgressBar
|
import im.vector.lib.attachmentviewer.databinding.ItemImageAttachmentBinding
|
||||||
import com.github.chrisbanes.photoview.PhotoView
|
|
||||||
|
|
||||||
class ZoomableImageViewHolder constructor(itemView: View) :
|
class ZoomableImageViewHolder constructor(itemView: View) :
|
||||||
BaseViewHolder(itemView) {
|
BaseViewHolder(itemView) {
|
||||||
|
|
||||||
val touchImageView: PhotoView = itemView.findViewById(R.id.touchImageView)
|
val views = ItemImageAttachmentBinding.bind(itemView)
|
||||||
val imageLoaderProgress: ProgressBar = itemView.findViewById(R.id.imageLoaderProgress)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
touchImageView.setAllowParentInterceptOnEdge(false)
|
views.touchImageView.setAllowParentInterceptOnEdge(false)
|
||||||
touchImageView.setOnScaleChangeListener { scaleFactor, _, _ ->
|
views.touchImageView.setOnScaleChangeListener { scaleFactor, _, _ ->
|
||||||
// Log.v("ATTACHEMENTS", "scaleFactor $scaleFactor")
|
// Log.v("ATTACHEMENTS", "scaleFactor $scaleFactor")
|
||||||
// It's a bit annoying but when you pitch down the scaling
|
// It's a bit annoying but when you pitch down the scaling
|
||||||
// is not exactly one :/
|
// is not exactly one :/
|
||||||
touchImageView.setAllowParentInterceptOnEdge(scaleFactor <= 1.0008f)
|
views.touchImageView.setAllowParentInterceptOnEdge(scaleFactor <= 1.0008f)
|
||||||
}
|
}
|
||||||
touchImageView.setScale(1.0f, true)
|
views.touchImageView.setScale(1.0f, true)
|
||||||
touchImageView.setAllowParentInterceptOnEdge(true)
|
views.touchImageView.setAllowParentInterceptOnEdge(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal val target = DefaultImageLoaderTarget.ZoomableImageTarget(this, touchImageView)
|
internal val target = DefaultImageLoaderTarget.ZoomableImageTarget(this, views.touchImageView)
|
||||||
|
|
||||||
override fun onRecycled() {
|
override fun onRecycled() {
|
||||||
super.onRecycled()
|
super.onRecycled()
|
||||||
touchImageView.setImageDrawable(null)
|
views.touchImageView.setImageDrawable(null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
build.gradle
10
build.gradle
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
// Ref: https://kotlinlang.org/releases.html
|
// Ref: https://kotlinlang.org/releases.html
|
||||||
ext.kotlin_version = '1.4.10'
|
ext.kotlin_version = '1.4.20'
|
||||||
ext.kotlin_coroutines_version = "1.3.9"
|
ext.kotlin_coroutines_version = "1.4.1"
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
@@ -12,7 +12,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
classpath 'com.android.tools.build:gradle:4.1.1'
|
||||||
classpath 'com.google.gms:google-services:4.3.4'
|
classpath 'com.google.gms:google-services:4.3.4'
|
||||||
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'
|
||||||
@@ -43,6 +43,10 @@ allprojects {
|
|||||||
includeGroupByRegex 'com\\.github\\.chrisbanes'
|
includeGroupByRegex 'com\\.github\\.chrisbanes'
|
||||||
// PFLockScreen-Android
|
// PFLockScreen-Android
|
||||||
includeGroupByRegex 'com\\.github\\.vector-im'
|
includeGroupByRegex 'com\\.github\\.vector-im'
|
||||||
|
|
||||||
|
//Chat effects
|
||||||
|
includeGroupByRegex 'com\\.github\\.jetradarmobile'
|
||||||
|
includeGroupByRegex 'nl\\.dionsegijn'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
maven {
|
maven {
|
||||||
|
@@ -165,7 +165,7 @@ In this case, the user can click on "Sign in with SSO" and the native web browse
|
|||||||
|
|
||||||
> https://homeserver.with.sso/_matrix/client/r0/login/sso/redirect?redirectUrl=element%3A%2F%element
|
> https://homeserver.with.sso/_matrix/client/r0/login/sso/redirect?redirectUrl=element%3A%2F%element
|
||||||
|
|
||||||
The parameter `redirectUrl` is set to `element://element`.
|
The parameter `redirectUrl` is set to `element://connect`.
|
||||||
|
|
||||||
ChromeCustomTabs are an intermediate way to display a WebPage, between a WebView and using the external browser. More info can be found [here](https://developer.chrome.com/multidevice/android/customtabs)
|
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)
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ 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`
|
||||||
|
|
||||||
> element://element?loginToken=MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy
|
> element://connect?loginToken=MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy
|
||||||
|
|
||||||
This navigation is intercepted by Element by the `LoginActivity`, which will then ask the homeserver to convert this `loginToken` to an access token
|
This navigation is intercepted by Element by the `LoginActivity`, which will then ask the homeserver to convert this `loginToken` to an access token
|
||||||
|
|
||||||
|
@@ -27,7 +27,6 @@ $ source env/bin/activate
|
|||||||
Every time you want to launch these test homeservers, type:
|
Every time you want to launch these test homeservers, type:
|
||||||
|
|
||||||
```shell script
|
```shell script
|
||||||
$ virtualenv -p python3 env
|
|
||||||
$ source env/bin/activate
|
$ source env/bin/activate
|
||||||
(env) $ demo/start.sh --no-rate-limit
|
(env) $ demo/start.sh --no-rate-limit
|
||||||
```
|
```
|
||||||
|
1
fastlane/metadata/android/ca/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/ca/changelogs/40100100.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// TODO
|
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 @@
|
|||||||
|
Xat 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 (anteriorment Riot.im)
|
1
fastlane/metadata/android/de/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/de/changelogs/40100100.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// TODO
|
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.12
|
1
fastlane/metadata/android/es/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/es/changelogs/40100100.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// TODO
|
@@ -1,30 +1,30 @@
|
|||||||
Element es un nuevo tipo de aplicación de mensajería y colaboración que:
|
Element es un nuevo tipo de aplicación de mensajería y colaboración que:
|
||||||
|
|
||||||
1. Le da el control para preservar su privacidad
|
1. Te da el control para preservar su privacidad
|
||||||
2. Le permite comunicarse con cualquier persona en la red Matrix e incluso más allá al integrarse con aplicaciones como Slack.
|
2. Te permite comunicarse con cualquier persona en la red Matrix e incluso más allá al integrarse con aplicaciones como Slack
|
||||||
3. Te protege de la publicidad, la minería de datos y los jardines vallados.
|
3. Te protege de la publicidad, la minería de datos y los jardines vallados
|
||||||
4. Lo protege a través del cifrado de un extremo a otro, con firma cruzada para verificar a otros
|
4. Te protege a través de encriptación de Extremo-a-Extremo, con firma cruzada para verificar a otros
|
||||||
|
|
||||||
Element es completamente diferente de otras aplicaciones de mensajería y colaboración porque es descentralizado y de código abierto.
|
Element es completamente diferente de otras aplicaciones de mensajería y colaboración porque es descentralizado y de código abierto.
|
||||||
|
|
||||||
Element le permite autohospedarse, o elegir un host, para que tenga privacidad, propiedad y control de sus datos y conversaciones. Te da acceso a una red abierta; para que no se quede atascado hablando solo con otros usuarios de Element. Y es muy seguro.
|
Element te permite tener su propio servidor privado, o elegir uno público, para que tenga privacidad, posesión, y control de sus datos y conversaciones. Te da acceso a una red abierta; para que no se quede atrapado hablando solo con otros usuarios de Element. Y es muy seguro.
|
||||||
|
|
||||||
Element puede hacer todo esto porque opera en Matrix, el estándar para la comunicación abierta y descentralizada.
|
Element puede hacer todo esto porque opera en Matrix, el estándar para la comunicación abierta y descentralizada.
|
||||||
|
|
||||||
Element te da el control permitiéndote elegir quién aloja tus conversaciones. Desde la aplicación Element, puede elegir hospedar de diferentes maneras:
|
Element te da el control permitiéndote elegir quién aloja tus conversaciones. Desde la aplicación Element, puedes elegir hospedar de diferentes maneras:
|
||||||
|
|
||||||
1. Obtenga una cuenta gratuita en el servidor público de matrix.org alojado por los desarrolladores de Matrix, o elija entre miles de servidores públicos alojados por voluntarios
|
1. Obtén una cuenta gratuita en el servidor público de matrix.org alojado por los desarrolladores de Matrix, o elije entre miles de servidores públicos alojados por voluntarios
|
||||||
2. Autohospede su cuenta ejecutando un servidor en su propio hardware
|
2. Autohospeda tu cuenta con un servidor en tu propio hardware
|
||||||
3. Regístrese para obtener una cuenta en un servidor personalizado simplemente suscribiéndose a la plataforma de alojamiento de Element Matrix Services
|
3. Regístrate para obtener una cuenta en un servidor personalizado simplemente suscribiéndote a la plataforma de alojamiento de Element Matrix Services
|
||||||
|
|
||||||
<b>¿Por qué elegir Element?</b>
|
<b>¿Por qué elegir Element?</b>
|
||||||
|
|
||||||
<b>POSEE SUS DATOS</b>: Tú decides dónde guardar tus datos y mensajes. Usted es el propietario y lo controla, no algún MEGACORP que extraiga sus datos o dé acceso a terceros.
|
<b>TOMA POSESIÓN DE TUS DATOS</b>: Tú decides dónde guardar tus datos y mensajes. Tú eres el propietario y quien lo controla, no alguna MEGACORP que extrae tu datos o da acceso a terceros.
|
||||||
|
|
||||||
<b>MENSAJERÍA ABIERTA Y COLABORACIÓN</b>: Puede chatear con cualquier otra persona en la red de Matrix, ya sea que estén usando Element u otra aplicación de Matrix, e incluso si están usando un sistema de mensajería diferente como Slack, IRC o XMPP.
|
<b>MENSAJERÍA ABIERTA Y COLABORACIÓN</b>: Puede chatear con cualquier otra persona en la red de Matrix, tanto si usan Element u otra aplicación de Matrix, e incluso si están usando un sistema de mensajería diferente como Slack, IRC o XMPP.
|
||||||
|
|
||||||
<b>SUPER SEGURO</b>: Cifrado real de extremo a extremo (solo aquellos en la conversación pueden descifrar mensajes) y firma cruzada para verificar los dispositivos de los participantes de la conversación.
|
<b>SUPER SEGURO</b>: Encriptación de Extremo-a-Extremo real (solo aquellos en la conversación pueden descifrar mensajes) y firma cruzada para verificar los dispositivos de los participantes de la conversación.
|
||||||
|
|
||||||
<b>COMUNICACIÓN COMPLETA</b>: Mensajería, llamadas de voz y video, uso compartido de archivos, uso compartido de pantalla y un montón de integraciones, bots y widgets. Construya salas, comunidades, manténgase en contacto y haga las cosas.
|
<b>COMUNICACIÓN COMPLETA</b>: Mensajería, llamadas de voz y video, uso compartido de archivos, uso compartido de pantalla y un montón de integraciones, bots y widgets. Crea salas, comunidades, mantente en contacto y organízate con eficacia.
|
||||||
|
|
||||||
<b>EN TODAS PARTES</b>: Manténgase en contacto donde quiera que esté con un historial de mensajes totalmente sincronizado en todos sus dispositivos y en la web en https://app.element.io.
|
<b>EN TODAS PARTES</b>: Mantente en contacto donde quiera que estés con un historial de mensajes totalmente sincronizado en todos sus dispositivos y en la web en https://app.element.io.
|
||||||
|
@@ -1 +1 @@
|
|||||||
Chat y VoIP descentralizados seguros. Mantenga sus datos a salvo de terceros.
|
Chat y VoIP descentralizados y seguros. Mantén tus datos a salvo de terceros.
|
||||||
|
@@ -1 +1 @@
|
|||||||
Element (anteriorment Riot.im)
|
Element (previamente Riot.im)
|
||||||
|
1
fastlane/metadata/android/fa/changelogs/40100100.txt
Normal file
1
fastlane/metadata/android/fa/changelogs/40100100.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// برای انجام
|
2
fastlane/metadata/android/fi/changelogs/40100100.txt
Normal file
2
fastlane/metadata/android/fi/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Tämä versio sisältää virheenkorjauksia ja muita parannuksia. Viestien lähettäminen on nyt paljon nopeampaa.
|
||||||
|
Täysi muutosloki: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
30
fastlane/metadata/android/fi/full_description.txt
Normal file
30
fastlane/metadata/android/fi/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Element on uudenlainen viestinsovellus, joka:
|
||||||
|
|
||||||
|
1. Antaa sinun päättää yksityisyydestäsi.
|
||||||
|
2. Antaa sinun kommunikoida kenen tahansa kanssa Matrix-verkossa ja jopa sen ulkopuolella siltaamalla sovelluksiin, kuten Slack
|
||||||
|
3. Suojaa sinua mainonnalta, tietojen keräämiseltä ja suljetuilta alustoilta
|
||||||
|
4. Suojaa sinut päästä päähän -salauksella sekä ristiin varmentamisella muiden todentamiseksi
|
||||||
|
|
||||||
|
Element eroaa täysin muista viestintäsovelluksista, koska se on hajautettu ja avointa lähdekoodia.
|
||||||
|
|
||||||
|
Element antaa sinun isännöidä itse - valita isännän - jotta sinulla on yksityisyys ja voit hallita tietojasi sekä keskustelujasi. Se antaa sinulle pääsyn avoimeen verkkoon; joten et ole jumissa Elementin käyttäjissä.
|
||||||
|
|
||||||
|
Element pystyy tekemään kaiken tämän, koska se toimii Matrixilla - avoimella, hajautetun viestinnän standardilla.
|
||||||
|
|
||||||
|
Element antaa sinulle hallinnan antamalla sinun valita, kuka isännöi keskustelujasi. Element-sovelluksessa voit valita isännän eri tavoin:
|
||||||
|
|
||||||
|
1. Hanki ilmainen tili Matrix-kehittäjien ylläpitämällä matrix.org-palvelimella tai valitse tuhansista vapaaehtoisten ylläpitämistä julkisista palvelimista.
|
||||||
|
2. Isännöi tiliäsi itse suorittamalla palvelinta omalla laitteellasi
|
||||||
|
3. Luo tili mukautetulla palvelimella yksinkertaisesti tilaamalla Element Matrix Services -palvelu
|
||||||
|
|
||||||
|
<b>Miksi valita Element?</b>
|
||||||
|
|
||||||
|
<b>OMAT TIEDOT</b>: Sinä päätät, missä tietosi ja viestisi säilytetään. Hallitset sitä itse, eikä jokin MEGAYHTIÖ, joka tutkii tietojasi tai antaa niitä kolmansille osapuolille.
|
||||||
|
|
||||||
|
<b>AVOIN KOMMUNIKOINYI JA YHTEISTYÖ</b>: Voit keskustella kaikkien muiden Matrix-verkon käyttäjien kanssa, riippumatta siitä käyttävätkö he Elementiä tai muuta Matrix-sovellusta, ja vaikka he käyttäisivät eri viestijärjestelmiä, kuten Slack, IRC tai XMPP.
|
||||||
|
|
||||||
|
<b>ERITTÄIN TURVALLINEN</b>: Vahva päästä päähän -salaus (vain keskustelussa olevat voivat purkaa viestien salauksen), ja ristiin varmentaminen keskustelun osallistujien laitteiden tarkistamiseksi.
|
||||||
|
|
||||||
|
<b>TÄYDELLISTÄ VIESTINTÄÄ</b>: Viestit, ääni- ja videopuhelut, tiedostojen jakaminen, näytön jakaminen ja koko joukko integraatioita, botteja ja widgettejä. Rakenna huoneita, yhteisöjä, pidä yhteyttä ja tee asioita.
|
||||||
|
|
||||||
|
<b>MISSÄ TAHANSA OLETKIN</b>: Pidä yhteyttä missä tahansa, täysin synkronoidun viestihistorian kautta kaikilla laitteillasi ja verkossa osoitteessa https://app.element.io.
|
@@ -1 +1 @@
|
|||||||
Turvallista, hajautettua keskustelua ja VoIP-puheluita. Pidä tietosi turvassa.
|
Turvallista, hajautettua, keskusteluja ja VoIP-puheluita. Pidä tietosi turvassa.
|
||||||
|
2
fastlane/metadata/android/it/changelogs/40100100.txt
Normal file
2
fastlane/metadata/android/it/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Questa nuova versione contiene soprattutto correzioni di errori e miglioramenti. L'invio di messaggi ora è molto più veloce.
|
||||||
|
Cronologia completa: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
1
fastlane/metadata/android/nb/short_description.txt
Normal file
1
fastlane/metadata/android/nb/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Sikker desentralisert chat & VoIP. Beskytt dataene dine fra tredjeparter.
|
1
fastlane/metadata/android/nb/title.txt
Normal file
1
fastlane/metadata/android/nb/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Element (tidligere Riot.im)
|
2
fastlane/metadata/android/pt_BR/changelogs/40100100.txt
Normal file
2
fastlane/metadata/android/pt_BR/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Esta nova versão contém principalmente correções de erros e melhorias. Enviar mensagens agora é muito mais rápido.
|
||||||
|
Registro de todas as alterações: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/sv/changelogs/40100100.txt
Normal file
2
fastlane/metadata/android/sv/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Den här nya versionen innehåller mest buggfixar och förbättringar. Det går nu mycket snabbare att skicka meddelanden.
|
||||||
|
Full ändringslogg: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
2
fastlane/metadata/android/uk/changelogs/40100100.txt
Normal file
2
fastlane/metadata/android/uk/changelogs/40100100.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Ця версія містить переважно виправлення помилок та деякі покращення. Відправлення повідомлень стало тепер ще швидшим.
|
||||||
|
Повний перелік змін: https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
@@ -7,7 +7,7 @@ Element — це застосунок для спілкування та спі
|
|||||||
|
|
||||||
Element ґрунтовно відрізняється від інших застосунків для спілкування та співпраці тому що він є децентралізованим та відкритоджерельним.
|
Element ґрунтовно відрізняється від інших застосунків для спілкування та співпраці тому що він є децентралізованим та відкритоджерельним.
|
||||||
|
|
||||||
Element дозволяє вам розміщувати сервер в себе або обирати будь-якого з надавачів послуг, таким чином забезпечуючи вам конфіденційність і можливість володіти власними даними й бесідами та контролювати їх. Він надає вам доступ до відкритої мережі, тож ви не є обмеженими спілкуванням виключно з користувачами Element. І він є дуже надійним та безпечним.
|
Element дозволяє вам розміщувати сервер в себе або обирати будь-якого з надавачів послуг, таким чином забезпечуючи вам конфіденційність і можливість володіти власними даними й бесідами та контролювати їх. Він надає вам доступ до відкритої мережі, тож ви не є обмеженими спілкуванням виключно з користувачами Element. І він є дуже надійним та безпечним.
|
||||||
|
|
||||||
Element здатен забезпечити усе це завдяки тому, що він заснований на протоколі Matrix — стандарті для відкритого та децентралізованого спілкування.
|
Element здатен забезпечити усе це завдяки тому, що він заснований на протоколі Matrix — стандарті для відкритого та децентралізованого спілкування.
|
||||||
|
|
||||||
|
@@ -0,0 +1,2 @@
|
|||||||
|
這個新版本主要包含錯誤修復與改善。傳送訊息更快了。
|
||||||
|
完整的變更紀錄請見:https://github.com/vector-im/element-android/releases/tag/v1.0.10
|
30
fastlane/metadata/android/zh_Hant/full_description.txt
Normal file
30
fastlane/metadata/android/zh_Hant/full_description.txt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
Element 是一種新型態的即時通訊軟體與協作應用程式:
|
||||||
|
|
||||||
|
1. 自己的隱私自己掌控
|
||||||
|
2. 讓您與任何在 Matrix 網路中的人通訊,甚至可與如 Slack 等的應用程式整合
|
||||||
|
3. 保護您免受廣告、資料採礦與圍牆花園的侵害
|
||||||
|
4. 透過端到端加密保護您,並使用交叉簽章來驗證其他人
|
||||||
|
|
||||||
|
Element 是去中心化且開放原始碼的應用程式,因此與其他即時通訊與協作軟體完全不同。
|
||||||
|
|
||||||
|
Element 讓您可以自架(或是自行選擇服務提供者)所以您擁有您資料與對話的隱私、所有權與控制權。它讓您可以存取開放的網路;因此,您不僅可以與其他 Matrix 使用者聊天。而且非常安全。
|
||||||
|
|
||||||
|
Element 能作到這些事情是因為它在 Matrix 上執行,這是一個開放的去中心化通訊的標準。
|
||||||
|
|
||||||
|
Element 讓您選擇您要在哪裡託管您的對話來將控制權還給您。在 Element 應用程式中,您可以選擇其他方式來託管:
|
||||||
|
|
||||||
|
1. 在由 Matrix 開發者架設的 matrix.org 公開伺服器上取得免費的帳號,或是從數千個由志願者所架設的公開伺服器中選擇
|
||||||
|
2. 在您自己的硬體上自行架設伺服器並建立帳號
|
||||||
|
3. 訂閱 Element Matrix 服務託管平台並在自訂伺服氣上註冊帳號
|
||||||
|
|
||||||
|
<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/zh_Hant/short_description.txt
Normal file
1
fastlane/metadata/android/zh_Hant/short_description.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
安全的去中心化聊天與 VoIP。確保您的資料不受第三方的影響。
|
1
fastlane/metadata/android/zh_Hant/title.txt
Normal file
1
fastlane/metadata/android/zh_Hant/title.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Element(曾名為 Riot.im)
|
@@ -18,7 +18,7 @@ org.gradle.jvmargs=-Xmx2048m
|
|||||||
org.gradle.vfs.watch=true
|
org.gradle.vfs.watch=true
|
||||||
|
|
||||||
vector.debugPrivateData=false
|
vector.debugPrivateData=false
|
||||||
vector.httpLogLevel=NONE
|
vector.httpLogLevel=BASIC
|
||||||
|
|
||||||
# Note: to debug, you can put and uncomment the following lines in the file ~/.gradle/gradle.properties to override the value above
|
# Note: to debug, you can put and uncomment the following lines in the file ~/.gradle/gradle.properties to override the value above
|
||||||
#vector.debugPrivateData=true
|
#vector.debugPrivateData=true
|
||||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=0080de8491f0918e4f529a6db6820fa0b9e818ee2386117f4394f95feb1d5583
|
distributionSha256Sum=22449f5231796abd892c98b2a07c9ceebe4688d192cd2d6763f8e3bf8acbedeb
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@@ -36,9 +36,10 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":matrix-sdk-android")
|
implementation project(":matrix-sdk-android")
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
|
||||||
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
|
||||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||||
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-rx2:$kotlin_coroutines_version"
|
||||||
|
|
||||||
// Paging
|
// Paging
|
||||||
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
|
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
|
||||||
|
|
||||||
|
@@ -21,34 +21,36 @@ import org.matrix.android.sdk.api.util.Cancelable
|
|||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
|
|
||||||
fun <T> singleBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Single<T> = Single.create {
|
fun <T> singleBuilder(builder: (MatrixCallback<T>) -> Cancelable): Single<T> = Single.create { emitter ->
|
||||||
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
|
val callback = object : MatrixCallback<T> {
|
||||||
override fun onSuccess(data: T) {
|
override fun onSuccess(data: T) {
|
||||||
it.onSuccess(data)
|
// Add `!!` to fix the warning:
|
||||||
|
// "Type mismatch: type parameter with nullable bounds is used T is used where T was expected. This warning will become an error soon"
|
||||||
|
emitter.onSuccess(data!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
override fun onFailure(failure: Throwable) {
|
||||||
it.tryOnError(failure)
|
emitter.tryOnError(failure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val cancelable = builder(callback)
|
val cancelable = builder(callback)
|
||||||
it.setCancellable {
|
emitter.setCancellable {
|
||||||
cancelable.cancel()
|
cancelable.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> completableBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Completable = Completable.create {
|
fun <T> completableBuilder(builder: (MatrixCallback<T>) -> Cancelable): Completable = Completable.create { emitter ->
|
||||||
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
|
val callback = object : MatrixCallback<T> {
|
||||||
override fun onSuccess(data: T) {
|
override fun onSuccess(data: T) {
|
||||||
it.onComplete()
|
emitter.onComplete()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
override fun onFailure(failure: Throwable) {
|
||||||
it.tryOnError(failure)
|
emitter.tryOnError(failure)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val cancelable = builder(callback)
|
val cancelable = builder(callback)
|
||||||
it.setCancellable {
|
emitter.setCancellable {
|
||||||
cancelable.cancel()
|
cancelable.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,14 +17,20 @@
|
|||||||
package org.matrix.android.sdk.rx
|
package org.matrix.android.sdk.rx
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import io.reactivex.Completable
|
||||||
|
import io.reactivex.Observable
|
||||||
|
import io.reactivex.Single
|
||||||
|
import kotlinx.coroutines.rx2.rxCompletable
|
||||||
import org.matrix.android.sdk.api.query.QueryStringValue
|
import org.matrix.android.sdk.api.query.QueryStringValue
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.identity.ThreePid
|
import org.matrix.android.sdk.api.session.identity.ThreePid
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
|
import org.matrix.android.sdk.api.session.room.members.RoomMemberQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
|
import org.matrix.android.sdk.api.session.room.model.EventAnnotationsSummary
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.GuestAccess
|
||||||
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
|
import org.matrix.android.sdk.api.session.room.model.ReadReceipt
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
import org.matrix.android.sdk.api.session.room.model.RoomHistoryVisibility
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomJoinRules
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
import org.matrix.android.sdk.api.session.room.notification.RoomNotificationState
|
||||||
@@ -32,9 +38,6 @@ import org.matrix.android.sdk.api.session.room.send.UserDraft
|
|||||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
import org.matrix.android.sdk.api.util.toOptional
|
import org.matrix.android.sdk.api.util.toOptional
|
||||||
import io.reactivex.Completable
|
|
||||||
import io.reactivex.Observable
|
|
||||||
import io.reactivex.Single
|
|
||||||
|
|
||||||
class RxRoom(private val room: Room) {
|
class RxRoom(private val room: Room) {
|
||||||
|
|
||||||
@@ -119,32 +122,28 @@ class RxRoom(private val room: Room) {
|
|||||||
room.invite3pid(threePid, it)
|
room.invite3pid(threePid, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateTopic(topic: String): Completable = completableBuilder<Unit> {
|
fun updateTopic(topic: String): Completable = rxCompletable {
|
||||||
room.updateTopic(topic, it)
|
room.updateTopic(topic)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateName(name: String): Completable = completableBuilder<Unit> {
|
fun updateName(name: String): Completable = rxCompletable {
|
||||||
room.updateName(name, it)
|
room.updateName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addRoomAlias(alias: String): Completable = completableBuilder<Unit> {
|
fun updateHistoryReadability(readability: RoomHistoryVisibility): Completable = rxCompletable {
|
||||||
room.addRoomAlias(alias, it)
|
room.updateHistoryReadability(readability)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateCanonicalAlias(alias: String): Completable = completableBuilder<Unit> {
|
fun updateJoinRule(joinRules: RoomJoinRules?, guestAccess: GuestAccess?): Completable = rxCompletable {
|
||||||
room.updateCanonicalAlias(alias, it)
|
room.updateJoinRule(joinRules, guestAccess)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateHistoryReadability(readability: RoomHistoryVisibility): Completable = completableBuilder<Unit> {
|
fun updateAvatar(avatarUri: Uri, fileName: String): Completable = rxCompletable {
|
||||||
room.updateHistoryReadability(readability, it)
|
room.updateAvatar(avatarUri, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateAvatar(avatarUri: Uri, fileName: String): Completable = completableBuilder<Unit> {
|
fun deleteAvatar(): Completable = rxCompletable {
|
||||||
room.updateAvatar(avatarUri, fileName, it)
|
room.deleteAvatar()
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteAvatar(): Completable = completableBuilder<Unit> {
|
|
||||||
room.deleteAvatar(it)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.identity.ThreePid
|
|||||||
import org.matrix.android.sdk.api.session.pushers.Pusher
|
import org.matrix.android.sdk.api.session.pushers.Pusher
|
||||||
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
import org.matrix.android.sdk.api.session.room.RoomSummaryQueryParams
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
import org.matrix.android.sdk.api.session.sync.SyncState
|
import org.matrix.android.sdk.api.session.sync.SyncState
|
||||||
@@ -46,6 +47,7 @@ import org.matrix.android.sdk.api.util.toOptional
|
|||||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
import org.matrix.android.sdk.internal.crypto.model.rest.DeviceInfo
|
||||||
import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
|
import org.matrix.android.sdk.internal.crypto.store.PrivateKeysInfo
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||||
|
|
||||||
class RxSession(private val session: Session) {
|
class RxSession(private val session: Session) {
|
||||||
|
|
||||||
@@ -92,6 +94,13 @@ class RxSession(private val session: Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun liveRoomMember(userId: String, roomId: String): Observable<Optional<RoomMemberSummary>> {
|
||||||
|
return session.getRoomMemberLive(userId, roomId).asObservable()
|
||||||
|
.startWithCallable {
|
||||||
|
session.getRoomMember(userId, roomId).toOptional()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun liveUsers(): Observable<List<User>> {
|
fun liveUsers(): Observable<List<User>> {
|
||||||
return session.getUsersLive().asObservable()
|
return session.getUsersLive().asObservable()
|
||||||
}
|
}
|
||||||
@@ -131,7 +140,7 @@ class RxSession(private val session: Session) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getRoomIdByAlias(roomAlias: String,
|
fun getRoomIdByAlias(roomAlias: String,
|
||||||
searchOnServer: Boolean): Single<Optional<String>> = singleBuilder {
|
searchOnServer: Boolean): Single<Optional<RoomAliasDescription>> = singleBuilder {
|
||||||
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
|
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply plugin: 'kotlin-kapt'
|
apply plugin: 'kotlin-kapt'
|
||||||
apply plugin: 'kotlin-android-extensions'
|
apply plugin: 'kotlin-parcelize'
|
||||||
apply plugin: 'realm-android'
|
apply plugin: 'realm-android'
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
@@ -9,14 +9,10 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "io.realm:realm-gradle-plugin:6.1.0"
|
classpath "io.realm:realm-gradle-plugin:10.1.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
androidExtensions {
|
|
||||||
experimental = true
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 29
|
||||||
testOptions.unitTests.includeAndroidResources = true
|
testOptions.unitTests.includeAndroidResources = true
|
||||||
@@ -63,7 +59,7 @@ android {
|
|||||||
|
|
||||||
release {
|
release {
|
||||||
buildConfigField "boolean", "LOG_PRIVATE_DATA", "false"
|
buildConfigField "boolean", "LOG_PRIVATE_DATA", "false"
|
||||||
buildConfigField "okhttp3.logging.HttpLoggingInterceptor.Level", "OKHTTP_LOGGING_LEVEL", "okhttp3.logging.HttpLoggingInterceptor.Level.NONE"
|
buildConfigField "okhttp3.logging.HttpLoggingInterceptor.Level", "OKHTTP_LOGGING_LEVEL", "okhttp3.logging.HttpLoggingInterceptor.Level.BASIC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +121,6 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
implementation "androidx.appcompat:appcompat:1.2.0"
|
||||||
implementation "androidx.fragment:fragment:1.3.0-beta01"
|
|
||||||
implementation "androidx.core:core-ktx:1.3.2"
|
implementation "androidx.core:core-ktx:1.3.2"
|
||||||
|
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||||
@@ -146,10 +141,10 @@ dependencies {
|
|||||||
implementation "ru.noties.markwon:core:$markwon_version"
|
implementation "ru.noties.markwon:core:$markwon_version"
|
||||||
|
|
||||||
// Image
|
// Image
|
||||||
implementation 'androidx.exifinterface:exifinterface:1.3.0'
|
implementation 'androidx.exifinterface:exifinterface:1.3.1'
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
|
implementation 'com.github.Zhuinden:realm-monarchy:0.7.1'
|
||||||
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
||||||
|
|
||||||
// Work
|
// Work
|
||||||
|
@@ -43,8 +43,8 @@ class ChangePasswordTest : InstrumentedTest {
|
|||||||
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
||||||
|
|
||||||
// Change password
|
// Change password
|
||||||
commonTestHelper.doSync<Unit> {
|
commonTestHelper.runBlockingTest {
|
||||||
session.changePassword(TestConstants.PASSWORD, NEW_PASSWORD, it)
|
session.changePassword(TestConstants.PASSWORD, NEW_PASSWORD)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to login with the previous password, it will fail
|
// Try to login with the previous password, it will fail
|
||||||
|
@@ -43,8 +43,8 @@ class DeactivateAccountTest : InstrumentedTest {
|
|||||||
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = false))
|
||||||
|
|
||||||
// Deactivate the account
|
// Deactivate the account
|
||||||
commonTestHelper.doSync<Unit> {
|
commonTestHelper.runBlockingTest {
|
||||||
session.deactivateAccount(TestConstants.PASSWORD, false, it)
|
session.deactivateAccount(TestConstants.PASSWORD, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to login on the previous account, it will fail (M_USER_DEACTIVATED)
|
// Try to login on the previous account, it will fail (M_USER_DEACTIVATED)
|
||||||
|
@@ -25,6 +25,7 @@ import androidx.work.WorkManager
|
|||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import org.matrix.android.sdk.BuildConfig
|
import org.matrix.android.sdk.BuildConfig
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
|
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
||||||
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
import org.matrix.android.sdk.common.DaggerTestMatrixComponent
|
import org.matrix.android.sdk.common.DaggerTestMatrixComponent
|
||||||
@@ -49,6 +50,7 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
|
|||||||
@Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
|
@Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
|
||||||
@Inject internal lateinit var olmManager: OlmManager
|
@Inject internal lateinit var olmManager: OlmManager
|
||||||
@Inject internal lateinit var sessionManager: SessionManager
|
@Inject internal lateinit var sessionManager: SessionManager
|
||||||
|
@Inject internal lateinit var homeServerHistoryService: HomeServerHistoryService
|
||||||
|
|
||||||
private val uiHandler = Handler(Looper.getMainLooper())
|
private val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
|
||||||
@@ -71,6 +73,8 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
|
|||||||
|
|
||||||
fun rawService() = rawService
|
fun rawService() = rawService
|
||||||
|
|
||||||
|
fun homeServerHistoryService() = homeServerHistoryService
|
||||||
|
|
||||||
fun legacySessionImporter(): LegacySessionImporter {
|
fun legacySessionImporter(): LegacySessionImporter {
|
||||||
return legacySessionImporter
|
return legacySessionImporter
|
||||||
}
|
}
|
||||||
|
@@ -40,6 +40,7 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.withTimeout
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
@@ -85,7 +86,7 @@ class CommonTestHelper(context: Context) {
|
|||||||
*
|
*
|
||||||
* @param session the session to sync
|
* @param session the session to sync
|
||||||
*/
|
*/
|
||||||
fun syncSession(session: Session) {
|
fun syncSession(session: Session, timeout: Long = TestConstants.timeOutMillis) {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
|
|
||||||
val job = GlobalScope.launch(Dispatchers.Main) {
|
val job = GlobalScope.launch(Dispatchers.Main) {
|
||||||
@@ -108,7 +109,7 @@ class CommonTestHelper(context: Context) {
|
|||||||
}
|
}
|
||||||
GlobalScope.launch(Dispatchers.Main) { syncLiveData.observeForever(syncObserver) }
|
GlobalScope.launch(Dispatchers.Main) { syncLiveData.observeForever(syncObserver) }
|
||||||
|
|
||||||
await(lock)
|
await(lock, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,7 +119,7 @@ class CommonTestHelper(context: Context) {
|
|||||||
* @param message the message to send
|
* @param message the message to send
|
||||||
* @param nbOfMessages the number of time the message will be sent
|
* @param nbOfMessages the number of time the message will be sent
|
||||||
*/
|
*/
|
||||||
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int): List<TimelineEvent> {
|
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int, timeout: Long = TestConstants.timeOutMillis): List<TimelineEvent> {
|
||||||
val timeline = room.createTimeline(null, TimelineSettings(10))
|
val timeline = room.createTimeline(null, TimelineSettings(10))
|
||||||
val sentEvents = ArrayList<TimelineEvent>(nbOfMessages)
|
val sentEvents = ArrayList<TimelineEvent>(nbOfMessages)
|
||||||
val latch = CountDownLatch(1)
|
val latch = CountDownLatch(1)
|
||||||
@@ -150,7 +151,7 @@ class CommonTestHelper(context: Context) {
|
|||||||
room.sendTextMessage(message + " #" + (i + 1))
|
room.sendTextMessage(message + " #" + (i + 1))
|
||||||
}
|
}
|
||||||
// Wait 3 second more per message
|
// Wait 3 second more per message
|
||||||
await(latch, timeout = TestConstants.timeOutMillis + 3_000L * nbOfMessages)
|
await(latch, timeout = timeout + 3_000L * nbOfMessages)
|
||||||
timeline.dispose()
|
timeline.dispose()
|
||||||
|
|
||||||
// Check that all events has been created
|
// Check that all events has been created
|
||||||
@@ -214,14 +215,14 @@ class CommonTestHelper(context: Context) {
|
|||||||
.getLoginFlow(hs, it)
|
.getLoginFlow(hs, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
doSync<RegistrationResult> {
|
doSync<RegistrationResult>(timeout = 60_000) {
|
||||||
matrix.authenticationService
|
matrix.authenticationService
|
||||||
.getRegistrationWizard()
|
.getRegistrationWizard()
|
||||||
.createAccount(userName, password, null, it)
|
.createAccount(userName, password, null, it)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform dummy step
|
// Perform dummy step
|
||||||
val registrationResult = doSync<RegistrationResult> {
|
val registrationResult = doSync<RegistrationResult>(timeout = 60_000) {
|
||||||
matrix.authenticationService
|
matrix.authenticationService
|
||||||
.getRegistrationWizard()
|
.getRegistrationWizard()
|
||||||
.dummy(it)
|
.dummy(it)
|
||||||
@@ -230,7 +231,7 @@ class CommonTestHelper(context: Context) {
|
|||||||
assertTrue(registrationResult is RegistrationResult.Success)
|
assertTrue(registrationResult is RegistrationResult.Success)
|
||||||
val session = (registrationResult as RegistrationResult.Success).session
|
val session = (registrationResult as RegistrationResult.Success).session
|
||||||
if (sessionTestParams.withInitialSync) {
|
if (sessionTestParams.withInitialSync) {
|
||||||
syncSession(session)
|
syncSession(session, 60_000)
|
||||||
}
|
}
|
||||||
|
|
||||||
return session
|
return session
|
||||||
@@ -343,6 +344,14 @@ class CommonTestHelper(context: Context) {
|
|||||||
await(latch, timeout)
|
await(latch, timeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> runBlockingTest(timeout: Long = TestConstants.timeOutMillis, block: suspend () -> T): T {
|
||||||
|
return runBlocking {
|
||||||
|
withTimeout(timeout) {
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Transform a method with a MatrixCallback to a synchronous method
|
// Transform a method with a MatrixCallback to a synchronous method
|
||||||
inline fun <reified T> doSync(timeout: Long? = TestConstants.timeOutMillis, block: (MatrixCallback<T>) -> Unit): T {
|
inline fun <reified T> doSync(timeout: Long? = TestConstants.timeOutMillis, block: (MatrixCallback<T>) -> Unit): T {
|
||||||
val lock = CountDownLatch(1)
|
val lock = CountDownLatch(1)
|
||||||
|
@@ -18,14 +18,21 @@ package org.matrix.android.sdk.common
|
|||||||
|
|
||||||
import org.matrix.android.sdk.api.session.Session
|
import org.matrix.android.sdk.api.session.Session
|
||||||
|
|
||||||
data class CryptoTestData(val firstSession: Session,
|
data class CryptoTestData(val roomId: String,
|
||||||
val roomId: String,
|
val sessions: List<Session>) {
|
||||||
val secondSession: Session? = null,
|
|
||||||
val thirdSession: Session? = null) {
|
val firstSession: Session
|
||||||
|
get() = sessions.first()
|
||||||
|
|
||||||
|
val secondSession: Session?
|
||||||
|
get() = sessions.getOrNull(1)
|
||||||
|
|
||||||
|
val thirdSession: Session?
|
||||||
|
get() = sessions.getOrNull(2)
|
||||||
|
|
||||||
fun cleanUp(testHelper: CommonTestHelper) {
|
fun cleanUp(testHelper: CommonTestHelper) {
|
||||||
testHelper.signOutAndClose(firstSession)
|
sessions.forEach {
|
||||||
secondSession?.let { testHelper.signOutAndClose(it) }
|
testHelper.signOutAndClose(it)
|
||||||
thirdSession?.let { testHelper.signOutAndClose(it) }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -68,12 +68,12 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
|
|||||||
if (encryptedRoom) {
|
if (encryptedRoom) {
|
||||||
val room = aliceSession.getRoom(roomId)!!
|
val room = aliceSession.getRoom(roomId)!!
|
||||||
|
|
||||||
mTestHelper.doSync<Unit> {
|
mTestHelper.runBlockingTest {
|
||||||
room.enableEncryption(callback = it)
|
room.enableEncryption()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CryptoTestData(aliceSession, roomId)
|
return CryptoTestData(roomId, listOf(aliceSession))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,7 +139,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
|
|||||||
// assertNotNull(roomFromBobPOV.powerLevels)
|
// assertNotNull(roomFromBobPOV.powerLevels)
|
||||||
// assertTrue(roomFromBobPOV.powerLevels.maySendMessage(bobSession.myUserId))
|
// assertTrue(roomFromBobPOV.powerLevels.maySendMessage(bobSession.myUserId))
|
||||||
|
|
||||||
return CryptoTestData(aliceSession, aliceRoomId, bobSession)
|
return CryptoTestData(aliceRoomId, listOf(aliceSession, bobSession))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,7 +157,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
|
|||||||
// wait the initial sync
|
// wait the initial sync
|
||||||
SystemClock.sleep(1000)
|
SystemClock.sleep(1000)
|
||||||
|
|
||||||
return CryptoTestData(aliceSession, aliceRoomId, cryptoTestData.secondSession, samSession)
|
return CryptoTestData(aliceRoomId, listOf(aliceSession, cryptoTestData.secondSession!!, samSession))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -381,4 +381,30 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun doE2ETestWithManyMembers(numberOfMembers: Int): CryptoTestData {
|
||||||
|
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
|
||||||
|
aliceSession.cryptoService().setWarnOnUnknownDevices(false)
|
||||||
|
|
||||||
|
val roomId = mTestHelper.doSync<String> {
|
||||||
|
aliceSession.createRoom(CreateRoomParams().apply { name = "MyRoom" }, it)
|
||||||
|
}
|
||||||
|
val room = aliceSession.getRoom(roomId)!!
|
||||||
|
|
||||||
|
mTestHelper.runBlockingTest {
|
||||||
|
room.enableEncryption()
|
||||||
|
}
|
||||||
|
|
||||||
|
val sessions = mutableListOf(aliceSession)
|
||||||
|
for (index in 1 until numberOfMembers) {
|
||||||
|
val session = mTestHelper.createAccount("User_$index", defaultSessionParams)
|
||||||
|
mTestHelper.doSync<Unit>(timeout = 600_000) { room.invite(session.myUserId, null, it) }
|
||||||
|
println("TEST -> " + session.myUserId + " invited")
|
||||||
|
mTestHelper.doSync<Unit> { session.joinRoom(room.roomId, null, emptyList(), it) }
|
||||||
|
println("TEST -> " + session.myUserId + " joined")
|
||||||
|
sessions.add(session)
|
||||||
|
}
|
||||||
|
|
||||||
|
return CryptoTestData(roomId, sessions)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -17,13 +17,13 @@
|
|||||||
package org.matrix.android.sdk.internal.crypto.encryption
|
package org.matrix.android.sdk.internal.crypto.encryption
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.amshove.kluent.shouldBe
|
import org.amshove.kluent.shouldBe
|
||||||
import org.junit.FixMethodOrder
|
import org.junit.FixMethodOrder
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.MethodSorters
|
import org.junit.runners.MethodSorters
|
||||||
import org.matrix.android.sdk.InstrumentedTest
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
import org.matrix.android.sdk.api.NoOpMatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.session.events.model.EventType
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
import org.matrix.android.sdk.api.session.events.model.toContent
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
import org.matrix.android.sdk.api.session.room.Room
|
import org.matrix.android.sdk.api.session.room.Room
|
||||||
@@ -57,13 +57,14 @@ class EncryptionTest : InstrumentedTest {
|
|||||||
@Test
|
@Test
|
||||||
fun test_EncryptionStateEvent() {
|
fun test_EncryptionStateEvent() {
|
||||||
performTest(roomShouldBeEncrypted = true) { room ->
|
performTest(roomShouldBeEncrypted = true) { room ->
|
||||||
// Send an encryption Event as a State Event
|
runBlocking {
|
||||||
room.sendStateEvent(
|
// Send an encryption Event as a State Event
|
||||||
eventType = EventType.STATE_ROOM_ENCRYPTION,
|
room.sendStateEvent(
|
||||||
stateKey = null,
|
eventType = EventType.STATE_ROOM_ENCRYPTION,
|
||||||
body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent(),
|
stateKey = null,
|
||||||
callback = NoOpMatrixCallback()
|
body = EncryptionEventContent(algorithm = MXCRYPTO_ALGORITHM_MEGOLM).toContent()
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -264,7 +264,7 @@ class KeysBackupTest : InstrumentedTest {
|
|||||||
assertNotNull(decryption)
|
assertNotNull(decryption)
|
||||||
// - Check decryptKeyBackupData() returns stg
|
// - Check decryptKeyBackupData() returns stg
|
||||||
val sessionData = keysBackup
|
val sessionData = keysBackup
|
||||||
.decryptKeyBackupData(keyBackupData!!,
|
.decryptKeyBackupData(keyBackupData,
|
||||||
session.olmInboundGroupSession!!.sessionIdentifier(),
|
session.olmInboundGroupSession!!.sessionIdentifier(),
|
||||||
cryptoTestData.roomId,
|
cryptoTestData.roomId,
|
||||||
decryption!!)
|
decryption!!)
|
||||||
|
@@ -111,7 +111,7 @@ class KeysBackupTestHelper(
|
|||||||
Assert.assertTrue(keysBackup.isEnabled)
|
Assert.assertTrue(keysBackup.isEnabled)
|
||||||
|
|
||||||
stateObserver.stopAndCheckStates(null)
|
stateObserver.stopAndCheckStates(null)
|
||||||
return PrepareKeysBackupDataResult(megolmBackupCreationInfo, keysVersion.version!!)
|
return PrepareKeysBackupDataResult(megolmBackupCreationInfo, keysVersion.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -555,7 +555,7 @@ class SASTest : InstrumentedTest {
|
|||||||
|
|
||||||
mTestHelper.waitWithLatch {
|
mTestHelper.waitWithLatch {
|
||||||
mTestHelper.retryPeriodicallyWithLatch(it) {
|
mTestHelper.retryPeriodicallyWithLatch(it) {
|
||||||
val prAlicePOV = aliceVerificationService.getExistingVerificationRequest(bobSession.myUserId)?.firstOrNull()
|
val prAlicePOV = aliceVerificationService.getExistingVerificationRequests(bobSession.myUserId).firstOrNull()
|
||||||
requestID = prAlicePOV?.transactionId
|
requestID = prAlicePOV?.transactionId
|
||||||
Log.v("TEST", "== alicePOV is $prAlicePOV")
|
Log.v("TEST", "== alicePOV is $prAlicePOV")
|
||||||
prAlicePOV?.transactionId != null && prAlicePOV.localId == req.localId
|
prAlicePOV?.transactionId != null && prAlicePOV.localId == req.localId
|
||||||
@@ -566,7 +566,7 @@ class SASTest : InstrumentedTest {
|
|||||||
|
|
||||||
mTestHelper.waitWithLatch {
|
mTestHelper.waitWithLatch {
|
||||||
mTestHelper.retryPeriodicallyWithLatch(it) {
|
mTestHelper.retryPeriodicallyWithLatch(it) {
|
||||||
val prBobPOV = bobVerificationService.getExistingVerificationRequest(aliceSession.myUserId)?.firstOrNull()
|
val prBobPOV = bobVerificationService.getExistingVerificationRequests(aliceSession.myUserId).firstOrNull()
|
||||||
Log.v("TEST", "== prBobPOV is $prBobPOV")
|
Log.v("TEST", "== prBobPOV is $prBobPOV")
|
||||||
prBobPOV?.transactionId == requestID
|
prBobPOV?.transactionId == requestID
|
||||||
}
|
}
|
||||||
@@ -581,7 +581,7 @@ class SASTest : InstrumentedTest {
|
|||||||
// wait for alice to get the ready
|
// wait for alice to get the ready
|
||||||
mTestHelper.waitWithLatch {
|
mTestHelper.waitWithLatch {
|
||||||
mTestHelper.retryPeriodicallyWithLatch(it) {
|
mTestHelper.retryPeriodicallyWithLatch(it) {
|
||||||
val prAlicePOV = aliceVerificationService.getExistingVerificationRequest(bobSession.myUserId)?.firstOrNull()
|
val prAlicePOV = aliceVerificationService.getExistingVerificationRequests(bobSession.myUserId).firstOrNull()
|
||||||
Log.v("TEST", "== prAlicePOV is $prAlicePOV")
|
Log.v("TEST", "== prAlicePOV is $prAlicePOV")
|
||||||
prAlicePOV?.transactionId == requestID && prAlicePOV?.isReady != null
|
prAlicePOV?.transactionId == requestID && prAlicePOV?.isReady != null
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.internal.session.media
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.EventType
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
internal class UrlsExtractorTest : InstrumentedTest {
|
||||||
|
|
||||||
|
private val urlsExtractor = UrlsExtractor()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun wrongEventTypeTest() {
|
||||||
|
createEvent(body = "https://matrix.org")
|
||||||
|
.copy(type = EventType.STATE_ROOM_GUEST_ACCESS)
|
||||||
|
.let { urlsExtractor.extract(it) }
|
||||||
|
.size shouldBeEqualTo 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun oneUrlTest() {
|
||||||
|
createEvent(body = "https://matrix.org")
|
||||||
|
.let { urlsExtractor.extract(it) }
|
||||||
|
.let { result ->
|
||||||
|
result.size shouldBeEqualTo 1
|
||||||
|
result[0] shouldBeEqualTo "https://matrix.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun withoutProtocolTest() {
|
||||||
|
createEvent(body = "www.matrix.org")
|
||||||
|
.let { urlsExtractor.extract(it) }
|
||||||
|
.size shouldBeEqualTo 0
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun oneUrlWithParamTest() {
|
||||||
|
createEvent(body = "https://matrix.org?foo=bar")
|
||||||
|
.let { urlsExtractor.extract(it) }
|
||||||
|
.let { result ->
|
||||||
|
result.size shouldBeEqualTo 1
|
||||||
|
result[0] shouldBeEqualTo "https://matrix.org?foo=bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun oneUrlWithParamsTest() {
|
||||||
|
createEvent(body = "https://matrix.org?foo=bar&bar=foo")
|
||||||
|
.let { urlsExtractor.extract(it) }
|
||||||
|
.let { result ->
|
||||||
|
result.size shouldBeEqualTo 1
|
||||||
|
result[0] shouldBeEqualTo "https://matrix.org?foo=bar&bar=foo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun oneUrlInlinedTest() {
|
||||||
|
createEvent(body = "Hello https://matrix.org, how are you?")
|
||||||
|
.let { urlsExtractor.extract(it) }
|
||||||
|
.let { result ->
|
||||||
|
result.size shouldBeEqualTo 1
|
||||||
|
result[0] shouldBeEqualTo "https://matrix.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun twoUrlsTest() {
|
||||||
|
createEvent(body = "https://matrix.org https://example.org")
|
||||||
|
.let { urlsExtractor.extract(it) }
|
||||||
|
.let { result ->
|
||||||
|
result.size shouldBeEqualTo 2
|
||||||
|
result[0] shouldBeEqualTo "https://matrix.org"
|
||||||
|
result[1] shouldBeEqualTo "https://example.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createEvent(body: String): Event = Event(
|
||||||
|
type = EventType.MESSAGE,
|
||||||
|
content = MessageTextContent(
|
||||||
|
msgType = MessageType.MSGTYPE_TEXT,
|
||||||
|
body = body
|
||||||
|
).toContent()
|
||||||
|
)
|
||||||
|
}
|
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.session.room.timeline
|
||||||
|
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.JUnit4
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.matrix.android.sdk.InstrumentedTest
|
||||||
|
import org.matrix.android.sdk.api.extensions.orFalse
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.toModel
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings
|
||||||
|
import org.matrix.android.sdk.common.CommonTestHelper
|
||||||
|
import org.matrix.android.sdk.common.CryptoTestHelper
|
||||||
|
import java.util.concurrent.CountDownLatch
|
||||||
|
import kotlin.test.fail
|
||||||
|
|
||||||
|
@RunWith(JUnit4::class)
|
||||||
|
@FixMethodOrder(MethodSorters.JVM)
|
||||||
|
class TimelineWithManyMembersTest : InstrumentedTest {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val NUMBER_OF_MEMBERS = 6
|
||||||
|
}
|
||||||
|
|
||||||
|
private val commonTestHelper = CommonTestHelper(context())
|
||||||
|
private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures when someone sends a message to a crowded room, everyone can decrypt the message.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
fun everyone_should_decrypt_message_in_a_crowded_room() {
|
||||||
|
val cryptoTestData = cryptoTestHelper.doE2ETestWithManyMembers(NUMBER_OF_MEMBERS)
|
||||||
|
|
||||||
|
val sessionForFirstMember = cryptoTestData.firstSession
|
||||||
|
val roomForFirstMember = sessionForFirstMember.getRoom(cryptoTestData.roomId)!!
|
||||||
|
|
||||||
|
val firstMessage = "First messages from Alice"
|
||||||
|
commonTestHelper.sendTextMessage(
|
||||||
|
roomForFirstMember,
|
||||||
|
firstMessage,
|
||||||
|
1,
|
||||||
|
600_000
|
||||||
|
)
|
||||||
|
|
||||||
|
for (index in 1 until cryptoTestData.sessions.size) {
|
||||||
|
val session = cryptoTestData.sessions[index]
|
||||||
|
val roomForCurrentMember = session.getRoom(cryptoTestData.roomId)!!
|
||||||
|
val timelineForCurrentMember = roomForCurrentMember.createTimeline(null, TimelineSettings(30))
|
||||||
|
timelineForCurrentMember.start()
|
||||||
|
|
||||||
|
session.startSync(true)
|
||||||
|
|
||||||
|
run {
|
||||||
|
val lock = CountDownLatch(1)
|
||||||
|
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
|
||||||
|
snapshot
|
||||||
|
.find { it.isEncrypted() }
|
||||||
|
?.let {
|
||||||
|
val body = it.root.getClearContent()?.toModel<MessageContent>()?.body
|
||||||
|
if (body?.startsWith(firstMessage).orFalse()) {
|
||||||
|
println("User " + session.myUserId + " decrypted as " + body)
|
||||||
|
return@createEventListener true
|
||||||
|
} else {
|
||||||
|
fail("User " + session.myUserId + " decrypted as " + body + " CryptoError: " + it.root.mCryptoError)
|
||||||
|
}
|
||||||
|
} ?: return@createEventListener false
|
||||||
|
}
|
||||||
|
timelineForCurrentMember.addListener(eventsListener)
|
||||||
|
commonTestHelper.await(lock, 600_000)
|
||||||
|
}
|
||||||
|
session.stopSync()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -71,38 +71,27 @@ class SearchMessagesTest : InstrumentedTest {
|
|||||||
commonTestHelper.await(lock)
|
commonTestHelper.await(lock)
|
||||||
|
|
||||||
lock = CountDownLatch(1)
|
lock = CountDownLatch(1)
|
||||||
aliceSession
|
val data = commonTestHelper.runBlockingTest {
|
||||||
.searchService()
|
aliceSession
|
||||||
.search(
|
.searchService()
|
||||||
searchTerm = "lore",
|
.search(
|
||||||
limit = 10,
|
searchTerm = "lore",
|
||||||
includeProfile = true,
|
limit = 10,
|
||||||
afterLimit = 0,
|
includeProfile = true,
|
||||||
beforeLimit = 10,
|
afterLimit = 0,
|
||||||
orderByRecent = true,
|
beforeLimit = 10,
|
||||||
nextBatch = null,
|
orderByRecent = true,
|
||||||
roomId = aliceRoomId,
|
nextBatch = null,
|
||||||
callback = object : MatrixCallback<SearchResult> {
|
roomId = aliceRoomId
|
||||||
override fun onSuccess(data: SearchResult) {
|
)
|
||||||
super.onSuccess(data)
|
}
|
||||||
assertTrue(data.results?.size == 2)
|
assertTrue(data.results?.size == 2)
|
||||||
assertTrue(
|
assertTrue(
|
||||||
data.results
|
data.results
|
||||||
?.all {
|
?.all {
|
||||||
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
|
(it.event.content?.get("body") as? String)?.startsWith(MESSAGE).orFalse()
|
||||||
}.orFalse()
|
}.orFalse()
|
||||||
)
|
)
|
||||||
lock.countDown()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailure(failure: Throwable) {
|
|
||||||
super.onFailure(failure)
|
|
||||||
fail(failure.localizedMessage)
|
|
||||||
lock.countDown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
lock.await(TestConstants.timeOutMillis, TimeUnit.MILLISECONDS)
|
|
||||||
|
|
||||||
aliceTimeline.removeAllListeners()
|
aliceTimeline.removeAllListeners()
|
||||||
cryptoTestData.cleanUp(commonTestHelper)
|
cryptoTestData.cleanUp(commonTestHelper)
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
package org.matrix.android.sdk.internal.network.interceptors
|
package org.matrix.android.sdk.internal.network.interceptors
|
||||||
|
|
||||||
import androidx.annotation.NonNull
|
import androidx.annotation.NonNull
|
||||||
import org.matrix.android.sdk.BuildConfig
|
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
@@ -38,37 +37,34 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
|||||||
*/
|
*/
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun log(@NonNull message: String) {
|
override fun log(@NonNull message: String) {
|
||||||
// In RELEASE there is no log, but for sure, test again BuildConfig.DEBUG
|
Timber.v(message)
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
Timber.v(message)
|
|
||||||
|
|
||||||
if (message.startsWith("{")) {
|
if (message.startsWith("{")) {
|
||||||
// JSON Detected
|
// JSON Detected
|
||||||
try {
|
try {
|
||||||
val o = JSONObject(message)
|
val o = JSONObject(message)
|
||||||
logJson(o.toString(INDENT_SPACE))
|
logJson(o.toString(INDENT_SPACE))
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
// Finally this is not a JSON string...
|
// Finally this is not a JSON string...
|
||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
}
|
}
|
||||||
} else if (message.startsWith("[")) {
|
} else if (message.startsWith("[")) {
|
||||||
// JSON Array detected
|
// JSON Array detected
|
||||||
try {
|
try {
|
||||||
val o = JSONArray(message)
|
val o = JSONArray(message)
|
||||||
logJson(o.toString(INDENT_SPACE))
|
logJson(o.toString(INDENT_SPACE))
|
||||||
} catch (e: JSONException) {
|
} catch (e: JSONException) {
|
||||||
// Finally not JSON...
|
// Finally not JSON...
|
||||||
Timber.e(e)
|
Timber.e(e)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Else not a json string to log
|
|
||||||
}
|
}
|
||||||
|
// Else not a json string to log
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logJson(formattedJson: String) {
|
private fun logJson(formattedJson: String) {
|
||||||
val arr = formattedJson.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
formattedJson
|
||||||
for (s in arr) {
|
.lines()
|
||||||
Timber.v(s)
|
.dropLastWhile { it.isEmpty() }
|
||||||
}
|
.forEach { Timber.v(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,7 @@ import androidx.work.WorkManager
|
|||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import org.matrix.android.sdk.BuildConfig
|
import org.matrix.android.sdk.BuildConfig
|
||||||
import org.matrix.android.sdk.api.auth.AuthenticationService
|
import org.matrix.android.sdk.api.auth.AuthenticationService
|
||||||
|
import org.matrix.android.sdk.api.auth.HomeServerHistoryService
|
||||||
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
import org.matrix.android.sdk.api.legacy.LegacySessionImporter
|
||||||
import org.matrix.android.sdk.api.raw.RawService
|
import org.matrix.android.sdk.api.raw.RawService
|
||||||
import org.matrix.android.sdk.internal.SessionManager
|
import org.matrix.android.sdk.internal.SessionManager
|
||||||
@@ -47,6 +48,7 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
|
|||||||
@Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
|
@Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
|
||||||
@Inject internal lateinit var olmManager: OlmManager
|
@Inject internal lateinit var olmManager: OlmManager
|
||||||
@Inject internal lateinit var sessionManager: SessionManager
|
@Inject internal lateinit var sessionManager: SessionManager
|
||||||
|
@Inject internal lateinit var homeServerHistoryService: HomeServerHistoryService
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Monarchy.init(context)
|
Monarchy.init(context)
|
||||||
@@ -65,6 +67,8 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
|
|||||||
|
|
||||||
fun rawService() = rawService
|
fun rawService() = rawService
|
||||||
|
|
||||||
|
fun homeServerHistoryService() = homeServerHistoryService
|
||||||
|
|
||||||
fun legacySessionImporter(): LegacySessionImporter {
|
fun legacySessionImporter(): LegacySessionImporter {
|
||||||
return legacySessionImporter
|
return legacySessionImporter
|
||||||
}
|
}
|
||||||
|
@@ -41,6 +41,16 @@ interface AuthenticationService {
|
|||||||
*/
|
*/
|
||||||
fun getLoginFlowOfSession(sessionId: String, callback: MatrixCallback<LoginFlowResult>): Cancelable
|
fun getLoginFlowOfSession(sessionId: String, callback: MatrixCallback<LoginFlowResult>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a SSO url
|
||||||
|
*/
|
||||||
|
fun getSsoUrl(redirectUrl: String, deviceId: String?, providerId: String?): String?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the sign in or sign up fallback URL
|
||||||
|
*/
|
||||||
|
fun getFallbackUrl(forSignIn: Boolean, deviceId: String?): String?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a LoginWizard, to login to the homeserver. The login flow has to be retrieved first.
|
* Return a LoginWizard, to login to the homeserver. The login flow has to be retrieved first.
|
||||||
*/
|
*/
|
||||||
|
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.auth
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple service to remember homeservers you already connected to.
|
||||||
|
*/
|
||||||
|
interface HomeServerHistoryService {
|
||||||
|
|
||||||
|
fun getKnownServersUrls(): List<String>
|
||||||
|
|
||||||
|
fun addHomeServerToHistory(url: String)
|
||||||
|
|
||||||
|
fun clearHistory()
|
||||||
|
}
|
@@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.auth.data
|
|||||||
sealed class LoginFlowResult {
|
sealed class LoginFlowResult {
|
||||||
data class Success(
|
data class Success(
|
||||||
val supportedLoginTypes: List<String>,
|
val supportedLoginTypes: List<String>,
|
||||||
|
val ssoIdentityProviders: List<SsoIdentityProvider>?,
|
||||||
val isLoginAndRegistrationSupported: Boolean,
|
val isLoginAndRegistrationSupported: Boolean,
|
||||||
val homeServerUrl: String,
|
val homeServerUrl: String,
|
||||||
val isOutdatedHomeserver: Boolean
|
val isOutdatedHomeserver: Boolean
|
||||||
|
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.auth.data
|
||||||
|
|
||||||
|
import android.os.Parcelable
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
@Parcelize
|
||||||
|
data class SsoIdentityProvider(
|
||||||
|
/**
|
||||||
|
* The id field would be opaque with the accepted characters matching unreserved URI characters as defined in RFC3986
|
||||||
|
* - this was chosen to avoid having to encode special characters in the URL. Max length 128.
|
||||||
|
*/
|
||||||
|
@Json(name = "id") val id: String,
|
||||||
|
/**
|
||||||
|
* The name field should be the human readable string intended for printing by the client.
|
||||||
|
*/
|
||||||
|
@Json(name = "name") val name: String?,
|
||||||
|
/**
|
||||||
|
* The icon field is the only optional field and should point to an icon representing the IdP.
|
||||||
|
* If present then it must be an HTTPS URL to an image resource.
|
||||||
|
* This should be hosted by the homeserver service provider to not leak the client's IP address unnecessarily.
|
||||||
|
*/
|
||||||
|
@Json(name = "icon") val iconUrl: String?
|
||||||
|
) : Parcelable {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// Not really defined by the spec, but we may define some ids here
|
||||||
|
const val ID_GOOGLE = "google"
|
||||||
|
const val ID_GITHUB = "github"
|
||||||
|
const val ID_APPLE = "apple"
|
||||||
|
const val ID_FACEBOOK = "facebook"
|
||||||
|
const val ID_TWITTER = "twitter"
|
||||||
|
}
|
||||||
|
}
|
@@ -27,7 +27,7 @@ interface LoginWizard {
|
|||||||
* @param password the password field
|
* @param password the password field
|
||||||
* @param deviceName the initial device name
|
* @param deviceName the initial device name
|
||||||
* @param callback the matrix callback on which you'll receive the result of authentication.
|
* @param callback the matrix callback on which you'll receive the result of authentication.
|
||||||
* @return return a [Cancelable]
|
* @return a [Cancelable]
|
||||||
*/
|
*/
|
||||||
fun login(login: String,
|
fun login(login: String,
|
||||||
password: String,
|
password: String,
|
||||||
|
@@ -14,16 +14,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.matrix.android.sdk.api.raw
|
package org.matrix.android.sdk.api.cache
|
||||||
|
|
||||||
sealed class RawCacheStrategy {
|
sealed class CacheStrategy {
|
||||||
// Data is always fetched from the server
|
// Data is always fetched from the server
|
||||||
object NoCache : RawCacheStrategy()
|
object NoCache : CacheStrategy()
|
||||||
|
|
||||||
// Once data is retrieved, it is stored for the provided amount of time.
|
// Once data is retrieved, it is stored for the provided amount of time.
|
||||||
// In case of error, and if strict is set to false, the cache can be returned if available
|
// In case of error, and if strict is set to false, the cache can be returned if available
|
||||||
data class TtlCache(val validityDurationInMillis: Long, val strict: Boolean) : RawCacheStrategy()
|
data class TtlCache(val validityDurationInMillis: Long, val strict: Boolean) : CacheStrategy()
|
||||||
|
|
||||||
// Once retrieved, the data is stored in cache and will be always get from the cache
|
// Once retrieved, the data is stored in cache and will be always get from the cache
|
||||||
object InfiniteCache : RawCacheStrategy()
|
object InfiniteCache : CacheStrategy()
|
||||||
}
|
}
|
@@ -22,3 +22,8 @@ fun CharSequence.ensurePrefix(prefix: CharSequence): CharSequence {
|
|||||||
else -> "$prefix$this"
|
else -> "$prefix$this"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a new line and then the provided string
|
||||||
|
*/
|
||||||
|
fun StringBuilder.appendNl(str: String) = append("\n").append(str)
|
||||||
|
@@ -15,11 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package org.matrix.android.sdk.api.pushrules
|
package org.matrix.android.sdk.api.pushrules
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.pushrules.rest.PushRule
|
import org.matrix.android.sdk.api.pushrules.rest.PushRule
|
||||||
import org.matrix.android.sdk.api.pushrules.rest.RuleSet
|
import org.matrix.android.sdk.api.pushrules.rest.RuleSet
|
||||||
import org.matrix.android.sdk.api.session.events.model.Event
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
interface PushRuleService {
|
interface PushRuleService {
|
||||||
/**
|
/**
|
||||||
@@ -29,13 +27,13 @@ interface PushRuleService {
|
|||||||
|
|
||||||
fun getPushRules(scope: String = RuleScope.GLOBAL): RuleSet
|
fun getPushRules(scope: String = RuleScope.GLOBAL): RuleSet
|
||||||
|
|
||||||
fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean)
|
||||||
|
|
||||||
fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun addPushRule(kind: RuleKind, pushRule: PushRule)
|
||||||
|
|
||||||
fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule)
|
||||||
|
|
||||||
fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun removePushRule(kind: RuleKind, pushRule: PushRule)
|
||||||
|
|
||||||
fun addPushRuleListener(listener: PushRuleListener)
|
fun addPushRuleListener(listener: PushRuleListener)
|
||||||
|
|
||||||
|
@@ -16,8 +16,7 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.raw
|
package org.matrix.android.sdk.api.raw
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.cache.CacheStrategy
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Useful methods to fetch raw data from the server. The access token will not be used to fetched the data
|
* Useful methods to fetch raw data from the server. The access token will not be used to fetched the data
|
||||||
@@ -26,17 +25,15 @@ interface RawService {
|
|||||||
/**
|
/**
|
||||||
* Get a URL, either from cache or from the remote server, depending on the cache strategy
|
* Get a URL, either from cache or from the remote server, depending on the cache strategy
|
||||||
*/
|
*/
|
||||||
fun getUrl(url: String,
|
suspend fun getUrl(url: String, cacheStrategy: CacheStrategy): String
|
||||||
rawCacheStrategy: RawCacheStrategy,
|
|
||||||
matrixCallback: MatrixCallback<String>): Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific case for the well-known file. Cache validity is 8 hours
|
* Specific case for the well-known file. Cache validity is 8 hours
|
||||||
*/
|
*/
|
||||||
fun getWellknown(userId: String, matrixCallback: MatrixCallback<String>): Cancelable
|
suspend fun getWellknown(userId: String): String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all the cache data
|
* Clear all the cache data
|
||||||
*/
|
*/
|
||||||
fun clearCache(matrixCallback: MatrixCallback<Unit>): Cancelable
|
suspend fun clearCache()
|
||||||
}
|
}
|
||||||
|
@@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.group.GroupService
|
|||||||
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
|
import org.matrix.android.sdk.api.session.homeserver.HomeServerCapabilitiesService
|
||||||
import org.matrix.android.sdk.api.session.identity.IdentityService
|
import org.matrix.android.sdk.api.session.identity.IdentityService
|
||||||
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
import org.matrix.android.sdk.api.session.integrationmanager.IntegrationManagerService
|
||||||
|
import org.matrix.android.sdk.api.session.media.MediaService
|
||||||
import org.matrix.android.sdk.api.session.permalinks.PermalinkService
|
import org.matrix.android.sdk.api.session.permalinks.PermalinkService
|
||||||
import org.matrix.android.sdk.api.session.profile.ProfileService
|
import org.matrix.android.sdk.api.session.profile.ProfileService
|
||||||
import org.matrix.android.sdk.api.session.pushers.PushersService
|
import org.matrix.android.sdk.api.session.pushers.PushersService
|
||||||
@@ -181,6 +182,11 @@ interface Session :
|
|||||||
*/
|
*/
|
||||||
fun widgetService(): WidgetService
|
fun widgetService(): WidgetService
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the media service associated with the session
|
||||||
|
*/
|
||||||
|
fun mediaService(): MediaService
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the integration manager service associated with the session
|
* Returns the integration manager service associated with the session
|
||||||
*/
|
*/
|
||||||
|
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.account
|
package org.matrix.android.sdk.api.session.account
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to manage the account. It's implemented at the session level.
|
* This interface defines methods to manage the account. It's implemented at the session level.
|
||||||
*/
|
*/
|
||||||
@@ -28,7 +25,7 @@ interface AccountService {
|
|||||||
* @param password Current password.
|
* @param password Current password.
|
||||||
* @param newPassword New password
|
* @param newPassword New password
|
||||||
*/
|
*/
|
||||||
fun changePassword(password: String, newPassword: String, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun changePassword(password: String, newPassword: String)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivate the account.
|
* Deactivate the account.
|
||||||
@@ -46,5 +43,5 @@ interface AccountService {
|
|||||||
* @param eraseAllData set to true to forget all messages that have been sent. Warning: this will cause future users to see
|
* @param eraseAllData set to true to forget all messages that have been sent. Warning: this will cause future users to see
|
||||||
* an incomplete view of conversations
|
* an incomplete view of conversations
|
||||||
*/
|
*/
|
||||||
fun deactivateAccount(password: String, eraseAllData: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun deactivateAccount(password: String, eraseAllData: Boolean)
|
||||||
}
|
}
|
||||||
|
@@ -36,7 +36,7 @@ sealed class CallState {
|
|||||||
* Connected. Incoming/Outgoing call, ice layer connecting or connected
|
* Connected. Incoming/Outgoing call, ice layer connecting or connected
|
||||||
* Notice that the PeerState failed is not always final, if you switch network, new ice candidtates
|
* Notice that the PeerState failed is not always final, if you switch network, new ice candidtates
|
||||||
* could be exchanged, and the connection could go back to connected
|
* could be exchanged, and the connection could go back to connected
|
||||||
* */
|
*/
|
||||||
data class Connected(val iceConnectionState: PeerConnection.PeerConnectionState) : CallState()
|
data class Connected(val iceConnectionState: PeerConnection.PeerConnectionState) : CallState()
|
||||||
|
|
||||||
/** Terminated. Incoming/Outgoing call, the call is terminated */
|
/** Terminated. Incoming/Outgoing call, the call is terminated */
|
||||||
|
@@ -20,7 +20,8 @@ import android.net.Uri
|
|||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import org.matrix.android.sdk.api.util.MimeTypes.normalizeMimeType
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
@@ -45,5 +46,5 @@ data class ContentAttachmentData(
|
|||||||
VIDEO
|
VIDEO
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSafeMimeType() = if (mimeType == "image/jpg") "image/jpeg" else mimeType
|
fun getSafeMimeType() = mimeType?.normalizeMimeType()
|
||||||
}
|
}
|
||||||
|
@@ -41,7 +41,7 @@ interface VerificationService {
|
|||||||
|
|
||||||
fun getExistingTransaction(otherUserId: String, tid: String): VerificationTransaction?
|
fun getExistingTransaction(otherUserId: String, tid: String): VerificationTransaction?
|
||||||
|
|
||||||
fun getExistingVerificationRequest(otherUserId: String): List<PendingVerificationRequest>?
|
fun getExistingVerificationRequests(otherUserId: String): List<PendingVerificationRequest>
|
||||||
|
|
||||||
fun getExistingVerificationRequest(otherUserId: String, tid: String?): PendingVerificationRequest?
|
fun getExistingVerificationRequest(otherUserId: String, tid: String?): PendingVerificationRequest?
|
||||||
|
|
||||||
|
@@ -49,6 +49,12 @@ object EventType {
|
|||||||
const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
|
const val STATE_ROOM_JOIN_RULES = "m.room.join_rules"
|
||||||
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
const val STATE_ROOM_GUEST_ACCESS = "m.room.guest_access"
|
||||||
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
const val STATE_ROOM_POWER_LEVELS = "m.room.power_levels"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that this Event has been deprecated, see
|
||||||
|
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
|
||||||
|
* - https://github.com/matrix-org/matrix-doc/pull/2432
|
||||||
|
*/
|
||||||
const val STATE_ROOM_ALIASES = "m.room.aliases"
|
const val STATE_ROOM_ALIASES = "m.room.aliases"
|
||||||
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
const val STATE_ROOM_TOMBSTONE = "m.room.tombstone"
|
||||||
const val STATE_ROOM_CANONICAL_ALIAS = "m.room.canonical_alias"
|
const val STATE_ROOM_CANONICAL_ALIAS = "m.room.canonical_alias"
|
||||||
@@ -56,6 +62,7 @@ object EventType {
|
|||||||
const val STATE_ROOM_RELATED_GROUPS = "m.room.related_groups"
|
const val STATE_ROOM_RELATED_GROUPS = "m.room.related_groups"
|
||||||
const val STATE_ROOM_PINNED_EVENT = "m.room.pinned_events"
|
const val STATE_ROOM_PINNED_EVENT = "m.room.pinned_events"
|
||||||
const val STATE_ROOM_ENCRYPTION = "m.room.encryption"
|
const val STATE_ROOM_ENCRYPTION = "m.room.encryption"
|
||||||
|
const val STATE_ROOM_SERVER_ACL = "m.room.server_acl"
|
||||||
|
|
||||||
// Call Events
|
// Call Events
|
||||||
const val CALL_INVITE = "m.call.invite"
|
const val CALL_INVITE = "m.call.invite"
|
||||||
|
@@ -18,8 +18,12 @@ package org.matrix.android.sdk.api.session.file
|
|||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.message.MessageWithAttachmentContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.message.getFileName
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
import org.matrix.android.sdk.api.util.Cancelable
|
||||||
import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
|
import org.matrix.android.sdk.internal.crypto.attachments.ElementToDecrypt
|
||||||
|
import org.matrix.android.sdk.internal.crypto.attachments.toElementToDecrypt
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -27,23 +31,6 @@ import java.io.File
|
|||||||
*/
|
*/
|
||||||
interface FileService {
|
interface FileService {
|
||||||
|
|
||||||
enum class DownloadMode {
|
|
||||||
/**
|
|
||||||
* Download file in external storage
|
|
||||||
*/
|
|
||||||
TO_EXPORT,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Download file in cache
|
|
||||||
*/
|
|
||||||
FOR_INTERNAL_USE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Download file in file provider path
|
|
||||||
*/
|
|
||||||
FOR_EXTERNAL_SHARE
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class FileState {
|
enum class FileState {
|
||||||
IN_CACHE,
|
IN_CACHE,
|
||||||
DOWNLOADING,
|
DOWNLOADING,
|
||||||
@@ -54,34 +41,79 @@ interface FileService {
|
|||||||
* Download a file.
|
* Download a file.
|
||||||
* Result will be a decrypted file, stored in the cache folder. url parameter will be used to create unique filename to avoid name collision.
|
* Result will be a decrypted file, stored in the cache folder. url parameter will be used to create unique filename to avoid name collision.
|
||||||
*/
|
*/
|
||||||
fun downloadFile(
|
fun downloadFile(fileName: String,
|
||||||
downloadMode: DownloadMode,
|
mimeType: String?,
|
||||||
id: String,
|
url: String?,
|
||||||
fileName: String,
|
elementToDecrypt: ElementToDecrypt?,
|
||||||
mimeType: String?,
|
callback: MatrixCallback<File>): Cancelable
|
||||||
url: String?,
|
|
||||||
elementToDecrypt: ElementToDecrypt?,
|
|
||||||
callback: MatrixCallback<File>): Cancelable
|
|
||||||
|
|
||||||
fun isFileInCache(mxcUrl: String, mimeType: String?): Boolean
|
fun downloadFile(messageContent: MessageWithAttachmentContent,
|
||||||
|
callback: MatrixCallback<File>): Cancelable =
|
||||||
|
downloadFile(
|
||||||
|
fileName = messageContent.getFileName(),
|
||||||
|
mimeType = messageContent.mimeType,
|
||||||
|
url = messageContent.getFileUrl(),
|
||||||
|
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt(),
|
||||||
|
callback = callback
|
||||||
|
)
|
||||||
|
|
||||||
|
fun isFileInCache(mxcUrl: String?,
|
||||||
|
fileName: String,
|
||||||
|
mimeType: String?,
|
||||||
|
elementToDecrypt: ElementToDecrypt?
|
||||||
|
): Boolean
|
||||||
|
|
||||||
|
fun isFileInCache(messageContent: MessageWithAttachmentContent) =
|
||||||
|
isFileInCache(
|
||||||
|
mxcUrl = messageContent.getFileUrl(),
|
||||||
|
fileName = messageContent.getFileName(),
|
||||||
|
mimeType = messageContent.mimeType,
|
||||||
|
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Use this URI and pass it to intent using flag Intent.FLAG_GRANT_READ_URI_PERMISSION
|
* Use this URI and pass it to intent using flag Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||||
* (if not other app won't be able to access it)
|
* (if not other app won't be able to access it)
|
||||||
*/
|
*/
|
||||||
fun getTemporarySharableURI(mxcUrl: String, mimeType: String?): Uri?
|
fun getTemporarySharableURI(mxcUrl: String?,
|
||||||
|
fileName: String,
|
||||||
|
mimeType: String?,
|
||||||
|
elementToDecrypt: ElementToDecrypt?): Uri?
|
||||||
|
|
||||||
|
fun getTemporarySharableURI(messageContent: MessageWithAttachmentContent): Uri? =
|
||||||
|
getTemporarySharableURI(
|
||||||
|
mxcUrl = messageContent.getFileUrl(),
|
||||||
|
fileName = messageContent.getFileName(),
|
||||||
|
mimeType = messageContent.mimeType,
|
||||||
|
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt()
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get information on the given file.
|
* Get information on the given file.
|
||||||
* Mimetype should be the same one as passed to downloadFile (limitation for now)
|
* Mimetype should be the same one as passed to downloadFile (limitation for now)
|
||||||
*/
|
*/
|
||||||
fun fileState(mxcUrl: String, mimeType: String?): FileState
|
fun fileState(mxcUrl: String?,
|
||||||
|
fileName: String,
|
||||||
|
mimeType: String?,
|
||||||
|
elementToDecrypt: ElementToDecrypt?): FileState
|
||||||
|
|
||||||
|
fun fileState(messageContent: MessageWithAttachmentContent): FileState =
|
||||||
|
fileState(
|
||||||
|
mxcUrl = messageContent.getFileUrl(),
|
||||||
|
fileName = messageContent.getFileName(),
|
||||||
|
mimeType = messageContent.mimeType,
|
||||||
|
elementToDecrypt = messageContent.encryptedFileInfo?.toElementToDecrypt()
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all the files downloaded by the service
|
* Clears all the files downloaded by the service, including decrypted files
|
||||||
*/
|
*/
|
||||||
fun clearCache()
|
fun clearCache()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all the decrypted files by the service
|
||||||
|
*/
|
||||||
|
fun clearDecryptedCache()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get size of cached files
|
* Get size of cached files
|
||||||
*/
|
*/
|
||||||
|
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.group
|
package org.matrix.android.sdk.api.session.group
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to interact within a group.
|
* This interface defines methods to interact within a group.
|
||||||
*/
|
*/
|
||||||
@@ -28,8 +25,7 @@ interface Group {
|
|||||||
/**
|
/**
|
||||||
* This methods allows you to refresh data about this group. It will be reflected on the GroupSummary.
|
* This methods allows you to refresh data about this group. It will be reflected on the GroupSummary.
|
||||||
* The SDK also takes care of refreshing group data every hour.
|
* The SDK also takes care of refreshing group data every hour.
|
||||||
* @param callback : the matrix callback to be notified of success or failure
|
|
||||||
* @return a Cancelable to be able to cancel requests.
|
* @return a Cancelable to be able to cancel requests.
|
||||||
*/
|
*/
|
||||||
fun fetchGroupData(callback: MatrixCallback<Unit>): Cancelable
|
suspend fun fetchGroupData()
|
||||||
}
|
}
|
||||||
|
@@ -92,9 +92,29 @@ interface IdentityService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Search MatrixId of users providing email and phone numbers
|
* Search MatrixId of users providing email and phone numbers
|
||||||
|
* Note the the user consent has to be set to true, or it will throw a UserConsentNotProvided failure
|
||||||
|
* Application has to explicitly ask for the user consent, and the answer can be stored using [setUserConsent]
|
||||||
|
* Please see https://support.google.com/googleplay/android-developer/answer/9888076?hl=en for more details.
|
||||||
*/
|
*/
|
||||||
fun lookUp(threePids: List<ThreePid>, callback: MatrixCallback<List<FoundThreePid>>): Cancelable
|
fun lookUp(threePids: List<ThreePid>, callback: MatrixCallback<List<FoundThreePid>>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current user consent for the current identity server, which has been stored using [setUserConsent].
|
||||||
|
* If [setUserConsent] has not been called, the returned value will be false.
|
||||||
|
* Note that if the identity server is changed, the user consent is reset to false.
|
||||||
|
* @return the value stored using [setUserConsent] or false if [setUserConsent] has never been called, or if the identity server
|
||||||
|
* has been changed
|
||||||
|
*/
|
||||||
|
fun getUserConsent(): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the user consent to the provided value. Application MUST explicitly ask for the user consent to send their private data
|
||||||
|
* (email and phone numbers) to the identity server.
|
||||||
|
* Please see https://support.google.com/googleplay/android-developer/answer/9888076?hl=en for more details.
|
||||||
|
* @param newValue true if the user explicitly give their consent, false if the user wants to revoke their consent.
|
||||||
|
*/
|
||||||
|
fun setUserConsent(newValue: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the status of the current user's threePid
|
* Get the status of the current user's threePid
|
||||||
* A lookup will be performed, but also pending binding state will be restored
|
* A lookup will be performed, but also pending binding state will be restored
|
||||||
|
@@ -24,6 +24,7 @@ sealed class IdentityServiceError : Failure.FeatureFailure() {
|
|||||||
object NoIdentityServerConfigured : IdentityServiceError()
|
object NoIdentityServerConfigured : IdentityServiceError()
|
||||||
object TermsNotSignedException : IdentityServiceError()
|
object TermsNotSignedException : IdentityServiceError()
|
||||||
object BulkLookupSha256NotSupported : IdentityServiceError()
|
object BulkLookupSha256NotSupported : IdentityServiceError()
|
||||||
|
object UserConsentNotProvided : IdentityServiceError()
|
||||||
object BindingError : IdentityServiceError()
|
object BindingError : IdentityServiceError()
|
||||||
object NoCurrentBindingError : IdentityServiceError()
|
object NoCurrentBindingError : IdentityServiceError()
|
||||||
}
|
}
|
||||||
|
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.integrationmanager
|
package org.matrix.android.sdk.api.session.integrationmanager
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the entry point to manage integration. You can grab an instance of this service through an active session.
|
* This is the entry point to manage integration. You can grab an instance of this service through an active session.
|
||||||
*/
|
*/
|
||||||
@@ -80,19 +77,17 @@ interface IntegrationManagerService {
|
|||||||
/**
|
/**
|
||||||
* Offers to enable or disable the integration.
|
* Offers to enable or disable the integration.
|
||||||
* @param enable the param to change
|
* @param enable the param to change
|
||||||
* @param callback the matrix callback to listen for result.
|
|
||||||
* @return Cancelable
|
* @return Cancelable
|
||||||
*/
|
*/
|
||||||
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun setIntegrationEnabled(enable: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Offers to allow or disallow a widget.
|
* Offers to allow or disallow a widget.
|
||||||
* @param stateEventId the eventId of the state event defining the widget.
|
* @param stateEventId the eventId of the state event defining the widget.
|
||||||
* @param allowed the param to change
|
* @param allowed the param to change
|
||||||
* @param callback the matrix callback to listen for result.
|
|
||||||
* @return Cancelable
|
* @return Cancelable
|
||||||
*/
|
*/
|
||||||
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun setWidgetAllowed(stateEventId: String, allowed: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the widget is allowed, false otherwise.
|
* Returns true if the widget is allowed, false otherwise.
|
||||||
@@ -105,7 +100,7 @@ interface IntegrationManagerService {
|
|||||||
* @param widgetType the widget type to check for
|
* @param widgetType the widget type to check for
|
||||||
* @param domain the domain to check for
|
* @param domain the domain to check for
|
||||||
*/
|
*/
|
||||||
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
suspend fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the widget domain is allowed, false otherwise.
|
* Returns true if the widget domain is allowed, false otherwise.
|
||||||
|
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.session.media
|
||||||
|
|
||||||
|
import org.matrix.android.sdk.api.cache.CacheStrategy
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.util.JsonDict
|
||||||
|
|
||||||
|
interface MediaService {
|
||||||
|
/**
|
||||||
|
* Extract URLs from an Event.
|
||||||
|
* @return the list of URLs contains in the body of the Event. It does not mean that URLs in this list have UrlPreview data
|
||||||
|
*/
|
||||||
|
fun extractUrls(event: Event): List<String>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Raw Url Preview data from the homeserver. There is no cache management for this request
|
||||||
|
* @param url The url to get the preview data from
|
||||||
|
* @param timestamp The optional timestamp
|
||||||
|
*/
|
||||||
|
suspend fun getRawPreviewUrl(url: String, timestamp: Long?): JsonDict
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Url Preview data from the homeserver, or from cache, depending on the cache strategy
|
||||||
|
* @param url The url to get the preview data from
|
||||||
|
* @param timestamp The optional timestamp. Note that this parameter is not taken into account
|
||||||
|
* if the data is already in cache and the cache strategy allow to use it
|
||||||
|
* @param cacheStrategy the cache strategy, see the type for more details
|
||||||
|
*/
|
||||||
|
suspend fun getPreviewUrl(url: String, timestamp: Long?, cacheStrategy: CacheStrategy): PreviewUrlData
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the cache of all retrieved UrlPreview data
|
||||||
|
*/
|
||||||
|
suspend fun clearCache()
|
||||||
|
}
|
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.session.media
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Facility data class to get the common field of a PreviewUrl response form the server
|
||||||
|
*
|
||||||
|
* Example of return data for the url `https://matrix.org`:
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* "matrix:image:size": 112805,
|
||||||
|
* "og:description": "Matrix is an open standard for interoperable, decentralised, real-time communication",
|
||||||
|
* "og:image": "mxc://matrix.org/2020-12-03_uFqjagCCTJbaaJxb",
|
||||||
|
* "og:image:alt": "Matrix is an open standard for interoperable, decentralised, real-time communication",
|
||||||
|
* "og:image:height": 467,
|
||||||
|
* "og:image:type": "image/jpeg",
|
||||||
|
* "og:image:width": 911,
|
||||||
|
* "og:locale": "en_US",
|
||||||
|
* "og:site_name": "Matrix.org",
|
||||||
|
* "og:title": "Matrix.org",
|
||||||
|
* "og:type": "website",
|
||||||
|
* "og:url": "https://matrix.org"
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
data class PreviewUrlData(
|
||||||
|
// Value of field "og:url". If not provided, this is the value passed in parameter
|
||||||
|
val url: String,
|
||||||
|
// Value of field "og:site_name"
|
||||||
|
val siteName: String?,
|
||||||
|
// Value of field "og:title"
|
||||||
|
val title: String?,
|
||||||
|
// Value of field "og:description"
|
||||||
|
val description: String?,
|
||||||
|
// Value of field "og:image"
|
||||||
|
val mxcUrl: String?
|
||||||
|
)
|
@@ -17,6 +17,7 @@
|
|||||||
package org.matrix.android.sdk.api.session.permalinks
|
package org.matrix.android.sdk.api.session.permalinks
|
||||||
|
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
|
import org.matrix.android.sdk.api.MatrixPatterns
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MatrixLinkify take a piece of text and turns all of the
|
* MatrixLinkify take a piece of text and turns all of the
|
||||||
@@ -35,7 +36,7 @@ object MatrixLinkify {
|
|||||||
* I disable it because it mess up with pills, and even with pills, it does not work correctly:
|
* I disable it because it mess up with pills, and even with pills, it does not work correctly:
|
||||||
* The url is not correct. Ex: for @user:matrix.org, the url will be @user:matrix.org, instead of a matrix.to
|
* The url is not correct. Ex: for @user:matrix.org, the url will be @user:matrix.org, instead of a matrix.to
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
// sanity checks
|
// sanity checks
|
||||||
if (spannable.isEmpty()) {
|
if (spannable.isEmpty()) {
|
||||||
return false
|
return false
|
||||||
@@ -48,14 +49,21 @@ object MatrixLinkify {
|
|||||||
val startPos = match.range.first
|
val startPos = match.range.first
|
||||||
if (startPos == 0 || text[startPos - 1] != '/') {
|
if (startPos == 0 || text[startPos - 1] != '/') {
|
||||||
val endPos = match.range.last + 1
|
val endPos = match.range.last + 1
|
||||||
val url = text.substring(match.range)
|
var url = text.substring(match.range)
|
||||||
|
if (MatrixPatterns.isUserId(url)
|
||||||
|
|| MatrixPatterns.isRoomAlias(url)
|
||||||
|
|| MatrixPatterns.isRoomId(url)
|
||||||
|
|| MatrixPatterns.isGroupId(url)
|
||||||
|
|| MatrixPatterns.isEventId(url)) {
|
||||||
|
url = PermalinkService.MATRIX_TO_URL_BASE + url
|
||||||
|
}
|
||||||
val span = MatrixPermalinkSpan(url, callback)
|
val span = MatrixPermalinkSpan(url, callback)
|
||||||
spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
spannable.setSpan(span, startPos, endPos, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hasMatch
|
return hasMatch
|
||||||
*/
|
|
||||||
return false
|
// return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,13 +44,12 @@ object PermalinkParser {
|
|||||||
if (fragment.isNullOrEmpty()) {
|
if (fragment.isNullOrEmpty()) {
|
||||||
return PermalinkData.FallbackLink(uri)
|
return PermalinkData.FallbackLink(uri)
|
||||||
}
|
}
|
||||||
val indexOfQuery = fragment.indexOf("?")
|
val safeFragment = fragment.substringBefore('?')
|
||||||
val safeFragment = if (indexOfQuery != -1) fragment.substring(0, indexOfQuery) else fragment
|
|
||||||
val viaQueryParameters = fragment.getViaParameters()
|
val viaQueryParameters = fragment.getViaParameters()
|
||||||
|
|
||||||
// we are limiting to 2 params
|
// we are limiting to 2 params
|
||||||
val params = safeFragment
|
val params = safeFragment
|
||||||
.split(MatrixPatterns.SEP_REGEX.toRegex())
|
.split(MatrixPatterns.SEP_REGEX)
|
||||||
.filter { it.isNotEmpty() }
|
.filter { it.isNotEmpty() }
|
||||||
.take(2)
|
.take(2)
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room
|
|||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.AliasService
|
||||||
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
import org.matrix.android.sdk.api.session.room.call.RoomCallService
|
||||||
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
import org.matrix.android.sdk.api.session.room.crypto.RoomCryptoService
|
||||||
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
import org.matrix.android.sdk.api.session.room.members.MembershipService
|
||||||
@@ -46,6 +47,7 @@ interface Room :
|
|||||||
DraftService,
|
DraftService,
|
||||||
ReadService,
|
ReadService,
|
||||||
TypingService,
|
TypingService,
|
||||||
|
AliasService,
|
||||||
TagsService,
|
TagsService,
|
||||||
MembershipService,
|
MembershipService,
|
||||||
StateService,
|
StateService,
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
package org.matrix.android.sdk.api.session.room
|
package org.matrix.android.sdk.api.session.room
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomDirectoryVisibility
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsParams
|
||||||
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoomsResponse
|
||||||
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
import org.matrix.android.sdk.api.session.room.model.thirdparty.ThirdPartyProtocol
|
||||||
@@ -39,4 +40,14 @@ interface RoomDirectoryService {
|
|||||||
* Includes both the available protocols and all fields required for queries against each protocol.
|
* Includes both the available protocols and all fields required for queries against each protocol.
|
||||||
*/
|
*/
|
||||||
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the visibility of a room in the directory
|
||||||
|
*/
|
||||||
|
suspend fun getRoomDirectoryVisibility(roomId: String): RoomDirectoryVisibility
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the visibility of a room in the directory
|
||||||
|
*/
|
||||||
|
suspend fun setRoomDirectoryVisibility(roomId: String, roomDirectoryVisibility: RoomDirectoryVisibility)
|
||||||
}
|
}
|
||||||
|
@@ -18,11 +18,15 @@ package org.matrix.android.sdk.api.session.room
|
|||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
import org.matrix.android.sdk.api.MatrixCallback
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
import org.matrix.android.sdk.api.session.room.members.ChangeMembershipState
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.RoomMemberSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
import org.matrix.android.sdk.api.session.room.model.RoomSummary
|
||||||
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
import org.matrix.android.sdk.api.session.room.model.create.CreateRoomParams
|
||||||
|
import org.matrix.android.sdk.api.session.room.peeking.PeekResult
|
||||||
import org.matrix.android.sdk.api.util.Cancelable
|
import org.matrix.android.sdk.api.util.Cancelable
|
||||||
import org.matrix.android.sdk.api.util.Optional
|
import org.matrix.android.sdk.api.util.Optional
|
||||||
|
import org.matrix.android.sdk.internal.session.room.alias.RoomAliasDescription
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to get rooms. It's implemented at the session level.
|
* This interface defines methods to get rooms. It's implemented at the session level.
|
||||||
@@ -119,7 +123,12 @@ interface RoomService {
|
|||||||
*/
|
*/
|
||||||
fun getRoomIdByAlias(roomAlias: String,
|
fun getRoomIdByAlias(roomAlias: String,
|
||||||
searchOnServer: Boolean,
|
searchOnServer: Boolean,
|
||||||
callback: MatrixCallback<Optional<String>>): Cancelable
|
callback: MatrixCallback<Optional<RoomAliasDescription>>): Cancelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a room alias
|
||||||
|
*/
|
||||||
|
suspend fun deleteRoomAlias(roomAlias: String)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a live data of all local changes membership that happened since the session has been opened.
|
* Return a live data of all local changes membership that happened since the session has been opened.
|
||||||
@@ -141,4 +150,32 @@ interface RoomService {
|
|||||||
* - the power level of the users are not taken into account. Normally in a DM, the 2 members are admins of the room
|
* - the power level of the users are not taken into account. Normally in a DM, the 2 members are admins of the room
|
||||||
*/
|
*/
|
||||||
fun getExistingDirectRoomWithUser(otherUserId: String): String?
|
fun getExistingDirectRoomWithUser(otherUserId: String): String?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a room member for the tuple {userId,roomId}
|
||||||
|
* @param userId the userId to look for.
|
||||||
|
* @param roomId the roomId to look for.
|
||||||
|
* @return the room member or null
|
||||||
|
*/
|
||||||
|
fun getRoomMember(userId: String, roomId: String): RoomMemberSummary?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Observe a live room member for the tuple {userId,roomId}
|
||||||
|
* @param userId the userId to look for.
|
||||||
|
* @param roomId the roomId to look for.
|
||||||
|
* @return a LiveData of the optional found room member
|
||||||
|
*/
|
||||||
|
fun getRoomMemberLive(userId: String, roomId: String): LiveData<Optional<RoomMemberSummary>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get some state events about a room
|
||||||
|
*/
|
||||||
|
fun getRoomState(roomId: String, callback: MatrixCallback<List<Event>>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this if you want to get information from a room that you are not yet in (or invited)
|
||||||
|
* It might be possible to get some information on this room if it is public or if guest access is allowed
|
||||||
|
* This call will try to gather some information on this room, but it could fail and get nothing more
|
||||||
|
*/
|
||||||
|
fun peekRoom(roomIdOrAlias: String, callback: MatrixCallback<PeekResult>)
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.session.room.alias
|
||||||
|
|
||||||
|
interface AliasService {
|
||||||
|
/**
|
||||||
|
* Get list of local alias of the room
|
||||||
|
* @return the list of the aliases (full aliases, not only the local part)
|
||||||
|
*/
|
||||||
|
suspend fun getRoomAliases(): List<String>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add local alias to the room
|
||||||
|
* @param aliasLocalPart the local part of the alias.
|
||||||
|
* Ex: for the alias "#my_alias:example.org", the local part is "my_alias"
|
||||||
|
*/
|
||||||
|
suspend fun addAlias(aliasLocalPart: String)
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.session.room.alias
|
||||||
|
|
||||||
|
sealed class RoomAliasError : Throwable() {
|
||||||
|
object AliasEmpty : RoomAliasError()
|
||||||
|
object AliasNotAvailable : RoomAliasError()
|
||||||
|
object AliasInvalid : RoomAliasError()
|
||||||
|
}
|
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.matrix.android.sdk.api.session.room.crypto
|
package org.matrix.android.sdk.api.session.room.crypto
|
||||||
|
|
||||||
import org.matrix.android.sdk.api.MatrixCallback
|
|
||||||
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
import org.matrix.android.sdk.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
|
||||||
|
|
||||||
interface RoomCryptoService {
|
interface RoomCryptoService {
|
||||||
@@ -30,6 +29,5 @@ interface RoomCryptoService {
|
|||||||
/**
|
/**
|
||||||
* Enable encryption of the room
|
* Enable encryption of the room
|
||||||
*/
|
*/
|
||||||
fun enableEncryption(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM,
|
suspend fun enableEncryption(algorithm: String = MXCRYPTO_ALGORITHM_MEGOLM)
|
||||||
callback: MatrixCallback<Unit>)
|
|
||||||
}
|
}
|
||||||
|
@@ -18,8 +18,10 @@ package org.matrix.android.sdk.api.session.room.failure
|
|||||||
|
|
||||||
import org.matrix.android.sdk.api.failure.Failure
|
import org.matrix.android.sdk.api.failure.Failure
|
||||||
import org.matrix.android.sdk.api.failure.MatrixError
|
import org.matrix.android.sdk.api.failure.MatrixError
|
||||||
|
import org.matrix.android.sdk.api.session.room.alias.RoomAliasError
|
||||||
|
|
||||||
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
||||||
object CreatedWithTimeout : CreateRoomFailure()
|
object CreatedWithTimeout : CreateRoomFailure()
|
||||||
data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
|
data class CreatedWithFederationFailure(val matrixError: MatrixError) : CreateRoomFailure()
|
||||||
|
data class AliasError(val aliasError: RoomAliasError) : CreateRoomFailure()
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,9 @@ import com.squareup.moshi.JsonClass
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing the EventType.STATE_ROOM_ALIASES state event content
|
* Class representing the EventType.STATE_ROOM_ALIASES state event content
|
||||||
|
* Note that this Event has been deprecated, see
|
||||||
|
* - https://matrix.org/docs/spec/client_server/r0.6.1#historical-events
|
||||||
|
* - https://github.com/matrix-org/matrix-doc/pull/2432
|
||||||
*/
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomAliasesContent(
|
data class RoomAliasesContent(
|
||||||
|
@@ -24,5 +24,14 @@ import com.squareup.moshi.JsonClass
|
|||||||
*/
|
*/
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class RoomCanonicalAliasContent(
|
data class RoomCanonicalAliasContent(
|
||||||
@Json(name = "alias") val canonicalAlias: String? = null
|
/**
|
||||||
|
* The canonical alias for the room. If not present, null, or empty the room should be considered to have no canonical alias.
|
||||||
|
*/
|
||||||
|
@Json(name = "alias") val canonicalAlias: String? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternative aliases the room advertises.
|
||||||
|
* This list can have aliases despite the alias field being null, empty, or otherwise not present.
|
||||||
|
*/
|
||||||
|
@Json(name = "alt_aliases") val alternativeAliases: List<String>? = null
|
||||||
)
|
)
|
||||||
|
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
*
|
||||||
|
* 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 org.matrix.android.sdk.api.session.room.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing the EventType.STATE_ROOM_SERVER_ACL state event content
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#m-room-server-acl
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class RoomServerAclContent(
|
||||||
|
/**
|
||||||
|
* True to allow server names that are IP address literals. False to deny.
|
||||||
|
* Defaults to true if missing or otherwise not a boolean.
|
||||||
|
* This is strongly recommended to be set to false as servers running with IP literal names are strongly
|
||||||
|
* discouraged in order to require legitimate homeservers to be backed by a valid registered domain name.
|
||||||
|
*/
|
||||||
|
@Json(name = "allow_ip_literals")
|
||||||
|
val allowIpLiterals: Boolean = true,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server names to allow in the room, excluding any port information. Wildcards may be used to cover
|
||||||
|
* a wider range of hosts, where * matches zero or more characters and ? matches exactly one character.
|
||||||
|
*
|
||||||
|
* This defaults to an empty list when not provided, effectively disallowing every server.
|
||||||
|
*/
|
||||||
|
@Json(name = "allow")
|
||||||
|
val allowList: List<String> = emptyList(),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The server names to disallow in the room, excluding any port information. Wildcards may be used to cover
|
||||||
|
* a wider range of hosts, where * matches zero or more characters and ? matches exactly one character.
|
||||||
|
*
|
||||||
|
* This defaults to an empty list when not provided.
|
||||||
|
*/
|
||||||
|
@Json(name = "deny")
|
||||||
|
val denyList: List<String> = emptyList()
|
||||||
|
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
const val ALL = "*"
|
||||||
|
}
|
||||||
|
}
|
@@ -94,7 +94,22 @@ class CreateRoomParams {
|
|||||||
* The server will clobber the following keys: creator.
|
* The server will clobber the following keys: creator.
|
||||||
* Future versions of the specification may allow the server to clobber other keys.
|
* Future versions of the specification may allow the server to clobber other keys.
|
||||||
*/
|
*/
|
||||||
var creationContent: Any? = null
|
val creationContent = mutableMapOf<String, Any>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to true to disable federation of this room.
|
||||||
|
* Default: false
|
||||||
|
*/
|
||||||
|
var disableFederation = false
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
if (value) {
|
||||||
|
creationContent[CREATION_CONTENT_KEY_M_FEDERATE] = false
|
||||||
|
} else {
|
||||||
|
// This is the default value, we remove the field
|
||||||
|
creationContent.remove(CREATION_CONTENT_KEY_M_FEDERATE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The power level content to override in the default power level event
|
* The power level content to override in the default power level event
|
||||||
@@ -120,4 +135,8 @@ class CreateRoomParams {
|
|||||||
fun enableEncryption() {
|
fun enableEncryption() {
|
||||||
algorithm = MXCRYPTO_ALGORITHM_MEGOLM
|
algorithm = MXCRYPTO_ALGORITHM_MEGOLM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val CREATION_CONTENT_KEY_M_FEDERATE = "m.federate"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import com.squareup.moshi.Json
|
|||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import org.matrix.android.sdk.api.session.events.model.Content
|
import org.matrix.android.sdk.api.session.events.model.Content
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||||
|
import org.matrix.android.sdk.api.util.MimeTypes
|
||||||
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
|
import org.matrix.android.sdk.internal.crypto.model.rest.EncryptedFileInfo
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
@@ -54,5 +55,5 @@ data class MessageImageContent(
|
|||||||
@Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null
|
@Json(name = "file") override val encryptedFileInfo: EncryptedFileInfo? = null
|
||||||
) : MessageImageInfoContent {
|
) : MessageImageInfoContent {
|
||||||
override val mimeType: String?
|
override val mimeType: String?
|
||||||
get() = encryptedFileInfo?.mimetype ?: info?.mimeType ?: "image/*"
|
get() = encryptedFileInfo?.mimetype ?: info?.mimeType ?: MimeTypes.Images
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ data class MessageStickerContent(
|
|||||||
/**
|
/**
|
||||||
* Set in local, not from server
|
* Set in local, not from server
|
||||||
*/
|
*/
|
||||||
|
@Transient
|
||||||
override val msgType: String = MessageType.MSGTYPE_STICKER_LOCAL,
|
override val msgType: String = MessageType.MSGTYPE_STICKER_LOCAL,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user