Skip to content

Commit 7c473ac

Browse files
AndyScherzingermahibi
authored andcommitted
style: Migrate user status dialog to ModalBottomSheet Composable
AI-assistant: Copilot 1.0.10 (Claude Sonnet 4.6) Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
1 parent 0486176 commit 7c473ac

17 files changed

Lines changed: 1351 additions & 1390 deletions

app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import com.nextcloud.talk.models.json.participants.TalkBanOverall
2222
import com.nextcloud.talk.models.json.profile.ProfileOverall
2323
import com.nextcloud.talk.models.json.reactions.ReactionsOverall
2424
import com.nextcloud.talk.models.json.status.StatusOverall
25+
import com.nextcloud.talk.models.json.status.predefined.PredefinedStatusOverall
2526
import com.nextcloud.talk.models.json.testNotification.TestNotificationOverall
2627
import com.nextcloud.talk.models.json.threads.ThreadOverall
2728
import com.nextcloud.talk.models.json.threads.ThreadsOverall
@@ -333,6 +334,48 @@ interface NcApiCoroutines {
333334
@GET
334335
suspend fun status(@Header("Authorization") authorization: String, @Url url: String): StatusOverall
335336

337+
@FormUrlEncoded
338+
@PUT
339+
suspend fun setStatusType(
340+
@Header("Authorization") authorization: String,
341+
@Url url: String,
342+
@Field("statusType") statusType: String
343+
): GenericOverall
344+
345+
@GET
346+
suspend fun getPredefinedStatuses(
347+
@Header("Authorization") authorization: String,
348+
@Url url: String
349+
): PredefinedStatusOverall
350+
351+
@GET
352+
suspend fun backupStatus(@Header("Authorization") authorization: String, @Url url: String): StatusOverall
353+
354+
@DELETE
355+
suspend fun statusDeleteMessage(@Header("Authorization") authorization: String, @Url url: String): GenericOverall
356+
357+
@FormUrlEncoded
358+
@PUT
359+
suspend fun setPredefinedStatusMessage(
360+
@Header("Authorization") authorization: String,
361+
@Url url: String,
362+
@Field("messageId") messageId: String,
363+
@Field("clearAt") clearAt: Long?
364+
): GenericOverall
365+
366+
@FormUrlEncoded
367+
@PUT
368+
suspend fun setCustomStatusMessage(
369+
@Header("Authorization") authorization: String,
370+
@Url url: String,
371+
@Field("statusIcon") statusIcon: String?,
372+
@Field("message") message: String,
373+
@Field("clearAt") clearAt: Long?
374+
): GenericOverall
375+
376+
@DELETE
377+
suspend fun revertStatus(@Header("Authorization") authorization: String, @Url url: String): GenericOverall
378+
336379
@FormUrlEncoded
337380
@POST
338381
suspend fun pinMessage(

app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogCompose.kt renamed to app/src/main/java/com/nextcloud/talk/chooseaccount/ChooseAccountDialogCompose.kt

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/*
22
* Nextcloud Talk - Android Client
33
*
4-
* SPDX-FileCopyrightText: 2025 Sowjanya Kota <sowjanya.kch@gmail.com>
4+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
55
* SPDX-License-Identifier: GPL-3.0-or-later
66
*/
77

8-
package com.nextcloud.talk.ui.dialog
8+
package com.nextcloud.talk.chooseaccount
99

1010
import android.app.Activity
1111
import android.content.Context
@@ -42,7 +42,6 @@ import androidx.compose.material3.TextButton
4242
import androidx.compose.runtime.Composable
4343
import androidx.compose.runtime.LaunchedEffect
4444
import androidx.compose.runtime.MutableState
45-
import androidx.compose.runtime.collectAsState
4645
import androidx.compose.runtime.getValue
4746
import androidx.compose.runtime.mutableStateListOf
4847
import androidx.compose.runtime.mutableStateOf
@@ -64,7 +63,7 @@ import androidx.compose.ui.unit.dp
6463
import androidx.compose.ui.viewinterop.AndroidView
6564
import androidx.compose.ui.window.Dialog
6665
import androidx.core.net.toUri
67-
import androidx.fragment.app.FragmentActivity
66+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
6867
import autodagger.AutoInjector
6968
import coil.compose.AsyncImage
7069
import com.nextcloud.android.common.core.utils.ecosystem.EcosystemApp
@@ -74,14 +73,18 @@ import com.nextcloud.talk.R
7473
import com.nextcloud.talk.account.ServerSelectionActivity
7574
import com.nextcloud.talk.account.data.model.AccountItem
7675
import com.nextcloud.talk.application.NextcloudTalkApplication
77-
import com.nextcloud.talk.chooseaccount.StatusUiState
78-
import com.nextcloud.talk.chooseaccount.StatusViewModel
76+
import com.nextcloud.talk.chooseaccount.ui.OnlineStatusModalBottomSheet
77+
import com.nextcloud.talk.chooseaccount.ui.StatusMessageModalBottomSheet
78+
import com.nextcloud.talk.chooseaccount.viewmodel.StatusMessageViewModel
79+
import com.nextcloud.talk.chooseaccount.viewmodel.StatusUiState
80+
import com.nextcloud.talk.chooseaccount.viewmodel.StatusViewModel
7981
import com.nextcloud.talk.contacts.loadImage
8082
import com.nextcloud.talk.conversationlist.ConversationsListActivity
8183
import com.nextcloud.talk.data.network.NetworkMonitor
8284
import com.nextcloud.talk.data.user.model.User
8385
import com.nextcloud.talk.invitation.viewmodels.InvitationsViewModel
8486
import com.nextcloud.talk.models.json.status.Status
87+
import com.nextcloud.talk.models.json.status.StatusType
8588
import com.nextcloud.talk.settings.SettingsActivity
8689
import com.nextcloud.talk.ui.StatusDrawable
8790
import com.nextcloud.talk.ui.theme.ViewThemeUtils
@@ -118,6 +121,9 @@ class ChooseAccountDialogCompose {
118121
@Inject
119122
lateinit var statusViewModel: StatusViewModel
120123

124+
@Inject
125+
lateinit var statusMessageViewModel: StatusMessageViewModel
126+
121127
@Inject
122128
lateinit var networkMonitor: NetworkMonitor
123129

@@ -131,10 +137,12 @@ class ChooseAccountDialogCompose {
131137
if (shouldDismiss.value) return
132138
val colorScheme = viewThemeUtils.getColorScheme(activity)
133139
val status = remember { mutableStateOf<Status?>(null) }
140+
val showOnlineStatusSheet = remember { mutableStateOf(false) }
141+
val showStatusMessageSheet = remember { mutableStateOf(false) }
134142
val context = LocalContext.current
135-
val statusViewState by statusViewModel.statusViewState.collectAsState()
136-
val invitationsState by invitationsViewModel.getInvitationsViewState.collectAsState()
137-
val isOnline by networkMonitor.isOnline.collectAsState()
143+
val statusViewState by statusViewModel.statusViewState.collectAsStateWithLifecycle()
144+
val invitationsState by invitationsViewModel.getInvitationsViewState.collectAsStateWithLifecycle()
145+
val isOnline by networkMonitor.isOnline.collectAsStateWithLifecycle()
138146
val currentUser = currentUserProvider.currentUser.blockingGet()!!
139147
val isStatusAvailable = CapabilitiesUtil.isUserStatusAvailable(currentUser)
140148
ecosystemManager = EcosystemManager(activity)
@@ -166,12 +174,11 @@ class ChooseAccountDialogCompose {
166174
accountItems = userItems,
167175
onCurrentUserClick = { shouldDismiss.value = true },
168176
onSetOnlineStatusClick = {
169-
shouldDismiss.value = true
170-
openSetOnlineStatusFragment(status.value, activity)
177+
showOnlineStatusSheet.value = true
171178
},
172179
onSetStatusMessageClick = {
173-
shouldDismiss.value = true
174-
openSetStatusMessageFragment(status.value, activity)
180+
statusMessageViewModel.resetDismissed()
181+
showStatusMessageSheet.value = true
175182
},
176183
onAddAccountClick = {
177184
shouldDismiss.value = true
@@ -202,6 +209,28 @@ class ChooseAccountDialogCompose {
202209
showEcosystem = showEcosystem,
203210
context = context
204211
)
212+
if (showOnlineStatusSheet.value) {
213+
val currentStatusType = StatusType.entries.firstOrNull { it.string == status.value?.status }
214+
OnlineStatusModalBottomSheet(
215+
currentStatusType = currentStatusType,
216+
onStatusSelected = { statusType ->
217+
statusViewModel.setStatusType(statusType)
218+
},
219+
onDismiss = { showOnlineStatusSheet.value = false }
220+
)
221+
}
222+
if (showStatusMessageSheet.value) {
223+
status.value?.let { currentStatus ->
224+
StatusMessageModalBottomSheet(
225+
currentStatus = currentStatus,
226+
viewModel = statusMessageViewModel,
227+
onDismiss = {
228+
showStatusMessageSheet.value = false
229+
statusViewModel.getStatus()
230+
}
231+
)
232+
}
233+
}
205234
}
206235
}
207236

@@ -229,22 +258,6 @@ class ChooseAccountDialogCompose {
229258
}
230259
}
231260

232-
private fun openSetOnlineStatusFragment(status: Status?, activity: Activity) {
233-
val fragmentActivity = activity as FragmentActivity
234-
status?.let {
235-
val setStatusDialog = OnlineStatusBottomDialogFragment.newInstance(it)
236-
setStatusDialog.show(fragmentActivity.supportFragmentManager, "fragment_set_status")
237-
} ?: Log.w(TAG, "status was null")
238-
}
239-
240-
private fun openSetStatusMessageFragment(status: Status?, activity: Activity) {
241-
val fragmentActivity = activity as FragmentActivity
242-
status?.let {
243-
val setStatusDialog = StatusMessageBottomDialogFragment.newInstance(it)
244-
setStatusDialog.show(fragmentActivity.supportFragmentManager, "fragment_set_status")
245-
} ?: Log.w(TAG, "status was null")
246-
}
247-
248261
private fun addAccount(activity: Activity) {
249262
val intent = Intent(activity, ServerSelectionActivity::class.java)
250263
intent.putExtra(BundleKeys.ADD_ADDITIONAL_ACCOUNT, true)

app/src/main/java/com/nextcloud/talk/chooseaccount/StatusRepository.kt

Lines changed: 0 additions & 14 deletions
This file was deleted.

app/src/main/java/com/nextcloud/talk/chooseaccount/StatusRepositoryImplementation.kt

Lines changed: 0 additions & 21 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Nextcloud Talk - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: GPL-3.0-or-later
6+
*/
7+
8+
package com.nextcloud.talk.chooseaccount.data
9+
10+
import com.nextcloud.talk.models.json.generic.GenericOverall
11+
import com.nextcloud.talk.models.json.status.StatusOverall
12+
import com.nextcloud.talk.models.json.status.predefined.PredefinedStatus
13+
14+
interface StatusRepository {
15+
suspend fun setStatus(credentials: String, url: String): StatusOverall
16+
suspend fun setStatusType(credentials: String, url: String, statusType: String): GenericOverall
17+
suspend fun getPredefinedStatuses(credentials: String, url: String): List<PredefinedStatus>
18+
suspend fun getBackupStatus(credentials: String, url: String): StatusOverall
19+
suspend fun clearStatusMessage(credentials: String, url: String): GenericOverall
20+
suspend fun setPredefinedStatusMessage(
21+
credentials: String,
22+
url: String,
23+
messageId: String,
24+
clearAt: Long?
25+
): GenericOverall
26+
suspend fun setCustomStatusMessage(
27+
credentials: String,
28+
url: String,
29+
statusIcon: String?,
30+
message: String,
31+
clearAt: Long?
32+
): GenericOverall
33+
suspend fun revertStatus(credentials: String, url: String): GenericOverall
34+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Nextcloud Talk - Android Client
3+
*
4+
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
5+
* SPDX-License-Identifier: GPL-3.0-or-later
6+
*/
7+
8+
package com.nextcloud.talk.chooseaccount.data
9+
10+
import com.nextcloud.talk.api.NcApiCoroutines
11+
import com.nextcloud.talk.models.json.generic.GenericOverall
12+
import com.nextcloud.talk.models.json.status.StatusOverall
13+
import com.nextcloud.talk.models.json.status.predefined.PredefinedStatus
14+
import javax.inject.Inject
15+
16+
class StatusRepositoryImplementation @Inject constructor(private val ncApiCoroutines: NcApiCoroutines) :
17+
StatusRepository {
18+
19+
override suspend fun setStatus(credentials: String, url: String): StatusOverall =
20+
ncApiCoroutines.status(credentials, url)
21+
22+
override suspend fun setStatusType(credentials: String, url: String, statusType: String): GenericOverall =
23+
ncApiCoroutines.setStatusType(credentials, url, statusType)
24+
25+
override suspend fun getPredefinedStatuses(credentials: String, url: String): List<PredefinedStatus> =
26+
ncApiCoroutines.getPredefinedStatuses(credentials, url).ocs?.data.orEmpty()
27+
28+
override suspend fun getBackupStatus(credentials: String, url: String): StatusOverall =
29+
ncApiCoroutines.backupStatus(credentials, url)
30+
31+
override suspend fun clearStatusMessage(credentials: String, url: String): GenericOverall =
32+
ncApiCoroutines.statusDeleteMessage(credentials, url)
33+
34+
override suspend fun setPredefinedStatusMessage(
35+
credentials: String,
36+
url: String,
37+
messageId: String,
38+
clearAt: Long?
39+
): GenericOverall = ncApiCoroutines.setPredefinedStatusMessage(credentials, url, messageId, clearAt)
40+
41+
override suspend fun setCustomStatusMessage(
42+
credentials: String,
43+
url: String,
44+
statusIcon: String?,
45+
message: String,
46+
clearAt: Long?
47+
): GenericOverall = ncApiCoroutines.setCustomStatusMessage(credentials, url, statusIcon, message, clearAt)
48+
49+
override suspend fun revertStatus(credentials: String, url: String): GenericOverall =
50+
ncApiCoroutines.revertStatus(credentials, url)
51+
}

0 commit comments

Comments
 (0)