forked from GitHub-Mirror/riotX-android
Compare commits
774 Commits
feature/ro
...
v0.8.0
Author | SHA1 | Date | |
---|---|---|---|
eb32c5455f | |||
57dcd569f3 | |||
fe17050580 | |||
ec40a8c969 | |||
6b1b3bec85 | |||
6bd6ececb7 | |||
c7db695e67 | |||
4cefdfedce | |||
6ce241163e | |||
79350899c5 | |||
f265724a3c | |||
2e50d2a36e | |||
643c062858 | |||
0e0db67aef | |||
6dc5b126d6 | |||
d2acabddd9 | |||
ec71b53c1e | |||
fc3d4187d1 | |||
a25f309990 | |||
5449592422 | |||
19b415871d | |||
6463f3439f | |||
f2320f9571 | |||
fc91694bdd | |||
dbb41108ef | |||
08c864bad7 | |||
9c5c65a243 | |||
b6199b1f27 | |||
38da54119a | |||
65b09ad4f0 | |||
603b8fae45 | |||
50e2e6a823 | |||
bb237e3bbb | |||
1bd2c0d220 | |||
bcb811a7e8 | |||
ec4d7e29ec | |||
a6df63f6d9 | |||
ea7213a5ae | |||
590a13334d | |||
631448335d | |||
12376368c7 | |||
f17564d743 | |||
a6fcc7dca6 | |||
70bce9e7dd | |||
17f3614288 | |||
238d1d87c6 | |||
82f639b91f | |||
c8bc553caa | |||
fa5d44af65 | |||
cbdbe5033f | |||
61ac250e2b | |||
04f72dfcb8 | |||
10ca5d94ea | |||
c5b8c69ae5 | |||
d3d7f7cc61 | |||
b6bb714264 | |||
a87310ac15 | |||
032e1b3d19 | |||
d9f15c1d21 | |||
99d09f71ad | |||
9c952b6bc8 | |||
fbae3d27c2 | |||
2f7d1f9f01 | |||
114101699d | |||
f5c0dcb5ea | |||
241220ce1f | |||
98d97e574c | |||
96e610970a | |||
2027802f82 | |||
54f93db632 | |||
3af7ca9ab0 | |||
93ef3edab3 | |||
c85852262e | |||
d0c3271628 | |||
ad9a48d5fa | |||
219d1383e5 | |||
8871280fab | |||
fb3e953e28 | |||
10712fd6ab | |||
9d478dbfe2 | |||
3013d67c16 | |||
bee8c2d159 | |||
945e5d5a74 | |||
93df8c56a8 | |||
cd1a964067 | |||
e4b829f0cf | |||
7206d84a6b | |||
b3233d3eb7 | |||
3c4c0ed46a | |||
24f1262005 | |||
86667a6d8a | |||
42e0d0f769 | |||
e976055253 | |||
84d6c8ec16 | |||
9fdfd091ac | |||
e66766f41c | |||
6177e69855 | |||
5c71cabb5f | |||
6ebe5532c5 | |||
8030c44f44 | |||
a85b5af761 | |||
d780c74abf | |||
5d7efa7f8f | |||
7e467443ed | |||
8439c337f7 | |||
151ad01038 | |||
73267442bb | |||
43fd794c96 | |||
36060fe332 | |||
3483debcc1 | |||
4324f6abbd | |||
43f8d8d8aa | |||
fb1ff77ec4 | |||
e355a7f6dd | |||
33e35368fc | |||
0e49a11e5e | |||
d47cf7e932 | |||
101057520b | |||
30b2e53002 | |||
5ab31a0ef5 | |||
b4ae331086 | |||
3f447df13c | |||
3517873156 | |||
118870bc41 | |||
d001ab5bef | |||
7496a88dcd | |||
6567c5e6c7 | |||
361427488f | |||
7272343e6d | |||
f0b3151d71 | |||
035359cb35 | |||
57b640622b | |||
de4c389c76 | |||
199456487c | |||
00ca5dc70a | |||
a04802b238 | |||
cb275aee37 | |||
fbf73c7c8e | |||
0040f8e924 | |||
6cca242f77 | |||
2929b8f617 | |||
8422c6de17 | |||
7c567b04bb | |||
1ac99e92a6 | |||
5ab975cc5c | |||
2cf63ea92a | |||
9e8d8ce878 | |||
b766bce07d | |||
01452efd8d | |||
0a0af221f0 | |||
af08759af6 | |||
e52f0faaa7 | |||
8fa676d034 | |||
b6594599c4 | |||
8be8cc9ef7 | |||
9762d5be40 | |||
b17b54d218 | |||
187e2a26db | |||
2f5fdbb7e2 | |||
8b1411f533 | |||
bdee5e0687 | |||
ce4e244a3b | |||
ff81715783 | |||
3196dcb57e | |||
50bf6df7fe | |||
02914495ce | |||
70a14f6350 | |||
cac5fb725a | |||
dbc17ae515 | |||
1de02c2fbb | |||
6d55c15761 | |||
377a228f88 | |||
2974f8b200 | |||
7388a408b8 | |||
f43dcb1183 | |||
492ed3954a | |||
7890e83204 | |||
00d1a2c380 | |||
78dfd6b3e6 | |||
3abce34484 | |||
4204ab262c | |||
c7a4d34192 | |||
7416fec93e | |||
3c40f64fb7 | |||
b57c71b1c9 | |||
fea54952d3 | |||
3dc5ef54ab | |||
9092b97fb8 | |||
cebd8136da | |||
64b3568d51 | |||
5e4e54153c | |||
d071324694 | |||
2c8cd89533 | |||
11b5c2c3ba | |||
9d7c4abb97 | |||
8e3234d188 | |||
b253722b98 | |||
fce576e3a4 | |||
7ed7b18ccd | |||
053bf7aeac | |||
6ccd083451 | |||
e39c4a7925 | |||
abdb83b9fd | |||
0bcc84cbd6 | |||
b2f6fb8c91 | |||
36042ed145 | |||
6ad1932fe5 | |||
4a6237b50e | |||
a7a19dab11 | |||
8d0aa0437c | |||
0a79b8b315 | |||
1dacfa6744 | |||
723a007c39 | |||
eaa1b04a4a | |||
b1710fde60 | |||
cd0a40c18d | |||
17636019e0 | |||
8078c39d6e | |||
be94b2f90a | |||
eff04be247 | |||
3986839801 | |||
9e436483de | |||
05a069be04 | |||
a1a71e2f1d | |||
203da0f37e | |||
6cd04525aa | |||
3c3c6aeac6 | |||
e71311f576 | |||
e4d0e0b0bf | |||
28e5e42ab1 | |||
b860c3b0e3 | |||
f7f97e2098 | |||
e28e2dadb9 | |||
c28be6adb0 | |||
c57af9cf3e | |||
679b0fff98 | |||
946fc36a26 | |||
13a5f784dc | |||
0ca8696e88 | |||
3622c0ecb4 | |||
116d569fa8 | |||
ee5ebb4b83 | |||
0a0c344bfb | |||
82fc97f619 | |||
20696353b8 | |||
ae5b6bd2b9 | |||
1e11d4492b | |||
6e39164b20 | |||
0a9ebb6bf6 | |||
db009ce683 | |||
55c80d3743 | |||
fbb23dfb66 | |||
e5779d425a | |||
99d9704a50 | |||
3f8ddbe880 | |||
30e43e47cd | |||
15dc4d6369 | |||
dceb5ffd8d | |||
eec470f2ce | |||
68db9c1cc0 | |||
cdfc402599 | |||
72d3f1e909 | |||
255fa11e89 | |||
119e4c0d32 | |||
a9c474105a | |||
6de64cbedd | |||
546c537e3b | |||
36c5f9af13 | |||
c2682c7f4b | |||
3073470c38 | |||
549f749682 | |||
d4dfb76e80 | |||
e80191b2e0 | |||
c62c77f14c | |||
d6e5c5a857 | |||
50a0660ab6 | |||
ecdb3c3326 | |||
2cd1d697fe | |||
3f9b7813bc | |||
f34f28b668 | |||
53572a3be6 | |||
90b6199e10 | |||
0aa299aa37 | |||
d387c310c8 | |||
8bd1fb08f7 | |||
ac6aff9175 | |||
adf0382d28 | |||
51554f7be0 | |||
c1c1c3f999 | |||
8b04fdab77 | |||
f8b665a245 | |||
d68a9a5342 | |||
5d2ff589f8 | |||
e85a0783fc | |||
d6c278288d | |||
4ad86a13a0 | |||
4f7ec91255 | |||
979b42aa30 | |||
fc49de080c | |||
d2b9668d4e | |||
0632870be1 | |||
8e39fd2a70 | |||
abbc62dd35 | |||
77de059dc9 | |||
1931a1a4a4 | |||
9c5987b682 | |||
4e4fb4c565 | |||
0582d0f641 | |||
ef2af14529 | |||
525da17678 | |||
aab41d7358 | |||
5db3c81aa9 | |||
c763635845 | |||
11d72b81f6 | |||
53543453b3 | |||
d4be68191c | |||
7ef471ad0d | |||
73dd735ba6 | |||
2f6d3adb17 | |||
2edfd4e830 | |||
ff7856c535 | |||
650a151b18 | |||
275dd20412 | |||
44f6391cb4 | |||
588e5d6e63 | |||
716999eec6 | |||
42e0a45f3f | |||
31397869b2 | |||
e842bf13b2 | |||
aea34da81e | |||
0814f53fed | |||
b5c6c1af0d | |||
de30e7c1c6 | |||
2d95fe921d | |||
84542326f4 | |||
53b1b89c47 | |||
28315be7b9 | |||
8605095668 | |||
737959f616 | |||
7817f49072 | |||
a060431aaf | |||
a3f561d788 | |||
0ea878af8a | |||
99de40c980 | |||
810a97c639 | |||
f02f16d9c5 | |||
62b7a83a31 | |||
4a80df082c | |||
60f6b3ef02 | |||
a0b1ef3216 | |||
1b66d1f746 | |||
643a2baabf | |||
cd62e87266 | |||
17cba1a432 | |||
f077cc8467 | |||
f3039601bf | |||
4c04014e4d | |||
ae8bceacba | |||
9b91b6ea87 | |||
b24a372262 | |||
63b43de4b8 | |||
d1a61f29e4 | |||
f6373221de | |||
ec0974f72c | |||
b5f2f01c8d | |||
21d808c1ce | |||
1e963bc0dc | |||
0d80750507 | |||
1c9cf7a810 | |||
c6d01fbcf4 | |||
9e1ded941f | |||
af433266c8 | |||
05d09bf950 | |||
6890f83810 | |||
51568c30a6 | |||
cc832633a5 | |||
e019ec6596 | |||
eadea9016b | |||
6422d946c9 | |||
5cc3dc00e3 | |||
5a2a9f908a | |||
c1f2e9f171 | |||
f6d34ec7fd | |||
620ba279d8 | |||
3fcfa33364 | |||
546da0f173 | |||
001711d5a3 | |||
8e1a964679 | |||
b25a130db1 | |||
8a9e6497e8 | |||
47e3797b7e | |||
5cbc90e06a | |||
b6e18e4a8f | |||
7e29665fd0 | |||
e04bf31faa | |||
d25cf79b07 | |||
faa8e6bbb2 | |||
d3d4deb884 | |||
f6b8e0c479 | |||
2a726f54a2 | |||
1197d4021d | |||
03f8120b7d | |||
acd7a709de | |||
5651ea515b | |||
9794b3a49d | |||
b3e1c3969d | |||
90eeb68d36 | |||
d1ff3314a7 | |||
f24bed17a2 | |||
a993a30203 | |||
ea0809ff87 | |||
9668487b6b | |||
91cc78d2ad | |||
562acc9702 | |||
dfab88ed95 | |||
36866dd24e | |||
c728834273 | |||
f5020d0f63 | |||
7da9cafcc2 | |||
6f09eea248 | |||
468bd5bcc9 | |||
3169093c50 | |||
d60d766354 | |||
0ffb5e627e | |||
b4a13f9504 | |||
88fb9667a3 | |||
ffa8b7e73a | |||
528958b3de | |||
3ffe2f7d40 | |||
3066d5f303 | |||
bf42b73713 | |||
ed93f4a6c1 | |||
b3d649a4d9 | |||
3739e50d46 | |||
9bf484cf1e | |||
6c2faff1f0 | |||
07fca0922b | |||
282de21708 | |||
ba9d119892 | |||
4453f0ced9 | |||
77168bfd6a | |||
25e9a179d2 | |||
73ec0f5a83 | |||
993fa74252 | |||
38fc4984fe | |||
695d8cce00 | |||
07e99901e1 | |||
20f53e9a58 | |||
ced72aff4f | |||
fdaaca49c2 | |||
3485f023b0 | |||
384dd100e9 | |||
1ba8a58219 | |||
69fb7bdf95 | |||
c8010561fc | |||
1f127335bc | |||
138a210a73 | |||
ca6bcde82d | |||
6bda437f5d | |||
5d6d0202a9 | |||
3e6b65e174 | |||
137dcab734 | |||
b22b8fba02 | |||
3ccdf4a244 | |||
5fbd271b1c | |||
db8ea0f5e8 | |||
a47a3ead1f | |||
05b2092ffc | |||
f4ab770be9 | |||
6249a59203 | |||
d4111d053d | |||
618e9a4f52 | |||
b8ebe3570b | |||
f2c8d4ad02 | |||
be524472ec | |||
1b82a1a24d | |||
cf0b331c3b | |||
2a92a3dc80 | |||
012840abba | |||
a5975a099e | |||
38da4b9ee5 | |||
242e60fcaa | |||
a23be05cbf | |||
ed39b02924 | |||
fe931b5361 | |||
90d9cd0587 | |||
9cedb18921 | |||
e89ba7b87b | |||
902657c22a | |||
eec2abf164 | |||
6879cc8ca8 | |||
fd6bbbd3b5 | |||
0ff0b014a9 | |||
a89f0ddd1d | |||
fdc9e84dd5 | |||
58f878fca9 | |||
88095e4bd9 | |||
47d22a3d5e | |||
28e82cb8ea | |||
35817245cb | |||
75266f42bb | |||
95c4c9ce56 | |||
ce5570105d | |||
188a9aebfa | |||
c95223f5d2 | |||
ef0362ba9c | |||
ea242f6737 | |||
cbc08d834b | |||
0ab6b33fb6 | |||
1b394527b6 | |||
a8f1388721 | |||
166be4e289 | |||
b49ccefe63 | |||
825760d17e | |||
b5af62c3ea | |||
a51d96bf00 | |||
7e142d201d | |||
2be6058971 | |||
49d73f360e | |||
bd88d85a21 | |||
be4fc5cce6 | |||
704da1be55 | |||
5d002532d3 | |||
d4161e9a1a | |||
7966ebef03 | |||
ed5faca5d2 | |||
51a4c93676 | |||
d8f449388c | |||
8ca829d538 | |||
e7819ce678 | |||
5402902bc2 | |||
bc1350aaf5 | |||
fd74e3dfb1 | |||
e0628da1cb | |||
aa4e74e986 | |||
6cc0c0672e | |||
501474b720 | |||
e11c66035c | |||
3d2d219d79 | |||
63af03bedd | |||
d3827b8673 | |||
4ca2531e47 | |||
4e8dc72439 | |||
25a4240a5a | |||
b9cfda23b6 | |||
06dcf75a32 | |||
21deb2551d | |||
70639f180c | |||
1dbb02a80d | |||
825463d9cd | |||
c313ce78cb | |||
39f58d048b | |||
3f792c7a84 | |||
347dcb469a | |||
9cd69d1e33 | |||
79fb1985aa | |||
e216cd15a8 | |||
37fde374b3 | |||
f7b471f141 | |||
93fd56a7ca | |||
5a9d88e791 | |||
eaf6a9923a | |||
d98567045c | |||
b4ce8748cb | |||
9d5433a857 | |||
6d4ee83e65 | |||
6e44cca17d | |||
0a73887c70 | |||
7fef063e15 | |||
24f391dac0 | |||
81c7f694d6 | |||
80e2fc0ca3 | |||
9f53406e99 | |||
3584658c36 | |||
12a0cbb400 | |||
20437446b4 | |||
35229882e3 | |||
a04f4421f6 | |||
af1e81f65e | |||
63f6081fa5 | |||
ee2e575211 | |||
0949d29f9c | |||
23466fb5a4 | |||
7f09e64d63 | |||
585f0ba4b7 | |||
245fbe86d9 | |||
456908c851 | |||
b79fdf6a85 | |||
d9f448c9aa | |||
7a6fc4936b | |||
d82fd10f3b | |||
4009f2c176 | |||
15c4b03340 | |||
7b5dff3dcf | |||
357123743f | |||
bb04af1e2c | |||
2f94fbd7eb | |||
f2a3bdb68e | |||
097e9714ff | |||
acae0fad3e | |||
4deb7eb865 | |||
f910cd6f97 | |||
652ac81fa1 | |||
99f4196388 | |||
c0b94f4111 | |||
1462fa0484 | |||
dafdc1d3ad | |||
394b89e76b | |||
0db8e7da43 | |||
dae8b5c196 | |||
215324a03e | |||
d3ce4c491c | |||
ed6d28bd3b | |||
c2e053b62b | |||
c450849cc3 | |||
fe884dba2d | |||
3fa4dbaa25 | |||
4a74f58516 | |||
c413321a22 | |||
d696bd2830 | |||
a2b6bd0f62 | |||
9cc922a8a2 | |||
c36d1bcd06 | |||
85499c6b33 | |||
8076eab4b5 | |||
d47c0f5ebc | |||
fd09a1224e | |||
c300c50093 | |||
77c4355aed | |||
1a92562182 | |||
9c390dcc0c | |||
95089b91b8 | |||
eb446d7b49 | |||
dc4786ecf0 | |||
e245023add | |||
90fad23493 | |||
000db4b192 | |||
2a16c36a59 | |||
ef6c1cfc63 | |||
4b4156996d | |||
087cc0e6e3 | |||
f4df27c2dc | |||
ab25980c4e | |||
77b402ce70 | |||
2763fbb496 | |||
6deba31111 | |||
ff6ce8a4b7 | |||
d0cff219aa | |||
65f0af918f | |||
ac38a6461c | |||
9a1e16a170 | |||
9e5c70dda3 | |||
0255696c88 | |||
76a9625f25 | |||
5af6bf3762 | |||
507bc2f622 | |||
125eacb20b | |||
6176520805 | |||
3aea0a50ca | |||
ab87a3caea | |||
c58328f94e | |||
03974c8bdf | |||
151ae7f4dd | |||
a34b053efe | |||
02e342849f | |||
b59017938b | |||
2c81e41288 | |||
cb44ab547c | |||
6d01a570fd | |||
4a2bf0d6c6 | |||
36af8a6a9f | |||
40a68c3e9f | |||
1a4ec34bb2 | |||
10490e3aa6 | |||
cd6624a8a6 | |||
3965218bf9 | |||
d78ff7ab08 | |||
cb274d6a33 | |||
c00dbce536 | |||
db88caf7fa | |||
c3d945d6bb | |||
df6080b1da | |||
4c128602b2 | |||
d609c49b31 | |||
001603cf9a | |||
d87ee32422 | |||
f0671b9e73 | |||
e218691bf2 | |||
9c67036c08 | |||
62657538af | |||
5438207fba | |||
fe88aaffbd | |||
21ba72e5e7 | |||
d48ae967bd | |||
0afde3b021 | |||
49ae954183 | |||
64bee91f7a | |||
4341b0d0f5 | |||
51fdccb393 | |||
7e3b300130 | |||
a98b324c89 | |||
977721881f | |||
838003b68a | |||
7d41352918 | |||
077396a832 | |||
32b79bd50e | |||
844f6d16a4 | |||
fc9ef579ca | |||
77fa5af1b8 | |||
90d25ff45e | |||
173452d38c | |||
a9f9083745 | |||
22dc2a6790 | |||
927cd7285d | |||
4d5bdecec6 | |||
0be987ac0d | |||
4bfaa00be4 | |||
8e78d8a58d | |||
e3e86c0a41 | |||
8a5fddd952 | |||
208460850e | |||
0ddef67cc9 | |||
896e582a9c | |||
477920f411 | |||
c647648e79 | |||
b654025a3b | |||
786a7d7560 | |||
b935b9311e | |||
8e12f71535 | |||
7eea2ccfb4 | |||
c32ef02a12 | |||
3651ec4870 | |||
87de7bd3e6 | |||
9494174c33 | |||
9bdea5b325 | |||
2f01ad99b3 | |||
bb3b5788ba | |||
45f7d3e9c4 | |||
0f7a56d005 | |||
63d2861bc8 | |||
6bbc784c29 | |||
c6fd625761 | |||
d8092abc4e | |||
6effb90361 | |||
42584fc55a | |||
30d9ddb3e8 | |||
020c32bb1a | |||
efd973208f | |||
30a6c98c08 | |||
1440080d04 | |||
61bb4c0427 | |||
3c25088243 | |||
fc1c0caea3 | |||
8901a5e09a | |||
25f1d21bc7 | |||
4d2ab9fa31 | |||
0289d2ee87 | |||
222201cc64 | |||
b15dea6de3 | |||
2ba83e456d | |||
1822fc4fbb | |||
e6dd1fbfec | |||
e2ea76f871 | |||
34d14eb304 | |||
3625c462f0 | |||
fe69206340 | |||
f9885fd04c | |||
316c8ec27e | |||
41465450d8 | |||
bd009caaf1 | |||
33252c3b65 | |||
4b971a9e67 | |||
698fc35704 | |||
1c69d8e425 |
@ -1,15 +1,38 @@
|
|||||||
# Use Docker file from https://hub.docker.com/r/runmymind/docker-android-sdk
|
# Use Docker file from https://hub.docker.com/r/runmymind/docker-android-sdk
|
||||||
# Last docker plugin version can be found here:
|
# Last docker plugin version can be found here:
|
||||||
# https://github.com/buildkite-plugins/docker-buildkite-plugin/releases
|
# https://github.com/buildkite-plugins/docker-buildkite-plugin/releases
|
||||||
|
# We propagate the environment to the container (sse https://github.com/buildkite-plugins/docker-buildkite-plugin#propagate-environment-optional-boolean)
|
||||||
# Build debug version of the RiotX application, from the develop branch and the features branches
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- label: "Assemble GPlay Debug version"
|
- label: "Compile and run Unit tests"
|
||||||
agents:
|
agents:
|
||||||
# We use a medium sized instance instead of the normal small ones because
|
# We use a medium sized instance instead of the normal small ones because
|
||||||
# gradle build is long
|
# gradle build can be memory hungry
|
||||||
queue: "medium"
|
queue: "medium"
|
||||||
|
commands:
|
||||||
|
- "./gradlew clean test --stacktrace"
|
||||||
|
plugins:
|
||||||
|
- docker#v3.1.0:
|
||||||
|
image: "runmymind/docker-android-sdk"
|
||||||
|
propagate-environment: true
|
||||||
|
|
||||||
|
- label: "Compile Android tests"
|
||||||
|
agents:
|
||||||
|
# We use a medium sized instance instead of the normal small ones because
|
||||||
|
# gradle build can be memory hungry
|
||||||
|
queue: "medium"
|
||||||
|
commands:
|
||||||
|
- "./gradlew clean assembleAndroidTest --stacktrace"
|
||||||
|
plugins:
|
||||||
|
- docker#v3.1.0:
|
||||||
|
image: "runmymind/docker-android-sdk"
|
||||||
|
propagate-environment: true
|
||||||
|
|
||||||
|
- label: "Assemble GPlay Debug version"
|
||||||
|
agents:
|
||||||
|
# We use a xlarge sized instance instead of the normal small ones because
|
||||||
|
# gradle build can be memory hungry
|
||||||
|
queue: "xlarge"
|
||||||
commands:
|
commands:
|
||||||
- "./gradlew clean lintGplayRelease assembleGplayDebug --stacktrace"
|
- "./gradlew clean lintGplayRelease assembleGplayDebug --stacktrace"
|
||||||
artifact_paths:
|
artifact_paths:
|
||||||
@ -18,12 +41,13 @@ steps:
|
|||||||
plugins:
|
plugins:
|
||||||
- docker#v3.1.0:
|
- docker#v3.1.0:
|
||||||
image: "runmymind/docker-android-sdk"
|
image: "runmymind/docker-android-sdk"
|
||||||
|
propagate-environment: true
|
||||||
|
|
||||||
- label: "Assemble FDroid Debug version"
|
- label: "Assemble FDroid Debug version"
|
||||||
agents:
|
agents:
|
||||||
# We use a medium sized instance instead of the normal small ones because
|
# We use a xlarge sized instance instead of the normal small ones because
|
||||||
# gradle build is long
|
# gradle build can be memory hungry
|
||||||
queue: "medium"
|
queue: "xlarge"
|
||||||
commands:
|
commands:
|
||||||
- "./gradlew clean lintFdroidRelease assembleFdroidDebug --stacktrace"
|
- "./gradlew clean lintFdroidRelease assembleFdroidDebug --stacktrace"
|
||||||
artifact_paths:
|
artifact_paths:
|
||||||
@ -32,12 +56,13 @@ steps:
|
|||||||
plugins:
|
plugins:
|
||||||
- docker#v3.1.0:
|
- docker#v3.1.0:
|
||||||
image: "runmymind/docker-android-sdk"
|
image: "runmymind/docker-android-sdk"
|
||||||
|
propagate-environment: true
|
||||||
|
|
||||||
- label: "Build Google Play unsigned APK"
|
- label: "Build Google Play unsigned APK"
|
||||||
agents:
|
agents:
|
||||||
# We use a medium sized instance instead of the normal small ones because
|
# We use a xlarge sized instance instead of the normal small ones because
|
||||||
# gradle build is long
|
# gradle build can be memory hungry
|
||||||
queue: "medium"
|
queue: "xlarge"
|
||||||
commands:
|
commands:
|
||||||
- "./gradlew clean assembleGplayRelease --stacktrace"
|
- "./gradlew clean assembleGplayRelease --stacktrace"
|
||||||
artifact_paths:
|
artifact_paths:
|
||||||
@ -46,8 +71,18 @@ steps:
|
|||||||
plugins:
|
plugins:
|
||||||
- docker#v3.1.0:
|
- docker#v3.1.0:
|
||||||
image: "runmymind/docker-android-sdk"
|
image: "runmymind/docker-android-sdk"
|
||||||
|
propagate-environment: true
|
||||||
|
|
||||||
# Code quality
|
# Code quality
|
||||||
|
|
||||||
- label: "Code quality"
|
- label: "Code quality"
|
||||||
command: "./tools/check/check_code_quality.sh"
|
command:
|
||||||
|
- "./tools/check/check_code_quality.sh"
|
||||||
|
|
||||||
|
- label: "ktlint"
|
||||||
|
command:
|
||||||
|
- "curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.34.2/ktlint && chmod a+x ktlint"
|
||||||
|
- "./ktlint --android --experimental -v"
|
||||||
|
plugins:
|
||||||
|
- docker#v3.1.0:
|
||||||
|
image: "openjdk"
|
||||||
|
32
.editorconfig
Normal file
32
.editorconfig
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# For ktlint configuration. Ref: https://ktlint.github.io/
|
||||||
|
|
||||||
|
[*.{kt,kts}]
|
||||||
|
# possible values: number (e.g. 2), "unset" (makes ktlint ignore indentation completely)
|
||||||
|
indent_size=unset
|
||||||
|
# true (recommended) / false
|
||||||
|
insert_final_newline=true
|
||||||
|
# possible values: number (e.g. 120) (package name, imports & comments are ignored), "off"
|
||||||
|
# it's automatically set to 100 on `ktlint --android ...` (per Android Kotlin Style Guide)
|
||||||
|
max_line_length=off
|
||||||
|
|
||||||
|
# Comma-separated list of rules to disable (Since 0.34.0)
|
||||||
|
# Note that rules in any ruleset other than the standard ruleset will need to be prefixed
|
||||||
|
# by the ruleset identifier.
|
||||||
|
disabled_rules=no-wildcard-imports,no-multi-spaces,colon-spacing,chain-wrapping,import-ordering,experimental:annotation
|
||||||
|
|
||||||
|
# The following (so far identified) rules are kept:
|
||||||
|
# no-blank-line-before-rbrace
|
||||||
|
# final-newline
|
||||||
|
# no-consecutive-blank-lines
|
||||||
|
# comment-spacing
|
||||||
|
# filename
|
||||||
|
# comma-spacing
|
||||||
|
# paren-spacing
|
||||||
|
# op-spacing
|
||||||
|
# string-template
|
||||||
|
# no-unused-imports
|
||||||
|
# curly-spacing
|
||||||
|
# no-semi
|
||||||
|
# no-empty-class-body
|
||||||
|
# experimental:multiline-if-else
|
||||||
|
# experimental:no-empty-first-line-in-method-block
|
14
.gitignore
vendored
14
.gitignore
vendored
@ -1,14 +1,18 @@
|
|||||||
*.iml
|
*.iml
|
||||||
.gradle
|
.gradle
|
||||||
/local.properties
|
/local.properties
|
||||||
.idea/*
|
# idea files: exclude everything except dictionnaries
|
||||||
/.idea/*
|
.idea/caches
|
||||||
/.idea/libraries
|
.idea/codeStyles
|
||||||
/.idea/modules.xml
|
.idea/libraries
|
||||||
/.idea/workspace.xml
|
.idea/*.xml
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/build
|
/build
|
||||||
/captures
|
/captures
|
||||||
.externalNativeBuild
|
.externalNativeBuild
|
||||||
|
|
||||||
/tmp
|
/tmp
|
||||||
|
|
||||||
|
ktlint
|
||||||
|
.idea/copyright/New_vector.xml
|
||||||
|
.idea/copyright/profiles_settings.xml
|
||||||
|
19
.idea/dictionaries/bmarty.xml
generated
Normal file
19
.idea/dictionaries/bmarty.xml
generated
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<component name="ProjectDictionaryState">
|
||||||
|
<dictionary name="bmarty">
|
||||||
|
<words>
|
||||||
|
<w>backstack</w>
|
||||||
|
<w>bytearray</w>
|
||||||
|
<w>ciphertext</w>
|
||||||
|
<w>decryptor</w>
|
||||||
|
<w>emoji</w>
|
||||||
|
<w>emojis</w>
|
||||||
|
<w>hmac</w>
|
||||||
|
<w>ktlint</w>
|
||||||
|
<w>linkified</w>
|
||||||
|
<w>linkify</w>
|
||||||
|
<w>megolm</w>
|
||||||
|
<w>pbkdf</w>
|
||||||
|
<w>pkcs</w>
|
||||||
|
</words>
|
||||||
|
</dictionary>
|
||||||
|
</component>
|
193
CHANGES.md
193
CHANGES.md
@ -1,11 +1,186 @@
|
|||||||
|
Changes in RiotX 0.8.0 (2019-11-19)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features ✨:
|
||||||
|
- Handle long click on room in the room list (#395)
|
||||||
|
- Ignore/UnIgnore users, and display list of ignored users (#542, #617)
|
||||||
|
|
||||||
|
Improvements 🙌:
|
||||||
|
- Search reaction by name or keyword in emoji picker
|
||||||
|
- Handle code tags (#567)
|
||||||
|
- Support spoiler messages
|
||||||
|
- Support m.sticker and m.room.join_rules events in timeline
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
- Markdown set to off by default (#412)
|
||||||
|
- Accessibility improvements to the attachment file type chooser
|
||||||
|
|
||||||
|
Bugfix 🐛:
|
||||||
|
- Fix issues with some member events rendering (#498)
|
||||||
|
- Passphrase does not match (Export room keys) (#644)
|
||||||
|
- Ask for permission to write external storage when uri comes from the keyboard (#658)
|
||||||
|
- Fix issue with english US/GB translation (#671)
|
||||||
|
|
||||||
|
Changes in RiotX 0.7.0 (2019-10-24)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Share elements from other app to RiotX (#58)
|
||||||
|
- Read marker (#84)
|
||||||
|
- Add ability to report content (#515)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Persist active tab between sessions (#503)
|
||||||
|
- Do not upload file too big for the homeserver (#587)
|
||||||
|
- Attachments: start using system pickers (#52)
|
||||||
|
- Mark all messages as read (#396)
|
||||||
|
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
- Accessibility improvements to read receipts in the room timeline and reactions emoji chooser
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Fix issue on upload error in loop (#587)
|
||||||
|
- Fix opening a permalink: the targeted event is displayed twice (#556)
|
||||||
|
- Fix opening a permalink paginates all the history up to the last event (#282)
|
||||||
|
- after login, the icon in the top left is a green 'A' for (all communities) rather than my avatar (#267)
|
||||||
|
- Picture uploads are unreliable, pictures are shown in wrong aspect ratio on desktop client (#517)
|
||||||
|
- Invitation notifications are not dismissed automatically if room is joined from another client (#347)
|
||||||
|
- Opening links from RiotX reuses browser tab (#599)
|
||||||
|
|
||||||
|
Changes in RiotX 0.6.1 (2019-09-24)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Fix crash: MergedHeaderItem was missing dimensionConverter
|
||||||
|
|
||||||
|
Changes in RiotX 0.6.0 (2019-09-24)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Save draft of a message when exiting a room with non empty composer (#329)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Add unread indent on room list (#485)
|
||||||
|
- Message Editing: Update notifications (#128)
|
||||||
|
- Remove any notification of a redacted event (#563)
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
- Fix a few accessibility issues
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Fix characters erased from the Search field when the result are coming (#545)
|
||||||
|
- "No connection" banner was displayed by mistake
|
||||||
|
- Leaving community (from another client) has no effect on RiotX (#497)
|
||||||
|
- Push rules was not retrieved after a clear cache
|
||||||
|
- m.notice messages trigger push notifications (#238)
|
||||||
|
- Embiggen messages with multiple emojis also for edited messages (#458)
|
||||||
|
|
||||||
|
Build:
|
||||||
|
- Fix (again) issue with bad versionCode generated by Buildkite (#553)
|
||||||
|
|
||||||
|
Changes in RiotX 0.5.0 (2019-09-17)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Implementation of login to homeserver with SSO (#557)
|
||||||
|
- Handle M_CONSENT_NOT_GIVEN error (#64)
|
||||||
|
- Auto configure homeserver and identity server URLs of LoginActivity with a magic link
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Reduce default release build log level, and lab option to enable more logs.
|
||||||
|
- Display a no network indicator when there is no network (#559)
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Fix crash due to missing informationData (#535)
|
||||||
|
- Progress in initial sync dialog is decreasing for a step and should not (#532)
|
||||||
|
- Fix rendering issue of accepted third party invitation event
|
||||||
|
- All current notifications were dismissed by mistake when the app is launched from the launcher
|
||||||
|
|
||||||
|
Build:
|
||||||
|
- Fix issue with version name (#533)
|
||||||
|
- Fix issue with bad versionCode generated by Buildkite (#553)
|
||||||
|
|
||||||
|
Changes in RiotX 0.4.0 (2019-08-30)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Display read receipts in timeline (#81)
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Reactions: Reinstate the ability to react with non-unicode keys (#307)
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Fix text diff linebreak display (#441)
|
||||||
|
- Date change message repeats for each redaction until a normal message (#358)
|
||||||
|
- Slide-in reply icon is distorted (#423)
|
||||||
|
- Regression / e2e replies not encrypted
|
||||||
|
- Some video won't play
|
||||||
|
- Privacy: remove log of notifiable event (#519)
|
||||||
|
- Fix crash with EmojiCompat (#530)
|
||||||
|
|
||||||
|
Changes in RiotX 0.3.0 (2019-08-08)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Create Direct Room flow
|
||||||
|
- Handle `/markdown` command
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- UI for pending edits (#193)
|
||||||
|
- UX image preview screen transition (#393)
|
||||||
|
- Basic support for resending failed messages (retry/remove)
|
||||||
|
- Enable proper cancellation of suspending functions (including db transaction)
|
||||||
|
- Enhances network connectivity checks in SDK
|
||||||
|
- Add "View Edit History" item in the message bottom sheet (#401)
|
||||||
|
- Cancel sync request on pause and timeout to 0 after pause (#404)
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
- Show sync progress also in room detail screen (#403)
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Edited message: link confusion when (edited) appears in body (#398)
|
||||||
|
- Close detail room screen when the room is left with another client (#256)
|
||||||
|
- Clear notification for a room left on another client
|
||||||
|
- Fix messages with empty `in_reply_to` not rendering (#447)
|
||||||
|
- Fix clear cache (#408) and Logout (#205)
|
||||||
|
- Fix `(edited)` link can be copied to clipboard (#402)
|
||||||
|
|
||||||
|
Build:
|
||||||
|
- Split APK: generate one APK per arch, to reduce APK size of about 30%
|
||||||
|
|
||||||
|
|
||||||
|
Changes in RiotX 0.2.0 (2019-07-18)
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Message Editing: View edit history (#121)
|
||||||
|
- Rooms filtering (#304)
|
||||||
|
- Edit in encrypted room
|
||||||
|
|
||||||
|
Improvements:
|
||||||
|
- Handle click on redacted events: view source and create permalink
|
||||||
|
- Improve long tap menu: reply on top, more compact (#368)
|
||||||
|
- Quick reply in timeline with swipe gesture (#167)
|
||||||
|
- Improve edit of replies
|
||||||
|
- Improve performance on Room Members and Users management (#381)
|
||||||
|
|
||||||
|
Other changes:
|
||||||
|
- migrate from rxbinding 2 to rxbinding 3
|
||||||
|
|
||||||
|
Bugfix:
|
||||||
|
- Fix regression on permalink click
|
||||||
|
- Fix crash reported by the PlayStore (#341)
|
||||||
|
- Fix Chat composer separator color in dark/black theme
|
||||||
|
- Fix bad layout for room directory filter (#349)
|
||||||
|
- Fix Copying link from a message shouldn't open context menu (#364)
|
||||||
|
|
||||||
Changes in RiotX 0.1.0 (2019-07-11)
|
Changes in RiotX 0.1.0 (2019-07-11)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
First release!
|
First release!
|
||||||
|
|
||||||
|
Mode details here: https://medium.com/@RiotChat/introducing-the-riotx-beta-for-android-b17952e8f771
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=======================================================
|
=======================================================
|
||||||
@ -13,24 +188,24 @@ First release!
|
|||||||
=======================================================
|
=======================================================
|
||||||
|
|
||||||
|
|
||||||
Changes in RiotX 0.XX (2019-XX-XX)
|
Changes in RiotX 0.0.0 (2019-XX-XX)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Features:
|
Features ✨:
|
||||||
-
|
-
|
||||||
|
|
||||||
Improvements:
|
Improvements 🙌:
|
||||||
-
|
-
|
||||||
|
|
||||||
Other changes:
|
Other changes:
|
||||||
-
|
-
|
||||||
|
|
||||||
Bugfix:
|
Bugfix 🐛:
|
||||||
-
|
-
|
||||||
|
|
||||||
Translations:
|
Translations 🗣:
|
||||||
-
|
-
|
||||||
|
|
||||||
Build:
|
Build 🧱:
|
||||||
-
|
-
|
||||||
|
|
||||||
|
@ -40,19 +40,45 @@ Please add a line to the top of the file `CHANGES.md` describing your change.
|
|||||||
|
|
||||||
Make sure the following commands execute without any error:
|
Make sure the following commands execute without any error:
|
||||||
|
|
||||||
> ./tools/check/check_code_quality.sh
|
#### Internal tool
|
||||||
|
|
||||||
> ./gradlew lintGplayRelease
|
<pre>
|
||||||
|
./tools/check/check_code_quality.sh
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
#### ktlint
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.34.2/ktlint && chmod a+x ktlint
|
||||||
|
./ktlint --android --experimental -v
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
Note that you can run
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
./ktlint --android --experimental -v -F
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
For ktlint to fix some detected errors for you (you still have to check and commit the fix of course)
|
||||||
|
|
||||||
|
#### lint
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
./gradlew lintGplayRelease
|
||||||
|
./gradlew lintFdroidRelease
|
||||||
|
</pre>
|
||||||
|
|
||||||
### Unit tests
|
### Unit tests
|
||||||
|
|
||||||
Make sure the following commands execute without any error:
|
Make sure the following commands execute without any error:
|
||||||
|
|
||||||
> ./gradlew testGplayReleaseUnitTest
|
<pre>
|
||||||
|
./gradlew testGplayReleaseUnitTest
|
||||||
|
</pre>
|
||||||
|
|
||||||
### Tests
|
### Tests
|
||||||
|
|
||||||
RiotX is currently supported on Android Jelly Bean (API 16+): please test your change on an Android device (or Android emulator) running with API 16. Many issues can happen (including crashes) on older devices.
|
RiotX is currently supported on Android KitKat (API 19+): please test your change on an Android device (or Android emulator) running with API 19. Many issues can happen (including crashes) on older devices.
|
||||||
Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient.
|
Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient.
|
||||||
|
|
||||||
### Internationalisation
|
### Internationalisation
|
||||||
@ -60,6 +86,10 @@ Also, if possible, please test your change on a real device. Testing on Android
|
|||||||
When adding new string resources, please only add new entries in file `value/strings.xml`. Translations will be added later by the community of translators with a specific tool named [Weblate](https://translate.riot.im/projects/riot-android/).
|
When adding new string resources, please only add new entries in file `value/strings.xml`. Translations will be added later by the community of translators with a specific tool named [Weblate](https://translate.riot.im/projects/riot-android/).
|
||||||
Do not hesitate to use plurals when appropriate.
|
Do not hesitate to use plurals when appropriate.
|
||||||
|
|
||||||
|
### Accessibility
|
||||||
|
|
||||||
|
Please consider accessibility as an important point. As a minimum requirement, in layout XML files please use attributes such as `android:contentDescription` and `android:importantForAccessibility`, and test with a screen reader if it's working well. You can add new string resources, dedicated to accessibility, in this case, please prefix theirs id with `a11y_`.
|
||||||
|
|
||||||
### Layout
|
### Layout
|
||||||
|
|
||||||
When adding or editing layouts, make sure the layout will render correctly if device uses a RTL (Right To Left) language.
|
When adding or editing layouts, make sure the layout will render correctly if device uses a RTL (Right To Left) language.
|
||||||
|
29
README.md
29
README.md
@ -1,4 +1,4 @@
|
|||||||
[](https://buildkite.com/matrix-dot-org/riotx-android)
|
[](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
|
||||||
[](https://translate.riot.im/engage/riot-android/?utm_source=widget)
|
[](https://translate.riot.im/engage/riot-android/?utm_source=widget)
|
||||||
[](https://matrix.to/#/#riotx:matrix.org)
|
[](https://matrix.to/#/#riotx:matrix.org)
|
||||||
[](https://sonarcloud.io/dashboard?id=vector.android.riotx)
|
[](https://sonarcloud.io/dashboard?id=vector.android.riotx)
|
||||||
@ -7,14 +7,31 @@
|
|||||||
|
|
||||||
# RiotX Android
|
# RiotX Android
|
||||||
|
|
||||||
RiotX is an Android Matrix Client currently in development. The application is not yet available on the PlayStore.
|
RiotX is an Android Matrix Client currently in beta but in active development.
|
||||||
|
|
||||||
It's based on a new Matrix SDK, written in Kotlin.
|
It is a total rewrite of [Riot-Android](https://github.com/vector-im/riot-android) with a new user experience. RiotX will become the official replacement as soon as all features are implemented.
|
||||||
|
|
||||||
Download nightly build here: [](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
|
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=im.vector.riotx)
|
||||||
|
|
||||||
|
Nightly build: [](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
|
||||||
|
|
||||||
|
# New Android SDK
|
||||||
|
|
||||||
|
RiotX is based on a new Android SDK fully written in Kotlin (like RiotX). In order to make the early development as fast as possible, RiotX and the new SDK currently share the same git repository. We will make separate repos once the API is stable enough.
|
||||||
|
|
||||||
|
|
||||||
|
# Roadmap
|
||||||
|
|
||||||
|
The current target is to release an application out of beta with the same level of features (and even more) as Riot.
|
||||||
|
The roadmap has 3 phases:
|
||||||
|
|
||||||
|
- [phase 0](https://github.com/vector-im/riotX-android/labels/phase0): Prototyping / Project setup
|
||||||
|
- [phase 1](https://github.com/vector-im/riotX-android/labels/phase1): Beta release to the Play Store
|
||||||
|
- [phase 2](https://github.com/vector-im/riotX-android/labels/phase2): Out of beta
|
||||||
|
|
||||||
Matrix Room: [](https://matrix.to/#/#riotx:matrix.org)
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Please refer to [CONTRIBUTING.md](https://github.com/vector-im/riotX-android/blob/develop/CONTRIBUTING.md) if you want to contribute the Matrix on Android projects!
|
Please refer to [CONTRIBUTING.md](https://github.com/vector-im/riotX-android/blob/develop/CONTRIBUTING.md) if you want to contribute on Matrix Android projects!
|
||||||
|
|
||||||
|
Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#riotx:matrix.org).
|
||||||
|
34
build.gradle
34
build.gradle
@ -1,7 +1,7 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.21'
|
ext.kotlin_version = '1.3.50'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
@ -10,11 +10,11 @@ buildscript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.4.1'
|
classpath 'com.android.tools.build:gradle:3.5.1'
|
||||||
classpath 'com.google.gms:google-services:4.2.0'
|
classpath 'com.google.gms:google-services:4.3.2'
|
||||||
classpath "com.airbnb.okreplay:gradle-plugin:1.4.0"
|
classpath "com.airbnb.okreplay:gradle-plugin:1.5.0"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2'
|
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
|
||||||
classpath 'com.google.android.gms:oss-licenses-plugin:0.9.5'
|
classpath 'com.google.android.gms:oss-licenses-plugin:0.9.5'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
@ -45,7 +45,31 @@ allprojects {
|
|||||||
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url 'https://repo.adobe.com/nexus/content/repositories/public/'
|
||||||
|
content {
|
||||||
|
includeGroupByRegex "diff_match_patch"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).all {
|
||||||
|
options.compilerArgs += [
|
||||||
|
'-Adagger.gradle.incremental=enabled'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
||||||
|
// Warnings are potential errors, so stop ignoring them
|
||||||
|
kotlinOptions.allWarningsAsErrors = true
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
extensions.findByName("kapt")?.arguments {
|
||||||
|
arg("dagger.gradle.incremental", "enabled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
This document aims to describe how Riot X android displays notifications to the end user. It also clarifies notifications and background settings in the app.
|
This document aims to describe how RiotX android displays notifications to the end user. It also clarifies notifications and background settings in the app.
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
1. [Prerequisites Knowledge](#prerequisites-knowledge)
|
1. [Prerequisites Knowledge](#prerequisites-knowledge)
|
||||||
@ -50,7 +50,7 @@ By default, this is 0, so the server will return immediately even if the respons
|
|||||||
|
|
||||||
**delay** is a client preference. When the server responds to a sync request, the client waits for `delay`before calling a new sync.
|
**delay** is a client preference. When the server responds to a sync request, the client waits for `delay`before calling a new sync.
|
||||||
|
|
||||||
When the Riot X Android app is open (i.e in foreground state), the default timeout is 30 seconds, and delay is 0.
|
When the RiotX Android app is open (i.e in foreground state), the default timeout is 30 seconds, and delay is 0.
|
||||||
|
|
||||||
## How does a mobile app receives push notification
|
## How does a mobile app receives push notification
|
||||||
|
|
||||||
@ -86,7 +86,7 @@ This need some disambiguation, because it is the source of common confusion:
|
|||||||
In order to send a push to a mobile, App developers need to have a server that will use the FCM APIs, and these APIs requires authentication!
|
In order to send a push to a mobile, App developers need to have a server that will use the FCM APIs, and these APIs requires authentication!
|
||||||
This server is called a **Push Gateway** in the matrix world
|
This server is called a **Push Gateway** in the matrix world
|
||||||
|
|
||||||
That means that Riot X Android, a matrix client created by New Vector, is using a **Push Gateway** with the needed credentials (FCM API secret Key) in order to send push to the New Vector client.
|
That means that RiotX Android, a matrix client created by New Vector, is using a **Push Gateway** with the needed credentials (FCM API secret Key) in order to send push to the New Vector client.
|
||||||
|
|
||||||
If you create your own matrix client, you will also need to deploy an instance of a **Push Gateway** with the credentials needed to use FCM for your app.
|
If you create your own matrix client, you will also need to deploy an instance of a **Push Gateway** with the credentials needed to use FCM for your app.
|
||||||
|
|
||||||
@ -223,7 +223,7 @@ Upon reception of the FCM push, RiotX will perform a sync call to the Home Serve
|
|||||||
* The sync generates additional notifications (e.g an encrypted message where the user is mentioned detected locally)
|
* The sync generates additional notifications (e.g an encrypted message where the user is mentioned detected locally)
|
||||||
* The sync takes too long and the process is killed before completion, or network is not reliable and the sync fails.
|
* The sync takes too long and the process is killed before completion, or network is not reliable and the sync fails.
|
||||||
|
|
||||||
Riot X implements several strategies in these cases (TODO document)
|
RiotX implements several strategies in these cases (TODO document)
|
||||||
|
|
||||||
## FCM Fallback mode
|
## FCM Fallback mode
|
||||||
|
|
||||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Tue Mar 19 09:53:05 CET 2019
|
#Fri Sep 27 10:10:35 CEST 2019
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
|
||||||
|
@ -5,16 +5,15 @@ apply plugin: 'kotlin-kapt'
|
|||||||
android {
|
android {
|
||||||
compileSdkVersion 28
|
compileSdkVersion 28
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
|
|
||||||
|
// Multidex is useful for tests
|
||||||
|
multiDexEnabled true
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@ -29,15 +28,18 @@ android {
|
|||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
||||||
implementation project(":matrix-sdk-android")
|
implementation project(":matrix-sdk-android")
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
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'
|
||||||
|
// Paging
|
||||||
|
implementation "androidx.paging:paging-runtime-ktx:2.1.0"
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test:runner:1.2.0'
|
androidTestImplementation 'androidx.test:runner:1.2.0'
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2019 New Vector Ltd
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.vector.matrix.rx;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
public void useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
|
||||||
|
|
||||||
assertEquals("im.vector.matrix.rx.test", appContext.getPackageName());
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ import androidx.lifecycle.LiveData
|
|||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.android.MainThreadDisposable
|
import io.reactivex.android.MainThreadDisposable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
|
||||||
private class LiveDataObservable<T>(
|
private class LiveDataObservable<T>(
|
||||||
private val liveData: LiveData<T>,
|
private val liveData: LiveData<T>,
|
||||||
@ -57,5 +58,5 @@ private class LiveDataObservable<T>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun <T> LiveData<T>.asObservable(): Observable<T> {
|
fun <T> LiveData<T>.asObservable(): Observable<T> {
|
||||||
return LiveDataObservable(this)
|
return LiveDataObservable(this).observeOn(Schedulers.computation())
|
||||||
}
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.rx
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
import io.reactivex.CompletableEmitter
|
||||||
|
|
||||||
|
internal class MatrixCallbackCompletable<T>(private val completableEmitter: CompletableEmitter) : MatrixCallback<T> {
|
||||||
|
|
||||||
|
override fun onSuccess(data: T) {
|
||||||
|
completableEmitter.onComplete()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFailure(failure: Throwable) {
|
||||||
|
completableEmitter.tryOnError(failure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Cancelable.toCompletable(completableEmitter: CompletableEmitter) {
|
||||||
|
completableEmitter.setCancellable {
|
||||||
|
this.cancel()
|
||||||
|
}
|
||||||
|
}
|
@ -14,25 +14,25 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.core.utils
|
package im.vector.matrix.rx
|
||||||
|
|
||||||
import com.jakewharton.rxrelay2.BehaviorRelay
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import io.reactivex.Observable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.SingleEmitter
|
||||||
|
|
||||||
open class RxStore<T>(defaultValue: T? = null) {
|
internal class MatrixCallbackSingle<T>(private val singleEmitter: SingleEmitter<T>) : MatrixCallback<T> {
|
||||||
|
|
||||||
private val storeSubject: BehaviorRelay<T> = if (defaultValue == null) {
|
override fun onSuccess(data: T) {
|
||||||
BehaviorRelay.create<T>()
|
singleEmitter.onSuccess(data)
|
||||||
} else {
|
|
||||||
BehaviorRelay.createDefault(defaultValue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun observe(): Observable<T> {
|
override fun onFailure(failure: Throwable) {
|
||||||
return storeSubject.hide().observeOn(Schedulers.computation())
|
singleEmitter.tryOnError(failure)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
fun post(value: T) {
|
|
||||||
storeSubject.accept(value)
|
fun <T> Cancelable.toSingle(singleEmitter: SingleEmitter<T>) {
|
||||||
|
singleEmitter.setCancellable {
|
||||||
|
this.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.rx
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
import io.reactivex.Observable
|
||||||
|
|
||||||
|
fun <T : Any> Observable<Optional<T>>.unwrap(): Observable<T> {
|
||||||
|
return filter { it.hasValue() }.map { it.get() }
|
||||||
|
}
|
@ -18,29 +18,60 @@ package im.vector.matrix.rx
|
|||||||
|
|
||||||
import im.vector.matrix.android.api.session.room.Room
|
import im.vector.matrix.android.api.session.room.Room
|
||||||
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
|
||||||
|
import im.vector.matrix.android.api.session.room.model.ReadReceipt
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
|
import im.vector.matrix.android.api.session.room.notification.RoomNotificationState
|
||||||
|
import im.vector.matrix.android.api.session.room.send.UserDraft
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.Single
|
||||||
|
|
||||||
class RxRoom(private val room: Room) {
|
class RxRoom(private val room: Room) {
|
||||||
|
|
||||||
fun liveRoomSummary(): Observable<RoomSummary> {
|
fun liveRoomSummary(): Observable<Optional<RoomSummary>> {
|
||||||
return room.liveRoomSummary().asObservable().observeOn(Schedulers.computation())
|
return room.getRoomSummaryLive().asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveRoomMemberIds(): Observable<List<String>> {
|
fun liveRoomMemberIds(): Observable<List<String>> {
|
||||||
return room.getRoomMemberIdsLive().asObservable().observeOn(Schedulers.computation())
|
return room.getRoomMemberIdsLive().asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveAnnotationSummary(eventId: String): Observable<EventAnnotationsSummary> {
|
fun liveAnnotationSummary(eventId: String): Observable<Optional<EventAnnotationsSummary>> {
|
||||||
return room.getEventSummaryLive(eventId).asObservable().observeOn(Schedulers.computation())
|
return room.getEventSummaryLive(eventId).asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveTimelineEvent(eventId: String): Observable<TimelineEvent> {
|
fun liveTimelineEvent(eventId: String): Observable<Optional<TimelineEvent>> {
|
||||||
return room.liveTimeLineEvent(eventId).asObservable().observeOn(Schedulers.computation())
|
return room.getTimeLineEventLive(eventId).asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun liveReadMarker(): Observable<Optional<String>> {
|
||||||
|
return room.getReadMarkerLive().asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun liveReadReceipt(): Observable<Optional<String>> {
|
||||||
|
return room.getMyReadReceiptLive().asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun loadRoomMembersIfNeeded(): Single<Unit> = Single.create {
|
||||||
|
room.loadRoomMembersIfNeeded(MatrixCallbackSingle(it)).toSingle(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun joinRoom(viaServers: List<String> = emptyList()): Single<Unit> = Single.create {
|
||||||
|
room.join(viaServers, MatrixCallbackSingle(it)).toSingle(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun liveEventReadReceipts(eventId: String): Observable<List<ReadReceipt>> {
|
||||||
|
return room.getEventReadReceiptsLive(eventId).asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun liveDrafts(): Observable<List<UserDraft>> {
|
||||||
|
return room.getDraftsLive().asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun liveNotificationState(): Observable<RoomNotificationState> {
|
||||||
|
return room.getLiveRoomNotificationState().asObservable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Room.rx(): RxRoom {
|
fun Room.rx(): RxRoom {
|
||||||
|
@ -16,32 +16,65 @@
|
|||||||
|
|
||||||
package im.vector.matrix.rx
|
package im.vector.matrix.rx
|
||||||
|
|
||||||
|
import androidx.paging.PagedList
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
import im.vector.matrix.android.api.session.pushers.Pusher
|
import im.vector.matrix.android.api.session.pushers.Pusher
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
|
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||||
import im.vector.matrix.android.api.session.sync.SyncState
|
import im.vector.matrix.android.api.session.sync.SyncState
|
||||||
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.Single
|
||||||
|
|
||||||
class RxSession(private val session: Session) {
|
class RxSession(private val session: Session) {
|
||||||
|
|
||||||
fun liveRoomSummaries(): Observable<List<RoomSummary>> {
|
fun liveRoomSummaries(): Observable<List<RoomSummary>> {
|
||||||
return session.liveRoomSummaries().asObservable().observeOn(Schedulers.computation())
|
return session.liveRoomSummaries().asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
|
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
|
||||||
return session.liveGroupSummaries().asObservable().observeOn(Schedulers.computation())
|
return session.liveGroupSummaries().asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun liveSyncState(): Observable<SyncState> {
|
fun liveSyncState(): Observable<SyncState> {
|
||||||
return session.syncState().asObservable().observeOn(Schedulers.computation())
|
return session.syncState().asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun livePushers(): Observable<List<Pusher>> {
|
fun livePushers(): Observable<List<Pusher>> {
|
||||||
return session.livePushers().asObservable().observeOn(Schedulers.computation())
|
return session.livePushers().asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun liveUser(userId: String): Observable<Optional<User>> {
|
||||||
|
return session.liveUser(userId).asObservable().distinctUntilChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun liveUsers(): Observable<List<User>> {
|
||||||
|
return session.liveUsers().asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun liveIgnoredUsers(): Observable<List<User>> {
|
||||||
|
return session.liveIgnoredUsers().asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun livePagedUsers(filter: String? = null): Observable<PagedList<User>> {
|
||||||
|
return session.livePagedUsers(filter).asObservable()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createRoom(roomParams: CreateRoomParams): Single<String> = Single.create {
|
||||||
|
session.createRoom(roomParams, MatrixCallbackSingle(it)).toSingle(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchUsersDirectory(search: String,
|
||||||
|
limit: Int,
|
||||||
|
excludedUserIds: Set<String>): Single<List<User>> = Single.create {
|
||||||
|
session.searchUsersDirectory(search, limit, excludedUserIds, MatrixCallbackSingle(it)).toSingle(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun joinRoom(roomId: String, viaServers: List<String> = emptyList()): Single<Unit> = Single.create {
|
||||||
|
session.joinRoom(roomId, viaServers, MatrixCallbackSingle(it)).toSingle(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Session.rx(): RxSession {
|
fun Session.rx(): RxSession {
|
||||||
|
@ -67,6 +67,10 @@ android {
|
|||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "1.8"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static def gitRevision() {
|
static def gitRevision() {
|
||||||
@ -86,49 +90,47 @@ static def gitRevisionDate() {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
def arrow_version = "0.8.0"
|
def arrow_version = "0.8.2"
|
||||||
def support_version = '1.1.0-beta01'
|
|
||||||
def moshi_version = '1.8.0'
|
def moshi_version = '1.8.0'
|
||||||
def lifecycle_version = '2.0.0'
|
def lifecycle_version = '2.1.0'
|
||||||
def coroutines_version = "1.0.1"
|
def coroutines_version = "1.3.2"
|
||||||
def markwon_version = '3.0.0'
|
def markwon_version = '3.1.0'
|
||||||
def daggerVersion = '2.23.1'
|
def daggerVersion = '2.24'
|
||||||
|
|
||||||
implementation fileTree(dir: 'libs', include: ['*.aar'])
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
implementation "androidx.appcompat:appcompat:1.1.0-rc01"
|
implementation "androidx.appcompat:appcompat:1.1.0"
|
||||||
implementation "androidx.recyclerview:recyclerview:1.1.0-beta01"
|
implementation "androidx.recyclerview:recyclerview:1.1.0-beta05"
|
||||||
|
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||||
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
|
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
|
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
|
||||||
implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
|
implementation 'com.squareup.retrofit2:converter-moshi:2.6.2'
|
||||||
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
|
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
|
||||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
|
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2'
|
||||||
implementation 'com.novoda:merlin:1.1.6'
|
implementation 'com.novoda:merlin:1.2.0'
|
||||||
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
|
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
|
||||||
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
|
||||||
|
|
||||||
implementation "ru.noties.markwon:core:$markwon_version"
|
implementation "ru.noties.markwon:core:$markwon_version"
|
||||||
|
|
||||||
|
// Image
|
||||||
|
implementation 'androidx.exifinterface:exifinterface:1.0.0'
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
|
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
|
||||||
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
|
||||||
|
|
||||||
// Work
|
// Work
|
||||||
implementation "androidx.work:work-runtime-ktx:2.1.0-rc01"
|
implementation "androidx.work:work-runtime-ktx:2.3.0-alpha01"
|
||||||
|
|
||||||
// FP
|
// FP
|
||||||
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
implementation "io.arrow-kt:arrow-core:$arrow_version"
|
||||||
implementation "io.arrow-kt:arrow-instances-core:$arrow_version"
|
implementation "io.arrow-kt:arrow-instances-core:$arrow_version"
|
||||||
implementation "io.arrow-kt:arrow-effects:$arrow_version"
|
|
||||||
implementation "io.arrow-kt:arrow-effects-instances:$arrow_version"
|
|
||||||
implementation "io.arrow-kt:arrow-integration-retrofit-adapter:$arrow_version"
|
|
||||||
|
|
||||||
// olm lib is now hosted by jitpack: https://jitpack.io/#org.matrix.gitlab.matrix-org/olm
|
// olm lib is now hosted by jitpack: https://jitpack.io/#org.matrix.gitlab.matrix-org/olm
|
||||||
implementation 'org.matrix.gitlab.matrix-org:olm:3.1.2'
|
implementation 'org.matrix.gitlab.matrix-org:olm:3.1.2'
|
||||||
@ -136,21 +138,25 @@ dependencies {
|
|||||||
// DI
|
// DI
|
||||||
implementation "com.google.dagger:dagger:$daggerVersion"
|
implementation "com.google.dagger:dagger:$daggerVersion"
|
||||||
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
|
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||||
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
|
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0'
|
||||||
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
|
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
|
||||||
|
|
||||||
// Logging
|
// Logging
|
||||||
implementation 'com.jakewharton.timber:timber:4.7.1'
|
implementation 'com.jakewharton.timber:timber:4.7.1'
|
||||||
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.0'
|
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1'
|
||||||
|
|
||||||
debugImplementation 'com.airbnb.okreplay:okreplay:1.4.0'
|
// Bus
|
||||||
releaseImplementation 'com.airbnb.okreplay:noop:1.4.0'
|
implementation 'org.greenrobot:eventbus:3.1.1'
|
||||||
androidTestImplementation 'com.airbnb.okreplay:espresso:1.4.0'
|
|
||||||
|
debugImplementation 'com.airbnb.okreplay:okreplay:1.5.0'
|
||||||
|
releaseImplementation 'com.airbnb.okreplay:noop:1.5.0'
|
||||||
|
androidTestImplementation 'com.airbnb.okreplay:espresso:1.5.0'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testImplementation 'org.robolectric:robolectric:4.0.2'
|
testImplementation 'org.robolectric:robolectric:4.3'
|
||||||
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
|
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
|
||||||
testImplementation "io.mockk:mockk:1.8.13.kotlin13"
|
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||||
|
testImplementation 'io.mockk:mockk:1.9.2.kotlin12'
|
||||||
testImplementation 'org.amshove.kluent:kluent-android:1.44'
|
testImplementation 'org.amshove.kluent:kluent-android:1.44'
|
||||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
@ -160,7 +166,8 @@ dependencies {
|
|||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||||
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'
|
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'
|
||||||
androidTestImplementation "io.mockk:mockk-android:1.8.13.kotlin13"
|
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
|
||||||
|
androidTestImplementation 'io.mockk:mockk-android:1.9.2.kotlin12'
|
||||||
androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
|
androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
|
||||||
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||||
|
|
||||||
|
Binary file not shown.
@ -17,12 +17,12 @@
|
|||||||
package im.vector.matrix.android
|
package im.vector.matrix.android
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.test.InstrumentationRegistry
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
interface InstrumentedTest {
|
interface InstrumentedTest {
|
||||||
fun context(): Context {
|
fun context(): Context {
|
||||||
return InstrumentationRegistry.getTargetContext()
|
return ApplicationProvider.getApplicationContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cacheDir(): File {
|
fun cacheDir(): File {
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android;
|
package im.vector.matrix.android;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
package im.vector.matrix.android.auth
|
package im.vector.matrix.android.auth
|
||||||
|
|
||||||
import androidx.test.annotation.UiThreadTest
|
import androidx.test.annotation.UiThreadTest
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.rule.GrantPermissionRule
|
import androidx.test.rule.GrantPermissionRule
|
||||||
import androidx.test.runner.AndroidJUnit4
|
|
||||||
import im.vector.matrix.android.InstrumentedTest
|
import im.vector.matrix.android.InstrumentedTest
|
||||||
import im.vector.matrix.android.OkReplayRuleChainNoActivity
|
import im.vector.matrix.android.OkReplayRuleChainNoActivity
|
||||||
import im.vector.matrix.android.api.auth.Authenticator
|
import im.vector.matrix.android.api.auth.Authenticator
|
||||||
@ -28,7 +28,6 @@ import org.junit.Rule
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
internal class AuthenticatorTest : InstrumentedTest {
|
internal class AuthenticatorTest : InstrumentedTest {
|
||||||
|
|
||||||
@ -50,7 +49,6 @@ internal class AuthenticatorTest : InstrumentedTest {
|
|||||||
@UiThreadTest
|
@UiThreadTest
|
||||||
@OkReplay(tape = "auth", mode = TapeMode.READ_WRITE)
|
@OkReplay(tape = "auth", mode = TapeMode.READ_WRITE)
|
||||||
fun auth() {
|
fun auth() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -59,6 +57,4 @@ internal class AuthenticatorTest : InstrumentedTest {
|
|||||||
val grantExternalStoragePermissionRule: GrantPermissionRule =
|
val grantExternalStoragePermissionRule: GrantPermissionRule =
|
||||||
GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
|
|||||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore
|
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore
|
||||||
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
|
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
|
||||||
import io.realm.RealmConfiguration
|
import io.realm.RealmConfiguration
|
||||||
import java.util.*
|
import kotlin.random.Random
|
||||||
|
|
||||||
internal class CryptoStoreHelper {
|
internal class CryptoStoreHelper {
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ internal class CryptoStoreHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun createCredential() = Credentials(
|
fun createCredential() = Credentials(
|
||||||
userId = "userId_" + Random().nextInt(),
|
userId = "userId_" + Random.nextInt(),
|
||||||
homeServer = "http://matrix.org",
|
homeServer = "http://matrix.org",
|
||||||
accessToken = "access_token",
|
accessToken = "access_token",
|
||||||
refreshToken = null,
|
refreshToken = null,
|
||||||
|
@ -62,8 +62,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||||||
JsonCanonicalizer.canonicalize("{\"a\":\"\\\"\"}"))
|
JsonCanonicalizer.canonicalize("{\"a\":\"\\\"\"}"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
* Test from https://matrix.org/docs/spec/appendices.html#examples
|
* Test from https://matrix.org/docs/spec/appendices.html#examples
|
||||||
* ========================================================================================== */
|
* ========================================================================================== */
|
||||||
@ -74,7 +72,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||||||
JsonCanonicalizer.canonicalize("""{}"""))
|
JsonCanonicalizer.canonicalize("""{}"""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun matrixOrg002Test() {
|
fun matrixOrg002Test() {
|
||||||
assertEquals("""{"one":1,"two":"Two"}""",
|
assertEquals("""{"one":1,"two":"Two"}""",
|
||||||
@ -84,7 +81,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||||||
}"""))
|
}"""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun matrixOrg003Test() {
|
fun matrixOrg003Test() {
|
||||||
assertEquals("""{"a":"1","b":"2"}""",
|
assertEquals("""{"a":"1","b":"2"}""",
|
||||||
@ -94,14 +90,12 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||||||
}"""))
|
}"""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun matrixOrg004Test() {
|
fun matrixOrg004Test() {
|
||||||
assertEquals("""{"a":"1","b":"2"}""",
|
assertEquals("""{"a":"1","b":"2"}""",
|
||||||
JsonCanonicalizer.canonicalize("""{"b":"2","a":"1"}"""))
|
JsonCanonicalizer.canonicalize("""{"b":"2","a":"1"}"""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun matrixOrg005Test() {
|
fun matrixOrg005Test() {
|
||||||
assertEquals("""{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}""",
|
assertEquals("""{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}""",
|
||||||
@ -126,7 +120,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||||||
}"""))
|
}"""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun matrixOrg006Test() {
|
fun matrixOrg006Test() {
|
||||||
assertEquals("""{"a":"日本語"}""",
|
assertEquals("""{"a":"日本語"}""",
|
||||||
@ -135,7 +128,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||||||
}"""))
|
}"""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun matrixOrg007Test() {
|
fun matrixOrg007Test() {
|
||||||
assertEquals("""{"日":1,"本":2}""",
|
assertEquals("""{"日":1,"本":2}""",
|
||||||
@ -145,7 +137,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
|
|||||||
}"""))
|
}"""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun matrixOrg008Test() {
|
fun matrixOrg008Test() {
|
||||||
assertEquals("""{"a":"日"}""",
|
assertEquals("""{"a":"日"}""",
|
||||||
|
@ -19,11 +19,7 @@ package im.vector.matrix.android.session.room.timeline
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.zhuinden.monarchy.Monarchy
|
import com.zhuinden.monarchy.Monarchy
|
||||||
import im.vector.matrix.android.InstrumentedTest
|
import im.vector.matrix.android.InstrumentedTest
|
||||||
import im.vector.matrix.android.internal.database.helper.add
|
import im.vector.matrix.android.internal.database.helper.*
|
||||||
import im.vector.matrix.android.internal.database.helper.addAll
|
|
||||||
import im.vector.matrix.android.internal.database.helper.isUnlinked
|
|
||||||
import im.vector.matrix.android.internal.database.helper.lastStateIndex
|
|
||||||
import im.vector.matrix.android.internal.database.helper.merge
|
|
||||||
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
import im.vector.matrix.android.internal.database.model.ChunkEntity
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
||||||
import im.vector.matrix.android.session.room.timeline.RoomDataHelper.createFakeListOfEvents
|
import im.vector.matrix.android.session.room.timeline.RoomDataHelper.createFakeListOfEvents
|
||||||
@ -39,7 +35,6 @@ import org.junit.Before
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
@RunWith(AndroidJUnit4::class)
|
||||||
internal class ChunkEntityTest : InstrumentedTest {
|
internal class ChunkEntityTest : InstrumentedTest {
|
||||||
|
|
||||||
@ -52,7 +47,6 @@ internal class ChunkEntityTest : InstrumentedTest {
|
|||||||
monarchy = Monarchy.Builder().setRealmConfiguration(testConfig).build()
|
monarchy = Monarchy.Builder().setRealmConfiguration(testConfig).build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun add_shouldAdd_whenNotAlreadyIncluded() {
|
fun add_shouldAdd_whenNotAlreadyIncluded() {
|
||||||
monarchy.runTransactionSync { realm ->
|
monarchy.runTransactionSync { realm ->
|
||||||
@ -198,5 +192,4 @@ internal class ChunkEntityTest : InstrumentedTest {
|
|||||||
chunk1.nextToken shouldEqual nextToken
|
chunk1.nextToken shouldEqual nextToken
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.session.room.timeline
|
package im.vector.matrix.android.session.room.timeline
|
||||||
|
|
||||||
import arrow.core.Try
|
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask
|
import im.vector.matrix.android.internal.session.room.timeline.GetContextOfEventTask
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor
|
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor
|
||||||
@ -24,7 +23,7 @@ import kotlin.random.Random
|
|||||||
|
|
||||||
internal class FakeGetContextOfEventTask constructor(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : GetContextOfEventTask {
|
internal class FakeGetContextOfEventTask constructor(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : GetContextOfEventTask {
|
||||||
|
|
||||||
override suspend fun execute(params: GetContextOfEventTask.Params): Try<TokenChunkEventPersistor.Result> {
|
override suspend fun execute(params: GetContextOfEventTask.Params): TokenChunkEventPersistor.Result {
|
||||||
val fakeEvents = RoomDataHelper.createFakeListOfEvents(30)
|
val fakeEvents = RoomDataHelper.createFakeListOfEvents(30)
|
||||||
val tokenChunkEvent = FakeTokenChunkEvent(
|
val tokenChunkEvent = FakeTokenChunkEvent(
|
||||||
Random.nextLong(System.currentTimeMillis()).toString(),
|
Random.nextLong(System.currentTimeMillis()).toString(),
|
||||||
@ -33,6 +32,4 @@ internal class FakeGetContextOfEventTask constructor(private val tokenChunkEvent
|
|||||||
)
|
)
|
||||||
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS)
|
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.session.room.timeline
|
package im.vector.matrix.android.session.room.timeline
|
||||||
|
|
||||||
import arrow.core.Try
|
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.PaginationTask
|
import im.vector.matrix.android.internal.session.room.timeline.PaginationTask
|
||||||
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor
|
import im.vector.matrix.android.internal.session.room.timeline.TokenChunkEventPersistor
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -24,11 +23,9 @@ import kotlin.random.Random
|
|||||||
|
|
||||||
internal class FakePaginationTask @Inject constructor(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : PaginationTask {
|
internal class FakePaginationTask @Inject constructor(private val tokenChunkEventPersistor: TokenChunkEventPersistor) : PaginationTask {
|
||||||
|
|
||||||
override suspend fun execute(params: PaginationTask.Params): Try<TokenChunkEventPersistor.Result> {
|
override suspend fun execute(params: PaginationTask.Params): TokenChunkEventPersistor.Result {
|
||||||
val fakeEvents = RoomDataHelper.createFakeListOfEvents(30)
|
val fakeEvents = RoomDataHelper.createFakeListOfEvents(30)
|
||||||
val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents)
|
val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents)
|
||||||
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction)
|
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,6 +88,4 @@ object RoomDataHelper {
|
|||||||
roomEntity.addOrUpdate(chunkEntity)
|
roomEntity.addOrUpdate(chunkEntity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -81,6 +81,4 @@ internal class TimelineTest : InstrumentedTest {
|
|||||||
// timelineEvents.size shouldEqual initialLoad + paginationCount
|
// timelineEvents.size shouldEqual initialLoad + paginationCount
|
||||||
// timeline.dispose()
|
// timeline.dispose()
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -22,6 +22,7 @@ import okhttp3.Interceptor
|
|||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import okhttp3.logging.HttpLoggingInterceptor
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import okio.Buffer
|
import okio.Buffer
|
||||||
|
import timber.log.Timber
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -51,27 +52,33 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
|
|||||||
var compressed = false
|
var compressed = false
|
||||||
|
|
||||||
var curlCmd = "curl"
|
var curlCmd = "curl"
|
||||||
if (curlOptions != null) {
|
curlOptions?.let {
|
||||||
curlCmd += " " + curlOptions!!
|
curlCmd += " $it"
|
||||||
}
|
}
|
||||||
curlCmd += " -X " + request.method()
|
curlCmd += " -X " + request.method
|
||||||
|
|
||||||
val requestBody = request.body()
|
val requestBody = request.body
|
||||||
if (requestBody != null) {
|
if (requestBody != null) {
|
||||||
val buffer = Buffer()
|
if (requestBody.contentLength() > 100_000) {
|
||||||
requestBody.writeTo(buffer)
|
Timber.w("Unable to log curl command data, size is too big (${requestBody.contentLength()})")
|
||||||
var charset: Charset? = UTF8
|
// Ensure the curl command will failed
|
||||||
val contentType = requestBody.contentType()
|
curlCmd += "DATA IS TOO BIG"
|
||||||
if (contentType != null) {
|
} else {
|
||||||
charset = contentType.charset(UTF8)
|
val buffer = Buffer()
|
||||||
|
requestBody.writeTo(buffer)
|
||||||
|
var charset: Charset? = UTF8
|
||||||
|
val contentType = requestBody.contentType()
|
||||||
|
if (contentType != null) {
|
||||||
|
charset = contentType.charset(UTF8)
|
||||||
|
}
|
||||||
|
// try to keep to a single line and use a subshell to preserve any line breaks
|
||||||
|
curlCmd += " --data $'" + buffer.readString(charset!!).replace("\n", "\\n") + "'"
|
||||||
}
|
}
|
||||||
// try to keep to a single line and use a subshell to preserve any line breaks
|
|
||||||
curlCmd += " --data $'" + buffer.readString(charset!!).replace("\n", "\\n") + "'"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val headers = request.headers()
|
val headers = request.headers
|
||||||
var i = 0
|
var i = 0
|
||||||
val count = headers.size()
|
val count = headers.size
|
||||||
while (i < count) {
|
while (i < count) {
|
||||||
val name = headers.name(i)
|
val name = headers.name(i)
|
||||||
val value = headers.value(i)
|
val value = headers.value(i)
|
||||||
@ -82,7 +89,7 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
curlCmd += ((if (compressed) " --compressed " else " ") + "'" + request.url().toString()
|
curlCmd += ((if (compressed) " --compressed " else " ") + "'" + request.url.toString()
|
||||||
// Replace localhost for emulator by localhost for shell
|
// Replace localhost for emulator by localhost for shell
|
||||||
.replace("://10.0.2.2:8080/".toRegex(), "://127.0.0.1:8080/")
|
.replace("://10.0.2.2:8080/".toRegex(), "://127.0.0.1:8080/")
|
||||||
+ "'")
|
+ "'")
|
||||||
@ -90,7 +97,7 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
|
|||||||
// Add Json formatting
|
// Add Json formatting
|
||||||
curlCmd += " | python -m json.tool"
|
curlCmd += " | python -m json.tool"
|
||||||
|
|
||||||
logger.log("--- cURL (" + request.url() + ")")
|
logger.log("--- cURL (" + request.url + ")")
|
||||||
logger.log(curlCmd)
|
logger.log(curlCmd)
|
||||||
|
|
||||||
return chain.proceed(request)
|
return chain.proceed(request)
|
||||||
|
@ -51,7 +51,6 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
|||||||
// 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 {
|
||||||
@ -61,7 +60,6 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
|
|||||||
// 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
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,6 @@ data class MatrixConfiguration(
|
|||||||
interface Provider {
|
interface Provider {
|
||||||
fun providesMatrixConfiguration(): MatrixConfiguration
|
fun providesMatrixConfiguration(): MatrixConfiguration
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,5 +97,4 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
|
|||||||
return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
|
return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ interface MatrixCallback<in T> {
|
|||||||
* @param data the data successfully returned from the async function
|
* @param data the data successfully returned from the async function
|
||||||
*/
|
*/
|
||||||
fun onSuccess(data: T) {
|
fun onSuccess(data: T) {
|
||||||
//no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,7 +35,6 @@ interface MatrixCallback<in T> {
|
|||||||
* @param failure the failure data returned from the async function
|
* @param failure the failure data returned from the async function
|
||||||
*/
|
*/
|
||||||
fun onFailure(failure: Throwable) {
|
fun onFailure(failure: Throwable) {
|
||||||
//no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.api
|
package im.vector.matrix.android.api
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class contains pattern to match the different Matrix ids
|
* This class contains pattern to match the different Matrix ids
|
||||||
*/
|
*/
|
||||||
@ -28,7 +27,7 @@ object MatrixPatterns {
|
|||||||
// regex pattern to find matrix user ids in a string.
|
// regex pattern to find matrix user ids in a string.
|
||||||
// See https://matrix.org/speculator/spec/HEAD/appendices.html#historical-user-ids
|
// See https://matrix.org/speculator/spec/HEAD/appendices.html#historical-user-ids
|
||||||
private const val MATRIX_USER_IDENTIFIER_REGEX = "@[A-Z0-9\\x21-\\x39\\x3B-\\x7F]+$DOMAIN_REGEX"
|
private const val MATRIX_USER_IDENTIFIER_REGEX = "@[A-Z0-9\\x21-\\x39\\x3B-\\x7F]+$DOMAIN_REGEX"
|
||||||
private val PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER = MATRIX_USER_IDENTIFIER_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
val PATTERN_CONTAIN_MATRIX_USER_IDENTIFIER = MATRIX_USER_IDENTIFIER_REGEX.toRegex(RegexOption.IGNORE_CASE)
|
||||||
|
|
||||||
// regex pattern to find room ids in a string.
|
// regex pattern to find room ids in a string.
|
||||||
private const val MATRIX_ROOM_IDENTIFIER_REGEX = "![A-Z0-9]+$DOMAIN_REGEX"
|
private const val MATRIX_ROOM_IDENTIFIER_REGEX = "![A-Z0-9]+$DOMAIN_REGEX"
|
||||||
@ -123,9 +122,9 @@ object MatrixPatterns {
|
|||||||
*/
|
*/
|
||||||
fun isEventId(str: String?): Boolean {
|
fun isEventId(str: String?): Boolean {
|
||||||
return str != null
|
return str != null
|
||||||
&& (str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER
|
&& (str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER
|
||||||
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3
|
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3
|
||||||
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4)
|
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,4 +136,22 @@ object MatrixPatterns {
|
|||||||
fun isGroupId(str: String?): Boolean {
|
fun isGroupId(str: String?): Boolean {
|
||||||
return str != null && str matches PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER
|
return str != null && str matches PATTERN_CONTAIN_MATRIX_GROUP_IDENTIFIER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract server name from a matrix id
|
||||||
|
*
|
||||||
|
* @param matrixId
|
||||||
|
* @return null if not found or if matrixId is null
|
||||||
|
*/
|
||||||
|
fun extractServerNameFromId(matrixId: String?): String? {
|
||||||
|
if (matrixId == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val index = matrixId.indexOf(":")
|
||||||
|
|
||||||
|
return if (index == -1) {
|
||||||
|
null
|
||||||
|
} else matrixId.substring(index + 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,16 +17,23 @@
|
|||||||
package im.vector.matrix.android.api.auth
|
package im.vector.matrix.android.api.auth
|
||||||
|
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
import im.vector.matrix.android.api.auth.data.Credentials
|
||||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
import im.vector.matrix.android.api.session.Session
|
import im.vector.matrix.android.api.session.Session
|
||||||
import im.vector.matrix.android.api.util.Cancelable
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to authenticate to a matrix server.
|
* This interface defines methods to authenticate to a matrix server.
|
||||||
*/
|
*/
|
||||||
interface Authenticator {
|
interface Authenticator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the supported login flows for this homeserver
|
||||||
|
*/
|
||||||
|
fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResponse>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param homeServerConnectionConfig this param is used to configure the Homeserver
|
* @param homeServerConnectionConfig this param is used to configure the Homeserver
|
||||||
* @param login the login field
|
* @param login the login field
|
||||||
@ -56,4 +63,9 @@ interface Authenticator {
|
|||||||
* @return the associated session if any, or null
|
* @return the associated session if any, or null
|
||||||
*/
|
*/
|
||||||
fun getSession(sessionParams: SessionParams): Session?
|
fun getSession(sessionParams: SessionParams): Session?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a session after a SSO successful login
|
||||||
|
*/
|
||||||
|
fun createSessionFromSso(credentials: Credentials, homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<Session>): Cancelable
|
||||||
}
|
}
|
@ -31,7 +31,7 @@ import okhttp3.TlsVersion
|
|||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class HomeServerConnectionConfig(
|
data class HomeServerConnectionConfig(
|
||||||
val homeServerUri: Uri,
|
val homeServerUri: Uri,
|
||||||
val identityServerUri: Uri,
|
val identityServerUri: Uri? = null,
|
||||||
val antiVirusServerUri: Uri? = null,
|
val antiVirusServerUri: Uri? = null,
|
||||||
val allowedFingerprints: MutableList<Fingerprint> = ArrayList(),
|
val allowedFingerprints: MutableList<Fingerprint> = ArrayList(),
|
||||||
val shouldPin: Boolean = false,
|
val shouldPin: Boolean = false,
|
||||||
@ -48,7 +48,7 @@ data class HomeServerConnectionConfig(
|
|||||||
class Builder {
|
class Builder {
|
||||||
|
|
||||||
private lateinit var homeServerUri: Uri
|
private lateinit var homeServerUri: Uri
|
||||||
private lateinit var identityServerUri: Uri
|
private var identityServerUri: Uri? = null
|
||||||
private var antiVirusServerUri: Uri? = null
|
private var antiVirusServerUri: Uri? = null
|
||||||
private val allowedFingerprints: MutableList<Fingerprint> = ArrayList()
|
private val allowedFingerprints: MutableList<Fingerprint> = ArrayList()
|
||||||
private var shouldPin: Boolean = false
|
private var shouldPin: Boolean = false
|
||||||
@ -253,13 +253,5 @@ data class HomeServerConnectionConfig(
|
|||||||
forceUsageTlsVersions
|
forceUsageTlsVersions
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
package im.vector.matrix.android.api.comparators
|
package im.vector.matrix.android.api.comparators
|
||||||
|
|
||||||
import im.vector.matrix.android.api.interfaces.DatedObject
|
import im.vector.matrix.android.api.interfaces.DatedObject
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
object DatedObjectComparators {
|
object DatedObjectComparators {
|
||||||
|
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.crypto
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.crypto.sas.EmojiRepresentation
|
||||||
|
import im.vector.matrix.android.internal.crypto.verification.getEmojiForCode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide all the emojis used for SAS verification (for debug purpose)
|
||||||
|
*/
|
||||||
|
fun getAllVerificationEmojis(): List<EmojiRepresentation> {
|
||||||
|
return (0..63).map { getEmojiForCode(it) }
|
||||||
|
}
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.api.extensions
|
|||||||
import im.vector.matrix.android.api.comparators.DatedObjectComparators
|
import im.vector.matrix.android.api.comparators.DatedObjectComparators
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/* ==========================================================================================
|
/* ==========================================================================================
|
||||||
* MXDeviceInfo
|
* MXDeviceInfo
|
||||||
@ -29,7 +28,6 @@ fun MXDeviceInfo.getFingerprintHumanReadable() = fingerprint()
|
|||||||
?.chunked(4)
|
?.chunked(4)
|
||||||
?.joinToString(separator = " ")
|
?.joinToString(separator = " ")
|
||||||
|
|
||||||
|
fun MutableList<DeviceInfo>.sortByLastSeen() {
|
||||||
fun List<DeviceInfo>.sortByLastSeen() {
|
sortWith(DatedObjectComparators.descComparator)
|
||||||
Collections.sort(this, DatedObjectComparators.descComparator)
|
|
||||||
}
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.failure
|
||||||
|
|
||||||
|
// This data class will be sent to the bus
|
||||||
|
data class ConsentNotGivenError(
|
||||||
|
val consentUri: String
|
||||||
|
)
|
@ -31,6 +31,7 @@ import java.io.IOException
|
|||||||
*/
|
*/
|
||||||
sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
|
sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
|
||||||
data class Unknown(val throwable: Throwable? = null) : Failure(throwable)
|
data class Unknown(val throwable: Throwable? = null) : Failure(throwable)
|
||||||
|
data class Cancelled(val throwable: Throwable? = null) : Failure(throwable)
|
||||||
data class NetworkConnection(val ioException: IOException? = null) : Failure(ioException)
|
data class NetworkConnection(val ioException: IOException? = null) : Failure(ioException)
|
||||||
data class ServerError(val error: MatrixError, val httpCode: Int) : Failure(RuntimeException(error.toString()))
|
data class ServerError(val error: MatrixError, val httpCode: Int) : Failure(RuntimeException(error.toString()))
|
||||||
// When server send an error, but it cannot be interpreted as a MatrixError
|
// When server send an error, but it cannot be interpreted as a MatrixError
|
||||||
@ -41,5 +42,4 @@ sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
|
|||||||
data class CryptoError(val error: MXCryptoError) : Failure(error)
|
data class CryptoError(val error: MXCryptoError) : Failure(error)
|
||||||
|
|
||||||
abstract class FeatureFailure : Failure()
|
abstract class FeatureFailure : Failure()
|
||||||
|
|
||||||
}
|
}
|
@ -26,8 +26,12 @@ import com.squareup.moshi.JsonClass
|
|||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class MatrixError(
|
data class MatrixError(
|
||||||
@Json(name = "errcode") val code: String,
|
@Json(name = "errcode") val code: String,
|
||||||
@Json(name = "error") val message: String
|
@Json(name = "error") val message: String,
|
||||||
) {
|
|
||||||
|
@Json(name = "consent_uri") val consentUri: String? = null,
|
||||||
|
// RESOURCE_LIMIT_EXCEEDED data
|
||||||
|
@Json(name = "limit_type") val limitType: String? = null,
|
||||||
|
@Json(name = "admin_contact") val adminUri: String? = null) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val FORBIDDEN = "M_FORBIDDEN"
|
const val FORBIDDEN = "M_FORBIDDEN"
|
||||||
@ -55,5 +59,8 @@ data class MatrixError(
|
|||||||
const val M_CONSENT_NOT_GIVEN = "M_CONSENT_NOT_GIVEN"
|
const val M_CONSENT_NOT_GIVEN = "M_CONSENT_NOT_GIVEN"
|
||||||
const val RESOURCE_LIMIT_EXCEEDED = "M_RESOURCE_LIMIT_EXCEEDED"
|
const val RESOURCE_LIMIT_EXCEEDED = "M_RESOURCE_LIMIT_EXCEEDED"
|
||||||
const val WRONG_ROOM_KEYS_VERSION = "M_WRONG_ROOM_KEYS_VERSION"
|
const val WRONG_ROOM_KEYS_VERSION = "M_WRONG_ROOM_KEYS_VERSION"
|
||||||
|
|
||||||
|
// Possible value for "limit_type"
|
||||||
|
const val LIMIT_TYPE_MAU = "monthly_active_user"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,9 +30,9 @@ object MatrixLinkify {
|
|||||||
*
|
*
|
||||||
* @param spannable the text in which the matrix items has to be clickable.
|
* @param spannable the text in which the matrix items has to be clickable.
|
||||||
*/
|
*/
|
||||||
fun addLinks(spannable: Spannable?, callback: MatrixPermalinkSpan.Callback?): Boolean {
|
fun addLinks(spannable: Spannable, callback: MatrixPermalinkSpan.Callback?): Boolean {
|
||||||
// sanity checks
|
// sanity checks
|
||||||
if (spannable.isNullOrEmpty()) {
|
if (spannable.isEmpty()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val text = spannable.toString()
|
val text = spannable.toString()
|
||||||
@ -42,7 +42,7 @@ object MatrixLinkify {
|
|||||||
hasMatch = true
|
hasMatch = true
|
||||||
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
|
val endPos = match.range.last + 1
|
||||||
val url = text.substring(match.range)
|
val url = text.substring(match.range)
|
||||||
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)
|
||||||
@ -51,5 +51,4 @@ object MatrixLinkify {
|
|||||||
}
|
}
|
||||||
return hasMatch
|
return hasMatch
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -18,6 +18,7 @@ package im.vector.matrix.android.api.permalinks
|
|||||||
|
|
||||||
import android.text.style.ClickableSpan
|
import android.text.style.ClickableSpan
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan.Callback
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This MatrixPermalinkSpan is a clickable span which use a [Callback] to communicate back.
|
* This MatrixPermalinkSpan is a clickable span which use a [Callback] to communicate back.
|
||||||
@ -34,6 +35,4 @@ class MatrixPermalinkSpan(private val url: String,
|
|||||||
override fun onClick(widget: View) {
|
override fun onClick(widget: View) {
|
||||||
callback?.onUrlClicked(url)
|
callback?.onUrlClicked(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -33,5 +33,4 @@ sealed class PermalinkData {
|
|||||||
data class GroupLink(val groupId: String) : PermalinkData()
|
data class GroupLink(val groupId: String) : PermalinkData()
|
||||||
|
|
||||||
data class FallbackLink(val uri: Uri) : PermalinkData()
|
data class FallbackLink(val uri: Uri) : PermalinkData()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.api.permalinks
|
package im.vector.matrix.android.api.permalinks
|
||||||
|
|
||||||
import android.text.TextUtils
|
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -48,10 +47,9 @@ object PermalinkFactory {
|
|||||||
* @return the permalink, or null in case of error
|
* @return the permalink, or null in case of error
|
||||||
*/
|
*/
|
||||||
fun createPermalink(id: String): String? {
|
fun createPermalink(id: String): String? {
|
||||||
return if (TextUtils.isEmpty(id)) {
|
return if (id.isEmpty()) {
|
||||||
null
|
null
|
||||||
} else MATRIX_TO_URL_BASE + escape(id)
|
} else MATRIX_TO_URL_BASE + escape(id)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,16 +70,14 @@ object PermalinkFactory {
|
|||||||
* @param url the universal link, Ex: "https://matrix.to/#/@benoit:matrix.org"
|
* @param url the universal link, Ex: "https://matrix.to/#/@benoit:matrix.org"
|
||||||
* @return the id from the url, ex: "@benoit:matrix.org", or null if the url is not a permalink
|
* @return the id from the url, ex: "@benoit:matrix.org", or null if the url is not a permalink
|
||||||
*/
|
*/
|
||||||
fun getLinkedId(url: String?): String? {
|
fun getLinkedId(url: String): String? {
|
||||||
val isSupported = url != null && url.startsWith(MATRIX_TO_URL_BASE)
|
val isSupported = url.startsWith(MATRIX_TO_URL_BASE)
|
||||||
|
|
||||||
return if (isSupported) {
|
return if (isSupported) {
|
||||||
url!!.substring(MATRIX_TO_URL_BASE.length)
|
url.substring(MATRIX_TO_URL_BASE.length)
|
||||||
} else null
|
} else null
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Escape '/' in id, because it is used as a separator
|
* Escape '/' in id, because it is used as a separator
|
||||||
*
|
*
|
||||||
@ -89,6 +85,6 @@ object PermalinkFactory {
|
|||||||
* @return the escaped id
|
* @return the escaped id
|
||||||
*/
|
*/
|
||||||
private fun escape(id: String): String {
|
private fun escape(id: String): String {
|
||||||
return id.replace("/".toRegex(), "%2F")
|
return id.replace("/", "%2F")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,5 +72,4 @@ object PermalinkParser {
|
|||||||
else -> PermalinkData.FallbackLink(uri)
|
else -> PermalinkData.FallbackLink(uri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -18,78 +18,111 @@ package im.vector.matrix.android.api.pushrules
|
|||||||
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
|
sealed class Action {
|
||||||
|
object Notify : Action()
|
||||||
|
object DoNotNotify : Action()
|
||||||
|
data class Sound(val sound: String = ACTION_OBJECT_VALUE_VALUE_DEFAULT) : Action()
|
||||||
|
data class Highlight(val highlight: Boolean) : Action()
|
||||||
|
}
|
||||||
|
|
||||||
class Action(val type: Type) {
|
private const val ACTION_NOTIFY = "notify"
|
||||||
|
private const val ACTION_DONT_NOTIFY = "dont_notify"
|
||||||
|
private const val ACTION_COALESCE = "coalesce"
|
||||||
|
|
||||||
enum class Type(val value: String) {
|
// Ref: https://matrix.org/docs/spec/client_server/latest#tweaks
|
||||||
NOTIFY("notify"),
|
private const val ACTION_OBJECT_SET_TWEAK_KEY = "set_tweak"
|
||||||
DONT_NOTIFY("dont_notify"),
|
|
||||||
COALESCE("coalesce"),
|
|
||||||
SET_TWEAK("set_tweak");
|
|
||||||
|
|
||||||
companion object {
|
private const val ACTION_OBJECT_SET_TWEAK_VALUE_SOUND = "sound"
|
||||||
|
private const val ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT = "highlight"
|
||||||
|
|
||||||
fun safeValueOf(value: String): Type? {
|
private const val ACTION_OBJECT_VALUE_KEY = "value"
|
||||||
try {
|
private const val ACTION_OBJECT_VALUE_VALUE_DEFAULT = "default"
|
||||||
return valueOf(value)
|
|
||||||
} catch (e: IllegalArgumentException) {
|
/**
|
||||||
return null
|
* Ref: https://matrix.org/docs/spec/client_server/latest#actions
|
||||||
}
|
*
|
||||||
|
* Convert
|
||||||
|
* <pre>
|
||||||
|
* "actions": [
|
||||||
|
* "notify",
|
||||||
|
* {
|
||||||
|
* "set_tweak": "sound",
|
||||||
|
* "value": "default"
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* "set_tweak": "highlight"
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* To
|
||||||
|
* [
|
||||||
|
* Action.Notify,
|
||||||
|
* Action.Sound("default"),
|
||||||
|
* Action.Highlight(true)
|
||||||
|
* ]
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Suppress("IMPLICIT_CAST_TO_ANY")
|
||||||
|
fun List<Action>.toJson(): List<Any> {
|
||||||
|
return map { action ->
|
||||||
|
when (action) {
|
||||||
|
is Action.Notify -> ACTION_NOTIFY
|
||||||
|
is Action.DoNotNotify -> ACTION_DONT_NOTIFY
|
||||||
|
is Action.Sound -> {
|
||||||
|
mapOf(
|
||||||
|
ACTION_OBJECT_SET_TWEAK_KEY to ACTION_OBJECT_SET_TWEAK_VALUE_SOUND,
|
||||||
|
ACTION_OBJECT_VALUE_KEY to action.sound
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
is Action.Highlight -> {
|
||||||
}
|
mapOf(
|
||||||
|
ACTION_OBJECT_SET_TWEAK_KEY to ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT,
|
||||||
var tweak_action: String? = null
|
ACTION_OBJECT_VALUE_KEY to action.highlight
|
||||||
var stringValue: String? = null
|
)
|
||||||
var boolValue: Boolean? = null
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun mapFrom(pushRule: PushRule): List<Action>? {
|
|
||||||
val actions = ArrayList<Action>()
|
|
||||||
pushRule.actions.forEach { actionStrOrObj ->
|
|
||||||
if (actionStrOrObj is String) {
|
|
||||||
when (actionStrOrObj) {
|
|
||||||
Action.Type.NOTIFY.value -> Action(Action.Type.NOTIFY)
|
|
||||||
Action.Type.DONT_NOTIFY.value -> Action(Action.Type.DONT_NOTIFY)
|
|
||||||
else -> {
|
|
||||||
Timber.w("Unsupported action type ${actionStrOrObj}")
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}?.let {
|
|
||||||
actions.add(it)
|
|
||||||
}
|
|
||||||
} else if (actionStrOrObj is Map<*, *>) {
|
|
||||||
val tweakAction = actionStrOrObj["set_tweak"] as? String
|
|
||||||
when (tweakAction) {
|
|
||||||
"sound" -> {
|
|
||||||
(actionStrOrObj["value"] as? String)?.let { stringValue ->
|
|
||||||
Action(Action.Type.SET_TWEAK).also {
|
|
||||||
it.tweak_action = "sound"
|
|
||||||
it.stringValue = stringValue
|
|
||||||
actions.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"highlight" -> {
|
|
||||||
(actionStrOrObj["value"] as? Boolean)?.let { boolValue ->
|
|
||||||
Action(Action.Type.SET_TWEAK).also {
|
|
||||||
it.tweak_action = "highlight"
|
|
||||||
it.boolValue = boolValue
|
|
||||||
actions.add(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Timber.w("Unsupported action type ${actionStrOrObj}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Timber.w("Unsupported action type ${actionStrOrObj}")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return if (actions.isEmpty()) null else actions
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun PushRule.getActions(): List<Action> {
|
||||||
|
val result = ArrayList<Action>()
|
||||||
|
|
||||||
|
actions.forEach { actionStrOrObj ->
|
||||||
|
when (actionStrOrObj) {
|
||||||
|
ACTION_NOTIFY -> Action.Notify
|
||||||
|
ACTION_DONT_NOTIFY -> Action.DoNotNotify
|
||||||
|
is Map<*, *> -> {
|
||||||
|
when (actionStrOrObj[ACTION_OBJECT_SET_TWEAK_KEY]) {
|
||||||
|
ACTION_OBJECT_SET_TWEAK_VALUE_SOUND -> {
|
||||||
|
(actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? String)?.let { stringValue ->
|
||||||
|
Action.Sound(stringValue)
|
||||||
|
}
|
||||||
|
// When the value is not there, default sound (not specified by the spec)
|
||||||
|
?: Action.Sound(ACTION_OBJECT_VALUE_VALUE_DEFAULT)
|
||||||
|
}
|
||||||
|
ACTION_OBJECT_SET_TWEAK_VALUE_HIGHLIGHT -> {
|
||||||
|
(actionStrOrObj[ACTION_OBJECT_VALUE_KEY] as? Boolean)?.let { boolValue ->
|
||||||
|
Action.Highlight(boolValue)
|
||||||
|
}
|
||||||
|
// When the value is not there, default is true, says the spec
|
||||||
|
?: Action.Highlight(true)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Timber.w("Unsupported set_tweak value ${actionStrOrObj[ACTION_OBJECT_SET_TWEAK_KEY]}")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Timber.w("Unsupported action type $actionStrOrObj")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}?.let {
|
||||||
|
result.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
@ -35,9 +35,7 @@ abstract class Condition(val kind: Kind) {
|
|||||||
else -> UNRECOGNIZE
|
else -> UNRECOGNIZE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun isSatisfied(conditionResolver: ConditionResolver): Boolean
|
abstract fun isSatisfied(conditionResolver: ConditionResolver): Boolean
|
||||||
|
@ -15,13 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.api.pushrules
|
package im.vector.matrix.android.api.pushrules
|
||||||
|
|
||||||
import android.text.TextUtils
|
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import im.vector.matrix.android.api.session.events.model.toModel
|
import im.vector.matrix.android.api.session.events.model.toModel
|
||||||
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
|
class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
|
||||||
|
|
||||||
@ -34,11 +32,11 @@ class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun isSatisfied(event: Event, displayName: String): Boolean {
|
fun isSatisfied(event: Event, displayName: String): Boolean {
|
||||||
var message = when (event.type) {
|
val message = when (event.type) {
|
||||||
EventType.MESSAGE -> {
|
EventType.MESSAGE -> {
|
||||||
event.content.toModel<MessageContent>()
|
event.content.toModel<MessageContent>()
|
||||||
}
|
}
|
||||||
//TODO the spec says:
|
// TODO the spec says:
|
||||||
// Matches any message whose content is unencrypted and contains the user's current display name
|
// Matches any message whose content is unencrypted and contains the user's current display name
|
||||||
// EventType.ENCRYPTED -> {
|
// EventType.ENCRYPTED -> {
|
||||||
// event.root.getClearContent()?.toModel<MessageContent>()
|
// event.root.getClearContent()?.toModel<MessageContent>()
|
||||||
@ -49,7 +47,6 @@ class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
|
|||||||
return caseInsensitiveFind(displayName, message.body)
|
return caseInsensitiveFind(displayName, message.body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
/**
|
/**
|
||||||
* Returns whether a string contains an occurrence of another, as a standalone word, regardless of case.
|
* Returns whether a string contains an occurrence of another, as a standalone word, regardless of case.
|
||||||
@ -60,20 +57,18 @@ class ContainsDisplayNameCondition : Condition(Kind.contains_display_name) {
|
|||||||
*/
|
*/
|
||||||
fun caseInsensitiveFind(subString: String, longString: String): Boolean {
|
fun caseInsensitiveFind(subString: String, longString: String): Boolean {
|
||||||
// add sanity checks
|
// add sanity checks
|
||||||
if (TextUtils.isEmpty(subString) || TextUtils.isEmpty(longString)) {
|
if (subString.isEmpty() || longString.isEmpty()) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var res = false
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val pattern = Pattern.compile("(\\W|^)" + Pattern.quote(subString) + "(\\W|$)", Pattern.CASE_INSENSITIVE)
|
val regex = Regex("(\\W|^)" + Regex.escape(subString) + "(\\W|$)", RegexOption.IGNORE_CASE)
|
||||||
res = pattern.matcher(longString).find()
|
return regex.containsMatchIn(longString)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Timber.e(e, "## caseInsensitiveFind() : failed")
|
Timber.e(e, "## caseInsensitiveFind() : failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
return res
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -29,28 +29,25 @@ class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind
|
|||||||
return "'$key' Matches '$pattern'"
|
return "'$key' Matches '$pattern'"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun isSatisfied(event: Event): Boolean {
|
fun isSatisfied(event: Event): Boolean {
|
||||||
//TODO encrypted events?
|
// TODO encrypted events?
|
||||||
val rawJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJsonValue(event) as? Map<*, *>
|
val rawJson = MoshiProvider.providesMoshi().adapter(Event::class.java).toJsonValue(event) as? Map<*, *>
|
||||||
?: return false
|
?: return false
|
||||||
val value = extractField(rawJson, key) ?: return false
|
val value = extractField(rawJson, key) ?: return false
|
||||||
|
|
||||||
//Patterns with no special glob characters should be treated as having asterisks prepended
|
// Patterns with no special glob characters should be treated as having asterisks prepended
|
||||||
// and appended when testing the condition.
|
// and appended when testing the condition.
|
||||||
try {
|
try {
|
||||||
val modPattern = if (hasSpecialGlobChar(pattern)) simpleGlobToRegExp(pattern) else simpleGlobToRegExp("*$pattern*")
|
val modPattern = if (hasSpecialGlobChar(pattern)) simpleGlobToRegExp(pattern) else simpleGlobToRegExp("*$pattern*")
|
||||||
val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL)
|
val regex = Regex(modPattern, RegexOption.DOT_MATCHES_ALL)
|
||||||
return regex.containsMatchIn(value)
|
return regex.containsMatchIn(value)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
//e.g PatternSyntaxException
|
// e.g PatternSyntaxException
|
||||||
Timber.e(e, "Failed to evaluate push condition")
|
Timber.e(e, "Failed to evaluate push condition")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun extractField(jsonObject: Map<*, *>, fieldPath: String): String? {
|
private fun extractField(jsonObject: Map<*, *>, fieldPath: String): String? {
|
||||||
val fieldParts = fieldPath.split(".")
|
val fieldParts = fieldPath.split(".")
|
||||||
if (fieldParts.isEmpty()) return null
|
if (fieldParts.isEmpty()) return null
|
||||||
@ -77,9 +74,9 @@ class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind
|
|||||||
return glob.contains("*") || glob.contains("?")
|
return glob.contains("*") || glob.contains("?")
|
||||||
}
|
}
|
||||||
|
|
||||||
//Very simple glob to regexp converter
|
// Very simple glob to regexp converter
|
||||||
private fun simpleGlobToRegExp(glob: String): String {
|
private fun simpleGlobToRegExp(glob: String): String {
|
||||||
var out = ""//"^"
|
var out = "" // "^"
|
||||||
for (i in 0 until glob.length) {
|
for (i in 0 until glob.length) {
|
||||||
val c = glob[i]
|
val c = glob[i]
|
||||||
when (c) {
|
when (c) {
|
||||||
@ -90,7 +87,7 @@ class EventMatchCondition(val key: String, val pattern: String) : Condition(Kind
|
|||||||
else -> out += c
|
else -> out += c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out += ""//'$'.toString()
|
out += "" // '$'.toString()
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,20 +18,25 @@ package im.vector.matrix.android.api.pushrules
|
|||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
import im.vector.matrix.android.api.pushrules.rest.PushRule
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
|
||||||
interface PushRuleService {
|
interface PushRuleService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch the push rules from the server
|
* Fetch the push rules from the server
|
||||||
*/
|
*/
|
||||||
fun fetchPushRules(scope: String = "global")
|
fun fetchPushRules(scope: String = RuleScope.GLOBAL)
|
||||||
|
|
||||||
//TODO get push rule set
|
// TODO get push rule set
|
||||||
fun getPushRules(scope: String = "global"): List<PushRule>
|
fun getPushRules(scope: String = RuleScope.GLOBAL): List<PushRule>
|
||||||
|
|
||||||
//TODO update rule
|
// TODO update rule
|
||||||
|
|
||||||
fun updatePushRuleEnableStatus(kind: String, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>)
|
fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
|
fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
|
fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
fun addPushRuleListener(listener: PushRuleListener)
|
fun addPushRuleListener(listener: PushRuleListener)
|
||||||
|
|
||||||
@ -41,6 +46,9 @@ interface PushRuleService {
|
|||||||
|
|
||||||
interface PushRuleListener {
|
interface PushRuleListener {
|
||||||
fun onMatchRule(event: Event, actions: List<Action>)
|
fun onMatchRule(event: Event, actions: List<Action>)
|
||||||
|
fun onRoomJoined(roomId: String)
|
||||||
|
fun onRoomLeft(roomId: String)
|
||||||
|
fun onEventRedacted(redactedEventId: String)
|
||||||
fun batchFinish()
|
fun batchFinish()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -18,18 +18,17 @@ package im.vector.matrix.android.api.pushrules
|
|||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
private val regex = Pattern.compile("^(==|<=|>=|<|>)?(\\d*)$")
|
private val regex = Regex("^(==|<=|>=|<|>)?(\\d*)$")
|
||||||
|
|
||||||
class RoomMemberCountCondition(val `is`: String) : Condition(Kind.room_member_count) {
|
class RoomMemberCountCondition(val iz: String) : Condition(Kind.room_member_count) {
|
||||||
|
|
||||||
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
|
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
|
||||||
return conditionResolver.resolveRoomMemberCountCondition(this)
|
return conditionResolver.resolveRoomMemberCountCondition(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun technicalDescription(): String {
|
override fun technicalDescription(): String {
|
||||||
return "Room member count is $`is`"
|
return "Room member count is $iz"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isSatisfied(event: Event, session: RoomService?): Boolean {
|
fun isSatisfied(event: Event, session: RoomService?): Boolean {
|
||||||
@ -56,16 +55,12 @@ class RoomMemberCountCondition(val `is`: String) : Condition(Kind.room_member_co
|
|||||||
*/
|
*/
|
||||||
private fun parseIsField(): Pair<String?, Int>? {
|
private fun parseIsField(): Pair<String?, Int>? {
|
||||||
try {
|
try {
|
||||||
val match = regex.matcher(`is`)
|
val match = regex.find(iz) ?: return null
|
||||||
if (match.find()) {
|
val (prefix, count) = match.destructured
|
||||||
val prefix = match.group(1)
|
return prefix to count.toInt()
|
||||||
val count = match.group(2).toInt()
|
|
||||||
return prefix to count
|
|
||||||
}
|
|
||||||
} catch (t: Throwable) {
|
} catch (t: Throwable) {
|
||||||
Timber.d(t)
|
Timber.d(t)
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,7 +37,7 @@ object RuleIds {
|
|||||||
|
|
||||||
// Default Underride Rules
|
// Default Underride Rules
|
||||||
const val RULE_ID_CALL = ".m.rule.call"
|
const val RULE_ID_CALL = ".m.rule.call"
|
||||||
const val RULE_ID_one_to_one_encrypted_room = ".m.rule.encrypted_room_one_to_one"
|
const val RULE_ID_ONE_TO_ONE_ENCRYPTED_ROOM = ".m.rule.encrypted_room_one_to_one"
|
||||||
const val RULE_ID_ONE_TO_ONE_ROOM = ".m.rule.room_one_to_one"
|
const val RULE_ID_ONE_TO_ONE_ROOM = ".m.rule.room_one_to_one"
|
||||||
const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message"
|
const val RULE_ID_ALL_OTHER_MESSAGES_ROOMS = ".m.rule.message"
|
||||||
const val RULE_ID_ENCRYPTED = ".m.rule.encrypted"
|
const val RULE_ID_ENCRYPTED = ".m.rule.encrypted"
|
||||||
|
@ -13,9 +13,8 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
package im.vector.matrix.android.api.pushrules
|
||||||
|
|
||||||
package im.vector.riotx.features.home.room
|
object RuleScope {
|
||||||
|
const val GLOBAL = "global"
|
||||||
import im.vector.riotx.core.utils.RxStore
|
}
|
||||||
|
|
||||||
class VisibleRoomStore : RxStore<String>()
|
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.pushrules
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules
|
||||||
|
*/
|
||||||
|
enum class RuleSetKey(val value: String) {
|
||||||
|
CONTENT("content"),
|
||||||
|
OVERRIDE("override"),
|
||||||
|
ROOM("room"),
|
||||||
|
SENDER("sender"),
|
||||||
|
UNDERRIDE("underride")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ref: https://matrix.org/docs/spec/client_server/latest#get-matrix-client-r0-pushrules-scope-kind-ruleid
|
||||||
|
*/
|
||||||
|
typealias RuleKind = RuleSetKey
|
@ -18,7 +18,6 @@ package im.vector.matrix.android.api.pushrules
|
|||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.room.model.PowerLevels
|
import im.vector.matrix.android.api.session.room.model.PowerLevels
|
||||||
|
|
||||||
|
|
||||||
class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) {
|
class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.sender_notification_permission) {
|
||||||
|
|
||||||
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
|
override fun isSatisfied(conditionResolver: ConditionResolver): Boolean {
|
||||||
@ -29,7 +28,6 @@ class SenderNotificationPermissionCondition(val key: String) : Condition(Kind.se
|
|||||||
return "User power level <$key>"
|
return "User power level <$key>"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun isSatisfied(event: Event, powerLevels: PowerLevels): Boolean {
|
fun isSatisfied(event: Event, powerLevels: PowerLevels): Boolean {
|
||||||
return event.senderId != null && powerLevels.getUserPowerLevel(event.senderId) >= powerLevels.notificationLevel(key)
|
return event.senderId != null && powerLevels.getUserPowerLevel(event.senderId) >= powerLevels.notificationLevel(key)
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ data class PushCondition(
|
|||||||
this.key?.let { SenderNotificationPermissionCondition(it) }
|
this.key?.let { SenderNotificationPermissionCondition(it) }
|
||||||
}
|
}
|
||||||
Condition.Kind.UNRECOGNIZE -> {
|
Condition.Kind.UNRECOGNIZE -> {
|
||||||
Timber.e("Unknwon kind $kind")
|
Timber.e("Unknown kind $kind")
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.api.pushrules.rest
|
|||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class PushRule(
|
data class PushRule(
|
||||||
/**
|
/**
|
||||||
@ -47,4 +46,3 @@ data class PushRule(
|
|||||||
*/
|
*/
|
||||||
val pattern: String? = null
|
val pattern: String? = null
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,10 +20,10 @@ import androidx.lifecycle.LiveData
|
|||||||
|
|
||||||
interface InitialSyncProgressService {
|
interface InitialSyncProgressService {
|
||||||
|
|
||||||
fun getLiveStatus() : LiveData<Status?>
|
fun getInitialSyncProgressStatus() : LiveData<Status?>
|
||||||
|
|
||||||
data class Status(
|
data class Status(
|
||||||
@StringRes val statusText: Int?,
|
@StringRes val statusText: Int,
|
||||||
val percentProgress: Int = 0
|
val percentProgress: Int = 0
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -19,6 +19,7 @@ package im.vector.matrix.android.api.session
|
|||||||
import androidx.annotation.MainThread
|
import androidx.annotation.MainThread
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.auth.data.SessionParams
|
import im.vector.matrix.android.api.auth.data.SessionParams
|
||||||
|
import im.vector.matrix.android.api.failure.ConsentNotGivenError
|
||||||
import im.vector.matrix.android.api.pushrules.PushRuleService
|
import im.vector.matrix.android.api.pushrules.PushRuleService
|
||||||
import im.vector.matrix.android.api.session.cache.CacheService
|
import im.vector.matrix.android.api.session.cache.CacheService
|
||||||
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
|
||||||
@ -26,9 +27,11 @@ import im.vector.matrix.android.api.session.content.ContentUrlResolver
|
|||||||
import im.vector.matrix.android.api.session.crypto.CryptoService
|
import im.vector.matrix.android.api.session.crypto.CryptoService
|
||||||
import im.vector.matrix.android.api.session.file.FileService
|
import im.vector.matrix.android.api.session.file.FileService
|
||||||
import im.vector.matrix.android.api.session.group.GroupService
|
import im.vector.matrix.android.api.session.group.GroupService
|
||||||
|
import im.vector.matrix.android.api.session.homeserver.HomeServerCapabilitiesService
|
||||||
import im.vector.matrix.android.api.session.pushers.PushersService
|
import im.vector.matrix.android.api.session.pushers.PushersService
|
||||||
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
import im.vector.matrix.android.api.session.room.RoomDirectoryService
|
||||||
import im.vector.matrix.android.api.session.room.RoomService
|
import im.vector.matrix.android.api.session.room.RoomService
|
||||||
|
import im.vector.matrix.android.api.session.securestorage.SecureStorageService
|
||||||
import im.vector.matrix.android.api.session.signout.SignOutService
|
import im.vector.matrix.android.api.session.signout.SignOutService
|
||||||
import im.vector.matrix.android.api.session.sync.FilterService
|
import im.vector.matrix.android.api.session.sync.FilterService
|
||||||
import im.vector.matrix.android.api.session.sync.SyncState
|
import im.vector.matrix.android.api.session.sync.SyncState
|
||||||
@ -50,17 +53,21 @@ interface Session :
|
|||||||
FileService,
|
FileService,
|
||||||
PushRuleService,
|
PushRuleService,
|
||||||
PushersService,
|
PushersService,
|
||||||
InitialSyncProgressService {
|
InitialSyncProgressService,
|
||||||
|
HomeServerCapabilitiesService,
|
||||||
|
SecureStorageService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The params associated to the session
|
* The params associated to the session
|
||||||
*/
|
*/
|
||||||
val sessionParams: SessionParams
|
val sessionParams: SessionParams
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useful shortcut to get access to the userId
|
||||||
|
*/
|
||||||
val myUserId: String
|
val myUserId: String
|
||||||
get() = sessionParams.credentials.userId
|
get() = sessionParams.credentials.userId
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method allow to open a session. It does start some service on the background.
|
* This method allow to open a session. It does start some service on the background.
|
||||||
*/
|
*/
|
||||||
@ -84,7 +91,7 @@ interface Session :
|
|||||||
/**
|
/**
|
||||||
* This method start the sync thread.
|
* This method start the sync thread.
|
||||||
*/
|
*/
|
||||||
fun startSync()
|
fun startSync(fromForeground: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method stop the sync thread.
|
* This method stop the sync thread.
|
||||||
@ -133,6 +140,9 @@ interface Session :
|
|||||||
*/
|
*/
|
||||||
fun onInvalidToken()
|
fun onInvalidToken()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A M_CONSENT_NOT_GIVEN error has been received from the homeserver
|
||||||
|
*/
|
||||||
|
fun onConsentNotGivenError(consentNotGivenError: ConsentNotGivenError)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -19,7 +19,7 @@ package im.vector.matrix.android.api.session.cache
|
|||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines a method to sign out. It's implemented at the session level.
|
* This interface defines a method to clear the cache. It's implemented at the session level.
|
||||||
*/
|
*/
|
||||||
interface CacheService {
|
interface CacheService {
|
||||||
|
|
||||||
@ -27,5 +27,4 @@ interface CacheService {
|
|||||||
* Clear the whole cached data, except credentials. Once done, the session is closed and has to be opened again
|
* Clear the whole cached data, except credentials. Once done, the session is closed and has to be opened again
|
||||||
*/
|
*/
|
||||||
fun clearCache(callback: MatrixCallback<Unit>)
|
fun clearCache(callback: MatrixCallback<Unit>)
|
||||||
|
|
||||||
}
|
}
|
@ -17,6 +17,7 @@
|
|||||||
package im.vector.matrix.android.api.session.content
|
package im.vector.matrix.android.api.session.content
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import kotlinx.android.parcel.Parcelize
|
import kotlinx.android.parcel.Parcelize
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@ -26,6 +27,7 @@ data class ContentAttachmentData(
|
|||||||
val date: Long = 0,
|
val date: Long = 0,
|
||||||
val height: Long? = 0,
|
val height: Long? = 0,
|
||||||
val width: Long? = 0,
|
val width: Long? = 0,
|
||||||
|
val exifOrientation: Int = ExifInterface.ORIENTATION_UNDEFINED,
|
||||||
val name: String? = null,
|
val name: String? = null,
|
||||||
val path: String,
|
val path: String,
|
||||||
val mimeType: String,
|
val mimeType: String,
|
||||||
@ -38,5 +40,4 @@ data class ContentAttachmentData(
|
|||||||
AUDIO,
|
AUDIO,
|
||||||
VIDEO
|
VIDEO
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -26,14 +26,12 @@ import im.vector.matrix.android.api.session.events.model.Content
|
|||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
import im.vector.matrix.android.internal.crypto.MXEventDecryptionResult
|
||||||
import im.vector.matrix.android.internal.crypto.NewSessionListener
|
import im.vector.matrix.android.internal.crypto.NewSessionListener
|
||||||
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
|
||||||
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
import im.vector.matrix.android.internal.crypto.model.ImportRoomKeysResult
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
import im.vector.matrix.android.internal.crypto.model.MXEncryptEventContentResult
|
||||||
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
import im.vector.matrix.android.internal.crypto.model.rest.DevicesListResponse
|
||||||
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
import im.vector.matrix.android.internal.crypto.model.rest.RoomKeyRequestBody
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
interface CryptoService {
|
interface CryptoService {
|
||||||
|
|
||||||
@ -111,10 +109,7 @@ interface CryptoService {
|
|||||||
|
|
||||||
fun downloadKeys(userIds: List<String>, forceDownload: Boolean, callback: MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>>)
|
fun downloadKeys(userIds: List<String>, forceDownload: Boolean, callback: MatrixCallback<MXUsersDevicesMap<MXDeviceInfo>>)
|
||||||
|
|
||||||
fun clearCryptoCache(callback: MatrixCallback<Unit>)
|
|
||||||
|
|
||||||
fun addNewSessionListener(newSessionListener: NewSessionListener)
|
fun addNewSessionListener(newSessionListener: NewSessionListener)
|
||||||
|
|
||||||
fun removeSessionListener(listener: NewSessionListener)
|
fun removeSessionListener(listener: NewSessionListener)
|
||||||
|
|
||||||
}
|
}
|
@ -210,5 +210,4 @@ interface KeysBackupService {
|
|||||||
val isEnabled: Boolean
|
val isEnabled: Boolean
|
||||||
val isStucked: Boolean
|
val isStucked: Boolean
|
||||||
val state: KeysBackupState
|
val state: KeysBackupState
|
||||||
|
|
||||||
}
|
}
|
@ -43,7 +43,7 @@ enum class SasVerificationTxState {
|
|||||||
Verifying,
|
Verifying,
|
||||||
Verified,
|
Verified,
|
||||||
|
|
||||||
//Global: The verification has been cancelled (by me or other), see cancelReason for details
|
// Global: The verification has been cancelled (by me or other), see cancelReason for details
|
||||||
Cancelled,
|
Cancelled,
|
||||||
OnCancelled
|
OnCancelled
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ import com.squareup.moshi.JsonClass
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@JsonClass(generateAdapter = true)
|
@JsonClass(generateAdapter = true)
|
||||||
data class AggregatedAnnotation (
|
data class AggregatedAnnotation(
|
||||||
override val limited: Boolean? = false,
|
override val limited: Boolean? = false,
|
||||||
override val count: Int? = 0,
|
override val count: Int? = 0,
|
||||||
val chunk: List<RelationChunkInfo>? = null
|
val chunk: List<RelationChunkInfo>? = null
|
||||||
|
@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.api.session.events.model
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
import android.text.TextUtils
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
import im.vector.matrix.android.api.session.crypto.MXCryptoError
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageContent
|
||||||
|
import im.vector.matrix.android.api.session.room.model.message.MessageType
|
||||||
|
import im.vector.matrix.android.api.session.room.send.SendState
|
||||||
import im.vector.matrix.android.api.util.JsonDict
|
import im.vector.matrix.android.api.util.JsonDict
|
||||||
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
import im.vector.matrix.android.internal.crypto.algorithms.olm.OlmDecryptionResult
|
||||||
import im.vector.matrix.android.internal.di.MoshiProvider
|
import im.vector.matrix.android.internal.di.MoshiProvider
|
||||||
@ -32,18 +34,16 @@ typealias Content = JsonDict
|
|||||||
* This methods is a facility method to map a json content to a model.
|
* This methods is a facility method to map a json content to a model.
|
||||||
*/
|
*/
|
||||||
inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? {
|
inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? {
|
||||||
return this?.let {
|
val moshi = MoshiProvider.providesMoshi()
|
||||||
val moshi = MoshiProvider.providesMoshi()
|
val moshiAdapter = moshi.adapter(T::class.java)
|
||||||
val moshiAdapter = moshi.adapter(T::class.java)
|
return try {
|
||||||
return try {
|
moshiAdapter.fromJsonValue(this)
|
||||||
moshiAdapter.fromJsonValue(it)
|
} catch (e: Exception) {
|
||||||
} catch (e: Exception) {
|
if (catchError) {
|
||||||
if (catchError) {
|
Timber.e(e, "To model failed : $e")
|
||||||
Timber.e(e, "To model failed : $e")
|
null
|
||||||
null
|
} else {
|
||||||
} else {
|
throw e
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,12 +52,10 @@ inline fun <reified T> Content?.toModel(catchError: Boolean = true): T? {
|
|||||||
* This methods is a facility method to map a model to a json Content
|
* This methods is a facility method to map a model to a json Content
|
||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
inline fun <reified T> T?.toContent(): Content? {
|
inline fun <reified T> T.toContent(): Content {
|
||||||
return this?.let {
|
val moshi = MoshiProvider.providesMoshi()
|
||||||
val moshi = MoshiProvider.providesMoshi()
|
val moshiAdapter = moshi.adapter(T::class.java)
|
||||||
val moshiAdapter = moshi.adapter(T::class.java)
|
return moshiAdapter.toJsonValue(this) as Content
|
||||||
return moshiAdapter.toJsonValue(it) as Content
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,10 +76,14 @@ data class Event(
|
|||||||
@Json(name = "redacts") val redacts: String? = null
|
@Json(name = "redacts") val redacts: String? = null
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@Transient
|
||||||
var mxDecryptionResult: OlmDecryptionResult? = null
|
var mxDecryptionResult: OlmDecryptionResult? = null
|
||||||
|
|
||||||
|
@Transient
|
||||||
var mCryptoError: MXCryptoError.ErrorType? = null
|
var mCryptoError: MXCryptoError.ErrorType? = null
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
var sendState: SendState = SendState.UNKNOWN
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if event is a state event.
|
* Check if event is a state event.
|
||||||
@ -91,98 +93,22 @@ data class Event(
|
|||||||
return EventType.isStateEvent(getClearType())
|
return EventType.isStateEvent(getClearType())
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================================================
|
// ==============================================================================================================
|
||||||
// Crypto
|
// Crypto
|
||||||
//==============================================================================================================
|
// ==============================================================================================================
|
||||||
|
|
||||||
// /**
|
|
||||||
// * For encrypted events, the plaintext payload for the event.
|
|
||||||
// * This is a small MXEvent instance with typically value for `type` and 'content' fields.
|
|
||||||
// */
|
|
||||||
// @Transient
|
|
||||||
// var mClearEvent: Event? = null
|
|
||||||
// private set
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Curve25519 key which we believe belongs to the sender of the event.
|
|
||||||
// * See `senderKey` property.
|
|
||||||
// */
|
|
||||||
// @Transient
|
|
||||||
// private var mSenderCurve25519Key: String? = null
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Ed25519 key which the sender of this event (for olm) or the creator of the megolm session (for megolm) claims to own.
|
|
||||||
// * See `claimedEd25519Key` property.
|
|
||||||
// */
|
|
||||||
// @Transient
|
|
||||||
// private var mClaimedEd25519Key: String? = null
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Curve25519 keys of devices involved in telling us about the senderCurve25519Key and claimedEd25519Key.
|
|
||||||
// * See `forwardingCurve25519KeyChain` property.
|
|
||||||
// */
|
|
||||||
// @Transient
|
|
||||||
// private var mForwardingCurve25519KeyChain: List<String> = ArrayList()
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Decryption error
|
|
||||||
// */
|
|
||||||
// @Transient
|
|
||||||
// var mCryptoError: MXCryptoError? = null
|
|
||||||
// private set
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if this event is encrypted.
|
* @return true if this event is encrypted.
|
||||||
*/
|
*/
|
||||||
fun isEncrypted(): Boolean {
|
fun isEncrypted(): Boolean {
|
||||||
return TextUtils.equals(type, EventType.ENCRYPTED)
|
return type == EventType.ENCRYPTED
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the clear data on this event.
|
|
||||||
* This is used after decrypting an event; it should not be used by applications.
|
|
||||||
*
|
|
||||||
* @param decryptionResult the decryption result, including the plaintext and some key info.
|
|
||||||
*/
|
|
||||||
// internal fun setClearData(decryptionResult: MXEventDecryptionResult?) {
|
|
||||||
// mClearEvent = null
|
|
||||||
// if (decryptionResult != null) {
|
|
||||||
// if (decryptionResult.clearEvent != null) {
|
|
||||||
// val adapter = MoshiProvider.providesMoshi().adapter(Event::class.java)
|
|
||||||
// mClearEvent = adapter.fromJsonValue(decryptionResult.clearEvent)
|
|
||||||
//
|
|
||||||
// if (mClearEvent != null) {
|
|
||||||
// mSenderCurve25519Key = decryptionResult.senderCurve25519Key
|
|
||||||
// mClaimedEd25519Key = decryptionResult.claimedEd25519Key
|
|
||||||
// mForwardingCurve25519KeyChain = decryptionResult.forwardingCurve25519KeyChain
|
|
||||||
//
|
|
||||||
// // For encrypted events with relation, the m.relates_to is kept in clear, so we need to put it back
|
|
||||||
// // in the clear event
|
|
||||||
// try {
|
|
||||||
// content?.get("m.relates_to")?.let { clearRelates ->
|
|
||||||
// mClearEvent = mClearEvent?.copy(
|
|
||||||
// content = HashMap(mClearEvent!!.content).apply {
|
|
||||||
// this["m.relates_to"] = clearRelates
|
|
||||||
// }
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// } catch (e: Exception) {
|
|
||||||
// Timber.e(e, "Unable to restore 'm.relates_to' the clear event")
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// mCryptoError = null
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The curve25519 key that sent this event.
|
* @return The curve25519 key that sent this event.
|
||||||
*/
|
*/
|
||||||
fun getSenderKey(): String? {
|
fun getSenderKey(): String? {
|
||||||
return mxDecryptionResult?.senderKey
|
return mxDecryptionResult?.senderKey
|
||||||
// return mClearEvent?.mSenderCurve25519Key ?: mSenderCurve25519Key
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -190,56 +116,25 @@ data class Event(
|
|||||||
*/
|
*/
|
||||||
fun getKeysClaimed(): Map<String, String> {
|
fun getKeysClaimed(): Map<String, String> {
|
||||||
return mxDecryptionResult?.keysClaimed ?: HashMap()
|
return mxDecryptionResult?.keysClaimed ?: HashMap()
|
||||||
// val res = HashMap<String, String>()
|
|
||||||
//
|
|
||||||
// val claimedEd25519Key = if (null != mClearEvent) mClearEvent!!.mClaimedEd25519Key else mClaimedEd25519Key
|
|
||||||
//
|
|
||||||
// if (null != claimedEd25519Key) {
|
|
||||||
// res["ed25519"] = claimedEd25519Key
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return res
|
|
||||||
}
|
}
|
||||||
//
|
|
||||||
/**
|
/**
|
||||||
* @return the event type
|
* @return the event type
|
||||||
*/
|
*/
|
||||||
fun getClearType(): String {
|
fun getClearType(): String {
|
||||||
return mxDecryptionResult?.payload?.get("type")?.toString()
|
return mxDecryptionResult?.payload?.get("type")?.toString() ?: type
|
||||||
?: type//get("type")?.toString() ?: type
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the event content
|
* @return the event content
|
||||||
*/
|
*/
|
||||||
fun getClearContent(): Content? {
|
fun getClearContent(): Content? {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
return mxDecryptionResult?.payload?.get("content") as? Content ?: content
|
return mxDecryptionResult?.payload?.get("content") as? Content ?: content
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * @return the linked crypto error
|
|
||||||
// */
|
|
||||||
// fun getCryptoError(): MXCryptoError? {
|
|
||||||
// return mCryptoError
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * Update the linked crypto error
|
|
||||||
// *
|
|
||||||
// * @param error the new crypto error.
|
|
||||||
// */
|
|
||||||
// fun setCryptoError(error: MXCryptoError?) {
|
|
||||||
// mCryptoError = error
|
|
||||||
// if (null != error) {
|
|
||||||
// mClearEvent = null
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
fun toContentStringWithIndent(): String {
|
fun toContentStringWithIndent(): String {
|
||||||
val contentMap = this.toContent()?.toMutableMap() ?: HashMap()
|
val contentMap = toContent().toMutableMap()
|
||||||
contentMap.remove("mxDecryptionResult")
|
|
||||||
contentMap.remove("mCryptoError")
|
|
||||||
return JSONObject(contentMap).toString(4)
|
return JSONObject(contentMap).toString(4)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,6 +167,7 @@ data class Event(
|
|||||||
if (redacts != other.redacts) return false
|
if (redacts != other.redacts) return false
|
||||||
if (mxDecryptionResult != other.mxDecryptionResult) return false
|
if (mxDecryptionResult != other.mxDecryptionResult) return false
|
||||||
if (mCryptoError != other.mCryptoError) return false
|
if (mCryptoError != other.mCryptoError) return false
|
||||||
|
if (sendState != other.sendState) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -289,6 +185,25 @@ data class Event(
|
|||||||
result = 31 * result + (redacts?.hashCode() ?: 0)
|
result = 31 * result + (redacts?.hashCode() ?: 0)
|
||||||
result = 31 * result + (mxDecryptionResult?.hashCode() ?: 0)
|
result = 31 * result + (mxDecryptionResult?.hashCode() ?: 0)
|
||||||
result = 31 * result + (mCryptoError?.hashCode() ?: 0)
|
result = 31 * result + (mCryptoError?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + sendState.hashCode()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Event.isTextMessage(): Boolean {
|
||||||
|
return getClearType() == EventType.MESSAGE
|
||||||
|
&& when (getClearContent()?.toModel<MessageContent>()?.type) {
|
||||||
|
MessageType.MSGTYPE_TEXT,
|
||||||
|
MessageType.MSGTYPE_EMOTE,
|
||||||
|
MessageType.MSGTYPE_NOTICE -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Event.isImageMessage(): Boolean {
|
||||||
|
return getClearType() == EventType.MESSAGE
|
||||||
|
&& when (getClearContent()?.toModel<MessageContent>()?.type) {
|
||||||
|
MessageType.MSGTYPE_IMAGE -> true
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.api.session.events.model
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants defining known event types from Matrix specifications.
|
* Constants defining known event types from Matrix specifications.
|
||||||
*/
|
*/
|
||||||
@ -93,7 +92,6 @@ object EventType {
|
|||||||
STATE_PINNED_EVENT
|
STATE_PINNED_EVENT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
fun isStateEvent(type: String): Boolean {
|
fun isStateEvent(type: String): Boolean {
|
||||||
return STATE_EVENTS.contains(type)
|
return STATE_EVENTS.contains(type)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
object LocalEcho {
|
||||||
|
|
||||||
|
private const val PREFIX = "local."
|
||||||
|
|
||||||
|
fun isLocalEchoId(eventId: String) = eventId.startsWith(PREFIX)
|
||||||
|
|
||||||
|
fun createLocalEchoId() = "${PREFIX}${UUID.randomUUID()}"
|
||||||
|
}
|
@ -15,9 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.api.session.events.model
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants defining known event relation types from Matrix specifications.
|
* Constants defining known event relation types from Matrix specifications
|
||||||
*/
|
*/
|
||||||
object RelationType {
|
object RelationType {
|
||||||
|
|
||||||
@ -25,7 +24,6 @@ object RelationType {
|
|||||||
const val ANNOTATION = "m.annotation"
|
const val ANNOTATION = "m.annotation"
|
||||||
/** Lets you define an event which replaces an existing event.*/
|
/** Lets you define an event which replaces an existing event.*/
|
||||||
const val REPLACE = "m.replace"
|
const val REPLACE = "m.replace"
|
||||||
/** ets you define an event which references an existing event.*/
|
/** Lets you define an event which references an existing event.*/
|
||||||
const val REFERENCE = "m.reference"
|
const val REFERENCE = "m.reference"
|
||||||
|
|
||||||
}
|
}
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.api.session.events.model
|
package im.vector.matrix.android.api.session.events.model
|
||||||
|
|
||||||
|
|
||||||
interface UnsignedRelationInfo {
|
interface UnsignedRelationInfo {
|
||||||
val limited : Boolean?
|
val limited : Boolean?
|
||||||
val count: Int?
|
val count: Int?
|
||||||
|
@ -20,7 +20,6 @@ import im.vector.matrix.android.api.MatrixCallback
|
|||||||
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to get files.
|
* This interface defines methods to get files.
|
||||||
*/
|
*/
|
||||||
|
@ -19,7 +19,6 @@ package im.vector.matrix.android.api.session.group
|
|||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
import im.vector.matrix.android.api.session.group.model.GroupSummary
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to get groups. It's implemented at the session level.
|
* This interface defines methods to get groups. It's implemented at the session level.
|
||||||
*/
|
*/
|
||||||
|
@ -16,12 +16,15 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.api.session.group.model
|
package im.vector.matrix.android.api.session.group.model
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.room.model.Membership
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds some data of a group.
|
* This class holds some data of a group.
|
||||||
* It can be retrieved through [im.vector.matrix.android.api.session.group.GroupService]
|
* It can be retrieved through [im.vector.matrix.android.api.session.group.GroupService]
|
||||||
*/
|
*/
|
||||||
data class GroupSummary(
|
data class GroupSummary(
|
||||||
val groupId: String,
|
val groupId: String,
|
||||||
|
val membership: Membership,
|
||||||
val displayName: String = "",
|
val displayName: String = "",
|
||||||
val shortDescription: String = "",
|
val shortDescription: String = "",
|
||||||
val avatarUrl: String = "",
|
val avatarUrl: String = "",
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.session.homeserver
|
||||||
|
|
||||||
|
data class HomeServerCapabilities(
|
||||||
|
/**
|
||||||
|
* Max size of file which can be uploaded to the homeserver in bytes. [MAX_UPLOAD_FILE_SIZE_UNKNOWN] if unknown or not retrieved yet
|
||||||
|
*/
|
||||||
|
val maxUploadFileSize: Long = MAX_UPLOAD_FILE_SIZE_UNKNOWN
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
const val MAX_UPLOAD_FILE_SIZE_UNKNOWN = -1L
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.session.homeserver
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface defines a method to retrieve the homeserver capabilities.
|
||||||
|
*/
|
||||||
|
interface HomeServerCapabilitiesService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the HomeServer capabilities
|
||||||
|
*/
|
||||||
|
fun getHomeServerCapabilities(): HomeServerCapabilities
|
||||||
|
}
|
@ -16,9 +16,6 @@
|
|||||||
package im.vector.matrix.android.api.session.pushers
|
package im.vector.matrix.android.api.session.pushers
|
||||||
|
|
||||||
data class Pusher(
|
data class Pusher(
|
||||||
|
|
||||||
val userId: String,
|
|
||||||
|
|
||||||
val pushKey: String,
|
val pushKey: String,
|
||||||
val kind: String,
|
val kind: String,
|
||||||
val appId: String,
|
val appId: String,
|
||||||
|
@ -17,8 +17,7 @@ package im.vector.matrix.android.api.session.pushers
|
|||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import java.util.*
|
import java.util.UUID
|
||||||
|
|
||||||
|
|
||||||
interface PushersService {
|
interface PushersService {
|
||||||
|
|
||||||
@ -53,7 +52,6 @@ interface PushersService {
|
|||||||
append: Boolean,
|
append: Boolean,
|
||||||
withEventIdOnly: Boolean): UUID
|
withEventIdOnly: Boolean): UUID
|
||||||
|
|
||||||
|
|
||||||
fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>)
|
fun removeHttpPusher(pushkey: String, appId: String, callback: MatrixCallback<Unit>)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -21,10 +21,14 @@ import im.vector.matrix.android.api.session.room.crypto.RoomCryptoService
|
|||||||
import im.vector.matrix.android.api.session.room.members.MembershipService
|
import im.vector.matrix.android.api.session.room.members.MembershipService
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.relation.RelationService
|
import im.vector.matrix.android.api.session.room.model.relation.RelationService
|
||||||
|
import im.vector.matrix.android.api.session.room.notification.RoomPushRuleService
|
||||||
|
import im.vector.matrix.android.api.session.room.reporting.ReportingService
|
||||||
import im.vector.matrix.android.api.session.room.read.ReadService
|
import im.vector.matrix.android.api.session.room.read.ReadService
|
||||||
|
import im.vector.matrix.android.api.session.room.send.DraftService
|
||||||
import im.vector.matrix.android.api.session.room.send.SendService
|
import im.vector.matrix.android.api.session.room.send.SendService
|
||||||
import im.vector.matrix.android.api.session.room.state.StateService
|
import im.vector.matrix.android.api.session.room.state.StateService
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineService
|
import im.vector.matrix.android.api.session.room.timeline.TimelineService
|
||||||
|
import im.vector.matrix.android.api.util.Optional
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines methods to interact within a room.
|
* This interface defines methods to interact within a room.
|
||||||
@ -32,11 +36,14 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineService
|
|||||||
interface Room :
|
interface Room :
|
||||||
TimelineService,
|
TimelineService,
|
||||||
SendService,
|
SendService,
|
||||||
|
DraftService,
|
||||||
ReadService,
|
ReadService,
|
||||||
MembershipService,
|
MembershipService,
|
||||||
StateService,
|
StateService,
|
||||||
|
ReportingService,
|
||||||
RelationService,
|
RelationService,
|
||||||
RoomCryptoService {
|
RoomCryptoService,
|
||||||
|
RoomPushRuleService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The roomId of this room
|
* The roomId of this room
|
||||||
@ -47,8 +54,7 @@ interface Room :
|
|||||||
* A live [RoomSummary] associated with the room
|
* A live [RoomSummary] associated with the room
|
||||||
* You can observe this summary to get dynamic data from this room.
|
* You can observe this summary to get dynamic data from this room.
|
||||||
*/
|
*/
|
||||||
fun liveRoomSummary(): LiveData<RoomSummary>
|
fun getRoomSummaryLive(): LiveData<Optional<RoomSummary>>
|
||||||
|
|
||||||
fun roomSummary(): RoomSummary?
|
fun roomSummary(): RoomSummary?
|
||||||
|
|
||||||
}
|
}
|
@ -30,20 +30,16 @@ interface RoomDirectoryService {
|
|||||||
/**
|
/**
|
||||||
* Get rooms from directory
|
* Get rooms from directory
|
||||||
*/
|
*/
|
||||||
fun getPublicRooms(server: String?,
|
fun getPublicRooms(server: String?, publicRoomsParams: PublicRoomsParams, callback: MatrixCallback<PublicRoomsResponse>): Cancelable
|
||||||
publicRoomsParams: PublicRoomsParams,
|
|
||||||
callback: MatrixCallback<PublicRoomsResponse>): Cancelable
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join a room by id
|
* Join a room by id
|
||||||
*/
|
*/
|
||||||
fun joinRoom(roomId: String,
|
fun joinRoom(roomId: String, callback: MatrixCallback<Unit>): Cancelable
|
||||||
callback: MatrixCallback<Unit>)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the overall metadata about protocols supported by the homeserver.
|
* Fetches the overall metadata about protocols supported by the homeserver.
|
||||||
* 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>>)
|
fun getThirdPartyProtocol(callback: MatrixCallback<Map<String, ThirdPartyProtocol>>): Cancelable
|
||||||
|
|
||||||
}
|
}
|
@ -20,6 +20,7 @@ import androidx.lifecycle.LiveData
|
|||||||
import im.vector.matrix.android.api.MatrixCallback
|
import im.vector.matrix.android.api.MatrixCallback
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||||
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
||||||
|
import im.vector.matrix.android.api.util.Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@ -27,10 +28,18 @@ import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
|
|||||||
interface RoomService {
|
interface RoomService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a room
|
* Create a room asynchronously
|
||||||
*/
|
*/
|
||||||
fun createRoom(createRoomParams: CreateRoomParams,
|
fun createRoom(createRoomParams: CreateRoomParams, callback: MatrixCallback<String>): Cancelable
|
||||||
callback: MatrixCallback<String>)
|
|
||||||
|
/**
|
||||||
|
* Join a room by id
|
||||||
|
* @param roomId the roomId of the room to join
|
||||||
|
* @param viaServers the servers to attempt to join the room through. One of the servers must be participating in the room.
|
||||||
|
*/
|
||||||
|
fun joinRoom(roomId: String,
|
||||||
|
viaServers: List<String> = emptyList(),
|
||||||
|
callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a room from a roomId
|
* Get a room from a roomId
|
||||||
@ -45,4 +54,8 @@ interface RoomService {
|
|||||||
*/
|
*/
|
||||||
fun liveRoomSummaries(): LiveData<List<RoomSummary>>
|
fun liveRoomSummaries(): LiveData<List<RoomSummary>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark all rooms as read
|
||||||
|
*/
|
||||||
|
fun markAllAsRead(roomIds: List<String>, callback: MatrixCallback<Unit>): Cancelable
|
||||||
}
|
}
|
@ -14,13 +14,11 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package im.vector.riotx.core.dialogs
|
package im.vector.matrix.android.api.session.room.failure
|
||||||
|
|
||||||
import android.content.Context
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
|
|
||||||
internal class DialogSendItemAdapter(context: Context, items: MutableList<DialogListItem>) : DialogAdapter(context) {
|
sealed class CreateRoomFailure : Failure.FeatureFailure() {
|
||||||
|
|
||||||
init {
|
object CreatedWithTimeout: CreateRoomFailure()
|
||||||
addAll(items)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -13,14 +13,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package im.vector.matrix.android.api.pushrules
|
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.session.room.failure
|
||||||
|
|
||||||
enum class RulesetKey(val value: String) {
|
import im.vector.matrix.android.api.failure.Failure
|
||||||
CONTENT("content"),
|
|
||||||
OVERRIDE("override"),
|
sealed class JoinRoomFailure : Failure.FeatureFailure() {
|
||||||
ROOM("room"),
|
|
||||||
SENDER("sender"),
|
object JoinedWithTimeout : JoinRoomFailure()
|
||||||
UNDERRIDE("underride"),
|
|
||||||
UNKNOWN("")
|
|
||||||
}
|
}
|
@ -30,7 +30,7 @@ interface MembershipService {
|
|||||||
* This methods load all room members if it was done yet.
|
* This methods load all room members if it was done yet.
|
||||||
* @return a [Cancelable]
|
* @return a [Cancelable]
|
||||||
*/
|
*/
|
||||||
fun loadRoomMembersIfNeeded(): Cancelable
|
fun loadRoomMembersIfNeeded(matrixCallback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the roomMember with userId or null.
|
* Return the roomMember with userId or null.
|
||||||
@ -52,16 +52,16 @@ interface MembershipService {
|
|||||||
/**
|
/**
|
||||||
* Invite a user in the room
|
* Invite a user in the room
|
||||||
*/
|
*/
|
||||||
fun invite(userId: String, callback: MatrixCallback<Unit>)
|
fun invite(userId: String, callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join the room, or accept an invitation.
|
* Join the room, or accept an invitation.
|
||||||
*/
|
*/
|
||||||
fun join(callback: MatrixCallback<Unit>)
|
|
||||||
|
fun join(viaServers: List<String> = emptyList(), callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Leave the room, or reject an invitation.
|
* Leave the room, or reject an invitation.
|
||||||
*/
|
*/
|
||||||
fun leave(callback: MatrixCallback<Unit>)
|
fun leave(callback: MatrixCallback<Unit>): Cancelable
|
||||||
|
|
||||||
}
|
}
|
@ -43,5 +43,4 @@ enum class Membership(val value: String) {
|
|||||||
fun isLeft(): Boolean {
|
fun isLeft(): Boolean {
|
||||||
return this == KNOCK || this == LEAVE || this == BAN
|
return this == KNOCK || this == LEAVE || this == BAN
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,9 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.api.session.room.model
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import android.text.TextUtils
|
|
||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
|
||||||
@ -45,14 +43,8 @@ data class PowerLevels(
|
|||||||
* @param userId the user id
|
* @param userId the user id
|
||||||
* @return the power level
|
* @return the power level
|
||||||
*/
|
*/
|
||||||
fun getUserPowerLevel(userId: String): Int {
|
fun getUserPowerLevel(userId: String): Int {
|
||||||
// sanity check
|
return users.getOrElse(userId) { usersDefault }
|
||||||
if (!TextUtils.isEmpty(userId)) {
|
|
||||||
val powerLevel = users[userId]
|
|
||||||
return powerLevel ?: usersDefault
|
|
||||||
}
|
|
||||||
|
|
||||||
return usersDefault
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -61,10 +53,8 @@ data class PowerLevels(
|
|||||||
* @param userId the user
|
* @param userId the user
|
||||||
* @param powerLevel the new power level
|
* @param powerLevel the new power level
|
||||||
*/
|
*/
|
||||||
fun setUserPowerLevel(userId: String?, powerLevel: Int) {
|
fun setUserPowerLevel(userId: String, powerLevel: Int) {
|
||||||
if (null != userId) {
|
users[userId] = powerLevel
|
||||||
users[userId] = Integer.valueOf(powerLevel)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,11 +64,10 @@ data class PowerLevels(
|
|||||||
* @param userId the user id
|
* @param userId the user id
|
||||||
* @return true if the user can send the event
|
* @return true if the user can send the event
|
||||||
*/
|
*/
|
||||||
fun maySendEventOfType(eventTypeString: String, userId: String): Boolean {
|
fun maySendEventOfType(eventTypeString: String, userId: String): Boolean {
|
||||||
return if (!TextUtils.isEmpty(eventTypeString) && !TextUtils.isEmpty(userId)) {
|
return if (eventTypeString.isNotEmpty() && userId.isNotEmpty()) {
|
||||||
getUserPowerLevel(userId) >= minimumPowerLevelForSendingEventAsMessage(eventTypeString)
|
getUserPowerLevel(userId) >= minimumPowerLevelForSendingEventAsMessage(eventTypeString)
|
||||||
} else false
|
} else false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,8 +76,8 @@ data class PowerLevels(
|
|||||||
* @param userId the user id
|
* @param userId the user id
|
||||||
* @return true if the user can send a room message
|
* @return true if the user can send a room message
|
||||||
*/
|
*/
|
||||||
fun maySendMessage(userId: String): Boolean {
|
fun maySendMessage(userId: String): Boolean {
|
||||||
return maySendEventOfType(EventType.MESSAGE, userId)
|
return maySendEventOfType(EventType.MESSAGE, userId)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,7 +87,7 @@ data class PowerLevels(
|
|||||||
* @param eventTypeString the type of event (in Event.EVENT_TYPE_XXX values)
|
* @param eventTypeString the type of event (in Event.EVENT_TYPE_XXX values)
|
||||||
* @return the required minimum power level.
|
* @return the required minimum power level.
|
||||||
*/
|
*/
|
||||||
fun minimumPowerLevelForSendingEventAsMessage(eventTypeString: String?): Int {
|
fun minimumPowerLevelForSendingEventAsMessage(eventTypeString: String?): Int {
|
||||||
return events[eventTypeString] ?: eventsDefault
|
return events[eventTypeString] ?: eventsDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,29 +98,24 @@ data class PowerLevels(
|
|||||||
* @param eventTypeString the type of event (in Event.EVENT_TYPE_STATE_ values).
|
* @param eventTypeString the type of event (in Event.EVENT_TYPE_STATE_ values).
|
||||||
* @return the required minimum power level.
|
* @return the required minimum power level.
|
||||||
*/
|
*/
|
||||||
fun minimumPowerLevelForSendingEventAsStateEvent(eventTypeString: String?): Int {
|
fun minimumPowerLevelForSendingEventAsStateEvent(eventTypeString: String?): Int {
|
||||||
return events[eventTypeString] ?: stateDefault
|
return events[eventTypeString] ?: stateDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the notification level for a dedicated key.
|
* Get the notification level for a dedicated key.
|
||||||
*
|
*
|
||||||
* @param key the notification key
|
* @param key the notification key
|
||||||
* @return the level
|
* @return the level
|
||||||
*/
|
*/
|
||||||
fun notificationLevel(key: String?): Int {
|
fun notificationLevel(key: String): Int {
|
||||||
if (null != key && notifications.containsKey(key)) {
|
val valAsVoid = notifications[key] ?: return 50
|
||||||
val valAsVoid = notifications[key]
|
|
||||||
|
|
||||||
// the first implementation was a string value
|
// the first implementation was a string value
|
||||||
return if (valAsVoid is String) {
|
return if (valAsVoid is String) {
|
||||||
Integer.parseInt(valAsVoid)
|
valAsVoid.toInt()
|
||||||
} else {
|
} else {
|
||||||
valAsVoid as Int
|
valAsVoid as Int
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 50
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
package im.vector.matrix.android.api.session.room.model
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
|
import im.vector.matrix.android.api.session.user.model.User
|
||||||
|
|
||||||
data class ReadReceipt(
|
data class ReadReceipt(
|
||||||
val userId: String,
|
val user: User,
|
||||||
val eventId: String,
|
|
||||||
val originServerTs: Long
|
val originServerTs: Long
|
||||||
)
|
)
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum for [RoomJoinRulesContent] : https://matrix.org/docs/spec/client_server/r0.4.0#m-room-join-rules
|
||||||
|
*/
|
||||||
|
enum class RoomJoinRules(val value: String) {
|
||||||
|
|
||||||
|
@Json(name = "public")
|
||||||
|
PUBLIC("public"),
|
||||||
|
|
||||||
|
@Json(name = "invite")
|
||||||
|
INVITE("invite"),
|
||||||
|
|
||||||
|
@Json(name = "knock")
|
||||||
|
KNOCK("knock"),
|
||||||
|
|
||||||
|
@Json(name = "private")
|
||||||
|
PRIVATE("private")
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing the EventType.STATE_ROOM_JOIN_RULES state event content
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class RoomJoinRulesContent(
|
||||||
|
@Json(name = "join_rule") val joinRules: RoomJoinRules? = null
|
||||||
|
)
|
@ -17,6 +17,7 @@
|
|||||||
package im.vector.matrix.android.api.session.room.model
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
import im.vector.matrix.android.api.session.room.model.tag.RoomTag
|
import im.vector.matrix.android.api.session.room.model.tag.RoomTag
|
||||||
|
import im.vector.matrix.android.api.session.room.send.UserDraft
|
||||||
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,10 +30,21 @@ data class RoomSummary(
|
|||||||
val topic: String = "",
|
val topic: String = "",
|
||||||
val avatarUrl: String = "",
|
val avatarUrl: String = "",
|
||||||
val isDirect: Boolean = false,
|
val isDirect: Boolean = false,
|
||||||
val latestEvent: TimelineEvent? = null,
|
val latestPreviewableEvent: TimelineEvent? = null,
|
||||||
val otherMemberIds: List<String> = emptyList(),
|
val otherMemberIds: List<String> = emptyList(),
|
||||||
val notificationCount: Int = 0,
|
val notificationCount: Int = 0,
|
||||||
val highlightCount: Int = 0,
|
val highlightCount: Int = 0,
|
||||||
|
val hasUnreadMessages: Boolean = false,
|
||||||
val tags: List<RoomTag> = emptyList(),
|
val tags: List<RoomTag> = emptyList(),
|
||||||
val membership: Membership = Membership.NONE
|
val membership: Membership = Membership.NONE,
|
||||||
)
|
val versioningState: VersioningState = VersioningState.NONE,
|
||||||
|
val readMarkerId: String? = null,
|
||||||
|
val userDrafts: List<UserDraft> = emptyList()
|
||||||
|
) {
|
||||||
|
|
||||||
|
val isVersioned: Boolean
|
||||||
|
get() = versioningState != VersioningState.NONE
|
||||||
|
|
||||||
|
val hasNewMessages: Boolean
|
||||||
|
get() = notificationCount != 0
|
||||||
|
}
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.session.room.model
|
||||||
|
|
||||||
|
enum class VersioningState {
|
||||||
|
NONE,
|
||||||
|
UPGRADED_ROOM_NOT_JOINED,
|
||||||
|
UPGRADED_ROOM_JOINED
|
||||||
|
}
|
@ -31,5 +31,4 @@ data class CallAnswerContent(
|
|||||||
@Json(name = "type") val type: String,
|
@Json(name = "type") val type: String,
|
||||||
@Json(name = "sdp") val sdp: String
|
@Json(name = "sdp") val sdp: String
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
@ -32,5 +32,4 @@ data class CallCandidatesContent(
|
|||||||
@Json(name = "sdpMLineIndex") val sdpMLineIndex: String,
|
@Json(name = "sdpMLineIndex") val sdpMLineIndex: String,
|
||||||
@Json(name = "candidate") val candidate: String
|
@Json(name = "candidate") val candidate: String
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
@ -37,6 +37,5 @@ data class CallInviteContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun isVideo(): Boolean = offer.sdp.contains(Offer.SDP_VIDEO)
|
fun isVideo(): Boolean = offer.sdp.contains(Offer.SDP_VIDEO)
|
||||||
}
|
}
|
@ -20,7 +20,6 @@ import android.util.Patterns
|
|||||||
import com.squareup.moshi.Json
|
import com.squareup.moshi.Json
|
||||||
import com.squareup.moshi.JsonClass
|
import com.squareup.moshi.JsonClass
|
||||||
import im.vector.matrix.android.api.MatrixPatterns.isUserId
|
import im.vector.matrix.android.api.MatrixPatterns.isUserId
|
||||||
import im.vector.matrix.android.api.auth.data.Credentials
|
|
||||||
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
|
||||||
import im.vector.matrix.android.api.session.events.model.Event
|
import im.vector.matrix.android.api.session.events.model.Event
|
||||||
import im.vector.matrix.android.api.session.events.model.EventType
|
import im.vector.matrix.android.api.session.events.model.EventType
|
||||||
@ -29,7 +28,6 @@ import im.vector.matrix.android.api.session.room.model.PowerLevels
|
|||||||
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomDirectoryVisibility
|
||||||
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
import im.vector.matrix.android.api.session.room.model.RoomHistoryVisibility
|
||||||
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
import im.vector.matrix.android.internal.auth.data.ThreePidMedium
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameter to create a room, with facilities functions to configure it
|
* Parameter to create a room, with facilities functions to configure it
|
||||||
@ -128,12 +126,12 @@ class CreateRoomParams {
|
|||||||
contentMap["algorithm"] = algorithm
|
contentMap["algorithm"] = algorithm
|
||||||
|
|
||||||
val algoEvent = Event(type = EventType.ENCRYPTION,
|
val algoEvent = Event(type = EventType.ENCRYPTION,
|
||||||
stateKey = "",
|
stateKey = "",
|
||||||
content = contentMap.toContent()
|
content = contentMap.toContent()
|
||||||
)
|
)
|
||||||
|
|
||||||
if (null == initialStates) {
|
if (null == initialStates) {
|
||||||
initialStates = Arrays.asList<Event>(algoEvent)
|
initialStates = mutableListOf(algoEvent)
|
||||||
} else {
|
} else {
|
||||||
initialStates!!.add(algoEvent)
|
initialStates!!.add(algoEvent)
|
||||||
}
|
}
|
||||||
@ -147,26 +145,18 @@ class CreateRoomParams {
|
|||||||
*/
|
*/
|
||||||
fun setHistoryVisibility(historyVisibility: RoomHistoryVisibility?) {
|
fun setHistoryVisibility(historyVisibility: RoomHistoryVisibility?) {
|
||||||
// Remove the existing value if any.
|
// Remove the existing value if any.
|
||||||
if (initialStates != null && !initialStates!!.isEmpty()) {
|
initialStates?.removeAll { it.getClearType() == EventType.STATE_HISTORY_VISIBILITY }
|
||||||
val newInitialStates = ArrayList<Event>()
|
|
||||||
for (event in initialStates!!) {
|
|
||||||
if (event.getClearType() != EventType.STATE_HISTORY_VISIBILITY) {
|
|
||||||
newInitialStates.add(event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
initialStates = newInitialStates
|
|
||||||
}
|
|
||||||
|
|
||||||
if (historyVisibility != null) {
|
if (historyVisibility != null) {
|
||||||
val contentMap = HashMap<String, RoomHistoryVisibility>()
|
val contentMap = HashMap<String, RoomHistoryVisibility>()
|
||||||
contentMap["history_visibility"] = historyVisibility
|
contentMap["history_visibility"] = historyVisibility
|
||||||
|
|
||||||
val historyVisibilityEvent = Event(type = EventType.STATE_HISTORY_VISIBILITY,
|
val historyVisibilityEvent = Event(type = EventType.STATE_HISTORY_VISIBILITY,
|
||||||
stateKey = "",
|
stateKey = "",
|
||||||
content = contentMap.toContent())
|
content = contentMap.toContent())
|
||||||
|
|
||||||
if (null == initialStates) {
|
if (null == initialStates) {
|
||||||
initialStates = Arrays.asList<Event>(historyVisibilityEvent)
|
initialStates = mutableListOf(historyVisibilityEvent)
|
||||||
} else {
|
} else {
|
||||||
initialStates!!.add(historyVisibilityEvent)
|
initialStates!!.add(historyVisibilityEvent)
|
||||||
}
|
}
|
||||||
@ -202,8 +192,8 @@ class CreateRoomParams {
|
|||||||
*/
|
*/
|
||||||
fun isDirect(): Boolean {
|
fun isDirect(): Boolean {
|
||||||
return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT
|
return preset == CreateRoomPreset.PRESET_TRUSTED_PRIVATE_CHAT
|
||||||
&& isDirect == true
|
&& isDirect == true
|
||||||
&& (1 == getInviteCount() || 1 == getInvite3PidCount())
|
&& (1 == getInviteCount() || 1 == getInvite3PidCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -220,22 +210,21 @@ class CreateRoomParams {
|
|||||||
* @param ids the participant ids to add.
|
* @param ids the participant ids to add.
|
||||||
*/
|
*/
|
||||||
fun addParticipantIds(hsConfig: HomeServerConnectionConfig,
|
fun addParticipantIds(hsConfig: HomeServerConnectionConfig,
|
||||||
credentials: Credentials,
|
userId: String,
|
||||||
ids: List<String>) {
|
ids: List<String>) {
|
||||||
for (id in ids) {
|
for (id in ids) {
|
||||||
if (Patterns.EMAIL_ADDRESS.matcher(id).matches()) {
|
if (Patterns.EMAIL_ADDRESS.matcher(id).matches() && hsConfig.identityServerUri != null) {
|
||||||
if (null == invite3pids) {
|
if (null == invite3pids) {
|
||||||
invite3pids = ArrayList()
|
invite3pids = ArrayList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val pid = Invite3Pid(idServer = hsConfig.identityServerUri.host!!,
|
val pid = Invite3Pid(idServer = hsConfig.identityServerUri.host!!,
|
||||||
medium = ThreePidMedium.EMAIL,
|
medium = ThreePidMedium.EMAIL,
|
||||||
address = id)
|
address = id)
|
||||||
|
|
||||||
invite3pids!!.add(pid)
|
invite3pids!!.add(pid)
|
||||||
} else if (isUserId(id)) {
|
} else if (isUserId(id)) {
|
||||||
// do not invite oneself
|
// do not invite oneself
|
||||||
if (credentials.userId != id) {
|
if (userId != id) {
|
||||||
if (null == invitedUserIds) {
|
if (null == invitedUserIds) {
|
||||||
invitedUserIds = ArrayList()
|
invitedUserIds = ArrayList()
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package im.vector.matrix.android.api.session.room.model.create
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A link to an old room in case of room versioning
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class Predecessor(
|
||||||
|
@Json(name = "room_id") val roomId: String? = null,
|
||||||
|
@Json(name = "event_id") val eventId: String? = null
|
||||||
|
)
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 New Vector Ltd
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package im.vector.matrix.android.api.session.room.model.create
|
||||||
|
|
||||||
|
import com.squareup.moshi.Json
|
||||||
|
import com.squareup.moshi.JsonClass
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content of a m.room.create type event
|
||||||
|
*/
|
||||||
|
@JsonClass(generateAdapter = true)
|
||||||
|
data class RoomCreateContent(
|
||||||
|
@Json(name = "creator") val creator: String? = null,
|
||||||
|
@Json(name = "room_version") val roomVersion: String? = null,
|
||||||
|
@Json(name = "predecessor") val predecessor: Predecessor? = null
|
||||||
|
)
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user