feat: update dependencies and support outdated config messages, refactor config factory to return null configs if new configs not supported

This commit is contained in:
0x330a 2023-04-03 17:22:51 +10:00
parent d8f8ab8fe1
commit 5acaffda56
No known key found for this signature in database
GPG key ID: 267811D6E6A2698C
18 changed files with 109 additions and 34 deletions

View file

@ -260,6 +260,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() {
CALL_CONNECTED -> {
wantsToAnswer = false
}
else -> { /* do nothing */ }
}
updateControls(state)
}

View file

@ -35,7 +35,7 @@ class ConversationViewModel(
private val storage: Storage
) : ViewModel() {
private val _uiState = MutableStateFlow(ConversationUiState(conversationExists = recipient != null))
private val _uiState = MutableStateFlow(ConversationUiState(conversationExists = true))
val uiState: StateFlow<ConversationUiState> = _uiState
private var _recipient: RetrieveOnce<Recipient> = RetrieveOnce {

View file

@ -67,13 +67,14 @@ object ConversationMenuHelper {
if (thread.expireMessages > 0) {
inflater.inflate(R.menu.menu_conversation_expiration_on, menu)
val item = menu.findItem(R.id.menu_expiring_messages)
val actionView = item.actionView
val iconView = actionView.findViewById<ImageView>(R.id.menu_badge_icon)
val badgeView = actionView.findViewById<TextView>(R.id.expiration_badge)
@ColorInt val color = context.getColorFromAttr(android.R.attr.textColorPrimary)
iconView.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)
badgeView.text = ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, thread.expireMessages)
actionView.setOnClickListener { onOptionsItemSelected(item) }
item.actionView?.let { actionView ->
val iconView = actionView.findViewById<ImageView>(R.id.menu_badge_icon)
val badgeView = actionView.findViewById<TextView>(R.id.expiration_badge)
@ColorInt val color = context.getColorFromAttr(android.R.attr.textColorPrimary)
iconView.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)
badgeView.text = ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, thread.expireMessages)
actionView.setOnClickListener { onOptionsItemSelected(item) }
}
} else {
inflater.inflate(R.menu.menu_conversation_expiration_off, menu)
}

View file

