Skip to content

Commit

Permalink
Merge pull request #63 from stakwork/aa/feature/empty-placeholder
Browse files Browse the repository at this point in the history
Implement empty chat placeholder view
  • Loading branch information
ariel10aguero authored Jan 22, 2025
2 parents 6c63c57 + 6290899 commit 0e26298
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package chat.sphinx.common.state
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import chat.sphinx.common.models.ChatMessage
import chat.sphinx.common.models.DashboardChat
import chat.sphinx.wrapper.dashboard.ChatId

abstract class MessageListData {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import chat.sphinx.wrapper.chat.*
import chat.sphinx.wrapper.contact.Contact
import chat.sphinx.wrapper.contact.getColorKey
import chat.sphinx.wrapper.dashboard.ChatId
import chat.sphinx.wrapper.dashboard.toContactId
import chat.sphinx.wrapper.getMinutesDifferenceWithDateTime
import chat.sphinx.wrapper.isDifferentDayThan
import chat.sphinx.wrapper.lightning.*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ actual fun Dashboard(
horizontalAlignment = Alignment.CenterHorizontally
) {
chatViewModel?.let { chatViewModel ->
MessageListUI(chatViewModel, dashboardViewModel)
MessageListUI(chatViewModel, dashboardViewModel, dashboardChat)
}
}
AttachmentPreview(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,37 +1,60 @@
package chat.sphinx.common.components

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.*
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.filled.Schedule
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.snapshots.SnapshotStateList
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.PathEffect
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.sphinx.common.chatMesssageUI.ChatMessageUI
import chat.sphinx.common.chatMesssageUI.DateSeparator
import chat.sphinx.common.models.ChatMessage
import chat.sphinx.common.models.DashboardChat
import chat.sphinx.common.state.MessageListData
import chat.sphinx.common.state.MessageListState
import chat.sphinx.common.viewmodel.DashboardViewModel
import chat.sphinx.common.viewmodel.chat.ChatViewModel
import chat.sphinx.wrapper.util.getHHMMSSString
import chat.sphinx.wrapper.util.getHHMMString
import chat.sphinx.wrapper.util.getInitials
import chat.sphinx.wrapper.util.toFormattedDate
import kotlinx.coroutines.launch
import theme.md_theme_dark_onBackground


@Composable
fun MessageListUI(
chatViewModel: ChatViewModel,
dashboardViewModel: DashboardViewModel
dashboardViewModel: DashboardViewModel,
dashboardChat: DashboardChat?
) {
chatViewModel.screenInit()
val isInactiveConversation = dashboardChat is DashboardChat.Inactive.Conversation

Box {
when (val messageListData = MessageListState.screenState()) {
is MessageListData.EmptyMessageListData -> {
Box(
modifier = Modifier.fillMaxSize()
)
ChatEmptyScreen(isInactiveConversation, dashboardChat)
}
is MessageListData.PopulatedMessageListData -> {
val listState = remember(messageListData.chatId) { LazyListState() }
Expand All @@ -41,9 +64,7 @@ fun MessageListUI(
items.addAll(chatMessages)

if (chatMessages.isEmpty()) {
Box(
modifier = Modifier.fillMaxSize()
)
ChatEmptyScreen(isInactiveConversation, dashboardChat)
} else {
ChatMessagesList(
items,
Expand All @@ -69,6 +90,139 @@ fun MessageListUI(
}
}

@Composable
fun ChatEmptyScreen(isInactiveConversation: Boolean, dashboardChat: DashboardChat?){
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.TopCenter
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Top,
modifier = Modifier.padding(top = 32.dp)
) {
// Profile Picture with PhotoUrl
Box(
modifier = Modifier
.size(80.dp)
.padding(bottom = 16.dp),
contentAlignment = Alignment.Center
) {
if (isInactiveConversation) {
Canvas(
modifier = Modifier.fillMaxSize(),
onDraw = {
drawCircle(
color = md_theme_dark_onBackground,
radius = size.minDimension / 2,
style = Stroke(
width = 4f,
pathEffect = PathEffect.dashPathEffect(floatArrayOf(8f, 4f), 0f)
)
)
}
)
PhotoUrlImage(
dashboardChat?.photoUrl,
modifier = Modifier
.fillMaxSize()
.clip(CircleShape),
firstNameLetter = (dashboardChat?.chatName ?: "Unknown Chat").getInitials(),
color = dashboardChat?.color?.let { Color(it) },
fontSize = 16
)

// Icon beside the profile picture
Icon(
Icons.Filled.Schedule,
contentDescription = null,
modifier = Modifier
.size(20.dp)
.align(Alignment.TopEnd)
.offset(x = (-1).dp, y = 50.dp),
tint = androidx.compose.material3.MaterialTheme.colorScheme.onBackground
)
} else {
PhotoUrlImage(
dashboardChat?.photoUrl,
modifier = Modifier
.size(64.dp)
.clip(CircleShape),
firstNameLetter = (dashboardChat?.chatName ?: "Unknown Chat").getInitials(),
color = dashboardChat?.color?.let { Color(it) },
fontSize = 16
)
}
}

Row {
// Chat Name
Text(
text = dashboardChat?.chatName ?: "Unknown",
fontSize = 15.sp,
maxLines = 1,
color = androidx.compose.material3.MaterialTheme.colorScheme.tertiary,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.padding(bottom = 4.dp)
)

if (!isInactiveConversation) {

Spacer(Modifier.width(8.dp))

androidx.compose.material.Icon(
Icons.Default.Lock,
contentDescription = "Lock",
tint = MaterialTheme.colorScheme.onBackground,
modifier = Modifier.padding(top = 2.dp).size(18.dp)
)
}

}

val descriptionText = if (isInactiveConversation) {
"Invited on ${dashboardChat?.sortBy?.toFormattedDate()}"
} else {
"Messages and calls are secured\n with end-to-end encryption"
}

// Description Text
Text(
text = descriptionText,
fontSize = 13.sp,
fontFamily = FontFamily.SansSerif,
fontWeight = FontWeight.W400,
maxLines = 2,
overflow = TextOverflow.Ellipsis,
color = androidx.compose.material3.MaterialTheme.colorScheme.onBackground,
modifier = Modifier.padding(bottom = 8.dp)
)
}


if (isInactiveConversation) {
Box(
modifier = Modifier
.fillMaxSize()
.padding(bottom = 32.dp),
contentAlignment = Alignment.BottomCenter
) {
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Your chat will be enabled\nas soon as your contact goes online",
fontSize = 14.sp,
textAlign = TextAlign.Center,
color = androidx.compose.material3.MaterialTheme.colorScheme.onBackground
)
}
}
}
}

}

@Composable
fun ChatMessagesList(
items: SnapshotStateList<ChatMessage>,
Expand Down
2 changes: 1 addition & 1 deletion sphinx-kotlin-core

0 comments on commit 0e26298

Please sign in to comment.