Skip to content

Commit 301dbb7

Browse files
authored
feat(apps): new flows for toggling apps in conversations (WPB-21442) (#4402)
1 parent 9c0d72c commit 301dbb7

File tree

50 files changed

+2018
-693
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2018
-693
lines changed

app/src/main/kotlin/com/wire/android/di/accountScoped/ConversationModule.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import com.wire.kalium.logic.feature.conversation.UpdateConversationMemberRoleUs
5959
import com.wire.kalium.logic.feature.conversation.UpdateConversationMutedStatusUseCase
6060
import com.wire.kalium.logic.feature.conversation.UpdateConversationReadDateUseCase
6161
import com.wire.kalium.logic.feature.conversation.UpdateConversationReceiptModeUseCase
62+
import com.wire.kalium.logic.feature.conversation.apps.ChangeAccessForAppsInConversationUseCase
6263
import com.wire.kalium.logic.feature.conversation.createconversation.CreateChannelUseCase
6364
import com.wire.kalium.logic.feature.conversation.createconversation.CreateRegularGroupUseCase
6465
import com.wire.kalium.logic.feature.conversation.delete.MarkConversationAsDeletedLocallyUseCase
@@ -385,4 +386,11 @@ class ConversationModule {
385386
@KaliumCoreLogic coreLogic: CoreLogic,
386387
@CurrentAccount currentAccount: UserId
387388
): FetchConversationUseCase = coreLogic.getSessionScope(currentAccount).fetchConversationUseCase
389+
390+
@ViewModelScoped
391+
@Provides
392+
fun provideChangeAccessForAppsInConversationUseCase(
393+
conversationScope: ConversationScope
394+
): ChangeAccessForAppsInConversationUseCase =
395+
conversationScope.changeAccessForAppsInConversation
388396
}

app/src/main/kotlin/com/wire/android/mapper/SystemMessageContentMapper.kt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,29 @@ class SystemMessageContentMapper @Inject constructor(
7777
is MessageContent.NewConversationWithCellMessage -> UIMessageContent.SystemMessage.NewConversationWithCellStarted
7878
is MessageContent.NewConversationWithCellSelfDeleteDisabledMessage ->
7979
UIMessageContent.SystemMessage.NewConversationWithCellSelfDeleteDisabled
80+
81+
is MessageContent.ConversationAppsEnabledChanged -> mapConversationConversationAppsAccessChanged(
82+
message.senderUserId,
83+
content,
84+
members
85+
)
86+
}
87+
88+
private fun mapConversationConversationAppsAccessChanged(
89+
senderUserId: UserId,
90+
content: MessageContent.ConversationAppsEnabledChanged,
91+
members: List<User>
92+
): UIMessageContent.SystemMessage {
93+
val sender = members.findUser(userId = senderUserId)
94+
val authorName = mapMemberName(
95+
user = sender,
96+
type = SelfNameType.ResourceTitleCase
97+
)
98+
return UIMessageContent.SystemMessage.ConversationAppsEnabledChanged(
99+
author = authorName,
100+
isAuthorSelfUser = sender is SelfUser,
101+
isAccessEnabled = content.isEnabled
102+
)
80103
}
81104

82105
private fun mapConversationCreated(senderUserId: UserId, date: Instant, userList: List<User>): UIMessageContent.SystemMessage {
@@ -252,7 +275,7 @@ class SystemMessageContentMapper @Inject constructor(
252275
FailedToAdd.Type.LegalHold -> UIMessageContent.SystemMessage.MemberFailedToAdd.Type.LegalHold
253276
FailedToAdd.Type.Unknown -> UIMessageContent.SystemMessage.MemberFailedToAdd.Type.Unknown
254277
}
255-
)
278+
)
256279

