diff --git a/.idea/.name b/.idea/.name index 8a14fc66..9ef16e6b 100644 --- a/.idea/.name +++ b/.idea/.name @@ -1 +1 @@ -Revolt \ No newline at end of file +PEP \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/activities/MainActivity.kt b/app/src/main/java/chat/revolt/activities/MainActivity.kt index 08ad8717..4dcc1474 100644 --- a/app/src/main/java/chat/revolt/activities/MainActivity.kt +++ b/app/src/main/java/chat/revolt/activities/MainActivity.kt @@ -697,7 +697,9 @@ fun AppEntrypoint( onToggleDrawer = {}, useDrawer = false, useBackButton = true, - backToChannelsScreen = {}, + backToChannelsScreen = { + navController.navigate("main") + }, backButtonAction = { navController.popBackStack() }, diff --git a/app/src/main/java/chat/revolt/api/routes/googlesheets/ServerDataRepository.kt b/app/src/main/java/chat/revolt/api/routes/googlesheets/ServerDataRepository.kt index eebcdccc..f4f9bb98 100644 --- a/app/src/main/java/chat/revolt/api/routes/googlesheets/ServerDataRepository.kt +++ b/app/src/main/java/chat/revolt/api/routes/googlesheets/ServerDataRepository.kt @@ -10,7 +10,7 @@ import kotlinx.serialization.Serializable * Repository for fetching server data from a Google Sheet */ class ServerDataRepository { - + /** * Fetches server data from Google Sheets and returns as a Flow * @param sheetUrl The URL of the published Google Sheet (CSV or JSON) @@ -25,6 +25,10 @@ class ServerDataRepository { name = rowData["name"] ?: "", description = rowData["description"] ?: "", inviteCode = rowData["inviteCode"] ?: "", + disabled = when (rowData["disabled"]?.lowercase()) { + "false" -> false + else -> true + }, ) } emit(servers) @@ -41,16 +45,5 @@ data class ServerData( val name: String, val description: String, val inviteCode: String, -) - -/** - * Data class representing a server category - */ -@Serializable -data class ServerCategory( - val id: String, - val name: String, - val description: String, - val iconName: String, - val sortOrder: Int + val disabled: Boolean, ) \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/composables/screens/chat/discover/DiscoverServersList.kt b/app/src/main/java/chat/revolt/composables/screens/chat/discover/DiscoverServersList.kt index 30fc6b98..31ddc3a0 100644 --- a/app/src/main/java/chat/revolt/composables/screens/chat/discover/DiscoverServersList.kt +++ b/app/src/main/java/chat/revolt/composables/screens/chat/discover/DiscoverServersList.kt @@ -1,6 +1,7 @@ package chat.revolt.composables.screens.chat.discover import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -14,6 +15,7 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.Card import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.IconButton @@ -24,6 +26,8 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -32,6 +36,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import chat.revolt.R +import chat.revolt.api.RevoltAPI import chat.revolt.api.routes.googlesheets.ServerData @Composable @@ -107,12 +112,18 @@ fun DiscoverServersList( .weight(1f) ) { items(uiState.servers) { server -> + // Check if the server is already joined + val isJoined = isServerAlreadyJoined(server.id) + ServerItem( server = server, isProcessing = uiState.processingServerId == server.id, onClick = { - if (server.inviteCode.isNotEmpty()) { - // First load server data, dialog will be shown after data is loaded + if (isJoined) { + // If already joined, navigate directly to server channels + onJoinToServerSuccess(server.id) + } else if (server.inviteCode.isNotEmpty()) { + // If not joined, load server data and show invite dialog viewModel.loadServerDataAndShowDialog(server.inviteCode, server.id) } } @@ -127,12 +138,30 @@ fun DiscoverServersList( } } +/** + * Check if the server with the given invite code is already joined + * @param inviteCode The invite code of the server + * @return True if the server is already joined, false otherwise + */ +@Composable +private fun isServerAlreadyJoined(serverId: String): Boolean { + // Check if the server exists in RevoltAPI.serverCache + return RevoltAPI.serverCache.containsKey(serverId) +} + @Composable fun ServerItem( server: ServerData, onClick: () -> Unit, isProcessing: Boolean = false ) { + // Calculate alpha values based on disabled state + val contentAlpha = if (server.disabled) 0.5f else 1.0f + val descriptionAlpha = if (server.disabled) 0.4f else 0.7f + + // Check if the server is already joined + val isJoined = isServerAlreadyJoined(server.id) + Card( modifier = Modifier .fillMaxWidth() @@ -148,7 +177,9 @@ fun ServerItem( Image( painter = painterResource(R.drawable.three_person), contentDescription = "", - colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onBackground) + colorFilter = ColorFilter.tint( + color = MaterialTheme.colorScheme.onBackground.copy(alpha = contentAlpha) + ) ) Spacer(modifier = Modifier.width(12.dp)) @@ -158,6 +189,7 @@ fun ServerItem( Text( text = server.name, style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onBackground.copy(alpha = contentAlpha) ) Spacer(modifier = Modifier.height(4.dp)) @@ -166,7 +198,7 @@ fun ServerItem( text = server.description, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onBackground.copy( - alpha = 0.7f, + alpha = descriptionAlpha, ), maxLines = 2, overflow = TextOverflow.Ellipsis @@ -188,12 +220,34 @@ fun ServerItem( modifier = Modifier .fillMaxSize() ) { - Image( - painter = painterResource(R.drawable.icn_arrow_forward_24dp), - contentDescription = "", - modifier = Modifier - .align(Alignment.Center) - ) + if (isJoined) { + // Show tick icon with green background for joined servers + Box( + modifier = Modifier + .size(24.dp) + .clip(CircleShape) + .background(Color(0xFF4CAF50)) // Green color + .align(Alignment.Center), + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(R.drawable.icn_check_24dp), + contentDescription = "Already joined", + colorFilter = ColorFilter.tint(Color.White) + ) + } + } else { + // Show arrow icon for servers not joined yet + Image( + painter = painterResource(R.drawable.icn_arrow_forward_24dp), + contentDescription = "Join server", + modifier = Modifier + .align(Alignment.Center), + colorFilter = ColorFilter.tint( + color = MaterialTheme.colorScheme.onBackground.copy(alpha = contentAlpha) + ) + ) + } } } } diff --git a/app/src/main/java/chat/revolt/composables/screens/chat/discover/ServerInviteDialog.kt b/app/src/main/java/chat/revolt/composables/screens/chat/discover/ServerInviteDialog.kt index 6b602649..88472408 100644 --- a/app/src/main/java/chat/revolt/composables/screens/chat/discover/ServerInviteDialog.kt +++ b/app/src/main/java/chat/revolt/composables/screens/chat/discover/ServerInviteDialog.kt @@ -3,7 +3,6 @@ package chat.revolt.composables.screens.chat.discover import androidx.compose.foundation.Image import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -16,7 +15,6 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -52,10 +50,9 @@ fun ServerInviteDialog( AlertDialog( onDismissRequest = onDismiss, icon = { - Icon( - painter = painterResource(R.drawable.icn_error_24dp), + Image( + painter = painterResource(R.drawable.link_no_valid_img), contentDescription = null, - tint = MaterialTheme.colorScheme.error ) }, title = { @@ -66,22 +63,26 @@ fun ServerInviteDialog( ) }, text = { - Text( - text = when (error.type) { - "NotFound" -> stringResource(id = R.string.invite_error_invalid_invite) - "Banned" -> stringResource(id = R.string.invite_error_banned) - else -> stringResource(id = R.string.invite_error_unknown) - }, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth() - ) - }, - confirmButton = {}, - dismissButton = { - TextButton(onClick = onDismiss) { - Text(text = stringResource(id = R.string.invite_cancel)) + Column { + Text( + text = when (error.type) { + "NotFound" -> stringResource(id = R.string.invite_error_invalid_invite) + "Banned" -> stringResource(id = R.string.invite_error_banned) + else -> stringResource(id = R.string.invite_error_unknown) + }, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth() + ) + Spacer(Modifier.height(32.dp)) + Button( + onClick = onDismiss, + modifier = Modifier.fillMaxWidth(), + ) { + Text(text = stringResource(id = R.string.spark_early_access_cta)) + } } - } + }, + confirmButton = {} ) return } @@ -196,7 +197,11 @@ fun ServerInviteDialog( .clip(CircleShape) ) } else { - IconPlaceholder(name = invite.userName, modifier = Modifier.size(24.dp).clip(CircleShape), fontSize = 12.sp) + IconPlaceholder( + name = invite.userName, modifier = Modifier + .size(24.dp) + .clip(CircleShape), fontSize = 12.sp + ) } Spacer(modifier = Modifier.width(4.dp)) Text(text = invite.userName, fontWeight = FontWeight.SemiBold) @@ -234,17 +239,6 @@ fun ServerInviteDialog( ) } -@Preview -@Composable -fun ServerInviteDialogPreviewLoading() { - ServerInviteDialog( - isLoading = true, - invite = null, - error = null, - onJoinClick = {}, - onDismiss = {} - ) -} @Preview @Composable diff --git a/app/src/main/res/drawable/icn_check_24dp.xml b/app/src/main/res/drawable/icn_check_24dp.xml index 280f0bd8..c9f56cbf 100644 --- a/app/src/main/res/drawable/icn_check_24dp.xml +++ b/app/src/main/res/drawable/icn_check_24dp.xml @@ -1,10 +1,10 @@ + - - + android:viewportWidth="24" + android:viewportHeight="24"> + + \ No newline at end of file diff --git a/app/src/main/res/drawable/link_no_valid_img.xml b/app/src/main/res/drawable/link_no_valid_img.xml new file mode 100644 index 00000000..ac1fffc5 --- /dev/null +++ b/app/src/main/res/drawable/link_no_valid_img.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9cb5ae53..51939841 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -548,9 +548,9 @@ No Thanks You are already a member of this server. %1$d members - There was an error + Link No Longer Valid No invite code was specified. - Could not find an invite with the specified code. + This link seems invalid or expired. Reach out for a new invite. You are banned from this server. An unknown error occurred. Joining…