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
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,32 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewWrapper
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.zIndex
import com.flipcash.app.contacts.ui.ContactAvatar
import com.flipcash.app.core.contacts.DeviceContact
import com.flipcash.app.directsend.internal.ContactListItem
import com.flipcash.app.permissions.ContactAccessHandle
import com.flipcash.app.theme.FlipcashThemeWrapper
import com.flipcash.features.directsend.R
import com.flipcash.services.models.chat.ChatId
import com.flipcash.shared.chat.ui.ChatListRow
import com.flipcash.shared.chat.ui.ConversationReference
import com.flipcash.shared.chat.ui.ChatRowSubtitle
import com.flipcash.shared.chat.ui.ChatRowTrailing
import com.flipcash.shared.chat.ui.SubtitleText
import com.flipcash.shared.common.ui.ContactAvatar
import com.getcode.theme.CodeTheme
import com.getcode.theme.White10
import com.getcode.theme.extraSmall
import com.getcode.ui.core.verticalScrollStateGradient
import com.getcode.util.formatLocalized
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import kotlin.compareTo
import kotlin.time.Clock
import kotlin.time.Duration.Companion.days
import kotlin.time.Duration.Companion.hours
Expand Down Expand Up @@ -294,116 +300,59 @@ private fun ContactRowItem(
showDivider: Boolean = true,
onClick: () -> Unit,
) {
Column(
modifier = modifier
.fillMaxWidth()
.background(CodeTheme.colors.background)
) {
Row(
modifier = Modifier
.fillMaxWidth()
.testTag("send_contact_row")
.clickable(onClick = onClick)
.padding(vertical = CodeTheme.dimens.inset)
.padding(end = CodeTheme.dimens.inset),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x3),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
// Spacer used by the unread indicator that we moved
// left for spacing compatibility and easy add back later
Box(modifier = Modifier.requiredWidth(CodeTheme.dimens.inset))
ContactAvatar(
contact = contact,
modifier = Modifier
.requiredSize(CodeTheme.dimens.staticGrid.x8)
.clip(CircleShape),
includeBorder = false,
ChatListRow(
modifier = modifier,
avatar = {
ContactAvatar(
contact = contact,
modifier = Modifier
.requiredSize(CodeTheme.dimens.staticGrid.x8)
.clip(CircleShape),
includeBorder = false,
)
},
title = {
Text(
modifier = Modifier.weight(1f),
text = contact.displayName,
style = CodeTheme.typography.textMedium,
color = CodeTheme.colors.textMain,
)

if (contact.isUnknown) {
Text(
modifier = Modifier.background(
color = CodeTheme.colors.surfaceVariant,
shape = CircleShape,
).padding(
vertical = CodeTheme.dimens.grid.x1,
horizontal = CodeTheme.dimens.grid.x2,
),
text = stringResource(R.string.label_unknownContact),
style = CodeTheme.typography.caption.copy(fontSize = 10.sp, lineHeight = 10.sp),
color = CodeTheme.colors.textSecondary,
)
}

Column(modifier = Modifier.weight(1f)) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x1),
) {
Text(
modifier = Modifier.weight(1f),
text = contact.displayName,
style = CodeTheme.typography.textMedium,
color = CodeTheme.colors.textMain,
)

when {
contact.isUnknown -> {
Text(
modifier = Modifier.background(
color = CodeTheme.colors.surfaceVariant,
shape = CircleShape,
).padding(
vertical = CodeTheme.dimens.grid.x1,
horizontal = CodeTheme.dimens.grid.x2,
),
text = stringResource(R.string.label_unknownContact),
style = CodeTheme.typography.caption.copy(fontSize = 10.sp, lineHeight = 10.sp),
color = CodeTheme.colors.textSecondary,
)
}
lastActivity != null -> {
val activityTextColor by animateColorAsState(
if (unreadCount > 0) CodeTheme.colors.indicator else CodeTheme.colors.textSecondary
)
Text(
text = formatLastActivity(lastActivity),
style = CodeTheme.typography.caption,
color = activityTextColor,
)
}
}

if (unreadCount > 0) {
UnreadBadge(
modifier = Modifier.padding(
start = CodeTheme.dimens.grid.x1,
end = CodeTheme.dimens.grid.x1,
),
count = unreadCount
)
} else if (isOnFlipcash) {
Icon(
modifier = Modifier.scale(0.6f),
painter = painterResource(id = R.drawable.ic_chevron_right),
contentDescription = null,
tint = CodeTheme.colors.textSecondary,
)
}
}

when {
isTyping -> Text(
text = stringResource(R.string.label_isTyping),
style = CodeTheme.typography.textSmall,
color = CodeTheme.colors.textSecondary,
)

else -> Text(
text = if (isOnFlipcash && !lastMessagePreview.isNullOrEmpty()) {
lastMessagePreview
} else if (isOnFlipcash) {
"${contact.displayName} joined Flipcash"
} else {
contact.displayNumber
},
style = CodeTheme.typography.textSmall,
color = CodeTheme.colors.textSecondary,
maxLines = 1,
overflow = androidx.compose.ui.text.style.TextOverflow.Ellipsis,
ChatRowTrailing(
lastActivity = lastActivity,
unreadCount = unreadCount,
canOpen = isOnFlipcash,
)
},
subtitle = {
ChatRowSubtitle(
isTyping = isTyping,
preview = lastMessagePreview.takeIf { isOnFlipcash },
fallback = {
SubtitleText(
if (isOnFlipcash) "${contact.displayName} joined Flipcash"
else contact.displayNumber
)
}
}

)
},
endAction = {
if (!isOnFlipcash) {
Text(
modifier = Modifier
Expand All @@ -420,31 +369,9 @@ private fun ContactRowItem(
color = CodeTheme.colors.textMain,
)
}
}
if (showDivider) {
HorizontalDivider(
color = CodeTheme.colors.divider,
modifier = Modifier
.fillMaxWidth()
.height(1.dp)
.padding(
start = CodeTheme.dimens.inset + CodeTheme.dimens.staticGrid.x8 + CodeTheme.dimens.grid.x3,
end = CodeTheme.dimens.inset,
),
)
}
}
}

@Composable
private fun UnreadBadge(count: Int, modifier: Modifier = Modifier) {
Box(
modifier = modifier
.size(CodeTheme.dimens.grid.x2)
.background(
color = CodeTheme.colors.indicator,
shape = CircleShape,
),
},
showDivider = showDivider,
onClick = onClick,
)
}

Expand Down Expand Up @@ -506,26 +433,6 @@ private fun EmptySearchState(
}
}