257280
is MemberChange.FederationRemoved -> UIMessageContent.SystemMessage.FederationMemberRemoved(
258281
memberNames = memberNameList
@@ -289,6 +312,7 @@ class SystemMessageContentMapper @Inject constructor(
289312
is OtherUser -> user.name?.let {
290313
UIText.DynamicString(it)
291314
} ?: UIText.StringResource(messageResourceProvider.memberNameDeleted)
315+
292316
is SelfUser -> when (type) {
293317
SelfNameType.ResourceLowercase -> UIText.StringResource(messageResourceProvider.memberNameYouLowercase)
294318
SelfNameType.ResourceTitleCase -> UIText.StringResource(messageResourceProvider.memberNameYouTitlecase)

app/src/main/kotlin/com/wire/android/navigation/TabletStyleHelper.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,11 @@ import com.wire.android.ui.destinations.NewConversationFolderScreenDestination
3737
import com.wire.android.ui.destinations.OtherUserProfileScreenDestination
3838
import com.wire.android.ui.destinations.SelfUserProfileScreenDestination
3939
import com.wire.android.ui.destinations.ServiceDetailsScreenDestination
40+
import com.wire.android.ui.destinations.UpdateAppsAccessScreenDestination
4041
import com.wire.android.ui.theme.isTablet
4142

43+
// Todo(docs): Add ADR about this change introduced in navigation styles for tablets, which requires
44+
// adjusting navigation styles for certain destinations when on tablets when using DestinationStyle.Runtime
4245
@Suppress("CyclomaticComplexMethod")
4346
@Composable
4447
fun AdjustDestinationStylesForTablets() {
@@ -53,6 +56,7 @@ fun AdjustDestinationStylesForTablets() {
5356
GroupConversationDetailsScreenDestination.style = if (isTablet) DialogNavigation else PopUpNavigationAnimation
5457
EditConversationNameScreenDestination.style = if (isTablet) DialogNavigation else SlideNavigationAnimation
5558
EditGuestAccessScreenDestination.style = if (isTablet) DialogNavigation else SlideNavigationAnimation
59+
UpdateAppsAccessScreenDestination.style = if (isTablet) DialogNavigation else SlideNavigationAnimation
5660
ChannelAccessOnUpdateScreenDestination.style = if (isTablet) DialogNavigation else SlideNavigationAnimation
5761
EditSelfDeletingMessagesScreenDestination.style = if (isTablet) DialogNavigation else SlideNavigationAnimation
5862
ConversationFoldersScreenDestination.style = if (isTablet) DialogNavigation else SlideNavigationAnimation
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Wire
3+
* Copyright (C) 2025 Wire Swiss GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/.
17+
*/
18+
package com.wire.android.ui.common.upgradetoapps
19+
20+
import androidx.compose.foundation.layout.padding
21+
import androidx.compose.material.Icon
22+
import androidx.compose.material3.MaterialTheme
23+
import androidx.compose.runtime.Composable
24+
import androidx.compose.ui.Modifier
25+
import androidx.compose.ui.res.painterResource
26+
import androidx.compose.ui.res.stringResource
27+
import com.wire.android.R
28+
import com.wire.android.ui.common.card.WireOutlinedCard
29+
import com.wire.android.ui.common.colorsScheme
30+
import com.wire.android.ui.theme.wireDimensions
31+
32+
@Composable
33+
fun UpgradeToGetAppsBanner(
34+
modifier: Modifier = Modifier
35+
) {
36+
WireOutlinedCard(
37+
title = stringResource(R.string.apps_upgrade_teams_for_apps_banner_title),
38+
textContent = stringResource(R.string.apps_upgrade_teams_for_apps_banner_content),
39+
trailingIcon = {
40+
Icon(
41+
painter = painterResource(id = R.drawable.ic_info),
42+
contentDescription = null,
43+
tint = colorsScheme().onBackground
44+
)
45+
},
46+
modifier = modifier.padding(
47+
start = MaterialTheme.wireDimensions.spacing8x,
48+
end = MaterialTheme.wireDimensions.spacing8x,
49+
top = MaterialTheme.wireDimensions.spacing8x,
50+
bottom = MaterialTheme.wireDimensions.spacing16x,
51+
)
52+
)
53+
}

app/src/main/kotlin/com/wire/android/ui/home/conversations/details/GroupConversationDetailsScreen.kt

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,15 @@ import com.wire.android.ui.destinations.OtherUserProfileScreenDestination
103103
import com.wire.android.ui.destinations.SearchConversationMessagesScreenDestination
104104
import com.wire.android.ui.destinations.SelfUserProfileScreenDestination
105105
import com.wire.android.ui.destinations.ServiceDetailsScreenDestination
106+
import com.wire.android.ui.destinations.UpdateAppsAccessScreenDestination
106107
import com.wire.android.ui.home.conversations.details.editguestaccess.EditGuestAccessParams
107108
import com.wire.android.ui.home.conversations.details.options.GroupConversationOptions
108109
import com.wire.android.ui.home.conversations.details.options.GroupConversationOptionsState
109110
import com.wire.android.ui.home.conversations.details.options.LoadingGroupConversation
110111
import com.wire.android.ui.home.conversations.details.participants.GroupConversationParticipants
111112
import com.wire.android.ui.home.conversations.details.participants.GroupConversationParticipantsState
112113
import com.wire.android.ui.home.conversations.details.participants.model.UIParticipant
114+
import com.wire.android.ui.home.conversations.details.updateappsaccess.UpdateAppsAccessParams
113115
import com.wire.android.ui.home.conversations.details.updatechannelaccess.UpdateChannelAccessArgs
114116
import com.wire.android.ui.home.conversations.folder.ConversationFoldersNavArgs
115117
import com.wire.android.ui.home.conversations.folder.ConversationFoldersNavBackArgs
@@ -201,8 +203,9 @@ fun GroupConversationDetailsScreen(
201203
navigator.navigate(
202204
NavigationCommand(
203205
AddMembersSearchScreenDestination(
204-
viewModel.conversationId,
205-
groupOptions.isServicesAllowed
206+
conversationId = viewModel.conversationId,
207+
isConversationAppsEnabled = groupOptions.isAppsAllowed,
208+
isSelfPartOfATeam = groupOptions.isSelfPartOfATeam
206209
)
207210
)
208211
)
@@ -215,13 +218,26 @@ fun GroupConversationDetailsScreen(
215218
viewModel.conversationId,
216219
EditGuestAccessParams(
217220
groupOptions.isGuestAllowed,
218-
groupOptions.isServicesAllowed,
221+
groupOptions.isAppsAllowed,
219222
groupOptions.isUpdatingGuestAllowed
220223
)
221224
)
222225
)
223226
)
224227
},
228+
onAppsAccessItemClicked = {
229+
navigator.navigate(
230+
NavigationCommand(
231+
UpdateAppsAccessScreenDestination(
232+
viewModel.conversationId,
233+
UpdateAppsAccessParams(
234+
isGuestAllowed = groupOptions.isGuestAllowed,
235+
isAppsAllowed = groupOptions.isAppsAllowed
236+
)
237+
)
238+
)
239+
)
240+
},
225241
onChannelAccessItemClicked = {
226242
navigator.navigate(
227243
NavigationCommand(
@@ -327,11 +343,12 @@ private fun GroupConversationDetailsContent(
327343
onProfilePressed: (UIParticipant) -> Unit,
328344
onAddParticipantsPressed: () -> Unit,
329345
onEditGuestAccess: () -> Unit,
346+
onAppsAccessItemClicked: () -> Unit,
330347
onChannelAccessItemClicked: () -> Unit,
331348
onEditSelfDeletingMessages: () -> Unit,
332349
onEditGroupName: () -> Unit,
333350
groupParticipantsState: GroupConversationParticipantsState,
334-
showAllowUserToAddParticipants: () -> (Boolean),
351+
showAllowUserToAddParticipants: () -> Boolean,
335352
isAbandonedOneOnOneConversation: Boolean,
336353
isWireCellEnabled: Boolean,
337354
onSearchConversationMessagesClick: () -> Unit,
@@ -493,6 +510,7 @@ private fun GroupConversationDetailsContent(
493510
GroupConversationDetailsTabItem.OPTIONS -> GroupConversationOptions(
494511
lazyListState = lazyListStates[pageIndex],
495512
onEditGuestAccess = onEditGuestAccess,
513+
onAppsAccessItemClicked = onAppsAccessItemClicked,
496514
onChannelAccessItemClicked = onChannelAccessItemClicked,
497515
onEditSelfDeletingMessages = onEditSelfDeletingMessages,
498516
onEditGroupName = onEditGroupName
@@ -595,25 +613,26 @@ enum class GroupConversationDetailsTabItem(@StringRes val titleResId: Int) : Tab
595613
fun PreviewGroupConversationDetails() {
596614
WireTheme {
597615
GroupConversationDetailsContent(
598-
sheetState = rememberWireModalSheetState(),
599-
initialPageIndex = GroupConversationDetailsTabItem.PARTICIPANTS,
600616
groupConversationOptionsState = GroupConversationOptionsState(ConversationId("v", "d")),
601-
showAllowUserToAddParticipants = { true },
617+
sheetState = rememberWireModalSheetState(),
602618
onBackPressed = {},
603619
onProfilePressed = {},
604620
onAddParticipantsPressed = {},
605-
groupParticipantsState = GroupConversationParticipantsState.PREVIEW,
606-
onEditGroupName = {},
607-
onEditSelfDeletingMessages = {},
608621
onEditGuestAccess = {},
622+
onAppsAccessItemClicked = {},
609623
onChannelAccessItemClicked = {},
610-
onSearchConversationMessagesClick = {},
611-
onConversationMediaClick = {},
624+
onEditSelfDeletingMessages = {},
625+
onEditGroupName = {},
626+
groupParticipantsState = GroupConversationParticipantsState.PREVIEW,
627+
showAllowUserToAddParticipants = { true },
612628
isAbandonedOneOnOneConversation = false,
613629
isWireCellEnabled = false,
630+
onSearchConversationMessagesClick = {},
631+
onConversationMediaClick = {},
614632
onMoveToFolder = {},
615633
onLeftConversation = {},
616634
onDeletedConversation = {},
635+
initialPageIndex = GroupConversationDetailsTabItem.PARTICIPANTS
617636
)
618637
}
619638
}

0 commit comments

Comments
 (0)