* Add initial Sentry setup for crashes and perf tracking
* Fix failing analytics tests
* Reformat code to fix style issue
* Close sentry when user signs out
* Add initial unit tests for Sentry
* Remove unused import
* Exclude amitkma from signoff requirements for PRs
* Fix crash on image upload preview on Android P
Using hardware bitmap allocation on Android framework versions prior to
Android Q causes a crash when decoding a bitmap if GL context wasn't
initialised. The issue is not documented in ImageDecoder reference but
it is mentioned in the comments of glide[1] with a link to internal
google discussion.
[1] f83cc274b4/library/src/main/java/com/bumptech/glide/load/resource/bitmap/HardwareConfigState.java (L22)
Signed-off-by: Paweł Matuszewski <pamat@protonmail.com>
We do not use `android-embedded_fcm_distributor` anymore (since #7068).
The code was compiling because `android-embedded_fcm_distributor` has a dependency on `firebase-messaging`.
- forcing the stem string template generator to be cachable, without this the templates are regenerated causing the vector module to recompile its sources (our slowest task!)
* feature/mna/clean-vm-for-dm-v2:
RefreshDevicesOnCryptoDevicesChangeUseCase unit tests
Adding changelog entry
Fix some coding style issues
DevicesViewModel unit tests
GetDeviceFullInfoListUseCase unit tests
GetCurrentSessionCrossSigningInfoUseCase unit tests
RefreshDevicesUseCase unit tests
Updating existing unit tests
Listen verification + refresh devices use cases
Moving recently created use cases inside v2 package
Inject new ViewModel in the fragment V2 + add use cases
Declare MarkAsManuallyVerified action
Empty ViewModel V2
# Conflicts:
# vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
* feature/mna/session-overview-screen: (57 commits)
Fix missing mapper in CryptoStoreHelper for tests
Fix unused string warning
Update unit tests
Rendering inactive status in SessionInfoView
Adding comment with examples of some parametrized strings
Fix post rebase
Fixing wrong copyright title
Adding last seen details + fix observation of wrong deviceId in ViewModel
Adding learn more link in verification status details
Unit tests for computing trust level of device
Unit tests for GetCurrentSessionCrossSigningInfoUseCase
Updating existing unit tests
Navigation from other session item
Show info in overview screen
Renaming CurrentSessionView into SessionInfoView to be more generic
Introducing some reusable usecases
Adding unit tests for viewModel
Adding unit tests for mapper
Adding unit tests for the new use case
Adding use case to get full device info for a given device id
...
# Conflicts:
# library/ui-strings/src/main/res/values/strings.xml
# vector/src/main/AndroidManifest.xml
# vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt
# vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
# vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesViewNavigator.kt
* feature/ons/device_manager_current_session: (169 commits)
new app layouts invites (#6911)
bottom navigation tabs are removed for AppLayout (#6905)
focus input when changing server address
Fix copyright
Improve createRoomThreePidEvents for clarity
Remove roomCreatorUserId and use current userId by default
Remove useless explicit field type
Change visibility of LocalRoomThirdPartyInviteContent to internal
Remove useless apply in CreateLocalRoomStateEventsTask
Update doc
Extract condition to reduce code complexity
Verify tombstone event
Remove safe call
Add unit tests for CreateRoomFromLocalRoomTask
Add unit tests for CreateLocalRoomStateEventsTask
Set stateKey as empty by default
Create local room state events in dedicated task
Fix local events generation following the specification
Update CreateRoomParams from the potential FeaturePreset before persisting
Persists CreateRoomParams into LocalRoomSummaryEntity
...
# Conflicts:
# vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
* develop: (169 commits)
new app layouts invites (#6911)
bottom navigation tabs are removed for AppLayout (#6905)
focus input when changing server address
Fix copyright
Improve createRoomThreePidEvents for clarity
Remove roomCreatorUserId and use current userId by default
Remove useless explicit field type
Change visibility of LocalRoomThirdPartyInviteContent to internal
Remove useless apply in CreateLocalRoomStateEventsTask
Update doc
Extract condition to reduce code complexity
Verify tombstone event
Remove safe call
Add unit tests for CreateRoomFromLocalRoomTask
Add unit tests for CreateLocalRoomStateEventsTask
Set stateKey as empty by default
Create local room state events in dedicated task
Fix local events generation following the specification
Update CreateRoomParams from the potential FeaturePreset before persisting
Persists CreateRoomParams into LocalRoomSummaryEntity
...
# Conflicts:
# vector/src/main/java/im/vector/app/features/settings/devices/v2/VectorSettingsDevicesFragment.kt
This patch removes the dependency on `VectorSettings` as well as only
enable animated rendering if the image is actually playable.
Signed-off-by: networkException <git@nwex.de>
This patch introduces a new `ImageContentRenderer` mode used for
autoplaying animated images. The mode shares url resolving semantics
with `FULL_SIZE` and `STICKER`, as such not just fetching thumbnail data
but shares sizing semantics with `THUMBNAIL` (scaling by image height).
This change fixes animated images not playing in cases in which only a
static thumbnail would be loaded.
This new mode will only be chosen if the message content is actually a
playable image, as such limiting bandwith usage to the required amount
by avoiding to load normal images fully (still fetching animated images
will increase bandwith usage as a whole of course).
Signed-off-by: networkException <git@nwex.de>
- we were saving the default distributor before asking the user, which meant when the user selected the same option it was skipped from being registered
- only unregisters during the force flow, otherwise we'll crash due to no app being registered
- this behaviour puts the app in an invalid state as we've lost all the ViewState we've collect from the previous onboarding steps
- the app already handles restoring the onboarding state via the system restoration
- the sync worker makes use of the CoroutineWorker which does not stop when the work completes, this means we often append to the existing worker. When appending by default the previous worker result payload is merged with (or in our case overwrites) the input data instead, meaning any failure state is set and kept until the worker stops, which in turns causes the sync worker to never sync
- the fix is to make use of an input merge that always favour the request input data instead of the previous worker results
* Decreases the size of rounded corners
* Increases the maximum width of message bubbles to help avoid unnecessary unused space on screen
Signed-off-by: Danny Seymour <danny@seymour.family>
2022-04-07 02:36:07 -07:00
1830 changed files with 34887 additions and 9444 deletions
- New App Layout is now enabled by default! Go to the Settings > Labs to toggle this ([#7166](https://github.com/vector-im/element-android/issues/7166))
- Render inline images in the timeline ([#351](https://github.com/vector-im/element-android/issues/351))
- Add privacy setting to disable personalized learning by the keyboard ([#6633](https://github.com/vector-im/element-android/issues/6633))
Bugfixes 🐛
----------
- Disable emoji keyboard not applies in reply ([#5029](https://github.com/vector-im/element-android/issues/5029))
- Fix animated images not autoplaying sometimes if only a thumbnail was fetched from the server ([#6215](https://github.com/vector-im/element-android/issues/6215))
- Add Warning shield when a user previously verified rotated their cross signing keys ([#6702](https://github.com/vector-im/element-android/issues/6702))
- Can't verify user when option to send keys to verified devices only is selected ([#6723](https://github.com/vector-im/element-android/issues/6723))
- Add option to only send to verified devices per room (web parity) ([#6725](https://github.com/vector-im/element-android/issues/6725))
- Delete pin code key and the key used for biometrics authentication on logout ([#6906](https://github.com/vector-im/element-android/issues/6906))
- Fix crash on previewing images to upload on Android Pie. ([#7184](https://github.com/vector-im/element-android/issues/7184))
- Fix app restarts in loop on Android 13 on the first run of the app. ([#7224](https://github.com/vector-im/element-android/issues/7224))
In development 🚧
----------------
- [Device Management] Learn more bottom sheets ([#7100](https://github.com/vector-im/element-android/issues/7100))
- [Device management] Verify current session ([#7114](https://github.com/vector-im/element-android/issues/7114))
- [Device management] Verify another session ([#7143](https://github.com/vector-im/element-android/issues/7143))
- [Device management] Rename a session ([#7158](https://github.com/vector-im/element-android/issues/7158))
- [Device Manager] Unverified and inactive sessions list ([#7170](https://github.com/vector-im/element-android/issues/7170))
- [Device management] Sign out a session ([#7190](https://github.com/vector-im/element-android/issues/7190))
- [Device Manager] Parse user agents ([#7247](https://github.com/vector-im/element-android/issues/7247))
- [Voice Broadcast] Add a feature flag with the composer action ([#7258](https://github.com/vector-im/element-android/issues/7258))
Improved Documentation 📚
------------------------
- Draft onboarding documentation of the project at `./docs/_developer_onboarding.md` ([#7126](https://github.com/vector-im/element-android/issues/7126))
SDK API changes ⚠️
------------------
- Allow the sync timeout to be configured (mainly useful for testing) ([#7198](https://github.com/vector-im/element-android/issues/7198))
- Ports SDK instrumentation tests to use suspending functions instead of countdown latches ([#7207](https://github.com/vector-im/element-android/issues/7207))
- [Device Manager] Extend user agent to include device information ([#7209](https://github.com/vector-im/element-android/issues/7209))
Other changes
-------------
- Add support for `/tableflip` command ([#12](https://github.com/vector-im/element-android/issues/12))
- Decreases the size of rounded corners and increases the maximum width of message bubbles to help avoid unnecessary unused space on screen ([#5712](https://github.com/vector-im/element-android/issues/5712))
- [AppLayout]: added tracking of new analytics events ([#6508](https://github.com/vector-im/element-android/issues/6508))
- Target API 12 and compile with Android SDK 32. ([#6929](https://github.com/vector-im/element-android/issues/6929))
- Add basic integration of Sentry to capture errors and crashes if user has given consent. ([#7076](https://github.com/vector-im/element-android/issues/7076))
- Add support to `/devtools` command. ([#7126](https://github.com/vector-im/element-android/issues/7126))
- Fix lint warning, and cleanup the code ([#7159](https://github.com/vector-im/element-android/issues/7159))
- Mutualize the pending auth handling ([#7193](https://github.com/vector-im/element-android/issues/7193))
- CI: Prevent modification of translations by developer. ([#7211](https://github.com/vector-im/element-android/issues/7211))
- Fix typo in strings.xml and make sure this is American English. ([#7287](https://github.com/vector-im/element-android/issues/7287))
Changes in Element v1.5.1 (2022-09-28)
======================================
Security ⚠️
----------
This update provides important security fixes, update now.
Ref: CVE-2022-39246 CVE-2022-39248
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))
- [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))
- 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)
=======================================
New App Layout can be enabled in the Labs settings. Please give it a try!
Features ✨
----------
- Adds New App Layout into Labs ([#7038](https://github.com/vector-im/element-android/issues/7038))
- Try to detect devices that lack Opus encoder support, use bundled libopus library for those. ([#7010](https://github.com/vector-im/element-android/issues/7010))
- Suggest @room when @channel, @everyone, or @here is typed in composer ([#6529](https://github.com/vector-im/element-android/issues/6529))
Bugfixes 🐛
----------
- Fix long incremental sync. ([#6917](https://github.com/vector-im/element-android/issues/6917))
- Fix push with FCM ([#7068](https://github.com/vector-im/element-android/issues/7068))
- Catch race condition crash in voice recording ([#6989](https://github.com/vector-im/element-android/issues/6989))
- Fix invite to room when in a space buttons not working. ([#7054](https://github.com/vector-im/element-android/issues/7054))
In development 🚧
----------------
- Create DM room only on first message - Create the DM and navigate to the new room after sending an event ([#5525](https://github.com/vector-im/element-android/issues/5525))
- [App Layout] New empty states for home screen ([#6835](https://github.com/vector-im/element-android/issues/6835))
- [App Layout] Bottom navigation tabs are removed for new home screen ([#6565](https://github.com/vector-im/element-android/issues/6565))
- [App Layout] fixed space switching dialog measured with wrong height sometimes ([#6750](https://github.com/vector-im/element-android/issues/6750))
- [App Layout] Fabs doesn't go off screen anymore ([#6765](https://github.com/vector-im/element-android/issues/6765))
- [New Layout] Adds back navigation through spaces ([#6877](https://github.com/vector-im/element-android/issues/6877))
- [App Layout] new room invites screen ([#6889](https://github.com/vector-im/element-android/issues/6889))
- [App Layout] - Invites now show empty screen after you reject last invite ([#6876](https://github.com/vector-im/element-android/issues/6876))
- [App Layout] - space switcher now has empty state ([#6754](https://github.com/vector-im/element-android/issues/6754))
- [App Layout] - Improves Developer Mode Debug Button UX and adds it to New App Layout ([#6871](https://github.com/vector-im/element-android/issues/6871))
- [New Layout] Changes space sheet to accordion-style with expandable subspaces ([#6907](https://github.com/vector-im/element-android/issues/6907))
- [New Layout] Adds space invites ([#6924](https://github.com/vector-im/element-android/issues/6924))
- [App Layout] fixed invites count badge bottom margin on a home screen ([#6947](https://github.com/vector-im/element-android/issues/6947))
- [New Layout] Changes space icon in fab and in release notes screen ([#7039](https://github.com/vector-im/element-android/issues/7039))
- [New Layout] Adds header to spaces bottom sheet ([#7040](https://github.com/vector-im/element-android/issues/7040))
- [App Layout] New App Layout is enabled by default (Edit: has to be enabled in Labs) ([#6958](https://github.com/vector-im/element-android/issues/6958))
- [App Layout] Obsolete settings are not shown when App Layout flag is enabled ([#6646](https://github.com/vector-im/element-android/issues/6646))
- Clarify that setting up a FCM Rewrite Proxy is not necessary for use of the UnifiedPush FCM distributor. ([#6727](https://github.com/vector-im/element-android/issues/6727))
- Focus input field when editing homeserver address to speed up login and registration. ([#6926](https://github.com/vector-im/element-android/issues/6926))
- Log basic Http information in production. ([#6925](https://github.com/vector-im/element-android/issues/6925))
- Converts the vector module to a library with a parent vector-app application module ([#6407](https://github.com/vector-im/element-android/issues/6407))
- Creates a dedicated strings module ([#3955](https://github.com/vector-im/element-android/issues/3955))
- Remove FragmentModule and the Fragment factory. No need to Inject the constructor on your Fragment, just add @AndroidEntryPoint annotation and @Inject class members. ([#6894](https://github.com/vector-im/element-android/issues/6894))
- Small refactor of UnifiedPushHelper ([#6936](https://github.com/vector-im/element-android/issues/6936))
- CI: only run sonarqube task when token is known ([#7057](https://github.com/vector-im/element-android/issues/7057))
Changes in Element v1.4.34 (2022-08-23)
=======================================
Features ✨
----------
- [Notification] - Handle creation of notification for live location and poll start ([#6746](https://github.com/vector-im/element-android/issues/6746))
Bugfixes 🐛
----------
- Fixes onboarding requiring matrix.org to be accessible on the first step, the server can now be manually changed ([#6718](https://github.com/vector-im/element-android/issues/6718))
- Fixing sign in/up for homeservers that rely on the SSO fallback url ([#6827](https://github.com/vector-im/element-android/issues/6827))
- Fixes uncaught exceptions in the SyncWorker to cause the worker to become stuck in the failure state ([#6836](https://github.com/vector-im/element-android/issues/6836))
- Fixes onboarding captcha crashing when no WebView is available by showing an error with information instead ([#6855](https://github.com/vector-im/element-android/issues/6855))
- Removes ability to continue registration after the app has been destroyed, fixes the next steps crashing due to missing information from the previous steps ([#6860](https://github.com/vector-im/element-android/issues/6860))
- Fixes crash when exiting the login or registration entry screens whilst they're loading ([#6861](https://github.com/vector-im/element-android/issues/6861))
- Fixes server selection being unable to trust certificates ([#6864](https://github.com/vector-im/element-android/issues/6864))
- Ensure SyncThread is started when the app is launched after a Push has been received. ([#6884](https://github.com/vector-im/element-android/issues/6884))
- Fixes missing firebase notifications after logging in when UnifiedPush distributor is installed ([#6891](https://github.com/vector-im/element-android/issues/6891))
In development 🚧
----------------
- Create DM room only on first message - Trigger the flow when the "Direct Message" action is selected from the room member details screen ([#5525](https://github.com/vector-im/element-android/issues/5525))
- added filter tabs for new App layout's Home screen ([#6505](https://github.com/vector-im/element-android/issues/6505))
- [App Layout] added dialog to configure app layout ([#6506](https://github.com/vector-im/element-android/issues/6506))
- Adds space list bottom sheet for new app layout ([#6749](https://github.com/vector-im/element-android/issues/6749))
- [App Layout] Dialpad moved from bottom navigation tab to a separate activity accessed via home screen context menu ([#6787](https://github.com/vector-im/element-android/issues/6787))
- Makes toolbar switch title based on space in New App Layout ([#6795](https://github.com/vector-im/element-android/issues/6795))
- [Devices management] Add a feature flag and empty screen for future new layout ([#6798](https://github.com/vector-im/element-android/issues/6798))
- Adds new chat bottom sheet as the click action of the main FAB in the new app layout ([#6801](https://github.com/vector-im/element-android/issues/6801))
- [Devices management] Other sessions section in new layout ([#6806](https://github.com/vector-im/element-android/issues/6806))
- [New Layout] Adds space settings accessible through clicking the toolbar ([#6859](https://github.com/vector-im/element-android/issues/6859))
- Rename `DebugService.logDbUsageInfo` (resp. `Session.logDbUsageInfo`) to `DebugService.getDbUsageInfo` (resp. `Session.getDbUsageInfo`) and return a String instead of logging. The caller may want to log the String. ([#6884](https://github.com/vector-im/element-android/issues/6884))
Other changes
-------------
- Removes the Login2 proof of concept - replaced by the FTUE changes ([#5974](https://github.com/vector-im/element-android/issues/5974))
- Enable auto-capitalization for Room creation Title field ([#6645](https://github.com/vector-im/element-android/issues/6645))
- Decouples the variant logic from the vector module ([#6783](https://github.com/vector-im/element-android/issues/6783))
- Add a developer setting to enable LeakCanary at runtime ([#6786](https://github.com/vector-im/element-android/issues/6786))
- [Create Room] Reduce some boilerplate with room state event contents ([#6799](https://github.com/vector-im/element-android/issues/6799))
- [Call] Memory leak after a call ([#6808](https://github.com/vector-im/element-android/issues/6808))
- Fix some string template ([#6843](https://github.com/vector-im/element-android/issues/6843))
Element Android support can be found in this room: [](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.
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_`.
@@ -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).
*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.
- 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.
@@ -18,7 +18,7 @@ The recently started UnifiedPush project is an Android protocol and library for
The *F-Droid* and *Gplay* flavors of Element Android support UnifiedPush, so the user can use any distributor installed on their devices. This would make it possible to have push notifications without depending on Google services or libraries. Currently, the main distributors are [ntfy](https://ntfy.sh) which does not require any setup (like manual registration) to use the public server and [NextPush](https://github.com/UP-NextPush/android), available as a nextcloud application.
The *Gplay* variant uses a UnifiedPush library which basically embed a FCM distributor built into the application (so a user doesn't need to do anything other than install the app to get FCM notifications). This variant uses Google Services to receive notifications if the user has not installed any distributor.
The *Gplay* variant uses a UnifiedPush library which basically embed a FCM distributor built into the application (so a user doesn't need to do anything other than install the app to get FCM notifications). This variant uses Google Services to receive notifications if the user has not installed any distributor. A [FCM Rewrite Proxy](https://unifiedpush.org/developers/embedded_fcm/#fcm-rewrite-proxy) is not required for Element Android's implementation of the FCM distributor - it will work with an existing Matrix push provider, such as [Sygnal](https://github.com/matrix-org/sygnal).
The *F-Droid* variant does not use this library to avoid any proprietary blob. It will use a polling service if the user has not installed any distributor.
* [Extensions used to streamline the test setup](#extensions-used-to-streamline-the-test-setup)
* [Fakes and Fixtures](#fakes-and-fixtures)
<!--- END -->
## Overview
Unit tests are a mechanism to validate our code executes the way we expect. They help to inform the design of our systems by requiring testability and
understanding, they describe the inner workings without relying on inline comments and protect from unexpected regressions.
However, unit tests are not a magical solution to solve all our problems and come at a cost. Unreliable and hard to maintain tests often end up ignored, deleted
or worse, provide a false sense of security.
### Best Practices
Tests can be written in many ways, the main rule is to keep them simple and maintainable. Some ways to help achieve this are...
- Break out logic into single units (following the Single Responsibility Principle) to reduce test complexity.
- Favour pure functions, avoiding mutable state.
- Prefer dependency injection to static calls to allow for simpler test setup.
- Write concise tests with a single function under test, clearly showing the inputs and expected output.
- Create separate test cases instead of changing parameters and grouping multiple assertions within a single test to help trace back failure causes (with the
exception of parameterised tests).
- Assert against entire models instead of subsets of properties to capture any possible changes within the test scope.
- Avoid invoking logic from production instances other than the class under test to guard from unrelated changes.
- Always inject `Dispatchers` and `Clock` instances and provide fake implementations for tests to avoid non deterministic results.
## Project Conventions
#### Setup
- Test file and class name should be the class under test with the Test suffix, created in a `test` sourceset, with the same package name as the class under
test.
- Dependencies of the class are instantiated inline, junit will recreate the test class for each test run.
- A line break between the dependencies and class under test helps clarify the instance being tested.
```kotlin
classMyClassTest{
privatevalfakeUppercaser=FakeUppercaser()
// line break between the class under test and its dependencies
fun`given a lowercase label, when uppercasing, then returns label uppercased`
```
When the input is given directly to the _when_, this can also be represented as...
```kotlin
@Test
fun`when uppercasing a lowercase label, then returns label uppercased`
```
Multiple given or returns statements can be used in the name although it could be a sign that the logic being tested does too much.
---
#### Format
- Test bodies are broken into sections through the use of blank lines where the sections correspond to the test name.
- Sections can span multiple lines.
```kotlin
// comments are for illustrative purposes
/* given */ val lowercaseLabel = "hello world"
/* when */ val result = textUppercaser.uppercase(lowercaseLabel)
/* then */ result shouldBeEqualTo "HELLO WORLD"
```
- Functions extracted from test bodies are placed beneath all the unit tests.
---
#### Assertions
- Assertions against test results are made using [Kluent's](https://github.com/MarkusAmshove/Kluent) _fluent_ api.
- Typically `shouldBeEqualTo`is the main assertion to use for asserting function return values as by project convention we assert against entire objects or
lists.
```kotlin
val result = listOf("hello", "world")
// Fail
result shouldBeEqualTo listOf("hello")
```
```kotlin
data class Person(val age: Int, val name: String)
val result = Person(age = 100, name = "Gandalf")
// Avoid
result.age shouldBeEqualTo 100
// Prefer
result shouldBeEqualTo Person(age = 100, "Gandalf")
```
- Exception throwing can be asserted against using `assertFailsWith<T:Throwable>`.
- When asserting reusable exceptions, include the message to distinguish between them.
```kotlin
assertFailsWith<ConcreteException>(message = "Details about error") {
// when section of the test
codeUnderTest()
}
```
---
#### Constants
- Reusable values are extracted to file level immutable properties or constants.
- These can be parameters or expected results.
- The naming convention is to prefix with `A` or `AN` for better matching with the test name.
```kotlin
private const val A_LOWERCASE_LABEL = "hello"
class MyTest {
@Test
fun `when uppercasing a lowercase label, then returns label uppercased`() {
val result = TextUppercaser().uppercase(A_LOWERCASE_LABEL)
...
}
}
```
---
#### Mocking
- In order to provide different behaviour for dependencies within tests our main method is through mocking, using [Mockk](https://mockk.io/).
- We avoid using relaxed mocks in favour of explicitly declaring mock behaviour through the _Fake_ convention. There are exceptions when mocking framework
classes which would require a lot of boilerplate.
- Using `Spy` is discouraged as it inherently requires real instances, which we are avoiding in our tests. There are exceptions such as `VectorFeatures` which
acts like a `Fixture` in release builds.
---
#### Fakes
- Fakes are reusable instances of classes purely for testing purposes. They provide functions to replace the functions of the interface/class they're faking
with test specific values.
- When faking an interface, the _Fake_ can be written using delegation or by stubbing
- All Fakes currently reside in the same package `${package}.test.fakes`
```kotlin
// Delegating to a mock
class FakeClock : Clock by mockk() {
fun givenEpoch(epoch: Long) {
every { epochMillis() } returns epoch
}
}
// Stubbing the interface
class FakeClock(private val epoch: Long) : Clock {
override fun epochMillis() = epoch
}
```
It's currently more common for fakes to fake class behaviour, we achieve this by wrapping and exposing a mock instance.
```kotlin
class FakeCursor {
val instance = mockk<Cursor>()
fun givenEmpty() {
every { instance.count } returns 0
every { instance.moveToFirst() } returns false
}
}
val fakeCursor = FakeCursor().apply { givenEmpty() }
```
#### Fixtures
- Fixtures are a reusable wrappers around data models. They provide default values to make creating instances as easy as possible, with the option to override
specific parameters when needed.
- Are namespaced within an `object`.
- Reduces the _find usages_ noise when searching for usages of the origin class construction.
- All Fixtures currently reside in the same package `${package}.test.fixtures`.
```kotlin
object ContentAttachmentDataFixture {
fun aContentAttachmentData(
type: ContentAttachmentData.Type.TEXT,
mimeType: String? = null
) = ContentAttachmentData(type, mimeType)
}
```
- Fixtures can also be used to manage specific combinations of parameters
```kotlin
fun aContentAttachmentAudioData() = aContentAttachmentData(
type = ContentAttachmentData.Type.AUDIO,
mimeType = "audio/mp3",
)
```
---
### Examples
##### Extensions used to streamline the test setup
```kotlin
class CircularCacheTest {
@Test
fun `when putting more than cache size then cache is limited to cache size`() {
val (cache, internalData) = createIntCache(cacheSize = 3)
cache.putInOrder(1, 1, 1, 1, 1, 1)
internalData shouldBeEqualTo arrayOf(1, 1, 1)
}
}
private fun createIntCache(cacheSize: Int): Pair<CircularCache<Int>, Array<Int?>> {
- `ViewModels` often emit multiple states which are copies of the previous state, the `test` extension `assertStatesChanges` allows only the difference to be
supplied.
```kotlin
data class ViewState(val name: String? = null, val age: Int? = null)
Főbb változások ebben a verzióban: Lehetővé teszi a felhasználók számára, hogy offline jelenjenek meg, és audio lejátszót ad hozzá a hangmellékletekhez.
Teljes változásjegyzék: https://github.com/vector-im/element-android/releases
Főbb változások ebben a verzióban: Lehetővé teszi a felhasználók számára, hogy offline jelenjenek meg, és audio lejátszót ad hozzá a hangmellékletekhez.
Teljes változásjegyzék: https://github.com/vector-im/element-android/releases
Főbb változások ebben a verzióban: Különböző hibajavítások és stabilitásjavítások.
Teljes változásjegyzék: https://github.com/vector-im/element-android/releases
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.