feat: Add vcard - #816
Conversation
| <?xml version="1.0" encoding="utf-8"?> | ||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
|
||
| <application> |
There was a problem hiding this comment.
ContactCard has no network calls, should I still do something?
There was a problem hiding this comment.
Pull request overview
Adds a reusable Compose contact-card feature with local persistence, QR presentation, and vCard sharing.
Changes:
- Adds contact-card models and Room schema v9.
- Adds creation, editing, preview, deletion, QR, and sharing UI.
- Registers the module and required dependencies/resources.
Reviewed changes
Copilot reviewed 55 out of 55 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
Ui/Compose/ContactCard/src/main/res/xml/contact_card_paths.xml |
Configures shareable cache paths. |
Ui/Compose/ContactCard/src/main/res/values/strings.xml |
Adds default UI strings. |
Ui/Compose/ContactCard/src/main/res/values-sv/strings.xml |
Adds Swedish translations. |
Ui/Compose/ContactCard/src/main/res/values-pt/strings.xml |
Adds Portuguese translations. |
Ui/Compose/ContactCard/src/main/res/values-pl/strings.xml |
Adds Polish translations. |
Ui/Compose/ContactCard/src/main/res/values-nl/strings.xml |
Adds Dutch translations. |
Ui/Compose/ContactCard/src/main/res/values-nb/strings.xml |
Adds Norwegian translations. |
Ui/Compose/ContactCard/src/main/res/values-it/strings.xml |
Adds Italian translations. |
Ui/Compose/ContactCard/src/main/res/values-fr/strings.xml |
Adds French translations. |
Ui/Compose/ContactCard/src/main/res/values-fi/strings.xml |
Adds Finnish translations. |
Ui/Compose/ContactCard/src/main/res/values-es/strings.xml |
Adds Spanish translations. |
Ui/Compose/ContactCard/src/main/res/values-el/strings.xml |
Adds Greek translations. |
Ui/Compose/ContactCard/src/main/res/values-de/strings.xml |
Adds German translations. |
Ui/Compose/ContactCard/src/main/res/values-da/strings.xml |
Adds Danish translations. |
Ui/Compose/ContactCard/src/main/res/drawable/onboarding_vcard.xml |
Adds onboarding illustration. |
Ui/Compose/ContactCard/src/main/res/drawable/ic_x.xml |
Adds X icon. |
Ui/Compose/ContactCard/src/main/res/drawable/ic_pencil.xml |
Adds edit icon. |
Ui/Compose/ContactCard/src/main/res/drawable/ic_linkedin.xml |
Adds LinkedIn icon. |
Ui/Compose/ContactCard/src/main/res/drawable/ic_link.xml |
Adds link icon. |
Ui/Compose/ContactCard/src/main/res/drawable/ic_instagram.xml |
Adds Instagram icon. |
Ui/Compose/ContactCard/src/main/res/drawable/ic_facebook.xml |
Adds Facebook icon. |
Ui/Compose/ContactCard/src/main/res/drawable/ic_bin.xml |
Adds deletion icon. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardViewModel.kt |
Manages editing and persistence state. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardShareExt.kt |
Creates and shares vCard files. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardScreen.kt |
Coordinates feature screens and actions. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardFileProvider.kt |
Defines the sharing provider. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/SectionCard.kt |
Adds editor section containers. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/QrCodeHeader.kt |
Renders vCard QR codes. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewTopBar.kt |
Adds preview navigation actions. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewData.kt |
Supplies Compose preview data. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewContent.kt |
Renders contact-card previews. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/PreviewActionsBottomSheet.kt |
Adds edit and delete actions. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/OnboardingContent.kt |
Adds feature onboarding UI. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/LoadingContent.kt |
Adds loading UI. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/LinksRow.kt |
Displays link-type icons. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/FieldDivider.kt |
Adds editor field dividers. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorTopBar.kt |
Adds save and cancel actions. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorField.kt |
Defines contact editor fields. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorContent.kt |
Implements contact-card editing. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactVCardBloc.kt |
Composes the visual contact card. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactInfoRows.kt |
Displays contact details. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/ContactCardConstants.kt |
Defines shared dimensions. |
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/BottomSheetAction.kt |
Defines bottom-sheet actions. |
Ui/Compose/ContactCard/src/main/AndroidManifest.xml |
Registers the file provider. |
Ui/Compose/ContactCard/build.gradle.kts |
Configures the new module. |
settings.gradle.kts |
Includes the ContactCard module. |
Network/build.gradle.kts |
Exposes OkHttp transitively. |
gradle/core.versions.toml |
Adds dependencies and module alias. |
Auth/src/main/kotlin/com/infomaniak/core/auth/room/UserDatabase.kt |
Adds card conversion and migration. |
Auth/src/main/kotlin/com/infomaniak/core/auth/models/user/User.kt |
Associates cards with users. |
Auth/src/main/kotlin/com/infomaniak/core/auth/models/user/Card.kt |
Defines card models and vCard output. |
Auth/src/main/kotlin/com/infomaniak/core/auth/CredentialManager.kt |
Removes the duplicated user lookup. |
Auth/src/main/kotlin/com/infomaniak/core/auth/BaseCredentialManager.kt |
Adds shared user access/update APIs. |
Auth/schemas/com.infomaniak.core.auth.room.UserDatabase/9.json |
Records Room schema v9. |
Auth/build.gradle.kts |
Adds Compose UI dependency. |
| @SerializedName("card") @SerialName("card") | ||
| val card: Card? = null, |
There was a problem hiding this comment.
Card did not exist before this PR, is there still an issue?
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 62 out of 62 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (6)
Ui/Compose/ContactCard/build.gradle.kts:18
ContactCardScreen,ContactCardViewModel, and the sharing extensions exposeCard/Userin their public signatures, butAuthis hidden from consumers' compile classpaths as animplementationdependency. An app depending only on this module can therefore fail to compile against those APIs. This dependency must be exposed withapi.
implementation(project(":Auth"))
Ui/Compose/ContactCard/build.gradle.kts:36
- This adds QRose as a runtime dependency, but
LICENSES.mdhas no QRose entry. The repository requires that file to be updated whenever a runtime dependency is added or removed.
implementation(core.qrose)
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/component/EditorContent.kt:71
- These callbacks and the state write run directly during composition. Composition may be retried or abandoned, which can trigger duplicate database saves or invalid state mutations. Handle
requestSavein aLaunchedEffect(requestSave)(or model save as an event outside composition).
if (requestSave) {
onSaveHandled()
if (isValid) onSave() else showValidationError = true
Ui/Compose/ContactCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardScreen.kt:230
- The back button has no accessibility label, so TalkBack announces an unlabeled control. Add a localized “Back” content description rather than treating this interactive icon as decorative.
contentDescription = null,
Auth/src/main/kotlin/com/infomaniak/core/auth/models/user/User.kt:49
- Inserting this defaulted parameter before the existing required
loginparameter still breaks every positionalUser(...)call in consuming composite builds: the former login argument is now matched toCard. Preserve source compatibility by appending the optional field after the existing constructor parameters (and regenerate the Room schema).
@SerializedName("card") @SerialName("card")
val card: Card? = null,
Auth/src/main/kotlin/com/infomaniak/core/auth/models/user/Card.kt:64
- The embedded bytes are always declared as JPEG, but
avatarBase64can come from any successful avatar response, including PNG or WebP. Such a mismatched PHOTO property is ignored by some contact importers. Carry the response media type into vCard generation and emit the correspondingTYPE(or omit the photo when unsupported).
if (!forQRCode) {
avatarBase64?.let {
builder.appendLine("PHOTO;ENCODING=b;TYPE=JPEG:$it")
}
| <?xml version="1.0" encoding="utf-8"?> | ||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
|
||
| <application> |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 63 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (3)
Auth/src/main/kotlin/com/infomaniak/core/auth/models/user/Card.kt:69
- vCard 3.0 folds at 75 UTF-8 octets, but this compares and slices UTF-16 character positions. Non-ASCII names or organizations can therefore produce overlong lines, and slicing can split a surrogate pair, yielding an invalid vCard. Fold the encoded bytes while keeping UTF-8 code points intact.
private fun StringBuilder.appendVCardLine(content: String) {
val maxOctets = 75
if (content.length <= maxOctets) {
Ui/Compose/ContactCard/build.gradle.kts:36
qroseis a new runtime dependency, but it is absent fromLICENSES.md. Add QRose and its MIT license to the repository license inventory as required for runtime dependency changes.
implementation(core.qrose)
Ui/Compose/ContactCard/build.gradle.kts:18
- The module's public APIs expose
CardandUsertypes (for example,ContactCardScreentakes(Card) -> Unit), butAuthis hidden as an implementation dependency. A consumer depending only on ContactCard will not receive those types on its compile classpath. Export Auth withapiso this independently consumed module has a usable public contract.
implementation(project(":Auth"))
| open suspend fun updateUser(user: User) { | ||
| userDatabase.userDao().update(user) |
| val mimeType = body.contentType()?.subtype?.uppercase() | ||
| val base64 = Base64.encodeToString(body.bytes(), Base64.NO_WRAP) |
| fun ContactCardScreen( | ||
| onBack: () -> Unit, | ||
| onShare: (Card) -> Unit, | ||
| viewModel: ContactCardViewModel = viewModel(), |
|


No description provided.