mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-25 11:05:25 +00:00
Fix compilation issues
This commit is contained in:
parent
1f9b00bc0a
commit
222df30a18
@ -35,6 +35,7 @@ import org.session.libsession.utilities.ConfigUpdateNotification
|
|||||||
import org.session.libsession.utilities.GroupUtil
|
import org.session.libsession.utilities.GroupUtil
|
||||||
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol.Companion.NAME_PADDED_LENGTH
|
import org.session.libsession.utilities.SSKEnvironment.ProfileManagerProtocol.Companion.NAME_PADDED_LENGTH
|
||||||
import org.session.libsession.utilities.TextSecurePreferences
|
import org.session.libsession.utilities.TextSecurePreferences
|
||||||
|
import org.session.libsession.utilities.UserConfigType
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
|
import org.session.libsignal.crypto.ecc.DjbECPrivateKey
|
||||||
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
import org.session.libsignal.crypto.ecc.DjbECPublicKey
|
||||||
@ -86,7 +87,7 @@ class ConfigToDatabaseSync @Inject constructor(
|
|||||||
.collect { config ->
|
.collect { config ->
|
||||||
try {
|
try {
|
||||||
Log.i(TAG, "Start syncing user configs")
|
Log.i(TAG, "Start syncing user configs")
|
||||||
syncUserConfigs(config.timestamp)
|
syncUserConfigs(config.configType, config.timestamp)
|
||||||
Log.i(TAG, "Finished syncing user configs")
|
Log.i(TAG, "Finished syncing user configs")
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Error syncing user configs", e)
|
Log.e(TAG, "Error syncing user configs", e)
|
||||||
@ -116,23 +117,23 @@ class ConfigToDatabaseSync @Inject constructor(
|
|||||||
updateGroup(info)
|
updateGroup(info)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun syncUserConfigs(updateTimestamp: Long) {
|
private fun syncUserConfigs(userConfigType: UserConfigType, updateTimestamp: Long) {
|
||||||
lateinit var updateUserInfo: UpdateUserInfo
|
val configUpdate = configFactory.withUserConfigs { configs ->
|
||||||
lateinit var updateUserGroupsInfo: UpdateUserGroupsInfo
|
when (userConfigType) {
|
||||||
lateinit var updateContacts: List<Contact>
|
UserConfigType.USER_PROFILE -> UpdateUserInfo(configs.userProfile)
|
||||||
lateinit var updateConvoVolatile: List<Conversation?>
|
UserConfigType.USER_GROUPS -> UpdateUserGroupsInfo(configs.userGroups)
|
||||||
|
UserConfigType.CONTACTS -> UpdateContacts(configs.contacts.all())
|
||||||
configFactory.withUserConfigs { configs ->
|
UserConfigType.CONVO_INFO_VOLATILE -> UpdateConvoVolatile(configs.convoInfoVolatile.all())
|
||||||
updateUserInfo = UpdateUserInfo(configs.userProfile)
|
}
|
||||||
updateUserGroupsInfo = UpdateUserGroupsInfo(configs.userGroups)
|
|
||||||
updateContacts = configs.contacts.all()
|
|
||||||
updateConvoVolatile = configs.convoInfoVolatile.all()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUser(updateUserInfo, updateTimestamp)
|
when (configUpdate) {
|
||||||
updateContacts(updateContacts, updateTimestamp)
|
is UpdateUserInfo -> updateUser(configUpdate, updateTimestamp)
|
||||||
updateUserGroups(updateUserGroupsInfo, updateTimestamp)
|
is UpdateUserGroupsInfo -> updateUserGroups(configUpdate, updateTimestamp)
|
||||||
updateConvoVolatile(updateConvoVolatile)
|
is UpdateContacts -> updateContacts(configUpdate, updateTimestamp)
|
||||||
|
is UpdateConvoVolatile -> updateConvoVolatile(configUpdate)
|
||||||
|
else -> error("Unknown config update type: $configUpdate")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class UpdateUserInfo(
|
private data class UpdateUserInfo(
|
||||||
@ -219,8 +220,10 @@ class ConfigToDatabaseSync @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateContacts(contacts: List<Contact>, messageTimestamp: Long) {
|
private data class UpdateContacts(val contacts: List<Contact>)
|
||||||
storage.addLibSessionContacts(contacts, messageTimestamp)
|
|
||||||
|
private fun updateContacts(contacts: UpdateContacts, messageTimestamp: Long) {
|
||||||
|
storage.addLibSessionContacts(contacts.contacts, messageTimestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class UpdateUserGroupsInfo(
|
private data class UpdateUserGroupsInfo(
|
||||||
@ -368,8 +371,10 @@ class ConfigToDatabaseSync @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateConvoVolatile(convos: List<Conversation?>) {
|
private data class UpdateConvoVolatile(val convos: List<Conversation?>)
|
||||||
val extracted = convos.filterNotNull()
|
|
||||||
|
private fun updateConvoVolatile(convos: UpdateConvoVolatile) {
|
||||||
|
val extracted = convos.convos.filterNotNull()
|
||||||
for (conversation in extracted) {
|
for (conversation in extracted) {
|
||||||
val threadId = when (conversation) {
|
val threadId = when (conversation) {
|
||||||
is Conversation.OneToOne -> storage.getThreadIdFor(conversation.accountId, null, null, createThread = false)
|
is Conversation.OneToOne -> storage.getThreadIdFor(conversation.accountId, null, null, createThread = false)
|
||||||
|
@ -49,6 +49,7 @@ import org.session.libsignal.utilities.IdPrefix
|
|||||||
import org.session.libsignal.utilities.Log
|
import org.session.libsignal.utilities.Log
|
||||||
import org.session.libsignal.utilities.toHexString
|
import org.session.libsignal.utilities.toHexString
|
||||||
import org.thoughtcrime.securesms.database.ConfigDatabase
|
import org.thoughtcrime.securesms.database.ConfigDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.ConfigVariant
|
||||||
import org.thoughtcrime.securesms.database.LokiThreadDatabase
|
import org.thoughtcrime.securesms.database.LokiThreadDatabase
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
import org.thoughtcrime.securesms.groups.GroupManager
|
import org.thoughtcrime.securesms.groups.GroupManager
|
||||||
@ -142,14 +143,18 @@ class ConfigFactory @Inject constructor(
|
|||||||
*
|
*
|
||||||
* @param cb A function that takes a [UserConfigsImpl] and returns a pair of the result of the operation and a boolean indicating if the configs were changed.
|
* @param cb A function that takes a [UserConfigsImpl] and returns a pair of the result of the operation and a boolean indicating if the configs were changed.
|
||||||
*/
|
*/
|
||||||
private fun <T> doWithMutableUserConfigs(cb: (UserConfigsImpl) -> Pair<T, ConfigUpdateNotification?>): T {
|
private fun <T> doWithMutableUserConfigs(cb: (UserConfigsImpl) -> Pair<T, List<ConfigUpdateNotification>>): T {
|
||||||
val (lock, configs) = ensureUserConfigsInitialized()
|
val (lock, configs) = ensureUserConfigsInitialized()
|
||||||
val (result, changed) = lock.write {
|
val (result, changed) = lock.write {
|
||||||
cb(configs)
|
cb(configs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed != null) {
|
if (changed.isNotEmpty()) {
|
||||||
_configUpdateNotifications.tryEmit(changed)
|
for (notification in changed) {
|
||||||
|
if (!_configUpdateNotifications.tryEmit(notification)) {
|
||||||
|
Log.e("ConfigFactory", "Unable to deliver config update notification")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@ -163,7 +168,7 @@ class ConfigFactory @Inject constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return doWithMutableUserConfigs { configs ->
|
val toDump = doWithMutableUserConfigs { configs ->
|
||||||
val config = when (userConfigType) {
|
val config = when (userConfigType) {
|
||||||
UserConfigType.CONTACTS -> configs.contacts
|
UserConfigType.CONTACTS -> configs.contacts
|
||||||
UserConfigType.USER_PROFILE -> configs.userProfile
|
UserConfigType.USER_PROFILE -> configs.userProfile
|
||||||
@ -171,22 +176,42 @@ class ConfigFactory @Inject constructor(
|
|||||||
UserConfigType.USER_GROUPS -> configs.userGroups
|
UserConfigType.USER_GROUPS -> configs.userGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge the list of config messages, we'll be told which messages have been merged
|
||||||
|
// and we will then find out which message has the max timestamp
|
||||||
val maxTimestamp = config.merge(messages.map { it.hash to it.data }.toTypedArray())
|
val maxTimestamp = config.merge(messages.map { it.hash to it.data }.toTypedArray())
|
||||||
.asSequence()
|
.asSequence()
|
||||||
.mapNotNull { hash -> messages.firstOrNull { it.hash == hash } }
|
.mapNotNull { hash -> messages.firstOrNull { it.hash == hash } }
|
||||||
.maxOfOrNull { it.timestamp }
|
.maxOfOrNull { it.timestamp }
|
||||||
|
|
||||||
Unit to maxTimestamp?.let(ConfigUpdateNotification::UserConfigsMerged)
|
maxTimestamp?.let {
|
||||||
|
(config.dump() to it) to
|
||||||
|
listOf(ConfigUpdateNotification.UserConfigsMerged(userConfigType, it))
|
||||||
|
} ?: (null to emptyList())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump now regardless so we can save the timestamp to the database
|
||||||
|
if (toDump != null) {
|
||||||
|
val (dump, timestamp) = toDump
|
||||||
|
configDatabase.storeConfig(
|
||||||
|
variant = userConfigType.configVariant,
|
||||||
|
publicKey = requiresCurrentUserAccountId().hexString,
|
||||||
|
data = dump,
|
||||||
|
timestamp = timestamp
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T> withMutableUserConfigs(cb: (MutableUserConfigs) -> T): T {
|
override fun <T> withMutableUserConfigs(cb: (MutableUserConfigs) -> T): T {
|
||||||
return doWithMutableUserConfigs {
|
return doWithMutableUserConfigs {
|
||||||
val result = cb(it)
|
val result = cb(it)
|
||||||
val changed = if (it.persistIfDirty(clock)) {
|
|
||||||
ConfigUpdateNotification.UserConfigsModified
|
val changed = if (it.userGroups.dirty() ||
|
||||||
|
it.convoInfoVolatile.dirty() ||
|
||||||
|
it.userProfile.dirty() ||
|
||||||
|
it.contacts.dirty()) {
|
||||||
|
listOf(ConfigUpdateNotification.UserConfigsModified)
|
||||||
} else {
|
} else {
|
||||||
null
|
emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
result to changed
|
result to changed
|
||||||
@ -293,15 +318,30 @@ class ConfigFactory @Inject constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
doWithMutableUserConfigs { configs ->
|
// Confirm push for the configs and gather the dumped data to be saved into the db.
|
||||||
contacts?.let { (push, result) -> configs.contacts.confirmPushed(push.seqNo, result.hash) }
|
// For this operation, we will no notify the users as there won't be any real change in terms
|
||||||
userProfile?.let { (push, result) -> configs.userProfile.confirmPushed(push.seqNo, result.hash) }
|
// of the displaying data.
|
||||||
convoInfoVolatile?.let { (push, result) -> configs.convoInfoVolatile.confirmPushed(push.seqNo, result.hash) }
|
val dump = doWithMutableUserConfigs { configs ->
|
||||||
userGroups?.let { (push, result) -> configs.userGroups.confirmPushed(push.seqNo, result.hash) }
|
sequenceOf(contacts, userProfile, convoInfoVolatile, userGroups)
|
||||||
|
.zip(
|
||||||
|
sequenceOf(
|
||||||
|
UserConfigType.CONTACTS to configs.contacts,
|
||||||
|
UserConfigType.USER_PROFILE to configs.userProfile,
|
||||||
|
UserConfigType.CONVO_INFO_VOLATILE to configs.convoInfoVolatile,
|
||||||
|
UserConfigType.USER_GROUPS to configs.userGroups
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.filter { (push, _) -> push != null }
|
||||||
|
.onEach { (push, config) -> config.second.confirmPushed(push!!.first.seqNo, push.second.hash) }
|
||||||
|
.map { (push, config) ->
|
||||||
|
Triple(config.first.configVariant, config.second.dump(), push!!.second.timestamp)
|
||||||
|
}.toList() to emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
configs.persistIfDirty(clock)
|
// We need to persist the data to the database to save timestamp after the push
|
||||||
|
val userAccountId = requiresCurrentUserAccountId()
|
||||||
Unit to null
|
for ((variant, data, timestamp) in dump) {
|
||||||
|
configDatabase.storeConfig(variant, userAccountId.hexString, data, timestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,18 +369,6 @@ class ConfigFactory @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getConfigTimestamp(forConfigObject: ConfigBase, publicKey: String): Long {
|
|
||||||
val variant = when (forConfigObject) {
|
|
||||||
is UserProfile -> SharedConfigMessage.Kind.USER_PROFILE.name
|
|
||||||
is Contacts -> SharedConfigMessage.Kind.CONTACTS.name
|
|
||||||
is ConversationVolatileConfig -> SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name
|
|
||||||
is UserGroupsConfig -> SharedConfigMessage.Kind.GROUPS.name
|
|
||||||
else -> throw UnsupportedOperationException("Can't support type of ${forConfigObject::class.simpleName} yet")
|
|
||||||
}
|
|
||||||
|
|
||||||
return configDatabase.retrieveConfigLastUpdateTimestamp(variant, publicKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun conversationInConfig(
|
override fun conversationInConfig(
|
||||||
publicKey: String?,
|
publicKey: String?,
|
||||||
groupPublicKey: String?,
|
groupPublicKey: String?,
|
||||||
@ -391,6 +419,10 @@ class ConfigFactory @Inject constructor(
|
|||||||
return (changeTimestampMs >= (lastUpdateTimestampMs - CONFIG_CHANGE_BUFFER_PERIOD))
|
return (changeTimestampMs >= (lastUpdateTimestampMs - CONFIG_CHANGE_BUFFER_PERIOD))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getConfigTimestamp(userConfigType: UserConfigType, publicKey: String): Long {
|
||||||
|
return configDatabase.retrieveConfigLastUpdateTimestamp(userConfigType.configVariant, publicKey)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getGroupAuth(groupId: AccountId): SwarmAuth? {
|
override fun getGroupAuth(groupId: AccountId): SwarmAuth? {
|
||||||
val (adminKey, authData) = withUserConfigs {
|
val (adminKey, authData) = withUserConfigs {
|
||||||
val group = it.userGroups.getClosedGroup(groupId.hexString)
|
val group = it.userGroups.getClosedGroup(groupId.hexString)
|
||||||
@ -441,6 +473,14 @@ class ConfigFactory @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val UserConfigType.configVariant: ConfigVariant
|
||||||
|
get() = when (this) {
|
||||||
|
UserConfigType.CONTACTS -> ConfigDatabase.CONTACTS_VARIANT
|
||||||
|
UserConfigType.USER_PROFILE -> ConfigDatabase.USER_PROFILE_VARIANT
|
||||||
|
UserConfigType.CONVO_INFO_VOLATILE -> ConfigDatabase.CONVO_INFO_VARIANT
|
||||||
|
UserConfigType.USER_GROUPS -> ConfigDatabase.USER_GROUPS_VARIANT
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sync group data from our local database
|
* Sync group data from our local database
|
||||||
*/
|
*/
|
||||||
@ -639,30 +679,6 @@ private class UserConfigsImpl(
|
|||||||
convoInfoVolatile.initFrom(storage, threadDb)
|
convoInfoVolatile.initFrom(storage, threadDb)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Persists the config if it is dirty and returns the list of classes that were persisted
|
|
||||||
*/
|
|
||||||
fun persistIfDirty(clock: SnodeClock): Boolean {
|
|
||||||
return sequenceOf(
|
|
||||||
contacts to ConfigDatabase.CONTACTS_VARIANT,
|
|
||||||
userGroups to ConfigDatabase.USER_GROUPS_VARIANT,
|
|
||||||
userProfile to ConfigDatabase.USER_PROFILE_VARIANT,
|
|
||||||
convoInfoVolatile to ConfigDatabase.CONVO_INFO_VARIANT
|
|
||||||
).fold(false) { acc, (config, variant) ->
|
|
||||||
if (config.needsDump()) {
|
|
||||||
configDatabase.storeConfig(
|
|
||||||
variant = variant,
|
|
||||||
publicKey = userAccountId.hexString,
|
|
||||||
data = config.dump(),
|
|
||||||
timestamp = clock.currentTimeMills()
|
|
||||||
)
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
acc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GroupConfigsImpl(
|
private class GroupConfigsImpl(
|
||||||
|
@ -35,6 +35,7 @@ import org.session.libsession.messaging.sending_receiving.handleVisibleMessage
|
|||||||
import org.session.libsession.messaging.utilities.Data
|
import org.session.libsession.messaging.utilities.Data
|
||||||
import org.session.libsession.messaging.utilities.SodiumUtilities
|
import org.session.libsession.messaging.utilities.SodiumUtilities
|
||||||
import org.session.libsession.utilities.SSKEnvironment
|
import org.session.libsession.utilities.SSKEnvironment
|
||||||
|
import org.session.libsession.utilities.UserConfigType
|
||||||
import org.session.libsignal.protos.UtilProtos
|
import org.session.libsignal.protos.UtilProtos
|
||||||
import org.session.libsignal.utilities.AccountId
|
import org.session.libsignal.utilities.AccountId
|
||||||
import org.session.libsignal.utilities.IdPrefix
|
import org.session.libsignal.utilities.IdPrefix
|
||||||
@ -103,24 +104,23 @@ class BatchMessageReceiveJob(
|
|||||||
executeAsync(dispatcherName)
|
executeAsync(dispatcherName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isHidden(message: Message): Boolean{
|
private fun isHidden(message: Message): Boolean {
|
||||||
// if the contact is marked as hidden for 1on1 messages
|
// if the contact is marked as hidden for 1on1 messages
|
||||||
// and the message's sentTimestamp is earlier than the sentTimestamp of the last config
|
// and the message's sentTimestamp is earlier than the sentTimestamp of the last config
|
||||||
val config = MessagingModuleConfiguration.shared.configFactory
|
val configFactory = MessagingModuleConfiguration.shared.configFactory
|
||||||
val publicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey()
|
val publicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey()
|
||||||
if(config.contacts == null || message.sentTimestamp == null || publicKey == null) return false
|
if (message.sentTimestamp == null || publicKey == null) return false
|
||||||
val contactConfigTimestamp = config.getConfigTimestamp(config.contacts!!, publicKey)
|
|
||||||
if(message.groupPublicKey == null && // not a group
|
val contactConfigTimestamp = configFactory.getConfigTimestamp(UserConfigType.CONTACTS, publicKey)
|
||||||
|
|
||||||
|
return configFactory.withUserConfigs { configs ->
|
||||||
|
message.groupPublicKey == null && // not a group
|
||||||
message.openGroupServerMessageID == null && // not a community
|
message.openGroupServerMessageID == null && // not a community
|
||||||
// not marked as hidden
|
// not marked as hidden
|
||||||
config.contacts?.get(message.senderOrSync)?.priority == ConfigBase.PRIORITY_HIDDEN &&
|
configs.contacts.get(message.senderOrSync)?.priority == ConfigBase.PRIORITY_HIDDEN &&
|
||||||
// the message's sentTimestamp is earlier than the sentTimestamp of the last config
|
// the message's sentTimestamp is earlier than the sentTimestamp of the last config
|
||||||
message.sentTimestamp!! < contactConfigTimestamp
|
message.sentTimestamp!! < contactConfigTimestamp
|
||||||
) {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun executeAsync(dispatcherName: String) {
|
suspend fun executeAsync(dispatcherName: String) {
|
||||||
|
@ -5,7 +5,6 @@ import kotlinx.coroutines.flow.filter
|
|||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.onStart
|
import kotlinx.coroutines.flow.onStart
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import network.loki.messenger.libsession_util.ConfigBase
|
|
||||||
import network.loki.messenger.libsession_util.MutableConfig
|
import network.loki.messenger.libsession_util.MutableConfig
|
||||||
import network.loki.messenger.libsession_util.MutableContacts
|
import network.loki.messenger.libsession_util.MutableContacts
|
||||||
import network.loki.messenger.libsession_util.MutableConversationVolatileConfig
|
import network.loki.messenger.libsession_util.MutableConversationVolatileConfig
|
||||||
@ -196,8 +195,18 @@ interface MutableGroupConfigs : GroupConfigs {
|
|||||||
|
|
||||||
|
|
||||||
sealed interface ConfigUpdateNotification {
|
sealed interface ConfigUpdateNotification {
|
||||||
|
/**
|
||||||
|
* The user configs have been modified locally.
|
||||||
|
*/
|
||||||
data object UserConfigsModified : ConfigUpdateNotification
|
data object UserConfigsModified : ConfigUpdateNotification
|
||||||
data class UserConfigsMerged(val timestamp: Long) : ConfigUpdateNotification
|
|
||||||
|
/**
|
||||||
|
* The user configs have been merged from the server.
|
||||||
|
*/
|
||||||
|
data class UserConfigsMerged(
|
||||||
|
val configType: UserConfigType,
|
||||||
|
val timestamp: Long
|
||||||
|
) : ConfigUpdateNotification
|
||||||
|
|
||||||
data class GroupConfigsUpdated(val groupId: AccountId) : ConfigUpdateNotification
|
data class GroupConfigsUpdated(val groupId: AccountId) : ConfigUpdateNotification
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user