Compare commits

..

1902 Commits

Author SHA1 Message Date
dec591517c Merge branch 'release/0.18.0' 2020-03-11 13:41:49 +01:00
d5cbcdd4e7 prepare release 0.18.0 2020-03-11 13:41:17 +01:00
fe1af4e34f Merge pull request #1131 from vector-im/feature/fix_qr_self_verification
Fix / Self verification mode 1 was not working
2020-03-11 13:19:16 +01:00
49f2064439 Fix / Self verification mode 1 was not working 2020-03-11 11:43:23 +01:00
ff5b284b2e Try to remove rule that is breaking CI 2020-03-11 11:19:22 +01:00
d9085b1231 Merge pull request #1128 from vector-im/feature/remove_runblocking_crypto
Remove dangerous runBlocking (and un-needed)
2020-03-11 10:42:48 +01:00
a9074cdbbb Remove dangerous runBlocking (and un-nedded) 2020-03-10 17:25:04 +01:00
09946ecf1b Merge pull request #1117 from vector-im/feature/pusher_fix
Pusher fix
2020-03-10 11:34:11 +01:00
d21a536542 Merge pull request #1115 from vector-im/feature/work_manager_script
Add script to dumpsys work manager data
2020-03-06 17:31:19 +01:00
937d497a1f Revert the check box in case of error 2020-03-06 17:24:57 +01:00
4261b0e78a Fix pusher issue. It was set by mistake when the notification for this device was disabled 2020-03-06 17:19:48 +01:00
71446a1a74 Remove useless check 2020-03-06 17:11:23 +01:00
a29ec7b0be Pusher: add a menu to force a refresh of the local data 2020-03-06 16:48:48 +01:00
13036a5933 Pusher: update javadoc 2020-03-06 16:37:13 +01:00
35179509f2 Merge pull request #1111 from vector-im/feature/verification_code
Feature/verification code
2020-03-06 15:02:57 +01:00
5008524635 Add script to dumpsys work manager data 2020-03-06 14:52:09 +01:00
147766176c Merge pull request #1090 from vector-im/feature/notif
Restore the push rule settings
2020-03-06 14:43:33 +01:00
23862cb3d0 Merge branch 'develop' into feature/notif 2020-03-06 14:43:23 +01:00
2b8e2a312b Avoid use toImmutableList() 2020-03-06 14:39:33 +01:00
62fdb4c27a Use getOrPut() 2020-03-06 14:37:30 +01:00
b929a2f185 Merge pull request #1099 from vector-im/feature/fix_share_image
Share images from clear and encrypted rooms.
2020-03-06 14:27:47 +01:00
fb858bc112 Rename to respect naming convention #3 2020-03-06 14:04:02 +01:00
5d0e917f04 Rename to respect naming convention #2 2020-03-06 13:50:00 +01:00
e420070066 Rename to respect naming convention 2020-03-06 13:40:35 +01:00
4504308f25 Less "!!" 2020-03-06 13:34:12 +01:00
05683967c0 Code review fixes. 2020-03-06 12:07:38 +01:00
23c20acff1 Remove TODO 2020-03-06 10:11:30 +01:00
be5e6eaa93 Rename parameter type for code clarity 2020-03-06 10:10:16 +01:00
555863fecc Merge pull request #1112 from vector-im/feature/navigate_to_profile_from_avatar
Open room member profile from avatar of the room member state event.
2020-03-06 09:42:32 +01:00
b187699a86 Open room member profile from avatar of the room member state event. 2020-03-05 18:44:34 +01:00
d891da39e6 Merge pull request #1104 from vector-im/feature/buildkite
Pipeline file for Buildkite is now hosted on another Github repository
2020-03-05 18:20:17 +01:00
f37cd8cddc Merge pull request #1110 from vector-im/feature/cleanup
Cleanup
2020-03-05 18:18:49 +01:00
2d456d93a7 Common code step 2 2020-03-05 18:16:05 +01:00
de36a28541 Common code step 1 2020-03-05 18:00:35 +01:00
4634b963a2 Code cleanup 2020-03-05 17:55:13 +01:00
b3f887ca28 Code quality 2020-03-05 17:30:34 +01:00
3425dd0a63 Make the tests compile and pass 2020-03-05 17:28:35 +01:00
2a774833ec More optimization 2020-03-05 17:11:52 +01:00
bda4bbb59c More optimization 2020-03-05 16:45:49 +01:00
0828f9270e Create asValidObject method - make it works 2020-03-05 16:23:56 +01:00
e326631752 Create asValidObject method - make it compiles #2 2020-03-05 15:39:01 +01:00
a3f8a53a52 Create asValidObject method - make it compiles. 2020-03-05 15:29:44 +01:00
7b5a50ec6e Create asValidObject method - not compiling 2020-03-05 12:06:19 +01:00
36c52d24a7 Move method to interface step 3 2020-03-05 11:24:35 +01:00
1b29c7bf91 Move method to interface step 2 2020-03-05 11:22:42 +01:00
b6aee04e24 Move method to interface step 1 2020-03-05 11:21:44 +01:00
a264dcf5c4 Lint: fix TextFields 2020-03-05 11:09:58 +01:00
37afc983c3 Fix typos. The typos has been fixed on Weblate by me. 2020-03-05 11:02:14 +01:00
b10e9c54b4 Add BinaryOperationInTimber lint rule and fix existing errors 2020-03-05 10:40:36 +01:00
03d2cd0639 Lint fix. 2020-03-04 17:57:57 +01:00
b7ad50a3ce Make mimeType private to encourage using getSafeMimeType() method. 2020-03-04 16:52:52 +01:00
9cbaadedfb Unused context parameter is removed. 2020-03-04 16:52:08 +01:00
d6cdcc60d1 Remove unused png files 2020-03-04 16:48:13 +01:00
1680cd8d8e Merge branch 'develop' into feature/fix_share_image 2020-03-04 16:27:01 +01:00
d4384328fe Use "image/jpeg" instead of "image/jpg" 2020-03-04 16:26:09 +01:00
5fd8425289 Remove unused files 2020-03-04 16:09:37 +01:00
dcb618c257 Merge pull request #1103 from vector-im/feature/space_in_passwords
Detect spaces in password if user fails to login (#1038)
2020-03-04 14:12:20 +01:00
277ad9e042 Merge branch 'develop' into feature/space_in_passwords 2020-03-04 14:12:12 +01:00
26d387cc12 Support sharing other media types. 2020-03-04 13:47:48 +01:00
4aebe6d303 Disable TravisCI checks, now done by Buildkite 2020-03-04 12:23:25 +01:00
7eccda6e25 Pipeline file for Buildkite is now hosted on another Github repository
https://github.com/matrix-org/pipelines/blob/master/riotx-android/pipeline.yml
2020-03-04 12:20:09 +01:00
78bc2bbaa5 AndroidStudio cleanup 2020-03-04 12:15:33 +01:00
cde068f267 Merge pull request #1079 from vector-im/feature/ftue
FTUE: do not display a different color when encrypting message when not in developer mode.
2020-03-04 12:14:24 +01:00
c8f43e73e2 Merge branch 'develop' into feature/ftue 2020-03-04 12:14:07 +01:00
f106f92d7e Merge pull request #1085 from vector-im/feature/ktlint_upgrade
ktlint 0.36.0, Chromebook support, Camera for QR code scanning
2020-03-04 12:11:19 +01:00
fa0e07e146 Merge branch 'develop' into feature/ktlint_upgrade 2020-03-04 12:10:56 +01:00
d6df0e451c Detect spaces in password if user fail to login (#1038) 2020-03-04 10:39:10 +01:00
0121eee5b8 changelog 2020-03-04 09:37:32 +01:00
30e46445ca Add documentation to install environment and run integration tests (#1098)
Add documentation to install environment and run integration tests
2020-03-04 09:35:09 +01:00
7158554ee2 Add fallback logic only if the mode is thumbnail. 2020-03-03 16:56:22 +01:00
34c5537436 Fix fallback to full image. 2020-03-03 16:42:33 +01:00
d09ac8fbce Try to show full image as the fallback of the thumbnail. 2020-03-03 14:54:05 +01:00
319667096f Return Try.Failure instead of throwing exception. 2020-03-03 13:41:40 +01:00
c4f2eeeab7 Changelog added. 2020-03-03 10:40:58 +01:00
5f14516dec Share images from clear and encrypted rooms. 2020-03-03 10:39:24 +01:00
5ff670b184 Merge pull request #1093 from vector-im/feature/plain_text
Add support for `/plain` command (#12)
2020-03-02 19:37:05 +01:00
b7ff546f66 Add support for /plain command (#12) 2020-03-01 09:59:00 +01:00
c13b636bae Code cleanup 2020-02-29 10:05:48 +01:00
a05caf6f0e Update the 2 notification settings screens by moving some pref to the root notification screen 2020-02-29 09:49:21 +01:00
3462df405c Fix GPlay build issue 2020-02-29 09:42:35 +01:00
6009026e2f Notification settings: create a category for troubleshhot 2020-02-29 09:35:26 +01:00
06e0af9a5b small mistake 2020-02-28 22:12:30 +01:00
3987a68a9a Changelog 2020-02-28 22:10:07 +01:00
1228fcda0d Rename class 2020-02-28 19:25:29 +01:00
c20de4feb0 Cleanup 2020-02-28 19:13:22 +01:00
957b9eee23 Cleanup 2020-02-28 19:06:26 +01:00
e5eb36e917 Cleanup 2020-02-28 19:04:30 +01:00
551604cdcb Add missing push rules 2020-02-28 19:02:13 +01:00
8a2bafec5f Restore push rule settings - fix issues 2020-02-28 18:35:51 +01:00
3013e311a4 Restore push rule settings - WIP 2020-02-28 16:51:11 +01:00
1c35d07acc PushRuleService.getPushRules() now returns a RuleSet. Use getAllRules() on this object to get all the rules. 2020-02-28 16:29:58 +01:00
039924436f Json parsing 2020-02-28 14:51:35 +01:00
41b4f412c4 Merge pull request #1089 from vector-im/feature/crash_in_attachment_preview
Fix crash on attachment preview screen (#1088)
2020-02-28 14:49:36 +01:00
2abe29300b Merge pull request #1087 from vector-im/feature/verification_cleanup
Verification cleanup
2020-02-28 14:48:27 +01:00
779026b0af Fix / mark master key as trusted after self verif 2020-02-28 11:46:32 +01:00
151fec5ce0 Fix crash on attachment preview screen (#1088) 2020-02-28 11:38:30 +01:00
b1b8513da4 Create fromBase64Safe() to parse data received from external source 2020-02-27 19:17:14 +01:00
0a9008a73d Be robust if other client sends padded base64 in the reciprocate 2020-02-27 18:35:05 +01:00
1ead2778c2 ... and rename the method fromBase64NoPadding() to fromBase64() 2020-02-27 18:33:57 +01:00
8299487f6d Avoid using encoder flag to decode Base64 string... 2020-02-27 18:13:42 +01:00
ceab0903cf Improve code - TU passed 2020-02-27 18:09:37 +01:00
77dd911054 Code quality 2020-02-27 17:42:25 +01:00
a914381090 Verification with QrCode: ensure there is a Camera to scan QrCodes. 2020-02-27 17:03:48 +01:00
9f28738fd6 Restore availability to Chromebooks (#932) 2020-02-27 15:41:35 +01:00
36a848471f Enable other lint check (no change necessary in source) 2020-02-27 15:27:46 +01:00
12861aacda lint: check negative margin 2020-02-27 15:11:43 +01:00
d85776297d Lint: fix IconDuplicates by remove unused resources 2020-02-27 14:56:18 +01:00
50031bef50 Lint: fix IconDipSize and IconDuplicatesConfig error (by removing unused resource) 2020-02-27 14:45:26 +01:00
c0d6b9d130 Lint fix IconXmlAndPng error 2020-02-27 14:35:57 +01:00
a1466e299b Fix missing recycle call and ensure this mistake will not happen again 2020-02-27 14:30:49 +01:00
bc9493d5b9 Upgrade ktlint to version 0.36.0 2020-02-27 12:48:17 +01:00
9bb4c7ed25 Version++ 2020-02-27 12:34:33 +01:00
128f3493b7 Merge branch 'release/0.17.0' 2020-02-27 12:32:36 +01:00
65e5a04836 Merge branch 'release/0.17.0' into develop 2020-02-27 12:32:35 +01:00
495e4792b1 Prepare release 0.17.0 2020-02-27 12:32:03 +01:00
f906fc894b Sync Strings with Riot 2020-02-27 11:59:39 +01:00
6e060f63c6 Try to decode QrCode data in the debug Activity 2020-02-27 11:32:59 +01:00
9c7f5251b0 Merge pull request #1084 from vector-im/feature/room_key_share_crash
Fix crash after rework. RoomKeyShare is now an interface
2020-02-26 20:45:50 +01:00
a296234163 Fix crash after rework. RoomKeyShare is now an interface 2020-02-26 20:35:34 +01:00
a4d7b79e3c Merge pull request #1083 from vector-im/feature/last_fixies
Last fixes before release
2020-02-26 18:37:21 +01:00
3ac2296464 Disable freestyle crop, usability was not easy 2020-02-26 17:46:33 +01:00
b5a402c1e1 Fix crash when editing image 2020-02-26 17:45:39 +01:00
b8eeede5fd Safer code 2020-02-26 17:28:27 +01:00
d3e7e7e109 Make the small avatar also clickable and little change in the API to factorize code 2020-02-26 17:17:39 +01:00
a3af0be103 prevent wildcard for import 2020-02-26 17:01:38 +01:00
6349f9828d Optimize import 2020-02-26 16:59:20 +01:00
989d396c78 Rename package "sas" to "verification" 2020-02-26 16:52:16 +01:00
73ac7ab341 Compact code 2020-02-26 16:48:50 +01:00
a3133773a3 generic name for parameter 2020-02-26 16:45:12 +01:00
6e67d4749f Merge pull request #1082 from vector-im/feature/fix_rageshakes
Fix crashes reported by rageshakes
2020-02-26 16:10:47 +01:00
38c1ef3eb6 Fix lint issue 2020-02-26 16:08:34 +01:00
674450ef29 Merge pull request #1076 from vector-im/feature/fullscreen_avatar
Display avatar in fullscreen.
2020-02-26 16:06:13 +01:00
5e775298a7 Merge pull request #1081 from vector-im/feature/fix_redacted_event_format
Fix redacted event format on room overview.
2020-02-26 15:57:10 +01:00
93a687a172 Code review fixes. 2020-02-26 17:55:23 +03:00
4ba8a42977 Fix crash reported from rageshake 2020-02-26 15:32:52 +01:00
054d7668ef Fix crash reported from rageshake 2020-02-26 15:19:47 +01:00
a13fec84b0 Fix crash reported from rageshake 2020-02-26 15:00:25 +01:00
4bb3fb128f Fix crash reported from rageshake 2020-02-26 14:54:36 +01:00
04726a1ace Fix redacted event format on room overview.
Fixes #758
2020-02-26 16:51:01 +03:00
ccf72ffaa7 Fix crash reported from rageshake 2020-02-26 14:50:01 +01:00
d2efe0e10c Merge branch 'develop' into feature/fullscreen_avatar 2020-02-26 16:23:02 +03:00
054b467caf Fix crash reported from rageshake 2020-02-26 14:18:48 +01:00
4280bc0780 Fix crash reported from rageshake 2020-02-26 14:10:51 +01:00
e1ea742023 Fix crash reported from rageshake 2020-02-26 13:59:58 +01:00
b7cf7e06a7 Merge pull request #1015 from vector-im/feature/new_signin_passphrase
Feature/new signin passphrase
2020-02-26 13:56:31 +01:00
536dce7929 Code review fixes. 2020-02-26 15:30:03 +03:00
56fc91a8c3 Code review fixes. 2020-02-26 15:26:53 +03:00
6622e0daca Code quality 2020-02-26 12:43:41 +01:00
f35b0660ca Rename constant for code readability 2020-02-26 12:37:36 +01:00
9d1718cda8 post merge clean 2020-02-26 12:20:03 +01:00
f7c128be3d Fix tests 2020-02-26 12:20:03 +01:00
c80fb52410 dead code 2020-02-26 12:20:03 +01:00
32389e1291 Remove wizard stuff 2020-02-26 12:20:03 +01:00
99f9a9817e Use human readable error (not technical) 2020-02-26 12:20:03 +01:00
b4a783198b code review 2020-02-26 12:20:03 +01:00
0cfc9451ca Cleaning 2020-02-26 12:20:03 +01:00
4b75baf772 Fix / trust was not properly updated after 4S restore 2020-02-26 12:20:03 +01:00
c579de1033 Fix / Test crash when crypto DB closed
Quick Work around
2020-02-26 12:20:03 +01:00
d537abc522 Fix / sign current device after entering xsigning passphrase 2020-02-26 12:20:03 +01:00
030f027516 Fixes #1051
XSigning | Self verification Empty bottomsheet
2020-02-26 12:20:03 +01:00
cbd7c1aa63 Fix / Bad ordering of active sessions 2020-02-26 12:20:03 +01:00
bdb1df75d4 Check trust on crypto thread 2020-02-26 12:20:03 +01:00
817dc19b9a Cleaning 2020-02-26 12:20:03 +01:00
f9be4fa2bd Fixes #1047 2020-02-26 12:20:03 +01:00
412aed6dcb Fix / Update title before return 2020-02-26 12:20:03 +01:00
9fc44c11de Fixes #937
Disabling bounds change animation, as it's messing with fragment change apparition and expanded state of bottomsheet
2020-02-26 12:20:03 +01:00
bf23094158 Fix / Green shield in conclusion title when verified from private keys 2020-02-26 12:20:03 +01:00
94d36e0c85 cleaning jni 2020-02-26 12:20:03 +01:00
0064934db9 Changed Encryption algorithm of 4S 2020-02-26 12:20:03 +01:00
e2e4ddf5ba Post rebase fix 2020-02-26 12:20:03 +01:00
9a08f5ec4e WIP / Verify from passphrase UX 2020-02-26 12:19:31 +01:00
cb669ad881 4S Activity WIP 2020-02-26 12:15:59 +01:00
3dc89c8d87 Update Self Verification BottomSheet for quads 2020-02-26 12:15:59 +01:00
cb73955946 Merge pull request #1050 from vector-im/feature/fix_some_perf
Feature/fix some perf
2020-02-26 12:02:36 +01:00
bfe15555a1 Update changes 2020-02-26 11:51:05 +01:00
bddeb6cb72 Clean files 2020-02-26 11:50:41 +01:00
d57f6838e9 Remove decryption from room summary mapper and make TimelineEventDecryptor scoped to session 2020-02-26 11:50:41 +01:00
cf8ffa3a7a Force trust task on crypto dispatcher to use cached realm from crypto store 2020-02-26 11:49:08 +01:00
a69049645a FTUE: do not display a different color when encrypting message when not in developer mode. 2020-02-26 11:25:37 +01:00
40b4db4a64 Merge pull request #1060 from vector-im/feature/data_class_cleanup
Data class cleanup
2020-02-26 10:57:10 +01:00
246b39786c Merge pull request #1073 from vector-im/feature/improve_api
Improve api of CreateRoomParams
2020-02-26 10:55:48 +01:00
1a273407de Display avatar in fullscreen. 2020-02-26 12:12:49 +03:00
633f9d8522 ktlint 2020-02-26 09:55:57 +01:00
076ac23b38 Modification done by AndroidStudio 3.6 2020-02-26 07:59:54 +01:00
67180fd8db New direct chat: selecting several participants was not adding the room to the direct chats list 2020-02-26 07:38:10 +01:00
fc95bf4926 Improve CreateRoomParams API: update some API for better chaining of builder like methods (#1070) 2020-02-26 07:32:22 +01:00
e73f138151 Improve CreateRoomParams API: update Javadoc and ensure the return values will not be discarded (#1070) 2020-02-26 07:17:25 +01:00
30432cd3f4 Merge pull request #1069 from vector-im/feature/fix_dm
Fix dm chips
2020-02-25 19:28:46 +01:00
1072060cbb New direct chat: selecting a participant sometimes results in two breadcrumbs (#1022) 2020-02-25 19:00:38 +01:00
a55e0f1af4 Fix crash - workaround 2020-02-25 18:17:40 +01:00
b95dfa4473 Create getBestName method for User 2020-02-25 18:14:02 +01:00
ec0cba2b23 Merge pull request #1067 from vector-im/feature/roomId
Display internal id of a room section in room profile
2020-02-25 12:22:14 +01:00
cfe9c4bb41 Display internal id of a room section in room profile, with copy to clipboard action, only in developer mode 2020-02-25 12:21:04 +01:00
68400cce03 Merge pull request #1049 from vector-im/feature/fix_invites
Feature/fix invites
2020-02-25 11:39:35 +01:00
17e028178e Code robustness (avoid using !!) 2020-02-25 11:20:11 +01:00
19b9617a09 Invite: fix inviterId being overrided 2020-02-25 10:53:47 +01:00
08e4b4473c Disable manual rules now checked by ktlint 2020-02-25 09:57:12 +01:00
b9b921a4df Code quality 2020-02-25 09:53:17 +01:00
483256093a Invite: fix room member not saved 2020-02-24 18:27:18 +01:00
d710a59554 Update change log 2020-02-24 17:44:51 +01:00
1023982858 Code readability 2020-02-24 17:40:28 +01:00
9c566b19f7 Ensure all eventId start with $, even ids for local echo 2020-02-24 17:35:43 +01:00
b694721728 Update CHANGES 2020-02-24 17:33:40 +01:00
8b0305c91d Clean code 2020-02-24 17:33:40 +01:00
133d8d7f14 RoomList: fix joining/rejecting state 2020-02-24 17:33:40 +01:00
9cdb1da614 Start fixing notif for invites 2020-02-24 17:33:40 +01:00
981c9ac4ac Invite sync: assign eventId and remove the primaryKey constraint 2020-02-24 17:33:40 +01:00
3e8a0f7252 Merge pull request #1044 from vector-im/feature/fix_big_image_rotation
Use exif info of the image for correct rotation.
2020-02-24 17:30:33 +01:00
281620b88d Merge pull request #1048 from vector-im/feature/profile_share_actions
Share action is added to room profile and room member profile
2020-02-24 17:29:17 +01:00
c6b3b1e648 Fix bug on test 2020-02-24 17:27:04 +01:00
96af1957f9 Fix bug on progress step, found by integration test testBackupWithPassword() 2020-02-24 16:27:58 +01:00
b680e24938 Fix some tests 2020-02-24 16:16:37 +01:00
dec62a893e Code review fixes. 2020-02-24 18:06:59 +03:00
b3d4747d97 Code review fixes. 2020-02-24 17:35:57 +03:00
1124aa25fd Code review fixes. 2020-02-24 17:22:07 +03:00
b3c8b5526d Each session now have it's proper crypto store 2020-02-24 15:03:12 +01:00
1e44e77503 Make code robust to int received instead of boolean
https://github.com/matrix-org/synapse/issues/6977
2020-02-24 14:42:47 +01:00
964b611f4e Merge pull request #1053 from vector-im/feature/fix_712
Fixes #712
2020-02-24 14:07:35 +01:00
3e587af163 klint 2020-02-24 14:07:15 +01:00
b03b6bfc37 Fix crash discovered thanks to integration tests 2020-02-24 12:53:18 +01:00
1a6d4d0b03 Try to fix XSigningTest 2020-02-21 19:20:40 +01:00
c41661ece8 Fixes #712 2020-02-21 19:05:20 +01:00
1b763fb4c8 Cleanup XSigningTest 2020-02-21 18:52:36 +01:00
9ef267cb07 Cleanup after each test 2020-02-21 18:36:13 +01:00
d167ff9496 Make KeysBackup test pass (still work to do) 2020-02-21 17:58:04 +01:00
ccfa59ad31 Cleanup var -> val 2020-02-21 15:05:48 +01:00
f650e29ddd Share action is added to room profile and room member profile
Fixes #858
2020-02-21 15:30:01 +03:00
1eefda18e4 Merge branch 'develop' into feature/fix_big_image_rotation 2020-02-21 13:13:02 +03:00
d6434654e2 Merge pull request #1043 from vector-im/feature/join_federation
Fix join room over federation
2020-02-21 10:08:05 +01:00
b6372df676 Merge pull request #1037 from vector-im/feature/crosssigning_qr
Migrate to binary QR code verification (#994)
2020-02-21 10:01:49 +01:00
d7de072155 typo 2020-02-21 09:58:56 +01:00
a11d70f173 Use exif info of the image for correct rotation. 2020-02-21 00:51:22 +03:00
a9909b37ba Update after Valere's review 2020-02-20 19:54:35 +01:00
3f9a5a4e54 Leaving a room creates a stuck "leaving room" loading screen. (#1041) 2020-02-20 19:31:33 +01:00
198e23c204 Second fix for #808 2020-02-20 19:23:32 +01:00
aefffc0c05 RoomPreviewNoPreviewFragment use room alias if there is no name 2020-02-20 19:19:31 +01:00
fd05fe36f5 Fix joining rooms from directory via federation isn't working. (#808) 2020-02-20 19:01:36 +01:00
b72698d63c Fix another issue when there is no name and no canonical alias on a public room 2020-02-20 18:47:07 +01:00
eec65fb622 Join room by roomId or room alias 2020-02-20 18:17:57 +01:00
87021dd6ec Rename field 2020-02-20 18:16:10 +01:00
b85c76b172 Simplify code 2020-02-20 18:05:53 +01:00
d867b1345f Format 2020-02-20 15:15:38 +01:00
80ef2192b9 Merge pull request #1036 from vector-im/feature/fix_key_restoring
Fix threading issues while restoring keys backup.
2020-02-20 15:13:13 +01:00
7d232527c8 Documentation of the API change is added. 2020-02-20 16:39:48 +03:00
e61d563589 Split long lines 2020-02-20 10:16:09 +01:00
74175ddfa0 Add a test and create extension for Byte to avoid using UByte (still experimental) 2020-02-20 10:12:07 +01:00
382fc6f05c Fix issue with long transactionId 2020-02-19 18:59:39 +01:00
932c478ed5 Change log 2020-02-19 18:11:23 +01:00
e81439d57b Remove v2 suffix 2020-02-19 18:09:33 +01:00
f81eb298cb Cleanup QRCode v1 2020-02-19 18:06:51 +01:00
859b9e4f8e Migrate to QrCode v2 - TODO: cleanup 2020-02-19 17:50:30 +01:00
e00d3ef63d QrCodeV2 WIP (al tests passing) 2020-02-19 17:34:07 +01:00
a97971dd84 Fix threading issues while restoring keys backup. 2020-02-19 18:30:12 +03:00
35b10daef1 Ensure RiotX is able to scan binary QrCodes 2020-02-19 14:26:45 +01:00
66a2958c39 Add unit test to check byte array to string conversion 2020-02-19 14:21:41 +01:00
571db7da55 Merge pull request #1035 from vector-im/feature/share_text
Fix share text to a single room issue
2020-02-19 10:08:29 +01:00
c6b231c0b1 Create toState() fun and use the enum 2020-02-18 14:12:50 +01:00
53410789c0 Cleanup 2020-02-18 14:12:50 +01:00
f8276e48e3 add kluent for test 2020-02-18 14:09:42 +01:00
86c38ebd2d Create Set.toggle() method 2020-02-18 13:33:49 +01:00
d730f96c41 Do not show alert when sharing text to a single room 2020-02-18 12:24:27 +01:00
7b3fcb7798 When sharing to a room save a draft to pre-fill the composer 2020-02-18 12:11:51 +01:00
26e8a60312 Merge pull request #1032 from vector-im/feature/crash
Fix crash in the room directory, when public room has no name (#1023)
2020-02-18 11:48:29 +01:00
7133d513b4 Fix crash in the room directory, when public room has no name (#1023) 2020-02-18 10:45:14 +01:00
8d1b2b35fd Merge pull request #1010 from vector-im/feature/attachment_process
Attachment process
2020-02-18 09:19:17 +01:00
b811bf9e7f Fix issue after merge 2020-02-17 23:21:08 +01:00
ebda12dd76 Merge branch 'develop' into feature/attachment_process 2020-02-17 19:22:50 +01:00
adc545a93d Merge pull request #1026 from vector-im/feature/crypto_service_renaming
Feature/crypto service renaming
2020-02-17 19:21:02 +01:00
fc740ae347 Merge pull request #1016 from vector-im/feature/cleanup_quadS
Cleanup quad s and AccountData service
2020-02-17 18:52:23 +01:00
67ed86fee5 Rename KeysBackup to DefaultKeysBackupService 2020-02-17 18:51:06 +01:00
f716e9d789 Fix compilation issue 2020-02-17 18:49:45 +01:00
141c7d6af0 Update comment 2020-02-17 18:43:04 +01:00
7495533edc Use let 2020-02-17 18:16:37 +01:00
f2f94c4a93 Reduce code duplication 2020-02-17 17:56:11 +01:00
4995c14f69 Add log 2020-02-17 17:46:15 +01:00
002e881704 Fix multiple share intent issue 2020-02-17 17:26:19 +01:00
51bbee297c Remove useless confirmation when shared data are previewables 2020-02-17 17:06:15 +01:00
82bd8a2e2a Ask for write permission before editing media 2020-02-17 16:29:10 +01:00
d67cd2cbef Small iteration on UI 2020-02-17 16:21:10 +01:00
6d2025b61a Update CHANGES 2020-02-17 15:54:17 +01:00
91cbcebf73 Make test compile 2020-02-17 15:50:42 +01:00
fd0dceb597 Clean code 2020-02-17 15:23:24 +01:00
48a033b3bd Fix navigation issue when sharing text to multiple rooms 2020-02-17 14:58:20 +01:00
a3b205b310 No preview for elements sent from the keyboard 2020-02-17 14:48:12 +01:00
ca0cd9e97d Better code 2020-02-17 14:38:56 +01:00
31d5578063 Media preview: do not propose to edit Gif 2020-02-17 14:35:57 +01:00
b6f5e27155 Fix issue after merge of develop 2020-02-17 13:50:36 +01:00
13d3aa9ff1 Merge branch 'develop' into feature/attachment_process 2020-02-17 13:48:21 +01:00
629ecf786a Merge pull request #1024 from vector-im/feature/wording
Account creation: wrongly hints that an email can be used to create an account (#941)
2020-02-17 13:34:04 +01:00
ecf07ff64a Account creation: wrongly hints that an email can be used to create an account (#941) 2020-02-17 10:30:54 +01:00
e349a35419 Crypto: expose cryptoService by a getter, removing the session implementation delegation 2020-02-16 15:40:31 +01:00
a61f508b5d Fix a nice bug 2020-02-14 22:00:36 +01:00
76085a4284 AccountData cleanup and Javadoc 2020-02-14 21:50:37 +01:00
446d826dd3 Create tag interface AccountDataContent 2020-02-14 20:53:45 +01:00
2d6f57e214 More cleanup/code lisibility 2020-02-14 20:50:21 +01:00
a305ce302e Coroutine sequencer: use semaphore 2020-02-14 19:37:51 +01:00
7ddea99fc6 Move and improve withOlmDecryption() and withOlmEncryption() 2020-02-14 18:51:27 +01:00
4c3b754de4 Use const from DefaultSharedSecretStorageService 2020-02-14 18:33:15 +01:00
7878da25b8 Use doSync<>() to reduce boilerplate and add test checks
and more cleanup
2020-02-14 18:18:20 +01:00
01597a89dc Avoid code duplication 2020-02-14 17:53:27 +01:00
b04ee7153a Merge pull request #995 from vector-im/feature/4s_msc1946
Feature/4s msc1946
2020-02-14 17:49:16 +01:00
db19ab0531 Merge branch 'develop' into feature/4s_msc1946 2020-02-14 17:45:44 +01:00
cad818c341 ktlint 2020-02-14 17:05:14 +01:00
1660a0f846 Version++ 2020-02-14 15:16:00 +01:00
56677f0908 Merge branch 'release/0.16.0' 2020-02-14 15:14:55 +01:00
4987a75039 Merge branch 'release/0.16.0' into develop 2020-02-14 15:14:54 +01:00
e20d1724c9 Prepare release 0.16.0 2020-02-14 15:14:48 +01:00
f6f9c349ec Add entry in changelog for the 2 mistakes 2020-02-14 14:52:10 +01:00
88b8ceaeb5 Merge pull request #1005 from vector-im/feature/fix_event_redaction_prompt
Do not ask for a reason if user wants to delete his own message.
2020-02-14 14:36:01 +01:00
e4577d8fef Small cleanup before merge 2020-02-14 14:34:22 +01:00
030d6824e3 Code review fixes. 2020-02-14 15:04:25 +03:00
ab437e249d Update emoji for API change 2020-02-14 12:43:27 +01:00
35835be03e klint 2020-02-14 12:06:07 +01:00
f99eca8014 Code review 2020-02-14 10:48:18 +01:00
e0eede1150 cleaning 2020-02-14 10:48:18 +01:00
64647cb465 Fix / Save account data after update (local echo) 2020-02-14 10:48:18 +01:00
def01cca8f Fix test + changes 2020-02-14 10:48:18 +01:00
61ea4191dc Update json viewer lib 2020-02-14 10:48:18 +01:00
108ebea84e SSSS service + test 2020-02-14 10:48:18 +01:00
bf06b57bad Refactor Account Data
Auto stash before rebase of "develop"
2020-02-14 10:48:18 +01:00
a250a895fe Remove redudant calls to eventBus post 2020-02-14 10:47:34 +01:00
2c2bf61727 Update Changelog 2020-02-14 09:40:07 +01:00
6c0bddc893 Code quality 2020-02-13 23:20:35 +01:00
930d62c87b Restore Breadcrumbs comparator, we can maybe improve this later 2020-02-13 23:00:03 +01:00
b66b96899e Better Kotlin code 2020-02-13 22:56:11 +01:00
e6bd09859f Compress image before sending 2020-02-13 22:50:55 +01:00
385fa317c0 Add a green frame around current small preview 2020-02-13 20:45:03 +01:00
ecd547b86c Auto close the room picker and open the first room when data are shared in case of multi selection 2020-02-13 20:10:59 +01:00
d87b951403 Improve code 2020-02-13 20:10:59 +01:00
06ba478232 Send files to several rooms at a time 2020-02-13 20:10:59 +01:00
81de914360 Propose to edit media before sending, when coming form another application 2020-02-13 20:10:59 +01:00
b7ec495d6b Add comment 2020-02-13 19:52:11 +01:00
a8953568f3 Set custom colors 2020-02-13 19:52:11 +01:00
41b20863fb Mention uCrop library copyright 2020-02-13 19:52:11 +01:00
94340a49d7 Ask for permission 2020-02-13 19:52:11 +01:00
c67fd508e7 Cleanup 2020-02-13 19:52:11 +01:00
eccc52fe13 Sharing: start extracting from RoomList as it's getting messy 2020-02-13 19:52:11 +01:00
b7a7aa2f15 Attachment: continue working on preview screen 2020-02-13 19:52:11 +01:00
6471787232 Share: start managing multi selection and warning 2020-02-13 19:52:11 +01:00
41f1ec5d88 Attachments: preview with pager mode 2020-02-13 19:51:20 +01:00
a26e959430 Attachements: introduce structure for preview, cropping and compressing 2020-02-13 19:51:20 +01:00
5808c1de22 TextView displaying emoji should have text color set to black 2020-02-13 19:50:31 +01:00
d21604b791 Merge pull request #989 from vector-im/feature/qr_code_mistake
Fix issue with verification when other client declares it can only show QR code (#988)
2020-02-13 19:41:10 +01:00
fd135e1eeb Compute message body for encrypted messages too. 2020-02-13 18:09:26 +03:00
f28e4cf991 Fix comparison of user ids. 2020-02-13 17:57:38 +03:00
1941862499 Fix / Remove debug code line 2020-02-13 15:50:08 +01:00
983593d647 getRedactionReason function is refactored. 2020-02-13 17:28:14 +03:00
1b413934b5 Set redaction reason as message body. 2020-02-13 16:42:13 +03:00
8a3e93ae96 Do not ask for a reason if user wants to delete his own message.
Fixes (#1003)
2020-02-13 14:59:41 +03:00
5191cbaf93 Merge pull request #1001 from vector-im/feature/pusher_service
Cleanup pusher service and improve API
2020-02-13 08:02:33 +01:00
f2e6900cfb Move throw line 2020-02-13 07:44:54 +01:00
0b7e757f3c Code lisibility: use generic name for parameters in Dagger modules 2020-02-13 07:12:11 +01:00
5b2c947af1 Rename internal class 2020-02-13 07:05:46 +01:00
6a69c6356d PushersService.pushers() has been renamed to PushersService.getPushers() 2020-02-13 07:04:54 +01:00
e492e4318b Do some parameter checks 2020-02-13 06:48:52 +01:00
93d38843c3 Add Javadoc 2020-02-13 06:36:21 +01:00
7d94519064 Merge pull request #998 from vector-im/feature/msc_2192_update_event_prefix
Use vendor prefix for non merged MSC
2020-02-12 22:41:12 +01:00
21bac0f867 Fix / typo in poll 2020-02-12 22:31:13 +01:00
32c4ad9ecb Use vendor prefix for non merged MSC 2020-02-12 19:09:23 +01:00
e1342d096b Merge pull request #810 from vector-im/feature/msc_2192
Feature/msc 2192
2020-02-12 17:41:50 +01:00
e91c6c216d code quality 2020-02-12 17:03:21 +01:00
6013e1653b Open room member profile from reactions and read receipts. (#990)
Open room member profile from reactions and read receipts. Fixes #875
2020-02-12 15:57:49 +01:00
47f47e40c4 code review and cleanup 2020-02-12 15:09:38 +01:00
9016688aec Fix compilation issue after rebase 2020-02-12 13:48:08 +01:00
d5f8a0c0fc code quality 2020-02-12 13:40:54 +01:00
33c657bff8 Update change log 2020-02-12 13:40:54 +01:00
9a7bd35ddc Add m.buttons support (a.k.a bot buttons) 2020-02-12 13:40:54 +01:00
3ac54c51f6 cleaning 2020-02-12 13:39:30 +01:00
c4ea2507f8 Add command to send poll 2020-02-12 13:39:30 +01:00
6001ac60ab klint cleaning 2020-02-12 13:37:16 +01:00
0cea26ec77 ux tweak on poll result 2020-02-12 13:37:16 +01:00
3dae220501 Fix / filter edits and poll response form lastPreviewableMessage 2020-02-12 13:37:16 +01:00
577c5a16b3 Support incremental poll response aggregation + display 2020-02-12 12:47:28 +01:00
a0aebed3f7 Message Poll UX, and model 2020-02-12 12:42:17 +01:00
3a044bd655 Add Javadoc 2020-02-12 11:39:36 +01:00
6acfab3242 Rename VerificationListener to Listener 2020-02-12 11:39:36 +01:00
bf02746d87 Clenaup VerificationService.VerificationListener 2020-02-12 11:39:36 +01:00
377d944228 Cleanup API 2020-02-12 11:39:36 +01:00
6ff974b3ea Fix issue with verification when other client declares it can only show QR code (#988) 2020-02-12 11:39:36 +01:00
7c5bb4ff5b Merge pull request #986 from vector-im/feature/fix_clear_cache_notification_click
Fix crash by removing all notifications after clearing cache.
2020-02-11 18:06:16 +03:00
3573aea600 Fix crash by removing all notifications after clearing cache.
Fixes #878
2020-02-11 16:48:28 +03:00
251de0b89c Merge pull request #982 from vector-im/feature/remove_message_step2
Redact message step2
2020-02-11 11:35:16 +01:00
6fce2a3066 Change wording adding "..." because there is now confirmation dialog
And make the item red because it is destructive. Also use "redact" terminology
2020-02-11 11:04:21 +01:00
b40da4ef0f Disable TextInputLayout instead of TextInputEditText 2020-02-11 11:00:33 +01:00
96341df5e7 Format layout 2020-02-11 11:00:01 +01:00
7ccc1c559c Merge pull request #977 from vector-im/feature/event_deletion_dialog
Show confirmation dialog before deleting a message
2020-02-11 10:45:17 +01:00
35ed22ab2b improve script 2020-02-11 10:38:13 +01:00
afbd9cff70 Merge branch 'develop' into feature/event_deletion_dialog
# Conflicts:
#	CHANGES.md
#	vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt
2020-02-11 12:11:36 +03:00
ce028f8bd2 Gathering reason input is refactored. 2020-02-11 00:10:24 +03:00
a7274b9df0 Version++ 2020-02-10 21:41:59 +01:00
c498416075 Merge branch 'release/0.15.0' 2020-02-10 21:40:36 +01:00
a9d6cb7be3 Merge branch 'release/0.15.0' into develop 2020-02-10 21:40:35 +01:00
d71797319c Prepare release 0.15.0 2020-02-10 21:40:27 +01:00
ba0133a047 Reason input for redacting event is added. 2020-02-10 23:03:37 +03:00
01a7ea0bd7 Merge branch 'feature/fix_notif' into develop 2020-02-10 19:16:20 +01:00
2e7fa23ce7 Fix #980 2020-02-10 19:13:35 +01:00
6750237764 Merge pull request #976 from vector-im/feature/viewEvents
Use View events
2020-02-10 16:46:21 +01:00
588a644e02 Merge pull request #975 from vector-im/feature/cleanup
Cleanup push rule code
2020-02-10 16:32:24 +01:00
1bc1c8ec4a Reorder improvements. 2020-02-10 18:17:22 +03:00
7e362be568 Convert to ViewEvents -> Cleanup after review 2020-02-10 16:10:57 +01:00
83d83e0812 Show confirmation dialog before deleting a message
Fixes #967
2020-02-10 17:58:48 +03:00
c97d298166 Merge pull request #948 from vector-im/feature/artifacts_downloading
Feature/artifacts downloading
2020-02-10 14:52:25 +01:00
81413e49bc Remove '(yet)' 2020-02-10 14:51:35 +01:00
b24f133105 Import strings from Riot 2020-02-10 14:50:21 +01:00
5b13be6332 Rename 2020-02-07 19:58:14 +01:00
abeb741cad Convert to ViewEvents -> RoomDetailViewModel part 5 2020-02-07 19:50:15 +01:00
84e1169525 Convert to ViewEvents -> RoomDetailViewModel part 4 2020-02-07 19:45:54 +01:00
27e217fce5 Convert to ViewEvents -> RoomDetailViewModel part 3 2020-02-07 19:41:23 +01:00
bdb1f850b2 Convert to ViewEvents -> RoomDetailViewModel part 2 2020-02-07 19:37:30 +01:00
0338535efa Convert to ViewEvents -> RoomDetailViewModel part 1 2020-02-07 19:27:18 +01:00
0dd3894a49 Use handle() pattern 2020-02-07 19:20:02 +01:00
c8ff8d3c9e Convert to ViewEvents -> DeviceListBottomSheetViewModel 2020-02-07 18:59:31 +01:00
70973c3302 Convert to ViewEvents -> CrossSigningSettingsViewModel 2020-02-07 18:47:54 +01:00
a930313bf3 Convert to ViewEvents -> VerificationBottomSheetViewModel 2020-02-07 18:27:13 +01:00
35054dc5e8 Convert to ViewEvents -> CreateDirectRoomViewModel 2020-02-07 18:11:53 +01:00
33b123f719 Convert to ViewEvents -> GroupListViewModel 2020-02-07 18:02:42 +01:00
24667f38b8 Convert to ViewEvents -> RoomMemberProfileViewModel 2020-02-07 17:47:37 +01:00
256a6e4322 Convert to ViewEvents -> RoomDetailViewModel 2020-02-07 17:34:26 +01:00
7f5cc77ee0 Convert to ViewEvents -> DevicesViewModel 2020-02-07 17:14:03 +01:00
c34307ecf7 Convert to ViewEvents -> RoomDirectoryViewModel 2020-02-07 16:32:01 +01:00
dd13b6bd99 Add test for DisplayName condition (passing) 2020-02-07 15:44:46 +01:00
9df699db59 Reorder tests 2020-02-07 15:35:09 +01:00
8bdb2b88fd make the test compile 2020-02-07 15:32:36 +01:00
2a534b5874 Handle SenderNotificationPermissionCondition 2020-02-07 15:32:20 +01:00
f719da96ed Rename Condition.Kind enum values and add some documentation 2020-02-07 15:02:39 +01:00
31e5c0eb1a Improve algorithm 2020-02-07 14:48:08 +01:00
34c5f37bbc findAll() does not return null value 2020-02-07 14:30:44 +01:00
9aadbbc3c7 Rework DefaultConditionResolver, and create RoomGetter 2020-02-07 14:27:24 +01:00
57758af2d7 Merge pull request #974 from vector-im/feature/crosssigning_cleanup
Improve prompt password dialog
2020-02-07 14:02:15 +01:00
0a2474ef12 ktlint 2020-02-07 14:01:18 +01:00
67bc100782 Merge pull request #959 from vector-im/feature/roomshields_perf
Refactor Room Shield / Profile shield
2020-02-06 16:54:17 +01:00
5fedfd9286 Cleanup 2020-02-06 16:00:05 +01:00
1917fbcc93 eventBus private 2020-02-06 13:56:57 +01:00
a48bf61ad7 quick dispatch to correct thread (will need more work) 2020-02-06 13:56:57 +01:00
5c1fcc47a1 Catch all decryption fails in mapping 2020-02-06 13:56:57 +01:00
d80c15f52f Dispatch init on crypto thread to avoid blocking cold start 2020-02-06 13:56:57 +01:00
3e2219cbb5 Ignore interrupted exception in setupRx 2020-02-06 13:56:57 +01:00
bf2e01b8c3 More Rx startWithcallable 2020-02-06 13:56:57 +01:00
75131fdf44 Post merge fix 2020-02-06 13:56:57 +01:00
911ff8cf16 cleaning (klint) 2020-02-06 13:56:57 +01:00
4506b7d6e6 Fix / annoying loading to get active sessions
Start with what's known locally
2020-02-06 13:56:57 +01:00
320dc4accd Refactor Room Shield / Profile shield 2020-02-06 13:56:57 +01:00
ffc9a595dd Merge pull request #964 from vector-im/feature/firefox_account_sso
Support SSO login with Firefox account (#606)
2020-02-06 11:28:16 +01:00
1602c6544f We have too many strings... 2020-02-05 18:06:39 +01:00
79242c8c16 Merge pull request #892 from vector-im/feature/indonesian_check
Import Indonesian resource check from TravisCI to Weblate pipeline
2020-02-05 18:02:00 +01:00
7d00aabc85 Share the same Copyright header. Disabled for XML files 2020-02-05 17:48:59 +01:00
ef72f2246a Import Indonesian resource check from TravisCI to Weblate pipeline 2020-02-05 17:47:11 +01:00
51c2b9e1e9 Import strings from Riot 2020-02-05 17:35:23 +01:00
2a4c8b3199 Support SSO login with Firefox account (#606) 2020-02-05 15:21:54 +01:00
3189c114dc Merge pull request #945 from vector-im/feature/stabilization_2
Feature/stabilization 2
2020-02-05 15:19:16 +01:00
50814dafe9 Update wording 2020-02-05 14:19:04 +01:00
dcd7d17ffd Fix compilation issue after merge and update CHANGES.md 2020-02-05 14:13:43 +01:00
d9c007d017 Merge branch 'develop' into feature/stabilization_2 2020-02-05 12:57:42 +01:00
05dd587fa8 Move FORMAT_MATRIX_HTML to a proper object and so fix a wrong usage issue 2020-02-05 12:44:31 +01:00
3384d91adb Rename MessageContent.type to MessageContent.msgType for code clarity and update a few the Javadoc 2020-02-05 12:39:26 +01:00
f72e5c1d94 Explain why and when to use EllipsizingTextView 2020-02-05 12:16:43 +01:00
a3ec0e03a0 Use NoOpMatrixCallback when it's possible 2020-02-05 12:05:12 +01:00
47ee2a24a7 Move NoOpMatrixCallback to MatrixCallback.kt file 2020-02-05 11:58:08 +01:00
b8096f21ea Restore Copyright and cleanup 2020-02-05 11:56:07 +01:00
a17ec14dd7 Cleanup and little change on Throwable logging 2020-02-05 11:39:23 +01:00
062c4559a2 Merge pull request #955 from vector-im/feature/room_history_in_e2e
Feature/room history in e2e
2020-02-04 21:18:26 +01:00
f7d511df38 Ganfra's review 2020-02-04 17:48:17 +01:00
6bff951c72 Keep MXCryptoConfig, but do a correct usage of it 2020-02-04 15:37:46 +01:00
bd033866a8 Encrypt for invited users by default, if the room state allows it (#803) 2020-02-04 14:41:32 +01:00
3e9b2e4a06 Use the correct enableEncryption() method 2020-02-04 14:04:48 +01:00
ed9c3379bf Rename file 2020-02-04 13:50:10 +01:00
1728d31401 Fix some issues and make test passes 2020-02-04 13:19:02 +01:00
225a6e00e6 Add doc and reorder 2020-02-04 12:10:51 +01:00
96a729ab2b Move file 2020-02-04 11:53:09 +01:00
badb4042ce Add sign_apk_unsafe.sh to the repo 2020-02-04 11:53:09 +01:00
c3bb421c1e ignore .idea/inspectionProfiles 2020-02-04 11:53:09 +01:00
09212a05d0 Add a script to download artifacts from buildkite 2020-02-04 11:53:09 +01:00
e02430bcd0 Ask for permission before opening the camera (#934) 2020-02-03 20:06:37 +01:00
4335fa4f72 ktlint 2020-02-03 16:26:18 +01:00
6df5edbad1 Version++ 2020-02-03 16:20:55 +01:00
007fbf8ed3 Merge branch 'release/0.14.3' 2020-02-03 16:17:55 +01:00
362799ac08 Merge branch 'release/0.14.3' into develop 2020-02-03 16:15:52 +01:00
0049af7980 Prepare version 0.14.3 2020-02-03 16:15:38 +01:00
f454078c6b Clean code 2020-02-03 16:14:36 +01:00
783a514496 Improve prompt password dialog
Reveal password, inline error when empty
2020-02-03 15:53:44 +01:00
88755a79b4 In memory sending: fix broken filtering 2020-02-03 15:18:19 +01:00
e6cd8a3a86 Merge develop into feature/stabilization_2 2020-02-03 13:59:20 +01:00
ce13e824b6 Merge remote-tracking branch 'origin/develop' into develop 2020-02-02 15:28:05 +01:00
b182a63ea1 fix concurrent co mofification 2020-02-02 15:28:00 +01:00
9ced2048d2 Version++ 2020-02-02 14:26:09 +01:00
cfee2f93f2 Prepare v0.14.2 2020-02-02 14:06:21 +01:00
97aca28c0d Merge branch 'release/0.14.2' 2020-02-02 14:05:50 +01:00
b158729b53 Prepare v0.14.2 2020-02-02 14:05:12 +01:00
367057cc29 Fix / cold start 2020-02-02 14:01:45 +01:00
5fb4f274f9 Version ++ 2020-02-02 08:00:57 +01:00
a35302eae0 Merge branch 'release/0.14.1' 2020-02-02 07:56:00 +01:00
6f60f1c6b4 Merge branch 'release/0.14.1' into develop 2020-02-02 07:56:00 +01:00
435d8cbc55 Prepare v0.14.1 2020-02-02 07:55:46 +01:00
bb0fafcb2f Merge pull request #929 from vector-im/feature/xsigning_fix_4
Feature/xsigning fix 4
2020-02-02 03:13:54 +01:00
1d2928b3fb ktlint 2020-02-02 03:13:15 +01:00
40b0f60964 Fix issue in dark theme. Also do not limit subtitles to 2 lines 2020-02-02 03:11:27 +01:00
96a556f449 Fix / Race causing key requests to be sent to early in xsigning 2020-02-02 01:21:08 +01:00
d436d3b8d4 Move rx logs to verbose 2020-02-02 00:41:36 +01:00
845f3f5ad1 FIx / use password textedit 2020-02-02 00:04:15 +01:00
fb838e5407 Fixes #813 2020-02-01 23:24:05 +01:00
40c70f64a8 Merge branch 'feature/to_device_done' into develop 2020-02-01 18:48:34 +01:00
245b3717b9 Send done in toDevice 2020-02-01 18:25:31 +01:00
9e15891053 Version++ 2020-02-01 17:21:41 +01:00
637eba277f Merge branch 'release/0.14.0' 2020-02-01 17:20:05 +01:00
649ebf4a34 Merge branch 'release/0.14.0' into develop 2020-02-01 17:20:04 +01:00
e9f220cca2 Prepare release 0.14.0 2020-02-01 17:19:53 +01:00
8a9bd97a88 Merge pull request #924 from vector-im/feature/crossing_fix_2
Feature/crossing fix 2
2020-02-01 17:17:30 +01:00
26400e6372 Prompt before resetting keys 2020-02-01 15:20:04 +01:00
282be29247 temp shield for read only 2020-02-01 15:20:04 +01:00
6ee7ee1460 Fix blink effect 2020-02-01 15:04:22 +01:00
2e0a84ccc9 display profile faster from known info 2020-02-01 15:03:00 +01:00
9d6e7d7bd0 Learn more shows my devices when keys not trusted 2020-02-01 14:36:17 +01:00
8f7b18239d Warn on verify when private keys not known 2020-02-01 14:36:17 +01:00
10094a212c ktlint 2020-02-01 14:02:51 +01:00
53e36dca9c ZXing 3.3.3 because of https://github.com/zxing/zxing/issues/1170 2020-02-01 13:52:33 +01:00
6ec2dd8c00 Add startWith and logs 2020-02-01 12:12:40 +01:00
f098d6cf5b Add startWith 2020-02-01 11:45:45 +01:00
cd606ba8a1 RoomMember decoration 2020-02-01 11:37:16 +01:00
59abee10f8 Convert to ConstraintLayout 2020-02-01 11:37:16 +01:00
64df9e23c2 Room Profile / Just show e2e status remove learn more 2020-02-01 11:03:00 +01:00
fc4f5faffd Update Room decoration algo 2020-02-01 10:21:29 +01:00
256f8b77aa Add Timber to rx module 2020-02-01 10:09:22 +01:00
f2f775cb99 Add TODOs 2020-02-01 01:17:18 +01:00
2616a889ef Merge pull request #923 from vector-im/feature/xcrossing_fix
Decoration in room profile and improve Rx flow
2020-01-31 20:48:20 +01:00
ccd4c1ed86 ktlint 2020-01-31 20:46:33 +01:00
bb92882958 (partially) Fix glitch 2020-01-31 20:28:57 +01:00
46dd17644f Room decoration - in room profile UI 2020-01-31 20:12:02 +01:00
7e34b2a672 Room decoration - convert to ConstraintLayout 2020-01-31 20:02:01 +01:00
c3c88c387b Improve Rx chain and cleanup 2020-01-31 19:55:22 +01:00
51e0f945a7 Quick Room Decoration 2020-01-31 18:52:33 +01:00
37230b0614 Fix issues with read marker and jumpToBottom 2020-01-31 18:09:34 +01:00
fd3619b100 Merge pull request #770 from vector-im/cross_signing
Cross signing
2020-01-31 17:05:18 +01:00
e18b9d5155 Room decoration - UI in room list 2020-01-31 16:10:52 +01:00
ec6d78bf96 Merge branch 'develop' into feature/stabilization_2 2020-01-31 15:47:33 +01:00
759b680e63 Timeline/Sync: Fix some issues 2020-01-31 15:28:35 +01:00
f5ecf4bd90 Room decoration - UI 2020-01-31 15:02:54 +01:00
27c74c9118 live device in settings 2020-01-31 14:42:00 +01:00
4d91bc934b Fix ktlint 2020-01-31 14:12:03 +01:00
5c547794f2 Merge branch 'develop' into cross_signing 2020-01-31 14:09:40 +01:00
43358cd86c Make self verification work! 2020-01-31 12:18:27 +01:00
87b76d10dd Format 2020-01-31 11:11:27 +01:00
80f4f95f81 QRCode: requestId is not supposed to be an eventId 2020-01-31 11:11:27 +01:00
8e5c7239cf Settings Sessions / Now live + support devices with no keys 2020-01-31 10:33:53 +01:00
7b385c3b36 Quick copy change device -> session 2020-01-31 10:00:44 +01:00
4fb59aadb1 Fix / ensure RoomKeyRequest are made after device is verified 2020-01-31 09:39:31 +01:00
850c830e1f Fix / auto ready request when waiting bottomsheet on screen 2020-01-31 09:16:03 +01:00
9dde43f65b PR Review: var -> val, internal and other cleanup 2020-01-30 23:40:25 +01:00
9d566e9352 Merge pull request #918 from vector-im/feature/sort_room_members
Sort room members by display names
2020-01-30 21:06:40 +01:00
eb46a4949f Merge pull request #920 from duncanturk/patch-1
Add "get it on F-Droid"
2020-01-30 21:05:53 +01:00
506c2dd262 Merge pull request #921 from vector-im/decorations
Add field in QR code and make some optional
2020-01-30 18:48:30 +01:00
ccd857016c ktlint 2020-01-30 18:46:08 +01:00
225e4e0433 To Device Verification Request 2020-01-30 18:43:50 +01:00
5e1b59f9d3 Timeline: handle an in memory local echo to make the UI snappier 2020-01-30 17:13:44 +01:00
069bd3c258 use isMe 2020-01-30 16:59:22 +01:00
fb98d6ef42 QRCode: add other_device_key field and make it optional, along with other_user_key 2020-01-30 16:46:12 +01:00
6282f81bc4 Remove typo 2020-01-30 16:46:12 +01:00
a5ca2b1d34 Fix / incoming start verif popup should not show when bottomsheet there 2020-01-30 16:36:13 +01:00
50d5ad3625 Self verification + toDevice Request 2020-01-30 16:35:42 +01:00
03c5e61b2e Fix / post merge 2020-01-30 16:35:06 +01:00
4ddd831d7f Prepare support for toDevice .request 2020-01-30 16:11:34 +01:00
ff95392e10 Fix / Refresh trust state on own keys/device trust change 2020-01-30 16:10:59 +01:00
e2c2c2418c Merge pull request #919 from vector-im/qr_step_validate
Qr step validate
2020-01-30 14:14:16 +01:00
e44dc347c6 Add "get it on F-Droid"
RiotX is on F-Droid now
2020-01-30 12:07:33 +01:00
fbd0bbc575 Improve clarity of the algorithm to enable encryption for DMs 2020-01-30 11:24:05 +01:00
b848d0530f Update realm to 6.1.0: should fix some of the native crashes 2020-01-30 11:04:37 +01:00
2bccd19f84 QRcode: Url encode the keys 2020-01-30 10:17:04 +01:00
2111daea52 Add a step to confirm that other user has scanned the SR code 2020-01-30 10:09:59 +01:00
9fc3fa7f19 Update some libs and remove incremental from dagger 2020-01-29 21:14:38 +01:00
57a13fa30d Sort room members by display names 2020-01-29 18:07:57 +01:00
c4649a5824 Merge pull request #916 from vector-im/debug_qr
Negotiate E2E by default for DMs (#907)
2020-01-29 18:02:43 +01:00
71a02a58af Sync/Timeline: handle displayName isUnique 2020-01-29 17:30:31 +01:00
6f6c3184dd Avoid test if previous result is null 2020-01-29 17:13:41 +01:00
d7feb6dd5c Merge pull request #913 from vector-im/feature/rainbow
Rainbow
2020-01-29 16:35:34 +01:00
e6c3f7c77b Nicer API 2020-01-29 16:26:19 +01:00
8b6ffc2fb1 ktlint 2020-01-29 16:18:33 +01:00
ae36846aaf Negotiate E2E by default for DMs (#907) 2020-01-29 16:11:23 +01:00
237da5bb16 No need to have mutable list in param 2020-01-29 16:03:28 +01:00
7f72af426b Timeline: fix getContext 2020-01-29 16:02:53 +01:00
a4abe5f552 Set timeout to 60s when creating a room 2020-01-29 16:00:07 +01:00
e1ddde5501 Make CreateRoomParams a regular data class 2020-01-29 14:23:32 +01:00
754ca3c582 Fix / fail to update usk when dl own keys 2020-01-29 14:00:02 +01:00
70b04dbaea Disable not passing test, to avoid waiting too long when running the test suite 2020-01-29 12:36:38 +01:00
b44b6726ed Also update the tests 2020-01-29 12:29:19 +01:00
80ec199135 Convert VerificationTxState to a sealed class 2020-01-29 12:00:49 +01:00
305dfd4c7a Merge pull request #911 from vector-im/feature/encryption_notice
Modify encryption notice
2020-01-29 10:32:23 +01:00
73bb4bb785 Merge pull request #912 from vector-im/feature/e2e_opt_out
e2e opt in when creating room (not DM)
2020-01-29 10:29:33 +01:00
1d84ccd64a Merge pull request #881 from vector-im/xsigning_sdk
Xsigning sdk
2020-01-29 10:26:46 +01:00
63e36b0403 Remove unused test 2020-01-29 10:16:57 +01:00
2c568b4de9 clean klint 2020-01-29 09:59:09 +01:00
27fe4e3680 Fix build and add tests 2020-01-29 09:44:53 +01:00
007b0cabf2 Add a few TUs 2020-01-28 22:43:10 +01:00
b2338dfcd3 Make the TU passes 2020-01-28 22:35:40 +01:00
6d7d4993a6 Add TUs for RainbowGenerator (not all passing) 2020-01-28 21:56:02 +01:00
da9b9f4864 Make the whole cell clickable 2020-01-28 21:31:02 +01:00
ef0b438a89 Give the possibility to enable encryption when creating room (#837) 2020-01-28 21:31:02 +01:00
a8f783bbfa Add state events to chunks 2020-01-28 18:59:21 +01:00
9a79297e14 Merge pull request #910 from vector-im/qr_code_step_2
Qr code step 2
2020-01-28 18:11:09 +01:00
a57393cafa More log + quick fix in settings 2020-01-28 18:09:17 +01:00
e12de3fba0 Merge pull request #891 from vector-im/feature/event-unknown
Feature/event unknown
2020-01-28 17:30:02 +01:00
2eeeea3377 Encryption is enabled only for MEGOLM. 2020-01-28 17:19:22 +01:00
976a8fc568 Hide the algorithm when turning on e2e (#897) 2020-01-28 16:36:28 +01:00
b7ecfd997d Fix compilation issue after rebase 2020-01-28 16:02:20 +01:00
e0b3ea7e48 QrCode: WIP 2020-01-28 15:55:44 +01:00
9c829e62e6 QrCode: WIP 2020-01-28 15:55:44 +01:00
20c7e4c3ad QrCode: improve UI 2020-01-28 15:55:44 +01:00
69ab5e43d5 QrCode: WIP 2020-01-28 15:55:02 +01:00
f46023e84c QrCode: WIP 2020-01-28 15:55:02 +01:00
d8d465f70b QrCode: WIP 2020-01-28 15:53:57 +01:00
8659216955 QrCode: WIP 2020-01-28 15:53:57 +01:00
39e746413a QrCode: WIP 2020-01-28 15:53:57 +01:00
0aaba26f17 Rename classes 2020-01-28 15:53:57 +01:00
fc04833157 Rename parameter 2020-01-28 15:53:57 +01:00
f80861bed8 Add TODO 2020-01-28 15:53:57 +01:00
9e796067cc Do not support SHOW or SCAN if cross-signing is not enabled 2020-01-28 15:53:57 +01:00
fb5148fd43 Avoid to inject credential (again) 2020-01-28 15:52:17 +01:00
be77017209 Avoid injecting credentials. Inject userId and deviceId instead
And cleanup API
2020-01-28 15:48:09 +01:00
962b85b041 Add TODO 2020-01-28 15:48:09 +01:00
adc2d570eb QR code: handle the case where other user can scan QR codes 2020-01-28 15:48:09 +01:00
df49ab8362 QR code: update code which build URL 2020-01-28 15:48:09 +01:00
efc8cfb9a1 QR code: modify APIs 2020-01-28 15:48:09 +01:00
345824daa2 Keep on renaming 2020-01-28 15:48:09 +01:00
050eb0af9d Create dedicated View and Epoxy item for QrCode 2020-01-28 15:48:09 +01:00
ca4ed6e1bd Fix / Error management and clear keys 2020-01-28 15:35:11 +01:00
bf7c53ecab Sync/pagination: get a working version 2020-01-28 14:46:26 +01:00
f021f8110d post merge 2020-01-28 12:04:19 +01:00
109ff4f908 Merge branch 'cross_signing' into xsigning_sdk 2020-01-28 11:33:54 +01:00
c9f0209ebf post merge fix 2020-01-28 11:23:37 +01:00
7daa088618 Merge branch 'develop' into cross_signing 2020-01-28 11:13:31 +01:00
83e44ac96e Fix / cross signing info live data not always updated 2020-01-28 11:02:12 +01:00
15b0bea870 Use clone for retrofit request to be able to retry 2020-01-28 10:13:36 +01:00
e5e62dc4a7 Fix SyncService and Alarm 2020-01-28 10:13:19 +01:00
f3e88c75cf Fix typo 2020-01-28 09:42:56 +01:00
ea6e8a6789 Basic debug screen to setup keys 2020-01-27 23:51:08 +01:00
6cece03998 Profile detailed device info + verify manually 2020-01-27 17:55:00 +01:00
f3db43f317 Ellipsize: introduce EllipsizingTextView 2020-01-27 12:41:43 +01:00
08ae0b485a Profile Screen / Add show device list trust screen 2020-01-27 09:25:58 +01:00
665c577747 SDK / update trust on key change + live method in Service 2020-01-27 09:25:16 +01:00
3a89a30056 Continue reworking sync/timeline events handling 2020-01-25 18:59:45 +01:00
d60351bcb7 Verify from RoomMember Profile 2020-01-24 19:15:23 +01:00
1d8b81bb04 Try reworking events/timeline process [WIP] 2020-01-24 18:43:35 +01:00
a758efc018 Renamed room transport classes 2020-01-24 11:32:24 +01:00
d0addc4c4f Refactored Verification Classes 2020-01-24 11:29:26 +01:00
bb5179140c Update profile screen for xSigning 2020-01-24 09:14:32 +01:00
e9ea69f055 Add support for /rainbow and /rainbowme command (#879) 2020-01-23 23:34:21 +01:00
7bcae75314 Remove some code from main thread 2020-01-23 20:31:18 +01:00
4331d2ef47 Network: reword the strategy for handling NetworkConnectivity (remove Merlin) 2020-01-23 19:08:55 +01:00
e47791f290 Merge pull request #888 from vector-im/qr_code
Qr code
2020-01-23 16:41:23 +01:00
91ae96a153 QuickFix / Do not verify yourself in dm 2020-01-23 16:16:57 +01:00
0148949a4f Fix / prevent verification toaster to show when in good room 2020-01-23 16:13:46 +01:00
65cb812fc6 Fix / Unknown transaction when started by other after request 2020-01-23 16:04:29 +01:00
e8a4f1fb90 Fix: .cancel won't appear in debug show all 2020-01-23 16:04:03 +01:00
632832a651 Nearly same code for DefaultItem and NoticeItem 2020-01-23 15:44:41 +01:00
d530c64a84 Render defaultItem as other item: display user avatar
Also ensure bottom sheet always has a header, for user avatar and date
2020-01-23 15:35:46 +01:00
426e291ce9 i18n for RiotX limitation messages 2020-01-23 14:46:36 +01:00
1276d1f39d Update My device list + action to verify 2020-01-23 13:57:17 +01:00
4a1012cf81 Add TODOs 2020-01-23 11:48:08 +01:00
5819790c1b Distinguish Show SR code and Scan QR code capability 2020-01-23 11:25:44 +01:00
b3089343ad Support SCAN method (WIP) 2020-01-23 10:47:29 +01:00
c65f25d7ae Rx: fix startWith on mainThread 2020-01-23 10:18:22 +01:00
37b950897f Base64 no wrap and extension for the reverse operation 2020-01-23 10:17:07 +01:00
fee2ec6b66 Scroll when event build come from sync/send + remove use of monarchy writeAsync 2020-01-22 20:33:52 +01:00
d2fab91e9d Improve code 2020-01-22 19:08:21 +01:00
c323b61575 Ignore typo 2020-01-22 18:27:59 +01:00
0e55f81879 Ensure all is escaped properly 2020-01-22 18:26:34 +01:00
cbf418c401 Update after MSC change 2020-01-22 18:22:01 +01:00
41c691f26c Create QrCodeData class and method to convert to URL and vice versa, with TUs 2020-01-22 17:58:25 +01:00
81337d1624 Also keep the same parameter order: (userId, deviceId) to avoid silly errors 2020-01-22 17:00:16 +01:00
79df6b8402 Start plugin QR code to the code 2020-01-22 15:56:43 +01:00
537b1be0c5 Update wording 2020-01-22 15:26:26 +01:00
c1259161e5 QRCode: generate and scan QRCodes 2020-01-22 15:03:56 +01:00
76065ac4fc Read: allow setting read marker and read receipt to latest known event independently 2020-01-22 14:43:39 +01:00
d93050240a Start reworking networkConnectivityCheck (WIP) 2020-01-22 14:41:42 +01:00
75e39535bc Merge pull request #883 from vector-im/feature/share
Improve the room list when sharing to RiotX
2020-01-22 11:49:50 +01:00
c971f18fc0 Add section header when displaying room list to share (#771) 2020-01-22 11:49:30 +01:00
3c2fa40b58 Sharing things to RiotX: sort list by recent room first (#771) 2020-01-22 11:49:04 +01:00
0b74863c6d Merge pull request #877 from vector-im/feature/version_name
F-Droid: fix the "-dev" issue in version name (#815)
2020-01-22 11:45:36 +01:00
dca950140d Merge branch 'develop' into feature/version_name 2020-01-22 11:45:27 +01:00
a13a78ccc0 Merge pull request #874 from vector-im/feature/authors
Builds repoductibility and Authors file
2020-01-22 11:43:51 +01:00
7327dc97b4 Merge pull request #876 from vector-im/feature/room_settings
Room settings, and enable encryption in unencrypted rooms (#212)
2020-01-22 11:40:26 +01:00
2bddf61afe Update realm to 6.1.0: should fix some of the native crashes 2020-01-21 15:15:29 +01:00
da3e547d82 Create facility extension to observe ViewEvents 2020-01-21 15:08:49 +01:00
a0aa1f34d3 Quick Fix todevice verif broken
Added dbg screen for cross signing
2020-01-21 14:58:06 +01:00
d1b8d81fb1 Fix double read receipts 2020-01-21 14:17:04 +01:00
e81c804ed6 Ensure when will be exhaustive 2020-01-21 12:51:28 +01:00
be371f9279 Introduce ViewEvents in ViewModel and code harmonization 2020-01-21 12:51:28 +01:00
a6364f0be5 remove dead code 2020-01-21 10:25:57 +01:00
390879e3fd Added check self keys + force DL after initialize Xsigning 2020-01-21 10:25:57 +01:00
6ab540045b Refactoring / deprecation of MXDeviceInfo
introduced TrustLevels
2020-01-21 10:25:57 +01:00
98ba2d39a8 SAS verif, support signing and verification of Cross Signing 2020-01-21 10:25:57 +01:00
859c75df98 Initial commit 2020-01-21 10:25:57 +01:00
ea9166e0c6 Merge pull request #811 from vector-im/verification_toasters
[Cross Signing DM Verif]  Basic Incoming request toast + cleaning
2020-01-21 10:21:24 +01:00
d672313649 Room settings: use boolean instead of Async 2020-01-20 17:41:29 +01:00
f5e6b4b857 F-Droid: fix the "-dev" issue in version name (#815) 2020-01-20 16:08:57 +01:00
28db05e509 Cleanup and copy wording from Riot-Web 2020-01-20 15:39:14 +01:00
56b140fcb4 Room settings: rename stuff for genericity 2020-01-20 15:23:40 +01:00
eee6969b02 Room settings, and enable encryption in unencrypted rooms (#212) 2020-01-20 15:11:21 +01:00
825427b7b0 Add a first content into the AUTHORS file 2020-01-17 16:50:18 +01:00
8c32796d5c Ensure builds are reproducible (#842) 2020-01-17 16:06:58 +01:00
e45c1e6c2a Fix / post merge issues 2020-01-17 15:17:16 +01:00
188cd6beff Verification: improve blinking effect (not perfect yet) 2020-01-17 15:05:06 +01:00
aaeb54db7c Verification: Introduce VerificationMethod enum 2020-01-17 15:05:06 +01:00
92f26bc20a Verification: migrate to Epoxy - Cleanup 2020-01-17 15:05:06 +01:00
fc22b7988f Verification: migrate to Epoxy - Add missing icons 2020-01-17 15:05:06 +01:00
878bae1c45 Verification: migrate to Epoxy - Choose Fragment 2020-01-17 15:05:06 +01:00
a8e81d95cf Verification: migrate to Epoxy - Disable item animation 2020-01-17 15:05:06 +01:00
cd1665a8e8 Verification: migrate to Epoxy - Conclusion 2020-01-17 15:05:06 +01:00
7170471686 Verification: migrate to Epoxy - create sub packages 2020-01-17 15:05:06 +01:00
98020404ff Verification: migrate to Epoxy - rename package 2020-01-17 15:05:06 +01:00
b2348427bd Verification: migrate to Epoxy - Emoji Fragment 2020-01-17 15:05:06 +01:00
832df59b58 Verification: migrate to Epoxy - Request Fragment 2020-01-17 15:05:06 +01:00
32689facc5 Verification: migrate to Epoxy - Request Fragment 2020-01-17 15:05:06 +01:00
d3071e5816 Rename layout for consistency 2020-01-17 15:04:36 +01:00
83a6f564c3 Ensure BottomSheets call ButterKnife unbinder 2020-01-17 15:04:36 +01:00
3b420dbb50 typo 2020-01-17 15:04:36 +01:00
9fe155bafd postWork now returns the Cancellable 2020-01-17 15:04:36 +01:00
3c982866d8 Restore lost Fragment binding... 2020-01-17 15:04:36 +01:00
494ad83704 Inject WorkManagerProvider, to avoid injecting the Android context
Also ensure WorkManager uses a distinct tags for each session (for future multi-sessions support)
2020-01-17 15:04:36 +01:00
4543658ae0 Extends SessionWorkerParams 2020-01-17 15:04:36 +01:00
689fd1ea90 Fix issue with SessionId for the worker
Also rename some variables
2020-01-17 15:04:36 +01:00
a95410c118 fix rebase 2020-01-17 15:04:36 +01:00
8749e49e80 Basic Incoming request toast + cleaning 2020-01-17 15:04:36 +01:00
8400ab6efe Merge branch 'develop' into cross_signing 2020-01-17 14:57:08 +01:00
d1699279fe Version++ 2020-01-17 14:25:25 +01:00
f471d9cff8 Merge branch 'release/0.13.0' 2020-01-17 14:24:11 +01:00
115058124c Merge branch 'release/0.13.0' into develop 2020-01-17 14:24:10 +01:00
7604748d3f Prepare release 0.13.0 2020-01-17 14:23:58 +01:00
d46a3ab87f Update CHANGES.md 2020-01-17 14:10:47 +01:00
b375463aec Merge pull request #854 from vector-im/feature/profiles_improvements
Feature/profiles improvements
2020-01-17 12:22:16 +01:00
cfb752c220 Merge pull request #851 from vector-im/feature/code_style
Share the same code formatting rules
2020-01-17 12:21:34 +01:00
c59712732a Introduce listener type for Epoxy items 2020-01-17 12:14:24 +01:00
626ebd9c63 Merge pull request #850 from vector-im/feature/e2e_attachments_cleanup
Feature/e2e attachments cleanup
2020-01-17 12:12:48 +01:00
5148d7ab46 Room profile: open it also when clicking on the room avatar 2020-01-17 10:15:04 +01:00
8c2a55a5a2 Settings: restore "Show read receipts" setting and create categories of per Riot-Web 2020-01-17 10:10:46 +01:00
34b6dd4270 Room profile: open room member profile from Event bottom sheet 2020-01-16 21:48:10 +01:00
79a68a36bd Room profile: ensure RoomMemberSummaries order is guaranteed 2020-01-16 21:29:05 +01:00
78408fa0ec Room profile: create extension join for Collections 2020-01-16 21:18:14 +01:00
b56ee9a377 Room profile: fix issue with divider color 2020-01-16 20:53:38 +01:00
9eff459ed6 Room profile: remove an extra divider 2020-01-16 16:43:37 +01:00
cd44b60bd5 Room profile: make link in room topic clickable 2020-01-16 16:36:56 +01:00
17ed8da57a Room profile: fix issue with icon 2020-01-16 16:27:21 +01:00
8ae51a95c5 Add formatting policy in the Contributing guide 2020-01-16 16:02:41 +01:00
f80f22fed2 XML formatting rule 2020-01-16 15:58:52 +01:00
fa57d0f6d5 160 char max per line 2020-01-16 15:27:00 +01:00
1104b5d483 DO_NOT_WRAP_AFTER_SINGLE_ANNOTATION 2020-01-16 14:26:52 +01:00
464462022c Kotlin code convention 2020-01-16 14:17:29 +01:00
1c63d3f8f0 Add rule 2020-01-16 14:15:50 +01:00
a916bd4ba8 Share the same code formatting rules 2020-01-16 14:05:14 +01:00
15e2c9f3a3 Fix formatting 2020-01-16 12:55:55 +01:00
f1a2fb51f5 Properly configure Snackbar styles 2020-01-16 12:51:33 +01:00
b0aa9fbd8f Inform user when the download of a file starts 2020-01-16 12:20:39 +01:00
d72f1ac576 Avoid exposing internal classes 2020-01-16 11:36:53 +01:00
ca157c7567 Better logs 2020-01-16 10:57:08 +01:00
ae26bf3369 Signout also clear cache 2020-01-16 10:57:08 +01:00
159c96681f Improve attachment encryption and decryption code 2020-01-16 10:57:08 +01:00
96d6b75037 Fix broken link 2020-01-16 10:57:08 +01:00
72e6181f00 Merge pull request #839 from vector-im/feature/developer
Show all hidden event in the timeline when the developer settings is ON
2020-01-16 10:56:27 +01:00
4ae09b8716 Merge pull request #831 from david1hyman/file-decryption-fix
File decryption path was writing incorrect stream to file
2020-01-16 10:50:15 +01:00
f128ed437f Merge pull request #843 from vector-im/feature/room_profile
Feature/room profile
2020-01-15 19:17:50 +01:00
11c8c8c2bd Fix fdroid background sync 2020-01-15 19:16:50 +01:00
2c331671ee Fix string 2020-01-15 17:44:38 +01:00
b44ddcfd61 Clean code after Benoit's review #2 2020-01-15 14:57:21 +01:00
7c0f2d6e32 Test: fix import 2020-01-15 11:48:02 +01:00
52de14b1b5 Clean code after Benoit's review 2020-01-15 11:46:33 +01:00
d6e6092eea Profile: add PowerLevelContent for building future actions + fix divider 2020-01-14 19:14:15 +01:00
9671a77e5d Clean code and update CHANGES 2020-01-14 18:48:13 +01:00
d3415d345f Merge branch 'develop' into feature/room_profile 2020-01-14 18:35:01 +01:00
df4df81ef3 Profile: handle ignore/unignore action + adjust UI 2020-01-14 17:08:21 +01:00
a7c948815c Merge branch 'develop' into cross_signing 2020-01-14 12:31:29 +01:00
9d5197b1c8 Show all hidden event in the timeline when the developer settings is ON 2020-01-13 22:47:41 +01:00
162f0949fa Profile: Start fetching profile info from a user 2020-01-13 18:44:01 +01:00
ae1a24e948 Room member profile: branch the UI and fix some UI issues 2020-01-13 16:49:14 +01:00
b5fead18fe Merge pull request #833 from vector-im/feature/typing
Send and render typing events (#564)
2020-01-13 15:17:43 +01:00
3c682430d9 Merge pull request #829 from vector-im/feature/stab
Feature/stab
2020-01-13 15:13:07 +01:00
717965bc37 Update comment 2020-01-13 15:12:39 +01:00
ecc463e920 Cleanup and fix a bug 2020-01-13 10:13:12 +01:00
f3e52b96c0 Cleanup 2020-01-11 22:12:56 +01:00
dd81fce8d8 Send and render typing events (#564) 2020-01-11 20:50:09 +01:00
7354eab061 Post merge fixes 2020-01-11 10:16:09 +01:00
1ae58aa6ad DefaultFileService - code was passing the inputStream to the decryption method
but not storing the output of the method anywhere
then it was writing inputStream to file and returning that file handle
changed inputStream to var and used it to store output of decryption method
2020-01-10 14:53:40 -05:00
fb9abefe59 Merge branch 'develop' into cross_signing 2020-01-10 18:38:54 +01:00
095216349e Exception -> Throwable 2020-01-10 18:35:29 +01:00
550908fa70 Render events m.room.encryption and m.room.guest_access in the timeline 2020-01-10 18:30:10 +01:00
0dbca829ea Fix crash with RoomCreationParams 2020-01-10 18:07:14 +01:00
03b5b098c7 Change the way versionCode is computed (#827) 2020-01-10 17:29:34 +01:00
171ec4fbdc Room member list: group by power level 2020-01-10 17:03:11 +01:00
32d2daee3c Exclude current user from autocompletion with room members 2020-01-10 16:28:14 +01:00
de84bb7535 Use more developerMode() 2020-01-10 11:03:42 +01:00
81712ae736 RoomProfile: fix some rendering + change anim 2020-01-09 19:47:54 +01:00
289951ea4a RoomMemberList : start showing items 2020-01-09 15:54:36 +01:00
8c9c65837d Version++ 2020-01-09 15:32:37 +01:00
24a7ce7d98 Merge branch 'release/0.12.0' 2020-01-09 15:31:30 +01:00
d486e613d8 Merge branch 'release/0.12.0' into develop 2020-01-09 15:31:29 +01:00
598d67234c Prepare release 0.12.0 2020-01-09 15:31:13 +01:00
fea4f2e129 Merge pull request #816 from vector-im/feature/integration_tests
Start porting of integration tests - Fix issue with multiple sessions
2020-01-09 15:28:29 +01:00
687ea1b5b3 ktlint 2020-01-09 15:28:16 +01:00
47e3b8ec46 Ensure foreground notification is always displayed 2020-01-09 15:09:37 +01:00
dd8c908dc7 Code cleanup 2020-01-09 15:02:39 +01:00
9775e8c32b Fix crash in syncService 2020-01-09 15:01:16 +01:00
e3205fb493 Fix compilation issue after rebase 2020-01-09 14:26:36 +01:00
35f011ba37 Fix ktlint issues 2020-01-09 14:20:17 +01:00
ed773dbb96 TI: Introduce doSync method 2020-01-09 14:20:17 +01:00
fa821826d2 TI: Import ExportEncryption test (passing) 2020-01-09 14:20:17 +01:00
293e3e3ce6 TI: Import AttachmentEncryption test (passing) 2020-01-09 14:20:17 +01:00
4244c0e48d TI: Import SAS Test - WIP 2020-01-09 14:20:17 +01:00
76e45431da TI: Import keys backup tests 2020-01-09 14:20:17 +01:00
f3fb07079e Cleanup tests 2020-01-09 14:20:17 +01:00
3ceac70536 Enable encryption on a room, SDK part (#212) 2020-01-09 14:20:17 +01:00
0f7209df1f TI: finish the work to identify a session with a sessionId 2020-01-09 14:20:17 +01:00
e177251ec0 TI: inject EventBus to allow multiple sessions - WIP 2020-01-09 14:20:17 +01:00
6746f68411 TI: create account 2020-01-09 14:20:17 +01:00
fc6d845c0d Import tests from legacy SDK 2020-01-09 14:20:17 +01:00
93cdce6c3e Cleanup tests 2020-01-09 14:20:17 +01:00
ae3381227c Add Unit tests from legacy SDK 2020-01-09 14:20:17 +01:00
b6a1ff1ca4 Import string from Riot legacy 2020-01-09 14:17:17 +01:00
7ec0227528 Merge pull request #824 from vector-im/feature/wording
Email domain can be limited on some homeserver, i18n of the displayed error (#754)
2020-01-09 12:26:28 +01:00
15639b45cf Introduce RoomMemberProfile files 2020-01-09 12:10:49 +01:00
f18ec8d021 Merge branch 'develop' into feature/room_profile 2020-01-09 11:56:09 +01:00
898bf234da Merge pull request #792 from vector-im/feature/stabilization
Feature/stabilization
2020-01-09 11:43:52 +01:00
3d0d95c371 Email domain can be limited on some homeserver, i18n of the displayed error (#754) 2020-01-09 11:34:57 +01:00
bd4a595f96 ChunkEntityTest: make it compile again 2020-01-09 11:19:08 +01:00
0f7d59a8c7 Cleanup during PR review 2020-01-09 09:42:34 +01:00
e14b9b3b20 Fix test compilation issue 2020-01-09 08:03:14 +01:00
43c4e20819 Merge pull request #820 from vector-im/feature/developer_mode_crash
Developer mode: Fail-fast (#745)
2020-01-09 07:56:06 +01:00
5312b44359 Merge pull request #821 from vector-im/feature/query_latch
Remove CountDownLatch (inspired from #419)
2020-01-09 07:55:38 +01:00
8c4d8763a2 Merge branch 'develop' into feature/stabilization 2020-01-08 22:28:08 +01:00
383605274c Introduce a very simple query langage and refact autocomplete 2020-01-08 22:17:32 +01:00
8032490606 Remove CountDownLatch (inspired from #419) 2020-01-08 18:58:51 +01:00
a458997ce0 Merge pull request #818 from vector-im/feature/oss
Exclude play-services-oss-licenses library from F-Droid build (#814)
2020-01-08 18:28:31 +01:00
29f152f349 Fix CI 2020-01-08 18:21:01 +01:00
6ca3ba6c9b Merge pull request #806 from Bubu/fix_697
call /join/{roomIdOrAlias} instead of /rooms/{roomId}/join
2020-01-08 18:17:34 +01:00
f4492e570d Merge branch 'develop' into fix_697 2020-01-08 18:17:23 +01:00
587fefedb5 Merge pull request #809 from Bubu/fix_807
set homeserver field when populating room directory list
2020-01-08 18:12:42 +01:00
943be39e1a Merge branch 'develop' into fix_807 2020-01-08 18:12:22 +01:00
616f3d3345 Merge pull request #817 from vector-im/feature/fab_scroll
Show skip to bottom FAB while scrolling down (#752)
2020-01-08 18:07:10 +01:00
2b8ecae8e3 Fix CI 2020-01-08 18:05:26 +01:00
17c4013383 Developer mode: Fail-fast (#745) 2020-01-08 17:58:26 +01:00
d662b4a9b4 Exclude play-services-oss-licenses library from F-Droid build (#814) 2020-01-08 15:57:35 +01:00
501ac36040 Reduce size of RoomDetailFragment 2020-01-08 15:05:20 +01:00
7575cb286e Show skip to bottom FAB while scrolling down (#752) 2020-01-08 15:05:20 +01:00
c60b4ddb5a Timeline: don't wait for realm notification to come back, use it right away to init 2020-01-08 13:59:43 +01:00
9970d7ffa0 SDK: get some better queries 2020-01-08 11:55:22 +01:00
2dd2a8db6c Emoji data source as singleton 2020-01-08 11:54:42 +01:00
8ef5c60e2e RageShake is enabled by default 2020-01-08 11:43:21 +01:00
03c3c9ae57 Timeline: clear unlinked should use new parameters 2020-01-07 18:15:48 +01:00
38c198fe02 Rx: fetch first before returning live data results 2020-01-07 18:15:07 +01:00
42c7421b05 Merge branch 'develop' into feature/stabilization 2020-01-07 14:42:38 +01:00
19fb3ce032 Merge branch 'develop' into feature/stabilization 2020-01-07 14:28:23 +01:00
5a7f4bed43 ktlint 2020-01-07 14:24:26 +01:00
03734a7ad5 Merge pull request #802 from vector-im/feature/sessionId
Identify a session with the userId and the deviceId
2020-01-07 14:23:09 +01:00
d710106bbb Clean code 2020-01-07 14:09:04 +01:00
f09bf61750 Room detail: try to get some better perfs with fetching data. LiveData is slow as we only use one HandlerThread at the time. Might want Realm 7.0 and frozen objects to rework that 2020-01-07 13:31:34 +01:00
f9487f8995 Work on timeline 2020-01-06 18:44:04 +01:00
99c523b710 Update libs 2020-01-06 18:43:34 +01:00
3cc15387ae Realm: compatch on launch 2020-01-06 18:41:09 +01:00
6245763577 Merge pull request #789 from vector-im/feature/christmas_fix
Auto completion for emojis
2020-01-06 14:20:44 +01:00
448552d287 Move list of Quick Emoji to Emoji Data Source 2020-01-06 13:48:34 +01:00
9ecceafb96 Move comment 2020-01-06 13:47:06 +01:00
92d7ebe94f Update changes 2020-01-06 13:47:06 +01:00
0e5fcd071c Completion on emoji: display the first 50 results 2020-01-06 13:46:37 +01:00
c8e67f8ab4 Completion on emoji WIP 2020-01-06 13:46:10 +01:00
5fa2acf60b Completion on emoji 2020-01-06 13:46:10 +01:00
9e73e95f55 Ensure there is never twice the same emoji 2020-01-06 13:46:10 +01:00
8b4c51139d Completion on emoji WIP 2020-01-06 13:46:10 +01:00
8597c2b9a2 Improve API 2020-01-06 13:46:10 +01:00
d88e5d8af8 DRY 2020-01-06 13:46:10 +01:00
c4fe0bdb7f Split into small methods 2020-01-06 13:46:10 +01:00
d73a1135ae Extract AutoComplete feature from RoomDetailFragment 2020-01-06 13:46:10 +01:00
ed097bcf37 Merge pull request #798 from vector-im/feature/settings_cleanup
Feature/settings cleanup
2020-01-06 13:41:50 +01:00
01db856a5d Improve (a bit) the devices list UX/UI 2020-01-06 10:51:30 +01:00
a00f51a264 Settings: rename "developer mode" to "advanced settings" 2020-01-06 10:32:36 +01:00
06b41af467 Merge pull request #793 from vector-im/outgoing_dm_verif
BottomSheet UX for verification
2020-01-06 10:22:27 +01:00
9e8217082c set homeserver field when populating room directory list
fixes #807

Signed-off-by: Marcus Hoffmann <bubu@bubu1.eu>
2020-01-06 03:48:53 +01:00
ce73007157 call /join/{roomIdOrAlias} instead of /rooms/{roomId}/join
The former endpoint doesn't work for joining over federation, the
server_name parameter is ignored.

Fixes #697

Signed-off-by: Marcus Hoffmann <bubu@bubu1.eu>
2020-01-06 01:01:59 +01:00
c2cd149299 Fix / accept button was not starting the verify sheet
Was launching start sheet, because request was not known by VerificationService. Due to message observer blocked trying to download keys..
2020-01-03 19:06:23 +01:00
08ed8d4fa7 Code review 2020-01-03 17:38:33 +01:00
f432d15757 Ensure key aliases are always computed the same way 2020-01-03 16:20:43 +01:00
215abea10a Introduce @SessionId 2020-01-03 16:20:43 +01:00
160927e7b5 Split code into several methods 2020-01-03 16:20:43 +01:00
c2e7e33050 Update SessionParamsEntity primaryKey to include deviceId 2020-01-03 16:20:43 +01:00
455448806d Merge pull request #799 from vector-im/feature/fix_crash
Fix crash when opening room creation screen from the room filtering screen
2020-01-02 18:57:17 +01:00
a969443517 Fix crash when opening room creation screen from the room filtering screen 2020-01-02 18:53:35 +01:00
1bd85082c3 Auto-review 2020-01-02 18:45:44 +01:00
de1d79b637 Remove Preference divider and cleanup prefs 2020-01-02 18:27:46 +01:00
8e478e78e1 Disable pref unused 2020-01-02 18:17:54 +01:00
96c9293edc Rageshake: vibrate 2020-01-02 18:15:23 +01:00
5c26f66523 Rageshake: settings for sensitivity 2020-01-02 17:42:44 +01:00
d1233e8470 Fix / tap on accept shows request button instead of start 2020-01-02 17:04:41 +01:00
5a24f78c05 Hide non working settings (#751) 2020-01-02 16:24:31 +01:00
bf28f14b8b Fix / Decline request was not implemented 2020-01-02 16:13:13 +01:00
703a1a034d Developer mode: hide show (decrypted) source actions 2020-01-02 16:11:44 +01:00
7d744f7d7f Developer mode: UI
And some cleanup
2020-01-02 16:01:47 +01:00
8dff196716 Device list: remove the detail dialog: handle the actions directly in the list 2020-01-02 15:44:47 +01:00
52c25b803f cleaning 2020-01-02 15:16:45 +01:00
6b2703f6ce Device list is now on a dedicated Fragment
New request to get info on the current device for VectorSettingsSecurityPrivacyFragment. The whole device list is only retrieved in the new Fragment
2020-01-02 15:05:17 +01:00
b26318f15c Fix / Cancel messages was not sent 2020-01-02 12:51:12 +01:00
f541661059 Use workers to send verification messages 2020-01-02 11:52:27 +01:00
e32d242e38 Timeline: remove use of isUnlinked method as it slows down the insertion a lot 2019-12-31 12:58:43 +01:00
5b210df7c5 Manage done states + cleaning 2019-12-31 10:36:10 +01:00
787908287c Member events: cache all over the session 2019-12-31 08:07:32 +01:00
935b3d7f3f cleaning 2019-12-30 20:18:08 +01:00
8156b754c1 RecyclerView: introduce view pool 2019-12-30 19:54:39 +01:00
03fd474aa8 Member events: try to cache (WIP) 2019-12-30 19:53:36 +01:00
3c4506cb58 merge madness ?? 2019-12-30 19:52:48 +01:00
3eed9b5083 cleaning 2019-12-30 18:42:32 +01:00
6bf3a703df BottomSheet UX 2019-12-30 18:01:06 +01:00
2152af8851 klint 2019-12-30 17:54:44 +01:00
5b33a42f8a FIx / missing strings after merge 2019-12-30 17:36:33 +01:00
a73cd61b96 WIP 2019-12-30 15:16:11 +01:00
4edd5e3530 Added SAS do not match api 2019-12-30 14:32:58 +01:00
4c0cbca4cb Support .verification.ready event 2019-12-30 14:32:58 +01:00
308b15b908 Fix / m.key.verification.key was not sent in toDevice mode 2019-12-30 14:32:04 +01:00
38906084d1 WIP 2019-12-30 14:32:04 +01:00
0997d9abf4 Merge branch 'develop' into cross_signing 2019-12-30 14:27:47 +01:00
6ad914154a Update some libs 2019-12-30 10:46:25 +01:00
cba7e460eb Action bottom sheet: fix deprecated constraints 2019-12-27 18:54:28 +01:00
6794173321 Room detail: fix crash with banner 2019-12-27 18:54:07 +01:00
92f4288d3e Realm: update realm lib version 2019-12-27 17:16:44 +01:00
8109262cbb Home: fix double tab selection 2019-12-27 17:16:30 +01:00
037bf45884 Sync: use foreground service on every android version 2019-12-27 17:09:57 +01:00
833a5a37a2 Pill: fix blink and clean files 2019-12-27 10:24:58 +01:00
00f316ba5d Room members: introduce RoomMemberEntity to be able to query. Still work to do. 2019-12-26 19:51:03 +01:00
dfd8181754 Room profile: start creating some classes and use shared action. 2019-12-20 20:28:27 +01:00
90f2199eb7 Merge pull request #785 from vector-im/feature/initial_sync
Feature/initial sync
2019-12-20 18:18:32 +01:00
63828bc159 Merge branch 'develop' into feature/initial_sync 2019-12-20 17:55:04 +01:00
35b4d90e0d ktlint 2019-12-20 17:54:35 +01:00
4fe9c52737 Move permission to the main AndroidManifest 2019-12-20 17:54:02 +01:00
c54358831f Group throwable extension together 2019-12-20 17:45:32 +01:00
a9d016ae79 Merge branch 'develop' into feature/room_profile 2019-12-20 16:43:16 +01:00
fcdaf14b01 Merge pull request #786 from vector-im/feature/room_alias_rendering
Autocompletion and pills for rooms and groups
2019-12-20 14:58:38 +01:00
83126d5f55 Fix android tests not working 2019-12-20 11:54:59 +01:00
e13281dc97 Update CHANGES and clean code 2019-12-20 11:27:26 +01:00
3cc65b1e71 ktlint 2019-12-20 11:05:54 +01:00
0ccb975d43 Disable MatrixLinkify 2019-12-20 11:04:06 +01:00
54f2ac0d8c Better comment 2019-12-20 10:59:41 +01:00
3ee5a7f54d Better code 2019-12-20 10:55:08 +01:00
3b0624ea40 Fix issue with "in reply to" link 2019-12-20 10:54:48 +01:00
c992d32afd Improve algo 2019-12-20 10:23:45 +01:00
c5739abe32 Update changes.md 2019-12-20 10:16:17 +01:00
3ac473d945 Remove extra blank line 2019-12-20 10:15:53 +01:00
c79b35b089 Autocomplete item layout 2019-12-20 10:15:11 +01:00
8dce98c538 Autocompletion: group (including pills for groups) 2019-12-20 02:54:48 +01:00
543c07fd69 Render pills for room links 2019-12-20 01:23:45 +01:00
05a788453f More generic name 2019-12-20 00:47:47 +01:00
c31b64771b Autocompletion: disable animation on the recycler view items 2019-12-20 00:42:19 +01:00
92f43a591a Autocompletion for room canonical alias 2019-12-20 00:38:42 +01:00
3a829bdfe8 Fix command truncation 2019-12-20 00:05:04 +01:00
237b22df59 Fix lots of trouble with the completion popup (resize, change mode, etc.) - next step 2019-12-19 20:31:36 +01:00
c18be94986 Fix lots of trouble with the completion popup (resize, change mode, etc.) 2019-12-19 20:03:10 +01:00
d342356f29 Add missing state events to the list (not sure about the side effects) 2019-12-19 19:48:30 +01:00
07817b69c2 Rename some event type 2019-12-19 19:46:09 +01:00
e73970d61b Render aliases and canonical alias change in the timeline 2019-12-19 19:39:35 +01:00
0eb0870d6c AvatarRenderer: allow to pass GlideRequests too (fix home group avatar) 2019-12-19 18:29:46 +01:00
55748a4af4 Merge branch 'develop' into feature/initial_sync 2019-12-19 17:49:45 +01:00
51d6b8828d Version++ 2019-12-19 16:46:01 +01:00
358fcb6b34 Merge branch 'release/0.11.0' 2019-12-19 16:44:27 +01:00
9a7cd3f270 Merge branch 'release/0.11.0' into develop 2019-12-19 16:44:27 +01:00
92315a4189 Prepare release 0.11.0 2019-12-19 16:44:14 +01:00
a6afd2e904 Timeline: handle failure when navigating to an unknown event (+ clean some files) 2019-12-19 16:10:59 +01:00
156cc1aa4a Import Strings from Riot 2019-12-19 15:50:18 +01:00
0d36e9d8a6 Merge pull request #779 from vector-im/feature/fix_some_crashes
Fix some crashes and issues
2019-12-19 14:02:19 +01:00
13439769a1 Update wording 2019-12-19 14:01:58 +01:00
7bb8cb0682 Permalink: fix nav to same room 2019-12-19 13:42:15 +01:00
a4ea9a09ad Room factory: add scope to avoid recreate all the dependencies 2019-12-19 13:41:57 +01:00
bf69810f8f Bottom sheet event preview for Sticker 2019-12-19 12:05:47 +01:00
bb9510e59b Create Size data class 2019-12-19 12:05:30 +01:00
4b0dfa49f4 Limit sticker size in the timeline 2019-12-19 11:44:07 +01:00
6652965e48 Ignore lint issue 2019-12-19 10:46:11 +01:00
94125a0215 Merge branch 'develop' into cross_signing 2019-12-19 10:15:47 +01:00
d97402f757 Merge pull request #767 from vector-im/dm_verif_incoming_timeline
Dm verif incoming timeline
2019-12-19 10:12:55 +01:00
5bde7b9f17 Read marker: fix banner visibility when following permalink 2019-12-19 09:58:05 +01:00
c8f0c83cd3 Timeline: don't retry automatically to avoid totally blocking pagination 2019-12-19 09:57:49 +01:00
b0ff2cb4bb cleanup 2019-12-18 19:31:10 +01:00
648691656a Disable click on Stickers (#703) 2019-12-18 19:20:44 +01:00
7eae85a394 Add a ZeroItem to avoid automatic scroll when the breadcrumbs are updated from another client 2019-12-18 18:41:46 +01:00
123ffe9f9c Cleanup 2019-12-18 17:00:18 +01:00
7697278bb2 LiveObservers: launch directly coroutines 2019-12-18 16:59:45 +01:00
c48a439eea Add @JvmStatic for performance reasons.
See https://github.com/airbnb/MvRx/wiki/Advanced-Concepts#mvrxviewmodel
2019-12-18 16:03:10 +01:00
9d26ba3186 Fix rendering issue with HTML formatted body 2019-12-18 12:33:51 +01:00
08970ad8c1 Fix a crash on public room list
It's maybe a workaround, as it should not happen, but at least it will not crash anymore
2019-12-18 09:56:58 +01:00
4c88c12cfe Initial sync, start the sync thread or the sync service 2019-12-17 18:46:19 +01:00
79f11ad686 Prevent crash when mimetype is null 2019-12-17 17:49:28 +01:00
7fa76b9d35 Prevent crash when opening unknown room, which should not happen... 2019-12-17 16:35:04 +01:00
65faedb06b BugReport screen: improve UX when description is too short (reported by Matthew) 2019-12-17 14:26:49 +01:00
1ceddd9607 Rageshake: log resumed screens and add the log verbosity ON/OFF to the rageshakes data 2019-12-17 14:05:58 +01:00
42cdb1db11 Fix crash reported by rageshake: writeToFile may throw exceptions 2019-12-17 12:26:45 +01:00
1c727c1ee4 Fix crash reported by rageshake 2019-12-17 10:42:58 +01:00
2316c98a65 Merge branch 'develop' into feature/initial_sync 2019-12-16 19:11:04 +01:00
a4aa38ee43 Fix new issue on permalink click 2019-12-16 17:14:26 +01:00
4a11d028c0 Merge pull request #706 from vector-im/feature/handle_matrix_to
Feature/handle matrix to
2019-12-16 15:50:21 +01:00
08d005a611 fix merge 2019-12-16 15:44:32 +01:00
c286f2a744 ktlint 2019-12-16 15:43:58 +01:00
89b414e8fe Merge branch 'develop' into dm_verif_incoming_timeline 2019-12-16 15:30:39 +01:00
e2b4899b36 Internal review 2019-12-16 15:21:24 +01:00
aa82cd2064 Update CHANGES 2019-12-16 15:16:46 +01:00
bc568343a2 Open matrix.to with a loader 2019-12-16 15:16:46 +01:00
abf0796794 Room alias and matrix.to link: we can now open a room though roomAlias as long as it's a joined one 2019-12-16 15:16:46 +01:00
02febfb01b Start handling room alias 2019-12-16 15:09:41 +01:00
91c98d4bfb Permalink: start handling permalink from outside the app 2019-12-16 15:05:55 +01:00
cfee6a43fd Merge pull request #760 from vector-im/feature/diff_match_patch_submodule
Use diff_match_patch sources as dependency
2019-12-16 15:02:29 +01:00
f14f1db0e0 Merge pull request #774 from vector-im/feature/breadcrumbs_fixes
Fix various UI issues
2019-12-16 15:00:21 +01:00
3feb2d8980 Merge pull request #768 from vector-im/feature/soft_logout
Handle invalid tokens gracefully
2019-12-16 14:57:11 +01:00
9fc3093c2c Fix issues... 2019-12-16 12:39:51 +01:00
7d910f2566 Auto review 2019-12-16 11:30:53 +01:00
0a0eda3e34 Display first letter of id if display name is empty 2019-12-16 11:08:48 +01:00
cecef5b8da Use id to get first letter, if display name is empty 2019-12-16 10:56:25 +01:00
c9ed95ed21 MatrixItem: create extension and check ids 2019-12-16 10:50:48 +01:00
3dfd6f5a69 Breadcrumbs: increase font size 2019-12-16 10:20:38 +01:00
8fc1400bab Improve user color computation and add unit tests 2019-12-14 10:38:50 +01:00
3e4b07cec3 Do not display " (IRC)") in display names 2019-12-14 10:19:11 +01:00
fbb1846694 Render default room name when it starts with an emoji (#477) 2019-12-13 21:23:18 +01:00
b435212c87 Use same default room colors than Riot-Web
And create MatrixItem
2019-12-13 20:50:32 +01:00
5dd46e82d7 Sync: make only one big transaction to avoid having bad states 2019-12-13 18:21:44 +01:00
3727affc15 cleaning 2019-12-13 18:00:04 +01:00
ff5305ee66 Fix / Verification Msg show fallback text in room summary 2019-12-13 17:56:06 +01:00
3953022258 Merge branch 'cross_signing' into dm_verif_incoming_timeline 2019-12-13 16:51:53 +01:00
1108ad5705 Scroll breadcrumbs to top when opened 2019-12-13 16:50:32 +01:00
b473aeb475 Merge pull request #765 from vector-im/sdk_reference_aggregation
Aggregate Event References for DM verifications
2019-12-13 16:45:27 +01:00
289c03e724 Code review 2019-12-13 16:41:55 +01:00
fe2be90002 Sync: use the CoroutineSequencer but need more tests 2019-12-13 15:37:38 +01:00
f073342954 Cleanup 2019-12-13 15:32:57 +01:00
38b40efac3 Using default values 2019-12-13 15:24:44 +01:00
e60bda7806 Better archi, better code, less bug... 2019-12-13 15:16:26 +01:00
92e60c939d ErrorFormatter: create interface 2019-12-13 14:09:27 +01:00
6e4830e325 ErrorFormatter: move it's declaration to VectorBaseFragment
and avoid duplicated code to manage default onError() in Login fragment
2019-12-13 13:58:49 +01:00
c6b98f3654 Soft Logout - display hard logout screen 2019-12-13 12:40:15 +01:00
12d54140e5 SoftLogout: also handle Unsupported mode 2019-12-13 12:08:37 +01:00
1de85daad9 SoftLogout: handle the case where user sign in with SSO on another account 2019-12-13 11:58:02 +01:00
210dcca0ee Fix / Handling multi open sessions 2019-12-13 11:22:39 +01:00
872baacfe4 Fix / verification conclusion not showing in non hidden mode 2019-12-13 11:20:19 +01:00
050519e998 Soft Logout - add a TODO, waiting for Synapse bugfix 2019-12-13 09:22:24 +01:00
1af44ce5f7 cleanip 2019-12-13 01:37:29 +01:00
8d1a36425d Cleanup 2019-12-13 01:29:49 +01:00
4e74b545ad SoftLogout: recovery with SSO 2019-12-13 01:25:58 +01:00
183d6b53bd SoftLogout: start handling SSO 2019-12-13 00:20:54 +01:00
14562f7285 SoftLogout: Inherit from Login stuff to get free forgot password functionality 2019-12-13 00:08:21 +01:00
17bcd680b0 organise packages 2019-12-12 23:28:54 +01:00
954019547d Soft Logout - update comment 2019-12-12 23:25:14 +01:00
782635ec8e Keep loading after success 2019-12-12 23:20:11 +01:00
e609f4a57e SoftLogout: epoxy: missing elements 2019-12-12 23:17:03 +01:00
907fa35547 Cleanup listener 2019-12-12 22:58:27 +01:00
00d0c34363 SoftLogout: use Epoxy 2019-12-12 22:58:15 +01:00
6811d31a6d Soft Logout - request homeserver login flow 2019-12-12 20:24:46 +01:00
a464c910f8 Fix crash with Realm 2019-12-12 19:43:16 +01:00
975de1dbed Cleaning / klint 2019-12-12 18:48:57 +01:00
d69881f321 cleanup 2019-12-12 17:41:16 +01:00
efc1f38f8c SoftLogout: adapt wording depending if all keys are backed up or not 2019-12-12 17:39:21 +01:00
dedc622140 Merge branch 'sdk_reference_aggregation' into dm_verif_incoming_timeline 2019-12-12 15:55:01 +01:00
b9e8da1fbb SoftLogout: clear notifications 2019-12-12 15:50:05 +01:00
d2fea275d8 SoftLogout: Loading UI 2019-12-12 15:33:22 +01:00
a5af949c15 SoftLogout: Store the info that the token is not valid anymore for a faster startup 2019-12-12 15:32:52 +01:00
9842cac504 More explicit val naming 2019-12-12 15:29:56 +01:00
35404b9a7f Fix merge 2019-12-12 15:05:13 +01:00
0afcb60e7d fix rebase 2019-12-12 14:31:01 +01:00
eab94b4f03 Sequencer: handle cancellation 2019-12-12 14:30:40 +01:00
cb595177a9 Fix test compilation 2019-12-12 13:37:17 +01:00
cb4d52c9fb Aggregate Event References for DM verifications 2019-12-12 13:37:17 +01:00
d0a3b4663e FIx / room transport was not updating state 2019-12-12 13:37:17 +01:00
f53b99a423 rebase 2019-12-12 13:37:17 +01:00
6da0693488 Convert KeyVerificationStart to data class 2019-12-12 13:37:17 +01:00
ea817ff1c5 fix rebase 2019-12-12 12:04:38 +01:00
62f0c6edc0 Fix / Use transport to start verification 2019-12-12 12:04:38 +01:00
e71ad0e515 Simple strategy to Ignore old verification messages 2019-12-12 12:03:59 +01:00
553604423e Support verification using room transport 2019-12-12 12:03:42 +01:00
be723256d3 FIx / room transport was not updating state 2019-12-12 10:49:42 +01:00
819d7182bb rebase 2019-12-12 10:49:42 +01:00
0a2ffdbdf1 Convert KeyVerificationStart to data class 2019-12-12 10:49:42 +01:00
4ac7331f3d fix rebase 2019-12-12 10:49:42 +01:00
7fc57bdf9b Fix / Use transport to start verification 2019-12-12 10:49:42 +01:00
d370f6d7c8 Simple strategy to Ignore old verification messages 2019-12-12 10:49:42 +01:00
46ef442139 cleaning 2019-12-12 10:49:42 +01:00
5f3dc73440 Code review 2019-12-12 10:49:42 +01:00
6137a88a6f Support verification using room transport 2019-12-12 10:49:42 +01:00
82af848c33 Fix / Verification Request Local Echo 2019-12-12 10:27:58 +01:00
6b61c95843 Coroutines: introduce a sequencer 2019-12-11 20:39:07 +01:00
261b4be287 Follow naming convention 2019-12-11 18:51:46 +01:00
205fc0d9d6 Soft Logout - issue with device display name 2019-12-11 18:49:44 +01:00
7699560458 Soft Logout - WIP 2019-12-11 18:35:30 +01:00
a193b2659d Create Uri extension and cleanup login code 2019-12-11 18:34:21 +01:00
bb85d41f05 Password could contain only spaces 2019-12-11 18:34:21 +01:00
9bfe904745 InvalidToken: Regular Signed out screen - move class 2019-12-11 18:34:21 +01:00
284dc8602f InvalidToken: Regular Signed out screen 2019-12-11 18:34:21 +01:00
29087d4a87 InvalidToken: Rework MainActivity args 2019-12-11 18:34:21 +01:00
18649ebddb InvalidToken: notify the app - WIP 2019-12-11 18:34:21 +01:00
d5935a13ac MatrixError: add some MatrixError from the spec and copy paste documentation 2019-12-11 18:34:21 +01:00
670d4dc34e MatrixError: rename the constants to follow the spec 2019-12-11 18:34:21 +01:00
5435a1739e SoftLogout: parse the parameter from server response 2019-12-11 18:34:21 +01:00
853518fbb2 Version++ 2019-12-11 18:34:06 +01:00
a673bf092d Show untrusted conclusions 2019-12-11 18:19:32 +01:00
0776a301ea Incoming DM verification handling in timeline 2019-12-11 16:49:34 +01:00
3a269be2ef Sync: fix crash on gplay flavor and reschedule when no network instead of showing a potential notification all the time 2019-12-11 16:24:30 +01:00
02f03e6b23 Fix test compilation 2019-12-11 16:00:53 +01:00
8305ce67dd Aggregate Event References for DM verifications 2019-12-11 14:44:31 +01:00
95deeb1be7 Merge pull request #730 from vector-im/feature/sdk_dm_verification
[SDK] MSC2241 / verification in DMs
2019-12-11 11:10:46 +01:00
0b93f34fa0 Use diff_match_patch sources as dependency 2019-12-11 10:51:09 +01:00
5338f93852 Sync: use a foreground service for initialSync. 2019-12-10 19:52:12 +01:00
73f0132d5d FIx / room transport was not updating state 2019-12-10 16:37:54 +01:00
902a9aa243 Merge branch 'release/0.10.0' 2019-12-10 15:47:36 +01:00
5915cebd6d Merge branch 'release/0.10.0' into develop 2019-12-10 15:47:35 +01:00
d91ff87fb9 Prepare release 0.10.0 2019-12-10 15:47:26 +01:00
c462d15bcf rebase 2019-12-10 14:23:56 +01:00
3cdd373368 Convert KeyVerificationStart to data class 2019-12-10 11:14:52 +01:00
e14602d1dc fix rebase 2019-12-10 11:14:52 +01:00
2aa9c3ea22 Fix / Use transport to start verification 2019-12-10 11:14:52 +01:00
bbd9738452 Simple strategy to Ignore old verification messages 2019-12-10 11:14:52 +01:00
36c5566b07 cleaning 2019-12-10 11:14:52 +01:00
ce63332a2f Code review 2019-12-10 11:14:52 +01:00
26b4b6e194 Support verification using room transport 2019-12-10 11:14:20 +01:00
79ef055bfb Merge pull request #746 from vector-im/feature/fix_various_issues
Fix 2 crashes reported by the PlayStore
2019-12-10 02:14:23 +01:00
3a761be6b4 Last cleanup 2019-12-10 01:28:07 +01:00
a9e2c31c32 Remove log for privacy 2019-12-10 01:08:05 +01:00
3ac53d20e9 Bugfix: react several times with the same reaction was possible (was a TODO). 2019-12-10 01:05:20 +01:00
3c18fd5335 Improve EmojiChooserFragment: improve filtering result: sort 2019-12-10 00:42:24 +01:00
f00f34b244 Improve EmojiChooserFragment: DI 2019-12-09 23:56:53 +01:00
63e0b15f3d Split EmojiDataSource - cleanup 2019-12-09 23:08:50 +01:00
80306f20df Split EmojiDataSource - avoid !! 2019-12-09 22:57:23 +01:00
2972177541 Split EmojiDataSource - cleanup 2019-12-09 22:46:39 +01:00
1ad8f47dc1 Split EmojiDataSource 2019-12-09 22:36:38 +01:00
8527d3f162 Improve emoji picker search result 2019-12-09 22:30:29 +01:00
99423bacb2 Cleanup 2019-12-09 22:09:17 +01:00
edc6c3dd4f Cleanup 2019-12-09 22:00:41 +01:00
a761a0dbd2 Cleanup 2019-12-09 21:56:03 +01:00
d431ab23c8 Cleanup 2019-12-09 21:33:10 +01:00
f0aa34774e Create RecyclerView extensions and cleanup all the recycler views 2019-12-09 21:31:56 +01:00
742136abe8 Create RecyclerView extensions and cleanup all the recycler views 2019-12-09 18:01:58 +01:00
36aba8554d Update CHANGES.md 2019-12-09 17:43:14 +01:00
da14ae432a Ensure we will not use EpoxyRecyclerView as a View anymore 2019-12-09 17:41:29 +01:00
9a01b4ace9 Make it through bunch of classes removing potential leaks 2019-12-09 17:41:29 +01:00
109c1fe482 Cleanup 2019-12-09 17:41:29 +01:00
dbd4525404 Make sure unhandled Rx error does not crash the app in production 2019-12-09 17:41:29 +01:00
c714266a81 Fix crash reported by the PlayStore.
NullPointerException: at im.vector.riotx.features.home.room.detail.RoomDetailFragment.updateJumpToReadMarkerViewVisibility (RoomDetailFragment.kt:524)
Also properly cleanup model build listener
2019-12-09 17:41:29 +01:00
8b1701e537 Merge pull request #738 from vector-im/feature/ban_reason
Displaay ban and other membership events reason
2019-12-09 14:53:06 +01:00
41d1b77370 Merge pull request #749 from vector-im/feature/hs_discovery
Support entering a RiotWeb client URL instead of the homeserver URL
2019-12-09 14:10:55 +01:00
ac75fe12bf Will be merged for next release 2019-12-09 14:09:03 +01:00
2f26f4b8bb Add default value (fix test compilation issue) 2019-12-09 14:09:03 +01:00
6d82ac7c59 Add default param values 2019-12-09 14:09:03 +01:00
411afb0bf3 Add shortcut for command length 2019-12-09 14:09:03 +01:00
57354cbd69 Add reason to slash commands 2019-12-09 14:09:03 +01:00
03d51281a2 Mistake 2019-12-09 14:08:06 +01:00
415511f3e0 Shortened lines 2019-12-09 14:08:06 +01:00
e0e778909d Better formatting 2019-12-09 14:08:06 +01:00
b9efc9f4bd Ensure user will never see 'null' in a String 2019-12-09 14:08:06 +01:00
872b14373b Better code 2019-12-09 14:08:06 +01:00
d28700e2bf Add reason for all membership events (https://github.com/matrix-org/matrix-doc/pull/2367) 2019-12-09 14:08:06 +01:00
18beef14cf "ban" event are not rendered correctly (#716) 2019-12-09 14:08:06 +01:00
e73923dca3 Merge pull request #741 from vector-im/feature/breadcrumbs
Breadcrumbs
2019-12-09 14:06:27 +01:00
94afd3e66d Add example of config without default homeserver url 2019-12-07 11:05:18 +01:00
5f540a5b45 Support entering a RiotWeb client URL instead of the homeserver URL during connection (#744) 2019-12-06 23:46:40 +01:00
a41617e8aa Fix lint false positive issue 2019-12-06 22:00:49 +01:00
ff1745b5dc Merge pull request #742 from vector-im/feature/fix_739
Fixes #739
2019-12-06 17:10:54 +01:00
8e3e9876b8 Fixes #739 2019-12-06 10:31:40 +01:00
9a4d8f87f6 Breadcrumbs: auto-review 2019-12-05 22:38:49 +01:00
aef76241a3 Breadcrumbs: changes 2019-12-05 22:09:55 +01:00
0768bd5c88 Breadcrumbs: nicer algorithm 2019-12-05 22:05:37 +01:00
65333e6031 Cleanup some Realm queries 2019-12-05 21:49:01 +01:00
849e7c613c Breadcrumbs: live update in correct order 2019-12-05 21:27:56 +01:00
60169d53d7 Breadcrumbs: add some visual attributes 2019-12-05 20:28:07 +01:00
4234c27af9 Version++ 2019-12-05 18:19:20 +01:00
f9c0256afd Merge branch 'release/0.9.1' 2019-12-05 18:17:55 +01:00
b9eb85e0a6 Merge branch 'release/0.9.1' into develop 2019-12-05 18:17:54 +01:00
6d8850b3d6 Prepare version 0.9.1 2019-12-05 18:17:36 +01:00
d88edd578f Merge pull request #740 from vector-im/feature/hot_fix_filter
Feature/hot fix filter
2019-12-05 18:14:46 +01:00
5373d9aa21 Breadcrumbs: fix layout issue 2019-12-05 17:49:45 +01:00
ad4d5e5c02 Breadcrumbs: limit number to 20 2019-12-05 17:43:23 +01:00
eb9775e307 Fix some crypto realm issues 2019-12-05 17:14:56 +01:00
aa9d66b991 Allow returning a value from an async transaction 2019-12-05 17:14:38 +01:00
4ff12605e9 Breadcrumbs: notify viewed rooms 2019-12-05 16:06:47 +01:00
7c561ae622 Breadcrumbs simple UI 2019-12-05 14:51:12 +01:00
cec08a20e5 Handle breadcrumbs from account data 2019-12-05 12:13:45 +01:00
fb8ba32fb4 Version++ 2019-12-05 09:46:36 +01:00
8e9ac8198d Merge branch 'release/0.9.0' 2019-12-05 09:44:06 +01:00
7a05207ae4 Merge branch 'release/0.9.0' into develop 2019-12-05 09:44:06 +01:00
6b39cf3b70 Prepare release 0.9.0 2019-12-05 09:43:58 +01:00
994759e11a Merge pull request #737 from vector-im/feature/otk_upload
Improve and cleanup OneTimeKey uploader
2019-12-05 09:38:05 +01:00
f31c1b69cb Remove delay when waiting for first sync to finish and add number of sent keys in the log 2019-12-04 16:52:55 +01:00
bdb9d2fbb8 Improve and cleanup OneTimeKey uploader
Fix boolean reset if request fails
Implement https://github.com/matrix-org/matrix-js-sdk/pull/493
2019-12-04 16:34:25 +01:00
9fb50dde32 Merge pull request #726 from vector-im/feature/sign_x_stabilization
Registration stabilization
2019-12-04 16:26:48 +01:00
a145aae0aa Avoid using !! 2019-12-04 15:38:16 +01:00
3623072f08 Attempt to properly cancel the crypto module when user signs out (#724)
Attempt to properly cancel the crypto module when user signs out (#724)
2019-12-04 15:38:16 +01:00
2717ad475a Merge pull request #699 from vector-im/feature/read_marker_rework
Feature/read marker rework
2019-12-04 14:12:41 +01:00
a6f8fe9317 Fix lint issue 2019-12-04 12:08:18 +01:00
f9eb80b4ec Simplify layout 2019-12-04 11:42:18 +01:00
9510d71cd3 Proposal for simple layout 2019-12-04 11:42:18 +01:00
e7a47ae32a Some cleanup 2019-12-04 11:42:18 +01:00
7890b929a7 Update CHANGES 2019-12-04 11:42:18 +01:00
0376de08f4 Clean files 2019-12-04 11:41:54 +01:00
90c472fef9 Read marker: fix mark all as read 2019-12-04 11:41:54 +01:00
8e873672a9 Read marker: change design 2019-12-04 11:41:54 +01:00
bba52e77d1 Read marker: fix merged items 2019-12-04 11:41:54 +01:00
64d73ae8e6 Read marker: handle the jump to read marker 2019-12-04 11:41:54 +01:00
d9982076f9 Read marker: continue rework [WIP] 2019-12-04 11:39:51 +01:00
ab489df83d Read marker: don't show unread on events we own 2019-12-04 11:33:06 +01:00
5e07e96bdb Read marker: start reworking how we manage it [WIP] 2019-12-04 11:33:06 +01:00
c495aa4914 Merge pull request #731 from vector-im/feature/fix_pills
Fix issue with pill: also send the text after the last pills
2019-12-03 18:19:36 +01:00
ff267ba9bc Update changelog 2019-12-03 16:36:44 +01:00
69f923383c Rename some classes with "Item" suffix, as a convention (ooi) 2019-12-03 16:32:25 +01:00
c69852c849 Make url clickable on the preview of event in the bottom sheet - avoid instantiating objects in the bind() method 2019-12-03 16:17:49 +01:00
6d7f2670df Make url clickable on the preview of event in the bottom sheet 2019-12-03 16:02:07 +01:00
71de8fdad3 Display pills Avatar in the message preview 2019-12-03 15:08:44 +01:00
998d9f2c59 Bugfix: Text after the last pill was not send 2019-12-03 14:48:41 +01:00
4f3da353e4 Add ellipsis char for action with another step 2019-12-03 13:23:44 +01:00
4154cb2b85 Improve wording of the title of read receipt list 2019-12-03 13:21:42 +01:00
3c6eb4bccf Rework FilterEntityQueries to fix issue of ghost Realm reference 2019-12-03 11:10:43 +01:00
7b4398404b Update wording for modular screens 2019-12-03 11:10:43 +01:00
9b882978ed Update modular link 2019-12-03 11:10:43 +01:00
49178dc633 Reduce some log level 2019-12-03 11:10:43 +01:00
490ce4b51d Fix issue of closing Realm in another thread (#725) 2019-12-03 10:05:10 +01:00
5b63856d96 Add log to detect if a realm instance is not properly closed 2019-12-02 18:33:31 +01:00
538c4d1a64 typo 2019-12-02 18:15:21 +01:00
1cadbb8eed Ensure credentials can be stored, even if they already exist 2019-12-02 13:48:20 +01:00
3f4f7457c7 Merge pull request #689 from vector-im/feature/signin_signup
Login and Registration
2019-12-02 13:47:28 +01:00
ebf21fe9d8 Merge pull request #687 from vector-im/feature/dat_pill
Send mention pills from composer
2019-11-29 16:28:34 +01:00
a343da594f Import Strings from Riot 2019-11-29 16:22:04 +01:00
938289e8eb ktlint 2019-11-29 15:44:08 +01:00
e23763e6db Update password from email twice 2019-11-29 15:43:39 +01:00
c06b8486ea Update wording 2019-11-29 15:36:54 +01:00
67fe776d91 Update Changes 2019-11-29 13:27:50 +01:00
10cc270273 ktlint 2019-11-29 13:27:26 +01:00
46d96429e0 Create ooi extension 2019-11-29 13:27:26 +01:00
9f9c418085 Pills: cleanup and robustness 2019-11-29 13:27:26 +01:00
c412006f0e Pills: render the avatar 2019-11-29 13:27:26 +01:00
5d3c376267 Pills: remove pills when a char is deleted 2019-11-29 13:27:26 +01:00
a3f8f138a6 Create showKeyBoard() extension 2019-11-29 13:27:26 +01:00
4b273e8746 Pills: simplify and improve the algorithm 2019-11-29 13:27:26 +01:00
f11cd47df3 Pills: cleanup 2019-11-29 13:27:26 +01:00
f984758d37 Pills: Daggerization 2019-11-29 13:27:26 +01:00
97766404d6 klint 2019-11-29 13:27:26 +01:00
38b93c527b Ensure received pills spans do not overlap 2019-11-29 13:27:26 +01:00
62bae67080 Code review 2019-11-29 13:27:26 +01:00
2a4cdec020 klint cleaning 2019-11-29 13:27:26 +01:00
6bd7257cf2 Send mention pills from composer 2019-11-29 13:27:26 +01:00
500eb113b6 Login screens: add some animation for Fragment transition (WIP) 2019-11-28 20:36:29 +01:00
1bec8c29b8 Add missing items for Status theme 2019-11-28 15:52:32 +01:00
0ecb23199c Login screens: add background color 2019-11-28 13:25:56 +01:00
33925fcf57 Login screens: fix crash on back navigation 2019-11-28 12:09:28 +01:00
bf9ce4f690 Merge pull request #714 from vector-im/feature/upgrade_gif_drawable
Force android-gif-drawable version
2019-11-28 10:24:40 +01:00
d2a4163dff Merge pull request #691 from vector-im/anoa/typo
Small typo fix
2019-11-28 09:55:16 +01:00
a0d7aef92e Force android-gif-drawable version
BigImageViewer update (updated the android-gif-drawable dep)
2019-11-28 09:39:04 +01:00
29f32cf8eb Login screens: fix regression on Back press 2019-11-27 16:48:28 +01:00
bb1c988a49 Login screens: Update the local pendingSessionData synchronously, store asynchronously 2019-11-27 16:36:35 +01:00
f063abe068 Login screens: keep PendingSessionData member up to date 2019-11-27 16:15:51 +01:00
db87d8f644 Login screens: Realm migration for Auth DB 2019-11-27 15:52:02 +01:00
efa858a337 Login screens: reorder reset action for clarity 2019-11-27 15:11:02 +01:00
fd90f3b9fc Login screens: reset SDK when home server url is deleted 2019-11-27 15:08:36 +01:00
aa51764068 Login screens: save isRegistrationStarted in DB 2019-11-27 15:04:00 +01:00
0a19ded167 Login screens: extract some classes 2019-11-27 14:34:07 +01:00
2e3763e8b4 Login screens: persist all data during login or registration 2019-11-27 14:26:06 +01:00
0c4e0890b1 Use Realm.use { } 2019-11-27 10:49:33 +01:00
e532d97ec1 Login screens: persist login mode 2019-11-27 10:04:41 +01:00
fbde8d7d18 ktlint 2019-11-26 18:04:42 +01:00
f96bea742e Login screens: split long lines 2019-11-26 18:04:00 +01:00
86bfdd011e Login screens: cleanup and ignore lint issue 2019-11-26 18:03:09 +01:00
d5c2c1938c Login screens: move user choices to the ViewState 2019-11-26 17:59:01 +01:00
fd18bcb97f Room profile: branch leave and notifications actions 2019-11-26 17:25:26 +01:00
ab4cab05cf Room profile: continue working on UI 2019-11-26 13:22:07 +01:00
7ce8a13ddf Login screens: prepare for saving user state 2019-11-26 13:11:31 +01:00
9bd4dbb65f Login screens: trim homeserver url 2019-11-26 12:40:17 +01:00
ee875b359b Login screens: update wording 2019-11-26 12:25:37 +01:00
3eb2e1655f Login screens: ensure homeserver version is supported - fix bug for SSO 2019-11-26 12:16:39 +01:00
9b207dd5dc Login screens: ensure homeserver version is supported 2019-11-26 11:39:33 +01:00
3f1540b54e Update wording 2019-11-26 09:51:35 +01:00
2b30925163 Login screens: doc for sign in 2019-11-26 09:49:53 +01:00
4690754f5f Merge pull request #702 from vector-im/feature/quick_fix
2 quick fixes
2019-11-25 18:48:43 +01:00
a9526cdd92 Login screens: use homeserver and identity server Uri provided along with the credential is any 2019-11-25 18:32:24 +01:00
ab4d42fb20 Login screens: mutualize the code which create session from the credentials 2019-11-25 18:16:57 +01:00
0014e8ef06 Login screens: rename variables 2019-11-25 17:32:27 +01:00
311d8ddf7b Login screens: fix layout issue 2019-11-25 17:24:31 +01:00
6cb3c222a9 Login screens: handle mandatory dummy stage automatically 2019-11-25 16:47:17 +01:00
f84ec08847 Code cleanup, restore comment, and fix regression on delay 2019-11-25 14:11:38 +01:00
9d0188cbf1 Create user from userId during initialSync 2019-11-22 20:28:52 +01:00
73462a3045 Clean some coroutine code 2019-11-22 20:04:11 +01:00
3eebf965e5 Fix emoji filtering not working 2019-11-22 15:19:09 +01:00
bba58d25e1 Do not show long click help if only invitation are displayed 2019-11-22 14:54:22 +01:00
fedb45b019 Login screens: add doc on signin 2019-11-22 14:35:39 +01:00
9b83f08654 Login screens: fix compilation issue (lint) 2019-11-22 14:24:22 +01:00
91fcf428dd Login screens: login with unknown email 2019-11-22 14:21:14 +01:00
7e1a279fd9 Update changelog (Fixes #34, Fixes #613) 2019-11-22 12:19:15 +01:00
8de1fa835b Improve M_LIMIT_EXCEEDED error rendering 2019-11-22 12:15:19 +01:00
af45c554fd Login screens: fix scroll issue 2019-11-22 12:15:19 +01:00
11bc7051fd Login screens: splash scrollable 2019-11-22 12:15:19 +01:00
489a594027 Login screens: ensure forms are scrollable on small screens 2019-11-22 12:15:19 +01:00
3f83c161e4 Login screens: fix code quality issues 2019-11-22 12:15:19 +01:00
e0a36b794f Login screens: fix lint issues 2019-11-22 12:15:19 +01:00
d2b516bdc2 Login screens: fix issue with reset password fragment navigation 2019-11-22 12:15:19 +01:00
37166caea2 Login screens: create sub method 2019-11-22 12:15:19 +01:00
9fa131c297 Login screens: reset password: display a better popup when link is not clicked yet 2019-11-22 12:15:19 +01:00
71ae3c4a8c Login screens: reset password: display a warning when the process is not finished 2019-11-22 12:15:19 +01:00
f87526e615 Login screens: reset password: add documentation 2019-11-22 12:15:19 +01:00
51f53e2ae9 Login screens: reset password: fix a few errors 2019-11-22 12:15:19 +01:00
ef35f0a044 Login screens: disable submit button when input is empty 2019-11-22 12:15:19 +01:00
5db3f51ddb Login screens: fix bad view binding 2019-11-22 12:15:19 +01:00
49f7ce3554 Login screens: better API 2019-11-22 12:15:19 +01:00
a3111dc2d8 Login screens: rename a few classes and packages 2019-11-22 12:15:19 +01:00
be95542110 Login screens: dummy stage shoud not be mandatory 2019-11-22 12:15:19 +01:00
6723a566c2 Login screens: refacto: create an AuthenticationWizard 2019-11-22 12:15:19 +01:00
90027cc4d5 Login screens: reset password WIP 2019-11-22 12:15:19 +01:00
810b226f21 Do not trim login nor password 2019-11-22 12:15:19 +01:00
42c5adf08d ktlint 2019-11-22 12:15:19 +01:00
5edfb78721 Cleanup errors and close keyboard at each login step 2019-11-22 12:15:19 +01:00
491a38a79f Login screens: send again 3pid 2019-11-22 12:15:19 +01:00
051f77087e Email format validation 2019-11-22 12:15:19 +01:00
1a603742d0 Cleanup 2019-11-22 12:15:19 +01:00
edb65f1787 Fix some errors 2019-11-22 12:15:19 +01:00
9af8355c07 Fix wording 2019-11-22 12:15:19 +01:00
dd44078297 Login screens: fix several issue with check email screen 2019-11-22 12:15:19 +01:00
a1f96a5b5a Login screens: typo 2019-11-22 12:15:19 +01:00
5770023593 Login screens: code cleanup 2019-11-22 12:15:19 +01:00
2789268c23 Login screens: MSISDN: check format and compute country code 2019-11-22 12:15:19 +01:00
eb4355890e Login screens: setup autofill 2019-11-22 12:15:19 +01:00
4e41156db3 Login screens: doc: registration forbidden 2019-11-22 12:15:19 +01:00
1a0b8b35f8 Login screens: Doc: adapt log to correct logs and fix typo 2019-11-22 12:15:19 +01:00
5f9cdcb4b4 Login screens: Doc: add msisdn stage 2019-11-22 12:15:19 +01:00
2e4c3f850a Cleanup 2019-11-22 12:15:19 +01:00
127916a8d9 Login screens: add MSISDN 2019-11-22 12:15:19 +01:00
248a584e1a Login screens: Add Msisdn - WIP 2019-11-22 12:15:19 +01:00
b8a3ad0c43 Login screens: Wait for email validation screen 2019-11-22 12:15:19 +01:00
1f161b7e23 Login screens: Add 3Pid step 1 2019-11-22 12:15:19 +01:00
23315ede92 Login screens: update wording 2019-11-22 12:15:19 +01:00
20ad3abb60 Login screens: set initial device name 2019-11-22 12:15:19 +01:00
ac377fceba Login screens: mutualize registration callback 2019-11-22 12:15:19 +01:00
abbe56acfa Login screens: UI: display errors properly 2019-11-22 12:15:19 +01:00
f74cabd145 Login screens: UI: style to prepare for landscape 2019-11-22 12:15:19 +01:00
0e2237226f Login screens: back button management for registration 2019-11-22 12:15:19 +01:00
62d5aba796 Login screens: back button management for SSO 2019-11-22 12:15:19 +01:00
f12e6c941d Login screens: sigin button for SSO 2019-11-22 12:15:19 +01:00
7caa8ce3bc Login screens: disabled registration 2019-11-22 12:15:19 +01:00
20f969d563 Login screens: fix issue on terms 2019-11-22 12:15:19 +01:00
a8f24e5c39 Login screens: a11y 2019-11-22 12:15:19 +01:00
8ae9544b48 Login screens: Loading on Captcha step 2019-11-22 12:15:19 +01:00
3758334824 Login screens: cleanup the Fragment stack after completing stage 2019-11-22 12:15:19 +01:00
6d8e5b892e Login screens: Show disclaimer dialog only in HomeActivity, now that RiotX supports registration 2019-11-22 12:15:19 +01:00
c18c140ec9 Login screens: Animate the logo in screen transition 2019-11-22 12:15:19 +01:00
1dc7dfc896 Login screens: registration fallback 2019-11-22 12:15:19 +01:00
1c03163a33 Login screens: prepare email and msisdn 2019-11-22 12:15:19 +01:00
9aa270c7ad Login screens: Perform dummy action when user does not want to enter an email -> account created! 2019-11-22 12:15:19 +01:00
3f80076fb1 Login screens: Terms step for registration 2019-11-22 12:15:19 +01:00
dfbf448bb7 Login screens: Captcha step for registration 2019-11-22 12:15:19 +01:00
95fc20dca0 Login screens: Registration: login/password step 2019-11-22 12:15:19 +01:00
381084b2ab Login screens: USER_IN_USE error 2019-11-22 12:15:19 +01:00
41ac2c6d70 Login screens: Registration WIP 2019-11-22 12:15:19 +01:00
08ea3d049e Login screens: Simple Input form (UI) 2019-11-22 12:15:19 +01:00
f24889230c Login screens: Captch screen (UI) 2019-11-22 12:15:19 +01:00
b5f9549a8b Login screens: Fix issues on button style 2019-11-22 12:15:19 +01:00
e3e38d4c8a Login screens: Fix issues on modular tile 2019-11-22 12:15:19 +01:00
416bef7903 Login screens: button theme 2019-11-22 12:15:19 +01:00
823acebf78 Login screens: harmonize styles for containers 2019-11-22 12:15:19 +01:00
3e91125872 Fix issues 2019-11-22 12:15:19 +01:00
9a628c7b5d ktlint 2019-11-22 12:15:19 +01:00
fb46a14172 Fix compilation issue after rebase 2019-11-22 12:15:19 +01:00
ca4e75a1a0 Login screens: Fix a few bugs 2019-11-22 12:15:19 +01:00
2871e4f5b1 Login screens: forget password screens 2019-11-22 12:15:19 +01:00
b7bfb20a2e Login screens: login and registration fallback 2019-11-22 12:15:19 +01:00
a1aa16715d Login screens: move elements from ViewState to ViewModel 2019-11-22 12:15:19 +01:00
55add4734d Login screens: Fix Other rendering issue 2019-11-22 12:15:19 +01:00
2849e1f846 Login screens: Splash: update icons 2019-11-22 12:15:19 +01:00
5b9876a20c Login screens: Fix navigation issue 2019-11-22 12:15:19 +01:00
adf299081d Login screens: re-click on an item submit it 2019-11-22 12:15:19 +01:00
d50b690523 Login screens: improve LoginFragment 2019-11-22 12:15:19 +01:00
c6b0ae63ea Login screens: handle loading Views and global navigation - WIP 2019-11-22 12:15:19 +01:00
3c93807fe6 Login screens: add some doc 2019-11-22 12:15:19 +01:00
7f1f98c2e5 Login screens: reset state when navigating back 2019-11-22 12:15:19 +01:00
6525314af8 Login screens: server ur form 2019-11-22 12:15:19 +01:00
da8d6fb4f4 Login screens: signup signin selection 2019-11-22 12:15:19 +01:00
fa6a9cab7e Login screens: server selection 2019-11-22 12:15:19 +01:00
bdfc4ad8a7 Login screens: splash screen 2019-11-22 12:15:19 +01:00
6ab7209e4d Handle navigation with VectorSharedAction 2019-11-22 12:14:48 +01:00
4485d1c685 Registration flow: SDK side 2019-11-22 12:14:48 +01:00
8b63f78d76 Add documentation on the sign up flow 2019-11-22 12:14:48 +01:00
2e87e0b4c1 fix typo 2019-11-21 01:41:59 +00:00
507134407b Update CHANGES.md 2019-11-19 15:10:41 +00:00
7663cd4e23 Merge branch 'develop' of github.com:vector-im/riotx-android into anoa/typo 2019-11-19 15:10:24 +00:00
ec2954200e Version++ 2019-11-19 09:58:48 +01:00
eb32c5455f Merge branch 'release/0.8.0' 2019-11-19 09:47:57 +01:00
fc367b3c3e Merge branch 'release/0.8.0' into develop 2019-11-19 09:47:56 +01:00
57dcd569f3 Prepare release 0.8.0 2019-11-19 09:47:12 +01:00
3673520ef6 Small typo fix 2019-11-18 13:30:03 +00:00
8aab46804b Profile room: continue working on it (try to get a nice animation) [WIP] 2019-11-15 20:37:36 +01:00
fe17050580 Merge pull request #685 from vector-im/feature/timeline_items
Feature/timeline items
2019-11-15 16:11:37 +01:00
0edc953a23 Room profile: start creating epoxy items and implementing UI 2019-11-14 20:13:59 +01:00
fa67509ac2 Room profile: start initializing all the classes + move some packages 2019-11-14 15:34:50 +01:00
ec40a8c969 Update CHANGES 2019-11-14 13:26:25 +01:00
6b1b3bec85 Clean code for klint 2019-11-14 13:25:04 +01:00
6bd6ececb7 Timeline: handle sticker events 2019-11-14 13:23:12 +01:00
c7db695e67 Timeline: handle join rules event 2019-11-14 12:21:55 +01:00
4cefdfedce Home: use detach/attach instead of hide/show 2019-11-14 11:18:45 +01:00
6ce241163e Merge pull request #679 from vector-im/feature/perf_again
Feature/perf again
2019-11-13 19:43:07 +01:00
79350899c5 Read receipts: use primary key to query 2019-11-13 19:21:14 +01:00
f265724a3c Login sso: handle failure 2019-11-13 19:20:03 +01:00
2e50d2a36e Clean code for klint 2019-11-13 11:38:30 +01:00
643c062858 Merge branch 'develop' into feature/perf_again 2019-11-13 10:44:59 +01:00
0e0db67aef Timeline: clear some resources when unbind 2019-11-12 20:34:19 +01:00
6dc5b126d6 Optimize room list processing 2019-11-12 19:53:07 +01:00
d2acabddd9 RoomDetail: fix enter/exit mode again after merge 2019-11-12 19:25:57 +01:00
ec71b53c1e RoomSummary: don't map read receipts 2019-11-12 19:25:21 +01:00
fc3d4187d1 Merge pull request #676 from vector-im/feature/long_click_room
Add help to reveal the long click on a room
2019-11-12 18:29:42 +01:00
a25f309990 Merge pull request #678 from vector-im/feature/block_user_menu
Add action to block user in the message action bottom sheet
2019-11-12 18:17:18 +01:00
5449592422 Add action to block user in the message action bottom sheet (following Nad's design) 2019-11-12 17:52:03 +01:00
19b415871d Extract displaymode, clear adapter on roomList/timeline and use commitNow when possible 2019-11-12 15:13:20 +01:00
6463f3439f Update Mvrx to 1.3 2019-11-12 15:11:52 +01:00
f2320f9571 Merge pull request #665 from vector-im/feature/color_theme
Ensure color is retrieved from current theme, even when theme change
2019-11-12 12:29:27 +01:00
fc91694bdd Merge pull request #673 from vector-im/feature/us
Update strings
2019-11-12 12:08:55 +01:00
dbb41108ef Improve layout 2019-11-12 11:50:16 +01:00
08c864bad7 Add help to reveal the long click on a room 2019-11-12 11:39:47 +01:00
9c5c65a243 Cleanup 2019-11-12 10:36:53 +01:00
b6199b1f27 Fix some issues with fragments managers (Home fragments) and lifecycle 2019-11-08 19:49:08 +01:00
38da54119a Merge branch 'develop' into feature/perf_again 2019-11-08 18:39:06 +01:00
65b09ad4f0 Merge pull request #675 from vector-im/feature/cleanup
Cleanup ViewModel for code clarity
2019-11-08 18:19:22 +01:00
603b8fae45 Add missing binding 2019-11-08 17:30:04 +01:00
50e2e6a823 Cleanup 2019-11-08 17:23:21 +01:00
bb237e3bbb Fix ViewModel for Signout 2019-11-08 17:21:46 +01:00
1bd2c0d220 Merge branch 'develop' into feature/perf_again 2019-11-08 17:09:22 +01:00
bcb811a7e8 Realm perf: use Dispatchers.Default for write, as we don't want to create so many threads (and we can only have one write transaction at a time) 2019-11-08 17:08:44 +01:00
ec4d7e29ec Ensure we use the correct viewModelProvider 2019-11-08 17:08:29 +01:00
a6df63f6d9 Fix crash 2019-11-08 16:56:45 +01:00
ea7213a5ae Split long lines 2019-11-08 16:16:42 +01:00
590a13334d ktlint 2019-11-08 16:04:41 +01:00
631448335d Rename stuff for code coherence 2019-11-08 15:36:12 +01:00
12376368c7 Rename class 2019-11-08 15:20:55 +01:00
f17564d743 Simple code 2019-11-08 15:08:50 +01:00
a6fcc7dca6 Move class to dedicated file 2019-11-08 15:07:01 +01:00
70bce9e7dd Ensure ViewModel follow the same pattern to handle actions 2019-11-08 15:05:11 +01:00
17f3614288 Perf: try to optimize room summary updates 2019-11-08 13:48:35 +01:00
238d1d87c6 Rename class 2019-11-08 13:31:39 +01:00
82f639b91f Rename to Shared 2019-11-08 12:09:08 +01:00
c8bc553caa Move class to dedicated file 2019-11-08 12:01:36 +01:00
fa5d44af65 Create common parent for Action view model, to handle navigation, action, or other type of event 2019-11-08 11:54:17 +01:00
cbdbe5033f Merge pull request #664 from vector-im/feature/room_list_actions
Feature/room list actions
2019-11-07 15:45:45 +01:00
61ac250e2b Merge branch 'develop' into feature/room_list_actions 2019-11-07 15:43:21 +01:00
04f72dfcb8 Clean code after Benoit's review 2019-11-07 15:19:12 +01:00
10ca5d94ea Fix issue after rebase 2019-11-07 14:29:08 +01:00
c5b8c69ae5 Merge pull request #668 from vector-im/feature/block_user
Block user and display ignored users list
2019-11-07 14:28:23 +01:00
d3d7f7cc61 Split long lines 2019-11-07 14:18:57 +01:00
b6bb714264 Display name and avatar of the user 2019-11-07 14:18:57 +01:00
a87310ac15 update comment 2019-11-07 14:18:57 +01:00
032e1b3d19 ktlint 2019-11-07 14:18:57 +01:00
d9f15c1d21 Block user possibility after reporting event content 2019-11-07 14:18:57 +01:00
99d09f71ad Changelog 2019-11-07 14:18:57 +01:00
9c952b6bc8 Display ignored users list 2019-11-07 14:18:57 +01:00
fbae3d27c2 Ignore/Unignore userIds 2019-11-07 14:13:29 +01:00
2f7d1f9f01 Ignored Users account data 2019-11-07 14:13:29 +01:00
114101699d Fix potential ignoring of account data (return@foreach) 2019-11-07 14:13:29 +01:00
f5c0dcb5ea Merge pull request #670 from vector-im/feature/fragment_factory
Feature/fragment factory
2019-11-07 13:59:46 +01:00
241220ce1f remove unused import 2019-11-07 13:59:21 +01:00
98d97e574c Fix regression when filtering emojis 2019-11-07 12:23:21 +01:00
96e610970a Finish the work 2019-11-07 12:08:17 +01:00
2027802f82 Add debug screen for all SAS emoji 2019-11-07 10:37:49 +01:00
54f93db632 RoomDetail : enter/exit special mode without waiting for draft to update 2019-11-06 20:08:19 +01:00
3af7ca9ab0 Retrofit: lazy init okhttp 2019-11-06 20:07:28 +01:00
93ef3edab3 Remove some use of sync write in realm 2019-11-06 18:47:11 +01:00
c85852262e Remove bad value 2019-11-06 18:28:16 +01:00
d0c3271628 Import string from Riot-Android and fix #671 2019-11-06 18:19:37 +01:00
ad9a48d5fa Clean code 2019-11-05 18:36:30 +01:00
219d1383e5 Fragments: use FragmentContainerView 2019-11-05 18:13:55 +01:00
8871280fab Fragments: use constructor injections in most of the Fragments 2019-11-05 18:12:04 +01:00
fb3e953e28 Merge pull request #667 from vector-im/feature/realm_cleanup
Import change form https://github.com/matrix-org/matrix-android-sdk/pull/505
2019-11-05 12:13:25 +01:00
10712fd6ab ktlint 2019-11-05 12:13:06 +01:00
9d478dbfe2 Import change form https://github.com/matrix-org/matrix-android-sdk/pull/505 2019-11-05 11:18:22 +01:00
3013d67c16 Fragment factory: start including the new version with FragmentFactory [WIP] 2019-11-04 19:33:56 +01:00
bee8c2d159 Ensure color is retrieved from current theme, even when theme change 2019-11-04 18:12:24 +01:00
945e5d5a74 Merge branch 'develop' into feature/room_list_actions 2019-11-04 17:17:43 +01:00
93df8c56a8 Fix compilation error and use mockk instead of manual mocking (prone to error) 2019-11-04 17:09:03 +01:00
cd1a964067 Merge pull request #649 from vector-im/feature/spoiler_support
Support spoilers in messages
2019-11-04 16:54:43 +01:00
e4b829f0cf Lift of 'return' 2019-11-04 16:53:51 +01:00
7206d84a6b Add FIXME 2019-11-04 16:51:45 +01:00
b3233d3eb7 Change spoiler bg colors 2019-11-04 16:50:32 +01:00
3c4c0ed46a Add /spoiler command 2019-11-04 16:50:32 +01:00
24f1262005 Merge refactoring 2019-11-04 16:49:53 +01:00
86667a6d8a Passes text color instead of context 2019-11-04 16:49:53 +01:00
42e0d0f769 Improve code to check url validity 2019-11-04 16:49:53 +01:00
e976055253 Support spoilers in messages 2019-11-04 16:49:53 +01:00
84d6c8ec16 Merge pull request #646 from vector-im/feature/search_reaction
Search reaction by name/keywords
2019-11-04 15:51:24 +01:00
9fdfd091ac Merge branch 'develop' into feature/search_reaction 2019-11-04 15:51:16 +01:00
e66766f41c Update CHANGES 2019-11-04 15:12:30 +01:00
6177e69855 Merge branch 'develop' into feature/room_list_actions 2019-11-04 15:11:20 +01:00
5c71cabb5f Clean code 2019-11-04 15:08:08 +01:00
6ebe5532c5 Room list actions: use new strings 2019-11-04 14:59:12 +01:00
8030c44f44 Room list actions: fix some UI issues and render selected notification state 2019-11-04 14:31:03 +01:00
a85b5af761 Merge pull request #641 from vector-im/feature/fix_crash
Fix crash
2019-11-04 14:28:31 +01:00
d780c74abf Merge pull request #657 from vector-im/feature/locales
Support Cyrillic script
2019-11-04 14:27:24 +01:00
5d7efa7f8f Merge pull request #660 from vector-im/feature/permission
Ask for permission to write external storage when uri comes from the keyboard (#658)
2019-11-04 14:26:12 +01:00
7e467443ed Merge pull request #651 from vector-im/feature/markdown_off
Markdown off
2019-11-04 10:23:21 +01:00
8439c337f7 Merge branch 'develop' into feature/markdown_off 2019-11-04 10:22:20 +01:00
151ad01038 Use RxBinding on searchView 2019-11-01 11:57:15 +01:00
73267442bb Fix / remove listener 2019-11-01 11:30:13 +01:00
43fd794c96 Ask for permission to write external storage when uri comes from the keyboard (#658) 2019-10-31 15:48:07 +01:00
36060fe332 Merge pull request #654 from vector-im/feature/timeline_message_code
Feature/timeline message code
2019-10-31 15:08:13 +01:00
3483debcc1 Little cleanup 2019-10-31 12:08:55 +01:00
4324f6abbd Add paragraph about a11y 2019-10-31 11:11:03 +01:00
43f8d8d8aa Merge pull request #656 from pvagner/a11y_file_type_selector
a11y: file type selector
2019-10-31 10:52:28 +01:00
fb1ff77ec4 Add string from Riot-Android 2019-10-31 10:09:27 +01:00
e355a7f6dd Changelog entry 2019-10-31 07:58:08 +01:00
33e35368fc a11y: better presentation for file type selector buttons to screen reader users
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-31 06:36:28 +01:00
0e49a11e5e Merge pull request #648 from vector-im/feature/fix_#498
Feature/fix #498
2019-10-30 19:28:35 +01:00
d47cf7e932 Merge branch 'develop' into feature/fix_#498 2019-10-30 19:26:11 +01:00
101057520b Fix disambiguated with empty senderName 2019-10-30 19:25:24 +01:00
30b2e53002 Update CHANGES 2019-10-30 19:02:44 +01:00
5ab31a0ef5 Fix klint 2019-10-30 19:00:56 +01:00
b4ae331086 Timeline: render inline and block code 2019-10-30 19:00:00 +01:00
3f447df13c Support local script (imported from https://github.com/vector-im/riot-android/pull/3364) 2019-10-30 16:59:31 +01:00
3517873156 Timeline: Start handling code blocks. [WIP] 2019-10-29 19:08:48 +01:00
118870bc41 ktlint cleanup 2019-10-29 17:02:55 +01:00
d001ab5bef Merge pull request #640 from Dominaezzz/kotlinify
The last of the clean up.
2019-10-29 17:01:38 +01:00
7496a88dcd Markdown set to off by default (Fixes #412) 2019-10-29 16:22:12 +01:00
6567c5e6c7 Small kotlin improvement 2019-10-29 16:20:22 +01:00
361427488f Passphrase does not match (Export room keys) (Fixes #644) 2019-10-29 14:38:04 +01:00
7272343e6d Update comment 2019-10-29 14:32:05 +01:00
f0b3151d71 Merge pull request #639 from vector-im/feature/compile_tests
Build and run test on CI
2019-10-29 14:27:47 +01:00
035359cb35 Update CHANGES and clean code 2019-10-28 17:01:41 +01:00
57b640622b Sender Name: we should use disambiguated display name over senderName. PrevContent fallback is now handled in SDK 2019-10-28 16:48:55 +01:00
de4c389c76 klint cleaning 2019-10-28 15:12:49 +01:00
199456487c Search reaction by name/keywords 2019-10-28 14:36:15 +01:00
00ca5dc70a RoomListActions: handle room notification state. Still need to branch UI 2019-10-25 18:23:47 +02:00
a04802b238 CI / upgrade queue to xlarge 2019-10-25 11:14:17 +02:00
cb275aee37 Room list actions: start showing items and refact a bit RxStore 2019-10-24 19:11:49 +02:00
fbf73c7c8e shorter code 2019-10-24 18:52:34 +02:00
0040f8e924 Fix crash reported by Rageshake, stateKey can be null 2019-10-24 18:51:47 +02:00
6cca242f77 Fix Android test compilation issue 2019-10-24 17:49:34 +02:00
2929b8f617 Ensure Android tests compile and fix warnings 2019-10-24 17:24:42 +02:00
8422c6de17 Remove test sample 2019-10-24 17:21:19 +02:00
7c567b04bb Make test compile and pass 2019-10-24 16:36:12 +02:00
1ac99e92a6 Light refactoring.
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-10-24 14:58:11 +01:00
5ab975cc5c General kotlinification.
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-10-24 14:53:44 +01:00
2cf63ea92a Remove import java.util.* from kotlin files.
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-10-24 14:53:10 +01:00
9e8d8ce878 Build and run test on CI 2019-10-24 15:52:40 +02:00
b766bce07d Version++ 2019-10-24 14:40:31 +02:00
01452efd8d Merge branch 'release/0.7.0' 2019-10-24 14:37:52 +02:00
0a0af221f0 Merge branch 'release/0.7.0' into develop 2019-10-24 14:37:51 +02:00
af08759af6 Prepare release 0.7.0 2019-10-24 14:37:28 +02:00
e52f0faaa7 Merge pull request #638 from vector-im/feature/filter
Fix 2 issues with share Activity: filter and room lists
2019-10-24 14:03:08 +02:00
8fa676d034 Share Activity: display rooms of all communities 2019-10-24 12:19:25 +02:00
b6594599c4 Rename member 2019-10-24 10:53:19 +02:00
8be8cc9ef7 Filter rooms when sharing element 2019-10-24 10:45:53 +02:00
9762d5be40 Room list actions: start creating all the components 2019-10-23 19:05:59 +02:00
b17b54d218 Merge pull request #637 from vector-im/feature/fix_room_summary
Feature/fix some room related stuff
2019-10-23 17:29:14 +02:00
187e2a26db Clean after Benoit's review 2019-10-23 17:26:56 +02:00
2f5fdbb7e2 Clean and fix lint 2019-10-23 16:20:38 +02:00
8b1411f533 Read marker: test if local echo before hitting the SDK to change read marker id + reduce a bit delay 2019-10-23 16:13:35 +02:00
bdee5e0687 Fix warning on Strings 2019-10-23 15:17:21 +02:00
ce4e244a3b Merge pull request #635 from vector-im/feature/strings
Import Strings from Riot
2019-10-23 15:09:58 +02:00
ff81715783 Import Strings from Riot 2019-10-23 14:18:40 +02:00
3196dcb57e MessageActions: disable if not synced atm 2019-10-23 12:20:03 +02:00
50bf6df7fe Room summary: fix some issues with local echo and sending event 2019-10-23 11:55:19 +02:00
02914495ce Merge pull request #632 from vector-im/feature/cleanuo
More cleanup
2019-10-23 10:26:54 +02:00
70a14f6350 Merge pull request #619 from vector-im/feature/attachments
Feature/attachments
2019-10-23 10:09:57 +02:00
cac5fb725a Code cleanup 2019-10-22 18:35:05 +02:00
dbc17ae515 Use AppCompatEditText instead of EditText 2019-10-22 18:23:53 +02:00
1de02c2fbb Ensure android.text.TextUtils will never be used again 2019-10-22 17:41:59 +02:00
6d55c15761 Fix lint issue 2019-10-22 17:41:21 +02:00
377a228f88 Improve code 2019-10-22 17:31:07 +02:00
2974f8b200 Merge branch 'develop' into feature/attachments 2019-10-22 17:27:15 +02:00
7388a408b8 Permissions: allow to provide the rationale message as it requires "context" and cannot be generic 2019-10-22 17:13:38 +02:00
f43dcb1183 Update room summary when saving local echo from DefaultRelationService 2019-10-22 16:54:48 +02:00
492ed3954a code cleanup 2019-10-22 16:54:48 +02:00
7890e83204 Merge pull request #630 from vector-im/feature/crypto_lock
Fix dead lock on crypto
2019-10-22 16:53:33 +02:00
00d1a2c380 Merge pull request #629 from vector-im/feature/fix_malformed_event_bug
Fix / event mapper persist the clear type in type
2019-10-22 14:47:08 +02:00
78dfd6b3e6 Fix potential lock due to nested synchronized(unknownSessionsFailure) 2019-10-22 14:20:43 +02:00
3abce34484 Add in existingRequest only if not filtered 2019-10-22 12:45:36 +02:00
4204ab262c Fix compilation issue 2019-10-22 12:42:01 +02:00
c7a4d34192 Attachments: handle rich content from keyboard 2019-10-22 12:37:59 +02:00
7416fec93e Do not decrypt event if session is unknown 2019-10-22 12:37:17 +02:00
3c40f64fb7 Add a few comments 2019-10-22 12:33:25 +02:00
b57c71b1c9 Remove unused import 2019-10-22 12:27:55 +02:00
fea54952d3 Code quality 2019-10-22 12:26:56 +02:00
3dc5ef54ab Fix compilation warnings 2019-10-22 12:21:50 +02:00
9092b97fb8 Merge pull request #622 from Dominaezzz/kotlinify
Some more clean up
2019-10-22 12:17:25 +02:00
cebd8136da Merge branch 'develop' into kotlinify 2019-10-22 12:16:20 +02:00
64b3568d51 Fix / event mapper persist the clear type in type 2019-10-22 11:57:11 +02:00
5e4e54153c Fix build error.
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-10-21 22:52:58 +01:00
d071324694 Address review comments.
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-10-21 22:29:36 +01:00
2c8cd89533 Handle rich content from app (WIP not compiling) 2019-10-21 19:02:28 +02:00
11b5c2c3ba Restore previous log level 2019-10-21 18:17:03 +02:00
9d7c4abb97 Merge pull request #615 from vector-im/feature/report_content
Add ability to report content
2019-10-21 18:13:44 +02:00
8e3234d188 Clean some code 2019-10-21 18:08:42 +02:00
b253722b98 Disable animation 2019-10-21 17:22:28 +02:00
fce576e3a4 Message action bottom sheet expanded 2019-10-21 17:22:28 +02:00
7ed7b18ccd Remove unused import 2019-10-21 17:22:28 +02:00
053bf7aeac Improve layout preview a bit 2019-10-21 17:22:28 +02:00
6ccd083451 Bottom sheet: fix RecyclerView usage 2019-10-21 17:22:28 +02:00
e39c4a7925 fix ktlint issue 2019-10-21 17:22:28 +02:00
abdb83b9fd Report content: change log 2019-10-21 17:22:28 +02:00
0bcc84cbd6 Try to fix the bottom sheet showing expanded by default #2
Seems ok now
2019-10-21 17:22:00 +02:00
b2f6fb8c91 Try to fix the bottom sheet showing expanded by default.
The second time it's open, it's not expanded... With this fix, the bug appear only at the third time...
2019-10-21 17:22:00 +02:00
36042ed145 Report content: red color for "block user" button 2019-10-21 17:22:00 +02:00
6ad1932fe5 Report content: custom reason 2019-10-21 17:22:00 +02:00
4a6237b50e Report content: confirmation dialogs 2019-10-21 17:22:00 +02:00
a7a19dab11 Report content: Service and REST request 2019-10-21 17:22:00 +02:00
8d0aa0437c Report content: UI menu 2019-10-21 17:21:26 +02:00
0a79b8b315 Cleanup 2019-10-21 17:21:26 +02:00
1dacfa6744 Rework message menu bottom sheet: remove sub Fragment and use Epoxy
- Also move some class to some dedicated package
2019-10-21 17:21:26 +02:00
723a007c39 Merge pull request #626 from vector-im/feature/myUserIdInject
Inject userId where possible
2019-10-21 16:01:48 +02:00
eaa1b04a4a Merge pull request #616 from vector-im/feature/big_font_regression
Fix regression after merge conflict: big font for messages with only big emoji
2019-10-18 15:03:43 +02:00
b1710fde60 Merge pull request #618 from vector-im/feature/mark_all_read
Mark all as read
2019-10-18 15:02:16 +02:00
cd0a40c18d Fix compil test issue 2019-10-18 14:34:44 +02:00
17636019e0 Change order of parameters 2019-10-18 14:32:34 +02:00
8078c39d6e Rename parameter 2019-10-18 14:29:32 +02:00
be94b2f90a Change order of parameters (no effect) 2019-10-18 14:28:12 +02:00
eff04be247 Change order of class (no effect) 2019-10-18 14:26:24 +02:00
3986839801 Inject userId 2019-10-18 14:25:19 +02:00
9e436483de Use klint 2019-10-16 10:39:42 +02:00
05a069be04 Attachments: fix themes for selection view 2019-10-16 10:04:33 +02:00
a1a71e2f1d App state: fix session 2019-10-16 10:04:11 +02:00
203da0f37e Mark all as read: not for all Room list and look if there is unread rooms 2019-10-16 10:03:30 +02:00
6cd04525aa Clean after Benoit's review 2019-10-15 11:37:22 +02:00
3c3c6aeac6 Removes the RoomList handling from a viewmodel as it doesn't have a ViewState and should be provided globally (IE, from application state) 2019-10-15 11:24:20 +02:00
e71311f576 Merge pull request #612 from vector-im/feature/browser_tab
Opening links from RiotX reuses browser tab (#599)
2019-10-15 11:05:06 +02:00
e4d0e0b0bf Update after Ganfra's review 2019-10-15 11:03:30 +02:00
28e5e42ab1 Merge pull request #614 from vector-im/feature/recycler_view_upgrade
Upgrade RecyclerView version to fix issues with a11y.
2019-10-15 10:47:59 +02:00
b860c3b0e3 Merge pull request #623 from Dominaezzz/typos
Fix some typos/errors in documentation.
2019-10-12 21:06:09 +02:00
f7f97e2098 Typos
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-10-12 16:04:47 +01:00
e28e2dadb9 Some more clean up
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-10-12 15:37:20 +01:00
c28be6adb0 Fix code quality check 2019-10-11 17:23:25 +02:00
c57af9cf3e Better formatting 2019-10-11 17:18:54 +02:00
679b0fff98 Use klint and update CHANGES 2019-10-11 17:12:53 +02:00
946fc36a26 Update contributing doc 2019-10-11 17:12:51 +02:00
13a5f784dc Merge branch 'develop' into feature/attachments 2019-10-11 17:05:03 +02:00
0ca8696e88 Attachments/Share: cleaning code and add contact picking 2019-10-11 16:41:04 +02:00
3622c0ecb4 Mark all as read 2019-10-11 16:22:32 +02:00
116d569fa8 Fix regression after merge conflict: big font for messages with only big emoji 2019-10-11 14:35:37 +02:00
ee5ebb4b83 Attachments: get better layout 2019-10-11 12:20:39 +02:00
0a0c344bfb Upgrade RecyclerView version to fix issues with a11y.
Also minor upgrade of some other libs
2019-10-11 10:10:16 +02:00
82fc97f619 Add dictionary specific to the project to VCS 2019-10-11 09:32:43 +02:00
20696353b8 Attachments: try to improve a bit the UI and adding options [WIP] 2019-10-10 19:12:16 +02:00
ae5b6bd2b9 Attachments/Sharing: refact a bit and handle more data. 2019-10-10 16:55:50 +02:00
1e11d4492b Merge pull request #610 from vector-im/feature/warnings
Fix all warnings and ensure they will not come back
2019-10-10 10:37:49 +02:00
6e39164b20 Sharing: start handling incoming share [WIP] 2019-10-09 20:05:37 +02:00
0a9ebb6bf6 Attachments: use a lib which handles for us all the intent stuff. 2019-10-09 19:51:00 +02:00
db009ce683 Fix warning on release build 2019-10-09 16:47:27 +02:00
55c80d3743 ktlint: ignore (experimental:annotation) rule 2019-10-09 16:44:45 +02:00
fbb23dfb66 ktlint: fix (no-empty-first-line-in-method-block) issues 2019-10-09 16:43:12 +02:00
e5779d425a ktlint: fix (experimental:multiline-if-else) issues 2019-10-09 16:40:44 +02:00
99d9704a50 ktlint: enable experimental features 2019-10-09 16:38:23 +02:00
3f8ddbe880 Opening links from RiotX reuses browser tab (#599) 2019-10-09 16:23:35 +02:00
30e43e47cd Fix filename ktlint issues 2019-10-09 15:44:01 +02:00
15dc4d6369 Fix ktlint issue automatically by running ./ktlint --android -v -F 2019-10-09 15:24:05 +02:00
dceb5ffd8d ktlint needs java 2019-10-09 15:19:07 +02:00
eec470f2ce Fix code quality issues 2019-10-09 15:15:15 +02:00
68db9c1cc0 Create a specific step for ktlint 2019-10-09 15:11:21 +02:00
cdfc402599 Fix Timber error in formatting 2019-10-09 15:06:38 +02:00
72d3f1e909 Configure ktlint 2019-10-09 15:06:38 +02:00
255fa11e89 Remove extra spaces 2019-10-09 12:49:00 +02:00
119e4c0d32 Fix warnings in the App 2019-10-09 12:49:00 +02:00
a9c474105a Fix warnings in the SDK 2019-10-09 12:49:00 +02:00
6de64cbedd Treat warnings from the kotlin compiler as errors 2019-10-09 12:49:00 +02:00
546c537e3b Upgrade build tools version from 3.5.0 to 3.5.1 2019-10-09 12:49:00 +02:00
36c5f9af13 Merge pull request #583 from vector-im/feature/invot_notification
Invitation notifications are not dismissed automatically if room is joined from another client (#347)
2019-10-09 12:48:07 +02:00
c2682c7f4b Merge pull request #609 from vector-im/feature/remove_event_bus
Stop sending bus event from SDK to App.
2019-10-09 12:47:06 +02:00
3073470c38 Attachments: start working on new UI (using system file picker) [WIP] 2019-10-08 19:59:09 +02:00
549f749682 Nest the try catch blocks 2019-10-08 14:00:11 +02:00
d4dfb76e80 Change constant value (for application upgrade reason) 2019-10-08 13:57:32 +02:00
e80191b2e0 Use mutableSet 2019-10-08 13:52:26 +02:00
c62c77f14c Stop sending bus event from SDK to App. 2019-10-08 12:00:40 +02:00
d6e5c5a857 Merge pull request #608 from vector-im/feature/a11y_review
Feature/a11y review
2019-10-08 11:16:08 +02:00
50a0660ab6 Invitation notifications are not dismissed automatically if room is joined from another client (#347) 2019-10-08 10:56:47 +02:00
ecdb3c3326 Merge pull request #591 from vector-im/feature/image_orientation
Fix issue with image orientation
2019-10-08 10:53:46 +02:00
2cd1d697fe Cleanup after Gafnra's review 2019-10-08 10:53:21 +02:00
3f9b7813bc Remove undocumented attribute and fix issue with image size when it contains exif rotation 2019-10-08 10:53:21 +02:00
f34f28b668 Add Exif orientation info to ContentAttachmentData 2019-10-08 10:52:54 +02:00
53572a3be6 Fix crash observed on the PlayStore 2019-10-08 10:52:54 +02:00
90b6199e10 Fix compilation issue 2019-10-08 10:45:45 +02:00
0aa299aa37 Private 2019-10-07 19:11:53 +02:00
d387c310c8 Cleanup code after a11y PR (#596) and fix some merging issues 2019-10-07 18:41:44 +02:00
8bd1fb08f7 Update template 2019-10-07 17:18:07 +02:00
ac6aff9175 Merge pull request #596 from pvagner/a11y
more a11y tweaks
2019-10-07 17:15:29 +02:00
adf0382d28 Merge pull request #603 from vector-im/feature/clear_corrupted_realm
Feature/clear corrupted realm
2019-10-07 16:35:23 +02:00
51554f7be0 Merge pull request #595 from vector-im/feature/lib_upgrade
Upgrade some dependencies
2019-10-07 16:22:30 +02:00
c1c1c3f999 Use latest coroutine lib: v1.3.2 2019-10-07 16:22:09 +02:00
8b04fdab77 Upgrade other libraries 2019-10-07 16:22:09 +02:00
f8b665a245 Fix warning 2019-10-07 16:21:18 +02:00
d68a9a5342 Split long line 2019-10-07 16:21:18 +02:00
5d2ff589f8 Upgrade gradle plugins 2019-10-07 16:21:18 +02:00
e85a0783fc Upgrade kotlin version 2019-10-07 16:21:18 +02:00
d6c278288d upgrade google play services plugin 2019-10-07 16:21:18 +02:00
4ad86a13a0 Upgrade the dependencies to the latest version 2019-10-07 16:21:18 +02:00
4f7ec91255 Merge pull request #604 from vector-im/feature/performance
Feature/performance
2019-10-07 16:08:39 +02:00
979b42aa30 Do not delete the crypto DB when deleting the session DB 2019-10-07 16:07:57 +02:00
fc49de080c Clean after benoit's review 2019-10-07 16:00:11 +02:00
d2b9668d4e Inject element where they are used 2019-10-07 15:25:54 +02:00
0632870be1 Merge pull request #605 from vector-im/feature/fixing_crashes
Feature/fixing crashes
2019-10-07 14:51:50 +02:00
8e39fd2a70 Clean after benoit's review 2019-10-07 14:45:58 +02:00
abbc62dd35 Clear corrupted db: add some logs 2019-10-04 19:42:27 +02:00
77de059dc9 Timeline: fix potential issues when starting/disposing the timeline 2019-10-04 19:37:44 +02:00
1931a1a4a4 Sync: use some suspending function where it makes sense 2019-10-04 19:37:23 +02:00
9c5987b682 SAS: fix potential crash 2019-10-04 19:36:22 +02:00
4e4fb4c565 Crypto store: fix potential issue with realm open/close process 2019-10-04 19:36:10 +02:00
0582d0f641 Timeline: fix some crashes 2019-10-04 12:12:39 +02:00
ef2af14529 Realm: remove RealmLiveData and use Optional for LiveData with potential null value 2019-10-03 19:19:53 +02:00
525da17678 Optimization: try to get a more performant reactions display management 2019-10-03 19:15:11 +02:00
aab41d7358 Code quality
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-03 16:34:31 +02:00
5db3c81aa9 Add contentDescription to the jump to botton view
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-02 20:51:57 +02:00
c763635845 Optimize: try to optimize a text message items 2019-10-02 20:36:52 +02:00
11d72b81f6 Add CHANGES.md entry 2019-10-02 20:04:33 +02:00
53543453b3 Login: add contentDescription to password reveal
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-02 20:04:33 +02:00
d4be68191c Fix conflicts after rebase
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-02 20:04:33 +02:00
7ef471ad0d Add contentDescription for the read receipts
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-02 20:04:33 +02:00
73dd735ba6 Reactions: Add content descriptions to emoji chooser category tabs and individual emojis
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-02 20:04:33 +02:00
2f6d3adb17 Message composer: describe the image button for dismissing as cancel rather than close
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-02 20:04:33 +02:00
2edfd4e830 Message composer: add content descriptions to image buttons
Signed-off-by: Peter Vágner <pvdeejay@gmail.com>
2019-10-02 20:04:33 +02:00
ff7856c535 Optimize: start removing some constraint layout from timeline 2019-10-02 19:30:01 +02:00
650a151b18 Optimize: remove some epoxy building from main thread 2019-10-01 20:12:15 +02:00
275dd20412 Optimize: don't build OkHttp in Application OnCreate if we don't need it 2019-10-01 20:12:01 +02:00
44f6391cb4 Optimize: use LazyThreeTen 2019-10-01 20:11:15 +02:00
588e5d6e63 Hot fix: fix home navigation issue 2019-10-01 17:39:20 +02:00
716999eec6 Merge pull request #592 from vector-im/feature/read_marker
Feature/read marker
2019-10-01 13:55:09 +02:00
42e0a45f3f Merge branch 'develop' into feature/read_marker 2019-10-01 13:37:21 +02:00
31397869b2 Read marker: refine JumpToReafMarkerView 2019-10-01 12:33:38 +02:00
e842bf13b2 Timeline: fix back pagination state 2019-10-01 12:32:48 +02:00
aea34da81e Merge pull request #593 from vector-im/feature/group_avatar
Group avatar live
2019-10-01 11:45:43 +02:00
0814f53fed Group avatar: clean and optimize a bit. 2019-10-01 11:25:41 +02:00
b5c6c1af0d Realm: allow to clear corrupted session db 2019-09-30 19:09:10 +02:00
de30e7c1c6 Code cleanup 2019-09-26 19:00:38 +02:00
2d95fe921d after login, the icon in the top left is a green 'A' for (all communities) rather than my avatar (#267) - part2 (Toolbar) 2019-09-26 18:42:27 +02:00
84542326f4 HomeDetailFragment observe the selectedGroupStore instead of passing argument 2019-09-26 18:06:24 +02:00
53b1b89c47 after login, the icon in the top left is a green 'A' for (all communities) rather than my avatar (#267) 2019-09-26 17:30:30 +02:00
28315be7b9 Update CHANGES 2019-09-26 17:05:18 +02:00
8605095668 Fix quality code issues 2019-09-26 16:49:41 +02:00
737959f616 Merge branch 'develop' into feature/read_marker 2019-09-26 15:15:34 +02:00
7817f49072 Merge pull request #590 from vector-im/feature/quickfix
Fix my dirty code
2019-09-26 14:50:38 +02:00
a060431aaf Fix my dirty code 2019-09-26 13:51:44 +02:00
a3f561d788 Merge branch 'develop' into feature/read_marker 2019-09-26 12:19:40 +02:00
0ea878af8a Timeline: fix some more issues 2019-09-26 11:55:16 +02:00
99de40c980 Merge pull request #589 from vector-im/feature/media_upload_failure
Fix media upload failure
2019-09-26 11:30:54 +02:00
810a97c639 Import string from Android-SDK (#355) 2019-09-26 11:14:13 +02:00
f02f16d9c5 Use IEC units instead of SI units for file sizes 2019-09-26 10:41:52 +02:00
62b7a83a31 Update after Dominaezzz's review 2019-09-26 10:08:44 +02:00
4a80df082c Timeline: refact [WIP] 2019-09-25 19:14:12 +02:00
60f6b3ef02 Auto review 2019-09-25 17:08:58 +02:00
a0b1ef3216 Do not upload file to big for the homeserver (#587)
Also create a HomeServerCapabilitiesService which provide configuration of the homeserver.
Data are retrieved every 8 hours (as RiotWeb?)
2019-09-25 16:59:50 +02:00
1b66d1f746 Fix bad rendering of file item if the filename is long 2019-09-25 15:25:26 +02:00
643a2baabf Set click and long click listener even if information data are not displayed 2019-09-25 15:03:16 +02:00
cd62e87266 Human readable error 2019-09-25 14:44:34 +02:00
17cba1a432 Display progress in the timeline when uploading file 2019-09-25 14:39:33 +02:00
f077cc8467 Stop sending media in an infinite loop in case of error (part of #587)
Not sure how this commit fix it, but the issue is not observed anymore with it
2019-09-25 14:09:26 +02:00
f3039601bf throw Failure instead of meaning less IOException 2019-09-25 11:27:23 +02:00
4c04014e4d Do not log big data request (ex: file upload) 2019-09-25 11:26:49 +02:00
ae8bceacba Create Extension to convert a Response to a Failure -> expose to other object 2019-09-25 11:26:13 +02:00
9b91b6ea87 Create Extension to convert a Response to a Failure 2019-09-25 10:56:18 +02:00
b24a372262 Show "Clear message queue" option (in debug mode) 2019-09-25 10:50:13 +02:00
63b43de4b8 Read marker: final refact [WIP] 2019-09-24 22:52:43 +02:00
d1a61f29e4 Merge pull request #586 from vector-im/feature/persist_tab
Persist opened tab between session (i.e. after application restart)
2019-09-24 16:12:28 +02:00
f6373221de Dagger cleanup 2019-09-24 16:05:08 +02:00
ec0974f72c Merge branch 'hotfix/dimensionConverter' 2019-09-24 14:28:51 +02:00
b5f2f01c8d Merge branch 'hotfix/dimensionConverter' into develop 2019-09-24 14:28:51 +02:00
21d808c1ce Fix crash: MergedHeaderItem was missing dimensionConverter 2019-09-24 14:28:34 +02:00
1e963bc0dc Fix crash: MergedHeaderItem was missing dimensionConverter 2019-09-24 14:23:13 +02:00
0d80750507 Create interface for UiStateRepository and an implementation with SharedPrefs 2019-09-24 13:43:50 +02:00
1c9cf7a810 Dagger code cleanup 2019-09-24 13:40:03 +02:00
c6d01fbcf4 ReadMarker: extract from ViewModel the jump to read marker visibility logic as it's easier to deal with. 2019-09-24 12:57:32 +02:00
9e1ded941f Persist active tab between sessions (#503) 2019-09-24 12:29:37 +02:00
af433266c8 Move currentDisplayMode to the ViewState 2019-09-24 11:32:55 +02:00
05d09bf950 Merge branch 'develop' into feature/read_marker 2019-09-24 11:10:59 +02:00
6890f83810 Cleanup dead code 2019-09-24 10:47:29 +02:00
51568c30a6 Version++ 2019-09-24 10:23:51 +02:00
cc832633a5 Merge branch 'release/0.6.0' 2019-09-24 10:22:42 +02:00
e019ec6596 Merge branch 'release/0.6.0' into develop 2019-09-24 10:22:42 +02:00
eadea9016b Prepare release 0.6.0 2019-09-24 10:22:36 +02:00
6422d946c9 Merge pull request #584 from vector-im/feature/hasUnread
isEventRead() returns true if the event has been sent by the user
2019-09-24 10:17:52 +02:00
5cc3dc00e3 Merge pull request #581 from vector-im/feature/talk_back
Fix a few accessibility issues
2019-09-24 10:06:28 +02:00
5a2a9f908a isEventRead() returns true if the event has been sent by the user 2019-09-24 10:04:57 +02:00
c1f2e9f171 Fix a few accessibility issues - home menu (best compromise) 2019-09-23 17:48:13 +02:00
f6d34ec7fd Timeline: update state management 2019-09-23 17:43:37 +02:00
620ba279d8 Fix a few accessibility issues 2019-09-23 16:32:54 +02:00
3fcfa33364 Merge pull request #573 from vector-im/feature/notif_invit
Clean up push rules management and fixes several issues
2019-09-23 16:23:35 +02:00
546da0f173 Merge branch 'develop' into feature/notif_invit 2019-09-23 16:23:22 +02:00
001711d5a3 Merge pull request #574 from vector-im/feature/big_emoji
Embiggen messages with multiple emojis also for edited messages
2019-09-23 16:22:53 +02:00
8e1a964679 After Ganfra's review 2019-09-23 15:08:18 +02:00
b25a130db1 Rename DimensionUtils to DimensionConverter, and inject resources instead of context. 2019-09-23 14:39:52 +02:00
8a9e6497e8 Merge pull request #578 from vector-im/feature/fix_focus_login
Fix infinite focus on HS field
2019-09-23 10:05:43 +02:00
47e3797b7e Fix infinite focus on HS field 2019-09-23 09:44:32 +02:00
5cbc90e06a Embiggen messages with multiple emojis also for edited messages (#458)
And daggerize DimensionUtils
2019-09-20 19:22:42 +02:00
b6e18e4a8f Timeline: add badge also when unread without notif 2019-09-20 18:34:58 +02:00
7e29665fd0 Timeline: add some comments and checks 2019-09-20 18:34:31 +02:00
e04bf31faa Fix wrong "no network" banner 2019-09-20 18:18:55 +02:00
d25cf79b07 Cleanup 2019-09-20 17:50:57 +02:00
faa8e6bbb2 m.notice messages trigger push notifications (#238) 2019-09-20 17:50:57 +02:00
d3d4deb884 Rework Action (better kotlin code) 2019-09-20 17:50:57 +02:00
f6b8e0c479 Fix issue: push rules was not retrieved after a clear cache.
We now store push rules from the sync response
2019-09-20 17:50:57 +02:00
2a726f54a2 Remove userId from PushRulesEntity and PusherEntity objects 2019-09-20 17:50:15 +02:00
1197d4021d Fix regression on PushRulesApi 2019-09-20 17:50:15 +02:00
03f8120b7d Create enum for Push rules. Also add some TODOs 2019-09-20 17:50:15 +02:00
acd7a709de Dagger: create @UserId to inject userId 2019-09-20 17:50:15 +02:00
5651ea515b Merge pull request #570 from vector-im/feature/left_group
Handle left group from sync
2019-09-20 17:44:13 +02:00
9794b3a49d Fix compilation issue of F-Droid build 2019-09-20 17:35:10 +02:00
b3e1c3969d Little changes after review 2019-09-20 17:34:50 +02:00
90eeb68d36 Timeline: fix permalink towards an hidden event 2019-09-20 17:22:04 +02:00
d1ff3314a7 Timeline : add badge on jump to bottom view 2019-09-19 19:12:45 +02:00
f24bed17a2 Add missing issue number 2019-09-19 17:56:34 +02:00
a993a30203 Handle left group from sync 2019-09-19 17:08:22 +02:00
ea0809ff87 Merge branch 'develop' into feature/read_marker 2019-09-19 16:57:00 +02:00
9668487b6b Timeline/Read: update read receipt locally to 2019-09-19 16:17:58 +02:00
91cc78d2ad Merge pull request #552 from vector-im/feature/draft
Save draft of a message when exiting a room with non empty composer (#329)
2019-09-19 13:11:35 +02:00
562acc9702 Save Draft only when app goes to background. 2019-09-19 13:09:08 +02:00
dfab88ed95 Display room with draft in the Catchup screen 2019-09-19 13:09:08 +02:00
36866dd24e Save draft of a message when exiting a room with non empty composer (#329) 2019-09-19 13:09:08 +02:00
c728834273 Merge pull request #566 from vector-im/feature/redact_notification
Redact notification
2019-09-19 13:02:17 +02:00
f5020d0f63 Daggerization and cleanup of NotificationUtils 2019-09-19 13:01:00 +02:00
7da9cafcc2 Remove any notification of a redacted event (#563)
Also do some cleanup and kotlinification on the code
2019-09-19 13:01:00 +02:00
6f09eea248 Merge pull request #562 from vector-im/feature/notification_edited
Message Editing: Update notifications (#128)
2019-09-19 12:59:10 +02:00
468bd5bcc9 Message Editing: Update notifications (#128) 2019-09-19 12:57:58 +02:00
3169093c50 Quick fix on the no connection banner displayed when internet is available 2019-09-19 12:55:39 +02:00
d60d766354 Merge pull request #524 from vector-im/feature/indicate_unread_rooms
Add unread indent on room list
2019-09-19 12:50:55 +02:00
0ffb5e627e Cleanup injected constructors 2019-09-19 12:43:39 +02:00
b4a13f9504 Add unread indent on room list 2019-09-19 12:43:39 +02:00
88fb9667a3 Timeline: continue fixing issues + read marker 2019-09-18 20:21:42 +02:00
ffa8b7e73a Better fix 2019-09-18 11:24:29 +02:00
528958b3de Avoid export on env variable 2019-09-18 10:58:03 +02:00
3ffe2f7d40 Fix (again) issue with bad versionCode generated by Buildkite (#553) 2019-09-18 10:29:29 +02:00
3066d5f303 Timeline\ReadMarker: continue fixing issues 2019-09-17 19:38:05 +02:00
bf42b73713 Merge pull request #555 from vector-im/feature/room_search
Cleanup on the room search screen
2019-09-17 15:28:54 +02:00
ed93f4a6c1 Cancel any request properly 2019-09-17 14:55:57 +02:00
b3d649a4d9 Fix characters erased from the Search field when the result are coming (#545) 2019-09-17 14:55:57 +02:00
3739e50d46 Better error message for timeout 2019-09-17 14:55:48 +02:00
9bf484cf1e Create a Failure to handle cancellation, and use it to ignore cancellation on room search 2019-09-17 14:55:48 +02:00
6c2faff1f0 Version++ (0.6.0) 2019-09-17 14:53:50 +02:00
07fca0922b Merge branch 'release/0.5.0' 2019-09-17 14:50:55 +02:00
282de21708 Merge branch 'release/0.5.0' into develop 2019-09-17 14:50:55 +02:00
ba9d119892 Prepare release 0.5.0 2019-09-17 14:50:43 +02:00
4453f0ced9 Merge pull request #560 from vector-im/feature/no_network
Display a "No network" banner when the device has no network
2019-09-17 14:40:42 +02:00
77168bfd6a Merge pull request #558 from vector-im/feature/login_sso
Quick implementation of SSO login - Also handling of magic link
2019-09-17 14:28:04 +02:00
25e9a179d2 SyncThread: Fix issue when network is back and the app was in background: do not restart the thread 2019-09-17 14:26:30 +02:00
73ec0f5a83 NetworkConnectivityChecker: filter onConnected callbacks (several callback if Wifi and LTE is connected)
Also do not use merlinsBeard.isConnected, which return trus even if there is no internet access (ex: with Wifi hotspot)
2019-09-17 14:22:08 +02:00
993fa74252 Cleanup after BillCarsonFr's review 2019-09-17 11:24:37 +02:00
38fc4984fe Display a no network indicator when there is no network: Create a dedicated View 2019-09-17 11:13:00 +02:00
695d8cce00 Display a no network indicator when there is no network (#559) 2019-09-17 10:59:58 +02:00
07e99901e1 SecretStoringUtils -> move to internal package 2019-09-17 10:38:37 +02:00
20f53e9a58 Signout: propose the user to retry in case of error 2019-09-17 10:33:27 +02:00
ced72aff4f Revert change done to save alias for the client 2019-09-17 10:32:09 +02:00
fdaaca49c2 Code quality (bad import) 2019-09-16 19:27:13 +02:00
3485f023b0 All current notifications were dismissed by mistake when the app is launched from the launcher 2019-09-16 19:24:52 +02:00
384dd100e9 Daggerization and Kotlinification of SecretStoringUtils 2019-09-16 19:19:14 +02:00
1ba8a58219 Cleanup SecretStoringUtils, and delete keys when user signs out 2019-09-16 18:29:06 +02:00
69fb7bdf95 Timeline\Read marker: continue fixing potential issues 2019-09-16 18:14:41 +02:00
c8010561fc Rework on sign out task 2019-09-16 17:45:26 +02:00
1f127335bc Daggerization of RealmKeysUtils 2019-09-16 15:50:56 +02:00
138a210a73 Dagger: Screen component now exposes ActiveSessionHolder instead of Session 2019-09-16 14:43:39 +02:00
ca6bcde82d Re add the remove CurlLoggingInterceptor 2019-09-16 14:43:08 +02:00
6bda437f5d Auto configure homeserver and identity server URLs of LoginActivity with a magic link 2019-09-16 10:58:51 +02:00
5d6d0202a9 Timeline: try to fix some issues with permalink [WIP] 2019-09-14 14:11:41 +02:00
3e6b65e174 Handle M_CONSENT_NOT_GIVEN error (#64) 2019-09-13 18:21:56 +02:00
137dcab734 Curl login interceptor now log the AT (on debug mode) 2019-09-13 16:20:19 +02:00
b22b8fba02 Fix the mess up with OnBackPress support on Fragment 2019-09-13 15:55:33 +02:00
3ccdf4a244 Login: some cleanup 2019-09-13 15:35:44 +02:00
5fbd271b1c Login: add SSO support 2019-09-13 15:19:45 +02:00
db8ea0f5e8 Login: check login flow - step 1 2019-09-13 11:08:54 +02:00
a47a3ead1f Login: move login code to the ViewModel 2019-09-13 10:39:22 +02:00
05b2092ffc Login: move existing code to a Fragment, MvRx style 2019-09-13 10:07:55 +02:00
f4ab770be9 Merge branch 'develop' into feature/read_marker 2019-09-12 17:24:50 +02:00
6249a59203 Merge pull request #554 from vector-im/feature/build_number
Fix issue with bad versionCode generated by Buildkite (#553)
2019-09-12 17:24:46 +02:00
d4111d053d Read marker: only show banner until scrolled to read marker 2019-09-12 16:35:45 +02:00
618e9a4f52 Fix issue with bad versionCode generated by Buildkite (#553) 2019-09-12 16:17:44 +02:00
b8ebe3570b Timeline: refact epoxy attributes 2019-09-11 18:04:17 +02:00
f2c8d4ad02 Merge pull request #549 from vector-im/feature/third_party_invite
Fix rendering issue of accepted third party invitation event
2019-09-06 16:36:30 +02:00
be524472ec Merge pull request #546 from vector-im/feature/cleanup
Cleanup
2019-09-06 16:25:08 +02:00
1b82a1a24d Cleanup 2019-09-06 15:52:29 +02:00
cf0b331c3b Handle invite to the current user rendering 2019-09-06 15:48:42 +02:00
2a92a3dc80 Fix rendering issue of accepted third party invitation event 2019-09-06 14:34:52 +02:00
012840abba Progress in initial sync dialog is decreasing for a step and should not (#532) 2019-09-05 18:14:05 +02:00
a5975a099e Cleanup and document DefaultInitialSyncProgressService 2019-09-05 17:23:09 +02:00
38da4b9ee5 Cleanup and document DefaultInitialSyncProgressService 2019-09-05 17:02:03 +02:00
242e60fcaa Rename CryptoManager to DefaultCryptoService 2019-09-05 16:14:34 +02:00
a23be05cbf Better type 2019-09-05 16:04:41 +02:00
ed39b02924 Avoid using keyword for variable names 2019-09-05 16:04:41 +02:00
fe931b5361 Merge pull request #418 from Dominaezzz/kotlinify-1
Some more kotlinification
2019-09-05 16:02:30 +02:00
90d9cd0587 Merge pull request #416 from Dominaezzz/kt-remove_java_util
Remove most usages of the java.util package
2019-09-05 15:33:03 +02:00
9cedb18921 Merge pull request #538 from vector-im/feature/log_mgmt
Reduce release build log level
2019-09-05 15:24:04 +02:00
e89ba7b87b Update wording 2019-09-05 15:23:38 +02:00
902657c22a Merge pull request #537 from vector-im/feature/fix_crash
Fix crash due to missing informationData (#535)
2019-09-02 15:31:28 +02:00
eec2abf164 Reduce release build log level 2019-09-02 14:33:53 +02:00
6879cc8ca8 Fix crash due to missing informationData (#535) 2019-09-02 14:24:36 +02:00
fd6bbbd3b5 Fix issue with version name (Fixes #533) 2019-08-30 15:57:39 +02:00
0ff0b014a9 Version++ (0.5.0) 2019-08-30 15:07:04 +02:00
a89f0ddd1d Merge branch 'release/0.4.0' 2019-08-30 15:04:43 +02:00
fdc9e84dd5 Merge branch 'release/0.4.0' into develop 2019-08-30 15:04:43 +02:00
58f878fca9 Prepare version 0.4.0 2019-08-30 15:04:28 +02:00
88095e4bd9 Add entry in change file 2019-08-30 14:54:15 +02:00
47d22a3d5e Import translation from Riot and MatrixSDK 2019-08-30 11:21:43 +02:00
28e82cb8ea Merge pull request #531 from vector-im/feature/fix_crash_530
Fix / EmojiCompat not initialized
2019-08-29 17:46:51 +02:00
35817245cb refactoring, code review 2019-08-29 17:27:49 +02:00
75266f42bb Fix / EmojiCompat not initialized 2019-08-29 16:49:22 +02:00
95c4c9ce56 Merge pull request #527 from vector-im/feature/privacy
Privacy: remove log of notifiable event (#519)
2019-08-29 12:16:34 +02:00
ce5570105d Privacy: remove log of notifiable event (#519) 2019-08-29 10:36:45 +02:00
188a9aebfa Merge pull request #525 from vector-im/feature/read_receipt_cleanup
Feature/read receipt cleanup
2019-08-29 10:19:06 +02:00
c95223f5d2 Add long click support on unsupported event 2019-08-28 18:17:37 +02:00
ef0362ba9c Display Read Receipt on unsupported events 2019-08-28 17:31:31 +02:00
ea242f6737 Hide ReadReceipt View when it is not relevant 2019-08-28 17:17:37 +02:00
cbc08d834b Merge pull request #522 from vector-im/feature/fix_e2e_reply
Fix / regression on e2e reply and edit of reply
2019-08-28 10:38:22 +02:00
0ab6b33fb6 Merge branch 'develop' into feature/fix_e2e_reply 2019-08-28 10:38:12 +02:00
1b394527b6 cleaning + code review 2019-08-28 10:22:51 +02:00
a8f1388721 Merge pull request #520 from vector-im/feature/read_receipts_511
Improve read receipt design
2019-08-28 10:17:56 +02:00
166be4e289 Improve read receipt design 2019-08-28 09:56:10 +02:00
b49ccefe63 Merge pull request #521 from vector-im/feature/fix_dome_video_wont_play
Some video won't play
2019-08-28 03:43:35 -04:00
825760d17e Fix / regression on e2e reply and edit of reply 2019-08-27 17:05:04 +02:00
b5af62c3ea Some video won't play
VideoView fails to play some remote uri video on some device. For now video is downloaded locally in internal cache then played. This offers basic support before full media preview implementation
2019-08-27 16:50:02 +02:00
a51d96bf00 Merge pull request #325 from vector-im/feature/non_unicode_reaction
Accept non unicode reactions
2019-08-27 08:10:51 -04:00
7e142d201d Use EmojiCompat to build EmojiSpans from text 2019-08-27 11:06:52 +02:00
2be6058971 accept non unicode reactions 2019-08-27 10:58:21 +02:00
49d73f360e Merge pull request #494 from vector-im/feature/fix_441
Fix text diff removed linebreak
2019-08-27 04:36:03 -04:00
51a4c93676 Read markers: continue working on ui 2019-08-23 16:54:32 +02:00
d8f449388c Read marker: start working on it (no UI) 2019-08-20 18:30:24 +02:00
9cd69d1e33 Merge branch 'release/0.3.0' 2019-08-08 16:45:03 +02:00
456908c851 Merge branch 'develop' into kt-remove_java_util 2019-08-06 18:27:39 +01:00
215324a03e Some kotlinification
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-08-06 11:36:39 +01:00
02e342849f Remove most usages of the java.util package
Signed-off-by: Dominic Fischer <dominicfischer7@gmail.com>
2019-07-21 23:23:56 +01:00
df6080b1da Merge branch 'release/0.2.0' 2019-07-18 17:47:39 +02:00
2167 changed files with 91504 additions and 24833 deletions

View File

@ -1,53 +0,0 @@
# Use Docker file from https://hub.docker.com/r/runmymind/docker-android-sdk
# Last docker plugin version can be found here:
# https://github.com/buildkite-plugins/docker-buildkite-plugin/releases
# Build debug version of the RiotX application, from the develop branch and the features branches
steps:
- label: "Assemble GPlay Debug version"
agents:
# We use a medium sized instance instead of the normal small ones because
# gradle build is long
queue: "medium"
commands:
- "./gradlew clean lintGplayRelease assembleGplayDebug --stacktrace"
artifact_paths:
- "vector/build/outputs/apk/gplay/debug/*.apk"
branches: "!master"
plugins:
- docker#v3.1.0:
image: "runmymind/docker-android-sdk"
- label: "Assemble FDroid Debug version"
agents:
# We use a medium sized instance instead of the normal small ones because
# gradle build is long
queue: "medium"
commands:
- "./gradlew clean lintFdroidRelease assembleFdroidDebug --stacktrace"
artifact_paths:
- "vector/build/outputs/apk/fdroid/debug/*.apk"
branches: "!master"
plugins:
- docker#v3.1.0:
image: "runmymind/docker-android-sdk"
- label: "Build Google Play unsigned APK"
agents:
# We use a medium sized instance instead of the normal small ones because
# gradle build is long
queue: "medium"
commands:
- "./gradlew clean assembleGplayRelease --stacktrace"
artifact_paths:
- "vector/build/outputs/apk/gplay/release/*.apk"
branches: "master"
plugins:
- docker#v3.1.0:
image: "runmymind/docker-android-sdk"
# Code quality
- label: "Code quality"
command: "./tools/check/check_code_quality.sh"

33
.editorconfig Normal file
View File

@ -0,0 +1,33 @@
# For ktlint configuration. Ref: https://ktlint.github.io/
[*.{kt,kts}]
# possible values: number (e.g. 2), "unset" (makes ktlint ignore indentation completely)
indent_size=unset
# true (recommended) / false
insert_final_newline=true
# possible values: number (e.g. 120) (package name, imports & comments are ignored), "off"
# it's automatically set to 100 on `ktlint --android ...` (per Android Kotlin Style Guide)
max_line_length=off
# Comma-separated list of rules to disable (Since 0.34.0)
# Note that rules in any ruleset other than the standard ruleset will need to be prefixed
# by the ruleset identifier.
disabled_rules=no-multi-spaces,colon-spacing,chain-wrapping,import-ordering,experimental:annotation
# The following (so far identified) rules are kept:
# no-blank-line-before-rbrace
# final-newline
# no-consecutive-blank-lines
# comment-spacing
# filename
# comma-spacing
# paren-spacing
# op-spacing
# string-template
# no-unused-imports
# curly-spacing
# no-semi
# no-empty-class-body
# experimental:multiline-if-else
# experimental:no-empty-first-line-in-method-block
# no-wildcard-imports

View File

@ -7,4 +7,4 @@
- [ ] Pull request is based on the develop branch
- [ ] Pull request updates [CHANGES.md](https://github.com/vector-im/riotX-android/blob/develop/CHANGES.md)
- [ ] Pull request includes screenshots or videos if containing UI changes
- [ ] Pull request includes a [sign off](https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst#sign-off)
- [ ] Pull request includes a [sign off](https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md#sign-off)

12
.gitignore vendored
View File

@ -1,14 +1,16 @@
*.iml
.gradle
/local.properties
.idea/*
/.idea/*
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
# idea files: exclude everything except dictionnaries
.idea/caches
.idea/libraries
.idea/inspectionProfiles
.idea/*.xml
.DS_Store
/build
/captures
.externalNativeBuild
/tmp
ktlint

156
.idea/codeStyles/Project.xml generated Normal file
View File

@ -0,0 +1,156 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="RIGHT_MARGIN" value="160" />
<JetCodeStyleSettings>
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
<value>
<package name="kotlinx.android.synthetic" withSubpackages="true" static="false" />
</value>
</option>
<option name="ALIGN_IN_COLUMNS_CASE_BRANCH" value="true" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT" value="2147483647" />
<option name="NAME_COUNT_TO_USE_STAR_IMPORT_FOR_MEMBERS" value="2147483647" />
<option name="CONTINUATION_INDENT_IN_PARAMETER_LISTS" value="true" />
<option name="CONTINUATION_INDENT_IN_ARGUMENT_LISTS" value="true" />
<option name="CONTINUATION_INDENT_FOR_EXPRESSION_BODIES" value="true" />
<option name="CONTINUATION_INDENT_FOR_CHAINED_CALLS" value="true" />
<option name="CONTINUATION_INDENT_IN_SUPERTYPE_LISTS" value="true" />
<option name="CONTINUATION_INDENT_IN_IF_CONDITIONS" value="true" />
<option name="CONTINUATION_INDENT_IN_ELVIS" value="true" />
<option name="WRAP_EXPRESSION_BODY_FUNCTIONS" value="0" />
<option name="IF_RPAREN_ON_NEW_LINE" value="false" />
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="XML">
<option name="RIGHT_MARGIN" value="160" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
<option name="RIGHT_MARGIN" value="160" />
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="1" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="0" />
<option name="CALL_PARAMETERS_WRAP" value="0" />
<option name="CALL_PARAMETERS_LPAREN_ON_NEXT_LINE" value="false" />
<option name="CALL_PARAMETERS_RPAREN_ON_NEXT_LINE" value="false" />
<option name="METHOD_PARAMETERS_WRAP" value="0" />
<option name="METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE" value="false" />
<option name="METHOD_PARAMETERS_RPAREN_ON_NEXT_LINE" value="false" />
<option name="EXTENDS_LIST_WRAP" value="0" />
<option name="METHOD_CALL_CHAIN_WRAP" value="0" />
<option name="ASSIGNMENT_WRAP" value="0" />
<option name="CLASS_ANNOTATION_WRAP" value="0" />
<option name="FIELD_ANNOTATION_WRAP" value="1" />
</codeStyleSettings>
</code_scheme>
</component>

6
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@ -0,0 +1,6 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

6
.idea/copyright/NewVector.xml generated Normal file
View File

@ -0,0 +1,6 @@
<component name="CopyrightManager">
<copyright>
<option name="notice" value="Copyright (c) &amp;#36;today.year New Vector Ltd&#10;&#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10; http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License." />
<option name="myName" value="NewVector" />
</copyright>
</component>

8
.idea/copyright/profiles_settings.xml generated Normal file
View File

@ -0,0 +1,8 @@
<component name="CopyrightManager">
<settings default="NewVector">
<LanguageOptions name="XML">
<option name="fileTypeOverride" value="1" />
<option name="prefixLines" value="false" />
</LanguageOptions>
</settings>
</component>

30
.idea/dictionaries/bmarty.xml generated Normal file
View File

@ -0,0 +1,30 @@
<component name="ProjectDictionaryState">
<dictionary name="bmarty">
<words>
<w>backstack</w>
<w>bytearray</w>
<w>checkables</w>
<w>ciphertext</w>
<w>coroutine</w>
<w>decryptor</w>
<w>emoji</w>
<w>emojis</w>
<w>fdroid</w>
<w>gplay</w>
<w>hmac</w>
<w>ktlint</w>
<w>linkified</w>
<w>linkify</w>
<w>megolm</w>
<w>msisdn</w>
<w>pbkdf</w>
<w>pkcs</w>
<w>riotx</w>
<w>signin</w>
<w>signout</w>
<w>signup</w>
<w>ssss</w>
<w>threepid</w>
</words>
</dictionary>
</component>

View File

@ -49,12 +49,12 @@ script:
# Build Android test (assembleAndroidTest) (disabled for now)
# Code quality (lintGplayRelease lintFdroidRelease)
# Split into two steps because if a task contain Fdroid, PlayService will be disabled
- ./gradlew clean assembleGplayRelease lintGplayRelease --stacktrace
- ./gradlew clean assembleFdroidRelease lintFdroidRelease --stacktrace
# Done by Buildkite now: - ./gradlew clean assembleGplayRelease lintGplayRelease --stacktrace
# Done by Buildkite now: - ./gradlew clean assembleFdroidRelease lintFdroidRelease --stacktrace
# Run unitary test (Disable for now, see https://travis-ci.org/vector-im/riot-android/builds/502504370)
# - ./gradlew testGplayReleaseUnitTest --stacktrace
# Other code quality check
- ./tools/check/check_code_quality.sh
# Done by Buildkite now: - ./tools/check/check_code_quality.sh
- ./tools/travis/check_pr.sh
# Check that indonesians file are identical. Due to Android issue, the resource folder must be value-in/, and Weblate export data into value-id/.
- diff ./vector/src/main/res/values-id/strings.xml ./vector/src/main/res/values-in/strings.xml
# Done by Buildkite now: - diff ./vector/src/main/res/values-id/strings.xml ./vector/src/main/res/values-in/strings.xml

View File

@ -0,0 +1,35 @@
A full developer contributors list can be found [here](https://github.com/vector-im/riotX-android/graphs/contributors).
# Core team:
Even if we try to be able to work on all the functionalities, we have more knowledge about what we have developed ourselves.
## Benoit: Android team leader
[@benoit.marty:matrix.org](https://matrix.to/#/@benoit.marty:matrix.org)
- Android team leader and project leader, Android developer, GitHub community manager.
- Specialist of the account creation, and many other fun features.
- Reviewing and polishing developed features, code quality manager, PRs reviewer, GitHub community manager.
- Release manager on the Play Store
## François: Software architect
[@ganfra:matrix.org](https://matrix.to/#/@ganfra:matrix.org)
- Software architect, Android developer
- First developer on the project.
- Work mainly on the global architecture of the project.
- Specialist of the timeline, and lots of other features.
## Valere: Product manager, Android developer
[@valere35:matrix.org](https://matrix.to/#/@valere35:matrix.org)
- Product manager, Android developer
- Specialist on the crypto implementation.
# Other contributors
First of all, we thank all contributors who use RiotX and report problems on this GitHub project or via the integrated rageshake function.
We do not forget all translators, for their work of translating RiotX into many languages. They are also the authors of RiotX.
Feel free to add your name below, when you contribute to the project!

View File

@ -1,25 +1,369 @@
Changes in RiotX 0.4.0 (2019-XX-XX)
Changes in RiotX 0.18.0 (2020-03-11)
===================================================
Improvements 🙌:
- Share image and other media from e2e rooms (#677)
- Add support for `/plain` command (#12)
- Detect spaces in password if user fail to login (#1038)
- FTUE: do not display a different color when encrypting message when not in developer mode.
- Open room member profile from avatar of the room member state event (#935)
- Restore the push rules configuration in the settings
Bugfix 🐛:
- Fix crash on attachment preview screen (#1088)
- "Share" option is not appearing in encrypted rooms for images (#1031)
- Set "image/jpeg" as MIME type of images instead of "image/jpg" (#1075)
- Self verification via QR code is failing (#1130)
SDK API changes ⚠️:
- PushRuleService.getPushRules() now returns a RuleSet. Use getAllRules() on this object to get all the rules.
Build 🧱:
- Upgrade ktlint to version 0.36.0
- Pipeline file for Buildkite is now hosted on another Github repository: https://github.com/matrix-org/pipelines/blob/master/riotx-android/pipeline.yml
Other changes:
- Restore availability to Chromebooks (#932)
- Add a [documentation](./docs/integration_tests.md) to run integration tests
Changes in RiotX 0.17.0 (2020-02-27)
===================================================
Features ✨:
- Secured Shared Storage Support (#984, #936)
- It's now possible to select several rooms (with a possible mix of clear/encrypted rooms) when sharing elements to RiotX (#1010)
- Media preview: media are previewed before being sent to a room (#1010)
- Image edition: it's now possible to edit image before sending: crop, rotate, and delete actions are supported (#1010)
- Sending image: image are sent to rooms with a reduced size. It's still possible to send original image file (#1010)
Improvements 🙌:
- Migrate to binary QR code verification (#994)
- Share action is added to room profile and room member profile (#858)
- Display avatar in fullscreen (#861)
- Fix some performance issues with crypto
Bugfix 🐛:
- Account creation: wrongly hints that an email can be used to create an account (#941)
- Fix crash in the room directory, when public room has no name (#1023)
- Fix restoring keys backup with passphrase (#526)
- Fix rotation of full-size image (#647)
- Fix joining rooms from directory via federation isn't working. (#808)
- Leaving a room creates a stuck "leaving room" loading screen. (#1041)
- Fix some invitation handling issues (#1013)
- New direct chat: selecting a participant sometimes results in two breadcrumbs (#1022)
- New direct chat: selecting several participants was not adding the room to the direct chats list
- Room overview shows deleted messages as “Encrypted message” (#758)
SDK API changes ⚠️:
- Get crypto methods through Session.cryptoService()
- ProgressListener.onProgress() function will be invoked on the background thread instead of UI thread
- Improve CreateRoomParams API (#1070)
Changes in RiotX 0.16.0 (2020-02-14)
===================================================
Features ✨:
- Polls and Bot Buttons (MSC 2192 matrix-org/matrix-doc#2192)
Improvements 🙌:
- Show confirmation dialog before deleting a message (#967, #1003)
- Open room member profile from reactions list and read receipts list (#875)
Bugfix 🐛:
- Fix crash by removing all notifications after clearing cache (#878)
- Fix issue with verification when other client declares it can only show QR code (#988)
- Fix too errors in the code (1941862499c9ec5268cc80882512ced379cafcfd, a250a895fe0a4acf08c671e03434edcd29ccd84f)
SDK API changes ⚠️:
- Javadoc improved for PushersService
- PushersService.pushers() has been renamed to PushersService.getPushers()
Changes in RiotX 0.15.0 (2020-02-10)
===================================================
Improvements 🙌:
- Improve navigation to the timeline (#789, #862)
- Improve network detection. It is now based on the sync request status (#873, #882)
Other changes:
- Support SSO login with Firefox account (#606)
Bugfix 🐛:
- Ask for permission before opening the camera (#934)
- Encrypt for invited users by default, if the room state allows it (#803)
Changes in RiotX 0.14.3 (2020-02-03)
===================================================
Bugfix 🐛:
- Fix Exception in DeviceListManager
Changes in RiotX 0.14.2 (2020-02-02)
===================================================
Bugfix 🐛:
- Fix RiotX not starting issue
Changes in RiotX 0.14.1 (2020-02-02)
===================================================
Bugfix 🐛:
- Cross-signing: fix UX issue when closing the bottom sheet verification (#813)
- Room and room member profile: fix issues on dark and black themes
Changes in RiotX 0.14.0 (2020-02-01)
===================================================
Features ✨:
- First implementation of Cross-signing
- Enable encryption in unencrypted rooms, from the room settings (#212)
- Negotiate E2E by default for DMs (#907)
Improvements 🙌:
- Sharing things to RiotX: sort list by recent room first (#771)
- Hide the algorithm when turning on e2e (#897)
- Sort room members by display names
Other changes:
- Add support for /rainbow and /rainbowme commands (#879)
Build 🧱:
- Ensure builds are reproducible (#842)
- F-Droid: fix the "-dev" issue in version name (#815)
Changes in RiotX 0.13.0 (2020-01-17)
===================================================
Features ✨:
- Send and render typing events (#564)
- Create Room Profile screen (#54)
- Create Room Member Profile screen (#59)
Improvements 🙌:
- Render events m.room.encryption and m.room.guest_access in the timeline
Bugfix 🐛:
- Fix broken background sync in F-Droid version
- Fix issue with downloaded file on encrypted rooms. The file was not properly decrypted
Build 🧱:
- Change the way versionCode is computed (#827)
Changes in RiotX 0.12.0 (2020-01-09)
===================================================
Improvements 🙌:
- The initial sync is now handled by a foreground service
- Render aliases and canonical alias change in the timeline
- Introduce developer mode in the settings (#745, #796)
- Improve devices list screen
- Add settings for rageshake sensibility
- Fix autocompletion issues and add support for rooms, groups, and emoji (#780)
- Show skip to bottom FAB while scrolling down (#752)
- Enable encryption on a room, SDK part (#212)
Other changes:
- Change the way RiotX identifies a session to allow the SDK to support several sessions with the same user (#800)
- Exclude play-services-oss-licenses library from F-Droid build (#814)
- Email domain can be limited on some homeservers, i18n of the displayed error (#754)
Bugfix 🐛:
- Fix crash when opening room creation screen from the room filtering screen
- Fix avatar image disappearing (#777)
- Fix read marker banner when permalink
- Fix joining upgraded rooms (#697)
- Fix matrix.org room directory not being browsable (#807)
- Hide non working settings (#751)
Changes in RiotX 0.11.0 (2019-12-19)
===================================================
Features ✨:
- Implement soft logout (#281)
Improvements 🙌:
- Handle navigation to room via room alias (#201)
- Open matrix.to link in RiotX (#57)
- Limit sticker size in the timeline
Other changes:
- Use same default room colors than Riot-Web
Bugfix 🐛:
- Scroll breadcrumbs to top when opened
- Render default room name when it starts with an emoji (#477)
- Do not display " (IRC)" in display names https://github.com/vector-im/riot-android/issues/444
- Fix rendering issue with HTML formatted body
- Disable click on Stickers (#703)
Build 🧱:
- Include diff-match-patch sources as dependency
Changes in RiotX 0.10.0 (2019-12-10)
===================================================
Features ✨:
- Breadcrumbs: switch from one room to another quickly (#571)
Improvements 🙌:
- Support entering a RiotWeb client URL instead of the homeserver URL during connection (#744)
Other changes:
- Add reason for all membership events (https://github.com/matrix-org/matrix-doc/pull/2367)
Bugfix 🐛:
- When automardown is ON, pills are sent as MD in body (#739)
- "ban" event are not rendered correctly (#716)
- Fix crash when rotating screen in Room timeline
Changes in RiotX 0.9.1 (2019-12-05)
===================================================
Bugfix 🐛:
- Fix an issue with DB transaction (#740)
Changes in RiotX 0.9.0 (2019-12-05)
===================================================
Features ✨:
- Account creation. It's now possible to create account on any homeserver with RiotX (#34)
- Iteration of the login flow (#613)
- [SDK] MSC2241 / verification in DMs (#707)
Improvements 🙌:
- Send mention Pills from composer
- Links in message preview in the bottom sheet are now active.
- Rework the read marker to make it more usable
Other changes:
- Fix a small grammatical error when an empty room list is shown.
Bugfix 🐛:
- Do not show long click help if only invitation are displayed
- Fix emoji filtering not working
- Fix issue of closing Realm in another thread (#725)
- Attempt to properly cancel the crypto module when user signs out (#724)
Changes in RiotX 0.8.0 (2019-11-19)
===================================================
Features ✨:
- Handle long click on room in the room list (#395)
- Ignore/UnIgnore users, and display list of ignored users (#542, #617)
Improvements 🙌:
- Search reaction by name or keyword in emoji picker
- Handle code tags (#567)
- Support spoiler messages
- Support m.sticker and m.room.join_rules events in timeline
Other changes:
- Markdown set to off by default (#412)
- Accessibility improvements to the attachment file type chooser
Bugfix 🐛:
- Fix issues with some member events rendering (#498)
- Passphrase does not match (Export room keys) (#644)
- Ask for permission to write external storage when uri comes from the keyboard (#658)
- Fix issue with english US/GB translation (#671)
Changes in RiotX 0.7.0 (2019-10-24)
===================================================
Features:
- Share elements from other app to RiotX (#58)
- Read marker (#84)
- Add ability to report content (#515)
Improvements:
- Persist active tab between sessions (#503)
- Do not upload file too big for the homeserver (#587)
- Attachments: start using system pickers (#52)
- Mark all messages as read (#396)
Other changes:
- Accessibility improvements to read receipts in the room timeline and reactions emoji chooser
Bugfix:
- Fix issue on upload error in loop (#587)
- Fix opening a permalink: the targeted event is displayed twice (#556)
- Fix opening a permalink paginates all the history up to the last event (#282)
- after login, the icon in the top left is a green 'A' for (all communities) rather than my avatar (#267)
- Picture uploads are unreliable, pictures are shown in wrong aspect ratio on desktop client (#517)
- Invitation notifications are not dismissed automatically if room is joined from another client (#347)
- Opening links from RiotX reuses browser tab (#599)
Changes in RiotX 0.6.1 (2019-09-24)
===================================================
Bugfix:
- Fix crash: MergedHeaderItem was missing dimensionConverter
Changes in RiotX 0.6.0 (2019-09-24)
===================================================
Features:
- Save draft of a message when exiting a room with non empty composer (#329)
Improvements:
- Add unread indent on room list (#485)
- Message Editing: Update notifications (#128)
- Remove any notification of a redacted event (#563)
Other changes:
- Fix a few accessibility issues
Bugfix:
- Fix characters erased from the Search field when the result are coming (#545)
- "No connection" banner was displayed by mistake
- Leaving community (from another client) has no effect on RiotX (#497)
- Push rules was not retrieved after a clear cache
- m.notice messages trigger push notifications (#238)
- Embiggen messages with multiple emojis also for edited messages (#458)
Build:
- Fix (again) issue with bad versionCode generated by Buildkite (#553)
Changes in RiotX 0.5.0 (2019-09-17)
===================================================
Features:
- Implementation of login to homeserver with SSO (#557)
- Handle M_CONSENT_NOT_GIVEN error (#64)
- Auto configure homeserver and identity server URLs of LoginActivity with a magic link
Improvements:
- Reduce default release build log level, and lab option to enable more logs.
- Display a no network indicator when there is no network (#559)
Bugfix:
- Fix crash due to missing informationData (#535)
- Progress in initial sync dialog is decreasing for a step and should not (#532)
- Fix rendering issue of accepted third party invitation event
- All current notifications were dismissed by mistake when the app is launched from the launcher
Build:
- Fix issue with version name (#533)
- Fix issue with bad versionCode generated by Buildkite (#553)
Changes in RiotX 0.4.0 (2019-08-30)
===================================================
Features:
- Display read receipts in timeline (#81)
Improvements:
-
Other changes:
-
- Reactions: Reinstate the ability to react with non-unicode keys (#307)
Bugfix:
- Fix text diff linebreak display (#441)
- Date change message repeats for each redaction until a normal message (#358)
- Slide-in reply icon is distorted (#423)
Translations:
-
Build:
-
- Regression / e2e replies not encrypted
- Some video won't play
- Privacy: remove log of notifiable event (#519)
- Fix crash with EmojiCompat (#530)
Changes in RiotX 0.3.0 (2019-08-08)
===================================================
@ -90,24 +434,26 @@ Mode details here: https://medium.com/@RiotChat/introducing-the-riotx-beta-for-a
=======================================================
Changes in RiotX 0.0.0 (2019-XX-XX)
Changes in RiotX 0.X.0 (2020-XX-XX)
===================================================
Features:
Features:
-
Improvements:
Improvements 🙌:
-
Bugfix 🐛:
-
Translations 🗣:
-
SDK API changes ⚠️:
-
Build 🧱:
-
Other changes:
-
Bugfix:
-
Translations:
-
Build:
-

View File

@ -1,6 +1,6 @@
# Contributing code to Matrix
Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst
Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md
Android support can be found in this [![Riot Android Matrix room #riot-android:matrix.org](https://img.shields.io/matrix/riot-android:matrix.org.svg?label=%23riot-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#riot-android:matrix.org) room.
@ -11,6 +11,7 @@ Dedicated room for RiotX: [![RiotX Android Matrix room #riot-android:matrix.org]
## Android Studio settings
Please set the "hard wrap" setting of Android Studio to 160 chars, this is the setting we use internally to format the source code (Menu `Settings/Editor/Code Style` then `Hard wrap at`).
Please ensure that your using the project formatting rules (which are in the project at .idea/codeStyles/), and format the file before committing them.
## Compilation
@ -40,26 +41,58 @@ Please add a line to the top of the file `CHANGES.md` describing your change.
Make sure the following commands execute without any error:
> ./tools/check/check_code_quality.sh
#### Internal tool
> ./gradlew lintGplayRelease
<pre>
./tools/check/check_code_quality.sh
</pre>
#### ktlint
<pre>
curl -sSLO https://github.com/pinterest/ktlint/releases/download/0.34.2/ktlint && chmod a+x ktlint
./ktlint --android --experimental -v
</pre>
Note that you can run
<pre>
./ktlint --android --experimental -v -F
</pre>
For ktlint to fix some detected errors for you (you still have to check and commit the fix of course)
#### lint
<pre>
./gradlew lintGplayRelease
./gradlew lintFdroidRelease
</pre>
### Unit tests
Make sure the following commands execute without any error:
> ./gradlew testGplayReleaseUnitTest
<pre>
./gradlew testGplayReleaseUnitTest
</pre>
### Tests
RiotX is currently supported on Android Jelly Bean (API 16+): please test your change on an Android device (or Android emulator) running with API 16. Many issues can happen (including crashes) on older devices.
RiotX is currently supported on Android KitKat (API 19+): please test your change on an Android device (or Android emulator) running with API 19. Many issues can happen (including crashes) on older devices.
Also, if possible, please test your change on a real device. Testing on Android emulator may not be sufficient.
You should consider adding Unit tests with your PR, and also integration tests (AndroidTest). Please refer to [this document](./docs/integration_tests.md) to install and run the integration test environment.
### Internationalisation
When adding new string resources, please only add new entries in file `value/strings.xml`. Translations will be added later by the community of translators with a specific tool named [Weblate](https://translate.riot.im/projects/riot-android/).
Do not hesitate to use plurals when appropriate.
### Accessibility
Please consider accessibility as an important point. As a minimum requirement, in layout XML files please use attributes such as `android:contentDescription` and `android:importantForAccessibility`, and test with a screen reader if it's working well. You can add new string resources, dedicated to accessibility, in this case, please prefix theirs id with `a11y_`.
### Layout
When adding or editing layouts, make sure the layout will render correctly if device uses a RTL (Right To Left) language.

View File

@ -12,12 +12,13 @@ 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)
Nightly build: [![Buildkite](https://badge.buildkite.com/657d3db27364448d69d54f66c690f7788bc6aa80a7628e37f3.svg?branch=develop)](https://buildkite.com/matrix-dot-org/riotx-android/builds?branch=develop)
# New Android SDK
RiotX is based on a new Android SDK fully written in Kotlin (like RiotX). In order to make the early development as fast as possible, RiotX and the new SDK currently share the same git repository. We will make separate repos once the API is stable enough.
RiotX is based on a new Android SDK fully written in Kotlin (like RiotX). In order to make the early development as fast as possible, RiotX and the new SDK currently share the same git repository. We will make separate repos once the SDK is stable enough.
# Roadmap

View File

@ -1,9 +1,7 @@
import javax.tools.JavaCompiler
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = '1.3.21'
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
@ -12,11 +10,11 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
classpath 'com.google.gms:google-services:4.2.0'
classpath "com.airbnb.okreplay:gradle-plugin:1.4.0"
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.google.gms:google-services:4.3.2'
classpath "com.airbnb.okreplay:gradle-plugin:1.5.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.6.2'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:2.7.1'
classpath 'com.google.android.gms:oss-licenses-plugin:0.9.5'
// NOTE: Do not place your application dependencies here; they belong
@ -36,6 +34,10 @@ allprojects {
includeGroupByRegex "com\\.github\\.jaiselrahman"
// And monarchy
includeGroupByRegex "com\\.github\\.Zhuinden"
// And ucrop
includeGroupByRegex "com\\.github\\.yalantis"
// JsonViewer
includeGroupByRegex 'com\\.github\\.BillCarsonFr'
}
}
maven {
@ -47,24 +49,11 @@ allprojects {
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
google()
jcenter()
maven {
url 'https://repo.adobe.com/nexus/content/repositories/public/'
content {
includeGroupByRegex "diff_match_patch"
}
}
}
tasks.withType(JavaCompile).all {
options.compilerArgs += [
'-Adagger.gradle.incremental=enabled'
]
}
afterEvaluate {
extensions.findByName("kapt")?.arguments {
arg("dagger.gradle.incremental", "enabled")
}
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
// Warnings are potential errors, so stop ignoring them
kotlinOptions.allWarningsAsErrors = true
}
}

1
diff-match-patch/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,8 @@
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
}
sourceCompatibility = "8"
targetCompatibility = "8"

File diff suppressed because it is too large Load Diff

97
docs/integration_tests.md Normal file
View File

@ -0,0 +1,97 @@
# Integration tests
Integration tests are useful to ensure that the code works well for any use cases.
They can also be used as sample on how to use the Matrix SDK.
In a ideal world, every API of the SDK should be covered by integration tests. For the moment, we have test mainly for the Crypto part, which is the tricky part. But it covers quite a lot of features: accounts creation, login to existing account, send encrypted messages, keys backup, verification, etc.
The Matrix SDK is able to open multiple sessions, for the same user, of for different users. This way we can test communication between several sessions on a single device.
## Pre requirements
Integration tests need a homeserver running on localhost.
The documentation describes what we do to have one, using [Synapse](https://github.com/matrix-org/synapse/), which is the Matrix reference homeserver.
## Install and run Synapse
Steps:
- Install virtualenv
```bash
python3 -m pip install virtualenv
```
- Clone Synapse repository
```bash
git clone -b develop https://github.com/matrix-org/synapse.git
```
or
```bash
git clone -b develop git@github.com:matrix-org/synapse.git
```
You should have the develop branch cloned by default.
- Run synapse, from the Synapse folder you just cloned
```bash
virtualenv -p python3 env
source env/bin/activate
pip install -e .
demo/start.sh --no-rate-limit
```
Alternatively, to install the latest Synapse release package (and not a cloned branch) you can run the following instead of `pip install -e .`:
```bash
pip install matrix-synapse
```
You should now have 3 running federated Synapse instances 🎉, at http://127.0.0.1:8080/, http://127.0.0.1:8081/ and http://127.0.0.1:8082/, which should display a "It Works! Synapse is running" message.
## Run the test
It's recommended to run tests using an Android Emulator and not a real device. First reason for that is that the tests will use http://10.0.2.2:8080 to connect to Synapse, which run locally on your machine.
You can run all the tests in the `androidTest` folders.
## Stop Synapse
To stop Synapse, you can run the following commands:
```bash
./demo/stop.sh
```
And you can deactivate the virtualenv:
```bash
deactivate
```
## Troubleshoot
You'll need python3 to be able to run synapse
### Android Emulator does cannot reach the homeserver
Try on the Emulator browser to open "http://10.0.2.2:8080". You should see the "Synapse is running" message.
### virtualenv command fails
You can try using
```bash
python3 -m venv env
```
or
```bash
python3 -m virtualenv env
```
instead of
```bash
virtualenv -p python3 env
```

260
docs/signin.md Normal file
View File

@ -0,0 +1,260 @@
# Sign in to a homeserver
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
### Get the flow
Client request the sign-in flows, once the homeserver is chosen by the user and its url is known (in the example it's `https://matrix.org`)
> curl -X GET 'https://matrix.org/_matrix/client/r0/login'
200
```json
{
"flows": [
{
"type": "m.login.password"
}
]
}
```
### Login with username
The user is able to connect using `m.login.password`
> curl -X POST --data $'{"identifier":{"type":"m.id.user","user":"alice"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
```json
{
"identifier": {
"type": "m.id.user",
"user": "alice"
},
"password": "weak_password",
"type": "m.login.password",
"initial_device_display_name": "Portable"
}
```
#### Incorrect password
403
```json
{
"errcode": "M_FORBIDDEN",
"error": "Invalid password"
}
```
#### Correct password:
We get credential (200)
```json
{
"user_id": "@benoit0816:matrix.org",
"access_token": "MDAxOGxvY2F0aW9uIG1hdHREDACTEDb2l0MDgxNjptYXRyaXgub3JnCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lkIG5vbmNlID0gfnYrSypfdTtkNXIuNWx1KgowMDJmc2lnbmF0dXJlIOsh1XqeAkXexh4qcofl_aR4kHJoSOWYGOhE7-ubX-DZCg",
"home_server": "matrix.org",
"device_id": "GTVREDALBF",
"well_known": {
"m.homeserver": {
"base_url": "https:\/\/matrix.org\/"
}
}
}
```
### Login with email
If the user has associated an email with its account, he can signin using the email.
> curl -X POST --data $'{"identifier":{"type":"m.id.thirdparty","medium":"email","address":"alice@yopmail.com"},"password":"weak_password","type":"m.login.password","initial_device_display_name":"Portable"}' 'https://matrix.org/_matrix/client/r0/login'
```json
{
"identifier": {
"type": "m.id.thirdparty",
"medium": "email",
"address": "alice@yopmail.com"
},
"password": "weak_password",
"type": "m.login.password",
"initial_device_display_name": "Portable"
}
```
#### Unknown email
403
```json
{
"errcode": "M_FORBIDDEN",
"error": ""
}
```
#### Known email, wrong password
403
```json
{
"errcode": "M_FORBIDDEN",
"error": "Invalid password"
}
```
##### Known email, correct password
We get the credentials (200)
```json
{
"user_id": "@alice:matrix.org",
"access_token": "MDAxOGxvY2F0aW9uIG1hdHJpeC5vcmREDACTEDZXJfaWQgPSBAYmVub2l0MDgxNjptYXRyaXgub3JnCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lkIG5vbmNlID0gNjtDY0MwRlNPSFFoOC5wOgowMDJmc2lnbmF0dXJlIGiTRm1mYLLxQywxOh3qzQVT8HoEorSokEP2u-bAwtnYCg",
"home_server": "matrix.org",
"device_id": "WBSREDASND",
"well_known": {
"m.homeserver": {
"base_url": "https:\/\/matrix.org\/"
}
}
}
```
### Login with Msisdn
Not supported yet in RiotX
### Login with SSO
> curl -X GET 'https://homeserver.with.sso/_matrix/client/r0/login'
200
```json
{
"flows": [
{
"type": "m.login.sso"
}
]
}
```
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
## Reset password
Ref: `https://matrix.org/docs/spec/client_server/latest#post-matrix-client-r0-account-password-email-requesttoken`
When the user has forgotten his password, he can reset it by providing an email and a new password.
Here is the flow:
### Send email
User is asked to enter the email linked to his account and a new password.
We display a warning regarding e2e.
At the first step, we do not send the password, only the email and a client secret, generated by the application
> curl -X POST --data $'{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","send_attempt":0,"email":"user@domain.com"}' 'https://matrix.org/_matrix/client/r0/account/password/email/requestToken'
```json
{
"client_secret": "6c57f284-85e2-421b-8270-fb1795a120a7",
"send_attempt": 0,
"email": "user@domain.com"
}
```
#### When the email is not known
We get a 400
```json
{
"errcode": "M_THREEPID_NOT_FOUND",
"error": "Email not found"
}
```
#### When the email is known
We get a 200 with a `sid`
```json
{
"sid": "tQNbrREDACTEDldA"
}
```
Then the user is asked to click on the link in the email he just received, and to confirm when it's done.
During this step, the new password is sent to the homeserver.
If the user confirms before the link is clicked, we get an error:
> curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
```json
{
"auth": {
"type": "m.login.email.identity",
"threepid_creds": {
"client_secret": "6c57f284-85e2-421b-8270-fb1795a120a7",
"sid": "tQNbrREDACTEDldA"
}
},
"new_password": "weak_password"
}
```
401
```json
{
"errcode": "M_UNAUTHORIZED",
"error": ""
}
```
### User clicks on the link
The link has the form:
https://matrix.org/_matrix/client/unstable/password_reset/email/submit_token?token=fzZLBlcqhTKeaFQFSRbsQnQCkzbwtGAD&client_secret=6c57f284-85e2-421b-8270-fb1795a120a7&sid=tQNbrREDACTEDldA
It contains the client secret, a token and the sid
When the user click the link, if validate his ownership and the new password can now be ent by the application (on user demand):
> curl -X POST --data $'{"auth":{"type":"m.login.email.identity","threepid_creds":{"client_secret":"6c57f284-85e2-421b-8270-fb1795a120a7","sid":"tQNbrREDACTEDldA"}},"new_password":"weak_password"}' 'https://matrix.org/_matrix/client/r0/account/password'
```json
{
"auth": {
"type": "m.login.email.identity",
"threepid_creds": {
"client_secret": "6c57f284-85e2-421b-8270-fb1795a120a7",
"sid": "tQNbrREDACTEDldA"
}
},
"new_password": "weak_password"
}
```
200
```json
{}
```
The password has been changed, and all the existing token are invalidated. User can now login with the new password.

579
docs/signup.md Normal file
View File

@ -0,0 +1,579 @@
# Sign up to a homeserver
This document describes the flow of registration to a homeserver. Examples come from the `matrix.org` homeserver.
*Ref*: https://matrix.org/docs/spec/client_server/latest#account-registration-and-management
## Sign up flows
### First step
Client request the sign-up flows, once the homeserver is chosen by the user and its url is known (in the example it's `https://matrix.org`)
> curl -X POST --data $'{}' 'https://matrix.org/_matrix/client/r0/register'
```json
{
}
```
We get the flows with a 401, which also means that the registration is possible on this homeserver.
```json
{
"session": "vwehdKMtkRedactedAMwgCACZ",
"flows": [
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.dummy"
]
},
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.email.identity"
]
}
],
"params": {
"m.login.recaptcha": {
"public_key": "6LcgI54UAAAAAoREDACTEDoDdOocFpYVdjYBRe4zb"
},
"m.login.terms": {
"policies": {
"privacy_policy": {
"version": "1.0",
"en": {
"name": "Terms and Conditions",
"url": "https:\/\/matrix.org\/_matrix\/consent?v=1.0"
}
}
}
}
}
}
```
If the registration is not possible, we get a 403
```json
{
"errcode": "M_FORBIDDEN",
"error": "Registration is disabled"
}
```
### Step 1: entering user name and password
The app is displaying a form to enter username and password.
> curl -X POST --data $'{"initial_device_display_name":"Mobile device","username":"alice","password": "weak_password"}' 'https://matrix.org/_matrix/client/r0/register'
```json
{
"initial_device_display_name": "Mobile device",
"username": "alice",
"password": "weak_password"
}
```
401. Note that the `session` value has changed (because we did not provide the previous value in the request body), but it's ok, we will use the new value for the next steps.
```json
{
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"flows": [
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.dummy"
]
},
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.email.identity"
]
}
],
"params": {
"m.login.recaptcha": {
"public_key": "6LcgI54UAAAAAoREDACTEDoDdOocFpYVdjYBRe4zb"
},
"m.login.terms": {
"policies": {
"privacy_policy": {
"version": "1.0",
"en": {
"name": "Terms and Conditions",
"url": "https:\/\/matrix.org\/_matrix\/consent?v=1.0"
}
}
}
}
}
}
```
#### If username already exists
We get a 400:
```json
{
"errcode": "M_USER_IN_USE",
"error": "User ID already taken."
}
```
### Step 2: entering email
User is proposed to enter an email. We skip this step.
> curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.dummy"}}' 'https://matrix.org/_matrix/client/r0/register'
```json
{
"auth": {
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"type": "m.login.dummy"
}
}
```
401
```json
{
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"flows": [
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.dummy"
]
},
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.email.identity"
]
}
],
"params": {
"m.login.recaptcha": {
"public_key": "6LcgI54UAAAAAoREDACTEDoDdOocFpYVdjYBRe4zb"
},
"m.login.terms": {
"policies": {
"privacy_policy": {
"version": "1.0",
"en": {
"name": "Terms and Conditions",
"url": "https:\/\/matrix.org\/_matrix\/consent?v=1.0"
}
}
}
}
},
"completed": [
"m.login.dummy"
]
}
```
### Step 2 bis: we enter an email
We request a token to the homeserver. The `client_secret` is generated by the application
> curl -X POST --data $'{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","email":"alice@yopmail.com","send_attempt":0}' 'https://matrix.org/_matrix/client/r0/register/email/requestToken'
```json
{
"client_secret": "53e679ea-oRED-ACTED-92b8-3012c49c6cfa",
"email": "alice@yopmail.com",
"send_attempt": 0
}
```
200
```json
{
"sid": "qlBCREDACTEDEtgxD"
}
```
And
> curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
```json
{
"auth": {
"threepid_creds": {
"client_secret": "53e679ea-oRED-ACTED-92b8-3012c49c6cfa",
"sid": "qlBCREDACTEDEtgxD"
},
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"type": "m.login.email.identity"
}
}
```
We get 401 since the email is not validated yet:
```json
{
"errcode": "M_UNAUTHORIZED",
"error": ""
}
```
The app is now polling on
> curl -X POST --data $'{"auth":{"threepid_creds":{"client_secret":"53e679ea-oRED-ACTED-92b8-3012c49c6cfa","sid":"qlBCREDACTEDEtgxD"},"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.email.identity"}}' 'https://matrix.org/_matrix/client/r0/register'
```json
{
"auth": {
"threepid_creds": {
"client_secret": "53e679ea-oRED-ACTED-92b8-3012c49c6cfa",
"sid": "qlBCREDACTEDEtgxD"
},
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"type": "m.login.email.identity"
}
}
```
We click on the link received by email `https://matrix.org/_matrix/client/unstable/registration/email/submit_token?token=vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ&client_secret=53e679ea-oRED-ACTED-92b8-3012c49c6cfa&sid=qlBCREDACTEDEtgxD` which contains:
- A `token` vtQjQIZfwdoREDACTEDozrmKYSWlCXsJ
- The `client_secret`: 53e679ea-oRED-ACTED-92b8-3012c49c6cfa
- A `sid`: qlBCREDACTEDEtgxD
Once the link is clicked, the registration request (polling) returns a 401 with the following content:
```json
{
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"flows": [
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.dummy"
]
},
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.email.identity"
]
}
],
"params": {
"m.login.recaptcha": {
"public_key": "6LcgI54UAAAAAoREDACTEDoDdOocFpYVdjYBRe4zb"
},
"m.login.terms": {
"policies": {
"privacy_policy": {
"version": "1.0",
"en": {
"name": "Terms and Conditions",
"url": "https:\/\/matrix.org\/_matrix\/consent?v=1.0"
}
}
}
}
},
"completed": [
"m.login.email.identity"
]
}
```
### Step 3: Accepting T&C
User is proposed to accept T&C and he accepts them
> curl -X POST --data $'{"auth":{"session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.terms"}}' 'https://matrix.org/_matrix/client/r0/register'
```json
{
"auth": {
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"type": "m.login.terms"
}
}
```
401
```json
{
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"flows": [
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.dummy"
]
},
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.email.identity"
]
}
],
"params": {
"m.login.recaptcha": {
"public_key": "6LcgI54UAAAAAoREDACTEDoDdOocFpYVdjYBRe4zb"
},
"m.login.terms": {
"policies": {
"privacy_policy": {
"version": "1.0",
"en": {
"name": "Terms and Conditions",
"url": "https:\/\/matrix.org\/_matrix\/consent?v=1.0"
}
}
}
}
},
"completed": [
"m.login.dummy",
"m.login.terms"
]
}
```
### Step 4: Captcha
User is proposed to prove he is not a robot and he does it:
> curl -X POST --data $'{"auth":{"response":"03AOLTBLSiGS9GhFDpAMblJ2nlXOmHXqAYJ5OvHCPUjiVLBef3k9snOYI_BDC32-t4D2jv-tpvkaiEI_uloobFd9RUTPpJ7con2hMddbKjSCYqXqcUQFhzhbcX6kw8uBnh2sbwBe80_ihrHGXEoACXQkL0ki1Q0uEtOeW20YBRjbNABsZPpLNZhGIWC0QVXnQ4FouAtZrl3gOAiyM-oG3cgP6M9pcANIAC_7T2P2amAHbtsTlSR9CsazNyS-rtDR9b5MywdtnWN9Aw8fTJb8cXQk_j7nvugMxzofPjSOrPKcr8h5OqPlpUCyxxnFtag6cuaPSUwh43D2L0E-ZX7djzaY2Yh_U2n6HegFNPOQ22CJmfrKwDlodmAfMPvAXyq77n3HpoREDACTEDo3830RHF4BfkGXUaZjctgg-A1mvC17hmQmQpkG7IhDqyw0onU-0vF_-ehCjq_CcQEDpS_O3uiHJaG5xGf-0rhLm57v_wA3deugbsZuO4uTuxZZycN_mKxZ97jlDVBetl9hc_5REPbhcT1w3uzTCSx7Q","session":"xptUYoREDACTEDogOWAGVnbJQ","type":"m.login.recaptcha"}}' 'https://matrix.org/_matrix/client/r0/register'
```json
{
"auth": {
"response": "03AOLTBLSiGS9GhFDpAMblJ2nlXOmHXqAYJ5OvHCPUjiVLBef3k9snOYI_BDC32-t4D2jv-tpvkaiEI_uloobFd9RUTPpJ7con2hMddbKjSCYqXqcUQFhzhbcX6kw8uBnh2sbwBe80_ihrHGXEoACXQkL0ki1Q0uEtOeW20YBRjbNABsZPpLNZhGIWC0QVXnQ4FouAtZrl3gOAiyM-oG3cgP6M9pcANIAC_7T2P2amAHbtsTlSR9CsazNyS-rtDR9b5MywdtnWN9Aw8fTJb8cXQk_j7nvugMxzofPjSOrPKcr8h5OqPlpUCyxxnFtag6cuaPSUwh43D2L0E-ZX7djzaY2Yh_U2n6HegFNPOQ22CJmfrKwDlodmAfMPvAXyq77n3HpoREDACTEDo3830RHF4BfkGXUaZjctgg-A1mvC17hmQmQpkG7IhDqyw0onU-0vF_-ehCjq_CcQEDpS_O3uiHJaG5xGf-0rhLm57v_wA3deugbsZuO4uTuxZZycN_mKxZ97jlDVBetl9hc_5REPbhcT1w3uzTCSx7Q",
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"type": "m.login.recaptcha"
}
}
```
200
```json
{
"user_id": "@alice:matrix.org",
"home_server": "matrix.org",
"access_token": "MDAxOGxvY2F0aW9uIG1hdHJpeC5vcmcKMoREDACTEDo50aWZpZXIga2V5CjAwMTBjaWQgZ2VuID0gMQowMDI5Y2lkIHVzZXJfaWQgPSBAYmVub2l0eHh4eDptYXRoREDACTEDoCjAwMTZjaWQgdHlwZSA9IGFjY2VzcwowMDIxY2lkIG5vbmNlID0gNHVSVm00aVFDaWlKdoREDACTEDoJmc2lnbmF0dXJlIOmHnTLRfxiPjhrWhS-dThUX-qAzZktfRThzH1YyAsxaCg",
"device_id": "FLBAREDAJZ"
}
```
The account is created!
### Step 5: MSISDN
Some homeservers may require the user to enter MSISDN.
On matrix.org, it's not required, and not even optional, but it's still possible for the app to add a MSISDN during the registration.
The user enter a phone number and select a country, the `client_secret` is generated by the application
> curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","send_attempt":1,"country":"FR","phone_number":"+33611223344"}' 'https://matrix.org/_matrix/client/r0/register/msisdn/requestToken'
```json
{
"client_secret": "d3e285f6-972a-496c-9a22-7915a2db57c7",
"send_attempt": 1,
"country": "FR",
"phone_number": "+33611223344"
}
```
If the msisdn is already associated to another account, you will received an error:
```json
{
"errcode": "M_THREEPID_IN_USE",
"error": "Phone number is already in use"
}
```
If it is not the case, the homeserver send the SMS and returns some data, especially a `sid` and a `submit_url`:
```json
{
"msisdn": "33611223344",
"intl_fmt": "+336 11 22 33 44",
"success": true,
"sid": "1678881798",
"submit_url": "https:\/\/matrix.org\/_matrix\/client\/unstable\/add_threepid\/msisdn\/submit_token"
}
```
When you execute the register request, with the received `sid`, you get an error since the MSISDN is not validated yet:
> curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
```json
"auth": {
"type": "m.login.msisdn",
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"threepid_creds": {
"client_secret": "d3e285f6-972a-496c-9a22-7915a2db57c7",
"sid": "1678881798"
}
}
}
```
There is an issue on Synapse, which return a 401, it sends too much data along with the classical MatrixError fields:
```json
{
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"flows": [
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.dummy"
]
},
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.email.identity"
]
}
],
"params": {
"m.login.recaptcha": {
"public_key": "6LcgI54UAAAAABGdGmruw6DdOocFpYVdjYBRe4zb"
},
"m.login.terms": {
"policies": {
"privacy_policy": {
"version": "1.0",
"en": {
"name": "Terms and Conditions",
"url": "https:\/\/matrix.org\/_matrix\/consent?v=1.0"
}
}
}
}
},
"completed": [],
"error": "",
"errcode": "M_UNAUTHORIZED"
}
```
The user receive the SMS, he can enter the SMS code in the app, which is sent using the "submit_url" received ie the response of the `requestToken` request:
> curl -X POST --data $'{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798","token":"123456"}' 'https://matrix.org/_matrix/client/unstable/add_threepid/msisdn/submit_token'
```json
{
"client_secret": "d3e285f6-972a-496c-9a22-7915a2db57c7",
"sid": "1678881798",
"token": "123456"
}
```
If the code is not correct, we get a 200 with:
```json
{
"success": false
}
```
And if the code is correct we get a 200 with:
```json
{
"success": true
}
```
We can now execute the registration request, to the homeserver
> curl -X POST --data $'{"auth":{"type":"m.login.msisdn","session":"xptUYoREDACTEDogOWAGVnbJQ","threepid_creds":{"client_secret":"d3e285f6-972a-496c-9a22-7915a2db57c7","sid":"1678881798"}}}' 'https://matrix.org/_matrix/client/r0/register'
```json
{
"auth": {
"type": "m.login.msisdn",
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"threepid_creds": {
"client_secret": "d3e285f6-972a-496c-9a22-7915a2db57c7",
"sid": "1678881798"
}
}
}
```
Now the homeserver consider that the `m.login.msisdn` step is completed (401):
```json
{
"session": "xptUYoREDACTEDogOWAGVnbJQ",
"flows": [
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.dummy"
]
},
{
"stages": [
"m.login.recaptcha",
"m.login.terms",
"m.login.email.identity"
]
}
],
"params": {
"m.login.recaptcha": {
"public_key": "6LcgI54UAAAAABGdGmruw6DdOocFpYVdjYBRe4zb"
},
"m.login.terms": {
"policies": {
"privacy_policy": {
"version": "1.0",
"en": {
"name": "Terms and Conditions",
"url": "https:\/\/matrix.org\/_matrix\/consent?v=1.0"
}
}
}
}
},
"completed": [
"m.login.msisdn"
]
}
```

View File

@ -1,6 +1,6 @@
#Tue Mar 19 09:53:05 CET 2019
#Fri Sep 27 10:10:35 CEST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

View File

@ -5,16 +5,15 @@ apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 28
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
versionCode 1
versionName "1.0"
// Multidex is useful for tests
multiDexEnabled true
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -29,17 +28,22 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
dependencies {
implementation project(":matrix-sdk-android")
implementation 'androidx.appcompat:appcompat:1.1.0-beta01'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
// Paging
implementation "androidx.paging:paging-runtime-ktx:2.1.0"
// Logging
implementation 'com.jakewharton.timber:timber:4.7.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

View File

@ -1,42 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.rx;
import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("im.vector.matrix.rx.test", appContext.getPackageName());
}
}

View File

@ -60,4 +60,12 @@ private class LiveDataObservable<T>(
fun <T> LiveData<T>.asObservable(): Observable<T> {
return LiveDataObservable(this).observeOn(Schedulers.computation())
}
}
internal fun <T> Observable<T>.startWithCallable(supplier: () -> T): Observable<T> {
val startObservable = Observable
.fromCallable(supplier)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
return startWith(startObservable)
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.rx
import im.vector.matrix.android.api.util.Optional
import io.reactivex.Observable
fun <T : Any> Observable<Optional<T>>.unwrap(): Observable<T> {
return filter { it.hasValue() }.map { it.get() }
}
fun <T : Any, U : Any> Observable<Optional<T>>.mapOptional(fn: (T) -> U?): Observable<Optional<U>> {
return map {
it.map(fn)
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.rx
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
import io.reactivex.Completable
import io.reactivex.Single
fun <T> singleBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Single<T> = Single.create {
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
override fun onSuccess(data: T) {
it.onSuccess(data)
}
override fun onFailure(failure: Throwable) {
it.tryOnError(failure)
}
}
val cancelable = builder(callback)
it.setCancellable {
cancelable.cancel()
}
}
fun <T> completableBuilder(builder: (callback: MatrixCallback<T>) -> Cancelable): Completable = Completable.create {
val callback: MatrixCallback<T> = object : MatrixCallback<T> {
override fun onSuccess(data: T) {
it.onComplete()
}
override fun onFailure(failure: Throwable) {
it.tryOnError(failure)
}
}
val cancelable = builder(callback)
it.setCancellable {
cancelable.cancel()
}
}

View File

@ -16,46 +16,87 @@
package im.vector.matrix.rx
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
import im.vector.matrix.android.api.session.room.model.EventAnnotationsSummary
import im.vector.matrix.android.api.session.room.model.ReadReceipt
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.notification.RoomNotificationState
import im.vector.matrix.android.api.session.room.send.UserDraft
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.api.util.toOptional
import io.reactivex.Observable
import io.reactivex.Single
class RxRoom(private val room: Room) {
fun liveRoomSummary(): Observable<RoomSummary> {
return room.liveRoomSummary().asObservable()
fun liveRoomSummary(): Observable<Optional<RoomSummary>> {
return room.getRoomSummaryLive()
.asObservable()
.startWithCallable { room.roomSummary().toOptional() }
}
fun liveRoomMemberIds(): Observable<List<String>> {
return room.getRoomMemberIdsLive().asObservable()
fun liveRoomMembers(queryParams: RoomMemberQueryParams): Observable<List<RoomMemberSummary>> {
return room.getRoomMembersLive(queryParams).asObservable()
.startWithCallable {
room.getRoomMembers(queryParams)
}
}
fun liveAnnotationSummary(eventId: String): Observable<EventAnnotationsSummary> {
return room.getEventSummaryLive(eventId).asObservable()
fun liveAnnotationSummary(eventId: String): Observable<Optional<EventAnnotationsSummary>> {
return room.getEventAnnotationsSummaryLive(eventId).asObservable()
.startWithCallable {
room.getEventAnnotationsSummary(eventId).toOptional()
}
}
fun liveTimelineEvent(eventId: String): Observable<TimelineEvent> {
return room.liveTimeLineEvent(eventId).asObservable()
fun liveTimelineEvent(eventId: String): Observable<Optional<TimelineEvent>> {
return room.getTimeLineEventLive(eventId).asObservable()
.startWithCallable {
room.getTimeLineEvent(eventId).toOptional()
}
}
fun loadRoomMembersIfNeeded(): Single<Unit> = Single.create {
room.loadRoomMembersIfNeeded(MatrixCallbackSingle(it)).toSingle(it)
fun liveStateEvent(eventType: String, stateKey: String): Observable<Optional<Event>> {
return room.getStateEventLive(eventType, stateKey).asObservable()
.startWithCallable {
room.getStateEvent(eventType, stateKey).toOptional()
}
}
fun joinRoom(viaServers: List<String> = emptyList()): Single<Unit> = Single.create {
room.join(viaServers, MatrixCallbackSingle(it)).toSingle(it)
fun liveReadMarker(): Observable<Optional<String>> {
return room.getReadMarkerLive().asObservable()
}
fun liveReadReceipt(): Observable<Optional<String>> {
return room.getMyReadReceiptLive().asObservable()
}
fun loadRoomMembersIfNeeded(): Single<Unit> = singleBuilder {
room.loadRoomMembersIfNeeded(it)
}
fun joinRoom(reason: String? = null,
viaServers: List<String> = emptyList()): Single<Unit> = singleBuilder {
room.join(reason, viaServers, it)
}
fun liveEventReadReceipts(eventId: String): Observable<List<ReadReceipt>> {
return room.getEventReadReceiptsLive(eventId).asObservable()
}
fun liveDrafts(): Observable<List<UserDraft>> {
return room.getDraftsLive().asObservable()
}
fun liveNotificationState(): Observable<RoomNotificationState> {
return room.getLiveRoomNotificationState().asObservable()
}
}
fun Room.rx(): RxRoom {
return RxRoom(this)
}
}

View File

@ -18,57 +18,119 @@ package im.vector.matrix.rx
import androidx.paging.PagedList
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.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.util.JsonDict
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.api.util.toOptional
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
import io.reactivex.Observable
import io.reactivex.Single
class RxSession(private val session: Session) {
fun liveRoomSummaries(): Observable<List<RoomSummary>> {
return session.liveRoomSummaries().asObservable()
fun liveRoomSummaries(queryParams: RoomSummaryQueryParams): Observable<List<RoomSummary>> {
return session.getRoomSummariesLive(queryParams).asObservable()
.startWithCallable {
session.getRoomSummaries(queryParams)
}
}
fun liveGroupSummaries(): Observable<List<GroupSummary>> {
return session.liveGroupSummaries().asObservable()
fun liveGroupSummaries(queryParams: GroupSummaryQueryParams): Observable<List<GroupSummary>> {
return session.getGroupSummariesLive(queryParams).asObservable()
.startWithCallable {
session.getGroupSummaries(queryParams)
}
}
fun liveBreadcrumbs(): Observable<List<RoomSummary>> {
return session.getBreadcrumbsLive().asObservable()
.startWithCallable {
session.getBreadcrumbs()
}
}
fun liveSyncState(): Observable<SyncState> {
return session.syncState().asObservable()
return session.getSyncStateLive().asObservable()
}
fun livePushers(): Observable<List<Pusher>> {
return session.livePushers().asObservable()
return session.getPushersLive().asObservable()
}
fun liveUser(userId: String): Observable<Optional<User>> {
return session.getUserLive(userId).asObservable()
.startWithCallable {
session.getUser(userId).toOptional()
}
}
fun liveUsers(): Observable<List<User>> {
return session.liveUsers().asObservable()
return session.getUsersLive().asObservable()
}
fun liveIgnoredUsers(): Observable<List<User>> {
return session.getIgnoredUsersLive().asObservable()
}
fun livePagedUsers(filter: String? = null): Observable<PagedList<User>> {
return session.livePagedUsers(filter).asObservable()
return session.getPagedUsersLive(filter).asObservable()
}
fun createRoom(roomParams: CreateRoomParams): Single<String> = Single.create {
session.createRoom(roomParams, MatrixCallbackSingle(it)).toSingle(it)
fun createRoom(roomParams: CreateRoomParams): Single<String> = singleBuilder {
session.createRoom(roomParams, it)
}
fun searchUsersDirectory(search: String,
limit: Int,
excludedUserIds: Set<String>): Single<List<User>> = Single.create {
session.searchUsersDirectory(search, limit, excludedUserIds, MatrixCallbackSingle(it)).toSingle(it)
excludedUserIds: Set<String>): Single<List<User>> = singleBuilder {
session.searchUsersDirectory(search, limit, excludedUserIds, it)
}
fun joinRoom(roomId: String, viaServers: List<String> = emptyList()): Single<Unit> = Single.create {
session.joinRoom(roomId, viaServers, MatrixCallbackSingle(it)).toSingle(it)
fun joinRoom(roomIdOrAlias: String,
reason: String? = null,
viaServers: List<String> = emptyList()): Single<Unit> = singleBuilder {
session.joinRoom(roomIdOrAlias, reason, viaServers, it)
}
fun getRoomIdByAlias(roomAlias: String,
searchOnServer: Boolean): Single<Optional<String>> = singleBuilder {
session.getRoomIdByAlias(roomAlias, searchOnServer, it)
}
fun getProfileInfo(userId: String): Single<JsonDict> = singleBuilder {
session.getProfile(userId, it)
}
fun liveUserCryptoDevices(userId: String): Observable<List<CryptoDeviceInfo>> {
return session.cryptoService().getLiveCryptoDeviceInfo(userId).asObservable().startWithCallable {
session.cryptoService().getCryptoDeviceInfo(userId)
}
}
fun liveCrossSigningInfo(userId: String): Observable<Optional<MXCrossSigningInfo>> {
return session.cryptoService().crossSigningService().getLiveCrossSigningKeys(userId).asObservable()
.startWithCallable {
session.cryptoService().crossSigningService().getUserCrossSigningKeys(userId).toOptional()
}
}
fun liveAccountData(types: Set<String>): Observable<List<UserAccountDataEvent>> {
return session.getLiveAccountDataEvents(types).asObservable()
.startWithCallable {
session.getAccountDataEvents(types)
}
}
}
fun Session.rx(): RxSession {
return RxSession(this)
}
}

View File

@ -10,7 +10,7 @@ buildscript {
jcenter()
}
dependencies {
classpath "io.realm:realm-gradle-plugin:5.12.0"
classpath "io.realm:realm-gradle-plugin:6.1.0"
}
}
@ -67,10 +67,14 @@ android {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
}
static def gitRevision() {
def cmd = "git rev-parse --short HEAD"
def cmd = "git rev-parse --short=8 HEAD"
return cmd.execute().text.trim()
}
@ -86,41 +90,43 @@ static def gitRevisionDate() {
dependencies {
def arrow_version = "0.8.0"
def support_version = '1.1.0-beta01'
def arrow_version = "0.8.2"
def moshi_version = '1.8.0'
def lifecycle_version = '2.0.0'
def coroutines_version = "1.0.1"
def markwon_version = '3.0.0'
def daggerVersion = '2.23.1'
def lifecycle_version = '2.2.0'
def arch_version = '2.1.0'
def coroutines_version = "1.3.2"
def markwon_version = '3.1.0'
def daggerVersion = '2.25.4'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
implementation "androidx.appcompat:appcompat:1.1.0-rc01"
implementation "androidx.recyclerview:recyclerview:1.1.0-beta01"
implementation "androidx.appcompat:appcompat:1.1.0"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
kapt "androidx.lifecycle:lifecycle-compiler:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
// Network
implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.squareup.retrofit2:converter-moshi:2.4.0'
implementation 'com.squareup.okhttp3:okhttp:3.14.1'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
implementation 'com.novoda:merlin:1.2.0'
implementation 'com.squareup.retrofit2:retrofit:2.6.2'
implementation 'com.squareup.retrofit2:converter-moshi:2.6.2'
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
implementation 'com.squareup.okhttp3:logging-interceptor:4.2.2'
implementation "com.squareup.moshi:moshi-adapters:$moshi_version"
kapt "com.squareup.moshi:moshi-kotlin-codegen:$moshi_version"
implementation "ru.noties.markwon:core:$markwon_version"
// Image
implementation 'androidx.exifinterface:exifinterface:1.1.0'
implementation 'id.zelory:compressor:3.0.0'
// Database
implementation 'com.github.Zhuinden:realm-monarchy:0.5.1'
kapt 'dk.ilios:realmfieldnameshelper:1.1.1'
// Work
implementation "androidx.work:work-runtime-ktx:2.1.0-rc01"
implementation "androidx.work:work-runtime-ktx:2.3.3"
// FP
implementation "io.arrow-kt:arrow-core:$arrow_version"
@ -132,21 +138,25 @@ dependencies {
// DI
implementation "com.google.dagger:dagger:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.4.0'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.4.0'
compileOnly 'com.squareup.inject:assisted-inject-annotations-dagger2:0.5.0'
kapt 'com.squareup.inject:assisted-inject-processor-dagger2:0.5.0'
// Logging
implementation 'com.jakewharton.timber:timber:4.7.1'
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.0'
implementation 'com.facebook.stetho:stetho-okhttp3:1.5.1'
debugImplementation 'com.airbnb.okreplay:okreplay:1.4.0'
releaseImplementation 'com.airbnb.okreplay:noop:1.4.0'
androidTestImplementation 'com.airbnb.okreplay:espresso:1.4.0'
// Bus
implementation 'org.greenrobot:eventbus:3.1.1'
debugImplementation 'com.airbnb.okreplay:okreplay:1.5.0'
releaseImplementation 'com.airbnb.okreplay:noop:1.5.0'
androidTestImplementation 'com.airbnb.okreplay:espresso:1.5.0'
testImplementation 'junit:junit:4.12'
testImplementation 'org.robolectric:robolectric:4.0.2'
testImplementation 'org.robolectric:robolectric:4.3'
//testImplementation 'org.robolectric:shadows-support-v4:3.0'
testImplementation "io.mockk:mockk:1.8.13.kotlin13"
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
testImplementation 'io.mockk:mockk:1.9.2.kotlin12'
testImplementation 'org.amshove.kluent:kluent-android:1.44'
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
@ -156,8 +166,9 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
androidTestImplementation 'org.amshove.kluent:kluent-android:1.44'
androidTestImplementation "io.mockk:mockk-android:1.8.13.kotlin13"
androidTestImplementation "androidx.arch.core:core-testing:$lifecycle_version"
// Note: version sticks to 1.9.2 due to https://github.com/mockk/mockk/issues/281
androidTestImplementation 'io.mockk:mockk-android:1.9.2.kotlin12'
androidTestImplementation "androidx.arch.core:core-testing:$arch_version"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
}

View File

@ -17,15 +17,16 @@
package im.vector.matrix.android
import android.content.Context
import androidx.test.InstrumentationRegistry
import androidx.test.core.app.ApplicationProvider
import java.io.File
interface InstrumentedTest {
fun context(): Context {
return InstrumentationRegistry.getTargetContext()
return ApplicationProvider.getApplicationContext()
}
fun cacheDir(): File {
return context().cacheDir
}
}
}

View File

@ -29,4 +29,4 @@ class OkReplayRuleChainNoActivity(
return RuleChain.outerRule(PermissionRule(configuration))
.around(RecorderRule(configuration))
}
}
}

View File

@ -18,5 +18,8 @@ package im.vector.matrix.android
import im.vector.matrix.android.internal.util.MatrixCoroutineDispatchers
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.Executors
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main, Main)
internal val testCoroutineDispatchers = MatrixCoroutineDispatchers(Main, Main, Main, Main,
Executors.newSingleThreadExecutor().asCoroutineDispatcher())

View File

@ -0,0 +1,61 @@
/*
* 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.account
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.common.SessionTestParams
import im.vector.matrix.android.common.TestConstants
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.junit.runners.MethodSorters
@RunWith(JUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class AccountCreationTest : InstrumentedTest {
private val commonTestHelper = CommonTestHelper(context())
private val cryptoTestHelper = CryptoTestHelper(commonTestHelper)
@Test
fun createAccountTest() {
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
commonTestHelper.signOutAndClose(session)
}
@Test
fun createAccountAndLoginAgainTest() {
val session = commonTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(withInitialSync = true))
// Log again to the same account
val session2 = commonTestHelper.logIntoAccount(session.myUserId, SessionTestParams(withInitialSync = true))
commonTestHelper.signOutAndClose(session)
commonTestHelper.signOutAndClose(session2)
}
@Test
fun simpleE2eTest() {
val res = cryptoTestHelper.doE2ETestWithAliceInARoom()
res.cleanUp(commonTestHelper)
}
}

View File

@ -1,64 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.auth
import androidx.test.annotation.UiThreadTest
import androidx.test.rule.GrantPermissionRule
import androidx.test.runner.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.OkReplayRuleChainNoActivity
import im.vector.matrix.android.api.auth.Authenticator
import okreplay.*
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
internal class AuthenticatorTest : InstrumentedTest {
lateinit var authenticator: Authenticator
lateinit var okReplayInterceptor: OkReplayInterceptor
private val okReplayConfig = OkReplayConfig.Builder()
.tapeRoot(AndroidTapeRoot(
context(), javaClass))
.defaultMode(TapeMode.READ_WRITE) // or TapeMode.READ_ONLY
.sslEnabled(true)
.interceptor(okReplayInterceptor)
.build()
@get:Rule
val testRule = OkReplayRuleChainNoActivity(okReplayConfig).get()
@Test
@UiThreadTest
@OkReplay(tape = "auth", mode = TapeMode.READ_WRITE)
fun auth() {
}
companion object {
@ClassRule
@JvmField
val grantExternalStoragePermissionRule: GrantPermissionRule =
GrantPermissionRule.grant(android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
}
}

View File

@ -0,0 +1,301 @@
/*
* Copyright 2016 OpenMarket Ltd
* Copyright 2018 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.common
import android.content.Context
import android.net.Uri
import androidx.lifecycle.Observer
import im.vector.matrix.android.api.Matrix
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.MatrixConfiguration
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.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.timeline.Timeline
import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
import im.vector.matrix.android.api.session.room.timeline.TimelineSettings
import im.vector.matrix.android.api.session.sync.SyncState
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import java.util.ArrayList
import java.util.UUID
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
/**
* This class exposes methods to be used in common cases
* Registration, login, Sync, Sending messages...
*/
class CommonTestHelper(context: Context) {
val matrix: Matrix
init {
Matrix.initialize(context, MatrixConfiguration("TestFlavor"))
matrix = Matrix.getInstance(context)
}
fun createAccount(userNamePrefix: String, testParams: SessionTestParams): Session {
return createAccount(userNamePrefix, TestConstants.PASSWORD, testParams)
}
fun logIntoAccount(userId: String, testParams: SessionTestParams): Session {
return logIntoAccount(userId, TestConstants.PASSWORD, testParams)
}
/**
* Create a Home server configuration, with Http connection allowed for test
*/
fun createHomeServerConfig(): HomeServerConnectionConfig {
return HomeServerConnectionConfig.Builder()
.withHomeServerUri(Uri.parse(TestConstants.TESTS_HOME_SERVER_URL))
.build()
}
/**
* This methods init the event stream and check for initial sync
*
* @param session the session to sync
*/
fun syncSession(session: Session) {
val lock = CountDownLatch(1)
session.open()
session.startSync(true)
val syncLiveData = runBlocking(Dispatchers.Main) {
session.getSyncStateLive()
}
val syncObserver = object : Observer<SyncState> {
override fun onChanged(t: SyncState?) {
if (session.hasAlreadySynced()) {
lock.countDown()
syncLiveData.removeObserver(this)
}
}
}
GlobalScope.launch(Dispatchers.Main) { syncLiveData.observeForever(syncObserver) }
await(lock)
}
/**
* Sends text messages in a room
*
* @param room the room where to send the messages
* @param message the message to send
* @param nbOfMessages the number of time the message will be sent
*/
fun sendTextMessage(room: Room, message: String, nbOfMessages: Int): List<TimelineEvent> {
val sentEvents = ArrayList<TimelineEvent>(nbOfMessages)
val latch = CountDownLatch(nbOfMessages)
val timelineListener = object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
}
override fun onNewTimelineEvents(eventIds: List<String>) {
// noop
}
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
val newMessages = snapshot
.filter { LocalEcho.isLocalEchoId(it.eventId).not() }
.filter { it.root.getClearType() == EventType.MESSAGE }
.filter { it.root.getClearContent().toModel<MessageContent>()?.body?.startsWith(message) == true }
if (newMessages.size == nbOfMessages) {
sentEvents.addAll(newMessages)
latch.countDown()
}
}
}
val timeline = room.createTimeline(null, TimelineSettings(10))
timeline.start()
timeline.addListener(timelineListener)
for (i in 0 until nbOfMessages) {
room.sendTextMessage(message + " #" + (i + 1))
}
await(latch)
timeline.removeListener(timelineListener)
timeline.dispose()
// Check that all events has been created
assertEquals(nbOfMessages.toLong(), sentEvents.size.toLong())
return sentEvents
}
// PRIVATE METHODS *****************************************************************************
/**
* Creates a unique account
*
* @param userNamePrefix the user name prefix
* @param password the password
* @param testParams test params about the session
* @return the session associated with the newly created account
*/
private fun createAccount(userNamePrefix: String,
password: String,
testParams: SessionTestParams): Session {
val session = createAccountAndSync(
userNamePrefix + "_" + System.currentTimeMillis() + UUID.randomUUID(),
password,
testParams
)
assertNotNull(session)
return session
}
/**
* Logs into an existing account
*
* @param userId the userId to log in
* @param password the password to log in
* @param testParams test params about the session
* @return the session associated with the existing account
*/
private fun logIntoAccount(userId: String,
password: String,
testParams: SessionTestParams): Session {
val session = logAccountAndSync(userId, password, testParams)
assertNotNull(session)
return session
}
/**
* Create an account and a dedicated session
*
* @param userName the account username
* @param password the password
* @param sessionTestParams parameters for the test
*/
private fun createAccountAndSync(userName: String,
password: String,
sessionTestParams: SessionTestParams): Session {
val hs = createHomeServerConfig()
doSync<LoginFlowResult> {
matrix.authenticationService
.getLoginFlow(hs, it)
}
doSync<RegistrationResult> {
matrix.authenticationService
.getRegistrationWizard()
.createAccount(userName, password, null, it)
}
// Preform dummy step
val registrationResult = doSync<RegistrationResult> {
matrix.authenticationService
.getRegistrationWizard()
.dummy(it)
}
assertTrue(registrationResult is RegistrationResult.Success)
val session = (registrationResult as RegistrationResult.Success).session
if (sessionTestParams.withInitialSync) {
syncSession(session)
}
return session
}
/**
* Start an account login
*
* @param userName the account username
* @param password the password
* @param sessionTestParams session test params
*/
private fun logAccountAndSync(userName: String,
password: String,
sessionTestParams: SessionTestParams): Session {
val hs = createHomeServerConfig()
doSync<LoginFlowResult> {
matrix.authenticationService
.getLoginFlow(hs, it)
}
val session = doSync<Session> {
matrix.authenticationService
.getLoginWizard()
.login(userName, password, "myDevice", it)
}
if (sessionTestParams.withInitialSync) {
syncSession(session)
}
return session
}
/**
* Await for a latch and ensure the result is true
*
* @param latch
* @throws InterruptedException
*/
fun await(latch: CountDownLatch) {
assertTrue(latch.await(TestConstants.timeOutMillis, TimeUnit.MILLISECONDS))
}
// Transform a method with a MatrixCallback to a synchronous method
inline fun <reified T> doSync(block: (MatrixCallback<T>) -> Unit): T {
val lock = CountDownLatch(1)
var result: T? = null
val callback = object : TestMatrixCallback<T>(lock) {
override fun onSuccess(data: T) {
result = data
super.onSuccess(data)
}
}
block.invoke(callback)
await(lock)
assertNotNull(result)
return result!!
}
/**
* Clear all provided sessions
*/
fun Iterable<Session>.signOutAndClose() = forEach { signOutAndClose(it) }
fun signOutAndClose(session: Session) {
doSync<Unit> { session.signOut(true, it) }
session.close()
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2018 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.common
import im.vector.matrix.android.api.session.Session
data class CryptoTestData(val firstSession: Session,
val roomId: String,
val secondSession: Session? = null,
val thirdSession: Session? = null) {
fun cleanUp(testHelper: CommonTestHelper) {
testHelper.signOutAndClose(firstSession)
secondSession?.let { testHelper.signOutAndClose(it) }
thirdSession?.let { testHelper.signOutAndClose(it) }
}
}

View File

@ -0,0 +1,302 @@
/*
* Copyright 2018 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.common
import android.os.SystemClock
import androidx.lifecycle.Observer
import im.vector.matrix.android.api.session.Session
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.toContent
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomSummary
import im.vector.matrix.android.api.session.room.model.create.CreateRoomParams
import im.vector.matrix.android.api.session.room.roomSummaryQueryParams
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
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM
import im.vector.matrix.android.internal.crypto.MXCRYPTO_ALGORITHM_MEGOLM_BACKUP
import im.vector.matrix.android.internal.crypto.keysbackup.model.MegolmBackupAuthData
import im.vector.matrix.android.internal.crypto.keysbackup.model.MegolmBackupCreationInfo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import java.util.HashMap
import java.util.concurrent.CountDownLatch
class CryptoTestHelper(private val mTestHelper: CommonTestHelper) {
private val messagesFromAlice: List<String> = listOf("0 - Hello I'm Alice!", "4 - Go!")
private val messagesFromBob: List<String> = listOf("1 - Hello I'm Bob!", "2 - Isn't life grand?", "3 - Let's go to the opera.")
private val defaultSessionParams = SessionTestParams(true)
/**
* @return alice session
*/
fun doE2ETestWithAliceInARoom(): 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)!!
mTestHelper.doSync<Unit> {
room.enableEncryption(callback = it)
}
return CryptoTestData(aliceSession, roomId)
}
/**
* @return alice and bob sessions
*/
fun doE2ETestWithAliceAndBobInARoom(): CryptoTestData {
val cryptoTestData = doE2ETestWithAliceInARoom()
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
val aliceRoom = aliceSession.getRoom(aliceRoomId)!!
val bobSession = mTestHelper.createAccount(TestConstants.USER_BOB, defaultSessionParams)
val lock1 = CountDownLatch(1)
val bobRoomSummariesLive = runBlocking(Dispatchers.Main) {
bobSession.getRoomSummariesLive(roomSummaryQueryParams { })
}
val newRoomObserver = object : Observer<List<RoomSummary>> {
override fun onChanged(t: List<RoomSummary>?) {
if (t?.isNotEmpty() == true) {
lock1.countDown()
bobRoomSummariesLive.removeObserver(this)
}
}
}
GlobalScope.launch(Dispatchers.Main) {
bobRoomSummariesLive.observeForever(newRoomObserver)
}
mTestHelper.doSync<Unit> {
aliceRoom.invite(bobSession.myUserId, callback = it)
}
mTestHelper.await(lock1)
val lock = CountDownLatch(1)
val roomJoinedObserver = object : Observer<List<RoomSummary>> {
override fun onChanged(t: List<RoomSummary>?) {
if (bobSession.getRoom(aliceRoomId)
?.getRoomMember(aliceSession.myUserId)
?.membership == Membership.JOIN) {
lock.countDown()
bobRoomSummariesLive.removeObserver(this)
}
}
}
GlobalScope.launch(Dispatchers.Main) {
bobRoomSummariesLive.observeForever(roomJoinedObserver)
}
mTestHelper.doSync<Unit> { bobSession.joinRoom(aliceRoomId, callback = it) }
mTestHelper.await(lock)
// Ensure bob can send messages to the room
// val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!!
// assertNotNull(roomFromBobPOV.powerLevels)
// assertTrue(roomFromBobPOV.powerLevels.maySendMessage(bobSession.myUserId))
return CryptoTestData(aliceSession, aliceRoomId, bobSession)
}
/**
* @return Alice, Bob and Sam session
*/
fun doE2ETestWithAliceAndBobAndSamInARoom(): CryptoTestData {
val statuses = HashMap<String, String>()
val cryptoTestData = doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
val room = aliceSession.getRoom(aliceRoomId)!!
val samSession = mTestHelper.createAccount(TestConstants.USER_SAM, defaultSessionParams)
val lock1 = CountDownLatch(2)
// val samEventListener = object : MXEventListener() {
// override fun onNewRoom(roomId: String) {
// if (TextUtils.equals(roomId, aliceRoomId)) {
// if (!statuses.containsKey("onNewRoom")) {
// statuses["onNewRoom"] = "onNewRoom"
// lock1.countDown()
// }
// }
// }
// }
//
// samSession.dataHandler.addListener(samEventListener)
room.invite(samSession.myUserId, null, object : TestMatrixCallback<Unit>(lock1) {
override fun onSuccess(data: Unit) {
statuses["invite"] = "invite"
super.onSuccess(data)
}
})
mTestHelper.await(lock1)
assertTrue(statuses.containsKey("invite") && statuses.containsKey("onNewRoom"))
// samSession.dataHandler.removeListener(samEventListener)
val lock2 = CountDownLatch(1)
samSession.joinRoom(aliceRoomId, null, object : TestMatrixCallback<Unit>(lock2) {
override fun onSuccess(data: Unit) {
statuses["joinRoom"] = "joinRoom"
super.onSuccess(data)
}
})
mTestHelper.await(lock2)
assertTrue(statuses.containsKey("joinRoom"))
// wait the initial sync
SystemClock.sleep(1000)
// samSession.dataHandler.removeListener(samEventListener)
return CryptoTestData(aliceSession, aliceRoomId, cryptoTestData.secondSession, samSession)
}
/**
* @return Alice and Bob sessions
*/
fun doE2ETestWithAliceAndBobInARoomWithEncryptedMessages(): CryptoTestData {
val cryptoTestData = doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val aliceRoomId = cryptoTestData.roomId
val bobSession = cryptoTestData.secondSession!!
bobSession.cryptoService().setWarnOnUnknownDevices(false)
aliceSession.cryptoService().setWarnOnUnknownDevices(false)
val roomFromBobPOV = bobSession.getRoom(aliceRoomId)!!
val roomFromAlicePOV = aliceSession.getRoom(aliceRoomId)!!
val lock = CountDownLatch(1)
val bobEventsListener = object : Timeline.Listener {
override fun onTimelineFailure(throwable: Throwable) {
// noop
}
override fun onNewTimelineEvents(eventIds: List<String>) {
// noop
}
override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
val messages = snapshot.filter { it.root.getClearType() == EventType.MESSAGE }
.groupBy { it.root.senderId!! }
// Alice has sent 2 messages and Bob has sent 3 messages
if (messages[aliceSession.myUserId]?.size == 2 && messages[bobSession.myUserId]?.size == 3) {
lock.countDown()
}
}
}
val bobTimeline = roomFromBobPOV.createTimeline(null, TimelineSettings(20))
bobTimeline.start()
bobTimeline.addListener(bobEventsListener)
// Alice sends a message
roomFromAlicePOV.sendTextMessage(messagesFromAlice[0])
// Bob send 3 messages
roomFromBobPOV.sendTextMessage(messagesFromBob[0])
roomFromBobPOV.sendTextMessage(messagesFromBob[1])
roomFromBobPOV.sendTextMessage(messagesFromBob[2])
// Alice sends a message
roomFromAlicePOV.sendTextMessage(messagesFromAlice[1])
mTestHelper.await(lock)
bobTimeline.removeListener(bobEventsListener)
bobTimeline.dispose()
return cryptoTestData
}
fun checkEncryptedEvent(event: Event, roomId: String, clearMessage: String, senderSession: Session) {
assertEquals(EventType.ENCRYPTED, event.type)
assertNotNull(event.content)
val eventWireContent = event.content.toContent()
assertNotNull(eventWireContent)
assertNull(eventWireContent.get("body"))
assertEquals(MXCRYPTO_ALGORITHM_MEGOLM, eventWireContent.get("algorithm"))
assertNotNull(eventWireContent.get("ciphertext"))
assertNotNull(eventWireContent.get("session_id"))
assertNotNull(eventWireContent.get("sender_key"))
assertEquals(senderSession.sessionParams.credentials.deviceId, eventWireContent.get("device_id"))
assertNotNull(event.eventId)
assertEquals(roomId, event.roomId)
assertEquals(EventType.MESSAGE, event.getClearType())
// TODO assertTrue(event.getAge() < 10000)
val eventContent = event.toContent()
assertNotNull(eventContent)
assertEquals(clearMessage, eventContent.get("body"))
assertEquals(senderSession.myUserId, event.senderId)
}
fun createFakeMegolmBackupAuthData(): MegolmBackupAuthData {
return MegolmBackupAuthData(
publicKey = "abcdefg",
signatures = mapOf("something" to mapOf("ed25519:something" to "hijklmnop"))
)
}
fun createFakeMegolmBackupCreationInfo(): MegolmBackupCreationInfo {
return MegolmBackupCreationInfo(
algorithm = MXCRYPTO_ALGORITHM_MEGOLM_BACKUP,
authData = createFakeMegolmBackupAuthData()
)
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.common
import okhttp3.Interceptor
import okhttp3.Protocol
import okhttp3.Request
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import javax.net.ssl.HttpsURLConnection
/**
* Allows to intercept network requests for test purpose by
* - re-writing the response
* - changing the response code (200/404/etc..).
* - Test delays..
*
* Basic usage:
* <code>
* val mockInterceptor = MockOkHttpInterceptor()
* mockInterceptor.addRule(MockOkHttpInterceptor.SimpleRule(".well-known/matrix/client", 200, "{}"))
*
* RestHttpClientFactoryProvider.defaultProvider = RestClientHttpClientFactory(mockInterceptor)
* AutoDiscovery().findClientConfig("matrix.org", <callback>)
* </code>
*/
class MockOkHttpInterceptor : Interceptor {
private var rules: ArrayList<Rule> = ArrayList()
fun addRule(rule: Rule) {
rules.add(rule)
}
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
rules.forEach { rule ->
if (originalRequest.url.toString().contains(rule.match)) {
rule.process(originalRequest)?.let {
return it
}
}
}
return chain.proceed(originalRequest)
}
abstract class Rule(val match: String) {
abstract fun process(originalRequest: Request): Response?
}
/**
* Simple rule that reply with the given body for any request that matches the match param
*/
class SimpleRule(match: String,
private val code: Int = HttpsURLConnection.HTTP_OK,
private val body: String = "{}") : Rule(match) {
override fun process(originalRequest: Request): Response? {
return Response.Builder()
.protocol(Protocol.HTTP_1_1)
.request(originalRequest)
.message("mocked answer")
.body(body.toResponseBody(null))
.code(code)
.build()
}
}
}

View File

@ -0,0 +1,19 @@
/*
* Copyright 2018 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.common
data class SessionTestParams @JvmOverloads constructor(val withInitialSync: Boolean = false)

View File

@ -0,0 +1,75 @@
/*
* Copyright 2018 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.common
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.fail
/**
* Compare two lists and their content
*/
fun assertListEquals(list1: List<Any>?, list2: List<Any>?) {
if (list1 == null) {
assertNull(list2)
} else {
assertNotNull(list2)
assertEquals("List sizes must match", list1.size, list2!!.size)
for (i in list1.indices) {
assertEquals("Elements at index $i are not equal", list1[i], list2[i])
}
}
}
/**
* Compare two maps and their content
*/
fun assertDictEquals(dict1: Map<String, Any>?, dict2: Map<String, Any>?) {
if (dict1 == null) {
assertNull(dict2)
} else {
assertNotNull(dict2)
assertEquals("Map sizes must match", dict1.size, dict2!!.size)
for (i in dict1.keys) {
assertEquals("Values for key $i are not equal", dict1[i], dict2[i])
}
}
}
/**
* Compare two byte arrays content.
* Note that if the arrays have not the same size, it also fails.
*/
fun assertByteArrayNotEqual(a1: ByteArray, a2: ByteArray) {
if (a1.size != a2.size) {
fail("Arrays have not the same size.")
}
for (index in a1.indices) {
if (a1[index] != a2[index]) {
// Difference found!
return
}
}
fail("Arrays are equals.")
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2018 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.common
import android.os.Debug
object TestConstants {
const val TESTS_HOME_SERVER_URL = "http://10.0.2.2:8080"
// Time out to use when waiting for server response. 10s
private const val AWAIT_TIME_OUT_MILLIS = 10_000
// Time out to use when waiting for server response, when the debugger is connected. 10 minutes
private const val AWAIT_TIME_OUT_WITH_DEBUGGER_MILLIS = 10 * 60_000
const val USER_ALICE = "Alice"
const val USER_BOB = "Bob"
const val USER_SAM = "Sam"
const val PASSWORD = "password"
val timeOutMillis: Long
get() = if (Debug.isDebuggerConnected()) {
// Wait more
AWAIT_TIME_OUT_WITH_DEBUGGER_MILLIS.toLong()
} else {
AWAIT_TIME_OUT_MILLIS.toLong()
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2018 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.common
import androidx.annotation.CallSuper
import im.vector.matrix.android.api.MatrixCallback
import org.junit.Assert.fail
import timber.log.Timber
import java.util.concurrent.CountDownLatch
/**
* Simple implementation of MatrixCallback, which count down the CountDownLatch on each API callback
* @param onlySuccessful true to fail if an error occurs. This is the default behavior
* @param <T>
*/
open class TestMatrixCallback<T>(private val countDownLatch: CountDownLatch,
private val onlySuccessful: Boolean = true) : MatrixCallback<T> {
@CallSuper
override fun onSuccess(data: T) {
countDownLatch.countDown()
}
@CallSuper
override fun onFailure(failure: Throwable) {
Timber.e(failure, "TestApiCallback")
if (onlySuccessful) {
fail("onFailure " + failure.localizedMessage)
}
countDownLatch.countDown()
}
}

View File

@ -0,0 +1,148 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.crypto
import android.os.MemoryFile
import android.util.Base64
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.internal.crypto.attachments.MXEncryptedAttachments
import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileInfo
import im.vector.matrix.android.internal.crypto.model.rest.EncryptedFileKey
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNotNull
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import java.io.ByteArrayInputStream
import java.io.InputStream
/**
* Unit tests AttachmentEncryptionTest.
*/
@Suppress("SpellCheckingInspection")
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class AttachmentEncryptionTest {
private fun checkDecryption(input: String, encryptedFileInfo: EncryptedFileInfo): String {
val `in` = Base64.decode(input, Base64.DEFAULT)
val inputStream: InputStream
inputStream = if (`in`.isEmpty()) {
ByteArrayInputStream(`in`)
} else {
val memoryFile = MemoryFile("file" + System.currentTimeMillis(), `in`.size)
memoryFile.outputStream.write(`in`)
memoryFile.inputStream
}
val decryptedStream = MXEncryptedAttachments.decryptAttachment(inputStream, encryptedFileInfo)
assertNotNull(decryptedStream)
val buffer = ByteArray(100)
val len = decryptedStream!!.read(buffer)
decryptedStream.close()
return Base64.encodeToString(buffer, 0, len, Base64.DEFAULT).replace("\n".toRegex(), "").replace("=".toRegex(), "")
}
@Test
fun checkDecrypt1() {
val encryptedFileInfo = EncryptedFileInfo(
v = "v2",
hashes = mapOf("sha256" to "47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU"),
key = EncryptedFileKey(
alg = "A256CTR",
k = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
key_ops = listOf("encrypt", "decrypt"),
kty = "oct",
ext = true
),
iv = "AAAAAAAAAAAAAAAAAAAAAA",
url = "dummyUrl"
)
assertEquals("", checkDecryption("", encryptedFileInfo))
}
@Test
fun checkDecrypt2() {
val encryptedFileInfo = EncryptedFileInfo(
v = "v2",
hashes = mapOf("sha256" to "YzF08lARDdOCzJpzuSwsjTNlQc4pHxpdHcXiD/wpK6k"),
key = EncryptedFileKey(
alg = "A256CTR",
k = "__________________________________________8",
key_ops = listOf("encrypt", "decrypt"),
kty = "oct",
ext = true
),
iv = "//////////8AAAAAAAAAAA",
url = "dummyUrl"
)
assertEquals("SGVsbG8sIFdvcmxk", checkDecryption("5xJZTt5cQicm+9f4", encryptedFileInfo))
}
@Test
fun checkDecrypt3() {
val encryptedFileInfo = EncryptedFileInfo(
v = "v2",
hashes = mapOf("sha256" to "IOq7/dHHB+mfHfxlRY5XMeCWEwTPmlf4cJcgrkf6fVU"),
key = EncryptedFileKey(
alg = "A256CTR",
k = "__________________________________________8",
key_ops = listOf("encrypt", "decrypt"),
kty = "oct",
ext = true
),
iv = "//////////8AAAAAAAAAAA",
url = "dummyUrl"
)
assertEquals("YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ",
checkDecryption("zhtFStAeFx0s+9L/sSQO+WQMtldqYEHqTxMduJrCIpnkyer09kxJJuA4K+adQE4w+7jZe/vR9kIcqj9rOhDR8Q",
encryptedFileInfo))
}
@Test
fun checkDecrypt4() {
val encryptedFileInfo = EncryptedFileInfo(
v = "v2",
hashes = mapOf("sha256" to "LYG/orOViuFwovJpv2YMLSsmVKwLt7pY3f8SYM7KU5E"),
key = EncryptedFileKey(
alg = "A256CTR",
k = "__________________________________________8",
key_ops = listOf("encrypt", "decrypt"),
kty = "oct",
ext = true
),
iv = "/////////////////////w",
url = "dummyUrl"
)
assertNotEquals("YWxwaGFudW1lcmljYWxseWFscGhhbnVtZXJpY2FsbHlhbHBoYW51bWVyaWNhbGx5YWxwaGFudW1lcmljYWxseQ",
checkDecryption("tJVNBVJ/vl36UQt4Y5e5m84bRUrQHhcdLPvS/7EkDvlkDLZXamBB6k8THbiawiKZ5Mnq9PZMSSbgOCvmnUBOMA",
encryptedFileInfo))
}
}

View File

@ -21,7 +21,7 @@ import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStore
import im.vector.matrix.android.internal.crypto.store.db.RealmCryptoStoreModule
import io.realm.RealmConfiguration
import java.util.*
import kotlin.random.Random
internal class CryptoStoreHelper {
@ -35,10 +35,10 @@ internal class CryptoStoreHelper {
}
fun createCredential() = Credentials(
userId = "userId_" + Random().nextInt(),
userId = "userId_" + Random.nextInt(),
homeServer = "http://matrix.org",
accessToken = "access_token",
refreshToken = null,
deviceId = "deviceId_sample"
)
}
}

View File

@ -16,20 +16,35 @@
package im.vector.matrix.android.internal.crypto
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.internal.crypto.model.OlmSessionWrapper
import im.vector.matrix.android.internal.crypto.store.IMXCryptoStore
import org.junit.Assert.*
import io.realm.Realm
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.matrix.olm.OlmAccount
import org.matrix.olm.OlmManager
import org.matrix.olm.OlmSession
private const val DUMMY_DEVICE_KEY = "DeviceKey"
class CryptoStoreTest {
@RunWith(AndroidJUnit4::class)
class CryptoStoreTest : InstrumentedTest {
private val cryptoStoreHelper = CryptoStoreHelper()
@Before
fun setup() {
Realm.init(context())
}
@Test
fun test_metadata_realm_ok() {
val cryptoStore: IMXCryptoStore = cryptoStoreHelper.createStore()
@ -114,4 +129,4 @@ class CryptoStoreTest {
olmAccount1.releaseAccount()
olmAccount2.releaseAccount()
}
}
}

View File

@ -0,0 +1,208 @@
/*
* Copyright 2018 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.crypto
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
/**
* Unit tests ExportEncryptionTest.
*/
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class ExportEncryptionTest {
@Test
fun checkExportError1() {
val password = "password"
val input = "-----"
var failed = false
try {
MXMegolmExportEncryption.decryptMegolmKeyFile(input.toByteArray(charset("UTF-8")), password)
} catch (e: Exception) {
failed = true
}
assertTrue(failed)
}
@Test
fun checkExportError2() {
val password = "password"
val input = "-----BEGIN MEGOLM SESSION DATA-----\n" + "-----"
var failed = false
try {
MXMegolmExportEncryption.decryptMegolmKeyFile(input.toByteArray(charset("UTF-8")), password)
} catch (e: Exception) {
failed = true
}
assertTrue(failed)
}
@Test
fun checkExportError3() {
val password = "password"
val input = "-----BEGIN MEGOLM SESSION DATA-----\n" +
" AXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" +
" cissyYBxjsfsAn\n" +
" -----END MEGOLM SESSION DATA-----"
var failed = false
try {
MXMegolmExportEncryption.decryptMegolmKeyFile(input.toByteArray(charset("UTF-8")), password)
} catch (e: Exception) {
failed = true
}
assertTrue(failed)
}
@Test
fun checkExportDecrypt1() {
val password = "password"
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXNhbHRzYWx0c2FsdHNhbHSIiIiIiIiIiIiIiIiIiIiIAAAACmIRUW2OjZ3L2l6j9h0lHlV3M2dx\n" + "cissyYBxjsfsAndErh065A8=\n-----END MEGOLM SESSION DATA-----"
val expectedString = "plain"
var decodedString: String? = null
try {
decodedString = MXMegolmExportEncryption.decryptMegolmKeyFile(input.toByteArray(charset("UTF-8")), password)
} catch (e: Exception) {
fail("## checkExportDecrypt1() failed : " + e.message)
}
assertEquals("## checkExportDecrypt1() : expectedString $expectedString -- decodedString $decodedString",
expectedString,
decodedString)
}
@Test
fun checkExportDecrypt2() {
val password = "betterpassword"
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAW1vcmVzYWx0bW9yZXNhbHT//////////wAAAAAAAAAAAAAD6KyBpe1Niv5M5NPm4ZATsJo5nghk\n" + "KYu63a0YQ5DRhUWEKk7CcMkrKnAUiZny\n-----END MEGOLM SESSION DATA-----"
val expectedString = "Hello, World"
var decodedString: String? = null
try {
decodedString = MXMegolmExportEncryption.decryptMegolmKeyFile(input.toByteArray(charset("UTF-8")), password)
} catch (e: Exception) {
fail("## checkExportDecrypt2() failed : " + e.message)
}
assertEquals("## checkExportDecrypt2() : expectedString $expectedString -- decodedString $decodedString",
expectedString,
decodedString)
}
@Test
fun checkExportDecrypt3() {
val password = "SWORDFISH"
val input = "-----BEGIN MEGOLM SESSION DATA-----\nAXllc3NhbHR5Z29vZG5lc3P//////////wAAAAAAAAAAAAAD6OIW+Je7gwvjd4kYrb+49gKCfExw\n" + "MgJBMD4mrhLkmgAngwR1pHjbWXaoGybtiAYr0moQ93GrBQsCzPbvl82rZhaXO3iH5uHo/RCEpOqp\nPgg29363BGR+/Ripq/VCLKGNbw==\n-----END MEGOLM SESSION DATA-----"
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
var decodedString: String? = null
try {
decodedString = MXMegolmExportEncryption.decryptMegolmKeyFile(input.toByteArray(charset("UTF-8")), password)
} catch (e: Exception) {
fail("## checkExportDecrypt3() failed : " + e.message)
}
assertEquals("## checkExportDecrypt3() : expectedString $expectedString -- decodedString $decodedString",
expectedString,
decodedString)
}
@Test
fun checkExportEncrypt1() {
val password = "password"
val expectedString = "plain"
var decodedString: String? = null
try {
decodedString = MXMegolmExportEncryption
.decryptMegolmKeyFile(MXMegolmExportEncryption.encryptMegolmKeyFile(expectedString, password, 1000), password)
} catch (e: Exception) {
fail("## checkExportEncrypt1() failed : " + e.message)
}
assertEquals("## checkExportEncrypt1() : expectedString $expectedString -- decodedString $decodedString",
expectedString,
decodedString)
}
@Test
fun checkExportEncrypt2() {
val password = "betterpassword"
val expectedString = "Hello, World"
var decodedString: String? = null
try {
decodedString = MXMegolmExportEncryption
.decryptMegolmKeyFile(MXMegolmExportEncryption.encryptMegolmKeyFile(expectedString, password, 1000), password)
} catch (e: Exception) {
fail("## checkExportEncrypt2() failed : " + e.message)
}
assertEquals("## checkExportEncrypt2() : expectedString $expectedString -- decodedString $decodedString",
expectedString,
decodedString)
}
@Test
fun checkExportEncrypt3() {
val password = "SWORDFISH"
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
var decodedString: String? = null
try {
decodedString = MXMegolmExportEncryption
.decryptMegolmKeyFile(MXMegolmExportEncryption.encryptMegolmKeyFile(expectedString, password, 1000), password)
} catch (e: Exception) {
fail("## checkExportEncrypt3() failed : " + e.message)
}
assertEquals("## checkExportEncrypt3() : expectedString $expectedString -- decodedString $decodedString",
expectedString,
decodedString)
}
@Test
fun checkExportEncrypt4() {
val password = "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword" + "passwordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpasswordpassword"
val expectedString = "alphanumericallyalphanumericallyalphanumericallyalphanumerically"
var decodedString: String? = null
try {
decodedString = MXMegolmExportEncryption
.decryptMegolmKeyFile(MXMegolmExportEncryption.encryptMegolmKeyFile(expectedString, password, 1000), password)
} catch (e: Exception) {
fail("## checkExportEncrypt4() failed : " + e.message)
}
assertEquals("## checkExportEncrypt4() : expectedString $expectedString -- decodedString $decodedString",
expectedString,
decodedString)
}
}

View File

@ -0,0 +1,38 @@
/*
* 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.crypto.crosssigning
import org.amshove.kluent.shouldBeNull
import org.amshove.kluent.shouldBeTrue
import org.junit.Test
@Suppress("SpellCheckingInspection")
class ExtensionsKtTest {
@Test
fun testComparingBase64StringWithOrWithoutPadding() {
// Without padding
"NMJyumnhMic".fromBase64().contentEquals("NMJyumnhMic".fromBase64()).shouldBeTrue()
// With padding
"NMJyumnhMic".fromBase64().contentEquals("NMJyumnhMic=".fromBase64()).shouldBeTrue()
}
@Test
fun testBadBase64() {
"===".fromBase64Safe().shouldBeNull()
}
}

View File

@ -0,0 +1,161 @@
package im.vector.matrix.android.internal.crypto.crosssigning
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.common.SessionTestParams
import im.vector.matrix.android.common.TestConstants
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class XSigningTest : InstrumentedTest {
private val mTestHelper = CommonTestHelper(context())
private val mCryptoTestHelper = CryptoTestHelper(mTestHelper)
@Test
fun test_InitializeAndStoreKeys() {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
mTestHelper.doSync<Unit> {
aliceSession.cryptoService().crossSigningService()
.initializeCrossSigning(UserPasswordAuth(
user = aliceSession.myUserId,
password = TestConstants.PASSWORD
), it)
}
val myCrossSigningKeys = aliceSession.cryptoService().crossSigningService().getMyCrossSigningKeys()
val masterPubKey = myCrossSigningKeys?.masterKey()
assertNotNull("Master key should be stored", masterPubKey?.unpaddedBase64PublicKey)
val selfSigningKey = myCrossSigningKeys?.selfSigningKey()
assertNotNull("SelfSigned key should be stored", selfSigningKey?.unpaddedBase64PublicKey)
val userKey = myCrossSigningKeys?.userKey()
assertNotNull("User key should be stored", userKey?.unpaddedBase64PublicKey)
assertTrue("Signing Keys should be trusted", myCrossSigningKeys?.isTrusted() == true)
assertTrue("Signing Keys should be trusted", aliceSession.cryptoService().crossSigningService().checkUserTrust(aliceSession.myUserId).isVerified())
mTestHelper.signOutAndClose(aliceSession)
}
@Test
fun test_CrossSigningCheckBobSeesTheKeys() {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession
val aliceAuthParams = UserPasswordAuth(
user = aliceSession.myUserId,
password = TestConstants.PASSWORD
)
val bobAuthParams = UserPasswordAuth(
user = bobSession!!.myUserId,
password = TestConstants.PASSWORD
)
mTestHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().initializeCrossSigning(aliceAuthParams, it) }
mTestHelper.doSync<Unit> { bobSession.cryptoService().crossSigningService().initializeCrossSigning(bobAuthParams, it) }
// Check that alice can see bob keys
mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { aliceSession.cryptoService().downloadKeys(listOf(bobSession.myUserId), true, it) }
val bobKeysFromAlicePOV = aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobSession.myUserId)
assertNotNull("Alice can see bob Master key", bobKeysFromAlicePOV!!.masterKey())
assertNull("Alice should not see bob User key", bobKeysFromAlicePOV.userKey())
assertNotNull("Alice can see bob SelfSigned key", bobKeysFromAlicePOV.selfSigningKey())
assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV.masterKey()?.unpaddedBase64PublicKey, bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()?.masterKey()?.unpaddedBase64PublicKey)
assertEquals("Bob keys from alice pov should match", bobKeysFromAlicePOV.selfSigningKey()?.unpaddedBase64PublicKey, bobSession.cryptoService().crossSigningService().getMyCrossSigningKeys()?.selfSigningKey()?.unpaddedBase64PublicKey)
assertFalse("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV.isTrusted())
mTestHelper.signOutAndClose(aliceSession)
mTestHelper.signOutAndClose(bobSession)
}
@Test
fun test_CrossSigningTestAliceTrustBobNewDevice() {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession
val aliceAuthParams = UserPasswordAuth(
user = aliceSession.myUserId,
password = TestConstants.PASSWORD
)
val bobAuthParams = UserPasswordAuth(
user = bobSession!!.myUserId,
password = TestConstants.PASSWORD
)
mTestHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().initializeCrossSigning(aliceAuthParams, it) }
mTestHelper.doSync<Unit> { bobSession.cryptoService().crossSigningService().initializeCrossSigning(bobAuthParams, it) }
// Check that alice can see bob keys
val bobUserId = bobSession.myUserId
mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> { aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true, it) }
val bobKeysFromAlicePOV = aliceSession.cryptoService().crossSigningService().getUserCrossSigningKeys(bobUserId)
assertTrue("Bob keys from alice pov should not be trusted", bobKeysFromAlicePOV?.isTrusted() == false)
mTestHelper.doSync<Unit> { aliceSession.cryptoService().crossSigningService().trustUser(bobUserId, it) }
// Now bobs logs in on a new device and verifies it
// 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!!
// Check that bob first session sees the new login
val data = mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {
bobSession.cryptoService().downloadKeys(listOf(bobUserId), true, it)
}
if (data.getUserDeviceIds(bobUserId)?.contains(bobSecondDeviceId) == false) {
fail("Bob should see the new device")
}
val bobSecondDevicePOVFirstDevice = bobSession.cryptoService().getDeviceInfo(bobUserId, bobSecondDeviceId)
assertNotNull("Bob Second device should be known and persisted from first", bobSecondDevicePOVFirstDevice)
// Manually mark it as trusted from first session
mTestHelper.doSync<Unit> {
bobSession.cryptoService().crossSigningService().trustDevice(bobSecondDeviceId, it)
}
// Now alice should cross trust bob's second device
val data2 = mTestHelper.doSync<MXUsersDevicesMap<CryptoDeviceInfo>> {
aliceSession.cryptoService().downloadKeys(listOf(bobUserId), true, it)
}
// check that the device is seen
if (data2.getUserDeviceIds(bobUserId)?.contains(bobSecondDeviceId) == false) {
fail("Alice should see the new device")
}
val result = aliceSession.cryptoService().crossSigningService().checkDeviceTrust(bobUserId, bobSecondDeviceId, null)
assertTrue("Bob second device should be trusted from alice POV", result.isCrossSignedVerified())
mTestHelper.signOutAndClose(aliceSession)
mTestHelper.signOutAndClose(bobSession)
mTestHelper.signOutAndClose(bobSession2)
}
}

View File

@ -0,0 +1,180 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.crypto.keysbackup
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.listeners.ProgressListener
import im.vector.matrix.android.common.assertByteArrayNotEqual
import org.junit.Assert.assertArrayEquals
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.matrix.olm.OlmManager
import org.matrix.olm.OlmPkDecryption
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class KeysBackupPasswordTest : InstrumentedTest {
@Before
fun ensureLibLoaded() {
OlmManager()
}
/**
* Check KeysBackupPassword utilities
*/
@Test
fun passwordConverter_ok() {
val generatePrivateKeyResult = generatePrivateKeyWithPassword(PASSWORD, null)
assertEquals(32, generatePrivateKeyResult.salt.length)
assertEquals(500_000, generatePrivateKeyResult.iterations)
assertEquals(OlmPkDecryption.privateKeyLength(), generatePrivateKeyResult.privateKey.size)
// Reverse operation
val retrievedPrivateKey = retrievePrivateKeyWithPassword(PASSWORD,
generatePrivateKeyResult.salt,
generatePrivateKeyResult.iterations)
assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size)
assertArrayEquals(generatePrivateKeyResult.privateKey, retrievedPrivateKey)
}
/**
* Check generatePrivateKeyWithPassword progress listener behavior
*/
@Test
fun passwordConverter_progress_ok() {
val progressValues = ArrayList<Int>(101)
var lastTotal = 0
generatePrivateKeyWithPassword(PASSWORD, object : ProgressListener {
override fun onProgress(progress: Int, total: Int) {
if (!progressValues.contains(progress)) {
progressValues.add(progress)
}
lastTotal = total
}
})
assertEquals(100, lastTotal)
// Ensure all values are here
assertEquals(101, progressValues.size)
for (i in 0..100) {
assertTrue(progressValues[i] == i)
}
}
/**
* Check KeysBackupPassword utilities, with bad password
*/
@Test
fun passwordConverter_badPassword_ok() {
val generatePrivateKeyResult = generatePrivateKeyWithPassword(PASSWORD, null)
assertEquals(32, generatePrivateKeyResult.salt.length)
assertEquals(500_000, generatePrivateKeyResult.iterations)
assertEquals(OlmPkDecryption.privateKeyLength(), generatePrivateKeyResult.privateKey.size)
// Reverse operation, with bad password
val retrievedPrivateKey = retrievePrivateKeyWithPassword(BAD_PASSWORD,
generatePrivateKeyResult.salt,
generatePrivateKeyResult.iterations)
assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size)
assertByteArrayNotEqual(generatePrivateKeyResult.privateKey, retrievedPrivateKey)
}
/**
* Check KeysBackupPassword utilities, with bad password
*/
@Test
fun passwordConverter_badIteration_ok() {
val generatePrivateKeyResult = generatePrivateKeyWithPassword(PASSWORD, null)
assertEquals(32, generatePrivateKeyResult.salt.length)
assertEquals(500_000, generatePrivateKeyResult.iterations)
assertEquals(OlmPkDecryption.privateKeyLength(), generatePrivateKeyResult.privateKey.size)
// Reverse operation, with bad iteration
val retrievedPrivateKey = retrievePrivateKeyWithPassword(PASSWORD,
generatePrivateKeyResult.salt,
500_001)
assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size)
assertByteArrayNotEqual(generatePrivateKeyResult.privateKey, retrievedPrivateKey)
}
/**
* Check KeysBackupPassword utilities, with bad salt
*/
@Test
fun passwordConverter_badSalt_ok() {
val generatePrivateKeyResult = generatePrivateKeyWithPassword(PASSWORD, null)
assertEquals(32, generatePrivateKeyResult.salt.length)
assertEquals(500_000, generatePrivateKeyResult.iterations)
assertEquals(OlmPkDecryption.privateKeyLength(), generatePrivateKeyResult.privateKey.size)
// Reverse operation, with bad iteration
val retrievedPrivateKey = retrievePrivateKeyWithPassword(PASSWORD,
BAD_SALT,
generatePrivateKeyResult.iterations)
assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size)
assertByteArrayNotEqual(generatePrivateKeyResult.privateKey, retrievedPrivateKey)
}
/**
* Check [retrievePrivateKeyWithPassword] with data coming from another platform (RiotWeb).
*/
@Test
fun passwordConverter_crossPlatform_ok() {
val password = "This is a passphrase!"
val salt = "TO0lxhQ9aYgGfMsclVWPIAublg8h9Nlu"
val iteration = 500_000
val retrievedPrivateKey = retrievePrivateKeyWithPassword(password, salt, iteration)
assertEquals(OlmPkDecryption.privateKeyLength(), retrievedPrivateKey.size)
// Data from RiotWeb
val privateKeyBytes = byteArrayOf(
116.toByte(), 224.toByte(), 229.toByte(), 224.toByte(), 9.toByte(), 3.toByte(), 178.toByte(), 162.toByte(),
120.toByte(), 23.toByte(), 108.toByte(), 218.toByte(), 22.toByte(), 61.toByte(), 241.toByte(), 200.toByte(),
235.toByte(), 173.toByte(), 236.toByte(), 100.toByte(), 115.toByte(), 247.toByte(), 33.toByte(), 132.toByte(),
195.toByte(), 154.toByte(), 64.toByte(), 158.toByte(), 184.toByte(), 148.toByte(), 20.toByte(), 85.toByte())
assertArrayEquals(privateKeyBytes, retrievedPrivateKey)
}
companion object {
private const val PASSWORD = "password"
private const val BAD_PASSWORD = "passw0rd"
private const val BAD_SALT = "AA0lxhQ9aYgGfMsclVWPIAublg8h9Nlu"
}
}

View File

@ -0,0 +1,104 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.crypto.keysbackup
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupService
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupState
import im.vector.matrix.android.api.session.crypto.keysbackup.KeysBackupStateListener
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import java.util.concurrent.CountDownLatch
/**
* This class observe the state change of a KeysBackup object and provide a method to check the several state change
* It checks all state transitions and detected forbidden transition
*/
internal class StateObserver(private val keysBackup: KeysBackupService,
private val latch: CountDownLatch? = null,
private val expectedStateChange: Int = -1) : KeysBackupStateListener {
private val allowedStateTransitions = listOf(
KeysBackupState.BackingUp to KeysBackupState.ReadyToBackUp,
KeysBackupState.BackingUp to KeysBackupState.WrongBackUpVersion,
KeysBackupState.CheckingBackUpOnHomeserver to KeysBackupState.Disabled,
KeysBackupState.CheckingBackUpOnHomeserver to KeysBackupState.NotTrusted,
KeysBackupState.CheckingBackUpOnHomeserver to KeysBackupState.ReadyToBackUp,
KeysBackupState.CheckingBackUpOnHomeserver to KeysBackupState.Unknown,
KeysBackupState.CheckingBackUpOnHomeserver to KeysBackupState.WrongBackUpVersion,
KeysBackupState.Disabled to KeysBackupState.Enabling,
KeysBackupState.Enabling to KeysBackupState.Disabled,
KeysBackupState.Enabling to KeysBackupState.ReadyToBackUp,
KeysBackupState.NotTrusted to KeysBackupState.CheckingBackUpOnHomeserver,
// This transition happens when we trust the device
KeysBackupState.NotTrusted to KeysBackupState.ReadyToBackUp,
KeysBackupState.ReadyToBackUp to KeysBackupState.WillBackUp,
KeysBackupState.Unknown to KeysBackupState.CheckingBackUpOnHomeserver,
KeysBackupState.WillBackUp to KeysBackupState.BackingUp,
KeysBackupState.WrongBackUpVersion to KeysBackupState.CheckingBackUpOnHomeserver,
// FIXME These transitions are observed during test, and I'm not sure they should occur. Don't have time to investigate now
KeysBackupState.ReadyToBackUp to KeysBackupState.BackingUp,
KeysBackupState.ReadyToBackUp to KeysBackupState.ReadyToBackUp,
KeysBackupState.WillBackUp to KeysBackupState.ReadyToBackUp,
KeysBackupState.WillBackUp to KeysBackupState.Unknown
)
private val stateList = ArrayList<KeysBackupState>()
private var lastTransitionError: String? = null
init {
keysBackup.addListener(this)
}
// TODO Make expectedStates mandatory to enforce test
fun stopAndCheckStates(expectedStates: List<KeysBackupState>?) {
keysBackup.removeListener(this)
expectedStates?.let {
assertEquals(it.size, stateList.size)
for (i in it.indices) {
assertEquals("The state $i is not correct. states: " + stateList.joinToString(separator = " "), it[i], stateList[i])
}
}
assertNull("states: " + stateList.joinToString(separator = " "), lastTransitionError)
}
override fun onStateChange(newState: KeysBackupState) {
stateList.add(newState)
// Check that state transition is valid
if (stateList.size >= 2
&& !allowedStateTransitions.contains(stateList[stateList.size - 2] to newState)) {
// Forbidden transition detected
lastTransitionError = "Forbidden transition detected from " + stateList[stateList.size - 2] + " to " + newState
}
if (expectedStateChange == stateList.size) {
latch?.countDown()
}
}
}

View File

@ -0,0 +1,363 @@
/*
* 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.crypto.ssss
import androidx.lifecycle.Observer
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.securestorage.EncryptedSecretContent
import im.vector.matrix.android.api.session.securestorage.KeySigner
import im.vector.matrix.android.api.session.securestorage.RawBytesKeySpec
import im.vector.matrix.android.api.session.securestorage.SecretStorageKeyContent
import im.vector.matrix.android.api.session.securestorage.SharedSecretStorageService
import im.vector.matrix.android.api.session.securestorage.SsssKeyCreationInfo
import im.vector.matrix.android.api.util.Optional
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.SessionTestParams
import im.vector.matrix.android.common.TestConstants
import im.vector.matrix.android.common.TestMatrixCallback
import im.vector.matrix.android.internal.crypto.SSSS_ALGORITHM_AES_HMAC_SHA2
import im.vector.matrix.android.internal.crypto.crosssigning.toBase64NoPadding
import im.vector.matrix.android.internal.crypto.secrets.DefaultSharedSecretStorageService
import im.vector.matrix.android.internal.session.sync.model.accountdata.UserAccountDataEvent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.amshove.kluent.shouldBe
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class QuadSTests : InstrumentedTest {
private val mTestHelper = CommonTestHelper(context())
private val emptyKeySigner = object : KeySigner {
override fun sign(canonicalJson: String): Map<String, Map<String, String>>? {
return null
}
}
@Test
fun test_Generate4SKey() {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
val quadS = aliceSession.sharedSecretStorageService
val TEST_KEY_ID = "my.test.Key"
mTestHelper.doSync<SsssKeyCreationInfo> {
quadS.generateKey(TEST_KEY_ID, "Test Key", emptyKeySigner, it)
}
// Assert Account data is updated
val accountDataLock = CountDownLatch(1)
var accountData: UserAccountDataEvent? = null
val liveAccountData = runBlocking(Dispatchers.Main) {
aliceSession.getLiveAccountDataEvent("${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID")
}
val accountDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$TEST_KEY_ID") {
accountData = t.getOrNull()
accountDataLock.countDown()
}
}
GlobalScope.launch(Dispatchers.Main) { liveAccountData.observeForever(accountDataObserver) }
mTestHelper.await(accountDataLock)
assertNotNull("Key should be stored in account data", accountData)
val parsed = SecretStorageKeyContent.fromJson(accountData!!.content)
assertNotNull("Key Content cannot be parsed", parsed)
assertEquals("Unexpected Algorithm", SSSS_ALGORITHM_AES_HMAC_SHA2, parsed!!.algorithm)
assertEquals("Unexpected key name", "Test Key", parsed.name)
assertNull("Key was not generated from passphrase", parsed.passphrase)
// Set as default key
quadS.setDefaultKey(TEST_KEY_ID, object : MatrixCallback<Unit> {})
var defaultKeyAccountData: UserAccountDataEvent? = null
val defaultDataLock = CountDownLatch(1)
val liveDefAccountData = runBlocking(Dispatchers.Main) {
aliceSession.getLiveAccountDataEvent(DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
val accountDefDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == DefaultSharedSecretStorageService.DEFAULT_KEY_ID) {
defaultKeyAccountData = t.getOrNull()!!
defaultDataLock.countDown()
}
}
GlobalScope.launch(Dispatchers.Main) { liveDefAccountData.observeForever(accountDefDataObserver) }
mTestHelper.await(defaultDataLock)
assertNotNull(defaultKeyAccountData?.content)
assertEquals("Unexpected default key ${defaultKeyAccountData?.content}", TEST_KEY_ID, defaultKeyAccountData?.content?.get("key"))
mTestHelper.signOutAndClose(aliceSession)
}
@Test
fun test_StoreSecret() {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
val keyId = "My.Key"
val info = generatedSecret(aliceSession, keyId, true)
val keySpec = RawBytesKeySpec.fromRecoveryKey(info.recoveryKey)
// Store a secret
val clearSecret = "42".toByteArray().toBase64NoPadding()
mTestHelper.doSync<Unit> {
aliceSession.sharedSecretStorageService.storeSecret(
"secret.of.life",
clearSecret,
listOf(SharedSecretStorageService.KeyRef(null, keySpec)), // default key
it
)
}
val secretAccountData = assertAccountData(aliceSession, "secret.of.life")
val encryptedContent = secretAccountData.content.get("encrypted") as? Map<*, *>
assertNotNull("Element should be encrypted", encryptedContent)
assertNotNull("Secret should be encrypted with default key", encryptedContent?.get(keyId))
val secret = EncryptedSecretContent.fromJson(encryptedContent?.get(keyId))
assertNotNull(secret?.ciphertext)
assertNotNull(secret?.mac)
assertNotNull(secret?.initializationVector)
// Try to decrypt??
val decryptedSecret = mTestHelper.doSync<String> {
aliceSession.sharedSecretStorageService.getSecret(
"secret.of.life",
null, // default key
keySpec!!,
it
)
}
assertEquals("Secret mismatch", clearSecret, decryptedSecret)
mTestHelper.signOutAndClose(aliceSession)
}
@Test
fun test_SetDefaultLocalEcho() {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
val quadS = aliceSession.sharedSecretStorageService
val TEST_KEY_ID = "my.test.Key"
mTestHelper.doSync<SsssKeyCreationInfo> {
quadS.generateKey(TEST_KEY_ID, "Test Key", emptyKeySigner, it)
}
// Test that we don't need to wait for an account data sync to access directly the keyid from DB
mTestHelper.doSync<Unit> {
quadS.setDefaultKey(TEST_KEY_ID, it)
}
mTestHelper.signOutAndClose(aliceSession)
}
@Test
fun test_StoreSecretWithMultipleKey() {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
val keyId1 = "Key.1"
val key1Info = generatedSecret(aliceSession, keyId1, true)
val keyId2 = "Key2"
val key2Info = generatedSecret(aliceSession, keyId2, true)
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
mTestHelper.doSync<Unit> {
aliceSession.sharedSecretStorageService.storeSecret(
"my.secret",
mySecretText.toByteArray().toBase64NoPadding(),
listOf(
SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)),
SharedSecretStorageService.KeyRef(keyId2, RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey))
),
it
)
}
val accountDataEvent = aliceSession.getAccountDataEvent("my.secret")
val encryptedContent = accountDataEvent?.content?.get("encrypted") as? Map<*, *>
assertEquals("Content should contains two encryptions", 2, encryptedContent?.keys?.size ?: 0)
assertNotNull(encryptedContent?.get(keyId1))
assertNotNull(encryptedContent?.get(keyId2))
// Assert that can decrypt with both keys
mTestHelper.doSync<String> {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey)!!,
it
)
}
mTestHelper.doSync<String> {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId2,
RawBytesKeySpec.fromRecoveryKey(key2Info.recoveryKey)!!,
it
)
}
mTestHelper.signOutAndClose(aliceSession)
}
@Test
fun test_GetSecretWithBadPassphrase() {
val aliceSession = mTestHelper.createAccount(TestConstants.USER_ALICE, SessionTestParams(true))
val keyId1 = "Key.1"
val passphrase = "The good pass phrase"
val key1Info = generatedSecretFromPassphrase(aliceSession, passphrase, keyId1, true)
val mySecretText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
mTestHelper.doSync<Unit> {
aliceSession.sharedSecretStorageService.storeSecret(
"my.secret",
mySecretText.toByteArray().toBase64NoPadding(),
listOf(SharedSecretStorageService.KeyRef(keyId1, RawBytesKeySpec.fromRecoveryKey(key1Info.recoveryKey))),
it
)
}
val decryptCountDownLatch = CountDownLatch(1)
var error = false
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromPassphrase(
"A bad passphrase",
key1Info.content?.passphrase?.salt ?: "",
key1Info.content?.passphrase?.iterations ?: 0,
null),
object : MatrixCallback<String> {
override fun onSuccess(data: String) {
decryptCountDownLatch.countDown()
}
override fun onFailure(failure: Throwable) {
error = true
decryptCountDownLatch.countDown()
}
}
)
mTestHelper.await(decryptCountDownLatch)
error shouldBe true
// Now try with correct key
mTestHelper.doSync<String> {
aliceSession.sharedSecretStorageService.getSecret("my.secret",
keyId1,
RawBytesKeySpec.fromPassphrase(
passphrase,
key1Info.content?.passphrase?.salt ?: "",
key1Info.content?.passphrase?.iterations ?: 0,
null),
it
)
}
mTestHelper.signOutAndClose(aliceSession)
}
private fun assertAccountData(session: Session, type: String): UserAccountDataEvent {
val accountDataLock = CountDownLatch(1)
var accountData: UserAccountDataEvent? = null
val liveAccountData = runBlocking(Dispatchers.Main) {
session.getLiveAccountDataEvent(type)
}
val accountDataObserver = Observer<Optional<UserAccountDataEvent>?> { t ->
if (t?.getOrNull()?.type == type) {
accountData = t.getOrNull()
accountDataLock.countDown()
}
}
GlobalScope.launch(Dispatchers.Main) { liveAccountData.observeForever(accountDataObserver) }
mTestHelper.await(accountDataLock)
assertNotNull("Account Data type:$type should be found", accountData)
return accountData!!
}
private fun generatedSecret(session: Session, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
val quadS = session.sharedSecretStorageService
val creationInfo = mTestHelper.doSync<SsssKeyCreationInfo> {
quadS.generateKey(keyId, keyId, emptyKeySigner, it)
}
assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
if (asDefault) {
mTestHelper.doSync<Unit> {
quadS.setDefaultKey(keyId, it)
}
assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
return creationInfo
}
private fun generatedSecretFromPassphrase(session: Session, passphrase: String, keyId: String, asDefault: Boolean = true): SsssKeyCreationInfo {
val quadS = session.sharedSecretStorageService
val creationInfo = mTestHelper.doSync<SsssKeyCreationInfo> {
quadS.generateKeyWithPassphrase(
keyId,
keyId,
passphrase,
emptyKeySigner,
null,
it)
}
assertAccountData(session, "${DefaultSharedSecretStorageService.KEY_ID_BASE}.$keyId")
if (asDefault) {
val setDefaultLatch = CountDownLatch(1)
quadS.setDefaultKey(keyId, TestMatrixCallback(setDefaultLatch))
mTestHelper.await(setDefaultLatch)
assertAccountData(session, DefaultSharedSecretStorageService.DEFAULT_KEY_ID)
}
return creationInfo
}
}

View File

@ -0,0 +1,518 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.internal.crypto.verification
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.session.crypto.verification.CancelCode
import im.vector.matrix.android.api.session.crypto.verification.IncomingSasVerificationTransaction
import im.vector.matrix.android.api.session.crypto.verification.OutgoingSasVerificationTransaction
import im.vector.matrix.android.api.session.crypto.verification.SasMode
import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod
import im.vector.matrix.android.api.session.crypto.verification.VerificationService
import im.vector.matrix.android.api.session.crypto.verification.VerificationTransaction
import im.vector.matrix.android.api.session.crypto.verification.VerificationTxState
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.toModel
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
import im.vector.matrix.android.internal.crypto.model.MXUsersDevicesMap
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationCancel
import im.vector.matrix.android.internal.crypto.model.rest.KeyVerificationStart
import im.vector.matrix.android.internal.crypto.model.rest.toValue
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Assert.fail
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class SASTest : InstrumentedTest {
private val mTestHelper = CommonTestHelper(context())
private val mCryptoTestHelper = CryptoTestHelper(mTestHelper)
@Test
fun test_aliceStartThenAliceCancel() {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession
val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession!!.cryptoService().verificationService()
val bobTxCreatedLatch = CountDownLatch(1)
val bobListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
bobTxCreatedLatch.countDown()
}
}
bobVerificationService.addListener(bobListener)
val txID = aliceVerificationService.beginKeyVerification(VerificationMethod.SAS,
bobSession.myUserId,
bobSession.cryptoService().getMyDevice().deviceId,
null)
assertNotNull("Alice should have a started transaction", txID)
val aliceKeyTx = aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID!!)
assertNotNull("Alice should have a started transaction", aliceKeyTx)
mTestHelper.await(bobTxCreatedLatch)
bobVerificationService.removeListener(bobListener)
val bobKeyTx = bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID)
assertNotNull("Bob should have started verif transaction", bobKeyTx)
assertTrue(bobKeyTx is SASDefaultVerificationTransaction)
assertNotNull("Bob should have starting a SAS transaction", bobKeyTx)
assertTrue(aliceKeyTx is SASDefaultVerificationTransaction)
assertEquals("Alice and Bob have same transaction id", aliceKeyTx!!.transactionId, bobKeyTx!!.transactionId)
val aliceSasTx = aliceKeyTx as SASDefaultVerificationTransaction?
val bobSasTx = bobKeyTx as SASDefaultVerificationTransaction?
assertEquals("Alice state should be started", VerificationTxState.Started, aliceSasTx!!.state)
assertEquals("Bob state should be started by alice", VerificationTxState.OnStarted, bobSasTx!!.state)
// Let's cancel from alice side
val cancelLatch = CountDownLatch(1)
val bobListener2 = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
if (tx.transactionId == txID) {
val immutableState = (tx as SASDefaultVerificationTransaction).state
if (immutableState is VerificationTxState.Cancelled && !immutableState.byMe) {
cancelLatch.countDown()
}
}
}
}
bobVerificationService.addListener(bobListener2)
aliceSasTx.cancel(CancelCode.User)
mTestHelper.await(cancelLatch)
assertTrue("Should be cancelled on alice side", aliceSasTx.state is VerificationTxState.Cancelled)
assertTrue("Should be cancelled on bob side", bobSasTx.state is VerificationTxState.Cancelled)
val aliceCancelState = aliceSasTx.state as VerificationTxState.Cancelled
val bobCancelState = bobSasTx.state as VerificationTxState.Cancelled
assertTrue("Should be cancelled by me on alice side", aliceCancelState.byMe)
assertFalse("Should be cancelled by other on bob side", bobCancelState.byMe)
assertEquals("Should be User cancelled on alice side", CancelCode.User, aliceCancelState.cancelCode)
assertEquals("Should be User cancelled on bob side", CancelCode.User, bobCancelState.cancelCode)
assertNull(bobVerificationService.getExistingTransaction(aliceSession.myUserId, txID))
assertNull(aliceVerificationService.getExistingTransaction(bobSession.myUserId, txID))
cryptoTestData.cleanUp(mTestHelper)
}
@Test
fun test_key_agreement_protocols_must_include_curve25519() {
fail("Not passing for the moment")
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val bobSession = cryptoTestData.secondSession!!
val protocols = listOf("meh_dont_know")
val tid = "00000000"
// Bob should receive a cancel
var cancelReason: CancelCode? = null
val cancelLatch = CountDownLatch(1)
val bobListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
if (tx.transactionId == tid && tx.state is VerificationTxState.Cancelled) {
cancelReason = (tx.state as VerificationTxState.Cancelled).cancelCode
cancelLatch.countDown()
}
}
}
bobSession.cryptoService().verificationService().addListener(bobListener)
// TODO bobSession!!.dataHandler.addListener(object : MXEventListener() {
// TODO override fun onToDeviceEvent(event: Event?) {
// TODO if (event!!.getType() == CryptoEvent.EVENT_TYPE_KEY_VERIFICATION_CANCEL) {
// TODO if (event.contentAsJsonObject?.get("transaction_id")?.asString == tid) {
// TODO canceledToDeviceEvent = event
// TODO cancelLatch.countDown()
// TODO }
// TODO }
// TODO }
// TODO })
val aliceSession = cryptoTestData.firstSession
val aliceUserID = aliceSession.myUserId
val aliceDevice = aliceSession.cryptoService().getMyDevice().deviceId
val aliceListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
if ((tx as IncomingSasVerificationTransaction).uxState === IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT) {
(tx as IncomingSasVerificationTransaction).performAccept()
}
}
}
aliceSession.cryptoService().verificationService().addListener(aliceListener)
fakeBobStart(bobSession, aliceUserID, aliceDevice, tid, protocols = protocols)
mTestHelper.await(cancelLatch)
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod, cancelReason)
cryptoTestData.cleanUp(mTestHelper)
}
@Test
fun test_key_agreement_macs_Must_include_hmac_sha256() {
fail("Not passing for the moment")
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val bobSession = cryptoTestData.secondSession!!
val mac = listOf("shaBit")
val tid = "00000000"
// Bob should receive a cancel
var canceledToDeviceEvent: Event? = null
val cancelLatch = CountDownLatch(1)
// TODO bobSession!!.dataHandler.addListener(object : MXEventListener() {
// TODO override fun onToDeviceEvent(event: Event?) {
// TODO if (event!!.getType() == CryptoEvent.EVENT_TYPE_KEY_VERIFICATION_CANCEL) {
// TODO if (event.contentAsJsonObject?.get("transaction_id")?.asString == tid) {
// TODO canceledToDeviceEvent = event
// TODO cancelLatch.countDown()
// TODO }
// TODO }
// TODO }
// TODO })
val aliceSession = cryptoTestData.firstSession
val aliceUserID = aliceSession.myUserId
val aliceDevice = aliceSession.cryptoService().getMyDevice().deviceId
fakeBobStart(bobSession, aliceUserID, aliceDevice, tid, mac = mac)
mTestHelper.await(cancelLatch)
val cancelReq = canceledToDeviceEvent!!.content.toModel<KeyVerificationCancel>()!!
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
cryptoTestData.cleanUp(mTestHelper)
}
@Test
fun test_key_agreement_short_code_include_decimal() {
fail("Not passing for the moment")
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val bobSession = cryptoTestData.secondSession!!
val codes = listOf("bin", "foo", "bar")
val tid = "00000000"
// Bob should receive a cancel
var canceledToDeviceEvent: Event? = null
val cancelLatch = CountDownLatch(1)
// TODO bobSession!!.dataHandler.addListener(object : MXEventListener() {
// TODO override fun onToDeviceEvent(event: Event?) {
// TODO if (event!!.getType() == CryptoEvent.EVENT_TYPE_KEY_VERIFICATION_CANCEL) {
// TODO if (event.contentAsJsonObject?.get("transaction_id")?.asString == tid) {
// TODO canceledToDeviceEvent = event
// TODO cancelLatch.countDown()
// TODO }
// TODO }
// TODO }
// TODO })
val aliceSession = cryptoTestData.firstSession
val aliceUserID = aliceSession.myUserId
val aliceDevice = aliceSession.cryptoService().getMyDevice().deviceId
fakeBobStart(bobSession, aliceUserID, aliceDevice, tid, codes = codes)
mTestHelper.await(cancelLatch)
val cancelReq = canceledToDeviceEvent!!.content.toModel<KeyVerificationCancel>()!!
assertEquals("Request should be cancelled with m.unknown_method", CancelCode.UnknownMethod.value, cancelReq.code)
cryptoTestData.cleanUp(mTestHelper)
}
private fun fakeBobStart(bobSession: Session,
aliceUserID: String?,
aliceDevice: String?,
tid: String,
protocols: List<String> = SASDefaultVerificationTransaction.KNOWN_AGREEMENT_PROTOCOLS,
hashes: List<String> = SASDefaultVerificationTransaction.KNOWN_HASHES,
mac: List<String> = SASDefaultVerificationTransaction.KNOWN_MACS,
codes: List<String> = SASDefaultVerificationTransaction.KNOWN_SHORT_CODES) {
val startMessage = KeyVerificationStart(
fromDevice = bobSession.cryptoService().getMyDevice().deviceId,
method = VerificationMethod.SAS.toValue(),
transactionId = tid,
keyAgreementProtocols = protocols,
hashes = hashes,
messageAuthenticationCodes = mac,
shortAuthenticationStrings = codes
)
val contentMap = MXUsersDevicesMap<Any>()
contentMap.setObject(aliceUserID, aliceDevice, startMessage)
// TODO val sendLatch = CountDownLatch(1)
// TODO bobSession.cryptoRestClient.sendToDevice(
// TODO EventType.KEY_VERIFICATION_START,
// TODO contentMap,
// TODO tid,
// TODO TestMatrixCallback<Void>(sendLatch)
// TODO )
}
// any two devices may only have at most one key verification in flight at a time.
// If a device has two verifications in progress with the same device, then it should cancel both verifications.
@Test
fun test_aliceStartTwoRequests() {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession
val aliceVerificationService = aliceSession.cryptoService().verificationService()
val aliceCreatedLatch = CountDownLatch(2)
val aliceCancelledLatch = CountDownLatch(2)
val createdTx = mutableListOf<SASDefaultVerificationTransaction>()
val aliceListener = object : VerificationService.Listener {
override fun transactionCreated(tx: VerificationTransaction) {
createdTx.add(tx as SASDefaultVerificationTransaction)
aliceCreatedLatch.countDown()
}
override fun transactionUpdated(tx: VerificationTransaction) {
if ((tx as SASDefaultVerificationTransaction).state is VerificationTxState.Cancelled && !(tx.state as VerificationTxState.Cancelled).byMe) {
aliceCancelledLatch.countDown()
}
}
}
aliceVerificationService.addListener(aliceListener)
val bobUserId = bobSession!!.myUserId
val bobDeviceId = bobSession.cryptoService().getMyDevice().deviceId
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
mTestHelper.await(aliceCreatedLatch)
mTestHelper.await(aliceCancelledLatch)
cryptoTestData.cleanUp(mTestHelper)
}
/**
* Test that when alice starts a 'correct' request, bob agrees.
*/
@Test
fun test_aliceAndBobAgreement() {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession
val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession!!.cryptoService().verificationService()
var accepted: ValidVerificationInfoAccept? = null
var startReq: ValidVerificationInfoStart.SasVerificationInfoStart? = null
val aliceAcceptedLatch = CountDownLatch(1)
val aliceListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
if ((tx as SASDefaultVerificationTransaction).state === VerificationTxState.OnAccepted) {
val at = tx as SASDefaultVerificationTransaction
accepted = at.accepted
startReq = at.startReq
aliceAcceptedLatch.countDown()
}
}
}
aliceVerificationService.addListener(aliceListener)
val bobListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
if ((tx as IncomingSasVerificationTransaction).uxState === IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT) {
val at = tx as IncomingSasVerificationTransaction
at.performAccept()
}
}
}
bobVerificationService.addListener(bobListener)
val bobUserId = bobSession.myUserId
val bobDeviceId = bobSession.cryptoService().getMyDevice().deviceId
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
mTestHelper.await(aliceAcceptedLatch)
assertTrue("Should have receive a commitment", accepted!!.commitment?.trim()?.isEmpty() == false)
// check that agreement is valid
assertTrue("Agreed Protocol should be Valid", accepted != null)
assertTrue("Agreed Protocol should be known by alice", startReq!!.keyAgreementProtocols.contains(accepted!!.keyAgreementProtocol))
assertTrue("Hash should be known by alice", startReq!!.hashes.contains(accepted!!.hash))
assertTrue("Hash should be known by alice", startReq!!.messageAuthenticationCodes.contains(accepted!!.messageAuthenticationCode))
accepted!!.shortAuthenticationStrings.forEach {
assertTrue("all agreed Short Code should be known by alice", startReq!!.shortAuthenticationStrings.contains(it))
}
cryptoTestData.cleanUp(mTestHelper)
}
@Test
fun test_aliceAndBobSASCode() {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession
val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession!!.cryptoService().verificationService()
val aliceSASLatch = CountDownLatch(1)
val aliceListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as OutgoingSasVerificationTransaction).uxState
when (uxState) {
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
aliceSASLatch.countDown()
}
else -> Unit
}
}
}
aliceVerificationService.addListener(aliceListener)
val bobSASLatch = CountDownLatch(1)
val bobListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as IncomingSasVerificationTransaction).uxState
when (uxState) {
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
tx.performAccept()
}
else -> Unit
}
if (uxState === IncomingSasVerificationTransaction.UxState.SHOW_SAS) {
bobSASLatch.countDown()
}
}
}
bobVerificationService.addListener(bobListener)
val bobUserId = bobSession.myUserId
val bobDeviceId = bobSession.cryptoService().getMyDevice().deviceId
val verificationSAS = aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
mTestHelper.await(aliceSASLatch)
mTestHelper.await(bobSASLatch)
val aliceTx = aliceVerificationService.getExistingTransaction(bobUserId, verificationSAS!!) as SASDefaultVerificationTransaction
val bobTx = bobVerificationService.getExistingTransaction(aliceSession.myUserId, verificationSAS) as SASDefaultVerificationTransaction
assertEquals("Should have same SAS", aliceTx.getShortCodeRepresentation(SasMode.DECIMAL),
bobTx.getShortCodeRepresentation(SasMode.DECIMAL))
cryptoTestData.cleanUp(mTestHelper)
}
@Test
fun test_happyPath() {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession
val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession!!.cryptoService().verificationService()
val aliceSASLatch = CountDownLatch(1)
val aliceListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as OutgoingSasVerificationTransaction).uxState
when (uxState) {
OutgoingSasVerificationTransaction.UxState.SHOW_SAS -> {
tx.userHasVerifiedShortCode()
}
OutgoingSasVerificationTransaction.UxState.VERIFIED -> {
aliceSASLatch.countDown()
}
else -> Unit
}
}
}
aliceVerificationService.addListener(aliceListener)
val bobSASLatch = CountDownLatch(1)
val bobListener = object : VerificationService.Listener {
override fun transactionUpdated(tx: VerificationTransaction) {
val uxState = (tx as IncomingSasVerificationTransaction).uxState
when (uxState) {
IncomingSasVerificationTransaction.UxState.SHOW_ACCEPT -> {
tx.performAccept()
}
IncomingSasVerificationTransaction.UxState.SHOW_SAS -> {
tx.userHasVerifiedShortCode()
}
IncomingSasVerificationTransaction.UxState.VERIFIED -> {
bobSASLatch.countDown()
}
else -> Unit
}
}
}
bobVerificationService.addListener(bobListener)
val bobUserId = bobSession.myUserId
val bobDeviceId = bobSession.cryptoService().getMyDevice().deviceId
aliceVerificationService.beginKeyVerification(VerificationMethod.SAS, bobUserId, bobDeviceId, null)
mTestHelper.await(aliceSASLatch)
mTestHelper.await(bobSASLatch)
// Assert that devices are verified
val bobDeviceInfoFromAlicePOV: CryptoDeviceInfo? = aliceSession.cryptoService().getDeviceInfo(bobUserId, bobDeviceId)
val aliceDeviceInfoFromBobPOV: CryptoDeviceInfo? = bobSession.cryptoService().getDeviceInfo(aliceSession.myUserId, aliceSession.cryptoService().getMyDevice().deviceId)
// latch wait a bit again
Thread.sleep(1000)
assertTrue("alice device should be verified from bob point of view", aliceDeviceInfoFromBobPOV!!.isVerified)
assertTrue("bob device should be verified from alice point of view", bobDeviceInfoFromAlicePOV!!.isVerified)
cryptoTestData.cleanUp(mTestHelper)
}
}

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.internal.crypto.verification.qrcode
fun hexToByteArray(hex: String): ByteArray {
// Remove all spaces
return hex.replace(" ", "")
.let {
if (it.length % 2 != 0) "0$it" else it
}
.let {
ByteArray(it.length / 2)
.apply {
for (i in this.indices) {
val index = i * 2
val v = it.substring(index, index + 2).toInt(16)
this[i] = v.toByte()
}
}
}
}

View File

@ -0,0 +1,249 @@
/*
* 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.crypto.verification.qrcode
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import org.amshove.kluent.shouldBeNull
import org.amshove.kluent.shouldEqual
import org.amshove.kluent.shouldEqualTo
import org.amshove.kluent.shouldNotBeNull
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class QrCodeTest : InstrumentedTest {
private val qrCode1 = QrCodeData.VerifyingAnotherUser(
transactionId = "MaTransaction",
userMasterCrossSigningPublicKey = "ktEwcUP6su1xh+GuE+CYkQ3H6W/DIl+ybHFdaEOrolU",
otherUserMasterCrossSigningPublicKey = "TXluZKTZLvSRWOTPlOqLq534bA+/K4zLFKSu9cGLQaU",
sharedSecret = "MTIzNDU2Nzg"
)
private val value1 = "MATRIX\u0002\u0000\u0000\u000DMaTransaction\u0092Ñ0qCú²íq\u0087á®\u0013à\u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢UMynd¤Ù.ô\u0091XäÏ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÁ\u008BA¥12345678"
private val qrCode2 = QrCodeData.SelfVerifyingMasterKeyTrusted(
transactionId = "MaTransaction",
userMasterCrossSigningPublicKey = "ktEwcUP6su1xh+GuE+CYkQ3H6W/DIl+ybHFdaEOrolU",
otherDeviceKey = "TXluZKTZLvSRWOTPlOqLq534bA+/K4zLFKSu9cGLQaU",
sharedSecret = "MTIzNDU2Nzg"
)
private val value2 = "MATRIX\u0002\u0001\u0000\u000DMaTransaction\u0092Ñ0qCú²íq\u0087á®\u0013à\u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢UMynd¤Ù.ô\u0091XäÏ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÁ\u008BA¥12345678"
private val qrCode3 = QrCodeData.SelfVerifyingMasterKeyNotTrusted(
transactionId = "MaTransaction",
deviceKey = "TXluZKTZLvSRWOTPlOqLq534bA+/K4zLFKSu9cGLQaU",
userMasterCrossSigningPublicKey = "ktEwcUP6su1xh+GuE+CYkQ3H6W/DIl+ybHFdaEOrolU",
sharedSecret = "MTIzNDU2Nzg"
)
private val value3 = "MATRIX\u0002\u0002\u0000\u000DMaTransactionMynd¤Ù.ô\u0091XäÏ\u0094ê\u008B«\u009Døl\u000F¿+\u008CË\u0014¤®õÁ\u008BA¥\u0092Ñ0qCú²íq\u0087á®\u0013à\u0098\u0091\u000DÇéoÃ\"_²lq]hC«¢U12345678"
private val sharedSecretByteArray = "12345678".toByteArray(Charsets.ISO_8859_1)
private val tlx_byteArray = hexToByteArray("4d 79 6e 64 a4 d9 2e f4 91 58 e4 cf 94 ea 8b ab 9d f8 6c 0f bf 2b 8c cb 14 a4 ae f5 c1 8b 41 a5")
private val kte_byteArray = hexToByteArray("92 d1 30 71 43 fa b2 ed 71 87 e1 ae 13 e0 98 91 0d c7 e9 6f c3 22 5f b2 6c 71 5d 68 43 ab a2 55")
@Test
fun testEncoding1() {
qrCode1.toEncodedString() shouldEqual value1
}
@Test
fun testEncoding2() {
qrCode2.toEncodedString() shouldEqual value2
}
@Test
fun testEncoding3() {
qrCode3.toEncodedString() shouldEqual value3
}
@Test
fun testSymmetry1() {
qrCode1.toEncodedString().toQrCodeData() shouldEqual qrCode1
}
@Test
fun testSymmetry2() {
qrCode2.toEncodedString().toQrCodeData() shouldEqual qrCode2
}
@Test
fun testSymmetry3() {
qrCode3.toEncodedString().toQrCodeData() shouldEqual qrCode3
}
@Test
fun testCase1() {
val url = qrCode1.toEncodedString()
val byteArray = url.toByteArray(Charsets.ISO_8859_1)
checkHeader(byteArray)
// Mode
byteArray[7] shouldEqualTo 0
checkSizeAndTransaction(byteArray)
compareArray(byteArray.copyOfRange(23, 23 + 32), kte_byteArray)
compareArray(byteArray.copyOfRange(23 + 32, 23 + 64), tlx_byteArray)
compareArray(byteArray.copyOfRange(23 + 64, byteArray.size), sharedSecretByteArray)
}
@Test
fun testCase2() {
val url = qrCode2.toEncodedString()
val byteArray = url.toByteArray(Charsets.ISO_8859_1)
checkHeader(byteArray)
// Mode
byteArray[7] shouldEqualTo 1
checkSizeAndTransaction(byteArray)
compareArray(byteArray.copyOfRange(23, 23 + 32), kte_byteArray)
compareArray(byteArray.copyOfRange(23 + 32, 23 + 64), tlx_byteArray)
compareArray(byteArray.copyOfRange(23 + 64, byteArray.size), sharedSecretByteArray)
}
@Test
fun testCase3() {
val url = qrCode3.toEncodedString()
val byteArray = url.toByteArray(Charsets.ISO_8859_1)
checkHeader(byteArray)
// Mode
byteArray[7] shouldEqualTo 2
checkSizeAndTransaction(byteArray)
compareArray(byteArray.copyOfRange(23, 23 + 32), tlx_byteArray)
compareArray(byteArray.copyOfRange(23 + 32, 23 + 64), kte_byteArray)
compareArray(byteArray.copyOfRange(23 + 64, byteArray.size), sharedSecretByteArray)
}
@Test
fun testLongTransactionId() {
// Size on two bytes (2_000 = 0x07D0)
val longTransactionId = "PatternId_".repeat(200)
val qrCode = qrCode1.copy(transactionId = longTransactionId)
val result = qrCode.toEncodedString()
val expected = value1.replace("\u0000\u000DMaTransaction", "\u0007\u00D0$longTransactionId")
result shouldEqual expected
// Reverse operation
expected.toQrCodeData() shouldEqual qrCode
}
@Test
fun testAnyTransactionId() {
for (qty in 0 until 0x1FFF step 200) {
val longTransactionId = "a".repeat(qty)
val qrCode = qrCode1.copy(transactionId = longTransactionId)
// Symmetric operation
qrCode.toEncodedString().toQrCodeData() shouldEqual qrCode
}
}
// Error cases
@Test
fun testErrorHeader() {
value1.replace("MATRIX", "MOTRIX").toQrCodeData().shouldBeNull()
value1.replace("MATRIX", "MATRI").toQrCodeData().shouldBeNull()
value1.replace("MATRIX", "").toQrCodeData().shouldBeNull()
}
@Test
fun testErrorVersion() {
value1.replace("MATRIX\u0002", "MATRIX\u0000").toQrCodeData().shouldBeNull()
value1.replace("MATRIX\u0002", "MATRIX\u0001").toQrCodeData().shouldBeNull()
value1.replace("MATRIX\u0002", "MATRIX\u0003").toQrCodeData().shouldBeNull()
value1.replace("MATRIX\u0002", "MATRIX").toQrCodeData().shouldBeNull()
}
@Test
fun testErrorSecretTooShort() {
value1.replace("12345678", "1234567").toQrCodeData().shouldBeNull()
}
@Test
fun testErrorNoTransactionNoKeyNoSecret() {
// But keep transaction length
"MATRIX\u0002\u0000\u0000\u000D".toQrCodeData().shouldBeNull()
}
@Test
fun testErrorNoKeyNoSecret() {
"MATRIX\u0002\u0000\u0000\u000DMaTransaction".toQrCodeData().shouldBeNull()
}
@Test
fun testErrorTransactionLengthTooShort() {
// In this case, the secret will be longer, so this is not an error, but it will lead to keys mismatch
value1.replace("\u000DMaTransaction", "\u000CMaTransaction").toQrCodeData().shouldNotBeNull()
}
@Test
fun testErrorTransactionLengthTooBig() {
value1.replace("\u000DMaTransaction", "\u000EMaTransaction").toQrCodeData().shouldBeNull()
}
private fun compareArray(actual: ByteArray, expected: ByteArray) {
actual.size shouldEqual expected.size
for (i in actual.indices) {
actual[i] shouldEqualTo expected[i]
}
}
private fun checkHeader(byteArray: ByteArray) {
// MATRIX
byteArray[0] shouldEqualTo 'M'.toByte()
byteArray[1] shouldEqualTo 'A'.toByte()
byteArray[2] shouldEqualTo 'T'.toByte()
byteArray[3] shouldEqualTo 'R'.toByte()
byteArray[4] shouldEqualTo 'I'.toByte()
byteArray[5] shouldEqualTo 'X'.toByte()
// Version
byteArray[6] shouldEqualTo 2
}
private fun checkSizeAndTransaction(byteArray: ByteArray) {
// Size
byteArray[8] shouldEqualTo 0
byteArray[9] shouldEqualTo 13
// Transaction
byteArray.copyOfRange(10, 10 + "MaTransaction".length).toString(Charsets.ISO_8859_1) shouldEqual "MaTransaction"
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.crypto.verification.qrcode
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import org.amshove.kluent.shouldBe
import org.amshove.kluent.shouldNotBeEqualTo
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class SharedSecretTest : InstrumentedTest {
@Test
fun testSharedSecretLengthCase() {
repeat(100) {
generateSharedSecretV2().length shouldBe 11
}
}
@Test
fun testSharedDiffCase() {
val sharedSecret1 = generateSharedSecretV2()
val sharedSecret2 = generateSharedSecretV2()
sharedSecret1 shouldNotBeEqualTo sharedSecret2
}
}

View File

@ -0,0 +1,232 @@
/*
* 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.crypto.verification.qrcode
import androidx.test.ext.junit.runners.AndroidJUnit4
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.api.session.crypto.verification.VerificationMethod
import im.vector.matrix.android.api.session.crypto.verification.VerificationService
import im.vector.matrix.android.common.CommonTestHelper
import im.vector.matrix.android.common.CryptoTestHelper
import im.vector.matrix.android.common.TestConstants
import im.vector.matrix.android.internal.crypto.model.rest.UserPasswordAuth
import im.vector.matrix.android.api.session.crypto.verification.PendingVerificationRequest
import org.amshove.kluent.shouldBe
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import java.util.concurrent.CountDownLatch
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.JVM)
class VerificationTest : InstrumentedTest {
private val mTestHelper = CommonTestHelper(context())
private val mCryptoTestHelper = CryptoTestHelper(mTestHelper)
data class ExpectedResult(
val sasIsSupported: Boolean = false,
val otherCanScanQrCode: Boolean = false,
val otherCanShowQrCode: Boolean = false
)
private val sas = listOf(
VerificationMethod.SAS
)
private val sasShow = listOf(
VerificationMethod.SAS,
VerificationMethod.QR_CODE_SHOW
)
private val sasScan = listOf(
VerificationMethod.SAS,
VerificationMethod.QR_CODE_SCAN
)
private val sasShowScan = listOf(
VerificationMethod.SAS,
VerificationMethod.QR_CODE_SHOW,
VerificationMethod.QR_CODE_SCAN
)
@Test
fun test_aliceAndBob_sas_sas() = doTest(
sas,
sas,
ExpectedResult(sasIsSupported = true),
ExpectedResult(sasIsSupported = true)
)
@Test
fun test_aliceAndBob_sas_show() = doTest(
sas,
sasShow,
ExpectedResult(sasIsSupported = true),
ExpectedResult(sasIsSupported = true)
)
@Test
fun test_aliceAndBob_show_sas() = doTest(
sasShow,
sas,
ExpectedResult(sasIsSupported = true),
ExpectedResult(sasIsSupported = true)
)
@Test
fun test_aliceAndBob_sas_scan() = doTest(
sas,
sasScan,
ExpectedResult(sasIsSupported = true),
ExpectedResult(sasIsSupported = true)
)
@Test
fun test_aliceAndBob_scan_sas() = doTest(
sasScan,
sas,
ExpectedResult(sasIsSupported = true),
ExpectedResult(sasIsSupported = true)
)
@Test
fun test_aliceAndBob_scan_scan() = doTest(
sasScan,
sasScan,
ExpectedResult(sasIsSupported = true),
ExpectedResult(sasIsSupported = true)
)
@Test
fun test_aliceAndBob_show_show() = doTest(
sasShow,
sasShow,
ExpectedResult(sasIsSupported = true),
ExpectedResult(sasIsSupported = true)
)
@Test
fun test_aliceAndBob_show_scan() = doTest(
sasShow,
sasScan,
ExpectedResult(sasIsSupported = true, otherCanScanQrCode = true),
ExpectedResult(sasIsSupported = true, otherCanShowQrCode = true)
)
@Test
fun test_aliceAndBob_scan_show() = doTest(
sasScan,
sasShow,
ExpectedResult(sasIsSupported = true, otherCanShowQrCode = true),
ExpectedResult(sasIsSupported = true, otherCanScanQrCode = true)
)
@Test
fun test_aliceAndBob_all_all() = doTest(
sasShowScan,
sasShowScan,
ExpectedResult(sasIsSupported = true, otherCanShowQrCode = true, otherCanScanQrCode = true),
ExpectedResult(sasIsSupported = true, otherCanShowQrCode = true, otherCanScanQrCode = true)
)
// TODO Add tests without SAS
private fun doTest(aliceSupportedMethods: List<VerificationMethod>,
bobSupportedMethods: List<VerificationMethod>,
expectedResultForAlice: ExpectedResult,
expectedResultForBob: ExpectedResult) {
val cryptoTestData = mCryptoTestHelper.doE2ETestWithAliceAndBobInARoom()
val aliceSession = cryptoTestData.firstSession
val bobSession = cryptoTestData.secondSession!!
mTestHelper.doSync<Unit> { callback ->
aliceSession.cryptoService().crossSigningService()
.initializeCrossSigning(UserPasswordAuth(
user = aliceSession.myUserId,
password = TestConstants.PASSWORD
), callback)
}
mTestHelper.doSync<Unit> { callback ->
bobSession.cryptoService().crossSigningService()
.initializeCrossSigning(UserPasswordAuth(
user = bobSession.myUserId,
password = TestConstants.PASSWORD
), callback)
}
val aliceVerificationService = aliceSession.cryptoService().verificationService()
val bobVerificationService = bobSession.cryptoService().verificationService()
var aliceReadyPendingVerificationRequest: PendingVerificationRequest? = null
var bobReadyPendingVerificationRequest: PendingVerificationRequest? = null
val latch = CountDownLatch(2)
val aliceListener = object : VerificationService.Listener {
override fun verificationRequestUpdated(pr: PendingVerificationRequest) {
// Step 4: Alice receive the ready request
if (pr.isReady) {
aliceReadyPendingVerificationRequest = pr
latch.countDown()
}
}
}
aliceVerificationService.addListener(aliceListener)
val bobListener = object : VerificationService.Listener {
override fun verificationRequestCreated(pr: PendingVerificationRequest) {
// Step 2: Bob accepts the verification request
bobVerificationService.readyPendingVerificationInDMs(
bobSupportedMethods,
aliceSession.myUserId,
cryptoTestData.roomId,
pr.transactionId!!
)
}
override fun verificationRequestUpdated(pr: PendingVerificationRequest) {
// Step 3: Bob is ready
if (pr.isReady) {
bobReadyPendingVerificationRequest = pr
latch.countDown()
}
}
}
bobVerificationService.addListener(bobListener)
val bobUserId = bobSession.myUserId
// Step 1: Alice starts a verification request
aliceVerificationService.requestKeyVerificationInDMs(aliceSupportedMethods, bobUserId, cryptoTestData.roomId)
mTestHelper.await(latch)
aliceReadyPendingVerificationRequest!!.let { pr ->
pr.isSasSupported() shouldBe expectedResultForAlice.sasIsSupported
pr.otherCanShowQrCode() shouldBe expectedResultForAlice.otherCanShowQrCode
pr.otherCanScanQrCode() shouldBe expectedResultForAlice.otherCanScanQrCode
}
bobReadyPendingVerificationRequest!!.let { pr ->
pr.isSasSupported() shouldBe expectedResultForBob.sasIsSupported
pr.otherCanShowQrCode() shouldBe expectedResultForBob.otherCanShowQrCode
pr.otherCanScanQrCode() shouldBe expectedResultForBob.otherCanScanQrCode
}
cryptoTestData.cleanUp(mTestHelper)
}
}

View File

@ -62,8 +62,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
JsonCanonicalizer.canonicalize("{\"a\":\"\\\"\"}"))
}
/* ==========================================================================================
* Test from https://matrix.org/docs/spec/appendices.html#examples
* ========================================================================================== */
@ -74,7 +72,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
JsonCanonicalizer.canonicalize("""{}"""))
}
@Test
fun matrixOrg002Test() {
assertEquals("""{"one":1,"two":"Two"}""",
@ -84,7 +81,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}"""))
}
@Test
fun matrixOrg003Test() {
assertEquals("""{"a":"1","b":"2"}""",
@ -94,14 +90,12 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}"""))
}
@Test
fun matrixOrg004Test() {
assertEquals("""{"a":"1","b":"2"}""",
JsonCanonicalizer.canonicalize("""{"b":"2","a":"1"}"""))
}
@Test
fun matrixOrg005Test() {
assertEquals("""{"auth":{"mxid":"@john.doe:example.com","profile":{"display_name":"John Doe","three_pids":[{"address":"john.doe@example.org","medium":"email"},{"address":"123456789","medium":"msisdn"}]},"success":true}}""",
@ -126,7 +120,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}"""))
}
@Test
fun matrixOrg006Test() {
assertEquals("""{"a":"日本語"}""",
@ -135,7 +128,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}"""))
}
@Test
fun matrixOrg007Test() {
assertEquals("""{"日":1,"本":2}""",
@ -145,7 +137,6 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
}"""))
}
@Test
fun matrixOrg008Test() {
assertEquals("""{"a":"日"}""",
@ -159,4 +150,4 @@ internal class JsonCanonicalizerTest : InstrumentedTest {
"a": null
}"""))
}
}
}

View File

@ -19,23 +19,25 @@ package im.vector.matrix.android.session.room.timeline
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.InstrumentedTest
import im.vector.matrix.android.internal.database.helper.*
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.room.send.SendState
import im.vector.matrix.android.internal.database.helper.addTimelineEvent
import im.vector.matrix.android.internal.database.helper.merge
import im.vector.matrix.android.internal.database.mapper.toEntity
import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.SessionRealmModule
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
import im.vector.matrix.android.session.room.timeline.RoomDataHelper.createFakeListOfEvents
import im.vector.matrix.android.session.room.timeline.RoomDataHelper.createFakeMessageEvent
import im.vector.matrix.android.session.room.timeline.RoomDataHelper.createFakeRoomMemberEvent
import io.realm.Realm
import io.realm.RealmConfiguration
import io.realm.kotlin.createObject
import org.amshove.kluent.shouldBeFalse
import org.amshove.kluent.shouldBeTrue
import org.amshove.kluent.shouldEqual
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
internal class ChunkEntityTest : InstrumentedTest {
@ -44,17 +46,23 @@ internal class ChunkEntityTest : InstrumentedTest {
@Before
fun setup() {
Realm.init(context())
val testConfig = RealmConfiguration.Builder().inMemory().name("test-realm").build()
val testConfig = RealmConfiguration.Builder()
.inMemory()
.name("test-realm")
.modules(SessionRealmModule())
.build()
monarchy = Monarchy.Builder().setRealmConfiguration(testConfig).build()
}
@Test
fun add_shouldAdd_whenNotAlreadyIncluded() {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()
val fakeEvent = createFakeMessageEvent()
chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS)
val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED).let {
realm.copyToRealmOrUpdate(it)
}
chunk.addTimelineEvent(ROOM_ID, fakeEvent, PaginationDirection.FORWARDS, emptyMap())
chunk.timelineEvents.size shouldEqual 1
}
}
@ -63,65 +71,23 @@ internal class ChunkEntityTest : InstrumentedTest {
fun add_shouldNotAdd_whenAlreadyIncluded() {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()
val fakeEvent = createFakeMessageEvent()
chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS)
chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS)
val fakeEvent = createFakeMessageEvent().toEntity(ROOM_ID, SendState.SYNCED).let {
realm.copyToRealmOrUpdate(it)
}
chunk.addTimelineEvent(ROOM_ID, fakeEvent, PaginationDirection.FORWARDS, emptyMap())
chunk.addTimelineEvent(ROOM_ID, fakeEvent, PaginationDirection.FORWARDS, emptyMap())
chunk.timelineEvents.size shouldEqual 1
}
}
@Test
fun add_shouldStateIndexIncremented_whenStateEventIsAddedForward() {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()
val fakeEvent = createFakeRoomMemberEvent()
chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS)
chunk.lastStateIndex(PaginationDirection.FORWARDS) shouldEqual 1
}
}
@Test
fun add_shouldStateIndexNotIncremented_whenNoStateEventIsAdded() {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()
val fakeEvent = createFakeMessageEvent()
chunk.add("roomId", fakeEvent, PaginationDirection.FORWARDS)
chunk.lastStateIndex(PaginationDirection.FORWARDS) shouldEqual 0
}
}
@Test
fun addAll_shouldStateIndexIncremented_whenStateEventsAreAddedForward() {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()
val fakeEvents = createFakeListOfEvents(30)
val numberOfStateEvents = fakeEvents.filter { it.isStateEvent() }.size
chunk.addAll("roomId", fakeEvents, PaginationDirection.FORWARDS)
chunk.lastStateIndex(PaginationDirection.FORWARDS) shouldEqual numberOfStateEvents
}
}
@Test
fun addAll_shouldStateIndexDecremented_whenStateEventsAreAddedBackward() {
monarchy.runTransactionSync { realm ->
val chunk: ChunkEntity = realm.createObject()
val fakeEvents = createFakeListOfEvents(30)
val numberOfStateEvents = fakeEvents.filter { it.isStateEvent() }.size
val lastIsState = fakeEvents.last().isStateEvent()
val expectedStateIndex = if (lastIsState) -numberOfStateEvents + 1 else -numberOfStateEvents
chunk.addAll("roomId", fakeEvents, PaginationDirection.BACKWARDS)
chunk.lastStateIndex(PaginationDirection.BACKWARDS) shouldEqual expectedStateIndex
}
}
@Test
fun merge_shouldAddEvents_whenMergingBackward() {
monarchy.runTransactionSync { realm ->
val chunk1: ChunkEntity = realm.createObject()
val chunk2: ChunkEntity = realm.createObject()
chunk1.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk2.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS)
chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
chunk1.timelineEvents.size shouldEqual 60
}
}
@ -135,38 +101,14 @@ internal class ChunkEntityTest : InstrumentedTest {
val eventsForChunk2 = eventsForChunk1 + createFakeListOfEvents(10)
chunk1.isLastForward = true
chunk2.isLastForward = false
chunk1.addAll("roomId", eventsForChunk1, PaginationDirection.FORWARDS)
chunk2.addAll("roomId", eventsForChunk2, PaginationDirection.BACKWARDS)
chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS)
chunk1.addAll(ROOM_ID, eventsForChunk1, PaginationDirection.FORWARDS)
chunk2.addAll(ROOM_ID, eventsForChunk2, PaginationDirection.BACKWARDS)
chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
chunk1.timelineEvents.size shouldEqual 40
chunk1.isLastForward.shouldBeTrue()
}
}
@Test
fun merge_shouldEventsBeLinked_whenMergingLinkedWithUnlinked() {
monarchy.runTransactionSync { realm ->
val chunk1: ChunkEntity = realm.createObject()
val chunk2: ChunkEntity = realm.createObject()
chunk1.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS, isUnlinked = true)
chunk2.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS, isUnlinked = false)
chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS)
chunk1.isUnlinked().shouldBeFalse()
}
}
@Test
fun merge_shouldEventsBeUnlinked_whenMergingUnlinkedWithUnlinked() {
monarchy.runTransactionSync { realm ->
val chunk1: ChunkEntity = realm.createObject()
val chunk2: ChunkEntity = realm.createObject()
chunk1.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS, isUnlinked = true)
chunk2.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS, isUnlinked = true)
chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS)
chunk1.isUnlinked().shouldBeTrue()
}
}
@Test
fun merge_shouldPrevTokenMerged_whenMergingForwards() {
monarchy.runTransactionSync { realm ->
@ -174,9 +116,9 @@ internal class ChunkEntityTest : InstrumentedTest {
val chunk2: ChunkEntity = realm.createObject()
val prevToken = "prev_token"
chunk1.prevToken = prevToken
chunk1.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS, isUnlinked = true)
chunk2.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS, isUnlinked = true)
chunk1.merge("roomId", chunk2, PaginationDirection.FORWARDS)
chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk1.merge(ROOM_ID, chunk2, PaginationDirection.FORWARDS)
chunk1.prevToken shouldEqual prevToken
}
}
@ -188,11 +130,25 @@ internal class ChunkEntityTest : InstrumentedTest {
val chunk2: ChunkEntity = realm.createObject()
val nextToken = "next_token"
chunk1.nextToken = nextToken
chunk1.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS, isUnlinked = true)
chunk2.addAll("roomId", createFakeListOfEvents(30), PaginationDirection.BACKWARDS, isUnlinked = true)
chunk1.merge("roomId", chunk2, PaginationDirection.BACKWARDS)
chunk1.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk2.addAll(ROOM_ID, createFakeListOfEvents(30), PaginationDirection.BACKWARDS)
chunk1.merge(ROOM_ID, chunk2, PaginationDirection.BACKWARDS)
chunk1.nextToken shouldEqual nextToken
}
}
}
private fun ChunkEntity.addAll(roomId: String,
events: List<Event>,
direction: PaginationDirection) {
events.forEach { event ->
val fakeEvent = event.toEntity(roomId, SendState.SYNCED).let {
realm.copyToRealmOrUpdate(it)
}
addTimelineEvent(roomId, fakeEvent, direction, emptyMap())
}
}
companion object {
private const val ROOM_ID = "roomId"
}
}

View File

@ -32,6 +32,4 @@ internal class FakeGetContextOfEventTask constructor(private val tokenChunkEvent
)
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, PaginationDirection.BACKWARDS)
}
}
}

View File

@ -28,6 +28,4 @@ internal class FakePaginationTask @Inject constructor(private val tokenChunkEven
val tokenChunkEvent = FakeTokenChunkEvent(params.from, Random.nextLong(System.currentTimeMillis()).toString(), fakeEvents)
return tokenChunkEventPersistor.insertInDb(tokenChunkEvent, params.roomId, params.direction)
}
}

View File

@ -23,4 +23,4 @@ internal data class FakeTokenChunkEvent(override val start: String?,
override val end: String?,
override val events: List<Event> = emptyList(),
override val stateEvents: List<Event> = emptyList()
) : TokenChunkEvent
) : TokenChunkEvent

View File

@ -16,21 +16,14 @@
package im.vector.matrix.android.session.room.timeline
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.api.session.events.model.Content
import im.vector.matrix.android.api.session.events.model.Event
import im.vector.matrix.android.api.session.events.model.EventType
import im.vector.matrix.android.api.session.events.model.toContent
import im.vector.matrix.android.api.session.room.model.Membership
import im.vector.matrix.android.api.session.room.model.RoomMember
import im.vector.matrix.android.api.session.room.model.RoomMemberSummary
import im.vector.matrix.android.api.session.room.model.message.MessageTextContent
import im.vector.matrix.android.api.session.room.model.message.MessageType
import im.vector.matrix.android.internal.database.helper.addAll
import im.vector.matrix.android.internal.database.helper.addOrUpdate
import im.vector.matrix.android.internal.database.model.ChunkEntity
import im.vector.matrix.android.internal.database.model.RoomEntity
import im.vector.matrix.android.internal.session.room.timeline.PaginationDirection
import io.realm.kotlin.createObject
import kotlin.random.Random
object RoomDataHelper {
@ -70,24 +63,7 @@ object RoomDataHelper {
}
fun createFakeRoomMemberEvent(): Event {
val roomMember = RoomMember(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent()
val roomMember = RoomMemberSummary(Membership.JOIN, "Fake name #${Random.nextLong()}").toContent()
return createFakeEvent(EventType.STATE_ROOM_MEMBER, roomMember)
}
fun fakeInitialSync(monarchy: Monarchy, roomId: String) {
monarchy.runTransactionSync { realm ->
val roomEntity = realm.createObject<RoomEntity>(roomId)
roomEntity.membership = Membership.JOIN
val eventList = createFakeListOfEvents(10)
val chunkEntity = realm.createObject<ChunkEntity>().apply {
nextToken = null
prevToken = Random.nextLong(System.currentTimeMillis()).toString()
isLastForward = true
}
chunkEntity.addAll(roomId, eventList, PaginationDirection.FORWARDS)
roomEntity.addOrUpdate(chunkEntity)
}
}
}
}

View File

@ -66,7 +66,7 @@ internal class TimelineTest : InstrumentedTest {
// val latch = CountDownLatch(2)
// var timelineEvents: List<TimelineEvent> = emptyList()
// timeline.listener = object : Timeline.Listener {
// override fun onUpdated(snapshot: List<TimelineEvent>) {
// override fun onTimelineUpdated(snapshot: List<TimelineEvent>) {
// if (snapshot.isNotEmpty()) {
// if (initialLoad == 0) {
// initialLoad = snapshot.size
@ -81,6 +81,4 @@ internal class TimelineTest : InstrumentedTest {
// timelineEvents.size shouldEqual initialLoad + paginationCount
// timeline.dispose()
// }
}
}

View File

@ -22,6 +22,7 @@ import okhttp3.Interceptor
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import okio.Buffer
import timber.log.Timber
import java.io.IOException
import java.nio.charset.Charset
import javax.inject.Inject
@ -51,27 +52,33 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
var compressed = false
var curlCmd = "curl"
if (curlOptions != null) {
curlCmd += " " + curlOptions!!
curlOptions?.let {
curlCmd += " $it"
}
curlCmd += " -X " + request.method()
curlCmd += " -X " + request.method
val requestBody = request.body()
val requestBody = request.body
if (requestBody != null) {
val buffer = Buffer()
requestBody.writeTo(buffer)
var charset: Charset? = UTF8
val contentType = requestBody.contentType()
if (contentType != null) {
charset = contentType.charset(UTF8)
if (requestBody.contentLength() > 100_000) {
Timber.w("Unable to log curl command data, size is too big (${requestBody.contentLength()})")
// Ensure the curl command will failed
curlCmd += "DATA IS TOO BIG"
} else {
val buffer = Buffer()
requestBody.writeTo(buffer)
var charset: Charset? = UTF8
val contentType = requestBody.contentType()
if (contentType != null) {
charset = contentType.charset(UTF8)
}
// try to keep to a single line and use a subshell to preserve any line breaks
curlCmd += " --data $'" + buffer.readString(charset!!).replace("\n", "\\n") + "'"
}
// try to keep to a single line and use a subshell to preserve any line breaks
curlCmd += " --data $'" + buffer.readString(charset!!).replace("\n", "\\n") + "'"
}
val headers = request.headers()
val headers = request.headers
var i = 0
val count = headers.size()
val count = headers.size
while (i < count) {
val name = headers.name(i)
val value = headers.value(i)
@ -82,7 +89,7 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
i++
}
curlCmd += ((if (compressed) " --compressed " else " ") + "'" + request.url().toString()
curlCmd += ((if (compressed) " --compressed " else " ") + "'" + request.url.toString()
// Replace localhost for emulator by localhost for shell
.replace("://10.0.2.2:8080/".toRegex(), "://127.0.0.1:8080/")
+ "'")
@ -90,7 +97,7 @@ internal class CurlLoggingInterceptor @Inject constructor(private val logger: Ht
// Add Json formatting
curlCmd += " | python -m json.tool"
logger.log("--- cURL (" + request.url() + ")")
logger.log("--- cURL (" + request.url + ")")
logger.log(curlCmd)
return chain.proceed(request)

View File

@ -51,7 +51,6 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
// Finally this is not a JSON string...
Timber.e(e)
}
} else if (message.startsWith("[")) {
// JSON Array detected
try {
@ -61,7 +60,6 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
// Finally not JSON...
Timber.e(e)
}
}
// Else not a json string to log
}
@ -73,4 +71,4 @@ class FormattedJsonHttpLogger : HttpLoggingInterceptor.Logger {
Timber.v(s)
}
}
}
}

View File

@ -6,9 +6,10 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application>
<application android:networkSecurityConfig="@xml/network_security_config">
<provider android:name="androidx.work.impl.WorkManagerInitializer"
<provider
android:name="androidx.work.impl.WorkManagerInitializer"
android:authorities="${applicationId}.workmanager-init"
android:exported="false"
tools:node="remove" />

View File

@ -22,23 +22,27 @@ import androidx.work.Configuration
import androidx.work.WorkManager
import com.zhuinden.monarchy.Monarchy
import im.vector.matrix.android.BuildConfig
import im.vector.matrix.android.api.auth.Authenticator
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
import im.vector.matrix.android.internal.di.DaggerMatrixComponent
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 javax.inject.Inject
data class MatrixConfiguration(
val applicationFlavor: String = "Default-application-flavor"
val applicationFlavor: String = "Default-application-flavor",
val cryptoConfig: MXCryptoConfig = MXCryptoConfig()
) {
interface Provider {
fun providesMatrixConfiguration(): MatrixConfiguration
}
}
/**
@ -47,7 +51,7 @@ data class MatrixConfiguration(
*/
class Matrix private constructor(context: Context, matrixConfiguration: MatrixConfiguration) {
@Inject internal lateinit var authenticator: Authenticator
@Inject internal lateinit var authenticationService: AuthenticationService
@Inject internal lateinit var userAgentHolder: UserAgentHolder
@Inject internal lateinit var backgroundDetectionObserver: BackgroundDetectionObserver
@Inject internal lateinit var olmManager: OlmManager
@ -55,18 +59,17 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
init {
Monarchy.init(context)
DaggerMatrixComponent.factory().create(context).inject(this)
DaggerMatrixComponent.factory().create(context, matrixConfiguration).inject(this)
if (context.applicationContext !is Configuration.Provider) {
WorkManager.initialize(context, Configuration.Builder().build())
}
ProcessLifecycleOwner.get().lifecycle.addObserver(backgroundDetectionObserver)
userAgentHolder.setApplicationFlavor(matrixConfiguration.applicationFlavor)
}
fun getUserAgent() = userAgentHolder.userAgent
fun authenticator(): Authenticator {
return authenticator
fun authenticationService(): AuthenticationService {
return authenticationService
}
companion object {
@ -97,6 +100,9 @@ class Matrix private constructor(context: Context, matrixConfiguration: MatrixCo
fun getSdkVersion(): String {
return BuildConfig.VERSION_NAME + " (" + BuildConfig.GIT_SDK_REVISION + ")"
}
}
fun decryptStream(inputStream: InputStream?, elementToDecrypt: ElementToDecrypt): InputStream? {
return MXEncryptedAttachments.decryptAttachment(inputStream, elementToDecrypt)
}
}
}

View File

@ -27,7 +27,7 @@ interface MatrixCallback<in T> {
* @param data the data successfully returned from the async function
*/
fun onSuccess(data: T) {
//no-op
// no-op
}
/**
@ -35,7 +35,11 @@ interface MatrixCallback<in T> {
* @param failure the failure data returned from the async function
*/
fun onFailure(failure: Throwable) {
//no-op
// no-op
}
}
}
/**
* Basic no op implementation
*/
class NoOpMatrixCallback<T>: MatrixCallback<T>

View File

@ -16,7 +16,6 @@
package im.vector.matrix.android.api
/**
* This class contains pattern to match the different Matrix ids
*/
@ -123,9 +122,9 @@ object MatrixPatterns {
*/
fun isEventId(str: String?): Boolean {
return str != null
&& (str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4)
&& (str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V3
|| str matches PATTERN_CONTAIN_MATRIX_EVENT_IDENTIFIER_V4)
}
/**
@ -145,15 +144,6 @@ object MatrixPatterns {
* @return null if not found or if matrixId is null
*/
fun extractServerNameFromId(matrixId: String?): String? {
if (matrixId == null) {
return null
}
val index = matrixId.indexOf(":")
return if (index == -1) {
null
} else matrixId.substring(index + 1)
return matrixId?.substringAfter(":", missingDelimiterValue = "")?.takeIf { it.isNotEmpty() }
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth
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.session.Session
import im.vector.matrix.android.api.util.Cancelable
/**
* This interface defines methods to authenticate or to create an account to a matrix server.
*/
interface AuthenticationService {
/**
* Request the supported login flows for this homeserver.
* This is the first method to call to be able to get a wizard to login or the create an account
*/
fun getLoginFlow(homeServerConnectionConfig: HomeServerConnectionConfig, callback: MatrixCallback<LoginFlowResult>): Cancelable
/**
* Return a LoginWizard, to login to the homeserver. The login flow has to be retrieved first.
*/
fun getLoginWizard(): LoginWizard
/**
* Return a RegistrationWizard, to create an matrix account on the homeserver. The login flow has to be retrieved first.
*/
fun getRegistrationWizard(): RegistrationWizard
/**
* True when login and password has been sent with success to the homeserver
*/
val isRegistrationStarted: Boolean
/**
* Cancel pending login or pending registration
*/
fun cancelPendingLoginOrRegistration()
/**
* Reset all pending settings, including current HomeServerConnectionConfig
*/
fun reset()
/**
* Check if there is an authenticated [Session].
* @return true if there is at least one active session.
*/
fun hasAuthenticatedSessions(): Boolean
/**
* Get the last authenticated [Session], if there is an active session.
* @return the last active session if any, or null
*/
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
*/
fun createSessionFromSso(homeServerConnectionConfig: HomeServerConnectionConfig,
credentials: Credentials,
callback: MatrixCallback<Session>): Cancelable
}

View File

@ -1,59 +0,0 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.auth.data.HomeServerConnectionConfig
import im.vector.matrix.android.api.auth.data.SessionParams
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.util.Cancelable
/**
* This interface defines methods to authenticate to a matrix server.
*/
interface Authenticator {
/**
* @param homeServerConnectionConfig this param is used to configure the Homeserver
* @param login the login field
* @param password the password field
* @param callback the matrix callback on which you'll receive the result of authentication.
* @return return a [Cancelable]
*/
fun authenticate(homeServerConnectionConfig: HomeServerConnectionConfig, login: String, password: String, callback: MatrixCallback<Session>): Cancelable
/**
* Check if there is an authenticated [Session].
* @return true if there is at least one active session.
*/
fun hasAuthenticatedSessions(): Boolean
/**
* Get the last authenticated [Session], if there is an active session.
* @return the last active session if any, or null
*/
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?
}

View File

@ -18,6 +18,7 @@ package im.vector.matrix.android.api.auth.data
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
import im.vector.matrix.android.internal.util.md5
/**
* This data class hold credentials user data.
@ -30,4 +31,11 @@ data class Credentials(
@Json(name = "home_server") val homeServer: String,
@Json(name = "access_token") val accessToken: String,
@Json(name = "refresh_token") val refreshToken: String?,
@Json(name = "device_id") val deviceId: String?)
@Json(name = "device_id") val deviceId: String?,
// Optional data that may contain info to override home server and/or identity server
@Json(name = "well_known") val wellKnown: WellKnown? = null
)
internal fun Credentials.sessionId(): String {
return (if (deviceId.isNullOrBlank()) userId else "$userId|$deviceId").md5()
}

View File

@ -25,7 +25,7 @@ import okhttp3.TlsVersion
/**
* This data class holds how to connect to a specific Homeserver.
* It's used with [im.vector.matrix.android.api.auth.Authenticator] class.
* It's used with [im.vector.matrix.android.api.auth.AuthenticationService] class.
* You should use the [Builder] to create one.
*/
@JsonClass(generateAdapter = true)
@ -253,13 +253,5 @@ data class HomeServerConnectionConfig(
forceUsageTlsVersions
)
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth.data
import im.vector.matrix.android.internal.auth.data.LoginFlowResponse
// Either a LoginFlowResponse, or an error if the homeserver is outdated
sealed class LoginFlowResult {
data class Success(
val loginFlowResponse: LoginFlowResponse,
val isLoginAndRegistrationSupported: Boolean,
val homeServerUrl: String
) : LoginFlowResult()
object OutdatedHomeserver : LoginFlowResult()
}

View File

@ -22,5 +22,6 @@ package im.vector.matrix.android.api.auth.data
*/
data class SessionParams(
val credentials: Credentials,
val homeServerConnectionConfig: HomeServerConnectionConfig
val homeServerConnectionConfig: HomeServerConnectionConfig,
val isTokenValid: Boolean
)

View File

@ -0,0 +1,111 @@
/*
* Copyright 2018 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.auth.data
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* Model for https://matrix.org/docs/spec/client_server/latest#get-matrix-client-versions
*
* Ex:
* <pre>
* {
* "unstable_features": {
* "m.lazy_load_members": true
* },
* "versions": [
* "r0.0.1",
* "r0.1.0",
* "r0.2.0",
* "r0.3.0"
* ]
* }
* </pre>
*/
@JsonClass(generateAdapter = true)
data class Versions(
@Json(name = "versions")
val supportedVersions: List<String>? = null,
@Json(name = "unstable_features")
val unstableFeatures: Map<String, Boolean>? = null
)
// MatrixClientServerAPIVersion
private const val r0_0_1 = "r0.0.1"
private const val r0_1_0 = "r0.1.0"
private const val r0_2_0 = "r0.2.0"
private const val r0_3_0 = "r0.3.0"
private const val r0_4_0 = "r0.4.0"
private const val r0_5_0 = "r0.5.0"
private const val r0_6_0 = "r0.6.0"
// MatrixVersionsFeature
private const val FEATURE_LAZY_LOAD_MEMBERS = "m.lazy_load_members"
private const val FEATURE_REQUIRE_IDENTITY_SERVER = "m.require_identity_server"
private const val FEATURE_ID_ACCESS_TOKEN = "m.id_access_token"
private const val FEATURE_SEPARATE_ADD_AND_BIND = "m.separate_add_and_bind"
/**
* Return true if the SDK supports this homeserver version
*/
fun Versions.isSupportedBySdk(): Boolean {
return supportLazyLoadMembers()
}
/**
* Return true if the SDK supports this homeserver version for login and registration
*/
fun Versions.isLoginAndRegistrationSupportedBySdk(): Boolean {
return !doesServerRequireIdentityServerParam()
&& doesServerAcceptIdentityAccessToken()
&& doesServerSeparatesAddAndBind()
}
/**
* Return true if the server support the lazy loading of room members
*
* @return true if the server support the lazy loading of room members
*/
private fun Versions.supportLazyLoadMembers(): Boolean {
return supportedVersions?.contains(r0_5_0) == true
|| unstableFeatures?.get(FEATURE_LAZY_LOAD_MEMBERS) == true
}
/**
* Indicate if the `id_server` parameter is required when registering with an 3pid,
* adding a 3pid or resetting password.
*/
private fun Versions.doesServerRequireIdentityServerParam(): Boolean {
if (supportedVersions?.contains(r0_6_0) == true) return false
return unstableFeatures?.get(FEATURE_REQUIRE_IDENTITY_SERVER) ?: true
}
/**
* Indicate if the `id_access_token` parameter can be safely passed to the homeserver.
* Some homeservers may trigger errors if they are not prepared for the new parameter.
*/
private fun Versions.doesServerAcceptIdentityAccessToken(): Boolean {
return supportedVersions?.contains(r0_6_0) == true
|| unstableFeatures?.get(FEATURE_ID_ACCESS_TOKEN) ?: false
}
private fun Versions.doesServerSeparatesAddAndBind(): Boolean {
return supportedVersions?.contains(r0_6_0) == true
|| unstableFeatures?.get(FEATURE_SEPARATE_ADD_AND_BIND) ?: false
}

View File

@ -0,0 +1,82 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth.data
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
* <pre>
* {
* "m.homeserver": {
* "base_url": "https://matrix.org"
* },
* "m.identity_server": {
* "base_url": "https://vector.im"
* }
* "m.integrations": {
* "managers": [
* {
* "api_url": "https://integrations.example.org",
* "ui_url": "https://integrations.example.org/ui"
* },
* {
* "api_url": "https://bots.example.org"
* }
* ]
* }
* }
* </pre>
*/
@JsonClass(generateAdapter = true)
data class WellKnown(
@Json(name = "m.homeserver")
val homeServer: WellKnownBaseConfig? = null,
@Json(name = "m.identity_server")
val identityServer: WellKnownBaseConfig? = null,
@Json(name = "m.integrations")
val integrations: Map<String, @JvmSuppressWildcards Any>? = 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

@ -0,0 +1,34 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth.data
import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass
/**
* https://matrix.org/docs/spec/client_server/r0.4.0.html#server-discovery
* <pre>
* {
* "base_url": "https://vector.im"
* }
* </pre>
*/
@JsonClass(generateAdapter = true)
data class WellKnownBaseConfig(
@Json(name = "base_url")
val baseURL: String? = null
)

View File

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

View File

@ -0,0 +1,48 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth.login
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.session.Session
import im.vector.matrix.android.api.util.Cancelable
interface LoginWizard {
/**
* @param login the login field
* @param password the password field
* @param deviceName the initial device name
* @param callback the matrix callback on which you'll receive the result of authentication.
* @return return a [Cancelable]
*/
fun login(login: String,
password: String,
deviceName: String,
callback: MatrixCallback<Session>): Cancelable
/**
* Reset user password
*/
fun resetPassword(email: String,
newPassword: String,
callback: MatrixCallback<Unit>): Cancelable
/**
* Confirm the new password, once the user has checked his email
*/
fun resetPasswordMailConfirmed(callback: MatrixCallback<Unit>): Cancelable
}

View File

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

View File

@ -0,0 +1,30 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth.registration
import im.vector.matrix.android.api.session.Session
// Either a session or an object containing data about registration stages
sealed class RegistrationResult {
data class Success(val session: Session) : RegistrationResult()
data class FlowResponse(val flowResult: FlowResult) : RegistrationResult()
}
data class FlowResult(
val missingStages: List<Stage>,
val completedStages: List<Stage>
)

View File

@ -0,0 +1,46 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth.registration
import im.vector.matrix.android.api.MatrixCallback
import im.vector.matrix.android.api.util.Cancelable
interface RegistrationWizard {
fun getRegistrationFlow(callback: MatrixCallback<RegistrationResult>): Cancelable
fun createAccount(userName: String, password: String, initialDeviceDisplayName: String?, callback: MatrixCallback<RegistrationResult>): Cancelable
fun performReCaptcha(response: String, callback: MatrixCallback<RegistrationResult>): Cancelable
fun acceptTerms(callback: MatrixCallback<RegistrationResult>): Cancelable
fun dummy(callback: MatrixCallback<RegistrationResult>): Cancelable
fun addThreePid(threePid: RegisterThreePid, callback: MatrixCallback<RegistrationResult>): Cancelable
fun sendAgainThreePid(callback: MatrixCallback<RegistrationResult>): Cancelable
fun handleValidateThreePid(code: String, callback: MatrixCallback<RegistrationResult>): Cancelable
fun checkIfEmailHasBeenValidated(delayMillis: Long, callback: MatrixCallback<RegistrationResult>): Cancelable
val currentThreePid: String?
// True when login and password has been sent with success to the homeserver
val isRegistrationStarted: Boolean
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.auth.registration
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)
// Undocumented yet: m.login.terms
data class Terms(override val mandatory: Boolean, val policies: TermPolicies) : Stage(mandatory)
// For unknown stages
data class Other(override val mandatory: Boolean, val type: String, val params: Map<*, *>?) : Stage(mandatory)
}
typealias TermPolicies = Map<*, *>

View File

@ -17,7 +17,6 @@
package im.vector.matrix.android.api.comparators
import im.vector.matrix.android.api.interfaces.DatedObject
import java.util.*
object DatedObjectComparators {
@ -38,4 +37,4 @@ object DatedObjectComparators {
(datedObject2.date - datedObject1.date).toInt()
}
}
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.crypto
import im.vector.matrix.android.api.session.crypto.verification.EmojiRepresentation
import im.vector.matrix.android.internal.crypto.verification.getEmojiForCode
/**
* Provide all the emojis used for SAS verification (for debug purpose)
*/
fun getAllVerificationEmojis(): List<EmojiRepresentation> {
return (0..63).map { getEmojiForCode(it) }
}

View File

@ -14,14 +14,14 @@
* limitations under the License.
*/
package im.vector.matrix.android.internal.crypto
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(
// Tell whether the encryption of the event content is enabled for the invited members.
// By default, we encrypt messages only for the joined members.
// The encryption for the invited members will be blocked if the history visibility is "joined".
var enableEncryptionForInvitedMembers: Boolean = false
// 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
)

View File

@ -0,0 +1,31 @@
/*
* 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.crypto
/**
* RoomEncryptionTrustLevel represents the trust level in an encrypted room.
*/
enum class RoomEncryptionTrustLevel {
// No one in the room has been verified -> Black shield
Default,
// There are one or more device un-verified -> the app should display a red shield
Warning,
// All devices in the room are verified -> the app should display a green shield
Trusted
}

View File

@ -0,0 +1,21 @@
/*
* 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.extensions
fun Boolean?.orTrue() = this ?: true
fun Boolean?.orFalse() = this ?: false

View File

@ -16,20 +16,21 @@
package im.vector.matrix.android.api.extensions
import im.vector.matrix.android.api.comparators.DatedObjectComparators
import im.vector.matrix.android.internal.crypto.model.MXDeviceInfo
import im.vector.matrix.android.internal.crypto.model.CryptoDeviceInfo
import im.vector.matrix.android.internal.crypto.model.rest.DeviceInfo
import java.util.*
/* ==========================================================================================
* MXDeviceInfo
* ========================================================================================== */
fun MXDeviceInfo.getFingerprintHumanReadable() = fingerprint()
fun CryptoDeviceInfo.getFingerprintHumanReadable() = fingerprint()
?.chunked(4)
?.joinToString(separator = " ")
/* ==========================================================================================
* DeviceInfo
* ========================================================================================== */
fun List<DeviceInfo>.sortByLastSeen() {
Collections.sort(this, DatedObjectComparators.descComparator)
}
fun List<DeviceInfo>.sortByLastSeen(): List<DeviceInfo> {
return this.sortedByDescending { it.lastSeenTs ?: 0 }
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.failure
import javax.net.ssl.HttpsURLConnection
fun Throwable.is401() =
this is Failure.ServerError
&& httpCode == HttpsURLConnection.HTTP_UNAUTHORIZED /* 401 */
&& error.code == MatrixError.M_UNAUTHORIZED
fun Throwable.isTokenError() =
this is Failure.ServerError
&& (error.code == MatrixError.M_UNKNOWN_TOKEN || error.code == MatrixError.M_MISSING_TOKEN)
fun Throwable.shouldBeRetried(): Boolean {
return this is Failure.NetworkConnection
|| (this is Failure.ServerError && error.code == MatrixError.M_LIMIT_EXCEEDED)
}

View File

@ -31,15 +31,16 @@ import java.io.IOException
*/
sealed class Failure(cause: Throwable? = null) : Throwable(cause = cause) {
data class Unknown(val throwable: Throwable? = null) : Failure(throwable)
data class Cancelled(val throwable: Throwable? = null) : Failure(throwable)
data class NetworkConnection(val ioException: IOException? = null) : Failure(ioException)
data class ServerError(val error: MatrixError, val httpCode: Int) : Failure(RuntimeException(error.toString()))
object SuccessError : Failure(RuntimeException(RuntimeException("SuccessResult is false")))
// When server send an error, but it cannot be interpreted as a MatrixError
data class OtherServerError(val errorBody: String, val httpCode: Int) : Failure(RuntimeException(errorBody))
data class OtherServerError(val errorBody: String, val httpCode: Int) : Failure(RuntimeException("HTTP $httpCode: $errorBody"))
data class RegistrationFlowError(val registrationFlowResponse: RegistrationFlowResponse) : Failure(RuntimeException(registrationFlowResponse.toString()))
data class CryptoError(val error: MXCryptoError) : Failure(error)
abstract class FeatureFailure : Failure()
}
}

View File

@ -0,0 +1,23 @@
/*
* Copyright 2019 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.matrix.android.api.failure
// This class will be sent to the bus
sealed class GlobalError {
data class InvalidToken(val softLogout: Boolean) : GlobalError()
data class ConsentNotGivenError(val consentUri: String) : GlobalError()
}

View File

@ -22,46 +22,114 @@ import com.squareup.moshi.JsonClass
/**
* This data class holds the error defined by the matrix specifications.
* You shouldn't have to instantiate it.
* Ref: https://matrix.org/docs/spec/client_server/latest#api-standards
*/
@JsonClass(generateAdapter = true)
data class MatrixError(
/** unique string which can be used to handle an error message */
@Json(name = "errcode") val code: String,
/** human-readable error message */
@Json(name = "error") val message: String,
// For M_CONSENT_NOT_GIVEN
@Json(name = "consent_uri") val consentUri: String? = null,
// RESOURCE_LIMIT_EXCEEDED data
// For M_RESOURCE_LIMIT_EXCEEDED
@Json(name = "limit_type") val limitType: String? = null,
@Json(name = "admin_contact") val adminUri: String? = null) {
@Json(name = "admin_contact") val adminUri: String? = null,
// 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
) {
companion object {
const val FORBIDDEN = "M_FORBIDDEN"
const val UNKNOWN = "M_UNKNOWN"
const val UNKNOWN_TOKEN = "M_UNKNOWN_TOKEN"
const val MISSING_TOKEN = "M_MISSING_TOKEN"
const val BAD_JSON = "M_BAD_JSON"
const val NOT_JSON = "M_NOT_JSON"
const val NOT_FOUND = "M_NOT_FOUND"
const val LIMIT_EXCEEDED = "M_LIMIT_EXCEEDED"
const val USER_IN_USE = "M_USER_IN_USE"
const val ROOM_IN_USE = "M_ROOM_IN_USE"
const val BAD_PAGINATION = "M_BAD_PAGINATION"
const val UNAUTHORIZED = "M_UNAUTHORIZED"
const val OLD_VERSION = "M_OLD_VERSION"
const val UNRECOGNIZED = "M_UNRECOGNIZED"
/** Forbidden access, e.g. joining a room without permission, failed login. */
const val M_FORBIDDEN = "M_FORBIDDEN"
/** An unknown error has occurred. */
const val M_UNKNOWN = "M_UNKNOWN"
/** The access token specified was not recognised. */
const val M_UNKNOWN_TOKEN = "M_UNKNOWN_TOKEN"
/** No access token was specified for the request. */
const val M_MISSING_TOKEN = "M_MISSING_TOKEN"
/** Request contained valid JSON, but it was malformed in some way, e.g. missing required keys, invalid values for keys. */
const val M_BAD_JSON = "M_BAD_JSON"
/** Request did not contain valid JSON. */
const val M_NOT_JSON = "M_NOT_JSON"
/** No resource was found for this request. */
const val M_NOT_FOUND = "M_NOT_FOUND"
/** Too many requests have been sent in a short period of time. Wait a while then try again. */
const val M_LIMIT_EXCEEDED = "M_LIMIT_EXCEEDED"
const val LOGIN_EMAIL_URL_NOT_YET = "M_LOGIN_EMAIL_URL_NOT_YET"
const val THREEPID_AUTH_FAILED = "M_THREEPID_AUTH_FAILED"
// Error code returned by the server when no account matches the given 3pid
const val THREEPID_NOT_FOUND = "M_THREEPID_NOT_FOUND"
const val THREEPID_IN_USE = "M_THREEPID_IN_USE"
const val SERVER_NOT_TRUSTED = "M_SERVER_NOT_TRUSTED"
const val TOO_LARGE = "M_TOO_LARGE"
/* ==========================================================================================
* Other error codes the client might encounter are
* ========================================================================================== */
/** Encountered when trying to register a user ID which has been taken. */
const val M_USER_IN_USE = "M_USER_IN_USE"
/** Sent when the room alias given to the createRoom API is already in use. */
const val M_ROOM_IN_USE = "M_ROOM_IN_USE"
/** (Not documented yet) */
const val M_BAD_PAGINATION = "M_BAD_PAGINATION"
/** The request was not correctly authorized. Usually due to login failures. */
const val M_UNAUTHORIZED = "M_UNAUTHORIZED"
/** (Not documented yet) */
const val M_OLD_VERSION = "M_OLD_VERSION"
/** The server did not understand the request. */
const val M_UNRECOGNIZED = "M_UNRECOGNIZED"
/** (Not documented yet) */
const val M_LOGIN_EMAIL_URL_NOT_YET = "M_LOGIN_EMAIL_URL_NOT_YET"
/** Authentication could not be performed on the third party identifier. */
const val M_THREEPID_AUTH_FAILED = "M_THREEPID_AUTH_FAILED"
/** Sent when a threepid given to an API cannot be used because no record matching the threepid was found. */
const val M_THREEPID_NOT_FOUND = "M_THREEPID_NOT_FOUND"
/** Sent when a threepid given to an API cannot be used because the same threepid is already in use. */
const val M_THREEPID_IN_USE = "M_THREEPID_IN_USE"
/** The client's request used a third party server, eg. identity server, that this server does not trust. */
const val M_SERVER_NOT_TRUSTED = "M_SERVER_NOT_TRUSTED"
/** The request or entity was too large. */
const val M_TOO_LARGE = "M_TOO_LARGE"
/** (Not documented yet) */
const val M_CONSENT_NOT_GIVEN = "M_CONSENT_NOT_GIVEN"
const val RESOURCE_LIMIT_EXCEEDED = "M_RESOURCE_LIMIT_EXCEEDED"
const val WRONG_ROOM_KEYS_VERSION = "M_WRONG_ROOM_KEYS_VERSION"
/** The request cannot be completed because the homeserver has reached a resource limit imposed on it. For example,
* a homeserver held in a shared hosting environment may reach a resource limit if it starts using too much memory
* or disk space. The error MUST have an admin_contact field to provide the user receiving the error a place to reach
* out to. Typically, this error will appear on routes which attempt to modify state (eg: sending messages, account
* data, etc) and not routes which only read state (eg: /sync, get account data, etc). */
const val M_RESOURCE_LIMIT_EXCEEDED = "M_RESOURCE_LIMIT_EXCEEDED"
/** The user ID associated with the request has been deactivated. Typically for endpoints that prove authentication, such as /login. */
const val M_USER_DEACTIVATED = "M_USER_DEACTIVATED"
/** Encountered when trying to register a user ID which is not valid. */
const val M_INVALID_USERNAME = "M_INVALID_USERNAME"
/** Sent when the initial state given to the createRoom API is invalid. */
const val M_INVALID_ROOM_STATE = "M_INVALID_ROOM_STATE"
/** The server does not permit this third party identifier. This may happen if the server only permits,
* for example, email addresses from a particular domain. */
const val M_THREEPID_DENIED = "M_THREEPID_DENIED"
/** The client's request to create a room used a room version that the server does not support. */
const val M_UNSUPPORTED_ROOM_VERSION = "M_UNSUPPORTED_ROOM_VERSION"
/** The client attempted to join a room that has a version the server does not support.
* Inspect the room_version property of the error response for the room's version. */
const val M_INCOMPATIBLE_ROOM_VERSION = "M_INCOMPATIBLE_ROOM_VERSION"
/** The state change requested cannot be performed, such as attempting to unban a user who is not banned. */
const val M_BAD_STATE = "M_BAD_STATE"
/** The room or resource does not permit guests to access it. */
const val M_GUEST_ACCESS_FORBIDDEN = "M_GUEST_ACCESS_FORBIDDEN"
/** A Captcha is required to complete the request. */
const val M_CAPTCHA_NEEDED = "M_CAPTCHA_NEEDED"
/** The Captcha provided did not match what was expected. */
const val M_CAPTCHA_INVALID = "M_CAPTCHA_INVALID"
/** A required parameter was missing from the request. */
const val M_MISSING_PARAM = "M_MISSING_PARAM"
/** A parameter that was specified has the wrong value. For example, the server expected an integer and instead received a string. */
const val M_INVALID_PARAM = "M_INVALID_PARAM"
/** The resource being requested is reserved by an application service, or the application service making the request has not created the resource. */
const val M_EXCLUSIVE = "M_EXCLUSIVE"
/** The user is unable to reject an invite to join the server notices room. See the Server Notices module for more information. */
const val M_CANNOT_LEAVE_SERVER_NOTICE_ROOM = "M_CANNOT_LEAVE_SERVER_NOTICE_ROOM"
/** (Not documented yet) */
const val M_WRONG_ROOM_KEYS_VERSION = "M_WRONG_ROOM_KEYS_VERSION"
// Possible value for "limit_type"
const val LIMIT_TYPE_MAU = "monthly_active_user"
}
}
}

View File

@ -21,8 +21,9 @@ package im.vector.matrix.android.api.listeners
*/
interface ProgressListener {
/**
* Will be invoked on the background thread, not in UI thread.
* @param progress from 0 to total by contract
* @param total
*/
fun onProgress(progress: Int, total: Int)
}
}

View File

@ -31,4 +31,4 @@ interface StepProgressListener {
* @param step The current step, containing progress data if available. Else you should consider progress as indeterminate
*/
fun onStepProgress(step: Step)
}
}

View File

@ -17,7 +17,6 @@
package im.vector.matrix.android.api.permalinks
import android.text.Spannable
import im.vector.matrix.android.api.MatrixPatterns
/**
* MatrixLinkify take a piece of text and turns all of the
@ -30,9 +29,15 @@ object MatrixLinkify {
*
* @param spannable the text in which the matrix items has to be clickable.
*/
fun addLinks(spannable: Spannable?, callback: MatrixPermalinkSpan.Callback?): Boolean {
@Suppress("UNUSED_PARAMETER")
fun addLinks(spannable: Spannable, callback: MatrixPermalinkSpan.Callback?): Boolean {
/**
* I disable it because it mess up with pills, and even with pills, it does not work correctly:
* The url is not correct. Ex: for @user:matrix.org, the url will be @user:matrix.org, instead of a matrix.to
*/
/*
// sanity checks
if (spannable.isNullOrEmpty()) {
if (spannable.isEmpty()) {
return false
}
val text = spannable.toString()
@ -50,6 +55,7 @@ object MatrixLinkify {
}
}
return hasMatch
*/
return false
}
}
}

View File

@ -35,6 +35,4 @@ class MatrixPermalinkSpan(private val url: String,
override fun onClick(widget: View) {
callback?.onUrlClicked(url)
}
}
}

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