parent
c0af196da7
commit
828f7bc420
|
|
@ -37,6 +37,9 @@
|
|||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewDeviceShouldUseNewSpec" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PreviewDimensionRespectsLimit" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
|
|
|
|||
|
|
@ -476,7 +476,7 @@ fun ChatRouterScreen(
|
|||
}
|
||||
|
||||
if (showStatusSheet) {
|
||||
val statusSheetState = rememberModalBottomSheetState()
|
||||
val statusSheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
|
||||
|
||||
ModalBottomSheet(
|
||||
sheetState = statusSheetState,
|
||||
|
|
|
|||
|
|
@ -1,24 +1,45 @@
|
|||
package chat.revolt.sheets
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.text.input.TextFieldLineLimits
|
||||
import androidx.compose.foundation.text.input.rememberTextFieldState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Edit
|
||||
import androidx.compose.material.icons.filled.Settings
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.revolt.R
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.routes.user.patchSelf
|
||||
import chat.revolt.api.schemas.User
|
||||
import chat.revolt.components.generic.SheetButton
|
||||
import chat.revolt.components.generic.asApiName
|
||||
import chat.revolt.components.generic.presenceFromStatus
|
||||
|
|
@ -26,18 +47,141 @@ import chat.revolt.components.screens.settings.UserOverview
|
|||
import chat.revolt.components.settings.profile.StatusPicker
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun StatusTextEditDialog(
|
||||
selfUser: User,
|
||||
initialStatus: String,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val fieldState = rememberTextFieldState(initialStatus)
|
||||
var errorText by remember { mutableStateOf<String?>(null) }
|
||||
var isConfirmEnabled by remember { mutableStateOf(false) }
|
||||
val context = LocalContext.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
LaunchedEffect(fieldState.text) {
|
||||
errorText = null
|
||||
isConfirmEnabled = fieldState.text.length <= 128
|
||||
}
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.status_text)
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.status_text_explainer)
|
||||
)
|
||||
TextField(
|
||||
state = fieldState,
|
||||
placeholder = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.status_text_placeholder),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
|
||||
)
|
||||
)
|
||||
},
|
||||
isError = errorText != null,
|
||||
supportingText = {
|
||||
errorText?.let {
|
||||
Text(
|
||||
text = it,
|
||||
color = MaterialTheme.colorScheme.error
|
||||
)
|
||||
}
|
||||
},
|
||||
lineLimits = TextFieldLineLimits.SingleLine
|
||||
)
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
enabled = isConfirmEnabled,
|
||||
onClick = {
|
||||
errorText = null
|
||||
if (fieldState.text.length > 128) {
|
||||
errorText = context.getString(R.string.status_text_error_too_long, 128)
|
||||
} else {
|
||||
if (fieldState.text == initialStatus) {
|
||||
onDismiss()
|
||||
return@TextButton
|
||||
} else if (fieldState.text.isBlank()) {
|
||||
if (selfUser.status?.text == null) {
|
||||
onDismiss()
|
||||
return@TextButton
|
||||
}
|
||||
scope.launch {
|
||||
try {
|
||||
patchSelf(remove = listOf("StatusText"))
|
||||
onDismiss()
|
||||
} catch (e: Exception) {
|
||||
Log.e("StatusTextEditDialog", "Failed to remove status text", e)
|
||||
errorText = context.getString(R.string.status_text_error_other)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scope.launch {
|
||||
try {
|
||||
patchSelf(
|
||||
status = selfUser.status?.copy(
|
||||
text = fieldState.text.toString().trim()
|
||||
)
|
||||
)
|
||||
onDismiss()
|
||||
} catch (e: Exception) {
|
||||
Log.e("StatusTextEditDialog", "Failed to update status text", e)
|
||||
errorText = context.getString(R.string.status_text_error_other)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.ok)
|
||||
)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
onClick = onDismiss
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.cancel)
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun StatusSheet(onBeforeNavigation: () -> Unit, onGoSettings: () -> Unit) {
|
||||
val selfUser = RevoltAPI.userCache[RevoltAPI.selfId]!!
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
var showStatusEditDialog by remember { mutableStateOf(false) }
|
||||
|
||||
if (showStatusEditDialog) {
|
||||
StatusTextEditDialog(
|
||||
selfUser = selfUser,
|
||||
initialStatus = selfUser.status?.text ?: "",
|
||||
onDismiss = { showStatusEditDialog = false }
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp, vertical = 8.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
UserOverview(selfUser)
|
||||
UserOverview(selfUser, internalPadding = false)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
|
|
@ -51,7 +195,41 @@ fun StatusSheet(onBeforeNavigation: () -> Unit, onGoSettings: () -> Unit) {
|
|||
}
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.padding(vertical = 8.dp)
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
.clickable {
|
||||
showStatusEditDialog = true
|
||||
}
|
||||
.background(MaterialTheme.colorScheme.surfaceContainerHigh)
|
||||
) {
|
||||
Text(
|
||||
text = selfUser.status?.text ?: stringResource(id = R.string.status_text_none),
|
||||
style = MaterialTheme.typography.bodyMedium.copy(
|
||||
color = if (selfUser.status?.text == null) {
|
||||
MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
|
||||
} else {
|
||||
MaterialTheme.colorScheme.onSurface
|
||||
}
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(start = 16.dp)
|
||||
)
|
||||
|
||||
Icon(
|
||||
imageVector = Icons.Default.Edit,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.padding(16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SheetButton(
|
||||
|
|
|
|||
|
|
@ -250,6 +250,12 @@
|
|||
<string name="status_offline">Offline</string>
|
||||
<string name="status_invisible">Invisible</string>
|
||||
<string name="status_invisible_explainer">You will be able to use Revolt as usual, but you will not appear as online to other people.</string>
|
||||
<string name="status_text_none">What\'s up?</string>
|
||||
<string name="status_text">Status text</string>
|
||||
<string name="status_text_explainer">Your status text will be visible to everyone. Keep it short and sweet.</string>
|
||||
<string name="status_text_placeholder">Tell the world what you\'re up to</string>
|
||||
<string name="status_text_error_too_long">Status text is too long. Try to keep it under %1$d characters.</string>
|
||||
<string name="status_text_error_other">An error occurred while updating your status text. Please try again later.</string>
|
||||
|
||||
<string name="no_connection">No connection</string>
|
||||
<string name="no_connection_message">You are not connected to the internet. Please check your connection and try again.</string>
|
||||
|
|
|
|||
Loading…
Reference in New Issue