@Composable
private fun formatLastActivity(instant: Instant): String {
val context = LocalContext.current
val is24Hour = DateFormat.is24HourFormat(context)
val tz = TimeZone.currentSystemDefault()
val todayDate = Clock.System.now().toLocalDateTime(tz).date
val messageDate = instant.toLocalDateTime(tz).date
val dayDiff = todayDate.toEpochDays() - messageDate.toEpochDays()

val time = instant.formatLocalized("h:mm a", is24Hour = is24Hour, if24Hour = "H:mm")

return when {
dayDiff == 0L -> time
dayDiff == 1L -> stringResource(R.string.label_chatReceipt_yesterday)
dayDiff in 2L..6L -> instant.formatLocalized("EEEE")
messageDate.year == todayDate.year -> instant.formatLocalized("MMM d")
else -> instant.formatLocalized("MMM d, yyyy")
}
}

@Preview
@PreviewWrapper(FlipcashThemeWrapper::class)
@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import com.flipcash.app.core.contacts.DeviceContact
import com.flipcash.app.core.ui.ConfirmationStyle
import com.flipcash.app.featureflags.FeatureFlag
import com.flipcash.app.featureflags.FeatureFlagController
import com.flipcash.shared.chat.ui.ChatListItem
import com.flipcash.shared.chat.ui.ReceiptStatus
import com.flipcash.shared.chat.ui.SeparatorConfig
import com.flipcash.shared.chat.models.ChatListItem
import com.flipcash.shared.chat.models.ReceiptStatus
import com.flipcash.shared.chat.models.SeparatorConfig
import com.flipcash.app.payments.PurchaseMethodController
import com.flipcash.app.tokens.TokenCoordinator
import com.flipcash.features.messenger.R
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.flipcash.app.messenger.internal.ChatViewModel
import com.flipcash.app.messenger.internal.screens.components.ChatTopBar
import com.flipcash.app.messenger.internal.screens.components.MessageList
import com.flipcash.app.messenger.internal.screens.components.UserControlBottomBar
import com.flipcash.shared.chat.ui.ChatAction
import com.flipcash.shared.chat.models.ChatAction
import com.getcode.navigation.core.LocalCodeNavigator
import com.getcode.ui.utils.rememberKeyboardController
import dev.chrisbanes.haze.hazeSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.flipcash.app.contacts.ui.ContactAvatar
import com.flipcash.app.core.contacts.DeviceContact
import com.flipcash.shared.common.ui.ContactAvatar
import com.getcode.navigation.core.CodeNavigator
import com.getcode.theme.CodeTheme
import com.getcode.ui.components.AppBarDefaults
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import com.flipcash.app.contacts.ui.ContactAvatar
import com.flipcash.app.core.android.IntentUtils
import com.flipcash.app.core.contacts.DeviceContact
import com.flipcash.features.messenger.R
import com.flipcash.shared.common.ui.ContactAvatar
import com.getcode.theme.CodeTheme

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ import androidx.paging.compose.itemKey
import com.flipcash.app.messenger.internal.ChatViewModel
import com.flipcash.services.models.chat.MessagePointer
import androidx.compose.runtime.CompositionLocalProvider
import com.flipcash.shared.chat.ui.ChatAction
import com.flipcash.shared.chat.ui.ChatActionHandler
import com.flipcash.shared.chat.ui.ChatListItem
import com.flipcash.shared.chat.models.ChatAction
import com.flipcash.shared.chat.models.ChatActionHandler
import com.flipcash.shared.chat.models.ChatListItem
import com.flipcash.shared.chat.ui.ContentBubble
import com.flipcash.shared.chat.ui.LocalChatActionHandler
import com.flipcash.shared.chat.ui.ReceiptStatus
import com.flipcash.shared.chat.ui.SeparatorConfig
import com.flipcash.shared.chat.models.LocalChatActionHandler
import com.flipcash.shared.chat.models.ReceiptStatus
import com.flipcash.shared.chat.models.SeparatorConfig
import com.flipcash.shared.chat.ui.bubblePositionOf
import com.getcode.theme.CodeTheme
import com.getcode.ui.utils.rememberKeyboardController
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewWrapper
import com.flipcash.app.theme.FlipcashThemeWrapper
import com.flipcash.shared.chat.ui.ReceiptStatus
import com.flipcash.shared.chat.models.ReceiptStatus
import com.flipcash.features.messenger.R
import com.flipcash.services.models.chat.MessagePointer
import com.flipcash.services.models.chat.PointerType
Expand Down
1 change: 1 addition & 0 deletions apps/flipcash/features/myaccount/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ dependencies {
testImplementation(libs.bundles.compose.ui.testing)

implementation(project(":apps:flipcash:shared:authentication"))
implementation(project(":apps:flipcash:shared:common-ui"))
implementation(project(":apps:flipcash:shared:contacts"))
implementation(project(":apps:flipcash:shared:featureflags"))
implementation(project(":apps:flipcash:shared:menu"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.flipcash.app.myaccount.internal

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
Expand Down Expand Up @@ -42,11 +41,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight.Companion.W600
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.flipcash.app.contacts.ui.ContactAvatar
import com.flipcash.core.R
import com.flipcash.services.models.SocialAccount
import com.flipcash.services.models.chat.MediaItem
import com.flipcash.services.models.chat.MediaItemRendition
import com.flipcash.shared.common.ui.ContactAvatar
import com.getcode.theme.CodeTheme
import com.getcode.ui.components.SwipeAction
import com.getcode.ui.components.SwipeActionRow
Expand Down Expand Up @@ -279,7 +278,7 @@ private fun ProfileHeader(
verticalArrangement = Arrangement.spacedBy(CodeTheme.dimens.grid.x3),
) {
ContactAvatar(
photoUri = profilePicture.displayUrl(),
photoUri = profilePicture?.url(preferred = MediaItemRendition.Role.DISPLAY),
displayName = displayName.orEmpty(),
modifier = Modifier
.size(96.dp)
Expand Down Expand Up @@ -307,15 +306,6 @@ private fun ProfileHeader(
}
}

// Prefer the DISPLAY rendition (falling back to THUMBNAIL / any) for the avatar image URL.
private fun MediaItem?.displayUrl(): String? {
val renditions = this?.renditions ?: return null
return (renditions.firstOrNull { it.role == MediaItemRendition.Role.DISPLAY }
?: renditions.firstOrNull { it.role == MediaItemRendition.Role.THUMBNAIL }
?: renditions.firstOrNull())
?.blob?.downloadUrl
}

/** Non-swipeable card wrapper — just visual styling. */
@Composable
private fun CardRow(
Expand Down
1 change: 1 addition & 0 deletions apps/flipcash/shared/chat-ui/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ dependencies {
implementation(project(":libs:datetime"))
implementation(libs.androidx.paging.runtime)
implementation(libs.compose.paging)
api(project(":apps:flipcash:shared:common-ui"))
implementation(project(":apps:flipcash:shared:theme"))

testImplementation(libs.robolectric)
Expand Down
Loading
Loading