@ -43,6 +43,7 @@ class ConfigFactory(private val context: Context,
fun unregisterListener(listener: ConfigFactoryUpdateListener) { listeners -= listener }
override val user: UserProfile? get() = synchronized(userLock) {
if (!ConfigBase.isNewConfigEnabled) return null
if (_userConfig == null) {
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
val userDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.USER_PROFILE.name, publicKey)
@ -58,6 +59,7 @@ class ConfigFactory(private val context: Context,
}
override val contacts: Contacts? get() = synchronized(contactsLock) {
if (!ConfigBase.isNewConfigEnabled) return null
if (_contacts == null) {
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
val contactsDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.CONTACTS.name, publicKey)
@ -73,6 +75,7 @@ class ConfigFactory(private val context: Context,
}
override val convoVolatile: ConversationVolatileConfig? get() = synchronized(convoVolatileLock) {
if (!ConfigBase.isNewConfigEnabled) return null
if (_convoVolatileConfig == null) {
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
val convoDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.CONVO_INFO_VOLATILE.name, publicKey)
@ -88,6 +91,7 @@ class ConfigFactory(private val context: Context,
}
override val userGroups: UserGroupsConfig? get() = synchronized(userGroupsLock) {
if (!ConfigBase.isNewConfigEnabled) return null
if (_userGroups == null) {
val (secretKey, publicKey) = maybeGetUserInfo() ?: return@synchronized null
val userGroupsDump = configDatabase.retrieveConfigAndHashes(SharedConfigMessage.Kind.GROUPS.name, publicKey)

View file

@ -98,7 +98,7 @@ class NewMessageFragment : Fragment() {
private fun hideLoader() {
binding.loader.animate().setDuration(150).alpha(0.0f).setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
binding.loader.visibility = View.GONE
}

View file

@ -55,7 +55,7 @@ class JoinCommunityFragment : Fragment() {
fun hideLoader() {
binding.loader.animate().setDuration(150).alpha(0.0f).setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
binding.loader.visibility = View.GONE
}

View file

@ -27,6 +27,7 @@ import kotlinx.coroutines.withContext
import network.loki.messenger.R
import network.loki.messenger.databinding.ActivityHomeBinding
import network.loki.messenger.databinding.ViewMessageRequestBannerBinding
import network.loki.messenger.libsession_util.ConfigBase
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
@ -182,6 +183,11 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
binding.recyclerView.adapter = homeAdapter
binding.globalSearchRecycler.adapter = globalSearchAdapter
binding.configOutdatedView.setOnClickListener {
textSecurePreferences.setHasLegacyConfig(false)
updateLegacyConfigView()
}
// Set up empty state view
binding.createNewPrivateChatButton.setOnClickListener { showNewConversation() }
IP2Country.configureIfNeeded(this@HomeActivity)
@ -335,6 +341,10 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
}
}
private fun updateLegacyConfigView() {
binding.configOutdatedView.isVisible = ConfigBase.isNewConfigEnabled && textSecurePreferences.getHasLegacyConfig()
}
override fun onResume() {
super.onResume()
ApplicationContext.getInstance(this).messageNotifier.setHomeScreenVisible(true)
@ -345,7 +355,12 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
if (textSecurePreferences.getHasViewedSeed()) {
binding.seedReminderView.isVisible = false
}
if (textSecurePreferences.getConfigurationMessageSynced()) {
updateLegacyConfigView()
// TODO: remove this after enough updates that we can rely on ConfigBase.isNewConfigEnabled to always return true
// This will only run if we aren't using new configs, as they are schedule to sync when there are changes applied
if (textSecurePreferences.getConfigurationMessageSynced() && !ConfigBase.isNewConfigEnabled) {
lifecycleScope.launch(Dispatchers.IO) {
ConfigurationMessageUtilities.syncConfigurationIfNeeded(this@HomeActivity)
}

View file

@ -12,6 +12,7 @@ import org.session.libsession.utilities.Address
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.ContentView
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.GroupConversation
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.Header
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.Message
import org.thoughtcrime.securesms.home.search.GlobalSearchAdapter.Model.SavedMessages
import org.thoughtcrime.securesms.util.DateUtils
@ -76,6 +77,8 @@ fun ContentView.bindQuery(query: String, model: GlobalSearchAdapter.Model) {
}
binding.searchResultSubtitle.text = getHighlight(query, membersString)
}
is Header, // do nothing for header
is SavedMessages -> Unit // do nothing for saved messages (displays note to self)
}
}

View file

@ -154,7 +154,7 @@ class KeyboardPageSearchView @JvmOverloads constructor(
.setDuration(REVEAL_DURATION)
.alpha(0f)
.setListener(object : AnimationCompleteListener() {
override fun onAnimationEnd(animation: Animator?) {
override fun onAnimationEnd(animation: Animator) {
visibility = INVISIBLE
}
})

View file

@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
class ProfileManager(private val context: Context, private val configFactory: ConfigFactory) : SSKEnvironment.ProfileManagerProtocol {
override fun setNickname(context: Context, recipient: Recipient, nickname: String?) {
if (recipient.isLocalNumber) return
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()
var contact = contactDatabase.getContactWithSessionID(sessionID)
@ -31,6 +32,7 @@ class ProfileManager(private val context: Context, private val configFactory: Co
override fun setName(context: Context, recipient: Recipient, name: String?) {
// New API
if (recipient.isLocalNumber) return
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()
var contact = contactDatabase.getContactWithSessionID(sessionID)
@ -48,6 +50,7 @@ class ProfileManager(private val context: Context, private val configFactory: Co
}
override fun setProfilePictureURL(context: Context, recipient: Recipient, profilePictureURL: String) {
if (recipient.isLocalNumber) return
val job = RetrieveProfileAvatarJob(recipient, profilePictureURL)
val jobManager = ApplicationContext.getInstance(context).jobManager
jobManager.add(job)
@ -64,6 +67,7 @@ class ProfileManager(private val context: Context, private val configFactory: Co
}
override fun setProfileKey(context: Context, recipient: Recipient, profileKey: ByteArray?) {
if (recipient.isLocalNumber) return
// New API
val sessionID = recipient.address.serialize()
val contactDatabase = DatabaseComponent.get(context).sessionContactDatabase()

View file

@ -8,11 +8,11 @@ import android.content.Context
import android.graphics.PointF
import android.graphics.Rect
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.annotation.ColorInt
import androidx.annotation.DimenRes
import network.loki.messenger.R
import org.session.libsession.utilities.getColorFromAttr
import android.view.inputmethod.InputMethodManager
fun View.contains(point: PointF): Boolean {
return hitRect.contains(point.x.toInt(), point.y.toInt())
@ -54,7 +54,7 @@ fun View.fadeIn(duration: Long = 150) {
fun View.fadeOut(duration: Long = 150) {
animate().setDuration(duration).alpha(0.0f).setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator?) {
override fun onAnimationEnd(animation: Animator) {
super.onAnimationEnd(animation)
visibility = View.GONE
}

View file

@ -27,8 +27,9 @@
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp">
<include layout="@layout/view_profile_picture"
<include
android:id="@+id/profileButton"
layout="@layout/view_profile_picture"
android:layout_width="@dimen/small_profile_picture_size"
android:layout_height="@dimen/small_profile_picture_size"
android:layout_alignParentLeft="true"
@ -37,10 +38,10 @@
<org.thoughtcrime.securesms.home.PathStatusView
android:id="@+id/pathStatusView"
android:layout_alignBottom="@+id/profileButton"
android:layout_alignEnd="@+id/profileButton"
android:layout_width="@dimen/path_status_view_size"
android:layout_height="@dimen/path_status_view_size"/>
android:layout_height="@dimen/path_status_view_size"
android:layout_alignEnd="@+id/profileButton"
android:layout_alignBottom="@+id/profileButton" />
<ImageView
android:id="@+id/sessionHeaderImage"
@ -72,16 +73,17 @@
</RelativeLayout>
<RelativeLayout
android:visibility="gone"
android:id="@+id/search_toolbar"
android:layout_marginHorizontal="@dimen/medium_spacing"
android:layout_width="match_parent"
android:layout_height="?actionBarSize">
android:layout_height="?actionBarSize"
android:layout_marginHorizontal="@dimen/medium_spacing"
android:visibility="gone">
<org.thoughtcrime.securesms.home.search.GlobalSearchInputLayout
android:layout_centerVertical="true"
android:id="@+id/globalSearchInputLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
android:layout_height="wrap_content"
android:layout_centerVertical="true" />
</RelativeLayout>
<View
@ -95,15 +97,29 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:visibility="gone"
android:textColor="?message_sent_text_color"
android:background="?colorAccent"
android:id="@+id/configOutdatedView"
android:textSize="9sp"
android:paddingVertical="4dp"
android:paddingHorizontal="64dp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/activity_home_outdated_client_config"
/>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
<RelativeLayout
android:focusable="false"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false">
android:clipChildren="false"
android:focusable="false">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
@ -116,14 +132,14 @@
tools:listitem="@layout/view_conversation" />
<androidx.recyclerview.widget.RecyclerView
android:visibility="gone"
android:scrollbars="vertical"
android:id="@+id/globalSearchRecycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/view_global_search_result"
tools:itemCount="6"
android:layout_height="match_parent"/>
tools:listitem="@layout/view_global_search_result" />
<LinearLayout
android:id="@+id/emptyStateContainer"
@ -159,6 +175,7 @@
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="@drawable/new_conversation_button_background"
android:contentDescription="@string/activity_appearance_follow_system_category"
android:layout_marginBottom="@dimen/new_conversation_button_bottom_offset"
android:src="@drawable/ic_plus"
app:tint="@color/white" />

View file

@ -873,4 +873,5 @@
<string name="delivery_status_failed">Failed to send</string>
<string name="giphy_permission_title">Search GIFs?</string>
<string name="giphy_permission_message">Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs.</string>
<string name="activity_home_outdated_client_config">Some of your devices are using outdated versions. Syncing may be unreliable until they are updated.</string>
</resources>

View file

@ -389,6 +389,8 @@
<item name="message_selected">@color/classic_dark_2</item>
</style>
<style name="Classic.Dark.Test" parent="Theme.Session.DayNight.NoActionBar"/>
<style name="Classic.Light">
<!-- Main styles -->
<item name="sessionLogoTint">@color/classic_light_0</item>

View file

@ -51,7 +51,7 @@ allprojects {
project.ext {
androidMinimumSdkVersion = 23
androidTargetSdkVersion = 31
androidCompileSdkVersion = 32
androidTargetSdkVersion = 33
androidCompileSdkVersion = 33
}
}

View file

@ -4,7 +4,7 @@ org.gradle.jvmargs=-Xmx8g
gradlePluginVersion=7.3.1
googleServicesVersion=4.3.12
kotlinVersion=1.7.20
kotlinVersion=1.6.21
coroutinesVersion=1.6.4
kotlinxJsonVersion=1.3.3
lifecycleVersion=2.5.1
@ -15,8 +15,8 @@ curve25519Version=0.6.0
protobufVersion=2.5.0
okhttpVersion=3.12.1
jacksonDatabindVersion=2.9.8
appcompatVersion=1.5.1
materialVersion=1.7.0
appcompatVersion=1.6.1
materialVersion=1.8.0
preferenceVersion=1.2.0
coreVersion=1.8.0

View file

@ -1,6 +1,7 @@
package org.session.libsession.messaging.sending_receiving
import android.text.TextUtils
import network.loki.messenger.libsession_util.ConfigBase
import org.session.libsession.avatars.AvatarHelper
import org.session.libsession.messaging.MessagingModuleConfiguration
import org.session.libsession.messaging.jobs.BackgroundGroupAddJob
@ -148,6 +149,9 @@ private fun handleConfigurationMessage(message: ConfigurationMessage) {
TextSecurePreferences.setConfigurationMessageSynced(context, true)
TextSecurePreferences.setLastProfileUpdateTime(context, message.sentTimestamp!!)
if (ConfigBase.isNewConfigEnabled) {
TextSecurePreferences.setHasLegacyConfig(context, true)
}
val allClosedGroupPublicKeys = storage.getAllClosedGroupPublicKeys()
for (closedGroup in message.closedGroups) {
if (allClosedGroupPublicKeys.contains(closedGroup.publicKey)) {

View file

@ -103,6 +103,8 @@ interface TextSecurePreferences {
fun setUpdateApkDigest(value: String?)
fun getUpdateApkDigest(): String?
fun getLocalNumber(): String?
fun getHasLegacyConfig(): Boolean
fun setHasLegacyConfig(newValue: Boolean)
fun setLocalNumber(localNumber: String)
fun removeLocalNumber()
fun isEnterSendsEnabled(): Boolean
@ -264,6 +266,9 @@ interface TextSecurePreferences {
const val AUTOPLAY_AUDIO_MESSAGES = "pref_autoplay_audio"
const val FINGERPRINT_KEY_GENERATED = "fingerprint_key_generated"
const val SELECTED_ACCENT_COLOR = "selected_accent_color"
const val HAS_RECEIVED_LEGACY_CONFIG = "has_received_legacy_config"
const val GREEN_ACCENT = "accent_green"
const val BLUE_ACCENT = "accent_blue"
const val PURPLE_ACCENT = "accent_purple"
@ -625,6 +630,16 @@ interface TextSecurePreferences {
return getStringPreference(context, LOCAL_NUMBER_PREF, null)
}
@JvmStatic
fun getHasLegacyConfig(context: Context): Boolean {
return getBooleanPreference(context, HAS_RECEIVED_LEGACY_CONFIG, false)
}
@JvmStatic
fun setHasLegacyConfig(context: Context, newValue: Boolean) {
setBooleanPreference(context, HAS_RECEIVED_LEGACY_CONFIG, newValue)
}
fun setLocalNumber(context: Context, localNumber: String) {
setStringPreference(context, LOCAL_NUMBER_PREF, localNumber.toLowerCase())
}
@ -1279,6 +1294,14 @@ class AppTextSecurePreferences @Inject constructor(
return getStringPreference(TextSecurePreferences.LOCAL_NUMBER_PREF, null)
}
override fun getHasLegacyConfig(): Boolean {
return getBooleanPreference(TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG, false)
}
override fun setHasLegacyConfig(newValue: Boolean) {
return setBooleanPreference(TextSecurePreferences.HAS_RECEIVED_LEGACY_CONFIG, newValue)
}
override fun setLocalNumber(localNumber: String) {
setStringPreference(TextSecurePreferences.LOCAL_NUMBER_PREF, localNumber.toLowerCase())
}