-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Bootstrap ContactCard Compose module with resources #819
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
cecb026
refactor: Expose okhttp as api in Network module
Elouan1411 96537ad
feat: Add ContactCard file provider and share extensions
Elouan1411 599f00a
feat: Bootstrap ContactCard Compose module
Elouan1411 20f11be
feat: Add ContactCard drawable resources
Elouan1411 937e034
feat: Add ContactCard string resources
Elouan1411 16cb0a4
feat: Update LICENSES.md
Elouan1411 07ee4ec
fix: Fix copilot review
Elouan1411 dee3d49
refactor: Clean code
Elouan1411 0215fc8
fix: Add security check for unknown content length
Elouan1411 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,35 +1,37 @@ | ||
| # Open Source Licenses | ||
|
|
||
| Infomaniak Android Core declares the following notable open source libraries as runtime dependencies (build-time and test-only dependencies are excluded). This list may not be exhaustive. | ||
| Infomaniak Android Core declares the following notable open source libraries as runtime dependencies (build-time and test-only | ||
| dependencies are excluded). This list may not be exhaustive. | ||
|
|
||
| | Library | License | | ||
| |---------|---------| | ||
| | [AndroidX AppCompat](https://developer.android.com/jetpack/androidx/releases/appcompat) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Biometric](https://developer.android.com/jetpack/androidx/releases/biometric) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Browser](https://developer.android.com/jetpack/androidx/releases/browser) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Core KTX](https://developer.android.com/jetpack/androidx/releases/core) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Core Splashscreen](https://developer.android.com/jetpack/androidx/releases/core) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX DataStore Preferences](https://developer.android.com/jetpack/androidx/releases/datastore) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Lifecycle](https://developer.android.com/jetpack/androidx/releases/lifecycle) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Navigation](https://developer.android.com/jetpack/androidx/releases/navigation) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX RecyclerView](https://developer.android.com/jetpack/androidx/releases/recyclerview) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Room](https://developer.android.com/jetpack/androidx/releases/room) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Work Runtime](https://developer.android.com/jetpack/androidx/releases/work) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Coil](https://github.com/coil-kt/coil) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Dagger Hilt](https://dagger.dev/hilt/) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [DotLottie Android](https://github.com/LottieFiles/dotlottie-android) | [MIT License](https://opensource.org/licenses/MIT) | | ||
| | [Google Material Components for Android](https://github.com/material-components/material-components-android) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Google Play App Update](https://developer.android.com/guide/playcore/in-app-updates) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Google Play Integrity](https://developer.android.com/google/play/integrity) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Google Play Review](https://developer.android.com/guide/playcore/in-app-review) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Jetpack Compose](https://developer.android.com/jetpack/compose) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Kotlin Standard Library](https://kotlinlang.org/) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Kotlinx Coroutines](https://github.com/Kotlin/kotlinx.coroutines) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Kotlinx Serialization](https://github.com/Kotlin/kotlinx.serialization) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Ktor](https://ktor.io/) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Lottie](https://github.com/airbnb/lottie-android) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Matomo SDK for Android](https://github.com/matomo-org/matomo-sdk-android) | [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) | | ||
| | [OkHttp](https://github.com/square/okhttp) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Okio](https://github.com/square/okio) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Sentry Android SDK](https://github.com/getsentry/sentry-java) | [MIT License](https://opensource.org/licenses/MIT) | | ||
| | [Splitties](https://github.com/LouisCAD/Splitties) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | Library | License | | ||
| |--------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------| | ||
| | [AndroidX AppCompat](https://developer.android.com/jetpack/androidx/releases/appcompat) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Biometric](https://developer.android.com/jetpack/androidx/releases/biometric) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Browser](https://developer.android.com/jetpack/androidx/releases/browser) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Core KTX](https://developer.android.com/jetpack/androidx/releases/core) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Core Splashscreen](https://developer.android.com/jetpack/androidx/releases/core) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX DataStore Preferences](https://developer.android.com/jetpack/androidx/releases/datastore) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Lifecycle](https://developer.android.com/jetpack/androidx/releases/lifecycle) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Navigation](https://developer.android.com/jetpack/androidx/releases/navigation) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX RecyclerView](https://developer.android.com/jetpack/androidx/releases/recyclerview) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Room](https://developer.android.com/jetpack/androidx/releases/room) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [AndroidX Work Runtime](https://developer.android.com/jetpack/androidx/releases/work) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Coil](https://github.com/coil-kt/coil) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Dagger Hilt](https://dagger.dev/hilt/) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [DotLottie Android](https://github.com/LottieFiles/dotlottie-android) | [MIT License](https://opensource.org/licenses/MIT) | | ||
| | [Google Material Components for Android](https://github.com/material-components/material-components-android) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Google Play App Update](https://developer.android.com/guide/playcore/in-app-updates) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Google Play Integrity](https://developer.android.com/google/play/integrity) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Google Play Review](https://developer.android.com/guide/playcore/in-app-review) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Jetpack Compose](https://developer.android.com/jetpack/compose) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Kotlin Standard Library](https://kotlinlang.org/) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Kotlinx Coroutines](https://github.com/Kotlin/kotlinx.coroutines) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Kotlinx Serialization](https://github.com/Kotlin/kotlinx.serialization) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Ktor](https://ktor.io/) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Lottie](https://github.com/airbnb/lottie-android) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Matomo SDK for Android](https://github.com/matomo-org/matomo-sdk-android) | [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) | | ||
| | [QRose](https://github.com/alexzhirkevich/qrose) | [MIT License](https://opensource.org/licenses/MIT) | | ||
| | [OkHttp](https://github.com/square/okhttp) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Okio](https://github.com/square/okio) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
| | [Sentry Android SDK](https://github.com/getsentry/sentry-java) | [MIT License](https://opensource.org/licenses/MIT) | | ||
| | [Splitties](https://github.com/LouisCAD/Splitties) | [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0) | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| plugins { | ||
| alias(core.plugins.infomaniak.android.library) | ||
| alias(core.plugins.infomaniak.android.library.flavor.aware) | ||
| alias(core.plugins.compose.compiler) | ||
| } | ||
|
|
||
| android { | ||
| namespace = "com.infomaniak.core.ui.compose.contactcard" | ||
|
|
||
| buildFeatures { | ||
| compose = true | ||
| } | ||
| } | ||
|
|
||
| dependencies { | ||
| api(core.androidx.lifecycle.viewmodel.ktx) | ||
| api(project(":Auth")) | ||
| implementation(project(":Avatar")) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Put all the project together. |
||
| implementation(project(":Common")) | ||
| implementation(project(":Ui:View:PrimaryPalette")) | ||
| implementation(project(":Ui:Compose:Margin")) | ||
| implementation(project(":Network")) | ||
|
|
||
| implementation(platform(core.compose.bom)) | ||
| api(core.compose.runtime) | ||
| api(core.compose.ui) | ||
| implementation(core.compose.foundation) | ||
| implementation(core.compose.material3) | ||
| implementation(core.compose.material.icons) | ||
| implementation("androidx.compose.material:material-icons-extended") | ||
| implementation(core.compose.ui.tooling.preview) | ||
|
|
||
| implementation(core.androidx.lifecycle.viewmodel.compose) | ||
| implementation(core.androidx.lifecycle.runtime.compose) | ||
| implementation(core.qrose) | ||
|
Elouan1411 marked this conversation as resolved.
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
|
|
||
| <application> | ||
|
github-advanced-security[bot] marked this conversation as resolved.
Fixed
github-advanced-security[bot] marked this conversation as resolved.
Fixed
|
||
|
|
||
| <provider | ||
| android:name=".ContactCardFileProvider" | ||
| android:authorities="${applicationId}.core.contactcard.provider" | ||
| android:exported="false" | ||
| android:grantUriPermissions="true"> | ||
| <meta-data | ||
| android:name="android.support.FILE_PROVIDER_PATHS" | ||
| android:resource="@xml/contact_card_paths" /> | ||
| </provider> | ||
| </application> | ||
| </manifest> | ||
22 changes: 22 additions & 0 deletions
22
...ard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardFileProvider.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| /* | ||
| * Infomaniak Core - Android | ||
| * Copyright (C) 2026 Infomaniak Network SA | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
| package com.infomaniak.core.ui.compose.contactcard | ||
|
|
||
| import androidx.core.content.FileProvider | ||
|
|
||
| class ContactCardFileProvider : FileProvider() |
89 changes: 89 additions & 0 deletions
89
...actCard/src/main/kotlin/com/infomaniak/core/ui/compose/contactcard/ContactCardShareExt.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| /* | ||
| * Infomaniak Core - Android | ||
| * Copyright (C) 2026 Infomaniak Network SA | ||
| * | ||
| * This program is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation, either (at your option) any later version. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| * | ||
| * You should have received a copy of the GNU General Public License | ||
| * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
| package com.infomaniak.core.ui.compose.contactcard | ||
|
|
||
| import android.app.Activity | ||
| import android.content.Context | ||
| import android.content.Intent | ||
| import android.util.Base64 | ||
| import androidx.core.content.FileProvider | ||
| import com.infomaniak.core.auth.models.user.Card | ||
| import com.infomaniak.core.common.cancellable | ||
| import com.infomaniak.core.network.networking.HttpClient | ||
| import com.infomaniak.core.network.utils.await | ||
| import kotlinx.coroutines.Dispatchers | ||
| import kotlinx.coroutines.withContext | ||
| import okhttp3.Request | ||
| import java.io.File | ||
|
|
||
| private const val MAX_AVATAR_SIZE = 5 * 1024 * 1024 // 5 MB | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But you can keep this one. |
||
| private val ILLEGAL_FILE_NAME_CHARACTERS = Regex("[\\\\/:*?\"<>|]+") | ||
|
|
||
| suspend fun Card.createShareFile(context: Context): File = withContext(Dispatchers.IO) { | ||
| val (avatarBase64, avatarMimeType) = getAvatarDataOrNull() | ||
|
|
||
| val fileName = "attachments_cache${firstName}_${lastName}.vcf" | ||
| val safeFileName = fileName.replace(ILLEGAL_FILE_NAME_CHARACTERS, "") | ||
|
|
||
| val directory = File(context.cacheDir, "attachments_cache").apply { mkdirs() } | ||
|
|
||
| File(directory, safeFileName).apply { | ||
| val vCardContent = makeVCardString(avatarBase64 = avatarBase64, avatarMimeType = avatarMimeType) | ||
| writeText(vCardContent) | ||
| } | ||
| } | ||
|
|
||
| private suspend fun Card.getAvatarDataOrNull(): Pair<String?, String?> { | ||
| val url = avatarUrl ?: return null to null | ||
|
|
||
| return runCatching { | ||
| val request = Request.Builder().url(url).build() | ||
|
|
||
| HttpClient.okHttpClient.newCall(request).await().use { response -> | ||
| val body = response.body | ||
| if (!response.isSuccessful) return@runCatching null to null | ||
|
|
||
| val contentLength = body.contentLength() | ||
| if (contentLength > MAX_AVATAR_SIZE || contentLength == (-1).toLong()) return@runCatching null to null | ||
|
|
||
| val mimeType = body.contentType()?.subtype?.uppercase() | ||
| val bytes = body.bytes() | ||
|
|
||
| if (bytes.size > MAX_AVATAR_SIZE) return@runCatching null to null | ||
|
|
||
| val base64 = Base64.encodeToString(bytes, Base64.NO_WRAP) | ||
|
tevincent marked this conversation as resolved.
|
||
|
|
||
| base64 to mimeType | ||
| } | ||
| } | ||
| .cancellable() | ||
| .getOrDefault(null to null) | ||
| } | ||
|
|
||
| suspend fun Activity.shareContactCard(card: Card) { | ||
| val file = card.createShareFile(this) | ||
| val authority = "${applicationContext.packageName}.core.contactcard.provider" | ||
| val uri = FileProvider.getUriForFile(this, authority, file) | ||
| val intent = Intent().apply { | ||
| action = Intent.ACTION_SEND | ||
| type = "text/vcard" | ||
| putExtra(Intent.EXTRA_STREAM, uri) | ||
| addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) | ||
| } | ||
|
|
||
| startActivity(Intent.createChooser(intent, getString(R.string.contactCardShareChooserTitle))) | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the whole file changed ?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just format it and add qrose