Skip to content

Commit b44ea31

Browse files
[SES-3434] - Fix receiving left groups' notification (#986)
* Fix still receiving generic notification for groups * Imports * Fixes tests * Fixes compile issues
1 parent 119a3e7 commit b44ea31

File tree

8 files changed

+125
-79
lines changed

8 files changed

+125
-79
lines changed

app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import androidx.lifecycle.ProcessLifecycleOwner;
4141
import androidx.work.Configuration;
4242

43+
import com.google.firebase.messaging.FirebaseMessaging;
4344
import com.squareup.phrase.Phrase;
4445

4546
import org.conscrypt.Conscrypt;
@@ -499,37 +500,6 @@ private void loadEmojiSearchIndexIfNeeded() {
499500
}
500501
});
501502
}
502-
503-
// Method to clear the local data - returns true on success otherwise false
504-
@SuppressLint("ApplySharedPref")
505-
public boolean clearAllData() {
506-
TextSecurePreferences.clearAll(this);
507-
getSharedPreferences(PREFERENCES_NAME, 0).edit().clear().commit();
508-
if (!deleteDatabase(SQLCipherOpenHelper.DATABASE_NAME)) {
509-
Log.d("Loki", "Failed to delete database.");
510-
return false;
511-
}
512-
configFactory.clearAll();
513-
return true;
514-
}
515-
516-
/**
517-
* Clear all local profile data and message history then restart the app after a brief delay.
518-
* @return true on success, false otherwise.
519-
*/
520-
@SuppressLint("ApplySharedPref")
521-
public boolean clearAllDataAndRestart() {
522-
clearAllData();
523-
Util.runOnMain(() -> new Handler().postDelayed(ApplicationContext.this::restartApplication, 200));
524-
return true;
525-
}
526-
527-
public void restartApplication() {
528-
Intent intent = new Intent(this, HomeActivity.class);
529-
startActivity(Intent.makeRestartActivityTask(intent.getComponent()));
530-
Runtime.getRuntime().exit(0);
531-
}
532-
533503
// endregion
534504

535505
// Method to wake up the screen and dismiss the keyguard

app/src/main/java/org/thoughtcrime/securesms/debugmenu/DebugMenuViewModel.kt

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import org.session.libsignal.utilities.Log
1616
import org.thoughtcrime.securesms.ApplicationContext
1717
import org.thoughtcrime.securesms.dependencies.ConfigFactory
1818
import org.session.libsession.messaging.groups.LegacyGroupDeprecationManager
19+
import org.thoughtcrime.securesms.util.ClearDataUtils
1920
import java.time.ZonedDateTime
2021
import javax.inject.Inject
2122

