feat: Add email contact picker when sending by email#620
feat: Add email contact picker when sending by email#620
Conversation
PR Reviewer Guide 🔍(Review updated until commit a2b1da9)Here are some key observations to aid the review process:
|
|
Persistent review updated to latest commit a604891 |
|
Persistent review updated to latest commit e08157e |
|
Persistent review updated to latest commit 2bb029a |
|
Persistent review updated to latest commit 573e64e |
|
Persistent review updated to latest commit a83cc96 |
|
Persistent review updated to latest commit a2b1da9 |
…y, improve performance and avoiding threading issues
a2b1da9 to
c9db984
Compare
There was a problem hiding this comment.
Pull request overview
Adds a native contact-picker affordance when sending a transfer by email, allowing users to select contacts and populate recipient email addresses.
Changes:
- Adds a trailing icon slot to
EmailAddressTextFieldand wires it through the decoration box. - Adds a trailing contact-picker button in
PickFilesScreento launch the native contacts email picker (multi-select when supported). - Adds ViewModel handling to read picked contact URIs via
ContentResolverand append discovered emails to recipients. - Adds localized accessibility content-description strings and a new
PersonsCircleAddvector icon.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| app/src/main/res/values/strings.xml | Adds default locale content description for the contact picker button. |
| app/src/main/res/values-sv/strings.xml | Adds Swedish translation for the new content description. |
| app/src/main/res/values-pt/strings.xml | Adds Portuguese translation for the new content description. |
| app/src/main/res/values-pl/strings.xml | Adds Polish translation for the new content description. |
| app/src/main/res/values-nl/strings.xml | Adds Dutch translation for the new content description. |
| app/src/main/res/values-nb/strings.xml | Adds Norwegian Bokmål translation for the new content description. |
| app/src/main/res/values-it/strings.xml | Adds Italian translation for the new content description. |
| app/src/main/res/values-fr/strings.xml | Adds French translation for the new content description. |
| app/src/main/res/values-fi/strings.xml | Adds Finnish translation for the new content description. |
| app/src/main/res/values-es/strings.xml | Adds Spanish translation for the new content description. |
| app/src/main/res/values-el/strings.xml | Adds Greek translation for the new content description. |
| app/src/main/res/values-de/strings.xml | Adds German translation for the new content description. |
| app/src/main/res/values-da/strings.xml | Adds Danish translation for the new content description. |
| app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/pickfiles/components/EmailAddressTextField.kt | Exposes trailingIcon support to display the picker button inside the recipient field. |
| app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/pickfiles/PickFilesViewModel.kt | Implements contact URI processing to extract and add recipient emails. |
| app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/pickfiles/PickFilesScreen.kt | Adds the trailing icon button and launches the contact picker; forwards results to the ViewModel. |
| app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/PersonsCircleAdd.kt | Introduces the contact-picker icon used by the new trailing button. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| try { | ||
| viewModelScope.launch { contactPickLaunch(sessionUris, context) } | ||
| } catch (e: Exception) { | ||
| SentryLog.e(TAG, "Error while importing contacts from picker result", e) |
There was a problem hiding this comment.
The try/catch here won’t catch failures thrown inside the coroutine (it only wraps the synchronous call to viewModelScope.launch). If queryContacts/contentResolver throws (e.g., SecurityException), the exception will be uncaught in viewModelScope. Wrap the body of the launched coroutine in runCatching/try-catch (or install a CoroutineExceptionHandler) so errors are logged and don’t crash/cancel the scope.
| try { | |
| viewModelScope.launch { contactPickLaunch(sessionUris, context) } | |
| } catch (e: Exception) { | |
| SentryLog.e(TAG, "Error while importing contacts from picker result", e) | |
| viewModelScope.launch { | |
| try { | |
| contactPickLaunch(sessionUris, context) | |
| } catch (e: Exception) { | |
| SentryLog.e(TAG, "Error while importing contacts from picker result", e) | |
| } |
| fun processContactPickerResultUri( | ||
| sessionUris: Uri, | ||
| context: Context, | ||
| ) { |
There was a problem hiding this comment.
This ViewModel method requires a UI Context to be passed in, which forces the UI layer to thread a Context through callbacks. In this codebase, ViewModels that need a Context typically inject @ApplicationContext (e.g., SettingsSentryViewModel.kt:37-39). Consider injecting @ApplicationContext into PickFilesViewModel and using that ContentResolver instead, so callers only pass the picked Uri(s).
| private suspend fun updateValidatedRecipientsEmails(newEmails: Set<String>) = withContext(Dispatchers.Main) { | ||
| validatedRecipientsEmails = validatedRecipientsEmails + newEmails | ||
| } |
There was a problem hiding this comment.
Avoid hard-coding Dispatchers.Main inside a ViewModel when you already have injected dispatchers (ioDispatcher) and the caller coroutine resumes on Main after withContext(ioDispatcher). This extra context switch is unnecessary and makes testing harder; prefer updating state in the existing viewModelScope context or inject a Main dispatcher if needed.
| selectedTransferType: GetSetCallbacks<TransferTypeUi>, | ||
| transferOptionsCallbacks: TransferOptionsCallbacks, | ||
| pickFiles: () -> Unit, | ||
| selectContact: (Uri, Context) -> Unit, |
There was a problem hiding this comment.
The selectContact callback signature includes Context, which propagates Android framework types through the composable tree and makes the API harder to reuse/test. If the ViewModel injects @ApplicationContext (see comment in PickFilesViewModel), this callback can likely be simplified to only pass the picked Uri (or a list of Uris).
| selectContact: (Uri, Context) -> Unit, | |
| selectContact: (Uri) -> Unit, |
b84cb36 to
3839858
Compare
3839858 to
f610f42
Compare
|



Ajout d'un bouton dans la zone de saisie pour l'envoi par email, pour ouvrir la sélection de contact native.
Note: Nouvelle méthode disponible pour android 17, à regarder à sa sortie.