diff --git a/.idea/kotlinScripting.xml b/.idea/kotlinScripting.xml
deleted file mode 100644
index 97f762a..0000000
--- a/.idea/kotlinScripting.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
- 2147483647
- true
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/net/buzzert/kordophonedroid/ui/messagelist/MessageListScreen.kt b/app/src/main/java/net/buzzert/kordophonedroid/ui/messagelist/MessageListScreen.kt
index 1865a6e..e180f2a 100644
--- a/app/src/main/java/net/buzzert/kordophonedroid/ui/messagelist/MessageListScreen.kt
+++ b/app/src/main/java/net/buzzert/kordophonedroid/ui/messagelist/MessageListScreen.kt
@@ -14,6 +14,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
@@ -39,9 +40,11 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
+import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
@@ -49,6 +52,14 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import net.buzzert.kordophone.backend.model.GUID
import net.buzzert.kordophone.backend.model.Message
import net.buzzert.kordophonedroid.ui.theme.KordophoneTopAppBar
+import java.text.SimpleDateFormat
+import java.time.Duration
+import java.time.Instant
+import java.time.LocalDate
+import java.time.Period
+import java.time.format.DateTimeFormatter
+import java.time.format.FormatStyle
+import java.util.Date
private val IncomingChatBubbleShape = RoundedCornerShape(4.dp, 20.dp, 20.dp, 20.dp)
private val OutgoingChatBubbleShape = RoundedCornerShape(20.dp, 4.dp, 20.dp, 20.dp)
@@ -56,6 +67,7 @@ private val OutgoingChatBubbleShape = RoundedCornerShape(20.dp, 4.dp, 20.dp, 20.
data class MessageListViewItem(
val text: String,
val fromMe: Boolean,
+ val date: Date,
val delivered: Boolean = true,
)
@@ -79,6 +91,7 @@ fun MessageListScreen(
MessageListViewItem(
text = it.text,
fromMe = it.sender == null,
+ date = it.date,
delivered = !viewModel.isPendingMessage(it)
)
}
@@ -140,14 +153,48 @@ fun Messages(
.fillMaxSize()
.padding(horizontal = 16.dp)
) {
+ var lastDate: Date? = null
+ val dateFormatter = SimpleDateFormat.getDateTimeInstance()
+
for (index in messages.indices) {
val content = messages[index]
+ if (lastDate == null) {
+ lastDate = content.date
+ }
+
+ val duration = Duration.between(content.date.toInstant(), lastDate.toInstant())
+ lastDate = content.date
+
+ Log.d("MessageListScreen", "period: $duration")
+
+ // Remember: This is upside down.
item {
MessageBubble(
text = content.text,
mine = content.fromMe,
- modifier = Modifier.alpha(if (!content.delivered) 0.5F else 1.0f)
+ modifier = Modifier
+ .alpha(if (!content.delivered) 0.5F else 1.0f)
)
+
+ // Greater than 30 minutes: show date:
+ if (duration.toMinutes() > 30) {
+ val formattedDate = dateFormatter.format(content.date)
+ Text(
+ text = formattedDate,
+ textAlign = TextAlign.Center,
+ style = MaterialTheme.typography.caption.copy(
+ color = MaterialTheme.colors.onSurface.copy(alpha = 0.4f)
+ ),
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(18.dp),
+ )
+ }
+
+ // Greater than five minutes: add a bit of space.
+ else if (duration.toMinutes() > 5) {
+ Spacer(modifier = Modifier.height(12.dp))
+ }
}
}
}
@@ -163,21 +210,27 @@ fun MessageBubble(
val backgroundBubbleColor = if (mine) MaterialTheme.colors.primary else MaterialTheme.colors.secondary
Column() {
- Row(
- modifier = modifier.fillMaxWidth(),
- horizontalArrangement = if (mine) Arrangement.End else Arrangement.Start,
- ) {
- Surface(
- color = backgroundBubbleColor,
- shape = if (mine) OutgoingChatBubbleShape else IncomingChatBubbleShape,
+ Row(modifier = modifier.fillMaxWidth()) {
+ if (mine) { Spacer(modifier = Modifier.weight(1f)) }
+
+ Row(
+ modifier = Modifier.fillMaxWidth(0.8f),
+ horizontalArrangement = if (mine) Arrangement.End else Arrangement.Start,
) {
- Text(
- text = text,
- style = MaterialTheme.typography.body1,
- modifier = Modifier
- .padding(16.dp)
- )
+ Surface(
+ color = backgroundBubbleColor,
+ shape = if (mine) OutgoingChatBubbleShape else IncomingChatBubbleShape,
+ ) {
+ Text(
+ text = text,
+ style = MaterialTheme.typography.body1,
+ modifier = Modifier
+ .padding(16.dp)
+ )
+ }
}
+
+ if (!mine) { Spacer(modifier = Modifier.weight(1f)) }
}
Spacer(modifier = Modifier.height(4.dp))
@@ -190,9 +243,9 @@ fun MessageBubble(
@Composable
private fun MessageListScreenPreview() {
val messages = listOf(
- MessageListViewItem(text = "Hello", fromMe = false),
- MessageListViewItem(text = "Hey there", fromMe = true),
- MessageListViewItem(text = "How's it going", fromMe = true, delivered = false)
+ MessageListViewItem(text = "Hello", fromMe = false, date = Date()),
+ MessageListViewItem(text = "Hey there, this is a longer text message that might wrap to another line", fromMe = true, date = Date()),
+ MessageListViewItem(text = "How's it going", fromMe = true, delivered = false, date = Date())
).reversed()
Scaffold() {