Skip to content

Commit 2e9a9ea

Browse files
Merge pull request #1737 from session-foundation/feature/message-pro-feature-set
Message Pro Features
2 parents 1ad6d62 + c61371e commit 2e9a9ea

File tree

17 files changed

+142
-37
lines changed

17 files changed

+142
-37
lines changed

app/src/main/java/org/session/libsession/messaging/messages/signal/OutgoingTextMessage.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ import org.session.libsession.messaging.messages.visible.VisibleMessage
66
import org.session.libsession.messaging.utilities.UpdateMessageData
77
import org.session.libsession.utilities.Address
88

9-
data class OutgoingTextMessage(
9+
data class OutgoingTextMessage private constructor(
1010
val recipient: Address,
1111
val message: String?,
1212
val expiresInMillis: Long,
1313
val expireStartedAtMillis: Long,
1414
val sentTimestampMillis: Long,
1515
val isOpenGroupInvitation: Boolean,
16-
val proFeatures: Set<ProFeature> = emptySet()
16+
val proFeatures: Set<ProFeature>
1717
) {
1818
constructor(
1919
message: VisibleMessage,
@@ -27,6 +27,7 @@ data class OutgoingTextMessage(
2727
expireStartedAtMillis = expireStartedAtMillis,
2828
sentTimestampMillis = message.sentTimestamp!!,
2929
isOpenGroupInvitation = false,
30+
proFeatures = message.proFeatures
3031
)
3132

3233
companion object {
@@ -36,7 +37,8 @@ data class OutgoingTextMessage(
3637
sentTimestampMillis: Long,
3738
expiresInMillis: Long,
3839
expireStartedAtMillis: Long,
39-
): OutgoingTextMessage? {
40+
proFeatures: Set<ProFeature>,
41+
): OutgoingTextMessage? {
4042
return OutgoingTextMessage(
4143
recipient = recipient,
4244
message = UpdateMessageData.buildOpenGroupInvitation(
@@ -47,6 +49,7 @@ data class OutgoingTextMessage(
4749
expireStartedAtMillis = expireStartedAtMillis,
4850
sentTimestampMillis = sentTimestampMillis,
4951
isOpenGroupInvitation = true,
52+
proFeatures = proFeatures
5053
)
5154
}
5255
}

app/src/main/java/org/session/libsession/messaging/messages/visible/VisibleMessage.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ data class VisibleMessage(
3030
var reaction: Reaction? = null,
3131
var hasMention: Boolean = false,
3232
var blocksMessageRequests: Boolean = false,
33+
/**
34+
* The pro features enabled for this message.
35+
*
36+
* Note:
37+
* * When this message is an incoming message, the pro features will only be populated
38+
* if we can prove that the sender has an active pro subscription.
39+
*
40+
* * When this message represents an outgoing message, this property can be populated by
41+
* application code at their wishes but the actual translating to protobuf onto the wired will
42+
* be checked against the current user's pro proof, if no active pro subscription is found,
43+
* the pro features will not be sent in the protobuf messages.
44+
*/
3345
var proFeatures: Set<ProFeature> = emptySet()
3446
) : Message() {
3547

app/src/main/java/org/session/libsession/messaging/sending_receiving/MessageSender.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,12 @@ class MessageSender @Inject constructor(
124124
msg.toProto(builder, messageDataProvider)
125125

126126
// Attach pro proof
127-
configFactory.withUserConfigs { it.userProfile.getProConfig() }?.proProof?.let { proof ->
128-
builder.proMessageBuilder.proofBuilder.copyFromLibSession(proof)
127+
val proProof = configFactory.withUserConfigs { it.userProfile.getProConfig() }?.proProof
128+
if (proProof != null && proProof.expiryMs > snodeClock.currentTimeMills()) {
129+
builder.proMessageBuilder.proofBuilder.copyFromLibSession(proProof)
130+
} else {
131+
// If we don't have any valid pro proof, clear the pro message
132+
builder.clearProMessage()
129133
}
130134

131135
// Attach the user's profile if needed

app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ import org.thoughtcrime.securesms.mms.SlideDeck
190190
import org.thoughtcrime.securesms.mms.VideoSlide
191191
import org.thoughtcrime.securesms.permissions.Permissions
192192
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
193+
import org.thoughtcrime.securesms.pro.ProStatusManager
193194
import org.thoughtcrime.securesms.reactions.ReactionsDialogFragment
194195
import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiDialogFragment
195196
import org.thoughtcrime.securesms.showSessionDialog
@@ -263,6 +264,7 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate,
263264
@Inject lateinit var messageSender: MessageSender
264265
@Inject lateinit var resendMessageUtilities: ResendMessageUtilities
265266
@Inject lateinit var messageNotifier: MessageNotifier
267+
@Inject lateinit var proStatusManager: ProStatusManager
266268
@Inject @ManagerScope
267269
lateinit var scope: CoroutineScope
268270

@@ -2144,6 +2146,8 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate,
21442146
val message = VisibleMessage().applyExpiryMode(viewModel.address)
21452147
message.sentTimestamp = sentTimestamp
21462148
message.text = text
2149+
// pro features
2150+
proStatusManager.addProFeatures(message)
21472151
val expiresInMillis = viewModel.recipient.expiryMode.expiryMillis
21482152
val outgoingTextMessage = OutgoingTextMessage(
21492153
message = message,
@@ -2206,6 +2210,8 @@ class ConversationActivityV2 : ScreenLockActionBarActivity(), InputBarDelegate,
22062210
val expireStartedAtMs = if (viewModel.recipient.expiryMode is ExpiryMode.AfterSend) {
22072211
sentTimestamp
22082212
} else 0
2213+
// pro features
2214+
proStatusManager.addProFeatures(message)
22092215
val outgoingTextMessage = OutgoingMediaMessage(
22102216
message = message,
22112217
recipient = recipient.address,

app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ResendMessageUtilities.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ResendMessageUtilities @Inject constructor(
3535
message.openGroupInvitation = openGroupInvitation
3636
} else {
3737
message.text = messageRecord.body
38+
message.proFeatures = messageRecord.proFeatures
3839
}
3940
message.sentTimestamp = messageRecord.timestamp
4041
if (recipient.isGroupOrCommunity) {

app/src/main/java/org/thoughtcrime/securesms/database/RecipientRepository.kt

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -430,15 +430,13 @@ class RecipientRepository @Inject constructor(
430430

431431
// Calculate the ProData for this recipient
432432
val proDataList = proDataContext?.proDataList
433-
var proData = if (!proDataList.isNullOrEmpty()) {
434-
proDataList.removeAll {
435-
it.isExpired(now) || proDatabase.isRevoked(it.genIndexHash)
436-
}
437433

438-
// The pro data that goes into the recipient, should show the one with the most information
439-
proDataList.firstOrNull { it.showProBadge }?.let {
440-
RecipientData.ProData(it.showProBadge)
441-
}
434+
proDataList?.removeAll {
435+
it.isExpired(now) || proDatabase.isRevoked(it.genIndexHash)
436+
}
437+
438+
var proData = if (!proDataList.isNullOrEmpty()) {
439+
RecipientData.ProData(showProBadge = proDataList.any { it.showProBadge })
442440
} else {
443441
null
444442
}
@@ -583,7 +581,17 @@ class RecipientRepository @Inject constructor(
583581
configFactory.withUserConfigs { configs ->
584582
val pro = configs.userProfile.getProConfig()
585583

586-
if (pro != null) {
584+
if (prefs.forceCurrentUserAsPro()) {
585+
proDataContext?.addProData(
586+
RecipientSettings.ProData(
587+
showProBadge = configs.userProfile.getProFeatures().contains(
588+
ProProfileFeature.PRO_BADGE
589+
),
590+
expiry = Instant.now().plusSeconds(3600),
591+
genIndexHash = "a1b2c3d4",
592+
)
593+
)
594+
} else if (pro != null) {
587595
proDataContext?.addProData(
588596
RecipientSettings.ProData(
589597
showProBadge = configs.userProfile.getProFeatures().contains(

app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,8 @@ open class Storage @Inject constructor(
369369
recipient = targetAddress,
370370
sentTimestampMillis = message.sentTimestamp!!,
371371
expiresInMillis = expiresInMillis,
372-
expireStartedAtMillis = expireStartedAt
372+
expireStartedAtMillis = expireStartedAt,
373+
proFeatures = message.proFeatures
373374
)!!
374375
else OutgoingTextMessage(
375376
message = message,

app/src/main/java/org/thoughtcrime/securesms/groups/SelectContactsViewModel.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ open class SelectContactsViewModel @AssistedInject constructor(
6969
::filterContacts
7070
).stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
7171

72-
val hasContacts: StateFlow<Boolean> = contactsFlow
72+
val hasContacts: StateFlow<Boolean?> = contactsFlow
7373
.map { it.isNotEmpty() }
74-
.stateIn(viewModelScope, SharingStarted.Eagerly, false)
74+
.stateIn(viewModelScope, SharingStarted.Eagerly, null)
7575

7676
// Output
7777
val currentSelected: Set<Address>

app/src/main/java/org/thoughtcrime/securesms/home/startconversation/group/CreateGroupScreen.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import org.thoughtcrime.securesms.ui.SearchBar
3838
import org.thoughtcrime.securesms.ui.components.AccentOutlineButton
3939
import org.thoughtcrime.securesms.ui.components.BackAppBar
4040
import org.thoughtcrime.securesms.ui.components.SessionOutlinedTextField
41+
import org.thoughtcrime.securesms.ui.components.SmallCircularProgressIndicator
4142
import org.thoughtcrime.securesms.ui.qaTag
4243
import org.thoughtcrime.securesms.ui.theme.LocalColors
4344
import org.thoughtcrime.securesms.ui.theme.LocalDimensions
@@ -86,6 +87,7 @@ fun CreateGroupScreen(
8687
onContactItemClicked = viewModel::onContactItemClicked,
8788
showLoading = viewModel.isLoading.collectAsState().value,
8889
items = viewModel.contacts.collectAsState().value,
90+
hasContacts = viewModel.hasContacts.collectAsState().value,
8991
onCreateClicked = viewModel::onCreateClicked,
9092
onBack = onBack,
9193
)
@@ -103,6 +105,7 @@ fun CreateGroup(
103105
onContactItemClicked: (address: Address) -> Unit,
104106
showLoading: Boolean,
105107
items: List<ContactItem>,
108+
hasContacts: Boolean?,
106109
onCreateClicked: () -> Unit,
107110
onBack: () -> Unit,
108111
modifier: Modifier = Modifier
@@ -160,7 +163,13 @@ fun CreateGroup(
160163
.nestedScroll(rememberNestedScrollInteropConnection()),
161164
fadingColor = LocalColors.current.backgroundSecondary
162165
) { bottomContentPadding ->
163-
if(items.isEmpty() && contactSearchQuery.isEmpty()){
166+
if(hasContacts == null){
167+
SmallCircularProgressIndicator(
168+
modifier = Modifier.padding(top = LocalDimensions.current.spacing)
169+
.align(Alignment.TopCenter),
170+
)
171+
}
172+
else if(!hasContacts && contactSearchQuery.isEmpty()){
164173
Text(
165174
modifier = Modifier.fillMaxWidth()
166175
.padding(top = LocalDimensions.current.xsSpacing),
@@ -245,6 +254,7 @@ private fun CreateGroupPreview(
245254
onContactItemClicked = {},
246255
showLoading = false,
247256
items = previewMembers,
257+
hasContacts = true,
248258
onCreateClicked = {},
249259
onBack = {},
250260
modifier = Modifier.background(LocalColors.current.backgroundSecondary),
@@ -270,6 +280,7 @@ private fun CreateEmptyGroupPreview(
270280
onContactItemClicked = {},
271281
showLoading = false,
272282
items = previewMembers,
283+
hasContacts = false,
273284
onCreateClicked = {},
274285
onBack = {},
275286
modifier = Modifier.background(LocalColors.current.backgroundSecondary),
@@ -294,6 +305,7 @@ private fun CreateEmptyGroupPreviewWithSearch(
294305
onContactItemClicked = {},
295306
showLoading = false,
296307
items = previewMembers,
308+
hasContacts = true,
297309
onCreateClicked = {},
298310
onBack = {},
299311
modifier = Modifier.background(LocalColors.current.backgroundSecondary),

app/src/main/java/org/thoughtcrime/securesms/notifications/AndroidAutoReplyReceiver.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import org.thoughtcrime.securesms.database.RecipientRepository
3939
import org.thoughtcrime.securesms.database.SmsDatabase
4040
import org.thoughtcrime.securesms.database.ThreadDatabase
4141
import org.thoughtcrime.securesms.mms.MmsException
42+
import org.thoughtcrime.securesms.pro.ProStatusManager
4243
import javax.inject.Inject
4344

4445
/**
@@ -67,6 +68,9 @@ class AndroidAutoReplyReceiver : BroadcastReceiver() {
6768
@Inject
6869
lateinit var messageSender: MessageSender
6970

71+
@Inject
72+
lateinit var proStatusManager: ProStatusManager
73+
7074
@SuppressLint("StaticFieldLeak")
7175
override fun onReceive(context: Context, intent: Intent) {
7276
if (REPLY_ACTION != intent.getAction()) return
@@ -92,6 +96,7 @@ class AndroidAutoReplyReceiver : BroadcastReceiver() {
9296

9397
val message = VisibleMessage()
9498
message.text = responseText.toString()
99+
proStatusManager.addProFeatures(message)
95100
message.sentTimestamp = nowWithOffset
96101
messageSender.send(message, address!!)
97102
val expiryMode = recipientRepository.getRecipientSync(address).expiryMode

0 commit comments

Comments
 (0)