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

Compare commits

...

228 Commits

Author SHA1 Message Date
Adam Brown
f299615b02 forcing the screenshot test to fail 2022-09-27 11:07:44 +01:00
Adam Brown
2d2b2e9218 using latest upload-artifact action (should fix missing glob) 2022-09-27 11:03:44 +01:00
Adam Brown
28f4e79b43 attempting to use 0% difference for screenshot verification
- this may cause false errors with the navigation/status bar https://github.com/cashapp/paparazzi/issues/453#issuecomment-1254001714
2022-09-27 10:16:45 +01:00
Adam Brown
4a81ee25ac manually including the paparazzi jar as the plugin is only applied when executing the screenshot tasks (which automatically included the jar previously) 2022-09-26 15:13:37 +01:00
Adam Brown
be1e8a8ef8 adding and recording example paparazzi test 2022-09-26 14:14:03 +01:00
Adam Brown
df752b9e58 Merge pull request #7210 from vector-im/feature/adm/emulator-network-access
Missing buildjet Emulator network
2022-09-26 13:39:12 +01:00
Adam Brown
2e4ca1d6d9 ensuring build flags are applied to all test steps 2022-09-26 12:29:28 +01:00
Adam Brown
ac9333312a switching emulator image to the playstore variant to fix no network on the buildjet runner
- updates max workers to match available resources
- re-enables previously failing test
2022-09-26 12:28:50 +01:00
Adam Brown
59e7b70b03 Merge pull request #7128 from vector-im/feature/adm/screenshot-testing-setup
Paparazzi screenshot testing setup
2022-09-26 12:01:01 +01:00
Jorge Martín
90e4760ee7 Fix VoiceRecorderLTests by faking OggOpusEncoder 2022-09-26 11:32:29 +02:00
Adam Brown
c0baa2e8fd making use of the lazy task registration to allow only applying the paparazzi plugin when needed 2022-09-26 10:26:39 +01:00
Adam Brown
dc0599f966 removing jetifier screenshot config as the jetifier is no longer needed 2022-09-26 10:26:39 +01:00
Adam Brown
7d18d89a61 adding missing colon to yml run param 2022-09-26 10:26:39 +01:00
Adam Brown
7740404b14 using ## heading for the examples block 2022-09-26 10:26:39 +01:00
Adam Brown
469dd46a45 adding changelog entry 2022-09-26 10:26:39 +01:00
Adam Brown
1fab6e69c5 adding origin of bash script url 2022-09-26 10:26:39 +01:00
Adam Brown
c19b359f43 adding docs for creating, recording and verifying screenshot tests 2022-09-26 10:26:39 +01:00
Adam Brown
243ca01924 including lfs files when checking out during tests workflow 2022-09-26 10:26:39 +01:00
Adam Brown
b0e2596b58 including screenshot verification and error result uploads as part of the test step 2022-09-26 10:26:38 +01:00
Adam Brown
7f8cb4b1a1 ignoring the screenshot failure results from git 2022-09-26 10:26:38 +01:00
Adam Brown
0f19726fe2 creating custom tasks to record and verify screenshot
- introduces a 'screenshot' flag to include/exclude the screenshot tests from the default test runs
2022-09-26 10:26:38 +01:00
Adam Brown
9ef4975025 adding github action to validate screenshot files are commited with git lfs 2022-09-26 10:26:38 +01:00
Adam Brown
9fd77044a9 including git lfs config for picking up screenshot test recordings 2022-09-26 10:26:38 +01:00
Adam Brown
c66a38057e adding paparazzi screenshot testing lib setup 2022-09-26 10:26:38 +01:00
Adam Brown
2c1eef7a59 Merge pull request #7142 from vector-im/feature/adm/dialpad-lib
Manually including `im.dlg:android-dialer:1.2.5`
2022-09-26 10:14:56 +01:00
Maxime NATUREL
223149805b Merge pull request #7189 from vector-im/feature/mna/device-manager-rename-session
[Device management] Rename a session (PSG-747)
2022-09-26 10:35:15 +02:00
Maxime NATUREL
7a4bf83da0 Fix lint issue 2022-09-26 09:46:58 +02:00
Maxime NATUREL
fd85ad0f1b Add Init action + corresponding initialized event 2022-09-26 09:46:58 +02:00
Maxime NATUREL
e437c9e131 Updating info icon tint color 2022-09-26 09:46:58 +02:00
Maxime NATUREL
f0fe636654 Fix file name for styles of session warning info view 2022-09-26 09:46:58 +02:00
Maxime NATUREL
5de097e251 Adding warning info view 2022-09-26 09:46:58 +02:00
Maxime NATUREL
bd9b843df7 Focus on edit text + open keyboard when landing on screen 2022-09-26 09:46:58 +02:00
Maxime NATUREL
5498a7e96e Adding unit tests for view model 2022-09-26 09:46:58 +02:00
Maxime NATUREL
c96d671e6b Adding unit tests for navigator 2022-09-26 09:46:58 +02:00
Maxime NATUREL
4a3966d4f5 Improve rename session use case and add tests 2022-09-26 09:46:58 +02:00
Maxime NATUREL
d7afea7b3a Rename session use case 2022-09-26 09:46:58 +02:00
Maxime NATUREL
b134d35dd6 Adding save button and view actions 2022-09-26 09:46:58 +02:00
Maxime NATUREL
33cf3d3032 Setup a custom toolbar 2022-09-26 09:46:58 +02:00
Maxime NATUREL
7eab37e9d1 Small renaming of navigator method 2022-09-26 09:46:58 +02:00
Maxime NATUREL
c3d359e58f Adding edit text into the screen 2022-09-26 09:46:58 +02:00
Maxime NATUREL
54aec63f6c Small improvement in code readability 2022-09-26 09:46:58 +02:00
Maxime NATUREL
82fabf4a85 Adding menu with rename action in session overview screen 2022-09-26 09:46:58 +02:00
Maxime NATUREL
3de96a3a0c Adding new method into navigator 2022-09-26 09:46:58 +02:00
Maxime NATUREL
1091ae41ad Default structure for the new code 2022-09-26 09:46:58 +02:00
Maxime NATUREL
45b72483fe Adding changelog entry 2022-09-26 09:46:58 +02:00
Maxime NATUREL
a83be29dbe Merge pull request #7206 from vector-im/feature/mna/mutualize-pending-auth
Mutualize the pending auth handling (PSG-742)
2022-09-26 09:45:52 +02:00
Adam Brown
d0bff7495d Merge pull request #7205 from vector-im/dependabot/gradle/fragment-1.5.3
Bump fragment from 1.5.2 to 1.5.3
2022-09-23 15:56:51 +01:00
Maxime NATUREL
c9eaf30057 Updating the log in ssoAuthDone method to improve privacy 2022-09-23 16:39:41 +02:00
Maxime NATUREL
854a604fbe Fix missing loading ViewEvent 2022-09-23 16:39:41 +02:00
Maxime NATUREL
99c2088d0e Using UiaCancelledException on reAuth cancellation 2022-09-23 16:39:41 +02:00
Maxime NATUREL
0d7d841d73 Adding unit tests 2022-09-23 16:39:41 +02:00
Maxime NATUREL
0cd352ccba Adding changelog entry 2022-09-23 16:39:41 +02:00
Maxime NATUREL
892fd4445c Mutualize pending auth handling 2022-09-23 16:39:41 +02:00
Onuray Sahin
6c79aae3aa Merge pull request #7171 from vector-im/feature/ons/device_manager_security_sessions
[Device Manager] Unverified and inactive sessions list (PSG-698, PSG-696)
2022-09-23 17:22:44 +03:00
Onuray Sahin
7cd30a1ed4 Merge branch 'develop' into feature/ons/device_manager_security_sessions 2022-09-23 16:16:49 +03:00
Benoit Marty
4fb7154f2b Merge pull request #7187 from vector-im/dependabot/gradle/com.github.UnifiedPush-android-connector-2.1.0
Bump android-connector from 2.0.1 to 2.1.0
2022-09-23 15:13:59 +02:00
Benoit Marty
46311356b7 Merge pull request #7222 from vector-im/feature/bma/ignore_flaky_test
Ignore flaky test "CantVerifyTest" and "fix" VoiceRecorderLTests
2022-09-23 15:10:30 +02:00
ganfra
6cba51eff3 Update changelog 1.5.0 for fastlane 2022-09-23 15:09:17 +02:00
Benoit Marty
97b3b2363b Disable not passing VoiceRecorderLTests, for the time we are investigating the issue. 2022-09-23 14:09:44 +02:00
ganfra
92be6d1b49 Merge branch 'main' into develop 2022-09-23 12:20:00 +02:00
ganfra
8d112a47d7 Merge branch 'hotfix/1.5.0_disable_applayout' into main 2022-09-23 12:20:00 +02:00
Benoit Marty
56f3ecc4af Disable flaky CantVerifyTest, for the time we are investigating the issue. 2022-09-23 11:46:40 +02:00
ganfra
f8ed3520f5 Applayout: disable applayout by default 2022-09-23 11:45:34 +02:00
Benoit Marty
56189a2d5d Merge pull request #7211 from vector-im/feature/bma/prevent_modification_of_translations
Prevent modification of translations
2022-09-23 10:46:38 +02:00
ganfra
cb6d0a66cb Merge branch 'hotfix/1.5.0_v2' into main 2022-09-22 18:18:26 +02:00
ganfra
40e304a4ff Merge branch 'main' into develop 2022-09-22 18:18:26 +02:00
ganfra
8d94643ff7 RoomList: revert changes on LiveData and fix previous issues (not updated list) 2022-09-22 18:17:55 +02:00
Benoit Marty
a5ab942097 Add TOC to CONTRIBUTING.md 2022-09-22 17:52:52 +02:00
Benoit Marty
a07761dedb Fix issue with knit. 2022-09-22 17:48:38 +02:00
Benoit Marty
c56f33a939 Add changelog 2022-09-22 17:36:08 +02:00
Benoit Marty
60bfd0dd42 Merge pull request #7159 from vector-im/feature/bma/fix_new_lint_warning
Fix lint warning
2022-09-22 17:35:10 +02:00
Benoit Marty
6e2ce10f65 Add a note for string reordering 2022-09-22 17:22:58 +02:00
Benoit Marty
97c3623f89 Add a note for plurals 2022-09-22 17:22:58 +02:00
Benoit Marty
729eba750b Add link to the file values/strings.xml, and fix typo in the path. 2022-09-22 17:22:58 +02:00
Benoit Marty
a7856db218 Add a section about renaming id of String resource 2022-09-22 17:10:46 +02:00
Benoit Marty
cefe2e9ef4 Add a rule to Danger to check that translation files are not modified by developers. 2022-09-22 17:03:45 +02:00
Benoit Marty
f4c5cba020 Merge pull request #7126 from vector-im/feature/bma/arch_doc
Architecture doc
2022-09-22 16:41:17 +02:00
Adam Brown
65156a8ece Merge pull request #7198 from vector-im/feature/adm/configurable-sync-timeout
Allow configurable sync timeout
2022-09-22 15:40:58 +01:00
Benoit Marty
828413c2c5 Fix some typo 2022-09-22 16:40:34 +02:00
Benoit Marty
086a6ee9a1 Update after Ganfra's review 2022-09-22 16:39:35 +02:00
Benoit Marty
3600e374f2 Avoid code duplication 2022-09-22 16:34:07 +02:00
Benoit Marty
0559911f39 Fix non passing tests 2022-09-22 16:34:07 +02:00
Benoit Marty
7f5c712e88 No need to use @SuppressLint("NewApi") when @ChecksSdkIntAtLeast is used - more cleanup 2022-09-22 16:34:07 +02:00
Benoit Marty
658a09ea6a No need to use @SuppressLint("NewApi") when @ChecksSdkIntAtLeast is used. 2022-09-22 16:32:14 +02:00
Benoit Marty
5886245bbf Reverse condition for code clarity with ChecksSdkIntAtLeast 2022-09-22 16:32:14 +02:00
Benoit Marty
0910b118ff Changelog 2022-09-22 16:32:14 +02:00
Benoit Marty
2bda97224c Cleanup 2022-09-22 16:32:14 +02:00
Benoit Marty
2266723789 Remove DefaultSharedPreferences since we now have @DefaultPreferences which provide a singleton. 2022-09-22 16:32:14 +02:00
Benoit Marty
c735ea5e3d Remove duplication between KeysBackupBanner.State and ServerBackupStatusViewModel.BannerState and move the some logic to the ViewModel 2022-09-22 16:32:14 +02:00
Benoit Marty
b4494ee8ea Remove DefaultSharedPreferences since we now have @DefaultPreferences which provide a singleton.
Some fun has been moved to injectable classes due to this change. Not compiling, still work to do, but I prefer to split into 2 separate commits.
2022-09-22 16:32:14 +02:00
Benoit Marty
5736c8f648 Remove DefaultSharedPreferences since we now have @DefaultPreferences which provide a singleton.
Some fun has been moved to injectable classes due to this change. Not compiling, still work to do, but I prefer to split into 2 separate commits.
2022-09-22 16:32:14 +02:00
Benoit Marty
0324927b04 Create VectorLocaleProvider, to just read the current Locale from the SharedPreference 2022-09-22 16:32:14 +02:00
Benoit Marty
d8436874e2 Fix StaticFieldLeak issue (context).
Make VectorLocal an injectable class.
2022-09-22 16:32:14 +02:00
Benoit Marty
7e8a39e6de Suppress LaunchActivityFromNotification. This is fine here, this is the notification for the diagnostic, we do not want to start an Activity. 2022-09-22 16:32:14 +02:00
Benoit Marty
832a472b57 Add @ChecksSdkIntAtLeast annotation, to be able to remove AndroidVersionTestOverrider 2022-09-22 16:32:14 +02:00
Benoit Marty
bb2eb56ee6 Add @ChecksSdkIntAtLeast annotation. 2022-09-22 16:32:14 +02:00
Benoit Marty
1ff4a5f212 Ignore AlwaysShowAction lint issue. Also make it an error, so that developer has to explicitly disable the warning. 2022-09-22 16:32:14 +02:00
dependabot[bot]
2aa9382fba Bump android-connector from 2.0.1 to 2.1.0
Bumps [android-connector](https://github.com/UnifiedPush/android-connector) from 2.0.1 to 2.1.0.
- [Release notes](https://github.com/UnifiedPush/android-connector/releases)
- [Commits](https://github.com/UnifiedPush/android-connector/compare/2.0.1...2.1.0)

---
updated-dependencies:
- dependency-name: com.github.UnifiedPush:android-connector
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-22 14:31:16 +00:00
Benoit Marty
151f6245db Merge pull request #6929 from vector-im/feature/bma/android12
Target API 32 (Android 12)
2022-09-22 16:30:04 +02:00
Benoit Marty
e98bfe5c9b Merge pull request #7156 from vector-im/feature/mna/device-manager-verify-other-session
[Device management] Verify another session (PSG-722)
2022-09-22 11:46:28 +02:00
Benoit Marty
4e30bc86b8 Merge pull request #7139 from vector-im/feature/mna/device-manager-verify-current-session
[Device management] Verify current session (PSG-722)
2022-09-22 11:46:07 +02:00
ganfra
fabfe36ede Update versions to 1.5.2 2022-09-22 10:31:31 +02:00
ganfra
21806efaa5 Merge branch 'release/1.5.0' into main 2022-09-22 10:28:04 +02:00
ganfra
2a9cf32829 Merge branch 'main' into develop 2022-09-22 10:28:04 +02:00
ganfra
14e7c913df Release 1.5.0: update CHANGES 2022-09-22 09:50:50 +02:00
ganfra
d08b33ec07 Translations: fix some mispells 2022-09-22 09:45:06 +02:00
dependabot[bot]
44f6e66efb Bump fragment from 1.5.2 to 1.5.3
Bumps `fragment` from 1.5.2 to 1.5.3.

Updates `fragment-ktx` from 1.5.2 to 1.5.3

Updates `fragment-testing` from 1.5.2 to 1.5.3

---
updated-dependencies:
- dependency-name: androidx.fragment:fragment-ktx
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: androidx.fragment:fragment-testing
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-21 23:10:46 +00:00
ganfra
619791d24f Merge pull request #7201 from RiotTranslateBot/weblate-element-android-element-app
Translations update from Weblate
2022-09-21 21:40:06 +02:00
Danial Behzadi
1446e8f50b Translated using Weblate (Persian)
Currently translated at 99.8% (2415 of 2419 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/
2022-09-21 19:16:35 +00:00
Auri B. P
401ce61930 Translated using Weblate (Catalan)
Currently translated at 98.7% (2389 of 2419 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/ca/
2022-09-21 19:16:32 +00:00
ganfra
feb33ce32b Translation: cleanup remaining TODOs 2022-09-21 19:43:47 +02:00
ganfra
03d843ac51 Rename device_manager strings 2022-09-21 18:04:32 +02:00
Adam Brown
600588dbbb adding trailing commas 2022-09-21 16:37:31 +01:00
ganfra
658a8dfd04 Merge pull request #7199 from RiotTranslateBot/weblate-element-android-element-app
Translations update from Weblate
2022-09-21 17:09:32 +02:00
Weblate
12e0e263fa Merge branch 'origin/develop' into Weblate. 2022-09-21 14:40:42 +00:00
ganfra
0a8e6c1758 Weblate: fix conflict 2022-09-21 16:39:56 +02:00
Adam Brown
d75e37966c adding changelog entry 2022-09-21 15:39:13 +01:00
Adam Brown
9ab78c93e2 reducing sync timeout for instrumentation tests to speed them up 2022-09-21 15:39:13 +01:00
Adam Brown
7f31098ba1 lifting the sync timeout to the matrix configuration 2022-09-21 15:39:09 +01:00
Benoit Marty
b9c28ba4ce Merge branch 'develop' into feature/bma/android12 2022-09-21 16:24:30 +02:00
ganfra
c05cbb4eed Merge pull request #7196 from vector-im/feature/ons/revert_string_key_changes
Revert changes of string keys
2022-09-21 16:02:18 +02:00
Onuray Sahin
793138bf1b Revert changes of string keys. 2022-09-21 16:44:47 +03:00
Nui Harime
d9faad6364 Translated using Weblate (Russian)
Currently translated at 98.0% (2339 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/
2022-09-21 12:45:19 +00:00
Michael Weimann
b82b5a6979 Translated using Weblate (German)
Currently translated at 98.9% (2362 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/de/
2022-09-21 12:45:18 +00:00
Onuray Sahin
8de9ef8c7d Code review fixes. 2022-09-21 14:30:24 +03:00
Onuray Sahin
4ab798f88d Code review fixes. 2022-09-21 14:16:51 +03:00
Benoit Marty
d31d833959 Merge pull request #7180 from vector-im/feature/fre/deferred_dm_labs_flag
Deferred DMs - Add and enable the feature by default in the labs settings
2022-09-21 12:17:19 +02:00
Benoit Marty
52d7369ac3 Merge pull request #7186 from vector-im/bugfix/eric/fixes-room-list-updates
Fixes Room List not getting updated when fragment is not in focus
2022-09-21 12:14:20 +02:00
NIkita Fedrunov
d8060a7922 review fixes 2022-09-21 11:28:21 +02:00
NIkita Fedrunov
602b378b65 cancel flow when order is changed 2022-09-21 10:43:08 +02:00
ganfra
bf19ef81d0 Merge pull request #7185 from vector-im/bugfix/nfe/app_layout_all_screens_test_fix
fixed all screens test to follow latest changes
2022-09-21 10:28:22 +02:00
Florian Renaud
c252f6eb70 Update lab setting wording following design review 2022-09-21 09:50:05 +02:00
Florian Renaud
fa8b56b1ad Restore tracking for deferred DMs 2022-09-21 09:36:07 +02:00
Florian Renaud
dd92bb756a Add visibility setting field for lab setting 2022-09-21 09:36:07 +02:00
Florian Renaud
3786bd9c65 changelog 2022-09-21 09:36:07 +02:00
Florian Renaud
e9d809d9c3 Move and enable deferred DMs into labs settings 2022-09-21 09:36:07 +02:00
ericdecanini
821636bcb2 Adds changelog file 2022-09-20 18:36:25 -04:00
ericdecanini
1a93bbf92f Renames roomsPagedList 2022-09-20 18:32:59 -04:00
ericdecanini
fe1e74fa06 Fixes room list not getting updated when not in focus 2022-09-20 18:22:39 -04:00
NIkita Fedrunov
f6dfd64326 fixed all screens test to follow latest changes 2022-09-20 23:27:00 +02:00
Nui Harime
32536a4009 Translated using Weblate (Russian)
Currently translated at 97.9% (2338 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/ru/
2022-09-20 14:32:47 +00:00
Onuray Sahin
45cf7dcd63 Merge branch 'develop' into feature/ons/device_manager_security_sessions 2022-09-20 17:11:51 +03:00
Onuray Sahin
3ea054f8e1 Fix unit test. 2022-09-20 15:06:52 +03:00
Adam Brown
2168362a8b including appcompat (instead of the support library) to fix colorPrimary attribute compiliation issues 2022-09-20 10:06:21 +01:00
Maxime NATUREL
943ec7ee75 Reducing argument number in session info view update method 2022-09-20 10:46:10 +02:00
Maxime NATUREL
72637b465f Using viewState value to check if it is current session 2022-09-20 10:46:10 +02:00
Maxime NATUREL
aa7f7d7111 Fix after rebase 2022-09-20 10:46:10 +02:00
Maxime NATUREL
17bb14c1dc Fixing coding style issues 2022-09-20 10:46:10 +02:00
Maxime NATUREL
921533e4b2 Getting the current session verification status to change verify button visibility 2022-09-20 10:46:10 +02:00
Maxime NATUREL
95d133e0e2 Moving some components inside the verification package 2022-09-20 10:46:10 +02:00
Maxime NATUREL
a6cb25d0c3 Verification of another session 2022-09-20 10:46:10 +02:00
Maxime NATUREL
c16e1ca291 Adding changelog entry 2022-09-20 10:46:10 +02:00
Maxime NATUREL
54a4dc7e9a Inverting some arguments to ease readability 2022-09-20 10:45:47 +02:00
Maxime NATUREL
cf6b8d76a8 Removing non necessary session id arg from ViewAction 2022-09-20 10:45:46 +02:00
Maxime NATUREL
e0c4706cf9 Removing non necessary session arg from ViewEvent 2022-09-20 10:45:46 +02:00
Maxime NATUREL
584c699409 Verify current session in Session overview screen 2022-09-20 10:45:46 +02:00
Maxime NATUREL
fa990351af Editing changelog entry 2022-09-20 10:45:46 +02:00
Maxime NATUREL
32b5606498 Fixing missing event to start verification process 2022-09-20 10:45:46 +02:00
Maxime NATUREL
35db958279 Adding unit tests for new action in DevicesViewModel 2022-09-20 10:45:46 +02:00
Maxime NATUREL
d826327773 Adding unit tests for CheckIfCurrentSessionCanBeVerifiedUseCase 2022-09-20 10:45:46 +02:00
Maxime NATUREL
8cd7b0744a Verification process for the current Session 2022-09-20 10:45:46 +02:00
Maxime NATUREL
5759a0f7da Adding click listeners on verify button 2022-09-20 10:45:46 +02:00
Maxime NATUREL
81beccdd8e Adding changelog entry 2022-09-20 10:45:46 +02:00
Onuray Sahin
72cc0deda2 Add changelog. 2022-09-19 16:45:52 +03:00
Onuray Sahin
2ad0cd46bb Fix unit tests. 2022-09-19 16:18:30 +03:00
Onuray Sahin
ec9843fb53 Fix unverified session detection logic. 2022-09-19 15:38:02 +03:00
Onuray Sahin
7db222af0c Render security recommendation sessions. 2022-09-19 15:37:13 +03:00
Onuray Sahin
740b69d48c Make other sessions view dynamic. 2022-09-19 13:42:30 +03:00
Benoit Marty
e2d131fc4f Move xml resource in the module where they are used to avoid lint false positive UnusedResources issues. 2022-09-19 11:56:40 +02:00
Benoit Marty
c91ba06285 Fix lint warnings, some code has vanished dur to the rebasing of the branch... 2022-09-19 10:50:15 +02:00
Szimszon
af7938432b Translated using Weblate (Hungarian)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/hu/
2022-09-19 07:32:46 +00:00
Anonimas
733add8d61 Translated using Weblate (Lithuanian)
Currently translated at 4.0% (3 of 75 strings)

Translation: Element Android/Element Android Store
Translate-URL: https://translate.element.io/projects/element-android/element-store/lt/
2022-09-17 19:33:29 +00:00
phardyle
a6dc219e28 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.5% (2375 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hans/
2022-09-17 19:33:28 +00:00
Gérson
a783bef1e1 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/
2022-09-17 19:33:27 +00:00
lvre
16443f957b Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/
2022-09-17 19:33:27 +00:00
Przemysław Romanik
77fa7aea56 Translated using Weblate (Polish)
Currently translated at 98.8% (2358 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/pl/
2022-09-17 19:33:27 +00:00
Anonimas
b82b47b50b Translated using Weblate (Lithuanian)
Currently translated at 51.5% (1229 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/lt/
2022-09-17 19:33:26 +00:00
Linerly
934a6026b2 Translated using Weblate (Indonesian)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/id/
2022-09-17 19:32:48 +00:00
Glandos
61289666bd Translated using Weblate (French)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/fr/
2022-09-17 19:32:48 +00:00
Priit Jõerüüt
6bb0e68e78 Translated using Weblate (Estonian)
Currently translated at 99.6% (2378 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/et/
2022-09-17 19:32:46 +00:00
Benoit Marty
d4eb619d40 Changelog 2022-09-16 23:30:20 +02:00
Benoit Marty
a1f4ffbf17 Use vanniktechEmoji "0.16.0-SNAPSHOT" 2022-09-16 23:12:48 +02:00
Benoit Marty
84afa4714a App compat 1.5.1 2022-09-16 23:01:56 +02:00
Benoit Marty
892484a1b3 Upgrade kotlin from 1.6.21 to 1.7.10 and dagger (+hilt) from 2.42 to 2.43.2 2022-09-16 23:01:56 +02:00
Benoit Marty
57db43c80a Fix gradle warning:
WARNING:API 'ApkVariantOutput.getVersionCodeOverride()' is obsolete and has been replaced with 'VariantOutput.versionCode()'.
2022-09-16 23:01:29 +02:00
Benoit Marty
c5571c06ed Upgrade gradle plugin from 7.1.3 to 7.2.2 2022-09-16 23:01:29 +02:00
Benoit Marty
842a9bbd55 Add dataExtractionRules, applicable to Android 12. Exclude everything from being backed up. Also properly support Android 11. 2022-09-16 23:01:29 +02:00
Benoit Marty
88482c9b2e Reduce level API check, this seems not necessary. 2022-09-16 23:00:39 +02:00
Benoit Marty
cde7096928 Restore this annotation 2022-09-16 23:00:39 +02:00
Benoit Marty
518ec738f3 Reduce level API check, this seems not necessary. 2022-09-16 23:00:39 +02:00
Benoit Marty
e17f009566 Reduce level API check, this seems not necessary. 2022-09-16 23:00:39 +02:00
Benoit Marty
536b9cf926 Move @Suppress("DEPRECATION") closer to the deprecated usage. Will help to detect other deprecated API usage. 2022-09-16 23:00:39 +02:00
Benoit Marty
24e4f94e61 Stop using deprecated method. 2022-09-16 23:00:39 +02:00
Benoit Marty
3f3c83a43d Remove deprecated internal class. 2022-09-16 23:00:39 +02:00
Benoit Marty
8b64bd38b7 'compileSdk': 32, 'targetSdk': 32 2022-09-16 23:00:39 +02:00
dependabot[bot]
d9ee51a212 Bump emoji2 from 1.1.0 to 1.2.0
Bumps emoji2 from 1.1.0 to 1.2.0.

---
updated-dependencies:
- dependency-name: androidx.emoji2:emoji2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-16 23:00:39 +02:00
dependabot[bot]
ea274c4df6 Bump appcompat from 1.4.2 to 1.5.0
Bumps appcompat from 1.4.2 to 1.5.0.

---
updated-dependencies:
- dependency-name: androidx.appcompat:appcompat
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-16 23:00:39 +02:00
Adam Brown
739a513f89 moving external library modules to an external directory 2022-09-16 15:15:32 +01:00
Adam Brown
e83fa9c81f removing dialpad reliance on the legacy support library 2022-09-16 15:15:32 +01:00
Adam Brown
abd70d953b disabling lint for the pulled in module 2022-09-16 15:15:32 +01:00
Adam Brown
5058f942af manually including the im.dlg:android-dialer:1.2.5
- avoids using appcompat
- avoids using an artifact without a source repository
2022-09-16 15:15:32 +01:00
Benoit Marty
bdda8dbc48 Changelogs 2022-09-14 18:19:57 +02:00
Benoit Marty
7341a65410 Run knit. 2022-09-14 18:17:15 +02:00
Benoit Marty
b9294381b8 Add a paragraph about test. 2022-09-14 17:52:11 +02:00
Benoit Marty
8623b85ac8 Add support to /devtools command 2022-09-14 17:49:55 +02:00
Benoit Marty
f67cf0d591 Reduce link size. 2022-09-14 17:38:50 +02:00
Benoit Marty
c72ab3d187 Add link to the new doc to the README file. 2022-09-14 17:38:28 +02:00
Benoit Marty
64fb985d3b First draft of documentation to onboard new developers. 2022-09-14 17:36:59 +02:00
Benoit Marty
970abb4dde Rename file. 2022-09-14 16:53:38 +02:00
Philip Goto
7afd49b7d8 Translated using Weblate (Dutch)
Currently translated at 25.3% (19 of 75 strings)

Translation: Element Android/Element Android Store
Translate-URL: https://translate.element.io/projects/element-android/element-store/nl/
2022-09-11 09:33:12 +00:00
Jeff Huang
44b6563376 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/zh_Hant/
2022-09-11 09:33:11 +00:00
Ihor Hordiichuk
aa4e830cb5 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/uk/
2022-09-11 09:33:10 +00:00
Jozef Gaal
84eb71d63f Translated using Weblate (Slovak)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/sk/
2022-09-11 09:33:08 +00:00
lvre
05483d9ca0 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/pt_BR/
2022-09-11 09:33:06 +00:00
Philip Goto
4b980e85f4 Translated using Weblate (Dutch)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/nl/
2022-09-11 09:33:05 +00:00
random
2f94162236 Translated using Weblate (Italian)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/it/
2022-09-11 09:33:02 +00:00
Linerly
596f2d993d Translated using Weblate (Indonesian)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/id/
2022-09-11 09:33:00 +00:00
Szimszon
7645992cf1 Translated using Weblate (Hungarian)
Currently translated at 99.8% (2382 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/hu/
2022-09-11 09:32:58 +00:00
Danial Behzadi
c858d31761 Translated using Weblate (Persian)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/fa/
2022-09-11 09:32:57 +00:00
Priit Jõerüüt
fd76bdfa4d Translated using Weblate (Estonian)
Currently translated at 98.7% (2355 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/et/
2022-09-11 09:32:55 +00:00
Deleted User
118fc2ffc1 Translated using Weblate (Spanish)
Currently translated at 97.3% (2322 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/es/
2022-09-11 09:32:54 +00:00
Vri
904c4e44b2 Translated using Weblate (German)
Currently translated at 98.9% (2362 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/de/
2022-09-11 09:32:47 +00:00
waclaw66
f53cdbb167 Translated using Weblate (Czech)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/cs/
2022-09-11 09:32:46 +00:00
Auri B. P
2f6f52c25a Translated using Weblate (Catalan)
Currently translated at 100.0% (2386 of 2386 strings)

Translation: Element Android/Element Android App
Translate-URL: https://translate.element.io/projects/element-android/element-app/ca/
2022-09-11 09:32:45 +00:00
Benoit Marty
6cada8f6a3 Merge branch 'release/1.4.36' into main 2022-09-10 08:13:58 +02:00
Benoit Marty
ba6f7c4288 Merge branch 'release/v1.4.34' into main 2022-08-23 17:00:11 +02:00
Adam Brown
ce28d7f8a5 Merge branch 'release/v1.4.32' 2022-08-10 09:47:50 +01:00
Adam Brown
dbb999d4b9 Merge branch 'hotfix/v1.4.31' 2022-08-01 17:52:34 +01:00
753 changed files with 7643 additions and 1401 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
**/snapshots/**/*.png filter=lfs diff=lfs merge=lfs -text

View File

@@ -8,7 +8,7 @@ on:
# Enrich gradle.properties for CI/CD
env:
GRADLE_OPTS: -Dorg.gradle.jvmargs="-Xmx3072m -Dfile.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError" -Dkotlin.daemon.jvm.options="-Xmx2560m" -Dkotlin.incremental=false
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 2 --no-daemon
CI_GRADLE_ARG_PROPERTIES: --stacktrace -PpreDexEnable=false --max-workers 4 --no-daemon
jobs:
tests:
@@ -24,12 +24,26 @@ jobs:
steps:
- uses: actions/checkout@v3
with:
lfs: true
fetch-depth: 0
- uses: actions/setup-java@v3
with:
distribution: 'adopt'
java-version: '11'
- uses: gradle/gradle-build-action@v2
- name: Run screenshot tests
run: ./gradlew verifyScreenshots $CI_GRADLE_ARG_PROPERTIES
- name: Archive Screenshot Results on Error
if: failure()
uses: actions/upload-artifact@v3
with:
name: screenshot-results
path: |
**/out/failures/
**/build/reports/tests/*UnitTest/
- uses: actions/setup-python@v4
with:
python-version: 3.8
@@ -40,27 +54,6 @@ jobs:
disableRateLimiting: true
public_baseurl: "http://10.0.2.2:8080/"
- name: AVD cache
uses: actions/cache@v3
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-${{ matrix.api-level }}
- name: create AVD and generate snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: ${{ matrix.api-level }}
arch: x86
profile: Nexus 5X
force-avd-creation: true # Is set to false in the doc https://github.com/ReactiveCircus/android-emulator-runner
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: echo "Generated AVD snapshot for caching."
- name: Run all the codecoverage tests at once
uses: reactivecircus/android-emulator-runner@v2
# continue-on-error: true
@@ -68,6 +61,7 @@ jobs:
api-level: ${{ matrix.api-level }}
arch: x86
profile: Nexus 5X
target: playstore
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true

15
.github/workflows/validate-lfs.yml vendored Normal file
View File

@@ -0,0 +1,15 @@
name: Validate Git LFS
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
name: Validate
steps:
- uses: actions/checkout@v3
with:
lfs: 'true'
- run: |
./tools/validate_lfs.sh

1
.gitignore vendored
View File

@@ -22,3 +22,4 @@
/package.json
/yarn.lock
/node_modules
**/out/failures

View File

@@ -1,3 +1,39 @@
Changes in Element v1.5.0 (2022-09-23)
======================================
Features ✨
----------
- Deferred DMs - Enable and move the feature to labs settings ([#7180](https://github.com/vector-im/element-android/issues/7180))
Bugfixes 🐛
----------
- Fix text margin in QR code view when no display name is set ([#5424](https://github.com/vector-im/element-android/issues/5424))
- [App Layout] Recents carousel now scrolled to first position when new item added to or moved to this position ([#6776](https://github.com/vector-im/element-android/issues/6776))
- Fixed problem when room list's scroll did jump after rooms placeholders were replaced with rooms summary items ([#7079](https://github.com/vector-im/element-android/issues/7079))
- Fixes crash when quickly double clicking FABs in the new app layout ([#7102](https://github.com/vector-im/element-android/issues/7102))
- Fixes space list and new chat bottom sheets showing too small in New App Layout (especially evident in landscape) ([#7103](https://github.com/vector-im/element-android/issues/7103))
- [App Layout] Room leaving prompt dialog now waits user to confirm leaving before do so ([#7122](https://github.com/vector-im/element-android/issues/7122))
- Fix empty verification bottom sheet. ([#7130](https://github.com/vector-im/element-android/issues/7130))
- [New Layout] Fixes new chat dialog not getting dismissed after selecting its actions ([#7132](https://github.com/vector-im/element-android/issues/7132))
- Fixes Room List not getting updated when fragment is not in focus ([#7186](https://github.com/vector-im/element-android/issues/7186))
In development 🚧
----------------
- Create DM room only on first message - Add a spinner when sending the first message ([#6970](https://github.com/vector-im/element-android/issues/6970))
- [Device Manager] Filter Other Sessions ([#7045](https://github.com/vector-im/element-android/issues/7045))
- [Device management] Session details screen ([#7077](https://github.com/vector-im/element-android/issues/7077))
- Create DM room only on first message - Fix glitch in the room list ([#7121](https://github.com/vector-im/element-android/issues/7121))
- Create DM room only on first message - Handle the local rooms within the new AppLayout ([#7153](https://github.com/vector-im/element-android/issues/7153))
Other changes
-------------
- [Modules] Lifts the application variants to the app module ([#6779](https://github.com/vector-im/element-android/issues/6779))
- Ensure that we do not expect all the Event fields when requesting `rooms/{roomId}/hierarchy` endpoint. ([#7035](https://github.com/vector-im/element-android/issues/7035))
- Move some GitHub actions to buildjet runners, and remove the second attempt to run integration tests. ([#7108](https://github.com/vector-im/element-android/issues/7108))
- Exclude legacy android support annotation library ([#7140](https://github.com/vector-im/element-android/issues/7140))
- Pulling no longer hosted im.dlg:android-dialer directly into the repository and removing legacy support library usages ([#7142](https://github.com/vector-im/element-android/issues/7142))
- Fixing build cache misses when compiling the vector module ([#7157](https://github.com/vector-im/element-android/issues/7157))
Changes in Element v1.4.36 (2022-09-10)
=======================================

View File

@@ -1,10 +1,42 @@
# Contributing code to Matrix
# Contributing to Element Android
<!--- TOC -->
* [Contributing code to Matrix](#contributing-code-to-matrix)
* [Android Studio settings](#android-studio-settings)
* [Template](#template)
* [Compilation](#compilation)
* [I want to help translating Element](#i-want-to-help-translating-element)
* [I want to submit a PR to fix an issue](#i-want-to-submit-a-pr-to-fix-an-issue)
* [Kotlin](#kotlin)
* [Changelog](#changelog)
* [Code quality](#code-quality)
* [Internal tool](#internal-tool)
* [ktlint](#ktlint)
* [lint](#lint)
* [Unit tests](#unit-tests)
* [Tests](#tests)
* [Internationalisation](#internationalisation)
* [Adding new string](#adding-new-string)
* [Plurals](#plurals)
* [Editing existing strings](#editing-existing-strings)
* [Removing existing strings](#removing-existing-strings)
* [Renaming string ids](#renaming-string-ids)
* [Reordering strings](#reordering-strings)
* [Accessibility](#accessibility)
* [Layout](#layout)
* [Authors](#authors)
* [Thanks](#thanks)
<!--- END -->
## Contributing code to Matrix
Please read https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.md
Element Android support can be found in this room: [![Element Android Matrix room #element-android:matrix.org](https://img.shields.io/matrix/element-android:matrix.org.svg?label=%23element-android:matrix.org&logo=matrix&server_fqdn=matrix.org)](https://matrix.to/#/#element-android:matrix.org).
# Specific rules for Matrix Android projects
The rest of the document contains specific rules for Matrix Android projects
## Android Studio settings
@@ -120,17 +152,21 @@ You should consider adding Unit tests with your PR, and also integration tests (
Translations are handled using an external tool: [Weblate](https://translate.element.io/projects/element-android/)
As a general rule, please never edit or add or remove translations to the project in a Pull Request. It can lead to merge conflict if the translations are also modified in Weblate side.
**As a general rule, please never edit or add or remove translations to the project in a Pull Request**. It can lead to merge conflict if the translations are also modified in Weblate side. Pull Request containing change(s) on the translation files cannot be merged.
#### Adding new string
When adding new string resources, please only add new entries in the file `value/strings.xml`. Translations will be added later by the community of translators using Weblate.
When adding new string resources, please only add new entries in the file `values/strings.xml` ([this file](./library/ui-strings/src/main/res/values/strings.xml)). Translations will be added later by the community of translators using Weblate.
The file `value/strings.xml` must only contain American English (U. S. English) values, as this is the default language of the Android operating system. So for instance, please use "color" instead of "colour". Element Android will still use the language set on the system by the user, like any other Android applications which provide translations. The system language can be any other English language variants, or any other languages. Note that this is also possible to override the system language using the Element Android in-app language settings.
The file `values/strings.xml` must only contain American English (U. S. English) values, as this is the default language of the Android operating system. So for instance, please use "color" instead of "colour". Element Android will still use the language set on the system by the user, like any other Android applications which provide translations. The system language can be any other English language variants, or any other languages. Note that this is also possible to override the system language using the Element Android in-app language settings.
New strings can be added anywhere in the file `value/strings.xml`, not necessarily at the end of the file. Generally, it's even better to add the new strings in some dedicated section per feature, and not at the end of the file, to avoid merge conflict between 2 PR adding strings at the end of the same file.
New strings can be added anywhere in the file `values/strings.xml`, not necessarily at the end of the file. Generally, it's even better to add the new strings in some dedicated section per feature, and not at the end of the file, to avoid merge conflict between 2 PR adding strings at the end of the same file.
Do not hesitate to use plurals when appropriate.
##### Plurals
Please use `plurals` resources when appropriate, and note that some languages have specific rules for `plurals`, so even if the string will always be at the plural form for English, please always create a `plurals` resource.
Specific plural forms can be found [here](https://unicode-org.github.io/cldr-staging/charts/37/supplemental/language_plural_rules.html).
#### Editing existing strings
@@ -150,6 +186,23 @@ And add `tools:ignore="UnusedResources"` to the string, to let lint ignore that
The string will be removed during the next sync with Weblate.
#### Renaming string ids
This is possible to rename ids of the String resources, but since translation files cannot be edited, add TODO in the main strings.xml file above the strings you want to rename.
```xml
<!-- TODO Rename id to put_new_id_here -->
<string name="current_id">Hello Matrix world!</string>
```
The string id(s) will be renamed during the next Weblate sync.
#### Reordering strings
To group strings per feature, or for any other reasons, it is possible to reorder string resources, but only in the [main strings.xml file](./library/ui-strings/src/main/res/values/strings.xml). ). We do not mind about ordering in the translation files, and anyway this is forbidden to edit manually the translation files.
It is also possible to add empty lines between string resources, and to add XML comments. Please note that the XML comment just above a String resource will also appear on Weblate and be visible to the translators.
### 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_`.

View File

@@ -44,10 +44,12 @@ If you would like to receive releases more quickly (bearing in mind that they ma
## Contributing
Please refer to [CONTRIBUTING.md](https://github.com/vector-im/element-android/blob/develop/CONTRIBUTING.md) if you want to contribute on Matrix Android projects!
Please refer to [CONTRIBUTING.md](./CONTRIBUTING.md) if you want to contribute on Matrix Android projects!
Come chat with the community in the dedicated Matrix [room](https://matrix.to/#/#element-android:matrix.org).
Also [this documentation](./docs/_developer_onboarding.md) can hopefully help developers to start working on the project.
## Triaging issues
Issues are triaged by community members and the Android App Team, following the [triage process](https://github.com/vector-im/element-meta/wiki/Triage-process).

View File

@@ -33,6 +33,7 @@ buildscript {
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10"
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
classpath 'app.cash.paparazzi:paparazzi-gradle-plugin:1.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@@ -71,6 +72,14 @@ allprojects {
groups.mavenCentral.group.each { includeGroup it }
}
}
// snapshots repository
maven {
url "https://oss.sonatype.org/content/repositories/snapshots"
content {
groups.snapshot.regex.each { includeGroupByRegex it }
groups.snapshot.group.each { includeGroup it }
}
}
maven {
url 'https://jitpack.io'
content {
@@ -216,7 +225,7 @@ project(":vector") {
}
}
project(":library:diff-match-patch") {
project(":library:external:diff-match-patch") {
sonarqube {
skipProject = true
}
@@ -287,3 +296,29 @@ dependencyAnalysis {
}
}
}
tasks.register("recordScreenshots", GradleBuild) {
startParameter.projectProperties.screenshot = ""
tasks = [':vector:recordPaparazziDebug']
}
tasks.register("verifyScreenshots", GradleBuild) {
startParameter.projectProperties.screenshot = ""
tasks = [':vector:verifyPaparazziDebug']
}
ext.initScreenshotTests = { project ->
def hasScreenshots = project.hasProperty("screenshot")
if (hasScreenshots) {
project.apply plugin: 'app.cash.paparazzi'
}
project.dependencies { testCompileOnly "app.cash.paparazzi:paparazzi:1.0.0" }
project.android.testOptions.unitTests.all {
def screenshotTestCapture = "**/*ScreenshotTest*"
if (hasScreenshots) {
include screenshotTestCapture
} else {
exclude screenshotTestCapture
}
}
}

View File

@@ -1 +0,0 @@
Fix text margin in QR code view when no display name is set

1
changelog.d/5798.misc Normal file
View File

@@ -0,0 +1 @@
Adds screenshot testing tooling

View File

@@ -1 +0,0 @@
[App Layout] Recents carousel now scrolled to first position when new item added to or moved to this position

View File

@@ -1 +0,0 @@
[Modules] Lifts the application variants to the app module

1
changelog.d/6929.misc Normal file
View File

@@ -0,0 +1 @@
Target API 12 and compile with Android SDK 32.

View File

@@ -1 +0,0 @@
Create DM room only on first message - Add a spinner when sending the first message

View File

@@ -1 +0,0 @@
Ensure that we do not expect all the Event fields when requesting `rooms/{roomId}/hierarchy` endpoint.

View File

@@ -1 +0,0 @@
[Device Manager] Filter Other Sessions

View File

@@ -1 +0,0 @@
[Device management] Session details screen

View File

@@ -1 +0,0 @@
Fixed problem when room list's scroll did jump after rooms placeholders were replaced with rooms summary items

View File

@@ -1 +0,0 @@
Fixes crash when quickly double clicking FABs in the new app layout

View File

@@ -1 +0,0 @@
Fixes space list and new chat bottom sheets showing too small in New App Layout (especially evident in landscape)

View File

@@ -1 +0,0 @@
Move some GitHub actions to buildjet runners, and remove the second attempt to run integration tests.

1
changelog.d/7114.wip Normal file
View File

@@ -0,0 +1 @@
[Device management] Verify current session

View File

@@ -1 +0,0 @@
Create DM room only on first message - Fix glitch in the room list

View File

@@ -1 +0,0 @@
[App Layout] Room leaving prompt dialog now waits user to confirm leaving before do so

1
changelog.d/7126.doc Normal file
View File

@@ -0,0 +1 @@
Draft onboarding documentation of the project at `./docs/_developer_onboarding.md`

1
changelog.d/7126.misc Normal file
View File

@@ -0,0 +1 @@
Add support to `/devtools` command.

View File

@@ -1 +0,0 @@
Fix empty verification bottom sheet.

View File

@@ -1 +0,0 @@
[New Layout] Fixes new chat dialog not getting dismissed after selecting its actions

View File

@@ -1 +0,0 @@
Exclude legacy android support annotation library

View File

@@ -1 +0,0 @@
Pulling no longer hosted im.dlg:android-dialer directly into the repository and removing legacy support library usages

1
changelog.d/7143.wip Normal file
View File

@@ -0,0 +1 @@
[Device management] Verify another session

View File

@@ -1 +0,0 @@
Create DM room only on first message - Handle the local rooms within the new AppLayout

View File

@@ -1 +0,0 @@
Fixing build cache misses when compiling the vector module

1
changelog.d/7158.wip Normal file
View File

@@ -0,0 +1 @@
[Device management] Rename a session

1
changelog.d/7159.misc Normal file
View File

@@ -0,0 +1 @@
Fix lint warning, and cleanup the code

View File

@@ -1 +0,0 @@
New App Layout is now enabled by default! Go to the Settings > Labs to toggle this

1
changelog.d/7170.wip Normal file
View File

@@ -0,0 +1 @@
[Device Manager] Unverified and inactive sessions list

1
changelog.d/7193.misc Normal file
View File

@@ -0,0 +1 @@
Mutualize the pending auth handling

1
changelog.d/7198.sdk Normal file
View File

@@ -0,0 +1 @@
Allow the sync timeout to be configured (mainly useful for testing)

1
changelog.d/7211.misc Normal file
View File

@@ -0,0 +1 @@
CI: Prevent modification of translations by developer.

View File

@@ -1,20 +1,17 @@
ext.versions = [
'minSdk' : 21,
'compileSdk' : 31,
'targetSdk' : 31,
'compileSdk' : 32,
'targetSdk' : 32,
'sourceCompat' : JavaVersion.VERSION_11,
'targetCompat' : JavaVersion.VERSION_11,
]
// Pinned to 7.1.3 because of https://github.com/vector-im/element-android/issues/6142
// Please test carefully before upgrading again.
def gradle = "7.1.3"
def gradle = "7.2.2"
// Ref: https://kotlinlang.org/releases.html
def kotlin = "1.6.21"
def kotlin = "1.7.10"
def kotlinCoroutines = "1.6.4"
def dagger = "2.42"
def dagger = "2.43.2"
def appDistribution = "16.0.0-beta04"
def retrofit = "2.9.0"
def arrow = "0.8.2"
@@ -28,9 +25,11 @@ def mavericks = "2.7.0"
def glide = "4.13.2"
def bigImageViewer = "1.8.1"
def jjwt = "0.11.5"
def vanniktechEmoji = "0.15.0"
// Temporary version to unblock #6929. Once 0.16.0 is released we should use it, and revert
// the whole commit which set version 0.16.0-SNAPSHOT
def vanniktechEmoji = "0.16.0-SNAPSHOT"
def fragment = "1.5.2"
def fragment = "1.5.3"
// Testing
def mockk = "1.12.3" // We need to use 1.12.3 to have mocking in androidTest until a new version is released: https://github.com/mockk/mockk/issues/819
@@ -51,7 +50,7 @@ ext.libs = [
],
androidx : [
'activity' : "androidx.activity:activity:1.5.1",
'appCompat' : "androidx.appcompat:appcompat:1.4.2",
'appCompat' : "androidx.appcompat:appcompat:1.5.1",
'biometric' : "androidx.biometric:biometric:1.1.0",
'core' : "androidx.core:core-ktx:1.8.0",
'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1",
@@ -100,7 +99,7 @@ ext.libs = [
'flipperNetworkPlugin' : "com.facebook.flipper:flipper-network-plugin:$flipper",
],
element : [
'opusencoder' : "io.element.android:opusencoder:1.0.4",
'opusencoder' : "io.element.android:opusencoder:1.1.0",
],
squareup : [
'moshi' : "com.squareup.moshi:moshi:$moshi",

View File

@@ -38,10 +38,18 @@ ext.groups = [
'com.google.testing.platform',
]
],
snapshot: [
regex: [
],
group: [
'com.vanniktech',
]
],
mavenCentral: [
regex: [
],
group: [
'app.cash.paparazzi',
'ch.qos.logback',
'com.adevinta.android',
'com.airbnb.android',
@@ -118,7 +126,7 @@ ext.groups = [
'com.sun.xml.bind.mvn',
'com.sun.xml.fastinfoset',
'com.thoughtworks.qdox',
'com.vanniktech',
// 'com.vanniktech',
'commons-cli',
'commons-codec',
'commons-io',
@@ -143,11 +151,14 @@ ext.groups = [
'it.unimi.dsi',
'jakarta.activation',
'jakarta.xml.bind',
'javax.activation',
'javax.annotation',
'javax.inject',
'javax.xml.bind',
'jline',
'jp.wasabeef',
'junit',
'kxml2',
'me.saket',
'net.bytebuddy',
'net.java',
@@ -176,11 +187,13 @@ ext.groups = [
'org.hamcrest',
'org.jacoco',
'org.java-websocket',
'org.jcodec',
'org.jetbrains',
'org.jetbrains.dokka',
'org.jetbrains.intellij.deps',
'org.jetbrains.kotlin',
'org.jetbrains.kotlinx',
'org.jetbrains.trove4j',
'org.json',
'org.jsoup',
'org.junit',

View File

@@ -0,0 +1,259 @@
# Developer on boarding
<!--- TOC -->
* [Introduction](#introduction)
* [Quick introduction to Matrix](#quick-introduction-to-matrix)
* [Matrix data](#matrix-data)
* [Room](#room)
* [Event](#event)
* [Sync](#sync)
* [Glossary about syncs](#glossary-about-syncs)
* [The Android project](#the-android-project)
* [Matrix SDK](#matrix-sdk)
* [Application](#application)
* [MvRx](#mvrx)
* [Behavior](#behavior)
* [Epoxy](#epoxy)
* [Other frameworks](#other-frameworks)
* [Push](#push)
* [Dependencies management](#dependencies-management)
* [Test](#test)
* [Other points](#other-points)
* [Logging](#logging)
* [Rageshake](#rageshake)
* [Tips](#tips)
* [Happy coding!](#happy-coding)
<!--- END -->
## Introduction
This doc is a quick introduction about the project and its architecture.
It's aim is to help new developers to understand the overall project and where to start developing.
Other useful documentation:
- all the docs in this folder!
- the [contributing doc](../CONTRIBUTING.md), that you should also read carefully.
### Quick introduction to Matrix
Matrix website: [matrix.org](https://matrix.org), [discover page](https://matrix.org/discover).
*Note*: Matrix.org is also hosting a homeserver ([.well-known file](https://matrix.org/.well-known/matrix/client)).
The reference homeserver (this is how Matrix servers are called) implementation is [Synapse](https://github.com/matrix-org/synapse/). But other implementations exist. The Matrix specification is here to ensure that any Matrix client, such as Element Android and its SDK can talk to any Matrix server.
Have a quick look to the client-server API documentation: [Client-server documentation](https://spec.matrix.org/v1.3/client-server-api/). Other network API exist, the list is here: (https://spec.matrix.org/latest/)
Matrix is an open source protocol. Change are possible and are tracked using [this GitHub repository](https://github.com/matrix-org/matrix-doc/). Changes to the protocol are called MSC: Matrix Spec Change. These are PullRequest to this project.
Matrix object are Json data. Unstable prefixes must be used for Json keys when the MSC is not merged (i.e. accepted).
#### Matrix data
There are many object and data in the Matrix worlds. Let's focus on the most important and used, `Room` and `Event`
##### Room
`Room` is a place which contains ordered `Event`s. They are identified with their `room_id`. Nearly all the data are stored in rooms, and shared using homeserver to all the Room Member.
*Note*: Spaces are also Rooms with a different `type`.
##### Event
`Events` are items of a Room, where data is embedded.
There are 2 types of Room Event:
- Regular Events: contain useful content for the user (message, image, etc.), but are not necessarily displayed as this in the timeline (reaction, message edition, call signaling).
- State Events: contain the state of the Room (name, topic, etc.). They have a non null value for the key `state_key`.
Also all the Room Member details are in State Events: one State Event per member. In this case, the `state_key` is the matrixId (= userId).
Important Fields of an Event:
- `event_id`: unique across the Matrix universe;
- `room_id`: the room the Event belongs to;
- `type`: describe what the Event contain, especially in the `content` section, and how the SDK should handle this Event;
- `content`: dynamic Event data; depends on the `type`.
So we have a triple `event_id`, `type`, `state_key` which uniquely defines an Event.
#### Sync
The `Sync` is a way for the Matrix client to be up to date regarding the user data hosted by the server. All the Events are coming through the sync response. More details can be found here: [spec.matrix.org/v1.3/client-server-api/#syncing](https://spec.matrix.org/v1.3/client-server-api/#syncing)
When the application is in foreground, this is a looping request. We are using Https requests, which offer the advantage to be compatible with any homeserver. A sync token is used as request parameter, to let the server know what the client knows.
The `SyncThread` is responsible to manage the sync request loop.
When the application is in background, a Push will trigger a sync request.
##### Glossary about syncs
- **initial sync**: a sync request without a token. This is the first request a client perform after login or after a clear cache. The server will include in the response all your rooms with the full state (all the room membership Event will not be present), with the latest messages for each room. We are in the process to replace this by version 3: sliding sync. All data are inserted to the Database (currently [Realm](https://www.mongodb.com/docs/realm/sdk/java/)).
- **incremental sync**: sync request with a token.
- **gappy sync**: sync request where all the new Events are not returned for one or several Rooms. Also called `limited sync`. It can be limited per Room. To get all the missing Events, a Room pagination API has to be called.
- **sync token**: `next_batch` value in the previous sync response. Will be provided as the `since` parameter for the next sync request.
### The Android project
The project should compile out of the box.
The project is split into several modules. The main ones are:
For the app
- `vector-app`: application entry point;
- `vector`: legacy application, but now a library. In the process of being split into several modules;
- `vector-config`: this is where all the configuration of the application should occurs. Should because we are in the process of migrating all the configuration here;
- `library/ui-strings`: this is where all the string resources are stored. Please refer to [contributing doc](../CONTRIBUTING.md) to know how to make change on this module;
- `library/ui-styles`: this is where the Android styles are defined.
For the SDK
- `matrix-sdk-android`: the main SDK module. The sources are in this project, but are also exported to [its own project](https://github.com/matrix-org/matrix-android-sdk2). All the PRs and issues related to the SDK take place in the Element Android project;
- `matrix-sdk-android-flow`: contains some wrapper to expose `Flow` to the application.
### Matrix SDK
SDK exposes `Services` to the client application. `Services` are public interface, and are defined in this parent package: `org.matrix.android.sdk.api`. Default implementation are internal to the SDK, in this parent package: `org.matrix.android.sdk.internal`. Note that you also have to declare the classes as `internal` when adding classes to the `org.matrix.android.sdk.internal` package.
Interface allows us to replace the implementation for testing purpose.
A generated documentation of the SDK is available [here](https://matrix-org.github.io/matrix-android-sdk2/). Updated after each release. Please ensure that the documentation (KDoc) of all the SDK Services is up to date, and is clear for a SDK user.
The SDK generated documentation also contains information about the entry points of the SDK.
[Dagger](https://dagger.dev/) is used to inject all the dependencies to the SDK classes.
SDK is exposing data as `LiveData`, but we are progressively migrating to `Flow`. Database is the source of truth.
Example:
- Client send an Event using the `SendService`;
- At the end a `SendEvent` task is used;
- Retrofit API is used to send data to the server;
- Goes to the server, which returns only the `event_id`;
- The `Event` is coming back from the `sync` response with eventually extra added data.
### Application
This is the UI part of the project.
There are two variants of the application: `Gplay` and `Fdroid`.
The main difference is about using Firebase on `Gplay` variant, to have Push from Google Services. `FDroid` variant cannot contain closed source dependency.
`Fdroid` is using background polling to lack the missing of Pushed. Now a solution using UnifiedPush has ben added to the project. See refer to [the dedicated documentation](./unifiedpush.md) for more details.
#### MvRx
[Maverick](https://airbnb.io/mavericks/#/README) (or MvRx) is an Android MVI framework that helps to develop Reactive application on Android.
- Activity: holder for Fragment. See the parent [VectorBaseActivity](../vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt);
- Fragment: manage screen of the application. See the parent [VectorBaseFragment](../vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt);
- BottomSheet: see the parent [VectorBaseBottomSheetDialogFragment](../vector/src/main/java/im/vector/app/core/platform/VectorBaseBottomSheetDialogFragment.kt);
- ViewModel: this is where the logic is placed. All our ViewModel has a `handle()` which takes action as parameter. See the parent [VectorViewModel](../vector/src/main/java/im/vector/app/core/platform/VectorViewModel.kt);
- VectorSharedActionViewModel: Specific ViewModel that can be used to communicate between Fragment(s) and the host Activity. See the parent [VectorSharedActionViewModel](../vector/src/main/java/im/vector/app/core/platform/VectorSharedActionViewModel.kt);
- ViewState: this are `data class`, and this represent the state of the View. Has to be copied and set to be updated. Fragment will update the UI regarding the current state (`invalidate()` method). `Async` class from MvRx can be used in the ViewState, especially for asynchronous data loading. Nullability can also be used for optional data. ViewStates have to implement `MavericksState`;
- ViewEvents: useful when the ViewModel asks the View to trigger a specific action: navigation, show dialog, etc. See the parent [VectorViewEvents](../vector/src/main/java/im/vector/app/core/platform/VectorViewEvents.kt);
- ViewAction (`VectorViewModelAction`): useful when the UI (generally the Fragment) asks the ViewModel to do something. See the parent [VectorViewModelAction](../vector/src/main/java/im/vector/app/core/platform/VectorViewModelAction.kt);
- Controller: see the `Epoxy` section just below.
##### Behavior
Fragment asks the ViewModel to perform an action (coming from the user, but not necessarily. ViewModel can then talk to the SDK, updates the state once or several times. Fragment update the UI regarding the new state.
When ViewModel is instantiated, it can subscribe using the SDK Services to get live state of the data.
`invalidate()` has to be used by default, but it's possible to listen to specific member(s) of the `ViewState` using `onEach`. TODO Add an example.
`awaitState()` method
#### Epoxy
[Epoxy](https://github.com/airbnb/epoxy) is an Android library for building complex screens in a RecyclerView. Please read [the introduction](https://github.com/airbnb/epoxy#epoxy).
- Controller declares items of the RecyclerView. Controller is injected in the Fragment. Controller extends `EpoxyController`, or one of its subclass, especially `TypedEpoxyController`;
- Fragment gives the state to the controller using `setData`;
- `buildModels` will be called by the framework;
- Controller will create ordered Items.
Epoxy does the diffing, and handle many other thing for us, like handling item type, etc.
See for instance the controller [AccountDataEpoxyController](../vector/src/main/java/im/vector/app/features/settings/devtools/AccountDataEpoxyController.kt)) for a simple example.
Warning: do not use twice the same item `id` or it will crash.
#### Other frameworks
- Dependency injection is managed by [Dagger](https://dagger.dev/) (SDK) and [Hilt](https://developer.android.com/training/dependency-injection/hilt-android) (App);
- [Retrofit](https://square.github.io/retrofit/) and [OkHttp3](https://square.github.io/okhttp/): network requests;
- [Moshi](https://github.com/square/moshi) is used to parse and serialize Json object;
### Push
Please see the dedicated documentation for more details.
This is the classical scenario:
- App receives a Push. Note: Push is ignored if app is in foreground;
- App asks the SDK to load Event data (fastlane mode). We have a change to get the data faster and display the notification faster;
- App asks the SDK to perform a sync request.
### Dependencies management
All the dependencies are declared in `build.gradle` files. But some versions are declared in [this dedicated file](../dependencies.gradle).
When adding a new dependency, you will have to update the file [dependencies_groups.gradle](../dependencies_groups.gradle) to allow the dependency to be downloaded from the artifact repository. Sometimes sub-dependencies need to be added too, until the project can compile.
[Dependabot](https://github.com/dependabot) is set up on the project. This tool will automatically create Pull Request to upgrade our dependencies one by one.
dependencies_group, gradle files, Dependabot, etc.
### Test
Please refer to [this dedicated document](./ui-tests.md).
TODO add link to the dedicated screenshot test documentation
### Other points
#### Logging
**Important warning: ** NEVER log private user data, or use the flag `LOG_PRIVATE_DATA`. Be very careful when logging `data class`, all the content will be output!
[Timber](https://github.com/JakeWharton/timber) is used to log data to logcat. We do not use directly the `Log` class. If possible please use a tag, as per
````kotlin
Timber.tag(loggerTag.value).d("my log")
````
because automatic tag (= class name) will not be available on the release version.
Also generally it is recommended to provide the `Throwable` to the Timber log functions.
Last point, not that `Timber.v` function may have no effect on some devices. Prefer using `Timber.d` and up.
#### Rageshake
Rageshake is a feature to send bug report directly from the application. Just shake your phone and you will be prompted to send a bug report.
Bug report can contain:
- a screenshot of the current application state
- the application logs from up to 15 application starts
- the logcat logs
- the key share history (crypto data)
The data will be sent to an internal server, which is not publicly accessible. A GitHub issue will also be created to a private GitHub repository.
Rageshake can be very useful to get logs from a release version of the application.
### Tips
- Element Android has a `developer mode` in the `Settings/Advanced settings`. Other useful options are available here;
- Show hidden Events can also help to debug feature. When developer mode is enabled, it is possible to view the source (= the Json content) of any Events;
- Type `/devtools` in a Room composer to access a developer menu. There are some other entry points. Developer mode has to be enabled;
- Hidden debug menu: when developer mode is enabled and on debug build, there are some extra screens that can be accessible using the green wheel. In those screens, it will be possible to toggle some feature flags;
- Using logcat, filtering with `onResume` can help you to understand what screen are currently displayed on your device. Searching for string displayed on the screen can also help to find the running code in the codebase.
- When this is possible, prefer using `sealed interface` instead of `sealed class`;
- When writing temporary code, using the string "DO NOT COMMIT" in a comment can help to avoid committing things by mistake. If committed and pushed, the CI will detect this String and will warn the user about it.
## Happy coding!
The team is here to support you, feel free to ask anything to other developers.
Also please feel to update this documentation, if incomplete/wrong/obsolete/etc.
**Thanks!**

View File

@@ -28,6 +28,7 @@ Here are the checks that Danger does so far:
- PR with change on layout should include screenshot in the description
- PR which adds png file warn about the usage of vector drawables
- non draft PR should have a reviewer
- files containing translations are not modified by developers
### Quality check

View File

@@ -0,0 +1,72 @@
# Screenshot testing
<!--- TOC -->
* [Overview](#overview)
* [Setup](#setup)
* [Recording](#recording)
* [Verifying](#verifying)
* [Contributing](#contributing)
* [Example](#example)
<!--- END -->
## Overview
- Screenshot tests are tests which record the content of a rendered screen and verify subsequent runs to check if the screen renders differently.
- Element uses [Paparazzi](https://github.com/cashapp/paparazzi) to render, record and verify android layouts.
- The screenshot verification occurs on every pull request as part of the `tests.yml` workflow.
## Setup
- Install Git LFS through your package manager of choice (`brew install git-lfs` | `yay -S git-lfs`).
- Install the Git LFS hooks into the project.
```bash
# with element-android as the current working directory
git lfs install --local
```
- If installed correctly, `git push` and `git pull` will now include LFS content.
## Recording
- `./gradlew recordScreenshots`
- Paparazzi will generate images in `${module}/src/test/snapshots`, which will need to be committed to the repository using Git LFS.
## Verifying
- `./gradlew verifyScreenshots`
- In the case of failure, Paparazzi will generate images in `${module}/out/failure`. The images will show the expected and actual screenshots along with a delta of the two images.
## Contributing
- When creating a test, the file (and class) name names must include `ScreenshotTest`, eg `ItemScreenshotTest`.
- After creating the new test, record and commit the newly rendered screens.
- `./tools/validate_lfs` can be ran to ensure everything is working correctly with Git LFS, the CI also runs this check.
## Example
```kotlin
class PaparazziExampleScreenshotTest {
@get:Rule
val paparazzi = Paparazzi(
deviceConfig = PIXEL_3,
theme = "Theme.Vector.Light",
)
@Test
fun `example paparazzi test`() {
// Inflate the layout
val view = paparazzi.inflate<ConstraintLayout>(R.layout.item_radio)
// Bind data to the view
view.findViewById<TextView>(R.id.actionTitle).text = paparazzi.resources.getString(R.string.room_settings_all_messages)
view.findViewById<ImageView>(R.id.radioIcon).setImageResource(R.drawable.ic_radio_on)
// Record the bound view
paparazzi.snapshot(view)
}
}
```

View File

@@ -0,0 +1,2 @@
Main changes in this version: Deferred DM enabled by default.
Full changelog: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,42 @@
Element yra ir saugaus žinučių siuntimo, ir produktyvaus komandinio bendradarbiavimo programėlė, puikiai tinkanti grupiniams pokalbiams dirbant nuotoliniu būdu. Ši pokalbių programa naudoja visapusį šifravimą, kad užtikrintų galingas vaizdo konferencijas, dalijimąsi failais ir balso skambučius.
<b>Element funkcijos turi:</b>
- Išplėstinės bendravimo internetu priemonės
- Visiškai užšifruotos žinutės, kad būtų galima saugiau bendrauti su įmone, net ir su nuotoliniais darbuotojais
- Decentralizuoti pokalbiai, pagrįsti atvirojo kodo sistema Matrix
- Saugus dalijimasis failais su šifruotais duomenimis valdant projektus
- Vaizdo pokalbiai su IP balso perdavimu ir ekrano bendrinimu
- Lengva integracija su mėgstamiausiomis internetinėmis bendradarbiavimo priemonėmis, projektų valdymo įrankiais, VoIP paslaugomis ir kitomis komandinių pokalbių programomis
Element visiškai skiriasi nuo kitų žinučių siuntimo ir bendradarbiavimo programėlių. Ji veikia Matrix - atvirame tinkle, skirtame saugiam žinučių siuntimui ir decentralizuotam bendravimui. Jame galima savarankiškai talpinti duomenis ir žinutes savo serveryje, kad naudotojai galėtų maksimaliai valdyti ir kontroliuoti savo duomenis ir žinutes.
<b>Privatumas ir šifruotos žinutės</b>
Element apsaugo jus nuo nepageidaujamų reklamų, duomenų gavybos ir uždarų sodų. Jis taip pat apsaugo visus jūsų duomenis, "vienas su vienu" vaizdo ir balso ryšį, naudodamas visapusį šifravimą ir kryžmiškai pasirašytą įrenginių patvirtinimą.
Element suteikia galimybę kontroliuoti savo privatumą ir kartu saugiai bendrauti su visais, esančiais Matrix tinkle, arba kitais verslo bendradarbiavimo įrankiais integruojantis su tokiomis programėlėmis kaip Slack.
<b>Element gali būti savarankiškai talpinamas</b>
Kad galėtumėte geriau kontroliuoti savo slaptus duomenis ir pokalbius, Element gali būti savarankiškai talpinamas arba galite pasirinkti bet kurį Matrix pagrindu veikiantį serverį - atvirojo kodo decentralizuoto bendravimo standartu. Element suteikia privatumą, saugumo atititikimą ir integracijos lankstumą.
<b>Jūsų duomenys priklauso jums</b>
Jūs nusprendžiate, kur laikyti savo duomenis ir žinutes. Be duomenų gavybos ar trečiųjų šalių prieigos rizikos.
Element suteikia jums kontrolę įvairiais būdais:
1. Gaukite nemokamą paskyrą viešajame serveryje matrix.org, kurį talpina Matrix kūrėjai, arba rinkitės iš tūkstančių viešųjų serverių, kurių talpinimą teikia savanoriai
2. Savarankiškai talpinkite savo paskyrą, naudodami serverį savo IT infrastruktūroje
3. Užsisakykite paskyrą nuosavame serveryje tiesiog užsisakydami "Element Matrix Services" talpinimo paslaugą
<b>Atviras žinučių siuntimas ir bendradarbiavimas</b>
Galite bendrauti su bet kuriuo Matrix tinklo nariu, nesvarbu, ar jis naudojasi Element, kita Matrix programėle, ar net jei naudoja kitą žinučių siuntimo programėlę.
<b>Super saugus</b>
Tikras visapusis šifravimas (žinutes gali iššifruoti tik pokalbio dalyviai) ir kryžminiu parašu patvirtintas įrenginių patvirtinimas.
<b>Pilnas bendravimas ir integracija</b>
Žinučių siuntimas, balso ir vaizdo skambučiai, failų ir ekrano bendrinimas ir daugybė integracijų, robotų ir valdiklių. Kurkite kambarius, bendruomenes, palaikykite ryšį ir atlikite darbus.
<b>Tęskite darbą ten, kur baigėte</b>
Palaikykite ryšį, kad ir kur būtumėte, naudodami visiškai sinchronizuotą žinučių istoriją visuose įrenginiuose ir internete adresu https://app.element.io
<b>Atviras kodas</b>
Element Android yra atvirojo kodo projektas, kurį talpina GitHub. Praneškite apie klaidas ir (arba) prisidėkite prie jo kūrimo adresu https://github.com/vector-im/element-android

View File

@@ -0,0 +1 @@
Grupiniai pokalbiai - šifruotos žinutės ir vaizdo skambučiai

View File

@@ -0,0 +1 @@
Element - Saugūs pokalbiai

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -0,0 +1,2 @@
Belangrijkste veranderingen in deze versie: Verscheidene foutoplossingen en stabiliteitsverbeteringen.
Volledige lijst met veranderingen: https://github.com/vector-im/element-android/releases

View File

@@ -15,7 +15,7 @@ org.gradle.vfs.watch=true
org.gradle.caching=true
# Android Settings
android.enableJetifier=true
android.enableJetifier=false
android.useAndroidX=true
#Project Settings

View File

@@ -17,7 +17,6 @@
package im.vector.lib.attachmentviewer
import android.annotation.SuppressLint
import android.graphics.Color
import android.os.Build
import android.os.Bundle
@@ -136,7 +135,6 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
}
}
@Suppress("DEPRECATION")
private fun setDecorViewFullScreen() {
// This is important for the dispatchTouchEvent, if not we must correct
// the touch coordinates
@@ -144,22 +142,20 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
// New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
window.setDecorFitsSystemWindows(false)
// New API instead of SYSTEM_UI_FLAG_IMMERSIVE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
} else {
@SuppressLint("WrongConstant")
window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
}
window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// New API instead of FLAG_TRANSLUCENT_STATUS
window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
// new API instead of FLAG_TRANSLUCENT_NAVIGATION
window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
} else {
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE)
@Suppress("DEPRECATION")
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
@Suppress("DEPRECATION")
window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
}
}
@@ -344,7 +340,6 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
?.handleCommand(commands)
}
@Suppress("DEPRECATION")
private fun hideSystemUI() {
systemUiVisibility = false
// Enables regular immersive mode.
@@ -356,17 +351,13 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
// new API instead of SYSTEM_UI_FLAG_HIDE_NAVIGATION
window.decorView.windowInsetsController?.hide(WindowInsets.Type.navigationBars())
// New API instead of SYSTEM_UI_FLAG_IMMERSIVE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
} else {
@SuppressLint("WrongConstant")
window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE
}
window.decorView.windowInsetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
// New API instead of FLAG_TRANSLUCENT_STATUS
window.statusBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
// New API instead of FLAG_TRANSLUCENT_NAVIGATION
window.navigationBarColor = ContextCompat.getColor(this, R.color.half_transparent_status_bar)
} else {
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
// Set the content to appear under the system bars so that the
// content doesn't resize when the system bars hide and show.
@@ -381,13 +372,13 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi
// Shows the system bars by removing all the flags
// except for the ones that make the content appear under the system bars.
@Suppress("DEPRECATION")
private fun showSystemUI() {
systemUiVisibility = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// New API instead of SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN and SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
window.setDecorFitsSystemWindows(false)
} else {
@Suppress("DEPRECATION")
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)

30
library/external/dialpad/build.gradle vendored Normal file
View File

@@ -0,0 +1,30 @@
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
android {
compileSdk versions.compileSdk
defaultConfig {
minSdk versions.minSdk
targetSdk versions.targetSdk
}
compileOptions {
sourceCompatibility versions.sourceCompat
targetCompatibility versions.targetCompat
}
kotlinOptions {
jvmTarget = "11"
}
}
dependencies {
implementation libs.androidx.appCompat
}
afterEvaluate {
tasks.findAll { it.name.startsWith("lint") }.each {
it.enabled = false
}
}

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.android.dialer.dialpadview" />

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 com.android.dialer.animation;
import android.view.animation.Interpolator;
import com.android.dialer.compat.PathInterpolatorCompat;
public class AnimUtils {
public static final Interpolator EASE_OUT_EASE_IN =
PathInterpolatorCompat.create(0.4f, 0, 0.2f, 1);
}

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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 com.android.dialer.compat;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.os.Build;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
public class PathInterpolatorCompat {
public static Interpolator create(
float controlX1, float controlY1, float controlX2, float controlY2) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return new PathInterpolator(controlX1, controlY1, controlX2, controlY2);
}
return new PathInterpolatorBase(controlX1, controlY1, controlX2, controlY2);
}
private static class PathInterpolatorBase implements Interpolator {
/** Governs the accuracy of the approximation of the {@link Path}. */
private static final float PRECISION = 0.002f;
private final float[] mX;
private final float[] mY;
public PathInterpolatorBase(Path path) {
final PathMeasure pathMeasure = new PathMeasure(path, false /* forceClosed */);
final float pathLength = pathMeasure.getLength();
final int numPoints = (int) (pathLength / PRECISION) + 1;
mX = new float[numPoints];
mY = new float[numPoints];
final float[] position = new float[2];
for (int i = 0; i < numPoints; ++i) {
final float distance = (i * pathLength) / (numPoints - 1);
pathMeasure.getPosTan(distance, position, null /* tangent */);
mX[i] = position[0];
mY[i] = position[1];
}
}
public PathInterpolatorBase(float controlX, float controlY) {
this(createQuad(controlX, controlY));
}
public PathInterpolatorBase(
float controlX1, float controlY1, float controlX2, float controlY2) {
this(createCubic(controlX1, controlY1, controlX2, controlY2));
}
private static Path createQuad(float controlX, float controlY) {
final Path path = new Path();
path.moveTo(0.0f, 0.0f);
path.quadTo(controlX, controlY, 1.0f, 1.0f);
return path;
}
private static Path createCubic(
float controlX1, float controlY1, float controlX2, float controlY2) {
final Path path = new Path();
path.moveTo(0.0f, 0.0f);
path.cubicTo(controlX1, controlY1, controlX2, controlY2, 1.0f, 1.0f);
return path;
}
@Override
public float getInterpolation(float t) {
if (t <= 0.0f) {
return 0.0f;
} else if (t >= 1.0f) {
return 1.0f;
}
// Do a binary search for the correct x to interpolate between.
int startIndex = 0;
int endIndex = mX.length - 1;
while (endIndex - startIndex > 1) {
int midIndex = (startIndex + endIndex) / 2;
if (t < mX[midIndex]) {
endIndex = midIndex;
} else {
startIndex = midIndex;
}
}
final float xRange = mX[endIndex] - mX[startIndex];
if (xRange == 0) {
return mY[startIndex];
}
final float tInRange = t - mX[startIndex];
final float fraction = tInRange / xRange;
final float startY = mY[startIndex];
final float endY = mY[endIndex];
return startY + (fraction * (endY - startY));
}
}
}

View File

@@ -0,0 +1,231 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* 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 com.android.dialer.dialpadview;
import android.content.Context;
import android.graphics.RectF;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
/**
* Custom class for dialpad buttons.
*
* <p>When touch exploration mode is enabled for accessibility, this class implements the
* lift-to-type interaction model:
*
* <ul>
* <li>Hovering over the button will cause it to gain accessibility focus
* <li>Removing the hover pointer while inside the bounds of the button will perform a click action
* <li>If long-click is supported, hovering over the button for a longer period of time will switch
* to the long-click action
* <li>Moving the hover pointer outside of the bounds of the button will restore to the normal click
* action
* </ul>
*/
public class DialpadKeyButton extends FrameLayout {
/** Timeout before switching to long-click accessibility mode. */
private static final int LONG_HOVER_TIMEOUT = ViewConfiguration.getLongPressTimeout() * 2;
/** Accessibility manager instance used to check touch exploration state. */
private AccessibilityManager mAccessibilityManager;
/** Bounds used to filter HOVER_EXIT events. */
private RectF mHoverBounds = new RectF();
/** Whether this view is currently in the long-hover state. */
private boolean mLongHovered;
/** Alternate content description for long-hover state. */
private CharSequence mLongHoverContentDesc;
/** Backup of standard content description. Used for accessibility. */
private CharSequence mBackupContentDesc;
/** Backup of clickable property. Used for accessibility. */
private boolean mWasClickable;
/** Backup of long-clickable property. Used for accessibility. */
private boolean mWasLongClickable;
/** Runnable used to trigger long-click mode for accessibility. */
private Runnable mLongHoverRunnable;
private OnPressedListener mOnPressedListener;
public DialpadKeyButton(Context context, AttributeSet attrs) {
super(context, attrs);
initForAccessibility(context);
}
public DialpadKeyButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initForAccessibility(context);
}
public void setOnPressedListener(OnPressedListener onPressedListener) {
mOnPressedListener = onPressedListener;
}
private void initForAccessibility(Context context) {
mAccessibilityManager =
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
}
public void setLongHoverContentDescription(CharSequence contentDescription) {
mLongHoverContentDesc = contentDescription;
if (mLongHovered) {
super.setContentDescription(mLongHoverContentDesc);
}
}
@Override
public void setContentDescription(CharSequence contentDescription) {
if (mLongHovered) {
mBackupContentDesc = contentDescription;
} else {
super.setContentDescription(contentDescription);
}
}
@Override
public void setPressed(boolean pressed) {
super.setPressed(pressed);
if (mOnPressedListener != null) {
mOnPressedListener.onPressed(this, pressed);
}
}
@Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mHoverBounds.left = getPaddingLeft();
mHoverBounds.right = w - getPaddingRight();
mHoverBounds.top = getPaddingTop();
mHoverBounds.bottom = h - getPaddingBottom();
}
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (action == AccessibilityNodeInfo.ACTION_CLICK) {
simulateClickForAccessibility();
return true;
}
return super.performAccessibilityAction(action, arguments);
}
@Override
public boolean onHoverEvent(MotionEvent event) {
// When touch exploration is turned on, lifting a finger while inside
// the button's hover target bounds should perform a click action.
if (mAccessibilityManager.isEnabled() && mAccessibilityManager.isTouchExplorationEnabled()) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_HOVER_ENTER:
// Lift-to-type temporarily disables double-tap activation.
mWasClickable = isClickable();
mWasLongClickable = isLongClickable();
if (mWasLongClickable && mLongHoverContentDesc != null) {
if (mLongHoverRunnable == null) {
mLongHoverRunnable =
new Runnable() {
@Override
public void run() {
setLongHovered(true);
announceForAccessibility(mLongHoverContentDesc);
}
};
}
postDelayed(mLongHoverRunnable, LONG_HOVER_TIMEOUT);
}
setClickable(false);
setLongClickable(false);
break;
case MotionEvent.ACTION_HOVER_EXIT:
if (mHoverBounds.contains(event.getX(), event.getY())) {
if (mLongHovered) {
performLongClick();
} else {
simulateClickForAccessibility();
}
}
cancelLongHover();
setClickable(mWasClickable);
setLongClickable(mWasLongClickable);
break;
}
}
return super.onHoverEvent(event);
}
/**
* When accessibility is on, simulate press and release to preserve the semantic meaning of
* performClick(). Required for Braille support.
*/
private void simulateClickForAccessibility() {
// Checking the press state prevents double activation.
if (isPressed()) {
return;
}
setPressed(true);
// Stay consistent with performClick() by sending the event after
// setting the pressed state but before performing the action.
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
setPressed(false);
}
private void setLongHovered(boolean enabled) {
if (mLongHovered != enabled) {
mLongHovered = enabled;
// Switch between normal and alternate description, if available.
if (enabled) {
mBackupContentDesc = getContentDescription();
super.setContentDescription(mLongHoverContentDesc);
} else {
super.setContentDescription(mBackupContentDesc);
}
}
}
private void cancelLongHover() {
if (mLongHoverRunnable != null) {
removeCallbacks(mLongHoverRunnable);
}
setLongHovered(false);
}
public interface OnPressedListener {
void onPressed(View view, boolean pressed);
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 com.android.dialer.dialpadview;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.TextView;
/**
* This is a custom text view intended only for rendering the numerals (and star and pound) on the
* dialpad. TextView has built in top/bottom padding to help account for ascenders/descenders.
*
* <p>Since vertical space is at a premium on the dialpad, particularly if the font size is scaled
* to a larger default, for the dialpad we use this class to more precisely render characters
* according to the precise amount of space they need.
*/
public class DialpadTextView extends TextView {
private Rect mTextBounds = new Rect();
private String mTextStr;
public DialpadTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
/** Draw the text to fit within the height/width which have been specified during measurement. */
@Override
public void draw(Canvas canvas) {
Paint paint = getPaint();
// Without this, the draw does not respect the style's specified text color.
paint.setColor(getCurrentTextColor());
// The text bounds values are relative and can be negative,, so rather than specifying a
// standard origin such as 0, 0, we need to use negative of the left/top bounds.
// For example, the bounds may be: Left: 11, Right: 37, Top: -77, Bottom: 0
canvas.drawText(mTextStr, -mTextBounds.left, -mTextBounds.top, paint);
}
/**
* Calculate the pixel-accurate bounds of the text when rendered, and use that to specify the
* height and width.
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mTextStr = getText().toString();
getPaint().getTextBounds(mTextStr, 0, mTextStr.length(), mTextBounds);
int width = resolveSize(mTextBounds.width(), widthMeasureSpec);
int height = resolveSize(mTextBounds.height(), heightMeasureSpec);
setMeasuredDimension(width, height);
}
}

View File

@@ -0,0 +1,455 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 com.android.dialer.dialpadview;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.style.TtsSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewPropertyAnimator;
import android.view.accessibility.AccessibilityManager;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.dialer.animation.AnimUtils;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Locale;
/** View that displays a twelve-key phone dialpad. */
public class DialpadView extends LinearLayout {
private static final String TAG = DialpadView.class.getSimpleName();
private static final double DELAY_MULTIPLIER = 0.66;
private static final double DURATION_MULTIPLIER = 0.8;
// For animation.
private static final int KEY_FRAME_DURATION = 33;
/** {@code True} if the dialpad is in landscape orientation. */
private final boolean mIsLandscape;
/** {@code True} if the dialpad is showing in a right-to-left locale. */
private final boolean mIsRtl;
private final int[] mButtonIds =
new int[] {
R.id.zero,
R.id.one,
R.id.two,
R.id.three,
R.id.four,
R.id.five,
R.id.six,
R.id.seven,
R.id.eight,
R.id.nine,
R.id.star,
R.id.pound
};
private EditText mDigits;
private ImageButton mDelete;
private View mOverflowMenuButton;
private ViewGroup mRateContainer;
private TextView mIldCountry;
private TextView mIldRate;
private boolean mCanDigitsBeEdited;
private int mTranslateDistance;
public DialpadView(Context context) {
this(context, null);
}
public DialpadView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public DialpadView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mTranslateDistance =
getResources().getDimensionPixelSize(R.dimen.dialpad_key_button_translate_y);
mIsLandscape =
getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
mIsRtl = Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL;
}
@Override
protected void onFinishInflate() {
setupKeypad();
mDigits = (EditText) findViewById(R.id.digits);
mDelete = (ImageButton) findViewById(R.id.deleteButton);
mOverflowMenuButton = findViewById(R.id.dialpad_overflow);
mRateContainer = (ViewGroup) findViewById(R.id.rate_container);
mIldCountry = (TextView) mRateContainer.findViewById(R.id.ild_country);
mIldRate = (TextView) mRateContainer.findViewById(R.id.ild_rate);
AccessibilityManager accessibilityManager =
(AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
if (accessibilityManager.isEnabled()) {
// The text view must be selected to send accessibility events.
mDigits.setSelected(true);
}
}
private void setupKeypad() {
final int[] letterIds =
new int[] {
R.string.dialpad_0_letters,
R.string.dialpad_1_letters,
R.string.dialpad_2_letters,
R.string.dialpad_3_letters,
R.string.dialpad_4_letters,
R.string.dialpad_5_letters,
R.string.dialpad_6_letters,
R.string.dialpad_7_letters,
R.string.dialpad_8_letters,
R.string.dialpad_9_letters,
R.string.dialpad_star_letters,
R.string.dialpad_pound_letters
};
final Resources resources = getContext().getResources();
DialpadKeyButton dialpadKey;
TextView numberView;
TextView lettersView;
final Locale currentLocale = resources.getConfiguration().locale;
final NumberFormat nf;
// We translate dialpad numbers only for "fa" and not any other locale
// ("ar" anybody ?).
if ("fa".equals(currentLocale.getLanguage())) {
nf = DecimalFormat.getInstance(resources.getConfiguration().locale);
} else {
nf = DecimalFormat.getInstance(Locale.ENGLISH);
}
for (int i = 0; i < mButtonIds.length; i++) {
dialpadKey = (DialpadKeyButton) findViewById(mButtonIds[i]);
numberView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_number);
lettersView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_letters);
final String numberString;
final CharSequence numberContentDescription;
if (mButtonIds[i] == R.id.pound) {
numberString = resources.getString(R.string.dialpad_pound_number);
numberContentDescription = numberString;
} else if (mButtonIds[i] == R.id.star) {
numberString = resources.getString(R.string.dialpad_star_number);
numberContentDescription = numberString;
} else {
numberString = nf.format(i);
// The content description is used for Talkback key presses. The number is
// separated by a "," to introduce a slight delay. Convert letters into a verbatim
// span so that they are read as letters instead of as one word.
String letters = resources.getString(letterIds[i]);
Spannable spannable =
Spannable.Factory.getInstance().newSpannable(numberString + "," + letters);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
spannable.setSpan(
(new TtsSpan.VerbatimBuilder(letters)).build(),
numberString.length() + 1,
numberString.length() + 1 + letters.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
numberContentDescription = spannable;
}
numberView.setText(numberString);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
numberView.setElegantTextHeight(false);
}
dialpadKey.setContentDescription(numberContentDescription);
if (lettersView != null) {
lettersView.setText(resources.getString(letterIds[i]));
}
}
final DialpadKeyButton one = (DialpadKeyButton) findViewById(R.id.one);
one.setLongHoverContentDescription(resources.getText(R.string.description_voicemail_button));
final DialpadKeyButton zero = (DialpadKeyButton) findViewById(R.id.zero);
zero.setLongHoverContentDescription(resources.getText(R.string.description_image_button_plus));
}
private Drawable getDrawableCompat(Context context, int id) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return context.getDrawable(id);
} else {
return context.getResources().getDrawable(id);
}
}
public void setShowVoicemailButton(boolean show) {
View view = findViewById(R.id.dialpad_key_voicemail);
if (view != null) {
view.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
}
}
/**
* Whether or not the digits above the dialer can be edited.
*
* @param canBeEdited If true, the backspace button will be shown and the digits EditText will be
* configured to allow text manipulation.
*/
public void setCanDigitsBeEdited(boolean canBeEdited) {
// View deleteButton = findViewById(R.id.deleteButton);
// deleteButton.setVisibility(canBeEdited ? View.VISIBLE : View.INVISIBLE);
// View overflowMenuButton = findViewById(R.id.dialpad_overflow);
// overflowMenuButton.setVisibility(canBeEdited ? View.VISIBLE : View.GONE);
// EditText digits = (EditText) findViewById(R.id.digits);
// digits.setClickable(canBeEdited);
// digits.setLongClickable(canBeEdited);
// digits.setFocusableInTouchMode(canBeEdited);
// digits.setCursorVisible(false);
mCanDigitsBeEdited = canBeEdited;
}
public void setCallRateInformation(String countryName, String displayRate) {
if (TextUtils.isEmpty(countryName) && TextUtils.isEmpty(displayRate)) {
mRateContainer.setVisibility(View.GONE);
return;
}
mRateContainer.setVisibility(View.VISIBLE);
mIldCountry.setText(countryName);
mIldRate.setText(displayRate);
}
public boolean canDigitsBeEdited() {
return mCanDigitsBeEdited;
}
/**
* Always returns true for onHoverEvent callbacks, to fix problems with accessibility due to the
* dialpad overlaying other fragments.
*/
@Override
public boolean onHoverEvent(MotionEvent event) {
return true;
}
public void animateShow() {
// This is a hack; without this, the setTranslationY is delayed in being applied, and the
// numbers appear at their original position (0) momentarily before animating.
final AnimatorListenerAdapter showListener = new AnimatorListenerAdapter() {};
for (int i = 0; i < mButtonIds.length; i++) {
int delay = (int) (getKeyButtonAnimationDelay(mButtonIds[i]) * DELAY_MULTIPLIER);
int duration = (int) (getKeyButtonAnimationDuration(mButtonIds[i]) * DURATION_MULTIPLIER);
final DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(mButtonIds[i]);
ViewPropertyAnimator animator = dialpadKey.animate();
if (mIsLandscape) {
// Landscape orientation requires translation along the X axis.
// For RTL locales, ensure we translate negative on the X axis.
dialpadKey.setTranslationX((mIsRtl ? -1 : 1) * mTranslateDistance);
animator.translationX(0);
} else {
// Portrait orientation requires translation along the Y axis.
dialpadKey.setTranslationY(mTranslateDistance);
animator.translationY(0);
}
animator
.setInterpolator(AnimUtils.EASE_OUT_EASE_IN)
.setStartDelay(delay)
.setDuration(duration)
.setListener(showListener)
.start();
}
}
public EditText getDigits() {
return mDigits;
}
public ImageButton getDeleteButton() {
return mDelete;
}
public View getOverflowMenuButton() {
return mOverflowMenuButton;
}
/**
* Get the animation delay for the buttons, taking into account whether the dialpad is in
* landscape left-to-right, landscape right-to-left, or portrait.
*
* @param buttonId The button ID.
* @return The animation delay.
*/
private int getKeyButtonAnimationDelay(int buttonId) {
if (mIsLandscape) {
if (mIsRtl) {
if (buttonId == R.id.three) {
return KEY_FRAME_DURATION * 1;
} else if (buttonId == R.id.six) {
return KEY_FRAME_DURATION * 2;
} else if (buttonId == R.id.nine) {
return KEY_FRAME_DURATION * 3;
} else if (buttonId == R.id.pound) {
return KEY_FRAME_DURATION * 4;
} else if (buttonId == R.id.two) {
return KEY_FRAME_DURATION * 5;
} else if (buttonId == R.id.five) {
return KEY_FRAME_DURATION * 6;
} else if (buttonId == R.id.eight) {
return KEY_FRAME_DURATION * 7;
} else if (buttonId == R.id.zero) {
return KEY_FRAME_DURATION * 8;
} else if (buttonId == R.id.one) {
return KEY_FRAME_DURATION * 9;
} else if (buttonId == R.id.four) {
return KEY_FRAME_DURATION * 10;
} else if (buttonId == R.id.seven || buttonId == R.id.star) {
return KEY_FRAME_DURATION * 11;
}
} else {
if (buttonId == R.id.one) {
return KEY_FRAME_DURATION * 1;
} else if (buttonId == R.id.four) {
return KEY_FRAME_DURATION * 2;
} else if (buttonId == R.id.seven) {
return KEY_FRAME_DURATION * 3;
} else if (buttonId == R.id.star) {
return KEY_FRAME_DURATION * 4;
} else if (buttonId == R.id.two) {
return KEY_FRAME_DURATION * 5;
} else if (buttonId == R.id.five) {
return KEY_FRAME_DURATION * 6;
} else if (buttonId == R.id.eight) {
return KEY_FRAME_DURATION * 7;
} else if (buttonId == R.id.zero) {
return KEY_FRAME_DURATION * 8;
} else if (buttonId == R.id.three) {
return KEY_FRAME_DURATION * 9;
} else if (buttonId == R.id.six) {
return KEY_FRAME_DURATION * 10;
} else if (buttonId == R.id.nine || buttonId == R.id.pound) {
return KEY_FRAME_DURATION * 11;
}
}
} else {
if (buttonId == R.id.one) {
return KEY_FRAME_DURATION * 1;
} else if (buttonId == R.id.two) {
return KEY_FRAME_DURATION * 2;
} else if (buttonId == R.id.three) {
return KEY_FRAME_DURATION * 3;
} else if (buttonId == R.id.four) {
return KEY_FRAME_DURATION * 4;
} else if (buttonId == R.id.five) {
return KEY_FRAME_DURATION * 5;
} else if (buttonId == R.id.six) {
return KEY_FRAME_DURATION * 6;
} else if (buttonId == R.id.seven) {
return KEY_FRAME_DURATION * 7;
} else if (buttonId == R.id.eight) {
return KEY_FRAME_DURATION * 8;
} else if (buttonId == R.id.nine) {
return KEY_FRAME_DURATION * 9;
} else if (buttonId == R.id.star) {
return KEY_FRAME_DURATION * 10;
} else if (buttonId == R.id.zero || buttonId == R.id.pound) {
return KEY_FRAME_DURATION * 11;
}
}
Log.wtf(TAG, "Attempted to get animation delay for invalid key button id.");
return 0;
}
/**
* Get the button animation duration, taking into account whether the dialpad is in landscape
* left-to-right, landscape right-to-left, or portrait.
*
* @param buttonId The button ID.
* @return The animation duration.
*/
private int getKeyButtonAnimationDuration(int buttonId) {
if (mIsLandscape) {
if (mIsRtl) {
if (buttonId == R.id.one
|| buttonId == R.id.four
|| buttonId == R.id.seven
|| buttonId == R.id.star) {
return KEY_FRAME_DURATION * 8;
} else if (buttonId == R.id.two
|| buttonId == R.id.five
|| buttonId == R.id.eight
|| buttonId == R.id.zero) {
return KEY_FRAME_DURATION * 9;
} else if (buttonId == R.id.three
|| buttonId == R.id.six
|| buttonId == R.id.nine
|| buttonId == R.id.pound) {
return KEY_FRAME_DURATION * 10;
}
} else {
if (buttonId == R.id.one
|| buttonId == R.id.four
|| buttonId == R.id.seven
|| buttonId == R.id.star) {
return KEY_FRAME_DURATION * 10;
} else if (buttonId == R.id.two
|| buttonId == R.id.five
|| buttonId == R.id.eight
|| buttonId == R.id.zero) {
return KEY_FRAME_DURATION * 9;
} else if (buttonId == R.id.three
|| buttonId == R.id.six
|| buttonId == R.id.nine
|| buttonId == R.id.pound) {
return KEY_FRAME_DURATION * 8;
}
}
} else {
if (buttonId == R.id.one
|| buttonId == R.id.two
|| buttonId == R.id.three
|| buttonId == R.id.four
|| buttonId == R.id.five
|| buttonId == R.id.six) {
return KEY_FRAME_DURATION * 10;
} else if (buttonId == R.id.seven || buttonId == R.id.eight || buttonId == R.id.nine) {
return KEY_FRAME_DURATION * 9;
} else if (buttonId == R.id.star || buttonId == R.id.zero || buttonId == R.id.pound) {
return KEY_FRAME_DURATION * 8;
}
}
Log.wtf(TAG, "Attempted to get animation duration for invalid key button id.");
return 0;
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* 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 com.android.dialer.dialpadview;
import android.content.Context;
import android.graphics.Rect;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.inputmethod.InputMethodManager;
import com.android.dialer.widget.ResizingTextEditText;
/** EditText which suppresses IME show up. */
public class DigitsEditText extends ResizingTextEditText {
private OnTextContextMenuClickListener mOnTextContextMenuClickListener;
public DigitsEditText(Context context, AttributeSet attrs) {
super(context, attrs);
setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
setShowSoftInputOnFocus(false);
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
final InputMethodManager imm =
((InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE));
if (imm != null && imm.isActive(this)) {
imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final boolean ret = super.onTouchEvent(event);
// Must be done after super.onTouchEvent()
final InputMethodManager imm =
((InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE));
if (imm != null && imm.isActive(this)) {
imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
}
return ret;
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
if (isCursorVisible()) {
setSelection(getText().length());
}
}
@Override
public boolean onTextContextMenuItem(int id) {
boolean value = super.onTextContextMenuItem(id);
if (mOnTextContextMenuClickListener != null) {
mOnTextContextMenuClickListener.onTextContextMenuClickListener(id);
}
return value;
}
public interface OnTextContextMenuClickListener {
void onTextContextMenuClickListener(int id);
}
public void setOnTextContextMenuClickListener(OnTextContextMenuClickListener listener) {
this.mOnTextContextMenuClickListener = listener;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2012 The Android Open Source Project
*
* 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 com.android.dialer.util;
import android.graphics.Paint;
import android.util.TypedValue;
import android.widget.TextView;
/** Provides static functions to work with views */
public class ViewUtil {
private ViewUtil() {}
public static void resizeText(TextView textView, int originalTextSize, int minTextSize) {
final Paint paint = textView.getPaint();
final int width = textView.getWidth();
if (width == 0) {
return;
}
textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, originalTextSize);
float ratio = width / paint.measureText(textView.getText().toString());
if (ratio <= 1.0f) {
textView.setTextSize(
TypedValue.COMPLEX_UNIT_PX, Math.max(minTextSize, originalTextSize * ratio));
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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 com.android.dialer.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.EditText;
import com.android.dialer.dialpadview.R;
import com.android.dialer.util.ViewUtil;
/** EditText which resizes dynamically with respect to text length. */
public class ResizingTextEditText extends EditText {
private final int mOriginalTextSize;
private final int mMinTextSize;
public ResizingTextEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mOriginalTextSize = (int) getTextSize();
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ResizingText);
mMinTextSize =
(int) a.getDimension(R.styleable.ResizingText_resizing_text_min_size, mOriginalTextSize);
a.recycle();
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
ViewUtil.resizeText(this, mOriginalTextSize, mMinTextSize);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
ViewUtil.resizeText(this, mOriginalTextSize, mMinTextSize);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

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