mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-18 03:08:26 +00:00
feat: add basic message read logic for synchronizing last reads, need to modify the query to use the last seen instead of the unread count in a subquery possibly for thread display record
This commit is contained in:
parent
03a343d832
commit
2f2ebe9451
@ -40,6 +40,7 @@ import org.session.libsession.messaging.sending_receiving.pollers.ClosedGroupPol
|
||||
import org.session.libsession.messaging.sending_receiving.pollers.Poller;
|
||||
import org.session.libsession.snode.SnodeModule;
|
||||
import org.session.libsession.utilities.Address;
|
||||
import org.session.libsession.utilities.ConfigFactoryUpdateListener;
|
||||
import org.session.libsession.utilities.ProfilePictureUtilities;
|
||||
import org.session.libsession.utilities.SSKEnvironment;
|
||||
import org.session.libsession.utilities.TextSecurePreferences;
|
||||
@ -115,6 +116,7 @@ import dagger.hilt.android.HiltAndroidApp;
|
||||
import kotlin.Unit;
|
||||
import kotlinx.coroutines.Job;
|
||||
import network.loki.messenger.BuildConfig;
|
||||
import network.loki.messenger.libsession_util.ConfigBase;
|
||||
|
||||
/**
|
||||
* Will be called once when the TextSecure process is created.
|
||||
@ -125,7 +127,7 @@ import network.loki.messenger.BuildConfig;
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
@HiltAndroidApp
|
||||
public class ApplicationContext extends Application implements DefaultLifecycleObserver {
|
||||
public class ApplicationContext extends Application implements DefaultLifecycleObserver, ConfigFactoryUpdateListener {
|
||||
|
||||
public static final String PREFERENCES_NAME = "SecureSMS-Preferences";
|
||||
|
||||
@ -199,6 +201,11 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
|
||||
return this.persistentLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyUpdates(@NonNull ConfigBase forConfigObject) {
|
||||
// forward to the config factory / storage ig
|
||||
storage.notifyConfigUpdates(forConfigObject);
|
||||
}
|
||||
@Override
|
||||
public void onCreate() {
|
||||
DatabaseModule.init(this);
|
||||
|
@ -399,6 +399,13 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa
|
||||
database.update(TABLE_NAME, contentValues, ID_WHERE, arrayOf(id.toString()))
|
||||
}
|
||||
|
||||
fun setMessagesRead(threadId: Long, beforeTime: Long): List<MarkedMessageInfo> {
|
||||
return setMessagesRead(
|
||||
THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1) AND " + DATE_RECEIVED + " <= ?",
|
||||
arrayOf(threadId.toString(), beforeTime.toString())
|
||||
)
|
||||
}
|
||||
|
||||
fun setMessagesRead(threadId: Long): List<MarkedMessageInfo> {
|
||||
return setMessagesRead(
|
||||
THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1)",
|
||||
|
@ -321,6 +321,9 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
public List<MarkedMessageInfo> setMessagesRead(long threadId, long beforeTime) {
|
||||
return setMessagesRead(THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1) AND " + DATE_RECEIVED + " <= ?", new String[]{threadId+"", beforeTime+""});
|
||||
}
|
||||
public List<MarkedMessageInfo> setMessagesRead(long threadId) {
|
||||
return setMessagesRead(THREAD_ID + " = ? AND (" + READ + " = 0 OR " + REACTIONS_UNREAD + " = 1)", new String[] {String.valueOf(threadId)});
|
||||
}
|
||||
|
@ -2,6 +2,11 @@ package org.thoughtcrime.securesms.database
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import network.loki.messenger.libsession_util.ConfigBase
|
||||
import network.loki.messenger.libsession_util.Contacts
|
||||
import network.loki.messenger.libsession_util.ConversationVolatileConfig
|
||||
import network.loki.messenger.libsession_util.UserProfile
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import org.session.libsession.avatars.AvatarHelper
|
||||
import org.session.libsession.database.StorageProtocol
|
||||
import org.session.libsession.messaging.BlindedIdMapping
|
||||
@ -52,21 +57,26 @@ import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.session.libsignal.crypto.ecc.ECKeyPair
|
||||
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
||||
import org.session.libsignal.messages.SignalServiceGroup
|
||||
import org.session.libsignal.utilities.Base64
|
||||
import org.session.libsignal.utilities.IdPrefix
|
||||
import org.session.libsignal.utilities.KeyHelper
|
||||
import org.session.libsignal.utilities.Log
|
||||
import org.session.libsignal.utilities.guava.Optional
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.ReactionRecord
|
||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||
import org.thoughtcrime.securesms.groups.OpenGroupManager
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority
|
||||
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||
import org.thoughtcrime.securesms.util.SessionMetaProtocol
|
||||
import java.security.MessageDigest
|
||||
import network.loki.messenger.libsession_util.util.Contact as LibSessionContact
|
||||
|
||||
class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, helper), StorageProtocol {
|
||||
class Storage(context: Context, helper: SQLCipherOpenHelper, private val configFactory: ConfigFactory) : Database(context, helper), StorageProtocol {
|
||||
|
||||
override fun getUserPublicKey(): String? {
|
||||
return TextSecurePreferences.getLocalNumber(context)
|
||||
@ -262,6 +272,81 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
return DatabaseComponent.get(context).lokiAPIDatabase().getAuthToken(id)
|
||||
}
|
||||
|
||||
override fun notifyConfigUpdates(forConfigObject: ConfigBase) {
|
||||
notifyUpdates(forConfigObject)
|
||||
}
|
||||
|
||||
fun notifyUpdates(forConfigObject: ConfigBase) {
|
||||
when (forConfigObject) {
|
||||
is UserProfile -> updateUser(forConfigObject)
|
||||
is Contacts -> updateContacts(forConfigObject)
|
||||
is ConversationVolatileConfig -> updateConvoVolatile(forConfigObject)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateUser(userProfile: UserProfile) {
|
||||
val userPublicKey = getUserPublicKey() ?: return
|
||||
// would love to get rid of recipient and context from this
|
||||
val recipient = Recipient.from(context, fromSerialized(userPublicKey), false)
|
||||
// update name
|
||||
val name = userProfile.getName() ?: return
|
||||
val userPic = userProfile.getPic()
|
||||
val profileManager = SSKEnvironment.shared.profileManager
|
||||
if (name.isNotEmpty()) {
|
||||
TextSecurePreferences.setProfileName(context, name)
|
||||
profileManager.setName(context, recipient, name)
|
||||
}
|
||||
|
||||
// update pfp
|
||||
if (userPic == null) {
|
||||
// clear picture if userPic is null
|
||||
TextSecurePreferences.setProfileKey(context, null)
|
||||
ProfileKeyUtil.setEncodedProfileKey(context, null)
|
||||
profileManager.setProfileKey(context, recipient, null)
|
||||
setUserProfilePictureURL(null)
|
||||
} else if (userPic.key.isNotEmpty() && userPic.url.isNotEmpty()
|
||||
&& TextSecurePreferences.getProfilePictureURL(context) != userPic.url) {
|
||||
val profileKey = Base64.encodeBytes(userPic.key)
|
||||
ProfileKeyUtil.setEncodedProfileKey(context, profileKey)
|
||||
profileManager.setProfileKey(context, recipient, userPic.key)
|
||||
setUserProfilePictureURL(userPic.url)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateContacts(contacts: Contacts) {
|
||||
val extracted = contacts.all().toList()
|
||||
extracted.forEach { contact ->
|
||||
val address = Address.fromSerialized(contact.id)
|
||||
val settings = getRecipientSettings(address) ?: run {
|
||||
// new contact, store it
|
||||
}
|
||||
contact.name
|
||||
contact.approved
|
||||
contact.approvedMe
|
||||
contact.blocked
|
||||
contact.nickname
|
||||
contact.profilePicture
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateConvoVolatile(convos: ConversationVolatileConfig) {
|
||||
val extracted = convos.all()
|
||||
for (conversation in extracted) {
|
||||
val threadId = when (conversation) {
|
||||
is Conversation.OneToOne -> conversation.sessionId.let {
|
||||
getOrCreateThreadIdFor(fromSerialized(it))
|
||||
}
|
||||
is Conversation.LegacyClosedGroup -> conversation.groupId.let {
|
||||
getOrCreateThreadIdFor("", it,null)
|
||||
}
|
||||
is Conversation.OpenGroup -> conversation.baseUrl.let {
|
||||
getOrCreateThreadIdFor("",null, it)
|
||||
}
|
||||
}
|
||||
Log.d("Loki-DBG", "Should update thread $threadId")
|
||||
}
|
||||
}
|
||||
|
||||
override fun setAuthToken(room: String, server: String, newValue: String) {
|
||||
val id = "$server.$room"
|
||||
DatabaseComponent.get(context).lokiAPIDatabase().setAuthToken(id, newValue)
|
||||
@ -455,6 +540,12 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
|
||||
override fun createGroup(groupId: String, title: String?, members: List<Address>, avatar: SignalServiceAttachmentPointer?, relay: String?, admins: List<Address>, formationTimestamp: Long) {
|
||||
DatabaseComponent.get(context).groupDatabase().create(groupId, title, members, avatar, relay, admins, formationTimestamp)
|
||||
val volatiles = configFactory.convoVolatile ?: return
|
||||
val groupPublicKey = GroupUtil.doubleDecodeGroupId(groupId)
|
||||
val groupVolatileConfig = volatiles.getOrConstructLegacyClosedGroup(groupPublicKey)
|
||||
groupVolatileConfig.lastRead = formationTimestamp
|
||||
volatiles.set(groupVolatileConfig)
|
||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
||||
}
|
||||
|
||||
override fun isGroupActive(groupPublicKey: String): Boolean {
|
||||
@ -660,6 +751,25 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
|
||||
return if (recipientSettings.isPresent) { recipientSettings.get() } else null
|
||||
}
|
||||
|
||||
override fun addLibSessionContacts(contacts: List<LibSessionContact>) {
|
||||
val recipientDatabase = DatabaseComponent.get(context).recipientDatabase()
|
||||
val threadDatabase = DatabaseComponent.get(context).threadDatabase()
|
||||
val mappingDb = DatabaseComponent.get(context).blindedIdMappingDatabase()
|
||||
val moreContacts = contacts.filter { contact ->
|
||||
val id = SessionId(contact.id)
|
||||
id.prefix != IdPrefix.BLINDED || mappingDb.getBlindedIdMapping(contact.id).none { it.sessionId != null }
|
||||
}
|
||||
for (contact in moreContacts) {
|
||||
val address = fromSerialized(contact.id)
|
||||
val recipient = Recipient.from(context, address, true)
|
||||
val (url, key) = contact.profilePicture?.let { it.url to it.key } ?: (null to null)
|
||||
// set or clear the avatar
|
||||
recipientDatabase.setProfileAvatar(recipient, url)
|
||||
recipientDatabase.setProfileKey(recipient, key)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun addContacts(contacts: List<ConfigurationMessage.Contact>) {
|
||||
val recipientDatabase = DatabaseComponent.get(context).recipientDatabase()
|
||||
val threadDatabase = DatabaseComponent.get(context).threadDatabase()
|
||||
|
@ -295,6 +295,27 @@ public class ThreadDatabase extends Database {
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
public List<MarkedMessageInfo> setRead(long threadId, long lastReadTime) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(READ, 1);
|
||||
contentValues.put(UNREAD_COUNT, 0);
|
||||
contentValues.put(UNREAD_MENTION_COUNT, 0);
|
||||
contentValues.put(LAST_SEEN, lastReadTime);
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""});
|
||||
|
||||
final List<MarkedMessageInfo> smsRecords = DatabaseComponent.get(context).smsDatabase().setMessagesRead(threadId, lastReadTime);
|
||||
final List<MarkedMessageInfo> mmsRecords = DatabaseComponent.get(context).mmsDatabase().setMessagesRead(threadId, lastReadTime);
|
||||
|
||||
notifyConversationListListeners();
|
||||
|
||||
return new LinkedList<MarkedMessageInfo>() {{
|
||||
addAll(smsRecords);
|
||||
addAll(mmsRecords);
|
||||
}};
|
||||
}
|
||||
|
||||
public List<MarkedMessageInfo> setRead(long threadId, boolean lastSeen) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(READ, 1);
|
||||
|
@ -5,21 +5,14 @@ import network.loki.messenger.libsession_util.ConfigBase
|
||||
import network.loki.messenger.libsession_util.Contacts
|
||||
import network.loki.messenger.libsession_util.ConversationVolatileConfig
|
||||
import network.loki.messenger.libsession_util.UserProfile
|
||||
import org.session.libsession.database.StorageProtocol
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.ConfigFactoryProtocol
|
||||
import org.session.libsession.utilities.ProfileKeyUtil
|
||||
import org.session.libsession.utilities.SSKEnvironment
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsession.utilities.recipients.Recipient
|
||||
import org.session.libsession.utilities.ConfigFactoryUpdateListener
|
||||
import org.session.libsignal.protos.SignalServiceProtos.SharedConfigMessage
|
||||
import org.session.libsignal.utilities.Base64
|
||||
import org.thoughtcrime.securesms.database.ConfigDatabase
|
||||
import java.util.concurrent.ConcurrentSkipListSet
|
||||
|
||||
class ConfigFactory(private val context: Context,
|
||||
private val configDatabase: ConfigDatabase,
|
||||
private val storage: StorageProtocol,
|
||||
private val maybeGetUserInfo: ()->Pair<ByteArray, String>?):
|
||||
ConfigFactoryProtocol {
|
||||
|
||||
@ -42,6 +35,10 @@ class ConfigFactory(private val context: Context,
|
||||
private var _convoVolatileConfig: ConversationVolatileConfig? = null
|
||||
private val convoHashes = ConcurrentSkipListSet<String>()
|
||||
|
||||
private val listeners: MutableList<ConfigFactoryUpdateListener> = mutableListOf()
|
||||
fun registerListener(listener: ConfigFactoryUpdateListener) { listeners += listener }
|
||||
fun unregisterListener(listener: ConfigFactoryUpdateListener) { listeners -= listener }
|
||||
|
||||
override val user: UserProfile? = synchronized(userLock) {
|
||||
if (_userConfig == null) {
|
||||
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
|
||||
@ -115,6 +112,9 @@ class ConfigFactory(private val context: Context,
|
||||
is Contacts -> persistContactsConfigDump()
|
||||
is ConversationVolatileConfig -> persistConvoVolatileConfigDump()
|
||||
}
|
||||
listeners.forEach { listener ->
|
||||
listener.notifyUpdates(forConfigObject)
|
||||
}
|
||||
}
|
||||
|
||||
override fun appendHash(configObject: ConfigBase, hash: String) {
|
||||
@ -125,14 +125,6 @@ class ConfigFactory(private val context: Context,
|
||||
}
|
||||
}
|
||||
|
||||
override fun notifyUpdates(forConfigObject: ConfigBase) {
|
||||
when (forConfigObject) {
|
||||
is UserProfile -> updateUser(forConfigObject)
|
||||
is Contacts -> updateContacts(forConfigObject)
|
||||
is ConversationVolatileConfig -> updateConvoVolatile(forConfigObject)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getHashesFor(forConfigObject: ConfigBase): List<String> =
|
||||
when (forConfigObject) {
|
||||
is UserProfile -> userHashes.toList()
|
||||
@ -147,42 +139,4 @@ class ConfigFactory(private val context: Context,
|
||||
is ConversationVolatileConfig -> convoHashes.removeAll(deletedHashes)
|
||||
}
|
||||
|
||||
private fun updateUser(userProfile: UserProfile) {
|
||||
val (_, userPublicKey) = maybeGetUserInfo() ?: return
|
||||
// would love to get rid of recipient and context from this
|
||||
val recipient = Recipient.from(context, Address.fromSerialized(userPublicKey), false)
|
||||
// update name
|
||||
val name = userProfile.getName() ?: return
|
||||
val userPic = userProfile.getPic()
|
||||
val profileManager = SSKEnvironment.shared.profileManager
|
||||
if (name.isNotEmpty()) {
|
||||
TextSecurePreferences.setProfileName(context, name)
|
||||
profileManager.setName(context, recipient, name)
|
||||
}
|
||||
|
||||
// update pfp
|
||||
if (userPic == null) {
|
||||
// clear picture if userPic is null
|
||||
TextSecurePreferences.setProfileKey(context, null)
|
||||
ProfileKeyUtil.setEncodedProfileKey(context, null)
|
||||
profileManager.setProfileKey(context, recipient, null)
|
||||
storage.setUserProfilePictureURL(null)
|
||||
} else if (userPic.key.isNotEmpty() && userPic.url.isNotEmpty()
|
||||
&& TextSecurePreferences.getProfilePictureURL(context) != userPic.url) {
|
||||
val profileKey = Base64.encodeBytes(userPic.key)
|
||||
ProfileKeyUtil.setEncodedProfileKey(context, profileKey)
|
||||
profileManager.setProfileKey(context, recipient, userPic.key)
|
||||
storage.setUserProfilePictureURL(userPic.url)
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateContacts(contacts: Contacts) {
|
||||
|
||||
}
|
||||
|
||||
private fun updateConvoVolatile(convos: ConversationVolatileConfig) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -6,7 +6,6 @@ import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
import org.session.libsession.database.MessageDataProvider
|
||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachmentProvider
|
||||
import org.thoughtcrime.securesms.crypto.AttachmentSecret
|
||||
@ -136,7 +135,7 @@ object DatabaseModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideStorage(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper) = Storage(context,openHelper)
|
||||
fun provideStorage(@ApplicationContext context: Context, openHelper: SQLCipherOpenHelper, configFactory: ConfigFactory) = Storage(context,openHelper, configFactory)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
|
@ -6,10 +6,10 @@ import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import org.session.libsession.utilities.ConfigFactoryUpdateListener
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.crypto.KeyPairUtilities
|
||||
import org.thoughtcrime.securesms.database.ConfigDatabase
|
||||
import org.thoughtcrime.securesms.database.Storage
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@ -23,12 +23,14 @@ object SessionUtilModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideConfigFactory(@ApplicationContext context: Context, configDatabase: ConfigDatabase, storage: Storage): ConfigFactory =
|
||||
ConfigFactory(context, configDatabase, storage) {
|
||||
fun provideConfigFactory(@ApplicationContext context: Context, configDatabase: ConfigDatabase): ConfigFactory =
|
||||
ConfigFactory(context, configDatabase) {
|
||||
val localUserPublicKey = TextSecurePreferences.getLocalNumber(context)
|
||||
val secretKey = maybeUserEdSecretKey(context)
|
||||
if (localUserPublicKey == null || secretKey == null) null
|
||||
else secretKey to localUserPublicKey
|
||||
}.apply {
|
||||
registerListener(context as ConfigFactoryUpdateListener)
|
||||
}
|
||||
|
||||
}
|
@ -213,6 +213,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
}
|
||||
val compoundPromise = all(promises)
|
||||
compoundPromise.successUi { // Do this on the UI thread so that it happens before the alwaysUi clause below
|
||||
val userConfig = configFactory.user
|
||||
if (isUpdatingProfilePicture && profilePicture != null) {
|
||||
AvatarHelper.setAvatar(this, Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)!!), profilePicture)
|
||||
TextSecurePreferences.setProfileAvatarId(this, SecureRandom().nextInt())
|
||||
@ -220,11 +221,14 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
// new config
|
||||
val url = TextSecurePreferences.getProfilePictureURL(this)
|
||||
val profileKey = ProfileKeyUtil.getProfileKey(this)
|
||||
if (!url.isNullOrEmpty() && !profileKey.isEmpty()) {
|
||||
configFactory.user?.setPic(UserPic(url, profileKey))
|
||||
if (!url.isNullOrEmpty() && profileKey.isNotEmpty()) {
|
||||
userConfig?.setPic(UserPic(url, profileKey))
|
||||
}
|
||||
}
|
||||
if (profilePicture != null || displayName != null) {
|
||||
if (userConfig != null && userConfig.needsDump()) {
|
||||
configFactory.persist(userConfig)
|
||||
}
|
||||
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(this@SettingsActivity)
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.database.SmsDatabase
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
@ -83,7 +84,8 @@ class DefaultConversationRepository @Inject constructor(
|
||||
private val mmsSmsDb: MmsSmsDatabase,
|
||||
private val recipientDb: RecipientDatabase,
|
||||
private val lokiMessageDb: LokiMessageDatabase,
|
||||
private val sessionJobDb: SessionJobDatabase
|
||||
private val sessionJobDb: SessionJobDatabase,
|
||||
private val configFactory: ConfigFactory
|
||||
) : ConversationRepository {
|
||||
|
||||
override fun maybeGetRecipientForThreadId(threadId: Long): Recipient? {
|
||||
|
@ -2,6 +2,7 @@ package org.session.libsession.database
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import network.loki.messenger.libsession_util.ConfigBase
|
||||
import org.session.libsession.messaging.BlindedIdMapping
|
||||
import org.session.libsession.messaging.calls.CallMessageType
|
||||
import org.session.libsession.messaging.contacts.Contact
|
||||
@ -31,6 +32,7 @@ import org.session.libsession.utilities.recipients.Recipient.RecipientSettings
|
||||
import org.session.libsignal.crypto.ecc.ECKeyPair
|
||||
import org.session.libsignal.messages.SignalServiceAttachmentPointer
|
||||
import org.session.libsignal.messages.SignalServiceGroup
|
||||
import network.loki.messenger.libsession_util.util.Contact as LibSessionContact
|
||||
|
||||
interface StorageProtocol {
|
||||
|
||||
@ -164,6 +166,7 @@ interface StorageProtocol {
|
||||
fun setContact(contact: Contact)
|
||||
fun getRecipientForThread(threadId: Long): Recipient?
|
||||
fun getRecipientSettings(address: Address): RecipientSettings?
|
||||
fun addLibSessionContacts(contacts: List<LibSessionContact>)
|
||||
fun addContacts(contacts: List<ConfigurationMessage.Contact>)
|
||||
|
||||
// Attachments
|
||||
@ -202,4 +205,7 @@ interface StorageProtocol {
|
||||
fun deleteReactions(messageId: Long, mms: Boolean)
|
||||
fun unblock(toUnblock: List<Recipient>)
|
||||
fun blockedContacts(): List<Recipient>
|
||||
|
||||
// Shared configs
|
||||
fun notifyConfigUpdates(forConfigObject: ConfigBase)
|
||||
}
|
||||
|
@ -161,7 +161,6 @@ class Poller(private val configFactory: ConfigFactoryProtocol) {
|
||||
}
|
||||
// process new results
|
||||
configFactory.persist(forConfigObject)
|
||||
configFactory.notifyUpdates(forConfigObject)
|
||||
}
|
||||
|
||||
private fun poll(snode: Snode, deferred: Deferred<Unit, Exception>): Promise<Unit, Exception> {
|
||||
|
@ -11,7 +11,10 @@ interface ConfigFactoryProtocol {
|
||||
val convoVolatile: ConversationVolatileConfig?
|
||||
fun persist(forConfigObject: ConfigBase)
|
||||
fun appendHash(configObject: ConfigBase, hash: String)
|
||||
fun notifyUpdates(forConfigObject: ConfigBase)
|
||||
fun getHashesFor(forConfigObject: ConfigBase): List<String>
|
||||
fun removeHashesFor(config: ConfigBase, deletedHashes: Set<String>): Boolean
|
||||
}
|
||||
|
||||
interface ConfigFactoryUpdateListener {
|
||||
fun notifyUpdates(forConfigObject: ConfigBase)
|
||||
}
|
@ -3,7 +3,6 @@ package org.session.libsession.utilities
|
||||
import org.session.libsignal.messages.SignalServiceGroup
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import java.io.IOException
|
||||
import kotlin.jvm.Throws
|
||||
|
||||
object GroupUtil {
|
||||
const val CLOSED_GROUP_PREFIX = "__textsecure_group__!"
|
||||
@ -97,4 +96,10 @@ object GroupUtil {
|
||||
fun doubleDecodeGroupID(groupID: String): ByteArray {
|
||||
return getDecodedGroupIDAsData(getDecodedGroupID(groupID))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@Throws(IOException::class)
|
||||
fun doubleDecodeGroupId(groupID: String): String {
|
||||
return Hex.toStringCondensed(getDecodedGroupIDAsData(getDecodedGroupID(groupID)))
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user