Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ package com.nextcloud.talk.activities

import android.app.KeyguardManager
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.provider.ContactsContract
import android.text.TextUtils
import android.util.Log
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
import androidx.core.net.toUri
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
Expand All @@ -39,8 +39,8 @@ import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ClosedInterfaceImpl
import com.nextcloud.talk.utils.DeepLinkHandler
import com.nextcloud.talk.utils.SecurityUtils
import com.nextcloud.talk.utils.UnifiedPushUtils
import com.nextcloud.talk.utils.ShortcutManagerHelper
import com.nextcloud.talk.utils.UnifiedPushUtils
import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.bundle.BundleKeys.KEY_ROOM_TOKEN
import io.reactivex.SingleObserver
Expand Down Expand Up @@ -386,7 +386,7 @@ class MainActivity :
* 3. Current active user as fallback (if server matches)
*/
private fun resolveTargetUser(users: List<User>, deepLinkResult: DeepLinkHandler.DeepLinkResult): User? {
val deepLinkHost = Uri.parse(deepLinkResult.serverUrl).host?.lowercase()
val deepLinkHost = deepLinkResult.serverUrl.toUri().host?.lowercase()
if (deepLinkHost.isNullOrBlank()) {
return currentUserProviderOld.currentUser.blockingGet()
}
Expand All @@ -395,21 +395,21 @@ class MainActivity :
val username = deepLinkResult.username
val exactMatch = if (username != null) {
users.find { user ->
val userHost = user.baseUrl?.let { Uri.parse(it).host?.lowercase() }
val userHost = user.baseUrl?.let { it.toUri().host?.lowercase() }
userHost == deepLinkHost && user.username?.lowercase() == username.lowercase()
}
} else {
null
}

val serverMatch = users.find { user ->
val userHost = user.baseUrl?.let { Uri.parse(it).host?.lowercase() }
val userHost = user.baseUrl?.let { it.toUri().host?.lowercase() }
userHost == deepLinkHost
}

val currentUser = currentUserProviderOld.currentUser.blockingGet()
val currentUserMatch = currentUser?.takeIf {
it.baseUrl?.let { url -> Uri.parse(url).host?.lowercase() } == deepLinkHost
it.baseUrl?.let { url -> url.toUri().host?.lowercase() } == deepLinkHost
}

return exactMatch ?: serverMatch ?: currentUserMatch
Expand Down
252 changes: 95 additions & 157 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import androidx.compose.ui.unit.dp

const val WAVEFORM_THUMB_SIZE = 20
const val WAVEFORM_SIZE = 30
const val MAX_HEIGHT = 100
const val OVERLAP = 0.025

@OptIn(ExperimentalMaterial3Api::class)
Expand Down
196 changes: 196 additions & 0 deletions app/src/main/java/com/nextcloud/talk/ui/ConversationDeleteNotice.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
/*
* Nextcloud Talk - Android Client
*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/

package com.nextcloud.talk.ui

import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.nextcloud.talk.R
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.preview.ComposePreviewUtils

@Composable
fun ConversationDeleteNoticeView(
data: ConversationDeleteNoticeViewData,
viewThemeUtils: ViewThemeUtils,
onDeleteNow: () -> Unit,
onKeep: () -> Unit,
onDismiss: () -> Unit
) {
val context = LocalContext.current
val colorScheme = remember { viewThemeUtils.getColorScheme(context) }
Card(
modifier = Modifier.fillMaxWidth(),
shape = RoundedCornerShape(4.dp),
colors = CardDefaults.cardColors(containerColor = colorScheme.surface),
border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant)
) {
Row(modifier = Modifier.padding(start = 8.dp, end = 0.dp)) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.baseline_info_24),
contentDescription = null,
modifier = Modifier
.padding(top = 8.dp)
.size(24.dp)
)
Spacer(modifier = Modifier.size(8.dp))
Column(
modifier = Modifier
.weight(1f)
.padding(top = 8.dp, bottom = 8.dp)
) {
Text(
text = pluralStringResource(
R.plurals.nc_conversation_auto_delete_info,
data.retentionDays,
data.retentionDays
),
style = MaterialTheme.typography.bodyMedium
)
}
ConversationDeleteNoticeActions(
isModeratorOrOwner = data.isModeratorOrOwner,
onDeleteNow = onDeleteNow,
onKeep = onKeep,
onDismiss = onDismiss
)
}
}
}

@Composable
private fun ConversationDeleteNoticeActions(
isModeratorOrOwner: Boolean,
onDeleteNow: () -> Unit,
onKeep: () -> Unit,
onDismiss: () -> Unit
) {
var expanded by remember { mutableStateOf(false) }
Column {
if (isModeratorOrOwner) {
Box {
IconButton(onClick = { expanded = true }) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_more_vert_24px),
contentDescription = null
)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false }
) {
DropdownMenuItem(
text = { Text(stringResource(R.string.nc_delete_now)) },
onClick = {
expanded = false
onDeleteNow()
}
)
DropdownMenuItem(
text = {
Text(stringResource(R.string.nc_keep))
},
onClick = {
expanded = false
onKeep()
}
)
}
}
} else {
IconButton(onClick = onDismiss) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.ic_baseline_close_24),
contentDescription = stringResource(R.string.nc_common_dismiss)
)
}
}
}
}

data class ConversationDeleteNoticeViewData(val retentionDays: Int, val isModeratorOrOwner: Boolean)

@Preview(name = "Dark Mode", uiMode = android.content.res.Configuration.UI_MODE_NIGHT_YES)
@Composable
fun ConversationDeleteNoticePreviewDark() {
ConversationDeleteNoticePreview()
}

@Preview(name = "R-t-L", locale = "ar")
@Composable
fun ConversationDeleteNoticePreviewRtl() {
ConversationDeleteNoticePreview()
}

@Preview(name = "Light Mode / Read-only")
@Composable
fun ConversationDeleteNoticePreviewReadOnly() {
ConversationDeleteNoticePreview(isModeratorOrOwner = false)
}

@Preview(name = "Dark Mode / Read-only", uiMode = android.content.res.Configuration.UI_MODE_NIGHT_YES)
@Composable
fun ConversationDeleteNoticePreviewDarkReadOnly() {
ConversationDeleteNoticePreview(isModeratorOrOwner = false)
}

@Preview(name = "R-t-L / Read-only", locale = "ar")
@Composable
fun ConversationDeleteNoticePreviewRtlReadOnly() {
ConversationDeleteNoticePreview(isModeratorOrOwner = false)
}

@Suppress("MagicNumber")
@Preview(name = "Light Mode")
@Composable
fun ConversationDeleteNoticePreview(retentionDays: Int = 7, isModeratorOrOwner: Boolean = true) {
val context = LocalContext.current
val previewUtils = ComposePreviewUtils.getInstance(context)
val viewThemeUtils = previewUtils.viewThemeUtils
val colorScheme = viewThemeUtils.getColorScheme(context)

MaterialTheme(colorScheme = colorScheme) {
ConversationDeleteNoticeView(
data = ConversationDeleteNoticeViewData(
retentionDays = retentionDays,
isModeratorOrOwner = isModeratorOrOwner
),
viewThemeUtils = viewThemeUtils,
onDeleteNow = {},
onKeep = {},
onDismiss = {}
)
}
}
Loading
Loading