diff --git a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt index 7e732d1aa7..ded6b4f140 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/calls/WebRtcCallActivity.kt @@ -260,6 +260,7 @@ class WebRtcCallActivity : PassphraseRequiredActionBarActivity() { CALL_CONNECTED -> { wantsToAnswer = false } + else -> { /* do nothing */ } } updateControls(state) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt index 5e4aa8d3a9..def8d41c43 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt @@ -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 = _uiState private var _recipient: RetrieveOnce = RetrieveOnce { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt index 8a6c84aecf..c35dabc65e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt @@ -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(R.id.menu_badge_icon) - val badgeView = actionView.findViewById(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(R.id.menu_badge_icon) + val badgeView = actionView.findViewById(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) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt index ac21c5adef..5083edd34d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ConfigFactory.kt @@ -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) diff --git a/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt index 8b880d2189..74e2cac4c8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt @@ -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 } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/JoinCommunityFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/JoinCommunityFragment.kt index 3afd98422d..ae59c3833e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/JoinCommunityFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/JoinCommunityFragment.kt @@ -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 } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index 4e2fc9f37e..9bd49c4431 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -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) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt index 2c64ded866..54f9290ffb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/search/GlobalSearchAdapterUtils.kt @@ -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) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt index 07da14b090..a85ea525ae 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt @@ -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 } }) diff --git a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt index 66aa1eaf81..3bf232d451 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sskenvironment/ProfileManager.kt @@ -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() diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt index 7b7f3a04f3..4895acb9a3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt @@ -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 } diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index 935848565c..8ecb983f4b 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -27,8 +27,9 @@ android:layout_marginLeft="20dp" android:layout_marginRight="20dp"> - + android:layout_height="@dimen/path_status_view_size" + android:layout_alignEnd="@+id/profileButton" + android:layout_alignBottom="@+id/profileButton" /> + android:layout_height="?actionBarSize" + android:layout_marginHorizontal="@dimen/medium_spacing" + android:visibility="gone"> + + android:layout_height="wrap_content" + android:layout_centerVertical="true" /> + + + android:clipChildren="false" + android:focusable="false"> + tools:listitem="@layout/view_global_search_result" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ebacb766d1..cb8f962858 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -873,4 +873,5 @@ Failed to send Search GIFs? Session will connect to Giphy to provide search results. You will not have full metadata protection when sending GIFs. + Some of your devices are using outdated versions. Syncing may be unreliable until they are updated. diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 2874d42972..9f049d4424 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -389,6 +389,8 @@ @color/classic_dark_2 +