mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-18 02:58:27 +00:00
feat: add basic contact logic for setting local contact state. Need to implement handling properly
This commit is contained in:
parent
164810e533
commit
8a000fe5a9
@ -390,7 +390,7 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializeProfileManager() {
|
private void initializeProfileManager() {
|
||||||
this.profileManager = new ProfileManager();
|
this.profileManager = new ProfileManager(this, configFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeTypingStatusSender() {
|
private void initializeTypingStatusSender() {
|
||||||
|
@ -420,7 +420,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
// only update the conversation every 3 seconds maximum
|
// only update the conversation every 3 seconds maximum
|
||||||
// channel is rendezvous and shouldn't block on try send calls as often as we want
|
// channel is rendezvous and shouldn't block on try send calls as often as we want
|
||||||
val bufferedFlow = bufferedLastSeenChannel.consumeAsFlow()
|
val bufferedFlow = bufferedLastSeenChannel.consumeAsFlow()
|
||||||
.debounce(3.seconds)
|
.debounce(1.seconds)
|
||||||
bufferedFlow.collectLatest {
|
bufferedFlow.collectLatest {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
storage.markConversationAsRead(viewModel.threadId, SnodeAPI.nowWithOffset)
|
storage.markConversationAsRead(viewModel.threadId, SnodeAPI.nowWithOffset)
|
||||||
@ -496,6 +496,10 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
handleRecyclerViewScrolled()
|
handleRecyclerViewScrolled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -951,13 +955,13 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
val wasTypingIndicatorVisibleBefore = binding.typingIndicatorViewContainer.isVisible
|
val wasTypingIndicatorVisibleBefore = binding.typingIndicatorViewContainer.isVisible
|
||||||
binding.typingIndicatorViewContainer.isVisible = wasTypingIndicatorVisibleBefore && isScrolledToBottom
|
binding.typingIndicatorViewContainer.isVisible = wasTypingIndicatorVisibleBefore && isScrolledToBottom
|
||||||
binding.typingIndicatorViewContainer.isVisible
|
binding.typingIndicatorViewContainer.isVisible
|
||||||
showOrHidScrollToBottomButton()
|
showOrHideScrollToBottomButton()
|
||||||
val firstVisiblePosition = layoutManager?.findFirstVisibleItemPosition() ?: -1
|
val firstVisiblePosition = layoutManager?.findFirstVisibleItemPosition() ?: -1
|
||||||
unreadCount = min(unreadCount, firstVisiblePosition).coerceAtLeast(0)
|
unreadCount = min(unreadCount, firstVisiblePosition).coerceAtLeast(0)
|
||||||
updateUnreadCountIndicator()
|
updateUnreadCountIndicator()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showOrHidScrollToBottomButton(show: Boolean = true) {
|
private fun showOrHideScrollToBottomButton(show: Boolean = true) {
|
||||||
binding?.scrollToBottomButton?.isVisible = show && !isScrolledToBottom && adapter.itemCount > 0
|
binding?.scrollToBottomButton?.isVisible = show && !isScrolledToBottom && adapter.itemCount > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1130,7 +1134,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
}
|
}
|
||||||
ViewUtil.hideKeyboard(this, visibleMessageView)
|
ViewUtil.hideKeyboard(this, visibleMessageView)
|
||||||
binding?.reactionsShade?.isVisible = true
|
binding?.reactionsShade?.isVisible = true
|
||||||
showOrHidScrollToBottomButton(false)
|
showOrHideScrollToBottomButton(false)
|
||||||
binding?.conversationRecyclerView?.suppressLayout(true)
|
binding?.conversationRecyclerView?.suppressLayout(true)
|
||||||
reactionDelegate.setOnActionSelectedListener(ReactionsToolbarListener(message))
|
reactionDelegate.setOnActionSelectedListener(ReactionsToolbarListener(message))
|
||||||
reactionDelegate.setOnHideListener(object: ConversationReactionOverlay.OnHideListener {
|
reactionDelegate.setOnHideListener(object: ConversationReactionOverlay.OnHideListener {
|
||||||
@ -1138,7 +1142,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
|
|||||||
binding?.reactionsShade?.let {
|
binding?.reactionsShade?.let {
|
||||||
ViewUtil.fadeOut(it, resources.getInteger(R.integer.reaction_scrubber_hide_duration), View.GONE)
|
ViewUtil.fadeOut(it, resources.getInteger(R.integer.reaction_scrubber_hide_duration), View.GONE)
|
||||||
}
|
}
|
||||||
showOrHidScrollToBottomButton(true)
|
showOrHideScrollToBottomButton(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onHide() {
|
override fun onHide() {
|
||||||
|
@ -8,6 +8,7 @@ import android.view.LayoutInflater
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import network.loki.messenger.databinding.DialogBlockedBinding
|
import network.loki.messenger.databinding.DialogBlockedBinding
|
||||||
|
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||||
import org.session.libsession.messaging.contacts.Contact
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
|
||||||
@ -35,7 +36,7 @@ class BlockedDialog(private val recipient: Recipient) : BaseDialog() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun unblock() {
|
private fun unblock() {
|
||||||
DatabaseComponent.get(requireContext()).recipientDatabase().setBlocked(recipient, false)
|
MessagingModuleConfiguration.shared.storage.setBlocked(listOf(recipient), false)
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -268,14 +268,6 @@ public class RecipientDatabase extends Database {
|
|||||||
notifyRecipientListeners();
|
notifyRecipientListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlocked(@NonNull Recipient recipient, boolean blocked) {
|
|
||||||
ContentValues values = new ContentValues();
|
|
||||||
values.put(BLOCK, blocked ? 1 : 0);
|
|
||||||
updateOrInsert(recipient.getAddress(), values);
|
|
||||||
recipient.resolve().setBlocked(blocked);
|
|
||||||
notifyRecipientListeners();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlocked(@NonNull List<Recipient> recipients, boolean blocked) {
|
public void setBlocked(@NonNull List<Recipient> recipients, boolean blocked) {
|
||||||
SQLiteDatabase db = getWritableDatabase();
|
SQLiteDatabase db = getWritableDatabase();
|
||||||
db.beginTransaction();
|
db.beginTransaction();
|
||||||
|
@ -191,9 +191,9 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
if (!targetRecipient.isGroupRecipient) {
|
if (!targetRecipient.isGroupRecipient) {
|
||||||
val recipientDb = DatabaseComponent.get(context).recipientDatabase()
|
val recipientDb = DatabaseComponent.get(context).recipientDatabase()
|
||||||
if (isUserSender || isUserBlindedSender) {
|
if (isUserSender || isUserBlindedSender) {
|
||||||
recipientDb.setApproved(targetRecipient, true)
|
setRecipientApproved(targetRecipient, true)
|
||||||
} else {
|
} else {
|
||||||
recipientDb.setApprovedMe(targetRecipient, true)
|
setRecipientApprovedMe(targetRecipient, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (message.isMediaMessage() || attachments.isNotEmpty()) {
|
if (message.isMediaMessage() || attachments.isNotEmpty()) {
|
||||||
@ -790,7 +790,7 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
for (contact in moreContacts) {
|
for (contact in moreContacts) {
|
||||||
val address = fromSerialized(contact.id)
|
val address = fromSerialized(contact.id)
|
||||||
val recipient = Recipient.from(context, address, true)
|
val recipient = Recipient.from(context, address, true)
|
||||||
val (url, key) = contact.profilePicture?.let { it.url to it.key } ?: (null to null)
|
val (url, key) = contact.profilePicture.let { it.url to it.key }
|
||||||
// set or clear the avatar
|
// set or clear the avatar
|
||||||
recipientDatabase.setProfileAvatar(recipient, url)
|
recipientDatabase.setProfileAvatar(recipient, url)
|
||||||
recipientDatabase.setProfileKey(recipient, key)
|
recipientDatabase.setProfileKey(recipient, key)
|
||||||
@ -826,11 +826,11 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
recipientDatabase.setApprovedMe(recipient, true)
|
recipientDatabase.setApprovedMe(recipient, true)
|
||||||
}
|
}
|
||||||
if (contact.isApproved == true) {
|
if (contact.isApproved == true) {
|
||||||
recipientDatabase.setApproved(recipient, true)
|
setRecipientApproved(recipient, true)
|
||||||
threadDatabase.setHasSent(threadId, true)
|
threadDatabase.setHasSent(threadId, true)
|
||||||
}
|
}
|
||||||
if (contact.isBlocked == true) {
|
if (contact.isBlocked == true) {
|
||||||
recipientDatabase.setBlocked(recipient, true)
|
setBlocked(listOf(recipient), true)
|
||||||
threadDatabase.deleteConversation(threadId)
|
threadDatabase.deleteConversation(threadId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -993,10 +993,16 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
|
|
||||||
override fun setRecipientApproved(recipient: Recipient, approved: Boolean) {
|
override fun setRecipientApproved(recipient: Recipient, approved: Boolean) {
|
||||||
DatabaseComponent.get(context).recipientDatabase().setApproved(recipient, approved)
|
DatabaseComponent.get(context).recipientDatabase().setApproved(recipient, approved)
|
||||||
|
configFactory.contacts?.upsertContact(recipient.address.serialize()) {
|
||||||
|
this.approved = approved
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setRecipientApprovedMe(recipient: Recipient, approvedMe: Boolean) {
|
override fun setRecipientApprovedMe(recipient: Recipient, approvedMe: Boolean) {
|
||||||
DatabaseComponent.get(context).recipientDatabase().setApprovedMe(recipient, approvedMe)
|
DatabaseComponent.get(context).recipientDatabase().setApprovedMe(recipient, approvedMe)
|
||||||
|
configFactory.contacts?.upsertContact(recipient.address.serialize()) {
|
||||||
|
this.approvedMe = approvedMe
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun insertCallMessage(senderPublicKey: String, callMessageType: CallMessageType, sentTimestamp: Long) {
|
override fun insertCallMessage(senderPublicKey: String, callMessageType: CallMessageType, sentTimestamp: Long) {
|
||||||
@ -1126,9 +1132,19 @@ class Storage(context: Context, helper: SQLCipherOpenHelper, private val configF
|
|||||||
DatabaseComponent.get(context).reactionDatabase().deleteMessageReactions(MessageId(messageId, mms))
|
DatabaseComponent.get(context).reactionDatabase().deleteMessageReactions(MessageId(messageId, mms))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun unblock(toUnblock: List<Recipient>) {
|
override fun setBlocked(recipients: List<Recipient>, isBlocked: Boolean) {
|
||||||
val recipientDb = DatabaseComponent.get(context).recipientDatabase()
|
val recipientDb = DatabaseComponent.get(context).recipientDatabase()
|
||||||
recipientDb.setBlocked(toUnblock, false)
|
recipientDb.setBlocked(recipients, isBlocked)
|
||||||
|
recipients.filter { it.isContactRecipient }.forEach { recipient ->
|
||||||
|
configFactory.contacts?.upsertContact(recipient.address.serialize()) {
|
||||||
|
this.blocked = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val contactsConfig = configFactory.contacts ?: return
|
||||||
|
if (contactsConfig.needsDump()) {
|
||||||
|
configFactory.persist(contactsConfig)
|
||||||
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun blockedContacts(): List<Recipient> {
|
override fun blockedContacts(): List<Recipient> {
|
||||||
|
@ -749,7 +749,7 @@ public class ThreadDatabase extends Database {
|
|||||||
} else {
|
} else {
|
||||||
MarkReadReceiver.process(context, messages);
|
MarkReadReceiver.process(context, messages);
|
||||||
}
|
}
|
||||||
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context, false, 0);
|
ApplicationContext.getInstance(context).messageNotifier.updateNotification(context, threadId);
|
||||||
setLastSeen(threadId, lastSeenTime);
|
setLastSeen(threadId, lastSeenTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
|||||||
import org.thoughtcrime.securesms.database.GroupDatabase
|
import org.thoughtcrime.securesms.database.GroupDatabase
|
||||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase
|
import org.thoughtcrime.securesms.database.MmsSmsDatabase
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.Storage
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||||
@ -90,6 +91,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
@Inject lateinit var threadDb: ThreadDatabase
|
@Inject lateinit var threadDb: ThreadDatabase
|
||||||
@Inject lateinit var mmsSmsDatabase: MmsSmsDatabase
|
@Inject lateinit var mmsSmsDatabase: MmsSmsDatabase
|
||||||
@Inject lateinit var recipientDatabase: RecipientDatabase
|
@Inject lateinit var recipientDatabase: RecipientDatabase
|
||||||
|
@Inject lateinit var storage: Storage
|
||||||
@Inject lateinit var groupDatabase: GroupDatabase
|
@Inject lateinit var groupDatabase: GroupDatabase
|
||||||
@Inject lateinit var textSecurePreferences: TextSecurePreferences
|
@Inject lateinit var textSecurePreferences: TextSecurePreferences
|
||||||
@Inject lateinit var configFactory: ConfigFactory
|
@Inject lateinit var configFactory: ConfigFactory
|
||||||
@ -515,7 +517,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { dialog, _ ->
|
.setPositiveButton(R.string.RecipientPreferenceActivity_block) { dialog, _ ->
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
recipientDatabase.setBlocked(thread.recipient, true)
|
storage.setBlocked(listOf(thread.recipient), true)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
@ -531,7 +533,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
|
|||||||
.setNegativeButton(android.R.string.cancel, null)
|
.setNegativeButton(android.R.string.cancel, null)
|
||||||
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock) { dialog, _ ->
|
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock) { dialog, _ ->
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
recipientDatabase.setBlocked(thread.recipient, false)
|
storage.setBlocked(listOf(thread.recipient), false)
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
binding.recyclerView.adapter!!.notifyDataSetChanged()
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
|
@ -55,7 +55,7 @@ class BlockedContactsViewModel @Inject constructor(private val storage: Storage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun unblock(toUnblock: List<Recipient>) {
|
fun unblock(toUnblock: List<Recipient>) {
|
||||||
storage.unblock(toUnblock)
|
storage.setBlocked(toUnblock, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
data class BlockedContactsViewState(
|
data class BlockedContactsViewState(
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.repository
|
package org.thoughtcrime.securesms.repository
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Contract
|
||||||
import org.session.libsession.database.MessageDataProvider
|
import org.session.libsession.database.MessageDataProvider
|
||||||
import org.session.libsession.messaging.messages.Destination
|
import org.session.libsession.messaging.messages.Destination
|
||||||
import org.session.libsession.messaging.messages.control.MessageRequestResponse
|
import org.session.libsession.messaging.messages.control.MessageRequestResponse
|
||||||
@ -23,6 +24,7 @@ import org.thoughtcrime.securesms.database.MmsSmsDatabase
|
|||||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||||
import org.thoughtcrime.securesms.database.SessionJobDatabase
|
import org.thoughtcrime.securesms.database.SessionJobDatabase
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase
|
import org.thoughtcrime.securesms.database.SmsDatabase
|
||||||
|
import org.thoughtcrime.securesms.database.Storage
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||||
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
||||||
@ -83,6 +85,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
private val mmsDb: MmsDatabase,
|
private val mmsDb: MmsDatabase,
|
||||||
private val mmsSmsDb: MmsSmsDatabase,
|
private val mmsSmsDb: MmsSmsDatabase,
|
||||||
private val recipientDb: RecipientDatabase,
|
private val recipientDb: RecipientDatabase,
|
||||||
|
private val storage: Storage,
|
||||||
private val lokiMessageDb: LokiMessageDatabase,
|
private val lokiMessageDb: LokiMessageDatabase,
|
||||||
private val sessionJobDb: SessionJobDatabase,
|
private val sessionJobDb: SessionJobDatabase,
|
||||||
private val configFactory: ConfigFactory
|
private val configFactory: ConfigFactory
|
||||||
@ -127,8 +130,10 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This assumes that recipient.isContactRecipient is true
|
||||||
|
@Contract
|
||||||
override fun setBlocked(recipient: Recipient, blocked: Boolean) {
|
override fun setBlocked(recipient: Recipient, blocked: Boolean) {
|
||||||
recipientDb.setBlocked(recipient, blocked)
|
storage.setBlocked(listOf(recipient), blocked)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun deleteLocally(recipient: Recipient, message: MessageRecord) {
|
override fun deleteLocally(recipient: Recipient, message: MessageRecord) {
|
||||||
@ -141,7 +146,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setApproved(recipient: Recipient, isApproved: Boolean) {
|
override fun setApproved(recipient: Recipient, isApproved: Boolean) {
|
||||||
recipientDb.setApproved(recipient, isApproved)
|
storage.setRecipientApproved(recipient, isApproved)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deleteForEveryone(
|
override suspend fun deleteForEveryone(
|
||||||
@ -272,7 +277,7 @@ class DefaultConversationRepository @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient): ResultOf<Unit> = suspendCoroutine { continuation ->
|
override suspend fun acceptMessageRequest(threadId: Long, recipient: Recipient): ResultOf<Unit> = suspendCoroutine { continuation ->
|
||||||
recipientDb.setApproved(recipient, true)
|
storage.setRecipientApproved(recipient, true)
|
||||||
val message = MessageRequestResponse(true)
|
val message = MessageRequestResponse(true)
|
||||||
MessageSender.send(message, Destination.from(recipient.address))
|
MessageSender.send(message, Destination.from(recipient.address))
|
||||||
.success {
|
.success {
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
package org.thoughtcrime.securesms.sskenvironment
|
package org.thoughtcrime.securesms.sskenvironment
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import network.loki.messenger.libsession_util.util.UserPic
|
||||||
import org.session.libsession.messaging.contacts.Contact
|
import org.session.libsession.messaging.contacts.Contact
|
||||||
import org.session.libsession.utilities.SSKEnvironment
|
import org.session.libsession.utilities.SSKEnvironment
|
||||||
import org.session.libsession.utilities.recipients.Recipient
|
import org.session.libsession.utilities.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.ApplicationContext
|
import org.thoughtcrime.securesms.ApplicationContext
|
||||||
|
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
||||||
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
|
||||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
||||||
|
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
|
||||||
|
|
||||||
class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
|
class ProfileManager(private val context: Context, private val configFactory: ConfigFactory) : SSKEnvironment.ProfileManagerProtocol {
|
||||||
|
|
||||||
override fun setNickname(context: Context, recipient: Recipient, nickname: String?) {
|
override fun setNickname(context: Context, recipient: Recipient, nickname: String?) {
|
||||||
val sessionID = recipient.address.serialize()
|
val sessionID = recipient.address.serialize()
|
||||||
@ -20,6 +23,7 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
|
|||||||
contact.nickname = nickname
|
contact.nickname = nickname
|
||||||
contactDatabase.setContact(contact)
|
contactDatabase.setContact(contact)
|
||||||
}
|
}
|
||||||
|
contactUpdatedInternal(contact)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setName(context: Context, recipient: Recipient, name: String) {
|
override fun setName(context: Context, recipient: Recipient, name: String) {
|
||||||
@ -37,6 +41,7 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
|
|||||||
val database = DatabaseComponent.get(context).recipientDatabase()
|
val database = DatabaseComponent.get(context).recipientDatabase()
|
||||||
database.setProfileName(recipient, name)
|
database.setProfileName(recipient, name)
|
||||||
recipient.notifyListeners()
|
recipient.notifyListeners()
|
||||||
|
contactUpdatedInternal(contact)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String) {
|
override fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String) {
|
||||||
@ -52,6 +57,7 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
|
|||||||
contact.profilePictureURL = profilePictureURL
|
contact.profilePictureURL = profilePictureURL
|
||||||
contactDatabase.setContact(contact)
|
contactDatabase.setContact(contact)
|
||||||
}
|
}
|
||||||
|
contactUpdatedInternal(contact)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setProfileKey(context: Context, recipient: Recipient, profileKey: ByteArray?) {
|
override fun setProfileKey(context: Context, recipient: Recipient, profileKey: ByteArray?) {
|
||||||
@ -68,10 +74,28 @@ class ProfileManager : SSKEnvironment.ProfileManagerProtocol {
|
|||||||
// Old API
|
// Old API
|
||||||
val database = DatabaseComponent.get(context).recipientDatabase()
|
val database = DatabaseComponent.get(context).recipientDatabase()
|
||||||
database.setProfileKey(recipient, profileKey)
|
database.setProfileKey(recipient, profileKey)
|
||||||
|
contactUpdatedInternal(contact)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setUnidentifiedAccessMode(context: Context, recipient: Recipient, unidentifiedAccessMode: Recipient.UnidentifiedAccessMode) {
|
override fun setUnidentifiedAccessMode(context: Context, recipient: Recipient, unidentifiedAccessMode: Recipient.UnidentifiedAccessMode) {
|
||||||
val database = DatabaseComponent.get(context).recipientDatabase()
|
val database = DatabaseComponent.get(context).recipientDatabase()
|
||||||
database.setUnidentifiedAccessMode(recipient, unidentifiedAccessMode)
|
database.setUnidentifiedAccessMode(recipient, unidentifiedAccessMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun contactUpdatedInternal(contact: Contact) {
|
||||||
|
val contactConfig = configFactory.contacts ?: return
|
||||||
|
contactConfig.upsertContact(contact.sessionID) {
|
||||||
|
this.name = contact.name.orEmpty()
|
||||||
|
this.nickname = contact.nickname.orEmpty()
|
||||||
|
val url = contact.profilePictureURL
|
||||||
|
val key = contact.profilePictureEncryptionKey
|
||||||
|
if (!url.isNullOrEmpty() && key != null && key.size == 32) {
|
||||||
|
this.profilePicture = UserPic(url, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (contactConfig.needsDump()) {
|
||||||
|
ConfigurationMessageUtilities.forceSyncConfigurationNowIfNeeded(context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -62,6 +62,25 @@ class Contacts(pointer: Long) : ConfigBase(pointer) {
|
|||||||
external fun all(): List<Contact>
|
external fun all(): List<Contact>
|
||||||
external fun set(contact: Contact)
|
external fun set(contact: Contact)
|
||||||
external fun erase(sessionId: String): Boolean
|
external fun erase(sessionId: String): Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to [updateIfExists], but will create the underlying contact if it doesn't exist before passing to [updateFunction]
|
||||||
|
*/
|
||||||
|
fun upsertContact(sessionId: String, updateFunction: Contact.()->Unit) {
|
||||||
|
val contact = getOrConstruct(sessionId)
|
||||||
|
updateFunction(contact)
|
||||||
|
set(contact)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the contact by sessionId with a given [updateFunction], and applies to the underlying config.
|
||||||
|
* the [updateFunction] doesn't run if there is no contact
|
||||||
|
*/
|
||||||
|
fun updateIfExists(sessionId: String, updateFunction: Contact.()->Unit) {
|
||||||
|
val contact = get(sessionId) ?: return
|
||||||
|
updateFunction(contact)
|
||||||
|
set(contact)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserProfile(pointer: Long) : ConfigBase(pointer) {
|
class UserProfile(pointer: Long) : ConfigBase(pointer) {
|
||||||
|
@ -204,7 +204,7 @@ interface StorageProtocol {
|
|||||||
fun removeReaction(emoji: String, messageTimestamp: Long, author: String, notifyUnread: Boolean)
|
fun removeReaction(emoji: String, messageTimestamp: Long, author: String, notifyUnread: Boolean)
|
||||||
fun updateReactionIfNeeded(message: Message, sender: String, openGroupSentTimestamp: Long)
|
fun updateReactionIfNeeded(message: Message, sender: String, openGroupSentTimestamp: Long)
|
||||||
fun deleteReactions(messageId: Long, mms: Boolean)
|
fun deleteReactions(messageId: Long, mms: Boolean)
|
||||||
fun unblock(toUnblock: List<Recipient>)
|
fun setBlocked(recipients: List<Recipient>, isBlocked: Boolean)
|
||||||
fun blockedContacts(): List<Recipient>
|
fun blockedContacts(): List<Recipient>
|
||||||
|
|
||||||
// Shared configs
|
// Shared configs
|
||||||
|
@ -150,7 +150,9 @@ data class ConfigurationSyncJob(val destination: Destination): Job {
|
|||||||
// store the new hash in list of hashes to track against
|
// store the new hash in list of hashes to track against
|
||||||
configFactory.appendHash(config, insertHash)
|
configFactory.appendHash(config, insertHash)
|
||||||
// dump and write config after successful
|
// dump and write config after successful
|
||||||
configFactory.persist(config)
|
if (config.needsDump()) { // usually this will be true?
|
||||||
|
configFactory.persist(config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "Error performing batch request", e)
|
Log.e(TAG, "Error performing batch request", e)
|
||||||
|
@ -163,7 +163,9 @@ class Poller(private val configFactory: ConfigFactoryProtocol, debounceTimer: Ti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// process new results
|
// process new results
|
||||||
configFactory.persist(forConfigObject)
|
if (forConfigObject.needsDump()) {
|
||||||
|
configFactory.persist(forConfigObject)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun poll(snode: Snode, deferred: Deferred<Unit, Exception>): Promise<Unit, Exception> {
|
private fun poll(snode: Snode, deferred: Deferred<Unit, Exception>): Promise<Unit, Exception> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user