Skip to content

Commit

Permalink
Disappearing messages (#375)
Browse files Browse the repository at this point in the history
* remove pinned frame url from android

* update libxmtp ref for pinned frame removal and db lock fix

* add message expiration to group and dm

* add ability to update expiration state

* add permission policy update

* write a test for disappearing messages

* remame

* more renames

* small tweaks to impl

* try to get the tests to pass

* try to mirror disappearing message

* try updating test

* update bindings

* update the test

* small test tweak

* getting closer on the test

* add tests for dms as well

* get it passing for dms

* fix up the lint

* rename

* more clean up

* fix lint

* fix lint

* remove small code from test

* remove frames V1 (#382)

* Make addWallet a delicate API (#381)

* add a delicate api warning level

* slightly update the logic

* Update library/src/main/java/org/xmtp/android/library/Client.kt

Co-authored-by: Nicholas Molnar <[email protected]>

* add a test for this case

* fix lint

---------

Co-authored-by: Nicholas Molnar <[email protected]>

* tweak slightly the name

---------

Co-authored-by: Cameron Voell <[email protected]>
Co-authored-by: cameronvoell <[email protected]>
Co-authored-by: Nicholas Molnar <[email protected]>
  • Loading branch information
4 people authored Feb 12, 2025
1 parent 7f5e17c commit bfac6ff
Show file tree
Hide file tree
Showing 22 changed files with 531 additions and 424 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,7 @@ class ClientTest {
)
}

@OptIn(DelicateApi::class)
@Test
fun testAddAccounts() {
val fixtures = fixtures()
Expand All @@ -539,6 +540,29 @@ class ClientTest {
)
}

@OptIn(DelicateApi::class)
@Test
fun testAddAccountsWithExistingInboxIds() {
val fixtures = fixtures()

assertThrows(
"This wallet is already associated with inbox ${fixtures.boClient.inboxId}",
XMTPException::class.java
) {
runBlocking { fixtures.alixClient.addAccount(fixtures.boAccount) }
}

assert(fixtures.boClient.inboxId != fixtures.alixClient.inboxId)
runBlocking { fixtures.alixClient.addAccount(fixtures.boAccount, true) }

val state = runBlocking { fixtures.alixClient.inboxState(true) }
assertEquals(state.addresses.size, 2)

val inboxId = runBlocking { fixtures.alixClient.inboxIdFromAddress(fixtures.boClient.address) }
assertEquals(inboxId, fixtures.alixClient.inboxId)
}

@OptIn(DelicateApi::class)
@Test
fun testRemovingAccounts() {
val fixtures = fixtures()
Expand Down
117 changes: 117 additions & 0 deletions library/src/androidTest/java/org/xmtp/android/library/DmTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertThrows
import org.junit.Before
Expand All @@ -18,6 +20,7 @@ import org.xmtp.android.library.codecs.Reaction
import org.xmtp.android.library.codecs.ReactionAction
import org.xmtp.android.library.codecs.ReactionCodec
import org.xmtp.android.library.codecs.ReactionSchema
import org.xmtp.android.library.libxmtp.DisappearingMessageSettings
import org.xmtp.android.library.libxmtp.Message
import org.xmtp.android.library.libxmtp.Message.MessageDeliveryStatus
import org.xmtp.android.library.messages.PrivateKey
Expand Down Expand Up @@ -400,4 +403,118 @@ class DmTest {
assertEquals(dm.consentState(), ConsentState.ALLOWED)
}
}

@Test
fun testDmDisappearingMessages() = runBlocking {
val initialSettings = DisappearingMessageSettings(
1_000_000_000,
1_000_000_000 // 1s duration
)

// Create group with disappearing messages enabled
val boDm = boClient.conversations.findOrCreateDm(
alix.walletAddress,
disappearingMessageSettings = initialSettings
)
boDm.send("howdy")
alixClient.conversations.syncAllConversations()

val alixDm = alixClient.findDmByInboxId(boClient.inboxId)

// Validate messages exist and settings are applied
assertEquals(boDm.messages().size, 1) // howdy
assertEquals(alixDm?.messages()?.size, 1) // howdy
Assert.assertNotNull(boDm.disappearingMessageSettings)
assertEquals(boDm.disappearingMessageSettings!!.retentionDurationInNs, 1_000_000_000)
assertEquals(boDm.disappearingMessageSettings!!.disappearStartingAtNs, 1_000_000_000)
Thread.sleep(5000)
// Validate messages are deleted
assertEquals(boDm.messages().size, 0)
assertEquals(alixDm?.messages()?.size, 0)

// Set message disappearing settings to null
boDm.updateDisappearingMessageSettings(null)
boDm.sync()
alixDm!!.sync()

assertNull(boDm.disappearingMessageSettings)
assertNull(alixDm.disappearingMessageSettings)
assertFalse(boDm.isDisappearingMessagesEnabled)
assertFalse(alixDm.isDisappearingMessagesEnabled)

// Send messages after disabling disappearing settings
boDm.send("message after disabling disappearing")
alixDm.send("another message after disabling")
boDm.sync()

Thread.sleep(1000)

// Ensure messages persist
assertEquals(
boDm.messages().size,
2
) // disappearing settings 1, disappearing settings 2, boMessage, alixMessage
assertEquals(
alixDm.messages().size,
2
) // disappearing settings 1, disappearing settings 2, boMessage, alixMessage

// Re-enable disappearing messages
val updatedSettings = DisappearingMessageSettings(
boDm.messages().first().sentAtNs + 1_000_000_000, // 1s from now
1_000_000_000 // 1s duration
)
boDm.updateDisappearingMessageSettings(updatedSettings)
boDm.sync()
alixDm.sync()

Thread.sleep(1000)

assertEquals(
boDm.disappearingMessageSettings!!.disappearStartingAtNs,
updatedSettings.disappearStartingAtNs
)
assertEquals(
alixDm.disappearingMessageSettings!!.disappearStartingAtNs,
updatedSettings.disappearStartingAtNs
)

// Send new messages
boDm.send("this will disappear soon")
alixDm.send("so will this")
boDm.sync()

assertEquals(
boDm.messages().size,
4
) // disappearing settings 3, disappearing settings 4, boMessage, alixMessage, disappearing settings 5, disappearing settings 6, boMessage2, alixMessage2
assertEquals(
alixDm.messages().size,
4
) // disappearing settings 3, disappearing settings 4, boMessage, alixMessage, disappearing settings 5, disappearing settings 6, boMessage2, alixMessage2

Thread.sleep(6000) // Wait for messages to disappear

// Validate messages were deleted
assertEquals(
boDm.messages().size,
2
) // disappearing settings 3, disappearing settings 4, boMessage, alixMessage, disappearing settings 5, disappearing settings 6
assertEquals(
alixDm.messages().size,
2
) // disappearing settings 3, disappearing settings 4, boMessage, alixMessage, disappearing settings 5, disappearing settings 6

// Final validation that settings persist
assertEquals(
boDm.disappearingMessageSettings!!.retentionDurationInNs,
updatedSettings.retentionDurationInNs
)
assertEquals(
alixDm.disappearingMessageSettings!!.retentionDurationInNs,
updatedSettings.retentionDurationInNs
)
assert(boDm.isDisappearingMessagesEnabled)
assert(alixDm.isDisappearingMessagesEnabled)
}
}

This file was deleted.

117 changes: 117 additions & 0 deletions library/src/androidTest/java/org/xmtp/android/library/GroupTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertThrows
import org.junit.Before
import org.junit.Test
Expand All @@ -19,6 +21,7 @@ import org.xmtp.android.library.codecs.Reaction
import org.xmtp.android.library.codecs.ReactionAction
import org.xmtp.android.library.codecs.ReactionCodec
import org.xmtp.android.library.codecs.ReactionSchema
import org.xmtp.android.library.libxmtp.DisappearingMessageSettings
import org.xmtp.android.library.libxmtp.GroupPermissionPreconfiguration
import org.xmtp.android.library.libxmtp.Message
import org.xmtp.android.library.libxmtp.Message.MessageDeliveryStatus
Expand Down Expand Up @@ -1021,4 +1024,118 @@ class GroupTest {
// Next syncAllGroups will not include the inactive group
assertEquals(numGroups, 2u)
}

@Test
fun testGroupDisappearingMessages() = runBlocking {
val initialSettings = DisappearingMessageSettings(
1_000_000_000,
1_000_000_000 // 1s duration
)

// Create group with disappearing messages enabled
val boGroup = boClient.conversations.newGroup(
listOf(alix.walletAddress),
disappearingMessageSettings = initialSettings
)
boGroup.send("howdy")
alixClient.conversations.syncAllConversations()

val alixGroup = alixClient.findGroup(boGroup.id)

// Validate messages exist and settings are applied
assertEquals(boGroup.messages().size, 2) // memberAdd, howdy
assertEquals(alixGroup?.messages()?.size, 1) // howdy
assertNotNull(boGroup.disappearingMessageSettings)
assertEquals(boGroup.disappearingMessageSettings!!.retentionDurationInNs, 1_000_000_000)
assertEquals(boGroup.disappearingMessageSettings!!.disappearStartingAtNs, 1_000_000_000)
Thread.sleep(5000)
// Validate messages are deleted
assertEquals(boGroup.messages().size, 1) // memberAdd
assertEquals(alixGroup?.messages()?.size, 0)

// Set message disappearing settings to null
boGroup.updateDisappearingMessageSettings(null)
boGroup.sync()
alixGroup!!.sync()

assertNull(boGroup.disappearingMessageSettings)
assertNull(alixGroup.disappearingMessageSettings)
assert(!boGroup.isDisappearingMessagesEnabled)
assert(!alixGroup.isDisappearingMessagesEnabled)

// Send messages after disabling disappearing settings
boGroup.send("message after disabling disappearing")
alixGroup.send("another message after disabling")
boGroup.sync()

Thread.sleep(1000)

// Ensure messages persist
assertEquals(
boGroup.messages().size,
5
) // memberAdd, disappearing settings 1, disappearing settings 2, boMessage, alixMessage
assertEquals(
alixGroup.messages().size,
4
) // disappearing settings 1, disappearing settings 2, boMessage, alixMessage

// Re-enable disappearing messages
val updatedSettings = DisappearingMessageSettings(
boGroup.messages().first().sentAtNs + 1_000_000_000, // 1s from now
1_000_000_000 // 1s duration
)
boGroup.updateDisappearingMessageSettings(updatedSettings)
boGroup.sync()
alixGroup.sync()

Thread.sleep(1000)

assertEquals(
boGroup.disappearingMessageSettings!!.disappearStartingAtNs,
updatedSettings.disappearStartingAtNs
)
assertEquals(
alixGroup.disappearingMessageSettings!!.disappearStartingAtNs,
updatedSettings.disappearStartingAtNs
)

// Send new messages
boGroup.send("this will disappear soon")
alixGroup.send("so will this")
boGroup.sync()

assertEquals(
boGroup.messages().size,
9
) // memberAdd, disappearing settings 3, disappearing settings 4, boMessage, alixMessage, disappearing settings 5, disappearing settings 6, boMessage2, alixMessage2
assertEquals(
alixGroup.messages().size,
8
) // disappearing settings 3, disappearing settings 4, boMessage, alixMessage, disappearing settings 5, disappearing settings 6, boMessage2, alixMessage2

Thread.sleep(6000) // Wait for messages to disappear

// Validate messages were deleted
assertEquals(
boGroup.messages().size,
7
) // memberAdd, disappearing settings 3, disappearing settings 4, boMessage, alixMessage, disappearing settings 5, disappearing settings 6
assertEquals(
alixGroup.messages().size,
6
) // disappearing settings 3, disappearing settings 4, boMessage, alixMessage, disappearing settings 5, disappearing settings 6

// Final validation that settings persist
assertEquals(
boGroup.disappearingMessageSettings!!.retentionDurationInNs,
updatedSettings.retentionDurationInNs
)
assertEquals(
alixGroup.disappearingMessageSettings!!.retentionDurationInNs,
updatedSettings.retentionDurationInNs
)
assert(boGroup.isDisappearingMessagesEnabled)
assert(alixGroup.isDisappearingMessagesEnabled)
}
}
4 changes: 2 additions & 2 deletions library/src/main/java/libxmtp-version.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Version: b6f090bc
Version: f5b10896
Branch: main
Date: 2025-02-07 22:46:17 +0000
Date: 2025-02-10 16:52:01 +0000
Loading

0 comments on commit bfac6ff

Please sign in to comment.