@@ -25,6 +26,7 @@ class DebugMenuViewModel @Inject constructor(
2526
private val textSecurePreferences: TextSecurePreferences,
2627
private val configFactory: ConfigFactory,
2728
private val deprecationManager: LegacyGroupDeprecationManager,
29+
private val clearDataUtils: ClearDataUtils
2830
) : ViewModel() {
2931
private val TAG = "DebugMenu"
3032

@@ -86,7 +88,7 @@ class DebugMenuViewModel @Inject constructor(
8688
// restart app
8789
viewModelScope.launch {
8890
delay(500) // giving time to save data
89-
ApplicationContext.getInstance(application).restartApplication()
91+
clearDataUtils.restartApplication()
9092
}
9193
}
9294

@@ -128,21 +130,21 @@ class DebugMenuViewModel @Inject constructor(
128130

129131
// clear remote and local data, then restart the app
130132
viewModelScope.launch {
131-
ApplicationContext.getInstance(application).clearAllData().let { success ->
132-
if(success){
133-
// save the environment
134-
textSecurePreferences.setEnvironment(env)
135-
delay(500)
136-
ApplicationContext.getInstance(application).restartApplication()
137-
} else {
138-
_uiState.value = _uiState.value.copy(
139-
showEnvironmentWarningDialog = false,
140-
showLoadingDialog = false
141-
)
142-
Log.e(TAG, "Failed to force sync when deleting data")
143-
_uiState.value = _uiState.value.copy(snackMessage = "Sorry, something went wrong...")
144-
return@launch
145-
}
133+
val success = runCatching { clearDataUtils.clearAllData() } .isSuccess
134+
135+
if(success){
136+
// save the environment
137+
textSecurePreferences.setEnvironment(env)
138+
delay(500)
139+
clearDataUtils.restartApplication()
140+
} else {
141+
_uiState.value = _uiState.value.copy(
142+
showEnvironmentWarningDialog = false,
143+
showLoadingDialog = false
144+
)
145+
Log.e(TAG, "Failed to force sync when deleting data")
146+
_uiState.value = _uiState.value.copy(snackMessage = "Sorry, something went wrong...")
147+
return@launch
146148
}
147149
}
148150
}

app/src/main/java/org/thoughtcrime/securesms/notifications/PushReceiver.kt

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import org.session.libsession.utilities.ConfigMessage
2626
import org.session.libsession.utilities.bencode.Bencode
2727
import org.session.libsession.utilities.bencode.BencodeList
2828
import org.session.libsession.utilities.bencode.BencodeString
29+
import org.session.libsession.utilities.getGroup
2930
import org.session.libsignal.protos.SignalServiceProtos.Envelope
3031
import org.session.libsignal.utilities.AccountId
3132
import org.session.libsignal.utilities.Base64
@@ -62,14 +63,8 @@ class PushReceiver @Inject constructor(
6263
}
6364

6465
private fun addMessageReceiveJob(pushData: PushData?) {
65-
// send a generic notification if we have no data
66-
if (pushData?.data == null) {
67-
sendGenericNotification()
68-
return
69-
}
70-
7166
try {
72-
val namespace = pushData.metadata?.namespace
67+
val namespace = pushData?.metadata?.namespace
7368
val params = when {
7469
namespace == Namespace.GROUP_MESSAGES() ||
7570
namespace == Namespace.REVOKED_GROUP_MESSAGES() ||
@@ -80,6 +75,17 @@ class PushReceiver @Inject constructor(
8075
"Received a closed group message push notification without an account ID"
8176
})
8277

78+
if (configFactory.getGroup(groupId)?.shouldPoll != true) {
79+
Log.d(TAG, "Received a push notification for a group that isn't active")
80+
return
81+
}
82+
83+
// send a generic notification if we have no data
84+
if (pushData.data == null) {
85+
sendGenericNotification()
86+
return
87+
}
88+
8389
if (namespace == Namespace.GROUP_MESSAGES()) {
8490
val envelope = checkNotNull(tryDecryptGroupEnvelope(groupId, pushData.data)) {
8591
"Unable to decrypt closed group message"
@@ -125,7 +131,13 @@ class PushReceiver @Inject constructor(
125131
}
126132
}
127133

128-
namespace == Namespace.DEFAULT() || pushData.metadata == null -> {
134+
namespace == Namespace.DEFAULT() || pushData?.metadata == null -> {
135+
// send a generic notification if we have no data
136+
if (pushData?.data == null) {
137+
sendGenericNotification()
138+
return
139+
}
140+
129141
val envelopeAsData = MessageWrapper.unwrap(pushData.data).toByteArray()
130142
MessageReceiveParameters(
131143
data = envelopeAsData,

app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsViewModel.kt

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ import kotlinx.coroutines.flow.update
1616
import kotlinx.coroutines.launch
1717
import network.loki.messenger.R
1818
import org.session.libsession.utilities.TextSecurePreferences
19-
import org.thoughtcrime.securesms.ApplicationContext
2019
import org.thoughtcrime.securesms.onboarding.manager.CreateAccountManager
20+
import org.thoughtcrime.securesms.util.ClearDataUtils
2121

2222
internal class MessageNotificationsViewModel(
2323
private val state: State,
2424
private val application: Application,
2525
private val prefs: TextSecurePreferences,
26-
private val createAccountManager: CreateAccountManager
26+
private val createAccountManager: CreateAccountManager,
27+
private val clearDataUtils: ClearDataUtils,
2728
): AndroidViewModel(application) {
2829
private val _uiStates = MutableStateFlow(UiState())
2930
val uiStates = _uiStates.asStateFlow()
@@ -71,8 +72,8 @@ internal class MessageNotificationsViewModel(
7172
fun quit() {
7273
_uiStates.update { it.copy(clearData = true) }
7374

74-
viewModelScope.launch(Dispatchers.IO) {
75-
ApplicationContext.getInstance(application).clearAllDataAndRestart()
75+
viewModelScope.launch {
76+
clearDataUtils.clearAllDataAndRestart()
7677
}
7778
}
7879

@@ -100,14 +101,16 @@ internal class MessageNotificationsViewModel(
100101
private val application: Application,
101102
private val prefs: TextSecurePreferences,
102103
private val createAccountManager: CreateAccountManager,
104+
private val clearDataUtils: ClearDataUtils,
103105
) : ViewModelProvider.Factory {
104106

105107
override fun <T : ViewModel> create(modelClass: Class<T>): T {
106108
return MessageNotificationsViewModel(
107109
state = profileName?.let(State::CreateAccount) ?: State.LoadAccount,
108110
application = application,
109111
prefs = prefs,
110-
createAccountManager = createAccountManager
112+
createAccountManager = createAccountManager,
113+
clearDataUtils = clearDataUtils,
111114
) as T
112115
}
113116
}

app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import org.session.libsignal.utilities.Log
2525
import org.thoughtcrime.securesms.ApplicationContext
2626
import org.thoughtcrime.securesms.createSessionDialog
2727
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
28+
import org.thoughtcrime.securesms.util.ClearDataUtils
2829
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
2930
import javax.inject.Inject
3031

@@ -37,6 +38,9 @@ class ClearAllDataDialog : DialogFragment() {
3738
@Inject
3839
lateinit var storage: StorageProtocol
3940

41+
@Inject
42+
lateinit var clearDataUtils: ClearDataUtils
43+
4044
private enum class Steps {
4145
INFO_PROMPT,
4246
NETWORK_PROMPT,
@@ -123,13 +127,15 @@ class ClearAllDataDialog : DialogFragment() {
123127
}
124128

125129
private suspend fun performDeleteLocalDataOnlyStep() {
126-
ApplicationContext.getInstance(context).clearAllDataAndRestart().let { success ->
127-
withContext(Main) {
128-
if (success) {
129-
dismissAllowingStateLoss()
130-
} else {
131-
Toast.makeText(ApplicationContext.getInstance(requireContext()), R.string.errorUnknown, Toast.LENGTH_LONG).show()
132-
}
130+
val result = runCatching {
131+
clearDataUtils.clearAllDataAndRestart()
132+
}
133+
134+
withContext(Main) {
135+
if (result.isSuccess) {
136+
dismissAllowingStateLoss()
137+
} else {
138+
Toast.makeText(ApplicationContext.getInstance(requireContext()), R.string.errorUnknown, Toast.LENGTH_LONG).show()
133139
}
134140
}
135141
}
@@ -160,15 +166,7 @@ class ClearAllDataDialog : DialogFragment() {
160166
}
161167
else if (deletionResultMap.values.all { it }) {
162168
// ..otherwise if the network data deletion was successful proceed to delete the local data as well.
163-
ApplicationContext.getInstance(context).clearAllDataAndRestart().let { success ->
164-
withContext(Main) {
165-
if (success) {
166-
dismissAllowingStateLoss()
167-
} else {
168-
Toast.makeText(ApplicationContext.getInstance(requireContext()), R.string.errorUnknown, Toast.LENGTH_LONG).show()
169-
}
170-
}
171-
}
169+
performDeleteLocalDataOnlyStep()
172170
}
173171
}
174172
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.thoughtcrime.securesms.util
2+
3+
import android.annotation.SuppressLint
4+
import android.app.Application
5+
import android.content.Intent
6+
import com.google.firebase.messaging.FirebaseMessaging
7+
import kotlinx.coroutines.Dispatchers
8+
import kotlinx.coroutines.delay
9+
import kotlinx.coroutines.withContext
10+
import org.session.libsession.utilities.TextSecurePreferences
11+
import org.session.libsignal.utilities.Log
12+
import org.thoughtcrime.securesms.ApplicationContext
13+
import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper
14+
import org.thoughtcrime.securesms.dependencies.ConfigFactory
15+
import org.thoughtcrime.securesms.home.HomeActivity
16+
import javax.inject.Inject
17+
import androidx.core.content.edit
18+
import kotlinx.coroutines.tasks.await
19+
20+
class ClearDataUtils @Inject constructor(
21+
private val application: Application,
22+
private val configFactory: ConfigFactory,
23+
) {
24+
// Method to clear the local data - returns true on success otherwise false
25+
@SuppressLint("ApplySharedPref")
26+
suspend fun clearAllData() {
27+
return withContext(Dispatchers.Default) {
28+
// Should not proceed if we can't delete db
29+
check(application.deleteDatabase(SQLCipherOpenHelper.DATABASE_NAME)) {
30+
"Failed to delete database"
31+
}
32+
33+
TextSecurePreferences.clearAll(application)
34+
application.getSharedPreferences(ApplicationContext.PREFERENCES_NAME, 0).edit(commit = true) { clear() }
35+
configFactory.clearAll()
36+
37+
// The token deletion is nice but not critical, so don't let it block the rest of the process
38+
runCatching {
39+
FirebaseMessaging.getInstance().deleteToken().await()
40+
}.onFailure { e ->
41+
Log.w("ClearDataUtils", "Failed to delete Firebase token: ${e.message}", e)
42+
}
43+
}
44+
}
45+
46+
/**
47+
* Clear all local profile data and message history then restart the app after a brief delay.
48+
* @return true on success, false otherwise.
49+
*/
50+
@SuppressLint("ApplySharedPref")
51+
suspend fun clearAllDataAndRestart() {
52+
clearAllData()
53+
delay(200)
54+
restartApplication()
55+
}
56+
57+
fun restartApplication() {
58+
val intent = Intent(application, HomeActivity::class.java)
59+
application.startActivity(Intent.makeRestartActivityTask(intent.component))
60+
Runtime.getRuntime().exit(0)
61+
}
62+
63+
}

app/src/play/kotlin/org/thoughtcrime/securesms/notifications/FirebaseTokenFetcher.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ package org.thoughtcrime.securesms.notifications
22

33
import com.google.firebase.messaging.FirebaseMessaging
44
import kotlinx.coroutines.flow.MutableStateFlow
5-
import kotlinx.coroutines.flow.StateFlow
6-
7-
import kotlinx.coroutines.tasks.await
85
import org.session.libsession.messaging.notifications.TokenFetcher
96
import javax.inject.Inject
107
import javax.inject.Singleton

app/src/test/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModelTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class ConversationViewModelTest: BaseViewModelTest() {
4949
configFactory = mock(),
5050
groupManagerV2 = mock(),
5151
legacyGroupDeprecationManager = mock(),
52+
expiredGroupManager = mock()
5253
)
5354
}
5455

0 commit comments

Comments
 (0)