mirror of
https://github.com/oxen-io/session-android.git
synced 2025-08-11 21:17:42 +00:00
feat: add contact syncing, UI improvements for profile syncing and conversation threads in the home screen
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = "1.4.0"
|
||||
ext.kovenant_version = "3.3.0"
|
||||
|
||||
repositories {
|
||||
@@ -124,8 +123,8 @@ dependencies {
|
||||
implementation "com.google.protobuf:protobuf-java:$protobufVersion"
|
||||
implementation "com.fasterxml.jackson.core:jackson-databind:$jacksonDatabindVersion"
|
||||
implementation "com.squareup.okhttp3:okhttp:$okhttpVersion"
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2"
|
||||
implementation "nl.komponents.kovenant:kovenant:$kovenantVersion"
|
||||
implementation "nl.komponents.kovenant:kovenant-android:$kovenantVersion"
|
||||
implementation "com.github.lelloman:android-identicons:v11"
|
||||
|
@@ -249,7 +249,14 @@ public class RecipientDatabase extends Database {
|
||||
recipient.resolve().setProfileAvatar(profileAvatar);
|
||||
}
|
||||
|
||||
public void setProfileSharing(@NonNull Recipient recipient, @SuppressWarnings("SameParameterValue") boolean enabled) {
|
||||
public void setProfileName(@NonNull Recipient recipient, @Nullable String profileName) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(SYSTEM_DISPLAY_NAME, profileName);
|
||||
updateOrInsert(recipient.getAddress(), contentValues);
|
||||
recipient.resolve().setProfileName(profileName);
|
||||
}
|
||||
|
||||
public void setProfileSharing(@NonNull Recipient recipient, boolean enabled) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(PROFILE_SHARING, enabled ? 1 : 0);
|
||||
updateOrInsert(recipient.getAddress(), contentValues);
|
||||
|
@@ -506,6 +506,10 @@ public class ThreadDatabase extends Database {
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
|
||||
public void notifyUpdatedFromConfig() {
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
public boolean update(long threadId, boolean unarchive) {
|
||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||
long count = mmsSmsDatabase.getConversationCount(threadId);
|
||||
|
@@ -22,9 +22,11 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import kotlinx.android.synthetic.main.activity_home.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import network.loki.messenger.R
|
||||
import org.session.libsession.messaging.threads.recipients.RecipientModifiedListener
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
|
||||
import org.thoughtcrime.securesms.conversation.ConversationActivity
|
||||
@@ -46,7 +48,10 @@ import org.thoughtcrime.securesms.loki.dialogs.*
|
||||
import org.thoughtcrime.securesms.loki.protocol.ClosedGroupsProtocolV2
|
||||
import java.io.IOException
|
||||
|
||||
class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListener, SeedReminderViewDelegate, NewConversationButtonSetViewDelegate {
|
||||
class HomeActivity : PassphraseRequiredActionBarActivity,
|
||||
ConversationClickListener,
|
||||
SeedReminderViewDelegate,
|
||||
NewConversationButtonSetViewDelegate {
|
||||
|
||||
private lateinit var glide: GlideRequests
|
||||
private var broadcastReceiver: BroadcastReceiver? = null
|
||||
@@ -71,9 +76,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
glide = GlideApp.with(this)
|
||||
// Set up toolbar buttons
|
||||
profileButton.glide = glide
|
||||
profileButton.publicKey = publicKey
|
||||
profileButton.displayName = TextSecurePreferences.getProfileName(this)
|
||||
profileButton.update()
|
||||
updateProfileButton()
|
||||
profileButton.setOnClickListener { openSettings() }
|
||||
pathStatusViewContainer.disableClipping()
|
||||
pathStatusViewContainer.setOnClickListener { showPath() }
|
||||
@@ -149,6 +152,12 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
}
|
||||
this.broadcastReceiver = broadcastReceiver
|
||||
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, IntentFilter("blockedContactsChanged"))
|
||||
lifecycleScope.launchWhenResumed {
|
||||
// update things based on TextSecurePrefs (profile info etc)
|
||||
TextSecurePreferences.events.filter { it == TextSecurePreferences.PROFILE_NAME_PREF }.collect {
|
||||
updateProfileButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@@ -198,6 +207,13 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
val threadCount = (recyclerView.adapter as HomeAdapter).itemCount
|
||||
emptyStateContainer.visibility = if (threadCount == 0) View.VISIBLE else View.GONE
|
||||
}
|
||||
|
||||
private fun updateProfileButton() {
|
||||
profileButton.publicKey = publicKey
|
||||
profileButton.displayName = TextSecurePreferences.getProfileName(this)
|
||||
profileButton.recycle()
|
||||
profileButton.update()
|
||||
}
|
||||
// endregion
|
||||
|
||||
// region Interaction
|
||||
@@ -356,7 +372,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity, ConversationClickListe
|
||||
|
||||
private fun openSettings() {
|
||||
val intent = Intent(this, SettingsActivity::class.java)
|
||||
show(intent)
|
||||
show(intent, isForResult = true)
|
||||
}
|
||||
|
||||
private fun showPath() {
|
||||
|
@@ -68,6 +68,10 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
|
||||
return TextSecurePreferences.getLocalNumber(this)!!
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val updatedProfileResultCode = 1234
|
||||
}
|
||||
|
||||
// region Lifecycle
|
||||
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
|
||||
super.onCreate(savedInstanceState, isReady)
|
||||
|
@@ -12,12 +12,18 @@ import org.session.libsignal.service.api.push.SignalServiceAddress
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos
|
||||
import org.session.libsignal.service.internal.push.SignalServiceProtos.DataMessage
|
||||
import org.session.libsignal.service.loki.utilities.removing05PrefixIfNeeded
|
||||
import org.session.libsignal.utilities.Base64
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.logging.Log
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase
|
||||
import org.thoughtcrime.securesms.jobs.RetrieveProfileAvatarJob
|
||||
import org.thoughtcrime.securesms.loki.utilities.ContactUtilities
|
||||
import org.thoughtcrime.securesms.loki.utilities.OpenGroupUtilities
|
||||
import org.thoughtcrime.securesms.sskenvironment.ProfileManager
|
||||
import java.util.*
|
||||
|
||||
object MultiDeviceProtocol {
|
||||
@@ -76,7 +82,7 @@ object MultiDeviceProtocol {
|
||||
// TODO: remove this after we migrate to new message receiving pipeline
|
||||
@JvmStatic
|
||||
fun handleConfigurationMessage(context: Context, content: SignalServiceProtos.Content, senderPublicKey: String, timestamp: Long) {
|
||||
if (TextSecurePreferences.getConfigurationMessageSynced(context)) return
|
||||
// if (TextSecurePreferences.getConfigurationMessageSynced(context)) return
|
||||
val configurationMessage = ConfigurationMessage.fromProto(content) ?: return
|
||||
val userPublicKey = TextSecurePreferences.getLocalNumber(context) ?: return
|
||||
if (senderPublicKey != userPublicKey) return
|
||||
@@ -103,6 +109,37 @@ object MultiDeviceProtocol {
|
||||
if (allOpenGroups.contains(openGroup)) continue
|
||||
OpenGroupUtilities.addGroup(context, openGroup, 1)
|
||||
}
|
||||
if (configurationMessage.profileKey.isNotEmpty()) {
|
||||
val profileKey = Base64.encodeBytes(configurationMessage.profileKey)
|
||||
TextSecurePreferences.setProfileKey(context, profileKey)
|
||||
}
|
||||
if (!configurationMessage.profilePicture.isNullOrEmpty()) {
|
||||
TextSecurePreferences.setProfilePictureURL(context, configurationMessage.profilePicture)
|
||||
}
|
||||
if (configurationMessage.displayName.isNotEmpty()) {
|
||||
TextSecurePreferences.setProfileName(context, configurationMessage.displayName)
|
||||
}
|
||||
val threadDatabase = DatabaseFactory.getThreadDatabase(context)
|
||||
val recipientDatabase = DatabaseFactory.getRecipientDatabase(context)
|
||||
for (contact in configurationMessage.contacts) {
|
||||
val address = Address.fromSerialized(contact.publicKey)
|
||||
val recipient = Recipient.from(context, address, true)
|
||||
if (!contact.profilePicture.isNullOrEmpty()) {
|
||||
recipientDatabase.setProfileAvatar(recipient, contact.profilePicture)
|
||||
}
|
||||
if (contact.profileKey?.isNotEmpty() == true) {
|
||||
recipientDatabase.setProfileKey(recipient, contact.profileKey)
|
||||
}
|
||||
if (contact.name.isNotEmpty()) {
|
||||
recipientDatabase.setProfileName(recipient, contact.name)
|
||||
}
|
||||
recipientDatabase.setProfileSharing(recipient, true)
|
||||
// create Thread if needed
|
||||
threadDatabase.getOrCreateThreadIdFor(recipient)
|
||||
}
|
||||
if (configurationMessage.contacts.isNotEmpty()) {
|
||||
threadDatabase.notifyUpdatedFromConfig()
|
||||
}
|
||||
// TODO: handle new configuration message fields or handle in new pipeline
|
||||
TextSecurePreferences.setConfigurationMessageSynced(context, true)
|
||||
}
|
||||
|
Reference in New Issue
Block a user