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
1 change: 0 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,6 @@ dependencies {
implementation(libs.androidx.navigation.compose)

implementation(libs.accompanist.permissions)
implementation(libs.accompanist.drawablepainter)

implementation(libs.androidx.camera.camera2)
implementation(libs.androidx.camera.lifecycle)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
import org.thoughtcrime.securesms.database.model.MessageId
import org.thoughtcrime.securesms.database.model.MessageRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import java.util.concurrent.ConcurrentHashMap
import kotlin.math.max

class ConversationAdapter(
Expand All @@ -56,8 +57,8 @@ class ConversationAdapter(
var visibleMessageViewDelegate: VisibleMessageViewDelegate? = null

private val updateQueue = Channel<String>(1024, onBufferOverflow = BufferOverflow.DROP_OLDEST)
private val contactCache = SparseArray<Contact>(100)
private val contactLoadedCache = SparseBooleanArray(100)
private val contactCache = ConcurrentHashMap<String, Contact>(100)
private val contactLoadedCache = ConcurrentHashMap<String, Boolean>(100)
private val lastSeen = AtomicLong(originalLastSeen)

var lastSentMessageId: MessageId? = null
Expand All @@ -79,8 +80,8 @@ class ConversationAdapter(
while (isActive) {
val item = updateQueue.receive()
val contact = getSenderInfo(item) ?: continue
contactCache[item.hashCode()] = contact
contactLoadedCache[item.hashCode()] = true
contactCache[item] = contact
contactLoadedCache[item] = true
}
}
}
Expand Down Expand Up @@ -131,18 +132,17 @@ class ConversationAdapter(
visibleMessageView.snIsSelected = isSelected
visibleMessageView.indexInAdapter = position
val senderId = message.individualRecipient.address.toString()
val senderIdHash = senderId.hashCode()
updateQueue.trySend(senderId)
if (contactCache[senderIdHash] == null && !contactLoadedCache.getOrDefault(
senderIdHash,
if (contactCache[senderId] == null && !contactLoadedCache.getOrDefault(
senderId,
false
)
) {
getSenderInfo(senderId)?.let { contact ->
contactCache[senderIdHash] = contact
contactCache[senderId] = contact
}
}
val contact = contactCache[senderIdHash]
val contact = contactCache[senderId]
val isExpanded = expandedMessageIds.contains(message.messageId)

visibleMessageView.bind(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
Expand All @@ -63,31 +62,39 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi
import com.bumptech.glide.integration.compose.GlideImage
import com.squareup.phrase.Phrase
import network.loki.messenger.BuildConfig
import network.loki.messenger.R
import org.session.libsession.utilities.NonTranslatableStringConstants
import org.session.libsession.utilities.NonTranslatableStringConstants.NETWORK_NAME
import org.session.libsession.utilities.StringSubstitutionConstants.NAME_KEY
import org.thoughtcrime.securesms.conversation.v2.settings.ConversationSettingsViewModel.Commands.HideNicknameDialog
import org.thoughtcrime.securesms.conversation.v2.settings.ConversationSettingsViewModel.Commands.RemoveNickname
import org.thoughtcrime.securesms.conversation.v2.settings.ConversationSettingsViewModel.Commands.SetNickname
import org.thoughtcrime.securesms.conversation.v2.settings.ConversationSettingsViewModel.Commands.UpdateNickname
import org.thoughtcrime.securesms.debugmenu.DebugActivity
import org.thoughtcrime.securesms.home.PathActivity
import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity
import org.thoughtcrime.securesms.preferences.SettingsViewModel.AvatarDialogState.TempAvatar
import org.thoughtcrime.securesms.preferences.SettingsViewModel.AvatarDialogState.UserAvatar
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.*
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.ClearData
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.HideAnimatedProCTA
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.HideAvatarPickerOptions
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.HideClearDataDialog
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.HideUrlDialog
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.HideUsernameDialog
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.OnAvatarDialogDismissed
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.OnDonateClicked
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.RemoveAvatar
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.SaveAvatar
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.SetUsername
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.ShowAnimatedProCTA
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.ShowAvatarDialog
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.ShowClearDataDialog
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.ShowUrlDialog
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.ShowUsernameDialog
import org.thoughtcrime.securesms.preferences.SettingsViewModel.Commands.UpdateUsername
import org.thoughtcrime.securesms.preferences.appearance.AppearanceSettingsActivity
import org.thoughtcrime.securesms.recoverypassword.RecoveryPasswordActivity
import org.thoughtcrime.securesms.tokenpage.TokenPageActivity
import org.thoughtcrime.securesms.ui.AccountIdHeader
import org.thoughtcrime.securesms.ui.AlertDialog
import org.thoughtcrime.securesms.ui.AnimatedProfilePicProCTA
import org.thoughtcrime.securesms.ui.AnimatedSessionProActivatedCTA
import org.thoughtcrime.securesms.ui.AnimatedSessionProCTA
import org.thoughtcrime.securesms.ui.CTAFeature
import org.thoughtcrime.securesms.ui.Cell
import org.thoughtcrime.securesms.ui.DialogButtonData
import org.thoughtcrime.securesms.ui.Divider
Expand All @@ -96,6 +103,7 @@ import org.thoughtcrime.securesms.ui.LargeItemButton
import org.thoughtcrime.securesms.ui.LargeItemButtonWithDrawable
import org.thoughtcrime.securesms.ui.LoadingDialog
import org.thoughtcrime.securesms.ui.OpenURLAlertDialog
import org.thoughtcrime.securesms.ui.PathDot
import org.thoughtcrime.securesms.ui.ProBadgeText
import org.thoughtcrime.securesms.ui.RadioOption
import org.thoughtcrime.securesms.ui.components.AcccentOutlineCopyButton
Expand All @@ -119,7 +127,8 @@ import org.thoughtcrime.securesms.ui.theme.accentTextButtonColors
import org.thoughtcrime.securesms.ui.theme.dangerButtonColors
import org.thoughtcrime.securesms.ui.theme.monospace
import org.thoughtcrime.securesms.ui.theme.primaryBlue
import org.thoughtcrime.securesms.ui.theme.transparentButtonColors
import org.thoughtcrime.securesms.ui.theme.primaryGreen
import org.thoughtcrime.securesms.ui.theme.primaryYellow
import org.thoughtcrime.securesms.util.AvatarUIData
import org.thoughtcrime.securesms.util.AvatarUIElement
import org.thoughtcrime.securesms.util.push
Expand Down Expand Up @@ -495,10 +504,16 @@ fun Buttons(
}
Divider()

Crossfade(if (hasPaths) R.drawable.ic_status else R.drawable.ic_path_yellow, label = "path") {
LargeItemButtonWithDrawable(
GetString(R.string.onionRoutingPath),
it,
Crossfade(if (hasPaths) primaryGreen else primaryYellow, label = "path") {
LargeItemButton(
AnnotatedString(stringResource(R.string.onionRoutingPath)),
icon = {
PathDot(
modifier = Modifier.align(Alignment.Center),
dotSize = LocalDimensions.current.iconSmall,
color = it
)
},
) { activity?.push<PathActivity>() }
}
Divider()
Expand Down Expand Up @@ -834,7 +849,9 @@ fun AvatarDialog(
.padding(LocalDimensions.current.xxxsSpacing)
.align(Alignment.BottomEnd)
,
painter = painterResource(id = R.drawable.ic_plus),
painter = painterResource(id =
if(state is SettingsViewModel.AvatarDialogState.NoAvatar) R.drawable.ic_plus
else R.drawable.ic_pencil),
contentDescription = null,
colorFilter = ColorFilter.tint(Color.Black)
)
Expand Down
66 changes: 61 additions & 5 deletions app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
Expand All @@ -31,6 +32,7 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.verticalScroll
Expand Down Expand Up @@ -85,7 +87,7 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import androidx.compose.ui.unit.times
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -145,6 +147,62 @@ fun AccountIdHeader(
}
}

@Composable
fun PathDot(
modifier: Modifier = Modifier,
dotSize: Dp = LocalDimensions.current.iconMedium,
glowSize: Dp = LocalDimensions.current.xxsSpacing,
color: Color = primaryGreen
) {
val fullSize = dotSize + 2 * glowSize
Box(
modifier = modifier.size(fullSize),
contentAlignment = Alignment.Center
) {
// Glow effect (outer circle with radial gradient)
Canvas(modifier = Modifier.fillMaxSize()) {
val center = Offset(this.size.width / 2, this.size.height / 2)
val radius = (fullSize * 0.5f).toPx()

drawCircle(
brush = Brush.radialGradient(
colors = listOf(
color, // Start color (opaque)
color.copy(alpha = 0f) // End color (transparent)
),
center = center,
radius = radius
),
center = center,
radius = radius
)
}

// Inner solid dot
Box(
modifier = Modifier
.size(dotSize)
.background(
color = color,
shape = CircleShape
)
)
}
}

@Preview
@Composable
fun PreviewPathDot(){
PreviewTheme {
Box(
modifier = Modifier.padding(20.dp)
) {
PathDot()
}
}
}


data class RadioOption<T>(
val value: T,
val title: GetString,
Expand Down Expand Up @@ -232,14 +290,12 @@ fun ItemButtonWithDrawable(
shape: Shape = RectangleShape,
onClick: () -> Unit
) {
val context = LocalContext.current

ItemButton(
annotatedStringText = AnnotatedString(text.string()),
modifier = modifier,
icon = {
Image(
painter = rememberDrawablePainter(drawable = AppCompatResources.getDrawable(context, icon)),
painter = painterResource(id = icon),
contentDescription = null,
colorFilter = iconTint?.let { ColorFilter.tint(it) },
modifier = Modifier.align(Alignment.Center)
Expand Down Expand Up @@ -318,7 +374,7 @@ fun LargeItemButton(
@Composable
fun LargeItemButton(
annotatedStringText: AnnotatedString,
@DrawableRes icon: Int,
icon: @Composable BoxScope.() -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
colors: ButtonColors = transparentButtonColors(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ data class Dimensions(
val iconLargeAvatar: Dp = 36.dp,
val iconLarge: Dp = 46.dp,
val iconXLarge: Dp = 60.dp,
val iconXXLarge: Dp = 80.dp,
val iconXXLarge: Dp = 90.dp,
val iconXXLargeAvatar: Dp = 190.dp,

val shapeExtraSmall: Dp = 8.dp,
Expand Down
17 changes: 0 additions & 17 deletions app/src/main/res/drawable/ic_path_yellow.xml

This file was deleted.

17 changes: 0 additions & 17 deletions app/src/main/res/drawable/ic_status.xml

This file was deleted.

2 changes: 0 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ androidMinSdkVersion = "26"
androidTargetSdkVersion = "35"
androidCompileSdkVersion = "35"
accompanistPermissionsVersion = "0.37.3"
accompanistThemeadapterAppcompatVersion = "0.33.1-alpha"
activityKtxVersion = "1.10.1"
androidImageCropperVersion = "4.5.0"
androidVersion = "125.6422.07"
Expand Down Expand Up @@ -79,7 +78,6 @@ huaweiPushVersion = "6.7.0.300"
googlePlayReviewVersion = "2.0.2"

[libraries]
accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanistThemeadapterAppcompatVersion" }
accompanist-permissions = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanistPermissionsVersion" }
android = { module = "io.github.webrtc-sdk:android", version.ref = "androidVersion" }
android-image-cropper = { module = "com.vanniktech:android-image-cropper", version.ref = "androidImageCropperVersion" }
Expand Down