1
0
mirror of https://github.com/vector-im/riotX-android synced 2025-10-06 00:02:48 +02:00

Compare commits

...

549 Commits

Author SHA1 Message Date
Benoit Marty
c3bdc6127c PushRule: add beforeRuleId and afterRuleId parameter when creating a rule 2020-06-24 18:34:31 +02:00
Benoit Marty
2d6ae3f494 Push rule: even if it was working, use properly the API https://matrix.org/docs/spec/client_server/r0.4.0#put-matrix-client-r0-pushrules-scope-kind-ruleid-enabled 2020-06-24 16:15:00 +02:00
Benoit Marty
920e36a554 Add FIXME 2020-06-24 14:04:39 +02:00
Benoit Marty
a13a39495f Notification: Adjust colors and remove divider between notification settings and leave room action 2020-06-24 14:02:00 +02:00
Benoit Marty
a98bc23691 Notification: Rooms and DMs do not have the same default 2020-06-24 12:25:06 +02:00
Benoit Marty
185c4eb764 Notification: New model and new UI (WIP for push rules) 2020-06-23 23:25:43 +02:00
Benoit Marty
625a1abe84 Bottomsheet: use correct background color from design 2020-06-23 16:02:47 +02:00
Benoit Marty
4e1a827405 Notification: add new icons 2020-06-23 15:55:18 +02:00
Benoit Marty
3f44056243 Merge pull request #1526 from johnjohndoe/retrofit2-call-awaitresponse
Use retrofit2.Call.awaitResponse extension provided by Retrofit 2.
2020-06-23 13:53:27 +02:00
Benoit Marty
d075cbf69b Merge pull request #1530 from vector-im/feature/display_name
Add capability to change the display name (#1529)
2020-06-23 13:52:51 +02:00
Benoit Marty
35fed2676a Cleanup after Onuray's review and improve wording when removing display name 2020-06-23 11:21:00 +02:00
Benoit Marty
9754e26e5f Add capability to change the display name (#1529) 2020-06-22 20:50:31 +02:00
Benoit Marty
af9295723c Merge pull request #1528 from vector-im/feature/tabs_design
Update room category as per design
2020-06-22 17:39:45 +02:00
Valere
55993aff04 Merge pull request #1416 from vector-im/feature/voip
Call support with WebRTC
2020-06-22 17:23:22 +02:00
Tobias Preuss
66c5a35f36 Use retrofit2.Call.awaitResponse extension provided by Retrofit 2.
+ This extension is identical to the one used in this project and is
  available since Retrofit 2.6.0.
  See b761518aa1.
2020-06-22 17:04:37 +02:00
Valere
c1260dcb9b Update room category as per design 2020-06-22 17:01:15 +02:00
Benoit Marty
f4e7405d92 Cleanup 2020-06-22 16:21:36 +02:00
Benoit Marty
c15cc34bfd Call: a11y 2020-06-22 16:15:15 +02:00
Benoit Marty
16f32da647 Cleanup during review. 2020-06-22 16:15:15 +02:00
Valere
4c34d73501 Fix / connection lost timer launched abusively 2020-06-22 15:10:50 +02:00
Benoit Marty
df1bd62f47 Merge pull request #1512 from johnjohndoe/patch-1
Fix minor typo in contribution guide.
2020-06-22 14:12:08 +02:00
Benoit Marty
3ced179fbb Merge branch 'develop' into patch-1 2020-06-22 14:11:50 +02:00
Benoit Marty
957ceff87c Merge pull request #1520 from johnjohndoe/random-housekeeping
Random housekeeping indicated by Lint
2020-06-22 14:11:08 +02:00
Tobias Preuss
85fcc2eab7 Fix minor typo.
+ Fix spelling of "remaining".
2020-06-22 12:25:34 +02:00
Tobias Preuss
e7143b53d5 Fix self-assignment of callback. 2020-06-22 12:08:49 +02:00
Tobias Preuss
b728e10616 Removed unneeded conversion. 2020-06-22 12:08:49 +02:00
Tobias Preuss
8ffa0061e9 Remove unneeded qualifier for constant. 2020-06-22 12:08:49 +02:00
Tobias Preuss
b767c2fa54 Let variable be "val" if possible. 2020-06-22 12:08:49 +02:00
Tobias Preuss
aeb41bc516 Remove redundant "public" qualifier. 2020-06-22 12:08:49 +02:00
Tobias Preuss
178bdff62a Use string template syntax. 2020-06-22 12:08:49 +02:00
Tobias Preuss
3e79da6a79 Infer type. 2020-06-22 12:08:49 +02:00
Valere
ef2fcd60d7 code cleaning 2020-06-22 09:54:45 +02:00
Benoit Marty
55b61775e8 Merge pull request #1514 from 532910/local_resources
put F-Droid and GPlay badges locally
2020-06-22 09:50:54 +02:00
Valere
07e57b1498 clean 2020-06-22 09:48:01 +02:00
Benoit Marty
b522c9f62f Merge pull request #1513 from huoxiaoyao/configure_os_independent
Minor dev setup improvement for Linux/Windows.
2020-06-22 09:47:37 +02:00
Valere
04a7c57d64 Fix / false detection of bt headset + restore state after call 2020-06-22 09:47:34 +02:00
Benoit Marty
367da0c78f Merge pull request #1523 from vector-im/feature/fix_1519
Feature/fix 1519
2020-06-22 09:42:47 +02:00
Benoit Marty
057c21f7d0 Incomplete predicate in RealmCryptoStore#getOutgoingRoomKeyRequest (#1519) 2020-06-22 09:17:37 +02:00
Benoit Marty
af8ab57e60 Rename methods and variables for code clarity 2020-06-22 09:14:59 +02:00
Sergio E. Nemirowski
409b6b807e put F-Droid and GPlay badges locally
this adds images for F-Droid and GPlay buttons for README.md

Signed-off-by: Sergio E. Nemirowski <sergio@outerface.net>
2020-06-20 19:42:31 +03:00
fabianu
4a454f0817 Added ANDROID_STUDIO as optional variable to specify android studio location. 2020-06-20 17:03:10 +02:00
Valere
6b806922ee Fix / prevent camera switch if no second camera 2020-06-20 09:50:32 +02:00
Valere
64a67b57b8 Fix / android 7 unlock screen on incoming call 2020-06-20 09:49:56 +02:00
Valere
76bcf9dcf7 Fix / activeCallPipInitialized not correctly initialized 2020-06-20 09:24:05 +02:00
Valere
9d401512d3 dead code 2020-06-19 19:06:25 +02:00
Valere
464e99505b Update change log 2020-06-19 18:57:50 +02:00
Valere
17cf3fd7ad Active call (with PIP) , in Room and Home 2020-06-19 18:54:39 +02:00
Valere
60998c9146 Missing release of webrtc surfaces 2020-06-19 17:34:05 +02:00
Valere
bd19225219 Add connection loader 2020-06-19 15:20:26 +02:00
Valere
2868d62185 hang up menu action 2020-06-19 15:20:10 +02:00
Valere
2a3d20d300 FIx rebase 2020-06-19 13:42:35 +02:00
Valere
30dee07a3b Hide switch camera for voice call 2020-06-19 13:37:12 +02:00
Valere
96ecb1d07e Fix Crash / stop capture in wrong thread 2020-06-19 13:37:12 +02:00
Valere
99056a7807 Fix / inversed icons HD/SD 2020-06-19 13:37:12 +02:00
Valere
374790176f Toggle HD/SD 2020-06-19 13:37:12 +02:00
Valere
f3e2a55869 Crash Fix / nullify factory after dispose 2020-06-19 13:37:12 +02:00
Valere
666f3ea152 code quality 2020-06-19 13:37:12 +02:00
Valere
25fe56116c Ask for permission before starting call 2020-06-19 13:37:12 +02:00
Valere
b27eead016 Support toggle front/back camera 2020-06-19 13:36:42 +02:00
Valere
77a01f0cd4 lazy create and destroy peer connection factory 2020-06-19 13:36:42 +02:00
Valere
5dfa08ace6 Bluetooth headset support 2020-06-19 13:36:42 +02:00
Valere
4c61dfef62 Support headset buttons in background 2020-06-19 13:36:42 +02:00
Valere
9653f082a3 accept/hangup on press on headset button 2020-06-19 13:36:42 +02:00
Valere
3e2d892fb5 Headset support
+ detect plug/unplugg
2020-06-19 13:36:42 +02:00
Valere
30d47b4fa6 Clear incoming calls managed by other session 2020-06-19 13:36:42 +02:00
Valere
fd3f591541 Show error on connecting timeout + refactoring 2020-06-19 13:36:42 +02:00
Valere
c85ba51274 Basic discard of old call events 2020-06-19 13:36:42 +02:00
Valere
843da1d48d Incoming notification + ringing 2020-06-19 13:36:42 +02:00
Valere
d8cf44fdc9 Simple cache of turn server response
in memory cache in service + show active call banner only if connected
2020-06-19 13:36:42 +02:00
Valere
8662797cf8 Restart capture after close for older android 2020-06-19 13:36:42 +02:00
Valere
eabb0bb41d Restart capture when camera is back to available 2020-06-19 13:36:42 +02:00
Valere
4966bef9c3 Quick signaling doc 2020-06-19 13:36:42 +02:00
Valere
0f625c27a1 Simple menu to select sound device 2020-06-19 13:36:42 +02:00
Valere
248b9ff1e1 Very basic audio speaker support 2020-06-19 13:36:42 +02:00
Valere
39f3a1c697 Fix glitch when opening timeline first time 2020-06-19 13:36:42 +02:00
Valere
c6100fc26c Code cleaning 2020-06-19 13:36:42 +02:00
Valere
84b474d070 klint 2020-06-19 13:36:42 +02:00
Valere
c4b977c6e1 Basic return to call Ux in Room detail 2020-06-19 13:36:42 +02:00
Valere
a1907aaddb Cleaning call states 2020-06-19 13:36:16 +02:00
Valere
56ed56a986 let remote view resize with aspect ratio 2020-06-19 13:36:16 +02:00
Valere
91f28bfb8a basic toggle mute and toggle video 2020-06-19 13:36:16 +02:00
Valere
46d7db8214 klint 2020-06-19 13:36:16 +02:00
Valere
b5cdb44642 Fix rebase 2020-06-19 13:36:16 +02:00
Valere
cb964c6dcd dead code 2020-06-19 13:36:16 +02:00
Valere
e79a4771c1 revert test code 2020-06-19 13:36:16 +02:00
Valere
9006acb66a WIP | Avoid re-negociation pre-agree-upon signaling/negotiation. 2020-06-19 13:36:16 +02:00
onurays
435a6b2f1a Add ice candidates to peer connection. 2020-06-19 13:36:16 +02:00
onurays
4d288ddd55 Require turn server before creating PeerConnection. 2020-06-19 13:36:16 +02:00
onurays
24cea5110e Show / hide call views according to call type. 2020-06-19 13:36:16 +02:00
onurays
79f804b2d4 Use single sdp and stream observer. 2020-06-19 13:36:16 +02:00
onurays
4b85e39e3e Implementation of turn server api. 2020-06-19 13:36:16 +02:00
onurays
8f5918de4d Cleanup unused code. 2020-06-19 13:36:16 +02:00
Benoit Marty
ae762aa928 Cleanup 2020-06-19 13:36:16 +02:00
Benoit Marty
928da82dde Make menu item live 2020-06-19 13:36:16 +02:00
Benoit Marty
94ea857738 Fix icons tint, esp in dark theme 2020-06-19 13:36:03 +02:00
Benoit Marty
0bb92e9e91 Hide m.call.candidates in the timeline by default.
And handle them correctly when all events are displayed
2020-06-19 13:36:03 +02:00
Benoit Marty
df4aab1d73 Use EventType.isCallEvent() 2020-06-19 13:36:03 +02:00
Benoit Marty
d3f93984d4 Compact coding 2020-06-19 13:36:03 +02:00
Benoit Marty
125d61eb68 Rename parameters 2020-06-19 13:36:03 +02:00
onurays
c0988ba6d9 Merge conflicts and implement answer function. 2020-06-19 13:36:03 +02:00
Benoit Marty
03b9904b07 Create a MxCall interface to better handle call 2020-06-19 13:36:03 +02:00
Benoit Marty
24a9931abd Rename some API 2020-06-19 13:36:03 +02:00
Benoit Marty
2581a3433e Create RoomCallService 2020-06-19 13:36:03 +02:00
Benoit Marty
8c9ca1e0f2 Cleanup listener 2020-06-19 13:35:38 +02:00
Benoit Marty
dcae051e85 Create enum as per the spec and use default values when applicable 2020-06-19 13:35:38 +02:00
Benoit Marty
3d03bf6f91 Add Javadoc to the model 2020-06-19 13:35:38 +02:00
onurays
54b154f85f Send sdp to remote party when answer is received. 2020-06-19 13:35:38 +02:00
onurays
37c926d178 Attach local video renderers. 2020-06-19 13:35:38 +02:00
onurays
f50f81d321 Implement rejecting incoming call. 2020-06-19 13:35:38 +02:00
onurays
743ace7e60 Move voip responsibilities from views to WebRtcPeerConnectionManager. 2020-06-19 13:35:38 +02:00
onurays
5d476e7259 Show the foreground service for incoming and outgoing calls. 2020-06-19 13:35:38 +02:00
onurays
fb6bcc8470 Foreground call service and action receiver implemented. 2020-06-19 13:35:38 +02:00
onurays
bda1633979 New material resources added. 2020-06-19 13:35:38 +02:00
onurays
4169f580b8 Create foreground call service. 2020-06-19 13:35:38 +02:00
onurays
4a4edcf82a Experimental implementation of Telecom API. 2020-06-19 13:35:38 +02:00
onurays
a1fc0db8a2 Finish CallActivity when m.call.hangup received. 2020-06-19 13:35:38 +02:00
Valere
dc19652c2b WIP
refact WIP


TMP


WIP
2020-06-19 13:35:38 +02:00
Benoit Marty
d2f1488934 Merge pull request #1500 from vector-im/feature/api_21
Min SDK level set to 21 (#405)
2020-06-19 09:45:22 +02:00
Benoit Marty
bbdf6c6eaf Merge pull request #1496 from vector-im/feature/small_fixies
Small fixies
2020-06-18 14:31:11 +02:00
Benoit Marty
f532d28fb3 Min SDK level set to 21 (#405) 2020-06-18 14:18:40 +02:00
Benoit Marty
af81a52746 Use CustomChromeTab to open T&C 2020-06-17 19:04:35 +02:00
Benoit Marty
86b4c9ac73 "Add Matrix app" menu is now always visible (#1495) 2020-06-17 18:13:09 +02:00
Benoit Marty
1df3b4e18f Fix dark theme issue on login screen (#1097) 2020-06-17 15:52:31 +02:00
Benoit Marty
fa204eca3b Add link to Widget doc 2020-06-17 15:37:35 +02:00
Benoit Marty
2c34fe2dc3 Add airplane mode icon 2020-06-17 15:30:56 +02:00
Benoit Marty
9c34187391 Move "integration" setting above "advanced" section 2020-06-17 15:17:22 +02:00
Benoit Marty
ff39b22686 Add changelog entry for proguard 2020-06-16 11:18:33 +02:00
Benoit Marty
601e11980f Merge pull request #1478 from vector-im/feature/proguard
Feature/proguard
2020-06-16 11:15:21 +02:00
Benoit Marty
914bfb105c Version++ 2020-06-15 23:28:57 +02:00
Benoit Marty
076ecca5a9 Merge branch 'release/0.22.0' into develop 2020-06-15 23:27:48 +02:00
Benoit Marty
840648b750 Prepare release 0.22.0 2020-06-15 23:27:10 +02:00
Benoit Marty
29fd4c4bd2 Fix issue on dark themes, after alert popup dismiss 2020-06-15 23:25:32 +02:00
Benoit Marty
905fa7dd86 Format 2020-06-15 20:05:50 +02:00
Benoit Marty
e8af71f641 Merge pull request #1485 from RiotTranslateBot/weblate-riot-android-riotx-application
Update from Weblate
2020-06-15 20:05:02 +02:00
rkfg
6901d368d2 Translated using Weblate (Russian)
Currently translated at 100.0% (231 of 231 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/ru/
2020-06-15 15:43:04 +00:00
Benoit Marty
e89a340fae Format string resources 2020-06-15 16:47:05 +02:00
Benoit Marty
c3d6135fb3 Fix lint issues 2020-06-15 16:29:10 +02:00
Benoit Marty
6611defd87 Merge pull request #1484 from RiotTranslateBot/weblate-riot-android-riotx-application
Update from Weblate
2020-06-15 16:10:51 +02:00
Weblate
5c449a9e30 michaelk merges translation 2020-06-15 13:24:46 +00:00
LinAGKar
415ac6a748 Translated using Weblate (Swedish)
Currently translated at 41.5% (712 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-06-15 12:55:46 +00:00
Osoitz
7ddafa098f Translated using Weblate (Basque)
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/eu/
2020-06-15 12:55:45 +00:00
Osoitz
177f7b9cb3 Translated using Weblate (Basque)
Currently translated at 100.0% (1717 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/eu/
2020-06-15 12:55:45 +00:00
Benoit Marty
fb1704b717 Merge pull request #1465 from vector-im/bmarty-patch-1
Add command line to run Android test
2020-06-15 14:48:01 +02:00
Benoit Marty
ade1f1b911 Merge pull request #1479 from vector-im/feature/memory_leaks
Feature/memory leaks
2020-06-15 14:47:16 +02:00
Benoit Marty
344a9836d2 Typo and cleanup 2020-06-15 14:44:44 +02:00
Benoit Marty
2c1487d303 Merge pull request #1466 from vector-im/feature/toggle_favorite
Add capability to add and remove a room from the favorites (#1217)
2020-06-15 14:29:48 +02:00
LinAGKar
e1e505e695 Translated using Weblate (Swedish)
Currently translated at 40.8% (701 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-06-14 05:26:12 +00:00
Marko Dimjašević
c5cd68416f Translated using Weblate (Croatian)
Currently translated at 71.6% (1229 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-06-14 05:26:12 +00:00
Slavi Pantaleev
45f757e157 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/bg/
2020-06-14 05:26:12 +00:00
Slavi Pantaleev
de77c8a210 Translated using Weblate (Bulgarian)
Currently translated at 82.8% (1421 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/bg/
2020-06-14 05:26:11 +00:00
ganfra
54b3af2c88 Merge pull request #1459 from vector-im/feature/power_level
Feature/power level
2020-06-12 16:12:37 +02:00
ganfra
171a945de9 Membership: refact a bit and add a left message when kicked or banned 2020-06-12 15:29:07 +02:00
LinAGKar
d845d10d73 Translated using Weblate (Swedish)
Currently translated at 40.7% (699 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-06-12 11:26:16 +00:00
reg4xp
98d91a746e Translated using Weblate (Persian)
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/fa/
2020-06-12 11:26:15 +00:00
reg4xp
1be1b5b263 Translated using Weblate (Persian)
Currently translated at 34.4% (591 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/fa/
2020-06-12 11:26:15 +00:00
Marko Dimjašević
dafb0c8d5c Translated using Weblate (Croatian)
Currently translated at 71.5% (1227 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-06-12 11:26:09 +00:00
ganfra
6ca69a9947 Remove unnecessary comment 2020-06-12 10:02:57 +02:00
ganfra
ff171a39c6 Memory leaks: clean after Benoit's remarks 2020-06-12 09:58:45 +02:00
Benoit Marty
8acee57118 Implement my suggestions 2020-06-11 22:01:04 +02:00
Benoit Marty
d03ab989e6 Hide WidgetBanner by default, it can be visible if phone is slow 2020-06-11 21:42:04 +02:00
Benoit Marty
4f5b1d9646 Close Activity when room is left.
Create a dedicated ViewModel to handle that in Activity rather than multiple times in Fragments
2020-06-11 21:40:22 +02:00
ganfra
f8dca1237a Fix lint issues 2020-06-11 20:20:06 +02:00
ganfra
c382f706a6 Leaks: disable leakcanary 2020-06-11 19:40:46 +02:00
ganfra
23cbed310a Proguard: activate it in release 2020-06-11 19:37:20 +02:00
ganfra
1786ba30f7 Proguard: handle matrix sdk 2020-06-11 19:36:15 +02:00
Benoit Marty
530ce0952c Typo and cleanup 2020-06-11 18:00:34 +02:00
Benoit Marty
262f10af9a Remove ability to kick or ban yourself 2020-06-11 16:59:14 +02:00
Benoit Marty
3430a8f3ea Fix demote yourself issue 2020-06-11 16:48:32 +02:00
Benoit Marty
959be3a23d Fix layout issue on read only rooms 2020-06-11 16:39:41 +02:00
Benoit Marty
15306fc116 Italic text 2020-06-11 16:30:34 +02:00
Benoit Marty
fb5013db88 Restore previous way to managed power level string, to be able to translate them correctly 2020-06-11 16:27:46 +02:00
Benoit Marty
ab4780c9b9 Remove translation of deleted strings 2020-06-11 16:27:46 +02:00
ganfra
e6a71ab7de PowerLevel: fix role order 2020-06-11 13:49:36 +02:00
LinAGKar
6aecf68098 Translated using Weblate (Swedish)
Currently translated at 40.6% (697 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-06-11 06:29:33 +00:00
Nils Haugen
dc54c6139f Translated using Weblate (Norwegian Nynorsk)
Currently translated at 49.4% (848 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/nn/
2020-06-11 06:29:33 +00:00
Priit Jõerüüt
71f158c526 Translated using Weblate (Estonian)
Currently translated at 97.6% (160 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/et/
2020-06-11 06:29:32 +00:00
Marko Dimjašević
dc7067baff Translated using Weblate (Croatian)
Currently translated at 71.5% (1227 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-06-11 06:29:32 +00:00
Besnik Bleta
ced226777f Translated using Weblate (Albanian)
Currently translated at 99.6% (1710 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sq/
2020-06-11 06:29:27 +00:00
ganfra
579d4f7a5b Merge branch 'develop' into feature/power_level 2020-06-10 17:21:04 +02:00
ganfra
60b91d4d50 PowerLevel : clean after Benoit's review 2020-06-10 17:19:33 +02:00
ganfra
917042c48c Remove memory leak from Autocompleter 2020-06-10 16:14:19 +02:00
Benoit Marty
ed27c35bb4 Merge pull request #1467 from vector-im/feature/modular_link
Update link to Modular url from "https://modular.im/" to "https://modular.im/services/matrix-hosting-riot" and open it using ChromeCustomTab
2020-06-10 10:12:48 +02:00
Benoit Marty
c35c94b7b7 Update link to Modular url from "https://modular.im/" to "https://modular.im/services/matrix-hosting-riot" and open it using ChromeCustomTab 2020-06-10 09:13:08 +02:00
Benoit Marty
d8317f7439 Add capability to add and remove a room from the favorites (#1217) 2020-06-10 00:42:14 +02:00
Benoit Marty
9a3813f883 Add command line to run Android test 2020-06-09 17:04:50 +02:00
Benoit Marty
0a7f77ea16 ktlint 2020-06-08 22:08:59 +02:00
ganfra
d6329a1ab6 Start looking at memory leaks 2020-06-08 19:46:55 +02:00
Benoit Marty
0ba120356a Merge pull request #1447 from vector-im/feature/fix_version
Feature/fix version
2020-06-08 18:16:51 +02:00
Benoit Marty
d402b49f07 Merge branch 'develop' into feature/fix_version 2020-06-08 18:16:42 +02:00
Benoit Marty
d4ba9fa09a Cleanup after Ganfra's review 2020-06-08 18:15:00 +02:00
Benoit Marty
62f352243d Merge pull request #1448 from vector-im/feature/fix
Feature/fix
2020-06-08 18:10:06 +02:00
Benoit Marty
1ad19b5e93 Merge branch 'develop' into feature/fix 2020-06-08 18:09:57 +02:00
Benoit Marty
e7ba0a5c60 Merge pull request #1449 from vector-im/feature/fix_1444
Wrong /query request (#1444)
2020-06-08 18:07:23 +02:00
Benoit Marty
050407f7c7 Merge branch 'develop' into feature/fix_1444 2020-06-08 18:07:15 +02:00
Benoit Marty
dffe096c59 Merge pull request #1451 from vector-im/feature/sso_redirect
Correctly handle SSO login redirection
2020-06-08 18:06:00 +02:00
ganfra
bf5ad2cf18 Power level: warn when demoting yourself 2020-06-08 17:36:30 +02:00
ganfra
a8ae4ddde8 Power level: use confirmation dialog 2020-06-08 16:33:56 +02:00
LinAGKar
2596a9ef7e Translated using Weblate (Swedish)
Currently translated at 40.4% (694 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-06-08 11:29:54 +00:00
Eduardo F
f74989ac1d Translated using Weblate (Portuguese (Brazil))
Currently translated at 51.2% (879 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/pt_BR/
2020-06-08 11:29:40 +00:00
Krystian Chachuła
d3bc4017a5 Translated using Weblate (Polish)
Currently translated at 90.8% (1559 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/pl/
2020-06-08 11:29:39 +00:00
Nils Haugen
ab8480d983 Translated using Weblate (Norwegian Nynorsk)
Currently translated at 78.0% (128 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/nn/
2020-06-08 11:29:39 +00:00
Nils Haugen
50dcc24900 Translated using Weblate (Norwegian Nynorsk)
Currently translated at 49.3% (847 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/nn/
2020-06-08 11:29:39 +00:00
Marko Dimjašević
a66470f93b Translated using Weblate (Croatian)
Currently translated at 68.9% (1183 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-06-08 11:29:38 +00:00
ganfra
d2dba1826d Update CHANGES 2020-06-08 10:32:02 +02:00
ganfra
7f02195377 Clean code 2020-06-08 10:29:09 +02:00
ganfra
0002cddd67 Merge branch 'develop' into feature/power_level 2020-06-08 10:12:53 +02:00
Benoit Marty
19e1683106 Move class LoginFlowType to api package 2020-06-08 09:16:31 +02:00
Benoit Marty
5c538c7865 Clarify type when retrieving supported login flow (be conform to the spec) 2020-06-08 09:11:23 +02:00
Benoit Marty
ee23967afe I made a mistake: registration step m.login.token type is not the same that login request. 2020-06-08 08:53:06 +02:00
ganfra
86dd8f3fd8 Update epoxy to last stable version 2020-06-05 20:14:36 +02:00
ganfra
f19e2a0995 Room left: fix state not being updated 2020-06-05 20:09:30 +02:00
ganfra
afd1002fdb Room Permission: default to true for sending event 2020-06-05 20:09:13 +02:00
ganfra
07c7ed0a4e Powerlevel: use edit text for custom 2020-06-05 20:08:39 +02:00
Benoit Marty
b48eb6e9cc SSO Update the documentation 2020-06-05 19:14:31 +02:00
ganfra
e5da5a34cb Power levels: handle some action permissions 2020-06-05 19:12:33 +02:00
Benoit Marty
f3a2c467ed small typo 2020-06-05 12:21:58 +02:00
ganfra
a1fd35aa67 Room member: continue to branch admin/moderator actions 2020-06-05 11:13:00 +02:00
ganfra
ad8ed37ff6 Profile action: fix editable icon 2020-06-05 11:12:33 +02:00
Benoit Marty
088e8bc9f9 Add some comment 2020-06-05 10:09:49 +02:00
Benoit Marty
3714323d74 Rename Constants 2020-06-05 01:16:19 +02:00
Benoit Marty
d70b19fa93 SSO login is now performed in the default browser (#1400) - WIP
Use ChromeCustomTabs to host the SSO web page
2020-06-05 01:14:35 +02:00
ganfra
08693a6875 Add some admin actions (ban, kick, unban) 2020-06-04 18:36:28 +02:00
ganfra
73eca2407b Power level: handle timeline rendering 2020-06-04 17:18:39 +02:00
Benoit Marty
ae7a52cecf Correctly handle SSO login redirection 2020-06-04 16:55:27 +02:00
Benoit Marty
2e244dd448 Merge pull request #1446 from vector-im/feature/various_fixes
Hide left rooms in breadcrumbs (#766)
2020-06-04 15:07:45 +02:00
Benoit Marty
1ad77530aa Use RoomSummaryQueryParams as per Ganfra's excellent suggestion 2020-06-04 14:36:51 +02:00
Benoit Marty
e44963728f Merge pull request #1450 from vector-im/feature/navigation_bar
Fix bad color contrast for navigation and status bar
2020-06-04 14:31:06 +02:00
ganfra
9075371145 Power level: start to handle updating 2020-06-04 13:09:20 +02:00
Benoit Marty
3b256a708e Fix status bar icon contrast on API in [21,23[ 2020-06-04 12:55:27 +02:00
Benoit Marty
aea517515c Fix navigation bar icon contrast on API in [21,27[ (#1342) 2020-06-04 12:50:42 +02:00
Benoit Marty
f28889284d Wrong /query request (#1444) 2020-06-04 11:59:04 +02:00
Valere
240f1f51b9 Merge pull request #1437 from vector-im/feature/fix_1169
Fix / reply ux stays too long
2020-06-04 11:44:53 +02:00
Valere
05efd7423e Merge branch 'develop' into feature/fix_1169 2020-06-04 11:44:32 +02:00
Benoit Marty
fce8a3bc18 changes.md 2020-06-04 11:43:54 +02:00
Valere
2adb5af051 update change log 2020-06-04 11:43:47 +02:00
Benoit Marty
8b7e5e527a Make Credentials.homeServer optional because it is deprecated (#1443)
It is never used currently in RiotX, but if homeserver does not sent it, it would crash.
2020-06-04 11:41:32 +02:00
Benoit Marty
c3d8916802 fix param name 2020-06-04 11:40:38 +02:00
Benoit Marty
532f5e58ea Move class Versions to internal package 2020-06-04 11:30:24 +02:00
Benoit Marty
57a5714fb5 Add the ability to compare Homeserver version (#1442) 2020-06-04 11:24:31 +02:00
Benoit Marty
a3fd49499b Hide left rooms in breadcrumbs (#766) 2020-06-04 08:59:01 +02:00
Benoit Marty
3dc2cd4d7a Disable one code check 2020-06-03 18:54:03 +02:00
Benoit Marty
0b738e3d9e Merge pull request #1409 from vector-im/feature/markdown_test
Send plain text in the body
2020-06-03 18:45:06 +02:00
Benoit Marty
b29c2b2de4 Send plain text in the body
According to https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes, the plain text version of the HTML should be provided in the body.

Also create MarkdownParser class to be able to unit test it.
2020-06-03 18:44:35 +02:00
Benoit Marty
40f2d19f81 Merge pull request #1415 from vector-im/feature/signup_username_digit
Temporary fix to show error when user is creating an account on matrix.org with userId containing only digits (#1410)
2020-06-03 18:41:55 +02:00
Benoit Marty
2e997f2c67 Wrong issue number 2020-06-03 18:41:27 +02:00
Benoit Marty
0fd50892af Temporary fix to show error when user is creating an account on matrix.org with userId containing only digits (#1410) 2020-06-03 18:41:07 +02:00
Benoit Marty
55bd346cb2 Merge pull request #1425 from vector-im/feature/integration_manager
Feature/integration manager
2020-06-03 18:10:03 +02:00
ganfra
0724ac133b Widget notice: capitalize first letter 2020-06-03 15:22:20 +02:00
ganfra
0507fa5b0e Widgets: clean again after Benoit's review 2020-06-03 12:00:52 +02:00
Benoit Marty
617e945afa Merge pull request #1436 from vector-im/feature/Fix_1430_X_made_no_change
Hide "X made no changes" event by default in timeline (#1430)
2020-06-03 09:47:51 +02:00
Benoit Marty
870c4bf765 Check that content is not null 2020-06-03 09:32:20 +02:00
Benoit Marty
9a592e9c7e Create IsUselessResolver object 2020-06-03 01:13:02 +02:00
ganfra
53592ac404 Fix lint issues 2020-06-02 20:28:18 +02:00
ganfra
d8848a6062 Merge branch 'develop' into feature/integration_manager 2020-06-02 20:26:03 +02:00
ganfra
173c1d3a6e Integration: make the default urls modifiable from MatrixConfiguration 2020-06-02 20:05:00 +02:00
ganfra
c815c4080d Widget: changes naming algorithm (align on web) 2020-06-02 19:51:16 +02:00
Valere
c09626182c Fix / reply ux stays too long 2020-06-02 19:31:25 +02:00
ganfra
65c6ce3033 Merge branch 'feature/integration_manager' of github.com:vector-im/riotX-android into feature/integration_manager 2020-06-02 19:02:31 +02:00
ganfra
06cc2f527e Clean after Benoit's review 2020-06-02 19:02:21 +02:00
ganfra
9da5061689 Update CHANGES.md
Co-authored-by: Benoit Marty <benoitm@matrix.org>
2020-06-02 16:37:51 +02:00
ganfra
82b4415f7d Widget: fix loading widgets without scalar token 2020-06-02 16:02:10 +02:00
Benoit Marty
3f1e5b9b1e Hide "X made no changes" event by default in timeline (#1430) 2020-06-02 15:54:01 +02:00
Benoit Marty
1b95d98ccd Merge pull request #1423 from vector-im/feature/invalidate
Yet another cleanup PR
2020-06-02 14:42:51 +02:00
Benoit Marty
e2e1925796 Restore .observeOn(AndroidSchedulers.mainThread()) 2020-06-02 14:24:29 +02:00
Benoit Marty
52c8f24df5 Merge pull request #1417 from vector-im/feature/you
Use "you" instead of your display name for notice events you have sent
2020-06-02 14:16:46 +02:00
Benoit Marty
ca855da8ae Fix issue reported during review by Onuray 2020-06-02 13:15:03 +02:00
Benoit Marty
a39d35e54c Improve Kotlin code readability: use when instead of if and add a few newlines 2020-06-02 13:15:03 +02:00
Benoit Marty
3bd2b24b10 Use "you" instead of display name when the current user has sent the event. 2020-06-02 13:15:03 +02:00
Benoit Marty
12448426d4 Fix typo reported by rageshake 2020-06-01 22:12:11 +02:00
LinAGKar
a043d7cac7 Translated using Weblate (Swedish)
Currently translated at 25.4% (436 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-06-01 15:29:17 +00:00
rkfg
4d88111d48 Translated using Weblate (Russian)
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/ru/
2020-06-01 15:29:15 +00:00
rkfg
34d6610bf8 Translated using Weblate (Russian)
Currently translated at 85.0% (1459 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-06-01 15:29:15 +00:00
Nils J. Haugen
4bfc52327b Translated using Weblate (Norwegian Nynorsk)
Currently translated at 49.4% (849 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/nn/
2020-06-01 15:29:14 +00:00
nosorae
15d5f7ff55 Translated using Weblate (Korean)
Currently translated at 73.2% (1256 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ko/
2020-06-01 15:29:14 +00:00
Szimszon
91ecd1aeeb Translated using Weblate (Hungarian)
Currently translated at 100.0% (1717 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hu/
2020-06-01 15:29:14 +00:00
sr093906
342f871916 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/zh_Hans/
2020-06-01 15:29:10 +00:00
Nikita Ledenev
18d51de0b9 Translated using Weblate (Russian)
Currently translated at 85.0% (1459 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-06-01 06:08:36 +00:00
rkfg
4dc6cae854 Translated using Weblate (Russian)
Currently translated at 85.0% (1459 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-06-01 06:08:35 +00:00
rkfg
5fb160e1ac Translated using Weblate (Russian)
Currently translated at 83.8% (1439 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-05-30 18:28:21 +00:00
Амёба
f1589314c2 Translated using Weblate (Russian)
Currently translated at 83.8% (1439 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-05-30 18:28:19 +00:00
LinAGKar
7fb9a550c8 Translated using Weblate (Swedish)
Currently translated at 23.2% (399 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-05-30 09:29:28 +00:00
Амёба
46f7f4814c Translated using Weblate (Russian)
Currently translated at 82.6% (1418 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-05-30 09:29:24 +00:00
Benoit Marty
c002cc104c Translated using Weblate (Portuguese (Brazil))
Currently translated at 51.1% (878 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/pt_BR/
2020-05-30 09:29:22 +00:00
random
492128a621 Translated using Weblate (Italian)
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/it/
2020-05-30 09:29:22 +00:00
random
fff0f09684 Translated using Weblate (Italian)
Currently translated at 100.0% (1717 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/it/
2020-05-30 09:29:22 +00:00
Szimszon
64054d13a3 Translated using Weblate (Hungarian)
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/hu/
2020-05-30 09:29:20 +00:00
Szimszon
ae8d7096c3 Translated using Weblate (Hungarian)
Currently translated at 98.5% (1691 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hu/
2020-05-30 09:29:20 +00:00
Kévin C
13e04b6362 Translated using Weblate (French)
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/fr/
2020-05-30 09:29:19 +00:00
Kévin C
89e557bcef Translated using Weblate (French)
Currently translated at 100.0% (1717 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/fr/
2020-05-30 09:29:19 +00:00
Samu Voutilainen
fdf4749c1b Translated using Weblate (Finnish)
Currently translated at 99.4% (163 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/fi/
2020-05-30 09:29:17 +00:00
zeritti
a63608bf97 Translated using Weblate (Czech)
Currently translated at 100.0% (1717 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/cs/
2020-05-30 09:29:17 +00:00
Jeff Huang
5c101e9466 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (164 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/zh_Hant/
2020-05-30 09:29:12 +00:00
Jeff Huang
4b25ebc731 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (1717 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/zh_Hant/
2020-05-30 09:29:12 +00:00
Besnik Bleta
8e88fcb462 Translated using Weblate (Albanian)
Currently translated at 99.4% (163 of 164 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/sq/
2020-05-30 09:29:10 +00:00
Besnik Bleta
fd19b345a1 Translated using Weblate (Albanian)
Currently translated at 99.4% (1707 of 1717 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sq/
2020-05-30 09:29:10 +00:00
Benoit Marty
4a7bba047b Merge pull request #1420 from vector-im/feature/fix_theme_switch
Fix: Switch theme is not fully taken into account without restarting the app
2020-05-29 19:22:43 +02:00
ganfra
440c21e9f3 Update CHANGES 2020-05-29 19:06:06 +02:00
ganfra
959b679086 Clean files 2020-05-29 19:03:54 +02:00
ganfra
64cfd4d81a Widget: fix nullable widgetId 2020-05-29 18:08:56 +02:00
ganfra
c742ca3b41 Widget: fix widget title color 2020-05-29 17:09:10 +02:00
ganfra
2002252f72 Widget: Handle failures on permissions 2020-05-29 16:44:17 +02:00
ganfra
7df8b3a9bf Widgets: observe wellknown for integ config and open Jitsi in browser 2020-05-29 12:23:36 +02:00
Benoit Marty
3fea2173f4 Move fun to a dedicated file. 2020-05-29 11:57:20 +02:00
Benoit Marty
d125cb5c01 Some cleanup:
- use invalidate() from MvRx
- use throttleFirst instead of debounce
- remove useless observe on main thread
- remove useless calls to super.invalidate()
2020-05-29 11:36:27 +02:00
Benoit Marty
86c9264ed9 Fix: Switch theme is not fully taken into account without restarting the app 2020-05-28 23:03:04 +02:00
ganfra
00f2d0249f Merge branch 'develop' into feature/integration_manager 2020-05-28 20:33:51 +02:00
ganfra
4465e6eea3 Widget: format url with roomId if needed 2020-05-28 20:26:34 +02:00
ganfra
b87fb8c396 Widget: show sticker in room summary format 2020-05-28 20:15:11 +02:00
ganfra
d4706b38b8 Widgets: display widget events in timeline 2020-05-28 20:04:41 +02:00
ganfra
31c82b4ba6 Widget: show room widgets in bottom sheet and fix some widget actions 2020-05-28 19:39:07 +02:00
ganfra
cb80d8d349 Widget: add active widgets 2020-05-28 17:08:57 +02:00
Benoit Marty
7be3434136 Merge branch 'hotfix/crash_locales' into develop 2020-05-28 11:31:38 +02:00
Benoit Marty
ec1422b0f0 Fix crash due to bad script. Tha bad value has already been fixed on Weblate. 2020-05-28 11:27:11 +02:00
Benoit Marty
b0a6eaaa96 Version++ 2020-05-28 10:45:58 +02:00
Benoit Marty
d1c4d4b099 Merge branch 'release/0.21.0' 2020-05-28 10:43:55 +02:00
Benoit Marty
d35905787d Merge branch 'release/0.21.0' into develop 2020-05-28 10:43:53 +02:00
Benoit Marty
9a972b2f73 Prepare release 0.21.0 2020-05-28 10:43:40 +02:00
ganfra
1fe0c8a3e9 Widgets: handle actions (revoke, delete, edit, open in browser) and permissions bottom sheet 2020-05-28 10:25:04 +02:00
Benoit Marty
116bab5bc8 Fix call event not rendered in e2e rooms. 2020-05-27 19:02:27 +02:00
Benoit Marty
c76eb3bc98 Fix lint issue 2020-05-27 18:58:45 +02:00
Benoit Marty
81c1717384 Format strings 2020-05-27 18:49:34 +02:00
Benoit Marty
0fd0500d30 Merge pull request #1414 from RiotTranslateBot/weblate-riot-android-riotx-application
Update from Weblate
2020-05-27 17:50:06 +02:00
Benoit Marty
34d638da4f Merge pull request #1411 from vector-im/feature/attachment_e2e
Feature/attachment e2e
2020-05-27 15:13:17 +02:00
Weblate
e39b177b5b Merge branch 'origin/develop' into Weblate. 2020-05-27 13:04:35 +00:00
LinAGKar
07aa3ee64c Translated using Weblate (Swedish)
Currently translated at 19.9% (335 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-05-27 13:04:29 +00:00
yuuki-san
c94856cdf8 Translated using Weblate (Slovak)
Currently translated at 95.7% (156 of 163 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/sk/
2020-05-27 13:04:26 +00:00
yuuki-san
4dd0c04537 Translated using Weblate (Slovak)
Currently translated at 53.9% (906 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sk/
2020-05-27 13:04:26 +00:00
Амёба
99c409b6d2 Translated using Weblate (Russian)
Currently translated at 82.6% (1390 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-05-27 13:04:26 +00:00
Marko Dimjašević
8cb2c2532f Translated using Weblate (Croatian)
Currently translated at 54.2% (912 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-05-27 13:04:24 +00:00
Benoit Marty
6f804cab4d Avoid duplicated events in DB (one with localId and one with eventId from homeserver, once synced) 2020-05-27 11:27:54 +02:00
Benoit Marty
cf3dbb378e Get uploaded files for e2e rooms, from local DB 2020-05-26 22:06:51 +02:00
ganfra
e32716aa48 Widget: add room active widgets to RoomDetailViewState 2020-05-26 19:47:06 +02:00
ganfra
ba46f10e3f Add integration entry to settings 2020-05-26 19:44:14 +02:00
ganfra
4b37ede8c2 Widget: handle sticker 2020-05-26 18:16:38 +02:00
ganfra
dbe4c0c8e4 Remove duplicates from identity feature 2020-05-26 11:38:29 +02:00
ganfra
4f4afd6840 Widget post api: handle last methods 2020-05-26 11:29:42 +02:00
ganfra
7409fde650 Merge branch 'develop' into feature/integration_manager 2020-05-26 08:55:01 +02:00
ganfra
cfa31e6332 Widgets: fix extracting user widgets 2020-05-26 08:31:19 +02:00
ganfra
df973a6275 Widget: makes the integration manager screen mostly working 2020-05-26 08:07:09 +02:00
Benoit Marty
0eb36a607b Merge pull request #1402 from vector-im/feature/rageshake_dialogs
Feature/rageshake dialogs
2020-05-26 00:04:33 +02:00
Benoit Marty
0509e76f18 var -> val 2020-05-25 23:54:53 +02:00
Benoit Marty
e379ccf086 Extract MatrixConfiguration to its own file, for a better visibility 2020-05-25 23:53:36 +02:00
Benoit Marty
7ae52d676d Use directly java.net.proxy class 2020-05-25 23:50:10 +02:00
Benoit Marty
3d33018ffa Merge pull request #1147 from unclejay80/http_proxy_init
added network proxy configuration
2020-05-25 23:43:11 +02:00
Benoit Marty
860595520b Merge pull request #1401 from vector-im/feature/cleanup
Small PR with code cleanup
2020-05-25 17:30:31 +02:00
Benoit Marty
ae318a835e Merge pull request #1387 from vector-im/feature/attachments_list
Attachments list
2020-05-25 17:29:54 +02:00
Benoit Marty
7a3dbecc08 Fixes #860 2020-05-25 17:05:17 +02:00
Benoit Marty
c52aae7c29 Uploads: Snackbar 2020-05-25 17:05:17 +02:00
Benoit Marty
f0f3e8ddb9 Uploads: auto-review 2020-05-25 17:05:17 +02:00
Benoit Marty
a95102a78f Uploads: Use StateView for better Loading/Empty rendering 2020-05-25 17:02:57 +02:00
Benoit Marty
2adafbeb03 Uploads: use SenderInfo in TimelineEvent 2020-05-25 17:02:57 +02:00
Benoit Marty
f3a5fb7fe3 Uploads: rework: provide information about the sender 2020-05-25 16:54:08 +02:00
Benoit Marty
907a786b1a Uploads: load element until loader not displayed anymore 2020-05-25 16:54:08 +02:00
Benoit Marty
e3ed3e5b05 Uploads: cleanup 2020-05-25 16:54:08 +02:00
Benoit Marty
a2b366ebfe Uploads: add placeholder for images 2020-05-25 16:54:08 +02:00
Benoit Marty
f7de2f0f13 Uploads: create extension 2020-05-25 16:54:08 +02:00
Benoit Marty
919225bdfd Uploads: create extension 2020-05-25 16:54:08 +02:00
Benoit Marty
88cba74cac Uploads: add screen - WIP 2020-05-25 16:54:08 +02:00
Benoit Marty
e9ca876444 Uploads: add screen - WIP 2020-05-25 16:54:08 +02:00
Benoit Marty
0992e76800 Uploads: add screen - WIP 2020-05-25 16:54:08 +02:00
Benoit Marty
8a9498bae4 Uploads: add the service and the task 2020-05-25 16:54:08 +02:00
Weblate
d2598480c8 var -> val 2020-05-25 16:54:08 +02:00
Benoit Marty
6e57b06673 Ensure Filter model match the spec and add Javadoc 2020-05-25 16:54:08 +02:00
Benoit Marty
a036be6436 Fix missing title in BugReport screen 2020-05-25 15:42:58 +02:00
Benoit Marty
53c7ea2831 Kotlin: use orEmpty() for Maps 2020-05-25 15:42:30 +02:00
Benoit Marty
e117fec74f Kotlin: use orEmpty() for Maps 2020-05-25 14:07:25 +02:00
Benoit Marty
6e01b75b2f Dagger: use generic name for parameters 2020-05-25 14:04:36 +02:00
Benoit Marty
691e7fe616 Kotlin: use orEmpty() 2020-05-25 14:04:36 +02:00
Benoit Marty
e793a46576 Merge pull request #1390 from vector-im/feature/icon
Change icon to magnifying-glass to filter room (#1384)
2020-05-25 10:57:30 +02:00
Benoit Marty
fa48e8cffa Change icon to magnifying-glass to filter room (#1384) 2020-05-25 10:57:14 +02:00
Benoit Marty
69cf437a39 Merge pull request #1291 from vector-im/feature/complete_security
Add hint to translators
2020-05-25 10:28:20 +02:00
Benoit Marty
ebbc432570 Merge pull request #1398 from vector-im/feature/date_time
Bugfixes
2020-05-25 10:13:30 +02:00
LinAGKar
2532724e92 Translated using Weblate (Swedish)
Currently translated at 18.8% (316 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-05-25 00:29:11 +00:00
MamasLT
e31693b4b7 Translated using Weblate (Lithuanian)
Currently translated at 2.5% (4 of 163 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/lt/
2020-05-25 00:29:10 +00:00
Marko Dimjašević
3ed6452232 Translated using Weblate (Croatian)
Currently translated at 50.9% (856 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-05-25 00:29:10 +00:00
Besnik Bleta
166aaa62f0 Translated using Weblate (Albanian)
Currently translated at 99.5% (1673 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sq/
2020-05-25 00:29:00 +00:00
MamasLT
45e5fff622 Added translation using Weblate (Lithuanian) 2020-05-23 23:44:45 +00:00
MamasLT
8f2dba09ee Added translation using Weblate (Lithuanian) 2020-05-23 23:43:32 +00:00
LinAGKar
2ea46c5e54 Translated using Weblate (Swedish)
Currently translated at 18.7% (315 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-05-23 14:29:20 +00:00
@a2sc:matrix.org
fc5f0f7673 Translated using Weblate (German)
Currently translated at 99.5% (1674 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/de/
2020-05-23 14:29:19 +00:00
Tirifto
188f4a2e72 Translated using Weblate (Esperanto)
Currently translated at 27.5% (463 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/eo/
2020-05-23 14:29:18 +00:00
Marko Dimjašević
cf97fc3b01 Translated using Weblate (Croatian)
Currently translated at 41.2% (693 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-05-23 14:29:15 +00:00
Osoitz
5267ba240a Translated using Weblate (Basque)
Currently translated at 100.0% (163 of 163 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/eu/
2020-05-23 14:29:00 +00:00
Osoitz
f185dcacd7 Translated using Weblate (Basque)
Currently translated at 100.0% (1682 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/eu/
2020-05-23 14:29:00 +00:00
Benoit Marty
330a33a0e8 Render formatted_body for m.notice and m.emote (Fixes #1196) 2020-05-21 01:47:17 +02:00
Benoit Marty
b75b299847 Create MessageContentWithFormattedBody interface 2020-05-21 01:05:47 +02:00
Benoit Marty
7c59bcc928 Only "org.matrix.custom.html" is supported 2020-05-21 00:41:36 +02:00
Benoit Marty
0e110b0794 Cleanup: use existing TextContent class instead of Pair<> 2020-05-21 00:40:12 +02:00
Benoit Marty
e156a62e19 Enable markdown (if active) when sending emote (Fixes #734) 2020-05-21 00:27:19 +02:00
Benoit Marty
628439aa65 Mardown: sending "**text in bold** was sending extra paragraph and extra new line 2020-05-21 00:25:59 +02:00
Benoit Marty
d49fcb80fc "Seen by" uses 12h time (Fixes #1378)
DateUtils.FORMAT_SHOW_TIME has to be used for i18n to be effective on DateUtils.getRelativeDateTimeString(), do not ask me why.
Also internal switching of language does not have effect on this method, you'll have to restart the application.
2020-05-20 23:52:41 +02:00
ganfra
00fd067c6b Widget: continue working on interaction with SDK. Not sure yet how to manage properly distinction between room and "admin" widgets. 2020-05-20 20:39:18 +02:00
Benoit Marty
ca37895619 Merge pull request #1374 from vector-im/feature/sas_v2
support new key agreement method for SAS
2020-05-20 18:32:01 +02:00
Benoit Marty
43497e0da9 Merge pull request #1315 from vector-im/feature/forward_pagination
Feature/forward pagination
2020-05-20 18:30:09 +02:00
LinAGKar
efa510c0a8 Translated using Weblate (Swedish)
Currently translated at 17.1% (287 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-05-20 15:29:38 +00:00
yuuki-san
0828159ee4 Translated using Weblate (Slovak)
Currently translated at 53.9% (906 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sk/
2020-05-20 15:29:35 +00:00
Амёба
90f21198c3 Translated using Weblate (Russian)
Currently translated at 82.1% (1381 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-05-20 15:29:34 +00:00
Eduardo F
a0b0778fce Translated using Weblate (Portuguese (Brazil))
Currently translated at 52.2% (878 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/pt_BR/
2020-05-20 15:29:33 +00:00
random
d937fa67ad Translated using Weblate (Italian)
Currently translated at 100.0% (1682 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/it/
2020-05-20 15:29:33 +00:00
Kim Brose
91d396fbca Translated using Weblate (German)
Currently translated at 100.0% (163 of 163 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/de/
2020-05-20 15:29:32 +00:00
@a2sc:matrix.org
afba5b2b6c Translated using Weblate (German)
Currently translated at 99.5% (1673 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/de/
2020-05-20 15:29:32 +00:00
Benoit Marty
b579a1bc83 Translated using Weblate (French)
Currently translated at 100.0% (1682 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/fr/
2020-05-20 15:29:31 +00:00
Priit Jõerüüt
db49673fc7 Translated using Weblate (Estonian)
Currently translated at 14.2% (239 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/et/
2020-05-20 15:29:31 +00:00
Marko Dimjašević
bb0511e659 Translated using Weblate (Croatian)
Currently translated at 26.2% (441 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-05-20 15:29:22 +00:00
Jeff Huang
0e0763ec2d Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (1682 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/zh_Hant/
2020-05-20 15:28:52 +00:00
ganfra
3faf42be53 Widget: get user list widgets from user account 2020-05-19 18:40:11 +02:00
ganfra
dea903bcb5 Merge branch 'develop' into feature/integration_manager 2020-05-19 16:08:46 +02:00
ganfra
e1c6542e03 Merge branch 'develop' into feature/forward_pagination 2020-05-19 15:25:33 +02:00
ganfra
01484978bd Fix lint 2020-05-19 15:24:36 +02:00
ganfra
cad14c93d0 Timeline: fix tests and add message order check 2020-05-19 14:39:42 +02:00
toastbroot
ee52b9185b Translated using Weblate (German)
Currently translated at 99.4% (1672 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/de/
2020-05-19 09:33:16 +00:00
Valere
861a7f791f Update change log 2020-05-19 09:57:54 +02:00
Valere
f2fa57224b Update matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/crypto/verification/DefaultVerificationService.kt
Co-authored-by: Hubert Chathi <hubert@uhoreg.ca>
2020-05-19 09:55:45 +02:00
Valere
e0977dd97b Add new key agreement protocol 2020-05-19 09:55:45 +02:00
Benoit Marty
f47bef71a4 Merge pull request #1354 from vector-im/feature/identity
Identity server
2020-05-18 17:28:57 +02:00
Benoit Marty
92985fc8e7 Split long line 2020-05-18 17:25:15 +02:00
Benoit Marty
243b0a7d82 ktlint 2020-05-18 17:23:33 +02:00
Benoit Marty
92c719a803 Set identity server: do not show the error in the EditText when user want to use the default identity server 2020-05-18 17:23:33 +02:00
Benoit Marty
f4108ae0eb Properly handle Loading state: button were still active... Also finish the work on the controller 2020-05-18 17:23:33 +02:00
Benoit Marty
ecf3fee709 Integrate Valere's remarks - step 3: use viewModelScope in ViewModels 2020-05-18 17:23:33 +02:00
Benoit Marty
e67e472025 Integrate Valere's remarks - step 2: Stop using (or at least reduce usage of) GlobalScope 2020-05-18 17:23:33 +02:00
Benoit Marty
a6541481bf Integrate Valere's remarks - step 1 2020-05-18 17:23:33 +02:00
Benoit Marty
85a4f83662 Colorize the identity server url 2020-05-18 17:23:33 +02:00
Benoit Marty
22955e6b34 Use debouncedClicks every where, for faster UI (it uses throttleFirst operator instead of debounce) 2020-05-18 17:23:33 +02:00
Benoit Marty
9520aff848 Use debouncedClicks every where, for faster UI (it uses throttleFirst operator instead of debounce) 2020-05-18 17:23:33 +02:00
Benoit Marty
6b09a78ece Identity: Improve identity choice screen after review 2020-05-18 17:23:33 +02:00
Benoit Marty
789bcc8d77 Identity: Bugfix: do not fail when trying to disconnect the current identity server, if there is no token available 2020-05-18 17:23:33 +02:00
Benoit Marty
2914117a8e Move some classes 2020-05-18 17:23:33 +02:00
Benoit Marty
8049962a99 Create a Wellknown module, because both AuthModule and HomeServerCapability module need it 2020-05-18 17:23:33 +02:00
Benoit Marty
225b1c380e Identity: retrieve the default identity server url 2020-05-18 17:23:33 +02:00
Benoit Marty
60d80ea0ba Fix compilation issue after rebase 2020-05-18 17:23:33 +02:00
Benoit Marty
c8211098f3 Identity: The store has to be migrated properly because it contains user's data 2020-05-18 17:23:33 +02:00
Benoit Marty
e78fde4eca Identity: rename a few class and add a mapper to avoid using Entities in the code 2020-05-18 17:23:33 +02:00
Benoit Marty
59d60813fb Cleanup 2020-05-18 17:23:33 +02:00
Benoit Marty
4c31e52892 Add facilities and Javadoc on SessionParams data class 2020-05-18 17:23:33 +02:00
Benoit Marty
c646fd2b36 ktlint 2020-05-18 17:23:33 +02:00
Benoit Marty
6432859732 Avoid code duplication 2020-05-18 17:23:33 +02:00
Benoit Marty
2beef7d816 Identity: fix issue with logout request.
Also disconnect previous set identity server when changing url, when disconnecting, and when deactivating account
2020-05-18 17:23:33 +02:00
Benoit Marty
623056455b Identity: fix rendering error 2020-05-18 17:23:33 +02:00
Benoit Marty
7a4d9370e3 Identity: human readable errors 2020-05-18 17:23:33 +02:00
Benoit Marty
fe3138492e Identity: fix issue in dark theme 2020-05-18 17:23:33 +02:00
Benoit Marty
05a52164f3 Identity: Changelog and documentation 2020-05-18 17:23:33 +02:00
Benoit Marty
d14f1dd1ab Capability: do not update data if the corresponding request fails 2020-05-18 17:23:13 +02:00
Benoit Marty
88e8c11ee5 Identity: protect against outdated homeserver 2020-05-18 17:23:13 +02:00
Benoit Marty
7afc7bdb31 Identity refresh main setting page. 2020-05-18 17:23:13 +02:00
Benoit Marty
84a3754c9f Confirm identity server disconnection in all cases, as Riot-Web does 2020-05-18 17:23:13 +02:00
Benoit Marty
4b2f8e9174 Auto-review 2020-05-18 17:23:13 +02:00
Benoit Marty
a17932e17e Add missing internal 2020-05-18 17:23:13 +02:00
Benoit Marty
084c27a2bb Identity: cleanup 2020-05-18 17:23:13 +02:00
Benoit Marty
ed2f62cbe7 Identity: ping API V2 and cleanup 2020-05-18 17:23:13 +02:00
Benoit Marty
38fb7185b6 Identity: One class per file 2020-05-18 17:23:13 +02:00
Benoit Marty
ce42d2fb8a Identity: improve terms not signed case 2020-05-18 17:23:13 +02:00
Benoit Marty
af3fc22e2d Identity: correctly handle terms update 2020-05-18 17:22:40 +02:00
Benoit Marty
b659cb60a2 Improve code 2020-05-18 17:22:40 +02:00
Benoit Marty
34cf9903dc Improve code 2020-05-18 17:22:40 +02:00
Benoit Marty
062a21e39a Improve code 2020-05-18 17:22:40 +02:00
Benoit Marty
4510aff00a ktlint 2020-05-18 17:22:40 +02:00
Benoit Marty
d0953b8406 Identity: Cleanup 2020-05-18 17:22:40 +02:00
Benoit Marty
7822660ce7 Identity: Extract enum for Epoxy Items 2020-05-18 17:22:40 +02:00
Benoit Marty
bdfcf5c67c Identity: cleanup Epoxy items 2020-05-18 17:22:40 +02:00
Benoit Marty
ae0d09a049 Identity: cancel binding WIP 2020-05-18 17:22:40 +02:00
Benoit Marty
69759b7415 Identity: store sendAttempt in DB 2020-05-18 17:22:40 +02:00
Benoit Marty
7e8e1ab9b7 Identity: change DB and add sendAttempt 2020-05-18 17:22:40 +02:00
Benoit Marty
b44f5d3b4a Handle correctly the verification code error case 2020-05-18 17:22:40 +02:00
Benoit Marty
03f8b66993 Remove undocumented parameter
https://github.com/matrix-org/sydent/issues/195
2020-05-18 17:22:40 +02:00
Benoit Marty
e411f139c8 Identity: validate code received by SMS 2020-05-18 17:22:40 +02:00
Benoit Marty
e962d1dadf Small improvement 2020-05-18 17:22:40 +02:00
Benoit Marty
756b0febe6 Identity: Add some doc 2020-05-18 17:22:40 +02:00
Benoit Marty
1535f3e2e5 Identity: bind/unbnd: restore the bind in progress State 2020-05-18 17:22:40 +02:00
Benoit Marty
3e808dec90 Identity: bind/unbnd WIP 2020-05-18 17:22:40 +02:00
Benoit Marty
637f4a8350 Fix small UI bug 2020-05-18 17:22:40 +02:00
Benoit Marty
d3bc9f52fd Remove duplicated class 2020-05-18 17:22:40 +02:00
Benoit Marty
ffd8ac859d Identity: fix sync of indetity server change 2020-05-18 17:22:40 +02:00
Benoit Marty
6e43e9b51c Identity: refresh pepper, logout feature and other improvements 2020-05-18 17:22:40 +02:00
Benoit Marty
426171508e Import and adapt Terms Of Service management: SDK and UI (compiling) - still fixing issue 2020-05-18 17:22:40 +02:00
Benoit Marty
e86460b578 Import and adapt Terms Of Service management: SDK and UI (compiling) 2020-05-18 17:22:40 +02:00
Benoit Marty
8dd5f88dba Identity: cleanup UI 2020-05-18 17:21:59 +02:00
Benoit Marty
3aa6de7cf5 Identity: progressing 2020-05-18 17:21:59 +02:00
Benoit Marty
a75242c79d Retrieve ThreePids from homeserver 2020-05-18 17:21:59 +02:00
Benoit Marty
784918350b Identity: import UI/UX From Riot and adapt to RiotX architecture 2020-05-18 17:21:59 +02:00
Benoit Marty
0199cf9a03 Identity - Fix issue with Realm 2020-05-18 17:21:59 +02:00
Benoit Marty
ab6e7a3b8a Identity - WIP (compilation ok) 2020-05-18 17:21:59 +02:00
Benoit Marty
f489265ce7 Create AccessTokenProvider 2020-05-18 17:21:59 +02:00
Benoit Marty
6c9c3e5cb3 To merge with previous previous commit 2020-05-18 17:21:59 +02:00
Benoit Marty
9b7c2599a7 Add withOlmUtility facility 2020-05-18 17:21:59 +02:00
Benoit Marty
25bbd7c526 Identity - Create DB 2020-05-18 17:21:59 +02:00
Benoit Marty
e0c3f3638d Merge pull request #1370 from vector-im/feature/redacted_message
Feature/redacted message
2020-05-18 16:30:40 +02:00
Benoit Marty
d45653dbb3 Ganfra's review: Improve the filters declaration 2020-05-18 16:26:18 +02:00
Benoit Marty
f70623beea Ganfra's review: Handle filterRedacted in TimelineHiddenReadReceipts 2020-05-18 16:26:18 +02:00
Benoit Marty
e542e4ba22 Add a setting to hide redacted events (#951) 2020-05-18 16:26:18 +02:00
Benoit Marty
05d1e64cb5 New rendering for redacted message 2020-05-18 16:25:54 +02:00
Benoit Marty
adac80062c Merge pull request #1368 from vector-im/feature/switch_language
Feature/switch language
2020-05-18 16:22:07 +02:00
Benoit Marty
28f8d9500e Better coroutine management 2020-05-18 16:21:47 +02:00
Benoit Marty
538bda329e Lazy load available languages 2020-05-18 16:21:47 +02:00
Benoit Marty
a00ddca188 Create SystemLocaleProvider 2020-05-18 16:21:47 +02:00
Benoit Marty
8ac2cb0530 Cleanup 2020-05-18 16:21:47 +02:00
Benoit Marty
19d655ec41 Locales: improve algo 2020-05-18 16:21:47 +02:00
Benoit Marty
4961bb0e08 FontSize: rework by creating FontScaleValue data class. 2020-05-18 16:21:47 +02:00
Benoit Marty
f45040c405 Locale: support locale change 2020-05-18 16:21:24 +02:00
Benoit Marty
9fed62e4a7 Improve template 2020-05-18 16:21:00 +02:00
Benoit Marty
43b9e2cec9 Merge pull request #1382 from vector-im/feature/aiplane_mode
Better connectivity lost indicator when airplane mode is on
2020-05-18 15:35:14 +02:00
Benoit Marty
3185b88fe5 Better connectivity lost indicator when airplane mode is on 2020-05-18 15:09:14 +02:00
LinAGKar
c2906d9b06 Translated using Weblate (Swedish)
Currently translated at 14.6% (245 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-05-16 18:28:48 +00:00
Амёба
cfb615f972 Translated using Weblate (Russian)
Currently translated at 82.1% (1381 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/ru/
2020-05-16 18:28:48 +00:00
Priit Jõerüüt
9c22c0952c Translated using Weblate (Estonian)
Currently translated at 5.9% (100 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/et/
2020-05-16 18:28:48 +00:00
Priit Jõerüüt
5a834619c0 Translated using Weblate (Estonian)
Currently translated at 97.5% (159 of 163 strings)

Translation: Riot Android/RiotX Matrix SDK
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-matrix-sdk/et/
2020-05-16 18:28:43 +00:00
LinAGKar
3b62f50f7b Translated using Weblate (Swedish)
Currently translated at 14.4% (242 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-05-16 08:03:01 +00:00
LinAGKar
18e804d174 Translated using Weblate (Swedish)
Currently translated at 14.3% (241 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/sv/
2020-05-16 07:22:14 +00:00
Szimszon
c105d82027 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1682 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hu/
2020-05-16 07:22:11 +00:00
Kévin C
860921217d Translated using Weblate (French)
Currently translated at 100.0% (1682 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/fr/
2020-05-16 07:22:06 +00:00
Priit Jõerüüt
3fe2f2876a Translated using Weblate (Estonian)
Currently translated at 1.6% (27 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/et/
2020-05-16 07:22:05 +00:00
Marko Dimjašević
e84fd408be Translated using Weblate (Croatian)
Currently translated at 0.5% (8 of 1682 strings)

Translation: Riot Android/RiotX application
Translate-URL: https://translate.riot.im/projects/riot-android/riotx-application/hr/
2020-05-16 07:22:05 +00:00
Marko Dimjašević
f361fd7355 Added translation using Weblate (Croatian) 2020-05-15 21:33:36 +00:00
ganfra
458e3ee5e8 Timeline: fetch next token with the help of getContext when required 2020-05-15 20:18:07 +02:00
Benoit Marty
5fa247a0c5 Remove temporary tool and strings_riotX.xml temporary files 2020-05-15 15:50:15 +02:00
Benoit Marty
48e58967b2 Version++ 2020-05-15 15:48:15 +02:00
Benoit Marty
0a41a9f773 Merge branch 'release/0.20.0' into develop 2020-05-15 15:45:26 +02:00
ganfra
22e3b370e3 IntegrationConfig: make preferred non null as we should at least get the default one 2020-05-14 17:54:27 +02:00
ganfra
8f5589d3e1 Start creating the widget url builder 2020-05-14 17:05:22 +02:00
ganfra
03389fc040 Change some naming 2020-05-14 17:05:08 +02:00
ganfra
996aa9ef66 Merge branch 'develop' into feature/integration_manager 2020-05-13 20:21:48 +02:00
ganfra
9778999a7f Create RoomWidget feature 2020-05-13 20:04:19 +02:00
ganfra
91301197ea Try to communicate with WidgetPostAPI 2020-05-13 20:04:08 +02:00
ganfra
01d6b52a60 Widgets: handle scalar token 2020-05-11 20:00:50 +02:00
ganfra
ce884ac577 Merge branch 'develop' into feature/integration_manager 2020-05-11 15:48:27 +02:00
ganfra
b047f36e86 Creates a Widget Manager to be used internally and state event service 2020-05-06 20:49:07 +02:00
ganfra
4fdd2f4eed Create WidgetsAPI 2020-05-06 15:53:28 +02:00
ganfra
182753e4ec Start creating integration manager 2020-05-06 11:53:35 +02:00
ganfra
29c9d3070c Start creating bunch of necessary classes 2020-05-05 13:05:45 +02:00
Benoit Marty
ffeae7ec83 Fix timeline navigation when opening an event in a previous lastForward chunk.
In this case, we do not have a nextToken, but there are more event to load. So we perform a GET /context on the last known event.
Not sure it is correct to do that though...
2020-05-05 02:41:32 +02:00
Benoit Marty
db77e7b817 Create a fun 2020-05-05 02:41:32 +02:00
Benoit Marty
fcee85a682 Cleanup and doc 2020-05-05 02:41:32 +02:00
Benoit Marty
17ddb5ce43 if all events are rendered in the timeline (developer mode), render the room creation event. 2020-05-05 02:41:32 +02:00
Benoit Marty
53583c691f Add some logs 2020-05-05 02:41:32 +02:00
Benoit Marty
2b9d3960b3 Improve tests 2020-05-05 02:41:32 +02:00
Benoit Marty
92befcde5d Add test to cover previous last forward case (passing) 2020-05-05 02:41:32 +02:00
Benoit Marty
697eaec197 TI: After jump to unread, newer messages are never loaded (#1008) 2020-05-05 02:41:32 +02:00
Benoit Marty
86fba28313 After jump to unread, newer messages are never loaded (#1008) 2020-05-05 02:41:32 +02:00
Benoit Marty
f3c3c07d46 Kotlin sugar 2020-05-05 00:14:57 +02:00
Benoit Marty
8966e24925 Create a debug method to send x times the same event 2020-05-05 00:14:57 +02:00
Benoit Marty
becc5a7b54 Add assertion in debug 2020-05-05 00:14:57 +02:00
Benoit Marty
a61434ae08 doc 2020-05-05 00:14:57 +02:00
Benoit Marty
20b726819f Rename "LastLive" -> "LastForward" 2020-05-05 00:14:57 +02:00
Benoit Marty
bfd847179f Wait more 2020-05-05 00:14:57 +02:00
Benoit Marty
7e955ef0e4 Add possibility to create clear room 2020-05-05 00:14:57 +02:00
Benoit Marty
2697800deb Doc and cleanup 2020-05-05 00:14:57 +02:00
Benoit Marty
2c47fe9f0d typo 2020-05-05 00:14:57 +02:00
Benoit Marty
aa16ba88ae Add hint to translators 2020-04-27 12:41:47 +02:00
unclejay
a2367ef14f added network proxy configuration 2020-03-16 21:12:15 +01:00
816 changed files with 32431 additions and 3844 deletions

View File

@@ -7,17 +7,21 @@
<w>ciphertext</w>
<w>coroutine</w>
<w>decryptor</w>
<w>displayname</w>
<w>emoji</w>
<w>emojis</w>
<w>fdroid</w>
<w>gplay</w>
<w>hmac</w>
<w>homeserver</w>
<w>ktlint</w>
<w>linkified</w>
<w>linkify</w>
<w>megolm</w>
<w>msisdn</w>
<w>msisdns</w>
<w>pbkdf</w>
<w>pids</w>
<w>pkcs</w>
<w>riotx</w>
<w>signin</w>

View File

@@ -1,3 +1,91 @@
Changes in RiotX 0.23.0 (2020-XX-XX)
===================================================
Features ✨:
- Call with WebRTC support (##611)
- Add capability to change the display name (#1529)
Improvements 🙌:
- "Add Matrix app" menu is now always visible (#1495)
Bugfix 🐛:
- Fix dark theme issue on login screen (#1097)
- Incomplete predicate in RealmCryptoStore#getOutgoingRoomKeyRequest (#1519)
Translations 🗣:
-
SDK API changes ⚠️:
-
Build 🧱:
- Enable code optimization (Proguard)
- SDK is now API level 21 minimum, and so RiotX (#405)
Other changes:
- Use `retrofit2.Call.awaitResponse` extension provided by Retrofit 2. (#1526)
- Fix minor typo in contribution guide (#1512)
- Fix self-assignment of callback in `DefaultRoomPushRuleService#setRoomNotificationState` (#1520)
- Random housekeeping clean-ups indicated by Lint (#1520)
Changes in RiotX 0.22.0 (2020-06-15)
===================================================
Features ✨:
- Integration Manager and Widget support (#48)
- Send stickers (#51)
Improvements 🙌:
- New wording for notice when current user is the sender
- Hide "X made no changes" event by default in timeline (#1430)
- Hide left rooms in breadcrumbs (#766)
- Handle PowerLevel properly (#627)
- Correctly handle SSO login redirection
- SSO login is now performed in the default browser, or in Chrome Custom tab if available (#1400)
- Improve checking of homeserver version support (#1442)
- Add capability to add and remove a room from the favorites (#1217)
Bugfix 🐛:
- Switch theme is not fully taken into account without restarting the app
- Temporary fix to show error when user is creating an account on matrix.org with userId containing only digits (#1410)
- Reply composer overlay stays on screen too long after send (#1169)
- Fix navigation bar icon contrast on API in [21,27[ (#1342)
- Fix status bar icon contrast on API in [21,23[
- Wrong /query request (#1444)
- Make Credentials.homeServer optional because it is deprecated (#1443)
- Fix issue on dark themes, after alert popup dismiss
Other changes:
- Send plain text in the body of events containing formatted body, as per https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes
- Update link to Modular url from "https://modular.im/" to "https://modular.im/services/matrix-hosting-riot" and open it using ChromeCustomTab
Changes in RiotX 0.21.0 (2020-05-28)
===================================================
Features ✨:
- Identity server support (#607)
- Switch language support (#41)
- Display list of attachments of a room (#860)
Improvements 🙌:
- Better connectivity lost indicator when airplane mode is on
- Add a setting to hide redacted events (#951)
- Render formatted_body for m.notice and m.emote (#1196)
- Change icon to magnifying-glass to filter room (#1384)
Bugfix 🐛:
- After jump to unread, newer messages are never loaded (#1008)
- Fix issues with FontScale switch (#69, #645)
- "Seen by" uses 12h time (#1378)
- Enable markdown (if active) when sending emote (#734)
- Screenshots for Rageshake now includes Dialogs such as BottomSheet (#1349)
SDK API changes ⚠️:
- initialize with proxy configuration
Other changes:
- support new key agreement method for SAS (#1374)
Changes in RiotX 0.20.0 (2020-05-15)
===================================================

View File

@@ -19,7 +19,11 @@ An Android Studio template has been added to the project to help creating all fi
To install the template (to be done only once):
- Go to folder `./tools/template`.
- Run the script `./configure.sh`.
- Mac OSX: Run the script `./configure.sh`.
Linux: Run `ANDROID_STUDIO=/path/to/android-studio ./configure`
- e.g. `ANDROID_STUDIO=/usr/local/android-studio ./configure`
- Restart Android Studio.
To create a new screen:
@@ -27,7 +31,7 @@ To create a new screen:
- Then right click on the package, and select `New/New Vector/RiotX Feature`.
- Follow the Wizard, especially replace `Main` by something more relevant to your feature.
- Click on `Finish`.
- Remainning steps are described as TODO in the generated files, or will be pointed out by the compilator, or at runtime :)
- Remaining steps are described as TODO in the generated files, or will be pointed out by the compilator, or at runtime :)
Note that if the templates are modified, the only things to do is to restart Android Studio for the change to take effect.

View File

@@ -11,8 +11,8 @@ RiotX is an Android Matrix Client currently in beta but in active development.
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.
[<img src="https://play.google.com/intl/en_us/badges/images/generic/en_badge_web_generic.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=im.vector.riotx)
[<img src="https://f-droid.org/badge/get-it-on.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/app/im.vector.riotx)
[<img src="resources/img/google-play-badge.png" alt="Get it on Google Play" height="60">](https://play.google.com/store/apps/details?id=im.vector.riotx)
[<img src="resources/img/f-droid-badge.png" alt="Get it on F-Droid" height="60">](https://f-droid.org/app/im.vector.riotx)
Nightly build: [![Buildkite](https://badge.buildkite.com/657d3db27364448d69d54f66c690f7788bc6aa80a7628e37f3.svg?branch=develop)](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)

92
docs/identity_server.md Normal file
View File

@@ -0,0 +1,92 @@
# Identity server
Issue: #607
PR: #1354
## Introduction
Identity Servers support contact discovery on Matrix by letting people look up Third Party Identifiers to see if the owner has publicly linked them with their Matrix ID.
## Implementation
The current implementation was Inspired by the code from Riot-Android.
Difference though (list not exhaustive):
- Only API v2 is supported (see https://matrix.org/docs/spec/identity_service/latest)
- Homeserver has to be up to date to support binding (Versions.isLoginAndRegistrationSupportedBySdk() has to return true)
- The SDK managed the session and client secret when binding ThreePid. Those data are not exposed to the client.
- The SDK supports incremental sendAttempt (this is not used by RiotX)
- The "Continue" button is now under the information, and not as the same place that the checkbox
- The app can cancel a binding. Current data are erased from DB.
- The API (IdentityService) is improved.
- A new DB to store data related to the identity server management.
Missing features (list not exhaustive):
- Invite by 3Pid (will be in a dedicated PR)
- Add email or phone to account (not P1, can be done on Riot-Web)
- List email and phone of the account (could be done in a dedicated PR)
- Search contact (not P1)
- Logout from identity server when user sign out or deactivate his account.
## Related MSCs
The list can be found here: https://matrix.org/blog/2019/09/27/privacy-improvements-in-synapse-1-4-and-riot-1-4
## Steps and requirements
- Only one identity server by account can be set. The user's choice is stored in account data with key `m.identity_server`. But every clients will managed its own token to log in to the identity server
```json
{
"type": "m.identity_server",
"content": {
"base_url": "https://matrix.org"
}
}
```
- The accepted terms are stored in the account data:
```json
{
"type": "m.accepted_terms",
"content": {
"accepted": [
"https://vector.im/identity-server-privacy-notice-1"
]
}
}
```
- Default identity server URL, from Wellknown data is proposed to the user.
- Identity server can be set
- Identity server can be changed on another user's device, so when the change is detected (thanks to account data sync) RiotX should properly disconnect from a previous identity server (I think it was not the case in Riot-Android, where we keep the token forever)
- Registration to the identity server is managed with an openId token
- Terms of service can be accepted when configuring the identity server.
- Terms of service can be accepted after, if they change.
- Identity server can be modified
- Identity server can be disconnected with a warning dialog, with special content if there are current bound 3pid on this identity server.
- Email can be bound
- Email can be unbound
- Phone can be bound
- Phone can be unbound
- Look up can be performed, to get matrixIds from local contact book (phone and email): Android permission correctly handled (not done yet)
- Look up pepper can be updated if it is rotated on the identity server
- Invitation using 3PID can be done (See #548) (not done yet)
- Homeserver access-token will never be sent to an identity server
- When user sign-out: logout from the identity server if any.
- When user deactivate account: logout from the identity server if any.
## Screens
### Settings
Identity server settings can be accessed from the internal setting of the application, both from "Discovery" section and from identity detail section.
### Discovery screen
This screen displays the identity server configuration and the binding of the user's ThreePid (email and msisdn). This is the main screen of the feature.
### Set identity server screen
This screen is a form to set a new identity server URL
## Ref:
- https://matrix.org/blog/2019/09/27/privacy-improvements-in-synapse-1-4-and-riot-1-4 is a good summary of the role of an Identity server and the proper way to configure and use it in respect to the privacy and the consent of the user.
- API documentation: https://matrix.org/docs/spec/identity_service/latest
- vector.im TOS: https://vector.im/identity-server-privacy-notice

View File

@@ -59,6 +59,12 @@ It's recommended to run tests using an Android Emulator and not a real device. F
You can run all the tests in the `androidTest` folders.
It can be done using this command:
```bash
./gradlew vector:connectedAndroidTest matrix-sdk-android:connectedAndroidTest
```
## Stop Synapse
To stop Synapse, you can run the following commands:

View File

@@ -2,7 +2,7 @@
This document describes the flow of signin to a homeserver, and also the flow when user want to reset his password. Examples come from the `matrix.org` homeserver.
## Sign up flows
## Sign in flows
### Get the flow
@@ -58,7 +58,7 @@ We get credential (200)
```json
{
"user_id": "@alice:matrix.org",
"access_token": "MDAxOGxvY2F0aW9uIG1hdHREDACTEDb2l0MDgxNjptYXRyaXgub3JnCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lkIG5vbmNlID0gfnYrSypfdTtkNXIuNWx1KgowMDJmc2lnbmF0dXJlIOsh1XqeAkXexh4qcofl_aR4kHJoSOWYGOhE7-ubX-DZCg",
"access_token": "MDAxOGxvY2F0aW9uIG1hdHREDACTEDb2l0MDgxNjptYXRyaXgub3JnCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lr",
"home_server": "matrix.org",
"device_id": "GTVREDALBF",
"well_known": {
@@ -117,7 +117,7 @@ We get the credentials (200)
```json
{
"user_id": "@alice:matrix.org",
"access_token": "MDAxOGxvY2F0aW9uIG1hdHJpeC5vcmREDACTEDZXJfaWQgPSBAYmVub2l0MDgxNjptYXRyaXgub3JnCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lkIG5vbmNlID0gNjtDY0MwRlNPSFFoOC5wOgowMDJmc2lnbmF0dXJlIGiTRm1mYLLxQywxOh3qzQVT8HoEorSokEP2u-bAwtnYCg",
"access_token": "MDAxOGxvY2F0aW9uIG1hdHJpeC5vcmREDACTEDZXJfaWQgPSBAYmVub2l0MDgxNjptYXRyaXgub3Jnfrfdegfszsefddvf",
"home_server": "matrix.org",
"device_id": "WBSREDASND",
"well_known": {
@@ -145,12 +145,59 @@ Not supported yet in RiotX
"flows": [
{
"type": "m.login.sso"
},
{
"type": "m.login.token"
}
]
}
```
In this case, the user can click on "Sign in with SSO" and the web screen will be displayed on the page `https://homeserver.with.sso/_matrix/static/client/login/` and the credentials will be passed back to the native code through the JS bridge
In this case, the user can click on "Sign in with SSO" and the native web browser, or a ChromeCustomTab if the device supports it, will be launched on the page
> https://homeserver.with.sso/_matrix/client/r0/login/sso/redirect?redirectUrl=riotx%3A%2F%2Friotx
The parameter `redirectUrl` is set to `riotx://riotx`.
ChromeCustomTabs are an intermediate way to display a WebPage, between a WebView and using the external browser. More info can be found [here](https://developer.chrome.com/multidevice/android/customtabs)
The browser will then take care of the SSO login, which may include creating a third party account, entering an email, settings a display name, or any other possibilities.
During the process, user may be asked to validate an email by clicking on a link it contains. The link has to be opened in the browser which initiates the authentication. This is why we cannot use WebView anymore.
Once the process is finished, the web page will call the `redirectUrl` with an extra parameter `loginToken`
> riotx://riotx?loginToken=MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy
This navigation is intercepted by RiotX by the `LoginActivity`, which will then ask the homeserver to convert this `loginToken` to an access token
> curl -X POST --data $'{"type":"m.login.token","token":"MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy"}' 'https://homeserver.with.sso/_matrix/client/r0/login'
```json
{
"type": "m.login.token",
"token": "MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVy"
}
```
We get the credentials (200)
```json
{
"user_id": "@alice:homeserver.with.sso",
"access_token": "MDAxOWxvY2F0aW9uIG1vemlsbGEub3JnCjAwMTNpZGVudGlmaWVyIGtleQowMDEwY2lkIGdlbiA9IDEKMDAyY2NpZCB1c2",
"home_server": "homeserver.with.sso",
"device_id": "DETBTVAHCH",
"well_known": {
"m.homeserver": {
"base_url": "https:\/\/homeserver.with.sso\/"
},
"m.identity_server": {
"base_url": "https:\/\/vector.im"
}
}
}
```
## Reset password

420
docs/voip_signaling.md Normal file
View File

@@ -0,0 +1,420 @@
╔════════════════════════════════════════════════╗
║ ║
║A] Placing a call offer ║
║ ║
╚════════════════════════════════════════════════╝
┌───────────────┐
│ Matrix │
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
┌─────────────────┐ │ ┌───────────────────────────┐ ┌─────────────────┐
│ Caller │ │ Signaling Room │ │ │ Callee │
└─────────────────┘ │ ├───────────────────────────┤ └─────────────────┘
┌────┐ │ │ │
│ 3 │ │ │ ┌────────────────────┐ │
┌─────────────────┐──────┴────┴──────────────────────────┼─▶│ m.call.invite │ │ │ ┌─────────────────┐
│ │ │ │ │ mx event │ │ │ │
│ │ │ └────────────────────┘ │ │ │ │
│ │ │ │ │ │ │
│ Riot.im │ │ │ │ │ Riot.im │
┌──│ App │ │ │ │ │ App │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ │ │ │ │ │ │
│ └─────────────────┘ │ │ │ └─────────────────┘
┌────┤ ▲ │ │ │
│ 1 │ ├────┐ │ └───────────────────────────┘
└────┤ │ 2 │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
│ ┌──┴────┴─────────┐ ┌─────────────────┐
│ │ │ │ │
│ │ │ │ │
│ │ WebRtc │ │ WebRtc │
└─▶│ │ │ │
│ │ │ │
│ │ │ │
└─────────────────┘ └─────────────────┘
┌────┐
│ 1 │ The Caller app get access to system resources (camera, mic), eventually stun/turn servers, define some
└────┘ constrains (video quality, format) and pass it to WebRtc in order to create a Peer Call offer
┌────┐
│ 2 │ The WebRtc layer creates a call Offer (sdp) that needs to be sent to callee
└────┘
┌────┐ The app layer, takes the webrtc offer, encapsulate it in a matrix event adds a callId and send it to the other
│ 3 │ user via the room
└────┘
┌──────────────┐
│ mx event │
├──────────────┴────────┐
│ type: m.call.invite │
│ + callId │
│ │
│ ┌──────────────────┐ │
│ │ webrtc sdp │ │
│ └──────────────────┘ │
└───────────────────────┘
╔════════════════════════════════════════════════╗
║ ║
║B] Sending connection establishment info ║
║ ║
╚════════════════════════════════════════════════╝
┌───────────────┐
│ Matrix │
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
┌─────────────────┐ │ ┌───────────────────────────┐ ┌─────────────────┐
│ Caller │ │ Signaling Room │ │ │ Callee │
└─────────────────┘ │ ├───────────────────────────┤ └─────────────────┘
│ ┌────────────────────┐ │ │
│ │ │ m.call.invite │ │
┌─────────────────┐ │ │ mx event │ │ │ ┌─────────────────┐
│ │ ┌────┐ │ │ └────────────────────┘ │ │ │
│ │ │ 3 │ │ ┌────────────────────┐ │ │ │ │
│ │──────┴────┴───────┼──────────────────┼─▶│ m.call.candidates │ │ │ │
│ Riot.im │ │ │ mx event │ │ │ │ Riot.im │
│ App │ │ │ └────────────────────┘ │ │ App │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
└─────────────────┘ │ │ │ └─────────────────┘
▲ │ │ │
├────┐ │ └───────────────────────────┘
│ 2 │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
┌───────┴────┴────┐ ┌─────────────────┐
│ │ │ │
│ │ │ │
│ WebRtc │ ┌───────────────┐ │ WebRtc │
│ │ │ Stun / Turn │ │ │
│ │ ├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ │
│ │ │ │ │
└─────────────────┘ │ └─────────────────┘
▲ │
│ │
└──────────┬────┬───────────▶ │
┌───────────────┐ │ 1 │ │
│ │ └────┘ │
│ Network Stack │ │
│ │ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
│ │
└───────────────┘
┌────┐
│ 1 │ The WebRtc layer gathers information on how it can be reach by the other peer directly (Ice candidates)
└────┘
┌──────────────────────────────────────────────────────────────────┐
│candidate:1 1 tcp 1518149375 127.0.0.1 35990 typ host │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│candidate:2 1 UDP 2130706431 192.168.1.102 1816 typ host │
└──────────────────────────────────────────────────────────────────┘
┌────┐
│ 2 │ The WebRTC layer notifies the App layer when it finds new Ice Candidates
└────┘
┌────┐ The app layer, takes the ice candidates, encapsulate them in one or several matrix event adds the callId and
│ 3 │ send it to the other user via the room
└────┘
┌──────────────┐
│ mx event │
├──────────────┴────────────────────────┐
│ type: m.call.candidates │
│ │
│ +CallId │
│ │
│ ┌──────────────────┐ │
│ │ice candidate sdp │ │
│ └──────────────────┘ │
│ ┌──────────────────┐ │
│ │ice candidate sdp │ │
│ └──────────────────┘ │
│ ┌──────────────────┐ │
│ │ice candidate sdp │ │
│ └──────────────────┘ │
└───────────────────────────────────────┘
╔════════════════════════════════════════════════╗
║ ║
║C] Receiving a call offer ║
║ ║
╚════════════════════════════════════════════════╝
┌───────────────┐
│ Matrix │
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ ┌─────────────────┐
│ │ Callee │
┌─────────────────┐ │ ┌───────────────────────────┐ └─────────────────┘
│ Caller │ │ Signaling Room │ │
└─────────────────┘ │ ├───────────────────────────┤
│ ┌────────────────────┐ │ │ ┌─────────────────┐
│ │ │ m.call.invite │───┼────────────────────────────┬────┬───▶│ │
┌─────────────────┐ │ │ mx event │ │ │ │ 1 │ │ │
│ │ │ │ └────────────────────┘ │ └────┘ │ │
│ │ │ ┌────────────────────┐ │ │ │ Riot.im │
│ │ │ │ │ m.call.candidates │ │ │ App │
│ Riot.im │ │ │ mx event │ │ │ │ │
│ App │ │ │ └────────────────────┘ │ │ │
│ │ │ ┌────────────────────┐◀──┼─────────────────┼───┬────┬───────────┤ │
│ │◀──────────────────┼──────────────────┼──│ m.call.answer │ │ │ 4 │ └──┬──────────────┘
│ │ │ │ mx event │ │ │ └────┘ ├────┐ ▲
└────┬────────────┘ │ │ └────────────────────┘ │ │ 2 │ ├────┐
│ │ │ │ ├────┘ │ 3 │
│ │ └───────────────────────────┘ ┌──▼─────────┴────┤
┌────▼────────────┐ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ │
│ │ │ │
│ │ │ WebRtc │
│ WebRtc │ │ ┌──┴─────────────────┐
│ │ │ │ caller offer │
┌──────────┴─────────┐ │ │ └──┬─────────────────┘
│ callee answer │ │ └─────────────────┘
└────────────────────┴───────┘
┌────┐
│ 1 │ Bob receives a call.invite event in a room, then creates a WebRTC peer connection object
└────┘
┌────┐
│ 2 │ The encapsulated call offer sdp from the mx event is transmitted to WebRTC
└────┘
┌────┐
│ 3 │ WebRTC then creates a call answer for the offer and send it back to app layer
└────┘
┌────┐ The app layer, takes the webrtc answer, encapsulate it in a matrix event adds a callId and send it to the
│ 3 │ other user via the room
└────┘
┌──────────────┐
│ mx event │
├──────────────┴────────┐
│ type: m.call.answer │
│ + callId │
│ │
│ ┌──────────────────┐ │
│ │ webrtc sdp │ │
│ └──────────────────┘ │
└───────────────────────┘
╔════════════════════════════════════════════════╗
║ ║
║D] Callee sends connection establishment info ║
║ ║
╚════════════════════════════════════════════════╝
┌───────────────┐
│ Matrix │
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
┌─────────────────┐ │ ┌───────────────────────────┐ ┌─────────────────┐
│ Caller │ │ Signaling Room │ │ │ Callee │
└─────────────────┘ │ ├───────────────────────────┤ └─────────────────┘
│ ┌────────────────────┐ │ │
│ │ │ m.call.invite │ │
┌─────────────────┐ │ │ mx event │ │ │ ┌─────────────────┐
│ │ │ │ └────────────────────┘ │ │ │
│ │ │ ┌────────────────────┐ │ │ │ │
│ │ │ │ │ m.call.candidates │ │ │ │
│ Riot.im │ │ │ mx event │ │ │ │ Riot.im │
│ App │ │ │ └────────────────────┘ │ ┌────┐ │ App │
│ │ │ ┌────────────────────┐ │ │ │ 3 │ │ │
│ │◀──────────────────┼┐ │ │ m.call.answer │ │ ┌───────┴────┴────────│ │
│ │ │ │ │ mx event │ │ ││ │ │
└─────────────────┘ ││ │ └────────────────────┘ │ │ └─────────────────┘
│ │ │ ┌────────────────────┐ │ ││ ▲
│ │└─────────────────┼──│ m.call.candidates │ │ │ ├────┐
▼ │ │ mx event │◀──┼────────────────┘│ │ 2 │
┌─────────────────┐ │ │ └────────────────────┘ │ ┌────┴────┴───────┐
│ │ └───────────────────────────┘ │ │ │
│ │ │ │ │
│ WebRtc │ │ │ WebRtc │
│ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ ┌───┴────────────────┐
│ │ │ │ caller offer │
┌────────┴───────────┐ │ │ └───┬────────────────┘
│ callee answer ├─────┘ ┌───────────────┐ └─────────────────┘
├────────────────────┤ │ Stun / Turn │ ▲
│ callee ice │ ├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ┌────┐ │
│ candidates │ │ │ 1 │ │
└────────────────────┘ │ ├────┴──┴───────┐
│ │ │
│ │ Network Stack │
│◀─────────────────────┤ │
│ │ │
│ └───────────────┘
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
┌────┐
│ 1 │ The WebRtc layer gathers information on how it can be reach by the other peer directly (Ice candidates)
└────┘
┌──────────────────────────────────────────────────────────────────┐
│candidate:1 1 tcp 1518149375 127.0.0.1 35990 typ host │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│candidate:2 1 UDP 2130706431 192.168.1.102 1816 typ host │
└──────────────────────────────────────────────────────────────────┘
┌────┐
│ 2 │ The WebRTC layer notifies the App layer when it finds new Ice Candidates
└────┘
┌────┐ The app layer, takes the ice candidates, encapsulate them in one or several matrix event adds the callId and
│ 3 │ send it to the other user via the room
└────┘
┌──────────────┐
│ mx event │
├──────────────┴────────────────────────┐
│ type: m.call.candidates │
│ │
│ +CallId │
│ │
│ ┌──────────────────┐ │
│ │ice candidate sdp │ │
│ └──────────────────┘ │
│ ┌──────────────────┐ │
│ │ice candidate sdp │ │
│ └──────────────────┘ │
│ ┌──────────────────┐ │
│ │ice candidate sdp │ │
│ └──────────────────┘ │
└───────────────────────────────────────┘
╔════════════════════════════════════════════════╗
║ ║
║D] Caller Callee connection ║
║ ║
╚════════════════════════════════════════════════╝
┌───────────────┐
┌─────────────────┐ │ Matrix │ ┌─────────────────┐
│ Caller │ ├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ Callee │
└─────────────────┘ │ └─────────────────┘
┌─────────────────┐ │ ┌─────────────────┐
│ │ │ │ │
│ │ │ │ │
│ │ │ │ │
│ Riot.im │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │ Riot.im │
│ App │ │ App │
│ │ │ │
│ │ │ │
│ │ │ │
└─────────────────┘ └─────────────────┘
┌───────────────┐
│ Internet │
├───────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
┌─────────────────┐ │ ┌─────────────────┐
│ │ │ │ │
│ ├───────────────────────────────────────────────────────────────────────────────────┴─────────────────────┤ │
│ WebRtc │█████████████████████████████████████████████████████████████████████████████████████████████████████████│ WebRtc │
┌─────────────┴──────┐ ├────────────────────────────────────────┬──────────────────────────┬───────────────┬─────────────────────┤ ┌─────┴──────────────┐
│ callee answer │ │ │ │ Video / Audio Stream │ │ │ caller offer │
├────────────────────┤ │ └──────────────────────────┘ │ │ ├────────────────────┤
│ callee ice ├──────────┘ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ └───────────┤ caller ice │
│ candidates │ │ candidates │
└────────────────────┘ └────────────────────┘
┌─────────────────────────────────────────────────────┐
│ │░
│ If connection is impossible (firewall), and a turn │░
│server is available, connection could happen through │░
│ a relay │░
│ │░
└─────────────────────────────────────────────────────┘░
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
┌───────────────┐
│ Internet │
└─┬─────────────┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
┌─────────────────┐ │ ┌─────────────────┐
│ │ │ ┌─────────────────────────┐ │ │
│ ├───────────────────────────────────────┐│ │ │ │ │
│ WebRtc │███████████████████████████████████████││ │ │ WebRtc │
│ ├───────────────────────────────────────┘│ │ │ │ │
│ │ ┌────────┴─────────────────┐ │ Relay │┌─────────────────────────────────────┤ │
┌───────────────┴────┐ │ │ Video / Audio Stream │ │ ││█████████████████████████████████████│ ┌───────┴────────────┐
│ callee answer ├────────────┘ └────────┬─────────────────┘ │ │└─────────────────────────────────────┴─────────┤ caller offer │
├────────────────────┤ │ │ │ ├────────────────────┤
│ callee ice │ │ │ │ │ caller ice │
│ candidates │ └─────────────────────────┘ │ │ candidates │
└────────────────────┘ │ └────────────────────┘
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─

View File

@@ -6,7 +6,7 @@ android {
compileSdkVersion 29
defaultConfig {
minSdkVersion 16
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"

View File

@@ -16,6 +16,7 @@
package im.vector.matrix.rx
import im.vector.matrix.android.api.query.QueryStringValue
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.members.RoomMemberQueryParams
@@ -61,7 +62,7 @@ class RxRoom(private val room: Room) {
}
}
fun liveStateEvent(eventType: String, stateKey: String): Observable<Optional<Event>> {
fun liveStateEvent(eventType: String, stateKey: QueryStringValue): Observable<Optional<Event>> {
return room.getStateEventLive(eventType, stateKey).asObservable()
.startWithCallable {
room.getStateEvent(eventType, stateKey).toOptional()

View File

@@ -17,16 +17,19 @@
package im.vector.matrix.rx
import androidx.paging.PagedList
import im.vector.matrix.android.api.query.QueryStringValue
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.crypto.crosssigning.MXCrossSigningInfo
import im.vector.matrix.android.api.session.group.GroupSummaryQueryParams
import im.vector.matrix.android.api.session.group.model.GroupSummary
import im.vector.matrix.android.api.session.identity.ThreePid
import im.vector.matrix.android.api.session.pushers.Pusher
import im.vector.matrix.android.api.session.room.RoomSummaryQueryParams
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.user.model.User
import im.vector.matrix.android.api.session.widgets.model.Widget
import im.vector.matrix.android.api.util.JsonDict
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.api.util.toOptional
@@ -53,10 +56,10 @@ class RxSession(private val session: Session) {
}
}
fun liveBreadcrumbs(): Observable<List<RoomSummary>> {
return session.getBreadcrumbsLive().asObservable()
fun liveBreadcrumbs(queryParams: RoomSummaryQueryParams): Observable<List<RoomSummary>> {
return session.getBreadcrumbsLive(queryParams).asObservable()
.startWithCallable {
session.getBreadcrumbs()
session.getBreadcrumbs(queryParams)
}
}
@@ -94,6 +97,11 @@ class RxSession(private val session: Session) {
return session.getPagedUsersLive(filter, excludedUserIds).asObservable()
}
fun liveThreePIds(refreshData: Boolean): Observable<List<ThreePid>> {
return session.getThreePidsLive(refreshData).asObservable()
.startWithCallable { session.getThreePids() }
}
fun createRoom(roomParams: CreateRoomParams): Single<String> = singleBuilder {
session.createRoom(roomParams, it)
}
@@ -145,6 +153,18 @@ class RxSession(private val session: Session) {
session.getAccountDataEvents(types)
}
}
fun liveRoomWidgets(
roomId: String,
widgetId: QueryStringValue,
widgetTypes: Set<String>? = null,
excludedTypes: Set<String>? = null
): Observable<List<Widget>> {
return session.widgetService().getRoomWidgetsLive(roomId, widgetId, widgetTypes, excludedTypes).asObservable()
.startWithCallable {
session.widgetService().getRoomWidgets(roomId, widgetId, widgetTypes, excludedTypes)
}
}
}
fun Session.rx(): RxSession {

View File

@@ -23,7 +23,7 @@ android {
testOptions.unitTests.includeAndroidResources = true
defaultConfig {
minSdkVersion 16
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "0.0.1"
@@ -35,6 +35,10 @@ android {
resValue "string", "git_sdk_revision", "\"${gitRevision()}\""
resValue "string", "git_sdk_revision_unix_date", "\"${gitRevisionUnixDate()}\""
resValue "string", "git_sdk_revision_date", "\"${gitRevisionDate()}\""
defaultConfig {
consumerProguardFiles 'proguard-rules.pro'
}
}
buildTypes {
@@ -49,9 +53,6 @@ android {
release {
buildConfigField "boolean", "LOG_PRIVATE_DATA", "false"
buildConfigField "okhttp3.logging.HttpLoggingInterceptor.Level", "OKHTTP_LOGGING_LEVEL", "okhttp3.logging.HttpLoggingInterceptor.Level.NONE"
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
@@ -158,6 +159,13 @@ dependencies {
// Bus
implementation 'org.greenrobot:eventbus:3.1.1'
// Phone number https://github.com/google/libphonenumber
implementation 'com.googlecode.libphonenumber:libphonenumber:8.10.23'
// Web RTC
// TODO meant for development purposes only. See http://webrtc.github.io/webrtc-org/native-code/android/
implementation 'org.webrtc:google-webrtc:1.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'

View File

@@ -19,3 +19,45 @@
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
### EVENT BUS ###
-keepattributes *Annotation*
-keepclassmembers class * {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
### MOSHI ###
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**
-keepclasseswithmembers class * {
@com.squareup.moshi.* <methods>;
}
-keep @com.squareup.moshi.JsonQualifier interface *
# Enum field names are used by the integrated EnumJsonAdapter.
# values() is synthesized by the Kotlin compiler and is used by EnumJsonAdapter indirectly
# Annotate enums with @JsonClass(generateAdapter = false) to use them with Moshi.
-keepclassmembers @com.squareup.moshi.JsonClass class * extends java.lang.Enum {
<fields>;
**[] values();
}
-keep class kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoaderImpl
-keepclassmembers class kotlin.Metadata {
public <methods>;
}
### OKHTTP for Android Studio ###
-keep class okhttp3.Headers { *; }
-keep interface okhttp3.Interceptor.* { *; }
### OLM JNI ###
-keep class org.matrix.olm.** { *; }

View File

@@ -28,10 +28,10 @@ import im.vector.matrix.android.api.auth.data.LoginFlowResult
import im.vector.matrix.android.api.auth.registration.RegistrationResult
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.LocalEcho
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.api.session.room.Room
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
@@ -88,7 +88,8 @@ class CommonTestHelper(context: Context) {
fun syncSession(session: Session) {
val lock = CountDownLatch(1)
session.open()
GlobalScope.launch(Dispatchers.Main) { session.open() }
session.startSync(true)
val syncLiveData = runBlocking(Dispatchers.Main) {
@@ -116,7 +117,7 @@ class CommonTestHelper(context: Context) {
*/
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int): List<TimelineEvent> {
val sentEvents = ArrayList<TimelineEvent>(nbOfMessages)
val latch = CountDownLatch(nbOfMessages)
val latch = CountDownLatch(1)
val timelineListener = object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
}
@@ -127,7 +128,7 @@ class CommonTestHelper(context: Context) {
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
val newMessages = snapshot
.filter { LocalEcho.isLocalEchoId(it.eventId).not() }
.filter { it.root.sendState == SendState.SYNCED }
.filter { it.root.getClearType() == EventType.MESSAGE }
.filter { it.root.getClearContent().toModel<MessageContent>()?.body?.startsWith(message) == true }
@@ -143,7 +144,8 @@ class CommonTestHelper(context: Context) {
for (i in 0 until nbOfMessages) {
room.sendTextMessage(message + " #" + (i + 1))
}
await(latch)
// Wait 3 second more per message
await(latch, timeout = TestConstants.timeOutMillis + 3_000L * nbOfMessages)
timeline.removeListener(timelineListener)
timeline.dispose()
@@ -291,6 +293,24 @@ class CommonTestHelper(context: Context) {
return requestFailure!!
}
fun createEventListener(latch: CountDownLatch, predicate: (List<TimelineEvent>) -> Boolean): Timeline.Listener {
return object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
// noop
}
override fun onNewTimelineEvents(eventIds: List<String>) {
// noop
}
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
if (predicate(snapshot)) {
latch.countDown()
}
}
}
}
/**
* Await for a latch and ensure the result is true
*
@@ -349,3 +369,13 @@ class CommonTestHelper(context: Context) {
session.close()
}
}
fun List<TimelineEvent>.checkSendOrder(baseTextMessage: String, numberOfMessages: Int, startIndex: Int): Boolean {
return drop(startIndex)
.take(numberOfMessages)
.foldRightIndexed(true) { index, timelineEvent, acc ->
val body = timelineEvent.root.content.toModel<MessageContent>()?.body
val currentMessageSuffix = numberOfMessages - index
acc && (body == null || body.startsWith(baseTextMessage) && body.endsWith("#$currentMessageSuffix"))
}
}

View File

@@ -53,17 +53,19 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
/**
* @return alice session
*/
fun doE2ETestWithAliceInARoom(): CryptoTestData {
fun doE2ETestWithAliceInARoom(encryptedRoom: Boolean = true): CryptoTestData {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, defaultSessionParams)
val roomId = mTestHelper.doSync<String> {
aliceSession.createRoom(CreateRoomParams(name = "MyRoom"), it)
}
val room = aliceSession.getRoom(roomId)!!
if (encryptedRoom) {
val room = aliceSession.getRoom(roomId)!!
mTestHelper.doSync<Unit> {
room.enableEncryption(callback = it)
mTestHelper.doSync<Unit> {
room.enableEncryption(callback = it)
}
}
return CryptoTestData(aliceSession, roomId)
@@ -72,8 +74,8 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
/**
* @return alice and bob sessions
*/
fun doE2ETestWithAliceAndBobInARoom(): CryptoTestData {
val cryptoTestData = doE2ETestWithAliceInARoom()
fun doE2ETestWithAliceAndBobInARoom(encryptedRoom: Boolean = true): CryptoTestData {
val cryptoTestData = doE2ETestWithAliceInARoom(encryptedRoom)
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
@@ -246,7 +248,7 @@ class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
assertNotNull(eventWireContent.get("session_id"))
assertNotNull(eventWireContent.get("sender_key"))
assertEquals(senderSession.sessionParams.credentials.deviceId, eventWireContent.get("device_id"))
assertEquals(senderSession.sessionParams.deviceId, eventWireContent.get("device_id"))
assertNotNull(event.eventId)
assertEquals(roomId, event.roomId)

View File

@@ -122,7 +122,7 @@ class XSigningTest : InstrumentedTest {
// We will want to test that in alice POV, this new device would be trusted by cross signing
val bobSession2 = mTestHelper.logIntoAccount(bobUserId, SessionTestParams(true))
val bobSecondDeviceId = bobSession2.sessionParams.credentials.deviceId!!
val bobSecondDeviceId = bobSession2.sessionParams.deviceId!!
// Check that bob first session sees the new login
val data = mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {

View File

@@ -90,7 +90,7 @@ class KeyShareTests : InstrumentedTest {
} catch (failure: Throwable) {
}
val outgoingRequestBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequest()
val outgoingRequestsBefore = aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
// Try to request
aliceSession2.cryptoService().requestRoomKeyForEvent(receivedEvent.root)
@@ -100,10 +100,10 @@ class KeyShareTests : InstrumentedTest {
var outGoingRequestId: String? = null
mTestHelper.retryPeriodicallyWithLatch(waitLatch) {
aliceSession2.cryptoService().getOutgoingRoomKeyRequest()
aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
.filter { req ->
// filter out request that was known before
!outgoingRequestBefore.any { req.requestId == it.requestId }
!outgoingRequestsBefore.any { req.requestId == it.requestId }
}
.let {
val outgoing = it.firstOrNull { it.sessionId == eventMegolmSessionId }
@@ -115,10 +115,10 @@ class KeyShareTests : InstrumentedTest {
Log.v("TEST", "=======> Outgoing requet Id is $outGoingRequestId")
val outgoingRequestAfter = aliceSession2.cryptoService().getOutgoingRoomKeyRequest()
val outgoingRequestAfter = aliceSession2.cryptoService().getOutgoingRoomKeyRequests()
// We should have a new request
Assert.assertTrue(outgoingRequestAfter.size > outgoingRequestBefore.size)
Assert.assertTrue(outgoingRequestAfter.size > outgoingRequestsBefore.size)
Assert.assertNotNull(outgoingRequestAfter.first { it.sessionId == eventMegolmSessionId })
// The first session should see an incoming request
@@ -126,7 +126,7 @@ class KeyShareTests : InstrumentedTest {
mTestHelper.waitWithLatch { latch ->
mTestHelper.retryPeriodicallyWithLatch(latch) {
// DEBUG LOGS
aliceSession.cryptoService().getIncomingRoomKeyRequest().let {
aliceSession.cryptoService().getIncomingRoomKeyRequests().let {
Log.v("TEST", "Incoming request Session 1 (looking for $outGoingRequestId)")
Log.v("TEST", "=========================")
it.forEach { keyRequest ->
@@ -135,7 +135,7 @@ class KeyShareTests : InstrumentedTest {
Log.v("TEST", "=========================")
}
val incoming = aliceSession.cryptoService().getIncomingRoomKeyRequest().firstOrNull { it.requestId == outGoingRequestId }
val incoming = aliceSession.cryptoService().getIncomingRoomKeyRequests().firstOrNull { it.requestId == outGoingRequestId }
incoming?.state == GossipingRequestState.REJECTED
}
}
@@ -148,14 +148,14 @@ class KeyShareTests : InstrumentedTest {
// Mark the device as trusted
aliceSession.cryptoService().setDeviceVerification(DeviceTrustLevel(crossSigningVerified = false, locallyVerified = true), aliceSession.myUserId,
aliceSession2.sessionParams.credentials.deviceId ?: "")
aliceSession2.sessionParams.deviceId ?: "")
// Re request
aliceSession2.cryptoService().reRequestRoomKeyForEvent(receivedEvent.root)
mTestHelper.waitWithLatch { latch ->
mTestHelper.retryPeriodicallyWithLatch(latch) {
aliceSession.cryptoService().getIncomingRoomKeyRequest().let {
aliceSession.cryptoService().getIncomingRoomKeyRequests().let {
Log.v("TEST", "Incoming request Session 1")
Log.v("TEST", "=========================")
it.forEach {
@@ -171,7 +171,7 @@ class KeyShareTests : InstrumentedTest {
Thread.sleep(6_000)
mTestHelper.waitWithLatch { latch ->
mTestHelper.retryPeriodicallyWithLatch(latch) {
aliceSession2.cryptoService().getOutgoingRoomKeyRequest().let {
aliceSession2.cryptoService().getOutgoingRoomKeyRequests().let {
it.any { it.requestBody?.sessionId == eventMegolmSessionId && it.state == OutgoingGossipingRequestState.CANCELLED }
}
}
@@ -252,13 +252,13 @@ class KeyShareTests : InstrumentedTest {
}
})
val txId: String = "m.testVerif12"
aliceVerificationService2.beginKeyVerification(VerificationMethod.SAS, aliceSession1.myUserId, aliceSession1.sessionParams.credentials.deviceId
val txId = "m.testVerif12"
aliceVerificationService2.beginKeyVerification(VerificationMethod.SAS, aliceSession1.myUserId, aliceSession1.sessionParams.deviceId
?: "", txId)
mTestHelper.waitWithLatch { latch ->
mTestHelper.retryPeriodicallyWithLatch(latch) {
aliceSession1.cryptoService().getDeviceInfo(aliceSession1.myUserId, aliceSession2.sessionParams.credentials.deviceId ?: "")?.isVerified == true
aliceSession1.cryptoService().getDeviceInfo(aliceSession1.myUserId, aliceSession2.sessionParams.deviceId ?: "")?.isVerified == true
}
}

View File

@@ -835,7 +835,7 @@ class KeysBackupTest : InstrumentedTest {
assertTrue(signature.valid)
assertNotNull(signature.device)
assertEquals(cryptoTestData.firstSession.cryptoService().getMyDevice().deviceId, signature.deviceId)
assertEquals(signature.device!!.deviceId, cryptoTestData.firstSession.sessionParams.credentials.deviceId)
assertEquals(signature.device!!.deviceId, cryptoTestData.firstSession.sessionParams.deviceId)
stateObserver.stopAndCheckStates(null)
cryptoTestData.cleanUp(mTestHelper)
@@ -997,7 +997,7 @@ class KeysBackupTest : InstrumentedTest {
keysBackup.backupAllGroupSessions(null, it)
}
val oldDeviceId = cryptoTestData.firstSession.sessionParams.credentials.deviceId!!
val oldDeviceId = cryptoTestData.firstSession.sessionParams.deviceId!!
val oldKeyBackupVersion = keysBackup.currentBackupVersion
val aliceUserId = cryptoTestData.firstSession.myUserId

View File

@@ -468,14 +468,19 @@ class SASTest : InstrumentedTest {
val aliceSASLatch = CountDownLatch(1)
val aliceListener = object : VerificationService.Listener {
var matchOnce = true
override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as OutgoingSasVerificationTransaction).uxState
Log.v("TEST", "== aliceState ${uxState.name}")
when (uxState) {
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
tx.userHasVerifiedShortCode()
}
OutgoingSasVerificationTransaction.UxState.VERIFIED -> {
aliceSASLatch.countDown()
if (matchOnce) {
matchOnce = false
aliceSASLatch.countDown()
}
}
else -> Unit
}
@@ -485,14 +490,23 @@ class SASTest : InstrumentedTest {
val bobSASLatch = CountDownLatch(1)
val bobListener = object : VerificationService.Listener {
var acceptOnce = true
var matchOnce = true
override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as IncomingSasVerificationTransaction).uxState
Log.v("TEST", "== bobState ${uxState.name}")
when (uxState) {
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
tx.performAccept()
if (acceptOnce) {
acceptOnce = false
tx.performAccept()
}
}
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
tx.userHasVerifiedShortCode()
if (matchOnce) {
matchOnce = false
tx.userHasVerifiedShortCode()
}
}
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
bobSASLatch.countDown()
@@ -579,7 +593,7 @@ class SASTest : InstrumentedTest {
requestID!!,
cryptoTestData.roomId,
bobSession.myUserId,
bobSession.sessionParams.credentials.deviceId!!,
bobSession.sessionParams.deviceId!!,
null)
bobVerificationService.beginKeyVerificationInDMs(
@@ -587,7 +601,7 @@ class SASTest : InstrumentedTest {
requestID!!,
cryptoTestData.roomId,
aliceSession.myUserId,
aliceSession.sessionParams.credentials.deviceId!!,
aliceSession.sessionParams.deviceId!!,
null)
// we should reach SHOW SAS on both

View File

@@ -0,0 +1,278 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.session.room.send
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import org.commonmark.parser.Parser
import org.commonmark.renderer.html.HtmlRenderer
import org.commonmark.renderer.text.TextContentRenderer
import org.junit.Assert.assertEquals
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
/**
* It will not be possible to test all combinations. For the moment I add a few tests, then, depending on the problem discovered in the wild,
* we can add more tests to cover the edge cases.
* Some tests are suffixed with `_not_passing`, maybe one day we will fix them...
* Riot-Web should be used as a reference for expected results, but not always. Especially Riot-Web add lots of `\n` in the
* formatted body, which is quite useless.
* Also Riot-Web does not provide plain text body when formatted text is provided. The body contains what the user has entered.
* See https://matrix.org/docs/spec/client_server/latest#m-room-message-msgtypes
*/
@Suppress("SpellCheckingInspection")
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class MarkdownParserTest : InstrumentedTest {
/**
* Create the same parser than in the RoomModule
*/
private val markdownParser = MarkdownParser(
Parser.builder().build(),
HtmlRenderer.builder().build(),
TextContentRenderer.builder().build()
)
@Test
fun parseNoMarkdown() {
testIdentity("")
testIdentity("a")
testIdentity("1")
testIdentity("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et " +
"dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea com" +
"modo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pari" +
"atur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.")
}
@Test
fun parseSpaces() {
testIdentity(" ")
testIdentity(" ")
testIdentity("\n")
}
@Test
fun parseNewLines() {
testIdentity("line1\nline2")
testIdentity("line1\nline2\nline3")
}
@Test
fun parseBold() {
testType(
name = "bold",
markdownPattern = "**",
htmlExpectedTag = "strong"
)
}
@Test
fun parseItalic() {
testType(
name = "italic",
markdownPattern = "*",
htmlExpectedTag = "em"
)
}
@Test
fun parseItalic2() {
// Riot-Web format
"_italic_".let { markdownParser.parse(it) }.expect("italic", "<em>italic</em>")
}
/**
* Note: the test is not passing, it does not work on Riot-Web neither
*/
@Test
fun parseStrike_not_passing() {
testType(
name = "strike",
markdownPattern = "~~",
htmlExpectedTag = "del"
)
}
@Test
fun parseCode() {
testType(
name = "code",
markdownPattern = "`",
htmlExpectedTag = "code",
plainTextPrefix = "\"",
plainTextSuffix = "\""
)
}
@Test
fun parseCode2() {
testType(
name = "code",
markdownPattern = "``",
htmlExpectedTag = "code",
plainTextPrefix = "\"",
plainTextSuffix = "\""
)
}
@Test
fun parseCode3() {
testType(
name = "code",
markdownPattern = "```",
htmlExpectedTag = "code",
plainTextPrefix = "\"",
plainTextSuffix = "\""
)
}
@Test
fun parseUnorderedList() {
"- item1".let { markdownParser.parse(it).expect(it, "<ul><li>item1</li></ul>") }
"- item1\n- item2".let { markdownParser.parse(it).expect(it, "<ul><li>item1</li><li>item2</li></ul>") }
}
@Test
fun parseOrderedList() {
"1. item1".let { markdownParser.parse(it).expect(it, "<ol><li>item1</li></ol>") }
"1. item1\n2. item2".let { markdownParser.parse(it).expect(it, "<ol><li>item1</li><li>item2</li></ol>") }
}
@Test
fun parseHorizontalLine() {
"---".let { markdownParser.parse(it) }.expect("***", "<hr />")
}
@Test
fun parseH2AndContent() {
"a\n---\nb".let { markdownParser.parse(it) }.expect("a\nb", "<h2>a</h2><p>b</p>")
}
@Test
fun parseQuote() {
"> quoted".let { markdownParser.parse(it) }.expect("«quoted»", "<blockquote><p>quoted</p></blockquote>")
}
@Test
fun parseQuote_not_passing() {
"> quoted\nline2".let { markdownParser.parse(it) }.expect("«quoted\nline2»", "<blockquote><p>quoted<br/>line2</p></blockquote>")
}
@Test
fun parseBoldItalic() {
"*italic* **bold**".let { markdownParser.parse(it) }.expect("italic bold", "<em>italic</em> <strong>bold</strong>")
"**bold** *italic*".let { markdownParser.parse(it) }.expect("bold italic", "<strong>bold</strong> <em>italic</em>")
}
@Test
fun parseHead() {
"# head1".let { markdownParser.parse(it) }.expect("head1", "<h1>head1</h1>")
"## head2".let { markdownParser.parse(it) }.expect("head2", "<h2>head2</h2>")
"### head3".let { markdownParser.parse(it) }.expect("head3", "<h3>head3</h3>")
"#### head4".let { markdownParser.parse(it) }.expect("head4", "<h4>head4</h4>")
"##### head5".let { markdownParser.parse(it) }.expect("head5", "<h5>head5</h5>")
"###### head6".let { markdownParser.parse(it) }.expect("head6", "<h6>head6</h6>")
}
@Test
fun parseHeads() {
"# head1\n# head2".let { markdownParser.parse(it) }.expect("head1\nhead2", "<h1>head1</h1><h1>head2</h1>")
}
@Test
fun parseBoldNewLines_not_passing() {
"**bold**\nline2".let { markdownParser.parse(it) }.expect("bold\nline2", "<strong>bold</strong><br />line2")
}
@Test
fun parseLinks() {
"[link](target)".let { markdownParser.parse(it) }.expect(""""link" (target)""", """<a href="target">link</a>""")
}
@Test
fun parseParagraph() {
"# head\ncontent".let { markdownParser.parse(it) }.expect("head\ncontent", "<h1>head</h1><p>content</p>")
}
private fun testIdentity(text: String) {
markdownParser.parse(text).expect(text, null)
}
private fun testType(name: String,
markdownPattern: String,
htmlExpectedTag: String,
plainTextPrefix: String = "",
plainTextSuffix: String = "") {
// Test simple case
"$markdownPattern$name$markdownPattern"
.let { markdownParser.parse(it) }
.expect(expectedText = "$plainTextPrefix$name$plainTextSuffix",
expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>")
// Test twice the same tag
"$markdownPattern$name$markdownPattern and $markdownPattern$name bis$markdownPattern"
.let { markdownParser.parse(it) }
.expect(expectedText = "$plainTextPrefix$name$plainTextSuffix and $plainTextPrefix$name bis$plainTextSuffix",
expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> and <$htmlExpectedTag>$name bis</$htmlExpectedTag>")
val textBefore = "a"
val textAfter = "b"
// With sticked text before
"$textBefore$markdownPattern$name$markdownPattern"
.let { markdownParser.parse(it) }
.expect(expectedText = "$textBefore$plainTextPrefix$name$plainTextSuffix",
expectedFormattedText = "$textBefore<$htmlExpectedTag>$name</$htmlExpectedTag>")
// With text before and space
"$textBefore $markdownPattern$name$markdownPattern"
.let { markdownParser.parse(it) }
.expect(expectedText = "$textBefore $plainTextPrefix$name$plainTextSuffix",
expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag>")
// With sticked text after
"$markdownPattern$name$markdownPattern$textAfter"
.let { markdownParser.parse(it) }
.expect(expectedText = "$plainTextPrefix$name$plainTextSuffix$textAfter",
expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter")
// With space and text after
"$markdownPattern$name$markdownPattern $textAfter"
.let { markdownParser.parse(it) }
.expect(expectedText = "$plainTextPrefix$name$plainTextSuffix $textAfter",
expectedFormattedText = "<$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter")
// With sticked text before and text after
"$textBefore$markdownPattern$name$markdownPattern$textAfter"
.let { markdownParser.parse(it) }
.expect(expectedText = "$textBefore$plainTextPrefix$name$plainTextSuffix$textAfter",
expectedFormattedText = "a<$htmlExpectedTag>$name</$htmlExpectedTag>$textAfter")
// With text before and after, with spaces
"$textBefore $markdownPattern$name$markdownPattern $textAfter"
.let { markdownParser.parse(it) }
.expect(expectedText = "$textBefore $plainTextPrefix$name$plainTextSuffix $textAfter",
expectedFormattedText = "$textBefore <$htmlExpectedTag>$name</$htmlExpectedTag> $textAfter")
}
private fun TextContent.expect(expectedText: String, expectedFormattedText: String?) {
assertEquals("TextContent are not identical", TextContent(expectedText, expectedFormattedText), this)
}
}

View File

@@ -0,0 +1,183 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.session.room.timeline
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.extensions.orFalse
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.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.common.checkSendOrder
import org.amshove.kluent.shouldBeFalse
import org.amshove.kluent.shouldBeTrue
import org.junit.Assert.assertTrue
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class TimelineBackToPreviousLastForwardTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
/**
* This test ensure that if we have a chunk in the timeline which is due to a sync, and we click to permalink of an
* even contained in a previous lastForward chunk, we will be able to go back to the live
*/
@Test
fun backToPreviousLastForwardTest() {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession!!
val aliceRoomId = cryptoTestData.roomId
aliceSession.cryptoService().setWarnOnUnknownDevices(false)
bobSession.cryptoService().setWarnOnUnknownDevices(false)
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!!
val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(30))
bobTimeline.start()
var roomCreationEventId: String? = null
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
roomCreationEventId = snapshot.lastOrNull()?.root?.eventId
// Ok, we have the 8 first messages of the initial sync (room creation and bob join event)
snapshot.size == 8
}
bobTimeline.addListener(eventsListener)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
}
// Bob stop to sync
bobSession.stopSync()
val messageRoot = "First messages from Alice"
// Alice sends 30 messages
commonTestHelper.sendTextMessage(
roomFromAlicePOV,
messageRoot,
30)
// Bob start to sync
bobSession.startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
// Ok, we have the 10 last messages from Alice.
snapshot.size == 10
&& snapshot.all { it.root.content.toModel<MessageContent>()?.body?.startsWith(messageRoot).orFalse() }
}
bobTimeline.addListener(eventsListener)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeTrue()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
}
// Bob navigate to the first event (room creation event), so inside the previous last forward chunk
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
// The event is in db, so it is fetch and auto pagination occurs, half of the number of events we have for this chunk (?)
snapshot.size == 4
}
bobTimeline.addListener(eventsListener)
// Restart the timeline to the first sent event, which is already in the database, so pagination should start automatically
assertTrue(roomFromBobPOV.getTimeLineEvent(roomCreationEventId!!) != null)
bobTimeline.restartWithEventId(roomCreationEventId)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeTrue()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()
}
// Bob scroll to the future
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
// Bob can see the first event of the room (so Back pagination has worked)
snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE
// 8 for room creation item, and 30 for the forward pagination
&& snapshot.size == 38
&& snapshot.checkSendOrder(messageRoot, 30, 0)
}
bobTimeline.addListener(eventsListener)
bobTimeline.paginate(Timeline.Direction.FORWARDS, 50)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()
}
bobTimeline.dispose()
cryptoTestData.cleanUp(commonTestHelper)
}
}

View File

@@ -0,0 +1,190 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.session.room.timeline
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.extensions.orFalse
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.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.common.checkSendOrder
import org.amshove.kluent.shouldBeFalse
import org.amshove.kluent.shouldBeTrue
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class TimelineForwardPaginationTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
/**
* This test ensure that if we click to permalink, we will be able to go back to the live
*/
@Test
fun forwardPaginationTest() {
val numberOfMessagesToSend = 90
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceInARoom(false)
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
aliceSession.cryptoService().setWarnOnUnknownDevices(false)
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
// Alice sends X messages
val message = "Message from Alice"
val sentMessages = commonTestHelper.sendTextMessage(
roomFromAlicePOV,
message,
numberOfMessagesToSend)
// Alice clear the cache
commonTestHelper.doSync<Unit> {
aliceSession.clearCache(it)
}
// And restarts the sync
aliceSession.startSync(true)
val aliceTimeline = roomFromAlicePOV.createTimeline(null, TimelineSettings(30))
aliceTimeline.start()
// Alice sees the 10 last message of the room, and can only navigate BACKWARD
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Alice timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root.content}")
}
// Ok, we have the 10 last messages of the initial sync
snapshot.size == 10
&& snapshot.all { it.root.content.toModel<MessageContent>()?.body?.startsWith(message).orFalse() }
}
// Open the timeline at last sent message
aliceTimeline.addListener(eventsListener)
commonTestHelper.await(lock)
aliceTimeline.removeAllListeners()
aliceTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeTrue()
aliceTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
}
// Alice navigates to the first message of the room, which is not in its database. A GET /context is performed
// Then she can paginate BACKWARD and FORWARD
run {
val lock = CountDownLatch(1)
val aliceEventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Alice timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root.content}")
}
// The event is not in db, so it is fetch alone
snapshot.size == 1
&& snapshot.all { it.root.content.toModel<MessageContent>()?.body?.startsWith("Message from Alice").orFalse() }
}
aliceTimeline.addListener(aliceEventsListener)
// Restart the timeline to the first sent event
aliceTimeline.restartWithEventId(sentMessages.last().eventId)
commonTestHelper.await(lock)
aliceTimeline.removeAllListeners()
aliceTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeTrue()
aliceTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeTrue()
}
// Alice paginates BACKWARD and FORWARD of 50 events each
// Then she can only navigate FORWARD
run {
val lock = CountDownLatch(1)
val aliceEventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Alice timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root.content}")
}
// Alice can see the first event of the room (so Back pagination has worked)
snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE
// 6 for room creation item (backward pagination), 1 for the context, and 50 for the forward pagination
&& snapshot.size == 6 + 1 + 50
}
aliceTimeline.addListener(aliceEventsListener)
// Restart the timeline to the first sent event
// We ask to load event backward and forward
aliceTimeline.paginate(Timeline.Direction.BACKWARDS, 50)
aliceTimeline.paginate(Timeline.Direction.FORWARDS, 50)
commonTestHelper.await(lock)
aliceTimeline.removeAllListeners()
aliceTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeTrue()
aliceTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()
}
// Alice paginates once again FORWARD for 50 events
// All the timeline is retrieved, she cannot paginate anymore in both direction
run {
val lock = CountDownLatch(1)
val aliceEventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Alice timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root.content}")
}
// 6 for room creation item (backward pagination),and numberOfMessagesToSend (all the message of the room)
snapshot.size == 6 + numberOfMessagesToSend
&& snapshot.checkSendOrder(message, numberOfMessagesToSend, 0)
}
aliceTimeline.addListener(aliceEventsListener)
// Ask for a forward pagination
aliceTimeline.paginate(Timeline.Direction.FORWARDS, 50)
commonTestHelper.await(lock)
aliceTimeline.removeAllListeners()
// The timeline is fully loaded
aliceTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
aliceTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()
}
aliceTimeline.dispose()
cryptoTestData.cleanUp(commonTestHelper)
}
}

View File

@@ -0,0 +1,241 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.session.room.timeline
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.extensions.orFalse
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.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.common.checkSendOrder
import org.amshove.kluent.shouldBeFalse
import org.amshove.kluent.shouldBeTrue
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
import timber.log.Timber
import java.util.concurrent.CountDownLatch
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class TimelinePreviousLastForwardTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
/**
* This test ensure that if we have a chunk in the timeline which is due to a sync, and we click to permalink, we will be able to go back to the live
*/
@Test
fun previousLastForwardTest() {
val cryptoTestData = cryptoTestHelper.doE2ETestWithAliceAndBobInARoom(false)
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession!!
val aliceRoomId = cryptoTestData.roomId
aliceSession.cryptoService().setWarnOnUnknownDevices(false)
bobSession.cryptoService().setWarnOnUnknownDevices(false)
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!!
val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(30))
bobTimeline.start()
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
// Ok, we have the 8 first messages of the initial sync (room creation and bob invite and join events)
snapshot.size == 8
}
bobTimeline.addListener(eventsListener)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
}
// Bob stop to sync
bobSession.stopSync()
val firstMessage = "First messages from Alice"
// Alice sends 30 messages
val firstMessageFromAliceId = commonTestHelper.sendTextMessage(
roomFromAlicePOV,
firstMessage,
30)
.last()
.eventId
// Bob start to sync
bobSession.startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
// Ok, we have the 10 last messages from Alice. This will be our future previous lastForward chunk
snapshot.size == 10
&& snapshot.all { it.root.content.toModel<MessageContent>()?.body?.startsWith(firstMessage).orFalse() }
}
bobTimeline.addListener(eventsListener)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeTrue()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
}
// Bob stop to sync
bobSession.stopSync()
val secondMessage = "Second messages from Alice"
// Alice sends again 30 messages
commonTestHelper.sendTextMessage(
roomFromAlicePOV,
secondMessage,
30)
// Bob start to sync
bobSession.startSync(true)
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
// Ok, we have the 10 last messages from Alice. This will be our future previous lastForward chunk
snapshot.size == 10
&& snapshot.all { it.root.content.toModel<MessageContent>()?.body?.startsWith(secondMessage).orFalse() }
}
bobTimeline.addListener(eventsListener)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeTrue()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
}
// Bob navigate to the first message sent from Alice
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
// The event is not in db, so it is fetch
snapshot.size == 1
}
bobTimeline.addListener(eventsListener)
// Restart the timeline to the first sent event, and paginate in both direction
bobTimeline.restartWithEventId(firstMessageFromAliceId)
bobTimeline.paginate(Timeline.Direction.BACKWARDS, 50)
bobTimeline.paginate(Timeline.Direction.FORWARDS, 50)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeTrue()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeTrue()
}
// Paginate in both direction
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
snapshot.size == 8 + 1 + 35
}
bobTimeline.addListener(eventsListener)
// Paginate in both direction
bobTimeline.paginate(Timeline.Direction.BACKWARDS, 50)
// Ensure the chunk in the middle is included in the next pagination
bobTimeline.paginate(Timeline.Direction.FORWARDS, 35)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeTrue()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()
}
// Bob scroll to the future, till the live
run {
val lock = CountDownLatch(1)
val eventsListener = commonTestHelper.createEventListener(lock) { snapshot ->
Timber.e("Bob timeline updated: with ${snapshot.size} events:")
snapshot.forEach {
Timber.w(" event ${it.root}")
}
// Bob can see the first event of the room (so Back pagination has worked)
snapshot.lastOrNull()?.root?.getClearType() == EventType.STATE_ROOM_CREATE
// 8 for room creation item 60 message from Alice
&& snapshot.size == 8 + 60
&& snapshot.checkSendOrder(secondMessage, 30, 0)
&& snapshot.checkSendOrder(firstMessage, 30, 30)
}
bobTimeline.addListener(eventsListener)
bobTimeline.paginate(Timeline.Direction.FORWARDS, 50)
commonTestHelper.await(lock)
bobTimeline.removeAllListeners()
bobTimeline.hasMoreToLoad(Timeline.Direction.FORWARDS).shouldBeFalse()
bobTimeline.hasMoreToLoad(Timeline.Direction.BACKWARDS).shouldBeFalse()
}
bobTimeline.dispose()
cryptoTestData.cleanUp(commonTestHelper)
}
}

View File

@@ -0,0 +1,54 @@
var android_widget_events = {};
var sendObjectMessageToRiotAndroid = function(parameters) {
Android.onWidgetEvent(JSON.stringify(parameters));
};
var onWidgetMessageToRiotAndroid = function(event) {
/* Use an internal "_id" field for matching onMessage events and requests
_id was originally used by the Modular API. Keep it */
if (!event.data._id) {
/* The Matrix Widget API v2 spec says:
"The requestId field should be unique and included in all requests" */
event.data._id = event.data.requestId;
}
/* Make sure to have one id */
if (!event.data._id) {
event.data._id = Date.now() + "-" + Math.random().toString(36);
}
console.log("onWidgetMessageToRiotAndroid " + event.data._id);
if (android_widget_events[event.data._id]) {
console.log("onWidgetMessageToRiotAndroid : already managed");
return;
}
if (!event.origin) {
event.origin = event.originalEvent.origin;
}
android_widget_events[event.data._id] = event;
console.log("onWidgetMessageToRiotAndroid : manage " + event.data);
sendObjectMessageToRiotAndroid({'event.data': event.data});
};
var sendResponseFromRiotAndroid = function(eventId, res) {
var event = android_widget_events[eventId];
console.log("sendResponseFromRiotAndroid to " + event.data.action + " for "+ eventId + ": " + JSON.stringify(res));
var data = JSON.parse(JSON.stringify(event.data));
data.response = res;
console.log("sendResponseFromRiotAndroid ---> " + data);
event.source.postMessage(data, event.origin);
android_widget_events[eventId] = true;
console.log("sendResponseFromRiotAndroid to done");
};
window.addEventListener('message', onWidgetMessageToRiotAndroid, false);

View File

@@ -23,7 +23,6 @@ import androidx.work.WorkManager
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.BuildConfig
import im.vector.matrix.android.api.auth.AuthenticationService
import im.vector.matrix.android.api.crypto.MXCryptoConfig
import im.vector.matrix.android.internal.SessionManager
import im.vector.matrix.android.internal.crypto.attachments.ElementToDecrypt
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
@@ -32,20 +31,10 @@ import im.vector.matrix.android.internal.network.UserAgentHolder
import im.vector.matrix.android.internal.util.BackgroundDetectionObserver
import org.matrix.olm.OlmManager
import java.io.InputStream
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import javax.inject.Inject
data class MatrixConfiguration(
val applicationFlavor: String = "Default-application-flavor",
val cryptoConfig: MXCryptoConfig = MXCryptoConfig()
) {
interface Provider {
fun providesMatrixConfiguration(): MatrixConfiguration
}
}
/**
* This is the main entry point to the matrix sdk.
* To get the singleton instance, use getInstance static method.

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api
import im.vector.matrix.android.api.crypto.MXCryptoConfig
import java.net.Proxy
data class MatrixConfiguration(
val applicationFlavor: String = "Default-application-flavor",
val cryptoConfig: MXCryptoConfig = MXCryptoConfig(),
val integrationUIUrl: String = "https://scalar.vector.im/",
val integrationRestUrl: String = "https://scalar.vector.im/api",
val integrationWidgetUrls: List<String> = listOf(
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
),
/**
* Optional proxy to connect to the matrix servers
* You can create one using for instance Proxy(proxyType, InetSocketAddress(hostname, port)
*/
val proxy: Proxy? = null
) {
/**
* Can be implemented by your Application class
*/
interface Provider {
fun providesMatrixConfiguration(): MatrixConfiguration
}
}

View File

@@ -20,7 +20,6 @@ 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.LoginFlowResult
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.auth.login.LoginWizard
import im.vector.matrix.android.api.auth.registration.RegistrationWizard
import im.vector.matrix.android.api.auth.wellknown.WellknownResult
@@ -37,6 +36,11 @@ interface AuthenticationService {
*/
fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResult>): Cancelable
/**
* Request the supported login flows for the corresponding sessionId.
*/
fun getLoginFlowOfSession(sessionId: String, callback: MatrixCallback<LoginFlowResult>): Cancelable
/**
* Return a LoginWizard, to login to the homeserver. The login flow has to be retrieved first.
*/
@@ -74,15 +78,6 @@ interface AuthenticationService {
*/
fun getLastAuthenticatedSession(): Session?
/**
* Get an authenticated session. You should at least call authenticate one time before.
* If you logout, this session will no longer be valid.
*
* @param sessionParams the sessionParams to open with.
* @return the associated session if any, or null
*/
fun getSession(sessionParams: SessionParams): Session?
/**
* Create a session after a SSO successful login
*/

View File

@@ -32,6 +32,6 @@ const val REGISTER_FALLBACK_PATH = "/_matrix/static/client/register/"
* Path to use when the client want to connect using SSO
* Ref: https://matrix.org/docs/spec/client_server/latest#sso-client-login
*/
const val SSO_FALLBACK_PATH = "/_matrix/client/r0/login/sso/redirect"
const val SSO_REDIRECT_PATH = "/_matrix/client/r0/login/sso/redirect"
const val SSO_REDIRECT_URL_PARAM = "redirectUrl"

View File

@@ -45,7 +45,7 @@ data class Credentials(
* @Deprecated. Clients should extract the server_name from user_id (by splitting at the first colon)
* if they require it. Note also that homeserver is not spelt this way.
*/
@Json(name = "home_server") val homeServer: String,
@Json(name = "home_server") val homeServer: String?,
/**
* ID of the logged-in device. Will be the same as the corresponding parameter in the request, if one was specified.
*/

View File

@@ -20,6 +20,7 @@ import android.net.Uri
import com.squareup.moshi.JsonClass
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig.Builder
import im.vector.matrix.android.internal.network.ssl.Fingerprint
import im.vector.matrix.android.internal.util.ensureTrailingSlash
import okhttp3.CipherSuite
import okhttp3.TlsVersion
@@ -68,18 +69,14 @@ data class HomeServerConnectionConfig(
*/
fun withHomeServerUri(hsUri: Uri): Builder {
if (hsUri.scheme != "http" && hsUri.scheme != "https") {
throw RuntimeException("Invalid home server URI: " + hsUri)
throw RuntimeException("Invalid home server URI: $hsUri")
}
// ensure trailing /
homeServerUri = if (!hsUri.toString().endsWith("/")) {
try {
val url = hsUri.toString()
Uri.parse("$url/")
} catch (e: Exception) {
throw RuntimeException("Invalid home server URI: $hsUri")
}
} else {
hsUri
val hsString = hsUri.toString().ensureTrailingSlash()
homeServerUri = try {
Uri.parse(hsString)
} catch (e: Exception) {
throw RuntimeException("Invalid home server URI: $hsUri")
}
return this
}
@@ -97,15 +94,11 @@ data class HomeServerConnectionConfig(
throw RuntimeException("Invalid identity server URI: $identityServerUri")
}
// ensure trailing /
if (!identityServerUri.toString().endsWith("/")) {
try {
val url = identityServerUri.toString()
this.identityServerUri = Uri.parse("$url/")
} catch (e: Exception) {
throw RuntimeException("Invalid identity server URI: $identityServerUri")
}
} else {
this.identityServerUri = identityServerUri
val isString = identityServerUri.toString().ensureTrailingSlash()
this.identityServerUri = try {
Uri.parse(isString)
} catch (e: Exception) {
throw RuntimeException("Invalid identity server URI: $identityServerUri")
}
return this
}

View File

@@ -16,12 +16,10 @@
package im.vector.matrix.android.api.auth.data
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
// Either a LoginFlowResponse, or an error if the homeserver is outdated
// Either a list of supported login types, or an error if the homeserver is outdated
sealed class LoginFlowResult {
data class Success(
val loginFlowResponse: LoginFlowResponse,
val supportedLoginTypes: List<String>,
val isLoginAndRegistrationSupported: Boolean,
val homeServerUrl: String
) : LoginFlowResult()

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.auth.data
package im.vector.matrix.android.api.auth.data
object LoginFlowTypes {
const val PASSWORD = "m.login.password"

View File

@@ -21,7 +21,48 @@ package im.vector.matrix.android.api.auth.data
* You don't have to manually instantiate it.
*/
data class SessionParams(
/**
* Please consider using shortcuts instead
*/
val credentials: Credentials,
/**
* Please consider using shortcuts instead
*/
val homeServerConnectionConfig: HomeServerConnectionConfig,
/**
* Set to false if the current token is not valid anymore. Application should not have to use this info.
*/
val isTokenValid: Boolean
)
) {
/*
* Shortcuts. Usually the application should only need to use these shortcuts
*/
/**
* The userId of the session (Ex: "@user:domain.org")
*/
val userId = credentials.userId
/**
* The deviceId of the session (Ex: "ABCDEFGH")
*/
val deviceId = credentials.deviceId
/**
* The current homeserver Url. It can be different that the homeserver url entered
* during login phase, because a redirection may have occurred
*/
val homeServerUrl = homeServerConnectionConfig.homeServerUri.toString()
/**
* The current homeserver host
*/
val homeServerHost = homeServerConnectionConfig.homeServerUri.host
/**
* The default identity server url if any, returned by the homeserver during login phase
*/
val defaultIdentityServerUrl = homeServerConnectionConfig.identityServerUri?.toString()
}

View File

@@ -54,30 +54,4 @@ data class WellKnown(
@Json(name = "m.integrations")
val integrations: JsonDict? = null
) {
/**
* Returns the list of integration managers proposed
*/
fun getIntegrationManagers(): List<WellKnownManagerConfig> {
val managers = ArrayList<WellKnownManagerConfig>()
integrations?.get("managers")?.let {
(it as? ArrayList<*>)?.let { configs ->
configs.forEach { config ->
(config as? Map<*, *>)?.let { map ->
val apiUrl = map["api_url"] as? String
val uiUrl = map["ui_url"] as? String ?: apiUrl
if (apiUrl != null
&& apiUrl.startsWith("https://")
&& uiUrl!!.startsWith("https://")) {
managers.add(WellKnownManagerConfig(
apiUrl = apiUrl,
uiUrl = uiUrl
))
}
}
}
}
}
return managers
}
}
)

View File

@@ -34,6 +34,12 @@ interface LoginWizard {
deviceName: String,
callback: MatrixCallback<Session>): Cancelable
/**
* Exchange a login token to an access token
*/
fun loginWithToken(loginToken: String,
callback: MatrixCallback<Session>): Cancelable
/**
* Reset user password
*/

View File

@@ -21,15 +21,12 @@ sealed class Stage(open val mandatory: Boolean) {
// m.login.recaptcha
data class ReCaptcha(override val mandatory: Boolean, val publicKey: String) : Stage(mandatory)
// m.login.oauth2
// m.login.email.identity
data class Email(override val mandatory: Boolean) : Stage(mandatory)
// m.login.msisdn
data class Msisdn(override val mandatory: Boolean) : Stage(mandatory)
// m.login.token
// m.login.dummy, can be mandatory if there is no other stages. In this case the account cannot be created by just sending a username
// and a password, the dummy stage has to be done
data class Dummy(override val mandatory: Boolean) : Stage(mandatory)

View File

@@ -19,11 +19,11 @@ package im.vector.matrix.android.api.crypto
/**
* Class to define the parameters used to customize or configure the end-to-end crypto.
*/
data class MXCryptoConfig(
data class MXCryptoConfig constructor(
// Tell whether the encryption of the event content is enabled for the invited members.
// SDK clients can disable this by settings it to false.
// Note that the encryption for the invited members will be blocked if the history visibility is "joined".
var enableEncryptionForInvitedMembers: Boolean = true,
val enableEncryptionForInvitedMembers: Boolean = true,
/**
* If set to true, the SDK will automatically ignore room key request (gossiping)
@@ -31,6 +31,5 @@ data class MXCryptoConfig(
* If set to false, the request will be forwarded to the application layer; in this
* case the application can decide to prompt the user.
*/
var discardRoomKeyRequestsFromUntrustedDevices : Boolean = true
val discardRoomKeyRequestsFromUntrustedDevices: Boolean = true
)

View File

@@ -16,10 +16,15 @@
package im.vector.matrix.android.api.extensions
inline fun <A> tryThis(operation: () -> A): A? {
import timber.log.Timber
inline fun <A> tryThis(message: String? = null, operation: () -> A): A? {
return try {
operation()
} catch (any: Throwable) {
if (message != null) {
Timber.e(any, message)
}
null
}
}

View File

@@ -39,7 +39,10 @@ data class MatrixError(
// For M_LIMIT_EXCEEDED
@Json(name = "retry_after_ms") val retryAfterMillis: Long? = null,
// For M_UNKNOWN_TOKEN
@Json(name = "soft_logout") val isSoftLogout: Boolean = false
@Json(name = "soft_logout") val isSoftLogout: Boolean = false,
// For M_INVALID_PEPPER
// {"error": "pepper does not match 'erZvr'", "lookup_pepper": "pQgMS", "algorithm": "sha256", "errcode": "M_INVALID_PEPPER"}
@Json(name = "lookup_pepper") val newLookupPepper: String? = null
) {
companion object {
@@ -129,6 +132,11 @@ data class MatrixError(
/** (Not documented yet) */
const val M_WRONG_ROOM_KEYS_VERSION = "M_WRONG_ROOM_KEYS_VERSION"
const val M_TERMS_NOT_SIGNED = "M_TERMS_NOT_SIGNED"
// For identity service
const val M_INVALID_PEPPER = "M_INVALID_PEPPER"
// Possible value for "limit_type"
const val LIMIT_TYPE_MAU = "monthly_active_user"
}

View File

@@ -29,13 +29,25 @@ interface PushRuleService {
fun getPushRules(scope: String = RuleScope.GLOBAL): RuleSet
fun updatePushRuleEnableStatus(kind: RuleKind, pushRule: PushRule, enabled: Boolean, callback: MatrixCallback<Unit>): Cancelable
fun updatePushRuleEnableStatus(kind: RuleKind,
pushRule: PushRule,
enabled: Boolean,
callback: MatrixCallback<Unit>): Cancelable
fun addPushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
fun addPushRule(kind: RuleKind,
pushRule: PushRule,
beforeRuleId: String?,
afterRuleId: String?,
callback: MatrixCallback<Unit>): Cancelable
fun updatePushRuleActions(kind: RuleKind, oldPushRule: PushRule, newPushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
fun updatePushRuleActions(kind: RuleKind,
oldPushRule: PushRule,
newPushRule: PushRule,
callback: MatrixCallback<Unit>): Cancelable
fun removePushRule(kind: RuleKind, pushRule: PushRule, callback: MatrixCallback<Unit>): Cancelable
fun removePushRule(kind: RuleKind,
pushRule: PushRule,
callback: MatrixCallback<Unit>): Cancelable
fun addPushRuleListener(listener: PushRuleListener)

View File

@@ -39,6 +39,6 @@ class SenderNotificationPermissionCondition(
fun isSatisfied(event: Event, powerLevels: PowerLevelsContent): Boolean {
val powerLevelsHelper = PowerLevelsHelper(powerLevels)
return event.senderId != null && powerLevelsHelper.getUserPowerLevel(event.senderId) >= powerLevelsHelper.notificationLevel(key)
return event.senderId != null && powerLevelsHelper.getUserPowerLevelValue(event.senderId) >= powerLevelsHelper.notificationLevel(key)
}
}

View File

@@ -31,7 +31,7 @@ internal data class GetPushRulesResponse(
val global: RuleSet,
/**
* Device specific rules, apply only to current device
* Device specific rules, apply only to current device. Not used anymore
*/
@Json(name = "device")
val device: RuleSet? = null

View File

@@ -25,8 +25,8 @@ sealed class QueryStringValue {
object IsNotNull : QueryStringValue()
object IsEmpty : QueryStringValue()
object IsNotEmpty : QueryStringValue()
data class Equals(val string: String, val case: Case) : QueryStringValue()
data class Contains(val string: String, val case: Case) : QueryStringValue()
data class Equals(val string: String, val case: Case = Case.SENSITIVE) : QueryStringValue()
data class Contains(val string: String, val case: Case = Case.SENSITIVE) : QueryStringValue()
enum class Case {
SENSITIVE,

View File

@@ -24,12 +24,15 @@ import im.vector.matrix.android.api.pushrules.PushRuleService
import im.vector.matrix.android.api.session.account.AccountService
import im.vector.matrix.android.api.session.accountdata.AccountDataService
import im.vector.matrix.android.api.session.cache.CacheService
import im.vector.matrix.android.api.session.call.CallSignalingService
import im.vector.matrix.android.api.session.content.ContentUploadStateTracker
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.file.FileService
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.identity.IdentityService
import im.vector.matrix.android.api.session.integrationmanager.IntegrationManagerService
import im.vector.matrix.android.api.session.profile.ProfileService
import im.vector.matrix.android.api.session.pushers.PushersService
import im.vector.matrix.android.api.session.room.RoomDirectoryService
@@ -39,7 +42,9 @@ import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageSer
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.SyncState
import im.vector.matrix.android.api.session.terms.TermsService
import im.vector.matrix.android.api.session.user.UserService
import im.vector.matrix.android.api.session.widgets.WidgetService
/**
* This interface defines interactions with a session.
@@ -54,6 +59,7 @@ interface Session :
SignOutService,
FilterService,
FileService,
TermsService,
ProfileService,
PushRuleService,
PushersService,
@@ -77,7 +83,7 @@ interface Session :
* Useful shortcut to get access to the userId
*/
val myUserId: String
get() = sessionParams.credentials.userId
get() = sessionParams.userId
/**
* The sessionId
@@ -145,6 +151,26 @@ interface Session :
*/
fun cryptoService(): CryptoService
/**
* Returns the identity service associated with the session
*/
fun identityService(): IdentityService
/**
* Returns the widget service associated with the session
*/
fun widgetService(): WidgetService
/**
* Returns the integration manager service associated with the session
*/
fun integrationManagerService(): IntegrationManagerService
/**
* Returns the call signaling service associated with the session
*/
fun callSignalingService(): CallSignalingService
/**
* Add a listener to the session.
* @param listener the listener to add.

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.call
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
interface CallSignalingService {
fun getTurnServer(callback: MatrixCallback<TurnServerResponse>): Cancelable
/**
* Create an outgoing call
*/
fun createOutgoingCall(roomId: String, otherUserId: String, isVideoCall: Boolean): MxCall
fun addCallListener(listener: CallsListener)
fun removeCallListener(listener: CallsListener)
fun getCallWithId(callId: String) : MxCall?
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.call
import org.webrtc.PeerConnection
sealed class CallState {
/** Idle, setting up objects */
object Idle : CallState()
/** Dialing. Outgoing call is signaling the remote peer */
object Dialing : CallState()
/** Local ringing. Incoming call offer received */
object LocalRinging : CallState()
/** Answering. Incoming call is responding to remote peer */
object Answering : CallState()
/**
* Connected. Incoming/Outgoing call, ice layer connecting or connected
* Notice that the PeerState failed is not always final, if you switch network, new ice candidtates
* could be exchanged, and the connection could go back to connected
* */
data class Connected(val iceConnectionState: PeerConnection.PeerConnectionState) : CallState()
/** Terminated. Incoming/Outgoing call, the call is terminated */
object Terminated : CallState()
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.call
import im.vector.matrix.android.api.session.room.model.call.CallAnswerContent
import im.vector.matrix.android.api.session.room.model.call.CallCandidatesContent
import im.vector.matrix.android.api.session.room.model.call.CallHangupContent
import im.vector.matrix.android.api.session.room.model.call.CallInviteContent
interface CallsListener {
/**
* Called when there is an incoming call within the room.
*/
fun onCallInviteReceived(mxCall: MxCall, callInviteContent: CallInviteContent)
fun onCallIceCandidateReceived(mxCall: MxCall, iceCandidatesContent: CallCandidatesContent)
/**
* An outgoing call is started.
*/
fun onCallAnswerReceived(callAnswerContent: CallAnswerContent)
/**
* Called when a called has been hung up
*/
fun onCallHangupReceived(callHangupContent: CallHangupContent)
fun onCallManagedByOtherSession(callId: String)
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.call
import org.webrtc.EglBase
import timber.log.Timber
/**
* The root [EglBase] instance shared by the entire application for
* the sake of reducing the utilization of system resources (such as EGL
* contexts)
* by performing a runtime check.
*/
object EglUtils {
// TODO how do we release that?
/**
* Lazily creates and returns the one and only [EglBase] which will
* serve as the root for all contexts that are needed.
*/
@get:Synchronized var rootEglBase: EglBase? = null
get() {
if (field == null) {
val configAttributes = EglBase.CONFIG_PLAIN
try {
field = EglBase.createEgl14(configAttributes)
?: EglBase.createEgl10(configAttributes) // Fall back to EglBase10.
} catch (ex: Throwable) {
Timber.e(ex, "Failed to create EglBase")
}
}
return field
}
private set
val rootEglBaseContext: EglBase.Context?
get() {
val eglBase = rootEglBase
return eglBase?.eglBaseContext
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.call
import org.webrtc.IceCandidate
import org.webrtc.SessionDescription
interface MxCallDetail {
val callId: String
val isOutgoing: Boolean
val roomId: String
val otherUserId: String
val isVideoCall: Boolean
}
/**
* Define both an incoming call and on outgoing call
*/
interface MxCall : MxCallDetail {
var state: CallState
/**
* Pick Up the incoming call
* It has no effect on outgoing call
*/
fun accept(sdp: SessionDescription)
/**
* Reject an incoming call
* It's an alias to hangUp
*/
fun reject() = hangUp()
/**
* End the call
*/
fun hangUp()
/**
* Start a call
* Send offer SDP to the other participant.
*/
fun offerSdp(sdp: SessionDescription)
/**
* Send Ice candidate to the other participant.
*/
fun sendLocalIceCandidates(candidates: List<IceCandidate>)
/**
* Send removed ICE candidates to the other participant.
*/
fun sendLocalIceCandidateRemovals(candidates: List<IceCandidate>)
fun addListener(listener: StateListener)
fun removeListener(listener: StateListener)
interface StateListener {
fun onStateUpdate(call: MxCall)
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.call
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
// TODO Should not be exposed
/**
* Ref: https://matrix.org/docs/spec/client_server/r0.6.1#get-matrix-client-r0-voip-turnserver
*/
@JsonClass(generateAdapter = true)
data class TurnServerResponse(
/**
* Required. The username to use.
*/
@Json(name = "username") val username: String?,
/**
* Required. The password to use.
*/
@Json(name = "password") val password: String?,
/**
* Required. A list of TURN URIs
*/
@Json(name = "uris") val uris: List<String>?,
/**
* Required. The time-to-live in seconds
*/
@Json(name = "ttl") val ttl: Int?
)

View File

@@ -138,7 +138,9 @@ interface CryptoService {
fun removeSessionListener(listener: NewSessionListener)
fun getOutgoingRoomKeyRequest(): List<OutgoingRoomKeyRequest>
fun getIncomingRoomKeyRequest(): List<IncomingRoomKeyRequest>
fun getOutgoingRoomKeyRequests(): List<OutgoingRoomKeyRequest>
fun getIncomingRoomKeyRequests(): List<IncomingRoomKeyRequest>
fun getGossipingEventsTrail(): List<Event>
}

View File

@@ -98,7 +98,7 @@ data class Event(
* @return true if event is state event.
*/
fun isStateEvent(): Boolean {
return EventType.isStateEvent(getClearType())
return stateKey != null
}
// ==============================================================================================================
@@ -162,6 +162,8 @@ data class Event(
*/
fun isRedactedBySameUser() = senderId == unsignedData?.redactedEvent?.senderId
fun resolvedPrevContent(): Content? = prevContent ?: unsignedData?.prevContent
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
@@ -220,3 +222,11 @@ fun Event.isImageMessage(): Boolean {
else -> false
}
}
fun Event.isVideoMessage(): Boolean {
return getClearType() == EventType.MESSAGE
&& when (getClearContent()?.toModel<MessageContent>()?.msgType) {
MessageType.MSGTYPE_VIDEO -> true
else -> false
}
}

View File

@@ -38,6 +38,8 @@ object EventType {
// State Events
const val STATE_ROOM_WIDGET_LEGACY = "im.vector.modular.widgets"
const val STATE_ROOM_WIDGET = "m.widget"
const val STATE_ROOM_NAME = "m.room.name"
const val STATE_ROOM_TOPIC = "m.room.topic"
const val STATE_ROOM_AVATAR = "m.room.avatar"
@@ -56,7 +58,6 @@ object EventType {
const val STATE_ROOM_ENCRYPTION = "m.room.encryption"
// Call Events
const val CALL_INVITE = "m.call.invite"
const val CALL_CANDIDATES = "m.call.candidates"
const val CALL_ANSWER = "m.call.answer"
@@ -84,29 +85,6 @@ object EventType {
// Unwedging
internal const val DUMMY = "m.dummy"
private val STATE_EVENTS = listOf(
STATE_ROOM_NAME,
STATE_ROOM_TOPIC,
STATE_ROOM_AVATAR,
STATE_ROOM_MEMBER,
STATE_ROOM_THIRD_PARTY_INVITE,
STATE_ROOM_CREATE,
STATE_ROOM_JOIN_RULES,
STATE_ROOM_GUEST_ACCESS,
STATE_ROOM_POWER_LEVELS,
STATE_ROOM_ALIASES,
STATE_ROOM_TOMBSTONE,
STATE_ROOM_CANONICAL_ALIAS,
STATE_ROOM_HISTORY_VISIBILITY,
STATE_ROOM_RELATED_GROUPS,
STATE_ROOM_PINNED_EVENT,
STATE_ROOM_ENCRYPTION
)
fun isStateEvent(type: String): Boolean {
return STATE_EVENTS.contains(type)
}
fun isCallEvent(type: String): Boolean {
return type == CALL_INVITE
|| type == CALL_CANDIDATES

View File

@@ -24,7 +24,15 @@ 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
val maxUploadFileSize: Long = MAX_UPLOAD_FILE_SIZE_UNKNOWN,
/**
* Last version identity server and binding supported
*/
val lastVersionIdentityServerSupported: Boolean = false,
/**
* Default identity server url, provided in Wellknown
*/
val defaultIdentityServerUrl: String? = null
) {
companion object {
const val MAX_UPLOAD_FILE_SIZE_UNKNOWN = -1L

View File

@@ -0,0 +1,22 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.identity
data class FoundThreePid(
val threePid: ThreePid,
val matrixId: String
)

View File

@@ -0,0 +1,109 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.identity
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
/**
* Provides access to the identity server configuration and services identity server can provide
*/
interface IdentityService {
/**
* Return the default identity server of the user, which may have been provided at login time by the homeserver,
* or by the Well-known setup of the homeserver
* It may be different from the current configured identity server
*/
fun getDefaultIdentityServer(): String?
/**
* Return the current identity server URL used by this account. Returns null if no identity server is configured.
*/
fun getCurrentIdentityServerUrl(): String?
/**
* Check if the identity server is valid
* See https://matrix.org/docs/spec/identity_service/latest#status-check
* RiotX SDK only supports identity server API v2
*/
fun isValidIdentityServer(url: String, callback: MatrixCallback<Unit>): Cancelable
/**
* Update the identity server url.
* If successful, any previous identity server will be disconnected.
* In case of error, any previous identity server will remain configured.
* @param url the new url.
* @param callback will notify the user if change is successful. The String will be the final url of the identity server.
* The SDK can prepend "https://" for instance.
*/
fun setNewIdentityServer(url: String, callback: MatrixCallback<String>): Cancelable
/**
* Disconnect (logout) from the current identity server
*/
fun disconnect(callback: MatrixCallback<Unit>): Cancelable
/**
* This will ask the identity server to send an email or an SMS to let the user confirm he owns the ThreePid
*/
fun startBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
/**
* This will cancel a pending binding of threePid.
*/
fun cancelBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
/**
* This will ask the identity server to send an new email or a new SMS to let the user confirm he owns the ThreePid
*/
fun sendAgainValidationCode(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
/**
* Submit the code that the identity server has sent to the user (in email or SMS)
* Once successful, you will have to call [finalizeBindThreePid]
* @param code the code sent to the user
*/
fun submitValidationToken(threePid: ThreePid, code: String, callback: MatrixCallback<Unit>): Cancelable
/**
* This will perform the actual association of ThreePid and Matrix account
*/
fun finalizeBindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
/**
* Unbind a threePid
* The request will actually be done on the homeserver
*/
fun unbindThreePid(threePid: ThreePid, callback: MatrixCallback<Unit>): Cancelable
/**
* Search MatrixId of users providing email and phone numbers
*/
fun lookUp(threePids: List<ThreePid>, callback: MatrixCallback<List<FoundThreePid>>): Cancelable
/**
* Get the status of the current user's threePid
* A lookup will be performed, but also pending binding state will be restored
*
* @param threePids the list of threePid the user owns (retrieved form the homeserver)
* @param callback onSuccess will be called with a map of ThreePid -> SharedState
*/
fun getShareStatus(threePids: List<ThreePid>, callback: MatrixCallback<Map<ThreePid, SharedState>>): Cancelable
fun addListener(listener: IdentityServiceListener)
fun removeListener(listener: IdentityServiceListener)
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.identity
import im.vector.matrix.android.api.failure.Failure
sealed class IdentityServiceError : Failure.FeatureFailure() {
object OutdatedIdentityServer : IdentityServiceError()
object OutdatedHomeServer : IdentityServiceError()
object NoIdentityServerConfigured : IdentityServiceError()
object TermsNotSignedException : IdentityServiceError()
object BulkLookupSha256NotSupported : IdentityServiceError()
object BindingError : IdentityServiceError()
object NoCurrentBindingError : IdentityServiceError()
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2019 New Vector Ltd
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth.data
data class WellKnownManagerConfig(
val apiUrl: String,
val uiUrl: String
)
package im.vector.matrix.android.api.session.identity
interface IdentityServiceListener {
fun onIdentityServerChange()
}

View File

@@ -0,0 +1,23 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.identity
enum class SharedState {
SHARED,
NOT_SHARED,
BINDING_IN_PROGRESS
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.identity
import com.google.i18n.phonenumbers.NumberParseException
import com.google.i18n.phonenumbers.PhoneNumberUtil
import im.vector.matrix.android.internal.session.profile.ThirdPartyIdentifier
sealed class ThreePid(open val value: String) {
data class Email(val email: String) : ThreePid(email)
data class Msisdn(val msisdn: String) : ThreePid(msisdn)
}
internal fun ThreePid.toMedium(): String {
return when (this) {
is ThreePid.Email -> ThirdPartyIdentifier.MEDIUM_EMAIL
is ThreePid.Msisdn -> ThirdPartyIdentifier.MEDIUM_MSISDN
}
}
@Throws(NumberParseException::class)
internal fun ThreePid.Msisdn.getCountryCode(): String {
return with(PhoneNumberUtil.getInstance()) {
getRegionCodeForCountryCode(parse("+$msisdn", null).countryCode)
}
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.integrationmanager
/**
* This class holds configuration of integration manager.
*/
data class IntegrationManagerConfig(
val uiUrl: String,
val restUrl: String,
val kind: Kind
) {
// Order matters, first is preferred
/**
* The kind of config, it will reflect where the data is coming from.
*/
enum class Kind {
/**
* Defined in UserAccountData
*/
ACCOUNT,
/**
* Defined in Wellknown
*/
HOMESERVER,
/**
* Fallback value, hardcoded by the SDK
*/
DEFAULT
}
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.integrationmanager
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
/**
* This is the entry point to manage integration. You can grab an instance of this service through an active session.
*/
interface IntegrationManagerService {
/**
* This listener allow you to observe change related to integrations.
*/
interface Listener {
/**
* Is called whenever integration is enabled or disabled, comes from user account data.
*/
fun onIsEnabledChanged(enabled: Boolean) {
// No-op
}
/**
* Is called whenever configs from user account data or wellknown are updated.
*/
fun onConfigurationChanged(configs: List<IntegrationManagerConfig>) {
// No-op
}
/**
* Is called whenever widget permissions from user account data are updated.
*/
fun onWidgetPermissionsChanged(widgets: Map<String, Boolean>) {
// No-op
}
}
/**
* Adds a listener to observe changes.
*/
fun addListener(listener: Listener)
/**
* Removes a previously added listener.
*/
fun removeListener(listener: Listener)
/**
* Return the list of current configurations, sorted by kind. First one is preferred.
* See [IntegrationManagerConfig.Kind]
*/
fun getOrderedConfigs(): List<IntegrationManagerConfig>
/**
* Return the preferred current configuration.
* See [IntegrationManagerConfig.Kind]
*/
fun getPreferredConfig(): IntegrationManagerConfig
/**
* Returns true if integration is enabled, false otherwise.
*/
fun isIntegrationEnabled(): Boolean
/**
* Offers to enable or disable the integration.
* @param enable the param to change
* @param callback the matrix callback to listen for result.
* @return Cancelable
*/
fun setIntegrationEnabled(enable: Boolean, callback: MatrixCallback<Unit>): Cancelable
/**
* Offers to allow or disallow a widget.
* @param stateEventId the eventId of the state event defining the widget.
* @param allowed the param to change
* @param callback the matrix callback to listen for result.
* @return Cancelable
*/
fun setWidgetAllowed(stateEventId: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
/**
* Returns true if the widget is allowed, false otherwise.
* @param stateEventId the eventId of the state event defining the widget.
*/
fun isWidgetAllowed(stateEventId: String): Boolean
/**
* Offers to allow or disallow a native widget domain.
* @param widgetType the widget type to check for
* @param domain the domain to check for
*/
fun setNativeWidgetDomainAllowed(widgetType: String, domain: String, allowed: Boolean, callback: MatrixCallback<Unit>): Cancelable
/**
* Returns true if the widget domain is allowed, false otherwise.
* @param widgetType the widget type to check for
* @param domain the domain to check for
*/
fun isNativeWidgetDomainAllowed(widgetType: String, domain: String): Boolean
}

View File

@@ -17,7 +17,9 @@
package im.vector.matrix.android.api.session.profile
import androidx.lifecycle.LiveData
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.identity.ThreePid
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.api.util.JsonDict
import im.vector.matrix.android.api.util.Optional
@@ -33,12 +35,19 @@ interface ProfileService {
}
/**
* Return the current dispayname for this user
* Return the current display name for this user
* @param userId the userId param to look for
*
*/
fun getDisplayName(userId: String, matrixCallback: MatrixCallback<Optional<String>>): Cancelable
/**
* Update the display name for this user
* @param userId the userId to update the display name of
* @param newDisplayName the new display name of the user
*/
fun setDisplayName(userId: String, newDisplayName: String, matrixCallback: MatrixCallback<Unit>): Cancelable
/**
* Return the current avatarUrl for this user.
* @param userId the userId param to look for
@@ -53,4 +62,15 @@ interface ProfileService {
*
*/
fun getProfile(userId: String, matrixCallback: MatrixCallback<JsonDict>): Cancelable
/**
* Get the current user 3Pids
*/
fun getThreePids(): List<ThreePid>
/**
* Get the current user 3Pids Live
* @param refreshData set to true to fetch data from the homeserver
*/
fun getThreePidsLive(refreshData: Boolean): LiveData<List<ThreePid>>
}

View File

@@ -17,6 +17,7 @@
package im.vector.matrix.android.api.session.room
import androidx.lifecycle.LiveData
import im.vector.matrix.android.api.session.room.call.RoomCallService
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.model.RoomSummary
@@ -27,8 +28,10 @@ import im.vector.matrix.android.api.session.room.reporting.ReportingService
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.state.StateService
import im.vector.matrix.android.api.session.room.tags.TagsService
import im.vector.matrix.android.api.session.room.timeline.TimelineService
import im.vector.matrix.android.api.session.room.typing.TypingService
import im.vector.matrix.android.api.session.room.uploads.UploadsService
import im.vector.matrix.android.api.util.Optional
/**
@@ -40,9 +43,12 @@ interface Room :
DraftService,
ReadService,
TypingService,
TagsService,
MembershipService,
StateService,
UploadsService,
ReportingService,
RoomCallService,
RelationService,
RoomCryptoService,
RoomPushRuleService {

View File

@@ -73,15 +73,17 @@ interface RoomService {
/**
* Get a snapshot list of Breadcrumbs
* @param queryParams parameters to query the room summaries. It can be use to keep only joined rooms, for instance.
* @return the immutable list of [RoomSummary]
*/
fun getBreadcrumbs(): List<RoomSummary>
fun getBreadcrumbs(queryParams: RoomSummaryQueryParams): List<RoomSummary>
/**
* Get a live list of Breadcrumbs
* @param queryParams parameters to query the room summaries. It can be use to keep only joined rooms, for instance.
* @return the [LiveData] of [RoomSummary]
*/
fun getBreadcrumbsLive(): LiveData<List<RoomSummary>>
fun getBreadcrumbsLive(queryParams: RoomSummaryQueryParams): LiveData<List<RoomSummary>>
/**
* Inform the Matrix SDK that a room is displayed.

View File

@@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.call
/**
* This interface defines methods to handle calls in a room. It's implemented at the room level.
*/
interface RoomCallService {
/**
* Return true if calls (audio or video) can be performed on this Room
*/
fun canStartCall(): Boolean
}

View File

@@ -63,6 +63,27 @@ interface MembershipService {
reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
/**
* Ban a user from the room
*/
fun ban(userId: String,
reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
/**
* Unban a user from the room
*/
fun unban(userId: String,
reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
/**
* Kick a user from the room
*/
fun kick(userId: String,
reason: String? = null,
callback: MatrixCallback<Unit>): Cancelable
/**
* Join the room, or accept an invitation.
*/

View File

@@ -17,10 +17,12 @@
package im.vector.matrix.android.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* Represents the membership of a user on a room
*/
@JsonClass(generateAdapter = false)
enum class Membership(val value: String) {
NONE("none"),
@@ -44,6 +46,10 @@ enum class Membership(val value: String) {
return this == KNOCK || this == LEAVE || this == BAN
}
fun isActive(): Boolean {
return activeMemberships().contains(this)
}
companion object {
fun activeMemberships(): List<Membership> {
return listOf(INVITE, JOIN)

View File

@@ -18,21 +18,21 @@ package im.vector.matrix.android.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import im.vector.matrix.android.api.session.room.powerlevels.PowerLevelsConstants
import im.vector.matrix.android.api.session.room.powerlevels.Role
/**
* Class representing the EventType.EVENT_TYPE_STATE_ROOM_POWER_LEVELS state event content.
*/
@JsonClass(generateAdapter = true)
data class PowerLevelsContent(
@Json(name = "ban") val ban: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
@Json(name = "kick") val kick: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
@Json(name = "invite") val invite: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
@Json(name = "redact") val redact: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
@Json(name = "events_default") val eventsDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_USER_LEVEL,
@Json(name = "ban") val ban: Int = Role.Moderator.value,
@Json(name = "kick") val kick: Int = Role.Moderator.value,
@Json(name = "invite") val invite: Int = Role.Moderator.value,
@Json(name = "redact") val redact: Int = Role.Moderator.value,
@Json(name = "events_default") val eventsDefault: Int = Role.Default.value,
@Json(name = "events") val events: MutableMap<String, Int> = HashMap(),
@Json(name = "users_default") val usersDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_USER_LEVEL,
@Json(name = "users_default") val usersDefault: Int = Role.Default.value,
@Json(name = "users") val users: MutableMap<String, Int> = HashMap(),
@Json(name = "state_default") val stateDefault: Int = PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL,
@Json(name = "state_default") val stateDefault: Int = Role.Moderator.value,
@Json(name = "notifications") val notifications: Map<String, Any> = HashMap()
)

View File

@@ -17,7 +17,9 @@
package im.vector.matrix.android.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = false)
enum class RoomDirectoryVisibility {
@Json(name = "private") PRIVATE,
@Json(name = "public") PUBLIC

View File

@@ -29,6 +29,7 @@ data class RoomGuestAccessContent(
@Json(name = "guest_access") val guestAccess: GuestAccess? = null
)
@JsonClass(generateAdapter = false)
enum class GuestAccess(val value: String) {
@Json(name = "can_join")
CanJoin("can_join"),

View File

@@ -17,10 +17,12 @@
package im.vector.matrix.android.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* Ref: https://matrix.org/docs/spec/client_server/latest#room-history-visibility
*/
@JsonClass(generateAdapter = false)
enum class RoomHistoryVisibility {
/**
* All events while this is the m.room.history_visibility value may be shared by any

View File

@@ -18,10 +18,12 @@
package im.vector.matrix.android.api.session.room.model
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* Enum for [RoomJoinRulesContent] : https://matrix.org/docs/spec/client_server/r0.4.0#m-room-join-rules
*/
@JsonClass(generateAdapter = false)
enum class RoomJoinRules(val value: String) {
@Json(name = "public")

View File

@@ -59,6 +59,12 @@ data class RoomSummary constructor(
val hasNewMessages: Boolean
get() = notificationCount != 0
val isFavorite: Boolean
get() = tags.any { it.name == RoomTag.ROOM_TAG_FAVOURITE }
val canStartCall: Boolean
get() = isDirect && joinedMembersCount == 2
companion object {
const val NOT_IN_BREADCRUMBS = -1
}

View File

@@ -19,16 +19,34 @@ package im.vector.matrix.android.api.session.room.model.call
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* This event is sent by the callee when they wish to answer the call.
*/
@JsonClass(generateAdapter = true)
data class CallAnswerContent(
/**
* Required. The ID of the call this event relates to.
*/
@Json(name = "call_id") val callId: String,
@Json(name = "version") val version: Int,
@Json(name = "answer") val answer: Answer
/**
* Required. The session description object
*/
@Json(name = "answer") val answer: Answer,
/**
* Required. The version of the VoIP specification this messages adheres to. This specification is version 0.
*/
@Json(name = "version") val version: Int = 0
) {
@JsonClass(generateAdapter = true)
data class Answer(
@Json(name = "type") val type: String,
/**
* Required. The type of session description. Must be 'answer'.
*/
@Json(name = "type") val type: SdpType = SdpType.ANSWER,
/**
* Required. The SDP text of the session description.
*/
@Json(name = "sdp") val sdp: String
)
}

View File

@@ -19,17 +19,39 @@ package im.vector.matrix.android.api.session.room.model.call
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* This event is sent by callers after sending an invite and by the callee after answering.
* Its purpose is to give the other party additional ICE candidates to try using to communicate.
*/
@JsonClass(generateAdapter = true)
data class CallCandidatesContent(
/**
* Required. The ID of the call this event relates to.
*/
@Json(name = "call_id") val callId: String,
@Json(name = "version") val version: Int,
@Json(name = "candidates") val candidates: List<Candidate> = emptyList()
/**
* Required. Array of objects describing the candidates.
*/
@Json(name = "candidates") val candidates: List<Candidate> = emptyList(),
/**
* Required. The version of the VoIP specification this messages adheres to. This specification is version 0.
*/
@Json(name = "version") val version: Int = 0
) {
@JsonClass(generateAdapter = true)
data class Candidate(
/**
* Required. The SDP media type this candidate is intended for.
*/
@Json(name = "sdpMid") val sdpMid: String,
@Json(name = "sdpMLineIndex") val sdpMLineIndex: String,
/**
* Required. The index of the SDP 'm' line this candidate is intended for.
*/
@Json(name = "sdpMLineIndex") val sdpMLineIndex: Int,
/**
* Required. The SDP 'a' line of the candidate.
*/
@Json(name = "candidate") val candidate: String
)
}

View File

@@ -19,8 +19,32 @@ package im.vector.matrix.android.api.session.room.model.call
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* Sent by either party to signal their termination of the call. This can be sent either once
* the call has been established or before to abort the call.
*/
@JsonClass(generateAdapter = true)
data class CallHangupContent(
/**
* Required. The ID of the call this event relates to.
*/
@Json(name = "call_id") val callId: String,
@Json(name = "version") val version: Int
)
/**
* Required. The version of the VoIP specification this message adheres to. This specification is version 0.
*/
@Json(name = "version") val version: Int = 0,
/**
* Optional error reason for the hangup. This should not be provided when the user naturally ends or rejects the call.
* When there was an error in the call negotiation, this should be `ice_failed` for when ICE negotiation fails
* or `invite_timeout` for when the other party did not answer in time. One of: ["ice_failed", "invite_timeout"]
*/
@Json(name = "reason") val reason: Reason? = null
) {
enum class Reason {
@Json(name = "ice_failed")
ICE_FAILED,
@Json(name = "invite_timeout")
INVITE_TIMEOUT
}
}

View File

@@ -19,23 +19,45 @@ package im.vector.matrix.android.api.session.room.model.call
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* This event is sent by the caller when they wish to establish a call.
*/
@JsonClass(generateAdapter = true)
data class CallInviteContent(
@Json(name = "call_id") val callId: String,
@Json(name = "version") val version: Int,
@Json(name = "lifetime") val lifetime: Int,
@Json(name = "offer") val offer: Offer
/**
* Required. A unique identifier for the call.
*/
@Json(name = "call_id") val callId: String?,
/**
* Required. The session description object
*/
@Json(name = "offer") val offer: Offer?,
/**
* Required. The version of the VoIP specification this message adheres to. This specification is version 0.
*/
@Json(name = "version") val version: Int? = 0,
/**
* Required. The time in milliseconds that the invite is valid for.
* Once the invite age exceeds this value, clients should discard it.
* They should also no longer show the call as awaiting an answer in the UI.
*/
@Json(name = "lifetime") val lifetime: Int?
) {
@JsonClass(generateAdapter = true)
data class Offer(
@Json(name = "type") val type: String,
@Json(name = "sdp") val sdp: String
/**
* Required. The type of session description. Must be 'offer'.
*/
@Json(name = "type") val type: SdpType? = SdpType.OFFER,
/**
* Required. The SDP text of the session description.
*/
@Json(name = "sdp") val sdp: String?
) {
companion object {
const val SDP_VIDEO = "m=video"
}
}
fun isVideo(): Boolean = offer.sdp.contains(Offer.SDP_VIDEO)
fun isVideo(): Boolean = offer?.sdp?.contains(Offer.SDP_VIDEO) == true
}

View File

@@ -1,25 +1,27 @@
/*
* Copyright 2020 New Vector Ltd
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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.powerlevels
package im.vector.matrix.android.api.session.room.model.call
object PowerLevelsConstants {
import com.squareup.moshi.Json
const val DEFAULT_ROOM_ADMIN_LEVEL = 100
const val DEFAULT_ROOM_MODERATOR_LEVEL = 50
const val DEFAULT_ROOM_USER_LEVEL = 0
enum class SdpType {
@Json(name = "offer")
OFFER,
@Json(name = "answer")
ANSWER
}

View File

@@ -17,7 +17,9 @@
package im.vector.matrix.android.api.session.room.model.create
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = false)
enum class CreateRoomPreset {
@Json(name = "private_chat")
PRESET_PRIVATE_CHAT,

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.model.message
interface MessageContentWithFormattedBody : MessageContent {
/**
* The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported.
*/
val format: String?
/**
* The formatted version of the body. This is required if format is specified.
*/
val formattedBody: String?
/**
* Get the formattedBody, only if not blank and if the format is equal to "org.matrix.custom.html"
*/
val matrixFormattedBody: String?
get() = formattedBody?.takeIf { it.isNotBlank() && format == MessageFormat.FORMAT_MATRIX_HTML }
}

View File

@@ -34,15 +34,15 @@ data class MessageEmoteContent(
@Json(name = "body") override val body: String,
/**
* The format used in the formatted_body. Currently only org.matrix.custom.html is supported.
* The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported.
*/
@Json(name = "format") val format: String? = null,
@Json(name = "format") override val format: String? = null,
/**
* The formatted version of the body. This is required if format is specified.
*/
@Json(name = "formatted_body") val formattedBody: String? = null,
@Json(name = "formatted_body") override val formattedBody: String? = null,
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
@Json(name = "m.new_content") override val newContent: Content? = null
) : MessageContent
) : MessageContentWithFormattedBody

View File

@@ -34,15 +34,15 @@ data class MessageNoticeContent(
@Json(name = "body") override val body: String,
/**
* The format used in the formatted_body. Currently only org.matrix.custom.html is supported.
* The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported.
*/
@Json(name = "format") val format: String? = null,
@Json(name = "format") override val format: String? = null,
/**
* The formatted version of the body. This is required if format is specified.
*/
@Json(name = "formatted_body") val formattedBody: String? = null,
@Json(name = "formatted_body") override val formattedBody: String? = null,
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
@Json(name = "m.new_content") override val newContent: Content? = null
) : MessageContent
) : MessageContentWithFormattedBody

View File

@@ -34,15 +34,15 @@ data class MessageTextContent(
@Json(name = "body") override val body: String,
/**
* The format used in the formatted_body. Currently only org.matrix.custom.html is supported.
* The format used in the formatted_body. Currently only "org.matrix.custom.html" is supported.
*/
@Json(name = "format") val format: String? = null,
@Json(name = "format") override val format: String? = null,
/**
* The formatted version of the body. This is required if format is specified.
*/
@Json(name = "formatted_body") val formattedBody: String? = null,
@Json(name = "formatted_body") override val formattedBody: String? = null,
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
@Json(name = "m.new_content") override val newContent: Content? = null
) : MessageContent
) : MessageContentWithFormattedBody

View File

@@ -22,9 +22,8 @@ data class RoomTag(
) {
companion object {
val ROOM_TAG_FAVOURITE = "m.favourite"
val ROOM_TAG_LOW_PRIORITY = "m.lowpriority"
val ROOM_TAG_NO_TAG = "m.recent"
val ROOM_TAG_SERVER_NOTICE = "m.server_notice"
const val ROOM_TAG_FAVOURITE = "m.favourite"
const val ROOM_TAG_LOW_PRIORITY = "m.lowpriority"
const val ROOM_TAG_SERVER_NOTICE = "m.server_notice"
}
}

View File

@@ -20,23 +20,20 @@ package im.vector.matrix.android.api.session.room.notification
* Defines the room notification state
*/
enum class RoomNotificationState {
/**
* All the messages will trigger a noisy notification
*/
ALL_MESSAGES_NOISY,
/**
* All the messages will trigger a notification
* This is the default for DMs
*/
ALL_MESSAGES,
/**
* Only the messages with user display name / user name will trigger notifications
* Only the messages with user display name / user name, or keywords will trigger notifications
* This is the default for Rooms
*/
MENTIONS_ONLY,
MENTIONS_AND_KEYWORDS,
/**
* No notifications
*/
MUTE
NONE
}

View File

@@ -17,7 +17,6 @@
package im.vector.matrix.android.api.session.room.powerlevels
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.room.model.PowerLevelsContent
/**
@@ -31,32 +30,84 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
* @param userId the user id
* @return the power level
*/
fun getUserPowerLevel(userId: String): Int {
fun getUserPowerLevelValue(userId: String): Int {
return powerLevelsContent.users.getOrElse(userId) {
powerLevelsContent.usersDefault
}
}
/**
* Returns the user power level of a dedicated user Id
*
* @param userId the user id
* @return the power level
*/
fun getUserRole(userId: String): Role {
val value = getUserPowerLevelValue(userId)
return Role.fromValue(value, powerLevelsContent.eventsDefault)
}
/**
* Tell if an user can send an event of a certain type
*
* @param userId the id of the user to check for.
* @param isState true if the event is a state event (ie. state key is not null)
* @param eventType the event type to check for
* @param userId the user id
* @return true if the user can send this type of event
*/
fun isAllowedToSend(eventType: String, userId: String): Boolean {
return if (eventType.isNotEmpty() && userId.isNotEmpty()) {
val powerLevel = getUserPowerLevel(userId)
fun isUserAllowedToSend(userId: String, isState: Boolean, eventType: String?): Boolean {
return if (userId.isNotEmpty()) {
val powerLevel = getUserPowerLevelValue(userId)
val minimumPowerLevel = powerLevelsContent.events[eventType]
?: if (EventType.isStateEvent(eventType)) {
powerLevelsContent.stateDefault
} else {
powerLevelsContent.eventsDefault
}
?: if (isState) {
powerLevelsContent.stateDefault
} else {
powerLevelsContent.eventsDefault
}
powerLevel >= minimumPowerLevel
} else false
}
/**
* Check if the user have the necessary power level to invite
* @param userId the id of the user to check for.
* @return true if able to invite
*/
fun isUserAbleToInvite(userId: String): Boolean {
val powerLevel = getUserPowerLevelValue(userId)
return powerLevel >= powerLevelsContent.invite
}
/**
* Check if the user have the necessary power level to ban
* @param userId the id of the user to check for.
* @return true if able to ban
*/
fun isUserAbleToBan(userId: String): Boolean {
val powerLevel = getUserPowerLevelValue(userId)
return powerLevel >= powerLevelsContent.ban
}
/**
* Check if the user have the necessary power level to kick
* @param userId the id of the user to check for.
* @return true if able to kick
*/
fun isUserAbleToKick(userId: String): Boolean {
val powerLevel = getUserPowerLevelValue(userId)
return powerLevel >= powerLevelsContent.kick
}
/**
* Check if the user have the necessary power level to redact
* @param userId the id of the user to check for.
* @return true if able to redact
*/
fun isUserAbleToRedact(userId: String): Boolean {
val powerLevel = getUserPowerLevelValue(userId)
return powerLevel >= powerLevelsContent.redact
}
/**
* Get the notification level for a dedicated key.
*
@@ -68,7 +119,7 @@ class PowerLevelsHelper(private val powerLevelsContent: PowerLevelsContent) {
// the first implementation was a string value
is String -> value.toInt()
is Int -> value
else -> PowerLevelsConstants.DEFAULT_ROOM_MODERATOR_LEVEL
else -> Role.Moderator.value
}
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package im.vector.matrix.android.api.session.room.powerlevels
import androidx.annotation.StringRes
import im.vector.matrix.android.R
sealed class Role(open val value: Int, @StringRes val res: Int) : Comparable<Role> {
object Admin : Role(100, R.string.power_level_admin)
object Moderator : Role(50, R.string.power_level_moderator)
object Default : Role(0, R.string.power_level_default)
data class Custom(override val value: Int) : Role(value, R.string.power_level_custom)
override fun compareTo(other: Role): Int {
return value.compareTo(other.value)
}
companion object {
// Order matters, default value should be checked after defined roles
fun fromValue(value: Int, default: Int): Role {
return when (value) {
Admin.value -> Admin
Moderator.value -> Moderator
Default.value,
default -> Default
else -> Custom(value)
}
}
}
}

View File

@@ -17,6 +17,7 @@
package im.vector.matrix.android.api.session.room.send
import im.vector.matrix.android.api.session.content.ContentAttachmentData
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.room.model.message.MessageType
import im.vector.matrix.android.api.session.room.model.message.OptionItem
@@ -28,6 +29,14 @@ import im.vector.matrix.android.api.util.Cancelable
*/
interface SendService {
/**
* Method to send a generic event asynchronously. If you want to send a state event, please use [StateService] instead.
* @param eventType the type of the event
* @param content the optional body as a json dict.
* @return a [Cancelable]
*/
fun sendEvent(eventType: String, content: Content?): Cancelable
/**
* Method to send a text message asynchronously.
* The text to send can be a Spannable and contains special spans (MatrixItemSpan) that will be translated

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.sender
data class SenderInfo(
val userId: String,
/**
* Consider using [disambiguatedDisplayName]
*/
val displayName: String?,
val isUniqueDisplayName: Boolean,
val avatarUrl: String?
) {
val disambiguatedDisplayName: String
get() = when {
displayName.isNullOrBlank() -> userId
isUniqueDisplayName -> displayName
else -> "$displayName ($userId)"
}
}

View File

@@ -18,7 +18,10 @@ package im.vector.matrix.android.api.session.room.state
import androidx.lifecycle.LiveData
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.query.QueryStringValue
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.util.Cancelable
import im.vector.matrix.android.api.util.JsonDict
import im.vector.matrix.android.api.util.Optional
interface StateService {
@@ -26,9 +29,15 @@ interface StateService {
/**
* Update the topic of the room
*/
fun updateTopic(topic: String, callback: MatrixCallback<Unit>)
fun updateTopic(topic: String, callback: MatrixCallback<Unit>): Cancelable
fun getStateEvent(eventType: String, stateKey: String): Event?
fun sendStateEvent(eventType: String, stateKey: String?, body: JsonDict, callback: MatrixCallback<Unit>): Cancelable
fun getStateEventLive(eventType: String, stateKey: String): LiveData<Optional<Event>>
fun getStateEvent(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): Event?
fun getStateEventLive(eventType: String, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData<Optional<Event>>
fun getStateEvents(eventTypes: Set<String>, stateKey: QueryStringValue = QueryStringValue.NoCondition): List<Event>
fun getStateEventsLive(eventTypes: Set<String>, stateKey: QueryStringValue = QueryStringValue.NoCondition): LiveData<List<Event>>
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.tags
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
/**
* This interface defines methods to handle tags of a room. It's implemented at the room level.
*/
interface TagsService {
/**
* Add a tag to a room
*/
fun addTag(tag: String, order: Double?, callback: MatrixCallback<Unit>): Cancelable
/**
* Remove tag from a room
*/
fun deleteTag(tag: String, callback: MatrixCallback<Unit>): Cancelable
}

View File

@@ -58,7 +58,7 @@ interface Timeline {
/**
* Check if the timeline can be enriched by paginating.
* @param the direction to check in
* @param direction the direction to check in
* @return true if timeline can be enriched
*/
fun hasMoreToLoad(direction: Direction): Boolean

View File

@@ -16,6 +16,7 @@
package im.vector.matrix.android.api.session.room.timeline
import im.vector.matrix.android.BuildConfig
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.RelationType
@@ -25,6 +26,7 @@ import im.vector.matrix.android.api.session.room.model.ReadReceipt
import im.vector.matrix.android.api.session.room.model.message.MessageContent
import im.vector.matrix.android.api.session.room.model.message.MessageStickerContent
import im.vector.matrix.android.api.session.room.model.message.isReply
import im.vector.matrix.android.api.session.room.sender.SenderInfo
import im.vector.matrix.android.api.util.ContentUtils.extractUsefulTextFromReply
import im.vector.matrix.android.internal.crypto.model.event.EncryptedEventContent
@@ -38,13 +40,17 @@ data class TimelineEvent(
val localId: Long,
val eventId: String,
val displayIndex: Int,
val senderName: String?,
val isUniqueDisplayName: Boolean,
val senderAvatar: String?,
val senderInfo: SenderInfo,
val annotations: EventAnnotationsSummary? = null,
val readReceipts: List<ReadReceipt> = emptyList()
) {
init {
if (BuildConfig.DEBUG) {
assert(eventId == root.eventId)
}
}
val metadata = HashMap<String, Any>()
/**
@@ -62,14 +68,6 @@ data class TimelineEvent(
}
}
fun getDisambiguatedDisplayName(): String {
return when {
senderName.isNullOrBlank() -> root.senderId ?: ""
isUniqueDisplayName -> senderName
else -> "$senderName (${root.senderId})"
}
}
/**
* Get the metadata associated with a key.
* @param key the key to get the metadata

View File

@@ -28,6 +28,14 @@ data class TimelineSettings(
* A flag to filter edit events
*/
val filterEdits: Boolean = false,
/**
* A flag to filter redacted events
*/
val filterRedacted: Boolean = false,
/**
* A flag to filter useless events, such as membership events without any change
*/
val filterUseless: Boolean = false,
/**
* A flag to filter by types. It should be used with [allowedTypes] field
*/
@@ -40,5 +48,4 @@ data class TimelineSettings(
* If true, will build read receipts for each event.
*/
val buildReadReceipts: Boolean = true
)

View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.uploads
data class GetUploadsResult(
// List of fetched Events, most recent first
val uploadEvents: List<UploadEvent>,
// token to get more events
val nextToken: String,
// True if there are more event to load
val hasMore: Boolean
)

View File

@@ -0,0 +1,32 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.uploads
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.model.message.MessageWithAttachmentContent
import im.vector.matrix.android.api.session.room.sender.SenderInfo
/**
* Wrapper around on Event.
* Similar to [im.vector.matrix.android.api.session.room.timeline.TimelineEvent], contains an Event with extra useful data
*/
data class UploadEvent(
val root: Event,
val eventId: String,
val contentWithAttachmentContent: MessageWithAttachmentContent,
val senderInfo: SenderInfo
)

View File

@@ -0,0 +1,35 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.room.uploads
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
/**
* This interface defines methods to get event with uploads (= attachments) sent to a room. It's implemented at the room level.
*/
interface UploadsService {
/**
* Get a list of events containing URL sent to a room, from most recent to oldest one
* @param numberOfEvents the expected number of events to retrieve. The result can contain less events.
* @param since token to get next page, or null to get the first page
*/
fun getUploads(numberOfEvents: Int,
since: String?,
callback: MatrixCallback<GetUploadsResult>): Cancelable
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.terms
import im.vector.matrix.android.internal.session.terms.TermsResponse
data class GetTermsResponse(
val serverResponse: TermsResponse,
val alreadyAcceptedTermUrls: Set<String>
)

View File

@@ -0,0 +1,37 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.session.terms
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
interface TermsService {
enum class ServiceType {
IntegrationManager,
IdentityService
}
fun getTerms(serviceType: ServiceType,
baseUrl: String,
callback: MatrixCallback<GetTermsResponse>): Cancelable
fun agreeToTerms(serviceType: ServiceType,
baseUrl: String,
agreedUrls: List<String>,
token: String?,
callback: MatrixCallback<Unit>): Cancelable
}

Some files were not shown because too many files have changed in this diff Show More