Repository navigation
feat: Add organization interface - #679
Conversation
There was a problem hiding this comment.
Pull request overview
Adds organization selection to sent transfers and new uploads, with organization-aware upload handling.
Changes:
- Adds organization switcher UI, avatars, localization, and account-scoped transfer views.
- Propagates organization IDs through upload, finalization, and cleanup.
- Adds required database and MyKSuite dependencies.
Reviewed changes
Copilot reviewed 39 out of 39 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
gradle/libs.versions.toml |
Adds STDatabase dependency alias. |
app/build.gradle.kts |
Adds database and MyKSuite dependencies. |
app/src/main/res/values/strings.xml |
Adds organization label. |
app/src/main/res/values-sv/strings.xml |
Adds Swedish label. |
app/src/main/res/values-pt/strings.xml |
Adds Portuguese label. |
app/src/main/res/values-pl/strings.xml |
Adds Polish label. |
app/src/main/res/values-nl/strings.xml |
Adds Dutch label. |
app/src/main/res/values-nb/strings.xml |
Adds Norwegian label. |
app/src/main/res/values-it/strings.xml |
Adds Italian label. |
app/src/main/res/values-fr/strings.xml |
Adds French label. |
app/src/main/res/values-fi/strings.xml |
Adds Finnish label. |
app/src/main/res/values-es/strings.xml |
Adds Spanish label. |
app/src/main/res/values-el/strings.xml |
Adds Greek label. |
app/src/main/res/values-de/strings.xml |
Adds German label. |
app/src/main/res/values-da/strings.xml |
Adds Danish label. |
app/src/main/java/com/infomaniak/swisstransfer/upload/UploadSessionStarterInterface.kt |
Uses the V2 API transfer model. |
app/src/main/java/com/infomaniak/swisstransfer/upload/UploadSessionManager.kt |
Passes organization ID to cleanup. |
app/src/main/java/com/infomaniak/swisstransfer/upload/TransferUploaderV2.kt |
Finalizes organization uploads. |
app/src/main/java/com/infomaniak/swisstransfer/upload/NewTransferParamsExt.kt |
Maps organization ID into requests. |
app/src/main/java/com/infomaniak/swisstransfer/upload/NewTransferParams.kt |
Stores selected organization ID. |
app/src/main/java/com/infomaniak/swisstransfer/upload/AbandonedTransferV2CleanupWorker.kt |
Preserves organization context during cleanup. |
app/src/main/java/com/infomaniak/swisstransfer/ui/utils/OrganizationAccountExt.kt |
Adds organization avatar and tier helpers. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/pickfiles/PickFilesViewModel.kt |
Captures the selected organization. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/pickfiles/PickFilesScreen.kt |
Adds organization selection to transfer options. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/pickfiles/components/TransferOptionsTypes.kt |
Adds the “Send with” option. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/transfers/TransfersViewModel.kt |
Exposes account-level transfer emptiness. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MyAccountViewModel.kt |
Updates copyright metadata. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MyAccountScreenWrapper.kt |
Refactors argument formatting. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MyAccountScreen.kt |
Refactors parameter and call formatting. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/sent/SentScreen.kt |
Adds organization switching to sent transfers. |
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/received/ReceivedScreen.kt |
Uses account-level empty state. |
app/src/main/java/com/infomaniak/swisstransfer/ui/OnboardingActivity.kt |
Names the login callback argument. |
app/src/main/java/com/infomaniak/swisstransfer/ui/images/icons/Organization.kt |
Adds the organization vector icon. |
app/src/main/java/com/infomaniak/swisstransfer/ui/components/transfer/TransferItemList.kt |
Supports optional list headers. |
app/src/main/java/com/infomaniak/swisstransfer/ui/components/SwissTransferBottomSheet.kt |
Adjusts content spacing. |
app/src/main/java/com/infomaniak/swisstransfer/ui/components/OrganizationSwitcherViewModel.kt |
Manages organization selection state. |
app/src/main/java/com/infomaniak/swisstransfer/ui/components/OrganizationSwitcherBottomSheet.kt |
Adds the organization picker sheet. |
app/src/main/java/com/infomaniak/swisstransfer/ui/components/OrganizationSwitcher.kt |
Adds the organization switcher control. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 40 out of 40 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (4)
gradle/libs.versions.toml:21
- This artifact still resolves through
swisstransfer = "10.1.0", but organization support (includingOrganizationAccount, the newAccountManagermethods, and the updated upload signatures) only exists in the unmerged dependency PR #312. As submitted, Gradle resolves the older release and the newly added imports/calls cannot compile. Publish the dependent changes and update the shared SwissTransfer version before merging this PR.
app/src/main/java/com/infomaniak/swisstransfer/ui/components/OrganizationSwitcherBottomSheet.kt:119 SharpRippleButtonalready applies its ownselectableusing theisSelectedargument. Adding anotherselectablehere while leaving that argument at its defaultfalsecreates conflicting selection semantics, so accessibility services can announce the selected organization as unselected. Pass the state through the component instead of adding a second selectable modifier.
SharpRippleButton(
modifier = Modifier
.height(ORGANIZATION_ITEM_HEIGHT)
.fillMaxWidth()
.selectable(selected = isSelected, onClick = onClick),
onClick = onClick,
) {
app/src/main/java/com/infomaniak/swisstransfer/ui/components/OrganizationSwitcherViewModel.kt:45
- This performs a one-shot organization query only when
currentUserFlowemits. The dependentAccountManager.loadUsersets the current user before asynchronously fetching and inserting organizations, so a fresh login commonly queries an empty cache and this flow never observes the later database update; both switchers then remain hidden. Expose/collect an organization-account database flow (or another signal that emits after refresh) instead of mapping only user changes.
val organizations: StateFlow<List<OrganizationAccount>> = accountManager.currentUserFlow
.map { user -> user?.let { accountManager.organizationAccountsForUser(it.id) } ?: emptyList() }
.stateIn(viewModelScope, SharingStarted.Lazily, initialValue = emptyList())
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/newtransfer/pickfiles/PickFilesViewModel.kt:330
- The selected organization is copied into the upload request, but file validation still calls
pickedFilesIssues()with the globalFileUtils.MAX_FILES_SIZE.OrganizationAccountexposeslimits.transferTotalSize, so selecting an account with a lower quota leaves Send enabled for an oversized transfer and the request only fails after upload-session creation. Make the validation react to the selected organization's limit and use that value in the max-size issue.
private suspend fun extractNewTransferParams() = NewTransferParams(
validityPeriod = selectedValidityPeriodOption.value.apiValue,
authorEmail = if (selectedTransferTypeFlow.value == TransferTypeUi.Mail) transferAuthorEmail.trim() else "",
password = if (selectedPasswordOption.value == PasswordTransferOption.ACTIVATED) transferPassword else NO_PASSWORD,
title = transferTitle,
message = transferMessage,
downloadCountLimit = selectedDownloadLimitOption.value.apiValue,
languageCode = selectedLanguageOption.value.apiValue,
recipientsEmails = if (selectedTransferTypeFlow.value == TransferTypeUi.Mail) validatedRecipientsEmails else emptySet(),
type = selectedTransferTypeFlow.value,
organizationAccountId = accountManager.selectedOrganizationAccount().first()?.id,
There was a problem hiding this comment.
🟡 Changes recommended
The declared KMP version is incompatible with the new APIs, and organization selection has unresolved asynchronous failure and ordering risks.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Review details
Suppressed comments (2)
gradle/libs.versions.toml:21
- This alias still resolves to
swisstransfer = "10.1.0", which predates the linked KMP PR #312. That release has neitherOrganizationAccountnor the new organization-selection and upload method signatures used by this PR, so the app cannot compile against the declared dependencies. Publish/select a KMP version containing #312 and update the shared version before merging.
app/src/main/java/com/infomaniak/swisstransfer/ui/components/OrganizationSwitcherViewModel.kt:47 - This suspend database write is unguarded inside a root
launch, so a persistence failure escapes the ViewModel coroutine instead of being handled and reported. Match the established pattern inTransfersViewModel.kt:59-65: wrap the call withrunCatching { ... }.cancellable()and report failures throughSentryLog.
fun switchToOrganization(organizationAccountId: Long) = viewModelScope.launch(ioDispatcher) {
accountManager.switchToOrganization(organizationAccountId)
}
- Files reviewed: 40/40 changed files
- Comments generated: 1
- Review effort level: Balanced
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
d28b64c to
a935c74
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 40 out of 40 changed files in this pull request and generated no new comments.
Suppressed comments (2)
gradle/libs.versions.toml:21
- The catalog is still pinned to
swisstransfer = "10.1.0", but that release lacks the organization models and the newUploadSessionRequest,AccountManager, andUploadV2ManagerAPIs referenced by this PR. PR #312 is still unreleased (even 10.1.1 predates it), so the declared dependencies cannot compile this code. Publish/select a KMP release containing #312 and update the catalog version before merging.
app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/received/ReceivedScreen.kt:64 accountTransfersAreEmptyis based onhasAccountTransferFlow(), which intentionally counts only sent transfers for the current account. Using it forisFirstTransfermakes the “Make your first transfer!” prompt appear for users who already have received transfers (or transfers under another account). Expose a separate state derived from!hasAnyTransferFlow()for this FAB, while keeping the account-scoped state for the Sent header.
val hasNoTransfers by transfersViewModel.accountTransfersAreEmpty.collectAsStateWithLifecycle()
f24b819 to
3a3076b
Compare
74d0c9a to
c50100f
Compare
c50100f to
83ee814
Compare
fd874e4 to
2d6feeb
Compare
# Conflicts: # app/src/main/java/com/infomaniak/swisstransfer/ui/screen/main/settings/MyAccountScreen.kt # app/src/main/res/values-de/strings.xml
# Conflicts: # Core
aecebd8 to
04a4d96
Compare
|



depends on : Infomaniak/android-core#824
depends on : Infomaniak/multiplatform-SwissTransfer#312