Add switch preference for notifications while locked

This commit is contained in:
Oscar Mira 2023-11-15 18:35:40 +01:00
parent 8268817216
commit bb6644505b
11 changed files with 70 additions and 22 deletions

View file

@ -18,6 +18,7 @@ import androidx.annotation.RequiresApi
import androidx.core.content.ContextCompat
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.signal.core.util.getParcelableExtraCompat
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
@ -276,6 +277,25 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__
sectionHeaderPref(R.string.NotificationsSettingsFragment__notify_when)
switchPref(
title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__new_activity_while_locked),
summary = DSLSettingsText.from(R.string.NotificationsSettingsFragment__receive_notifications_for_messages_or_missed_calls_when_the_app_is_locked),
isChecked = state.notifyWhileLocked,
onToggle = { isChecked ->
if (isChecked && !state.canEnableNotifyWhileLocked) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.NotificationsSettingsFragment__push_notifications_unavailable)
.setMessage(R.string.NotificationsSettingsFragment__sorry_this_feature_requires_push_notifications_delivered_via_fcm_or_unifiedpush)
.setPositiveButton(android.R.string.ok, null)
.show()
false
} else {
viewModel.setNotifyWhileLocked(isChecked)
true
}
}
)
switchPref(
title = DSLSettingsText.from(R.string.NotificationsSettingsFragment__contact_joins_signal),
isChecked = state.notifyWhenContactJoinsSignal,

View file

@ -5,6 +5,8 @@ import android.net.Uri
data class NotificationsSettingsState(
val messageNotificationsState: MessageNotificationsState,
val callNotificationsState: CallNotificationsState,
val notifyWhileLocked: Boolean,
val canEnableNotifyWhileLocked: Boolean,
val notifyWhenContactJoinsSignal: Boolean
)

View file

@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.components.settings.app.notifications
import android.app.Application
import android.content.SharedPreferences
import android.net.Uri
import android.os.Build
@ -17,6 +18,8 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer
private val store = Store(getState())
private val application: Application = ApplicationDependencies.getApplication()
val state: LiveData<NotificationsSettingsState> = store.stateLiveData
init {
@ -96,6 +99,11 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer
refresh()
}
fun setNotifyWhileLocked(enabled: Boolean) {
TextSecurePreferences.setPassphraseLockNotificationsEnabled(application, enabled)
refresh()
}
fun setNotifyWhenContactJoinsSignal(enabled: Boolean) {
SignalStore.settings().isNotifyWhenContactJoinsSignal = enabled
refresh()
@ -117,7 +125,7 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer
inChatSoundsEnabled = SignalStore.settings().isMessageNotificationsInChatSoundsEnabled,
repeatAlerts = SignalStore.settings().messageNotificationsRepeatAlerts,
messagePrivacy = SignalStore.settings().messageNotificationsPrivacy.toString(),
priority = TextSecurePreferences.getNotificationPriority(ApplicationDependencies.getApplication()),
priority = TextSecurePreferences.getNotificationPriority(application),
),
callNotificationsState = CallNotificationsState(
notificationsEnabled = SignalStore.settings().isCallNotificationsEnabled && canEnableNotifications(),
@ -125,6 +133,8 @@ class NotificationsSettingsViewModel(private val sharedPreferences: SharedPrefer
ringtone = SignalStore.settings().callRingtone,
vibrateEnabled = SignalStore.settings().isCallVibrateEnabled
),
notifyWhileLocked = TextSecurePreferences.isPassphraseLockNotificationsEnabled(application) && SignalStore.account().pushAvailable,
canEnableNotifyWhileLocked = SignalStore.account().pushAvailable,
notifyWhenContactJoinsSignal = SignalStore.settings().isNotifyWhenContactJoinsSignal
)

View file

@ -73,10 +73,13 @@ object FcmFetchManager {
@JvmStatic
fun postMayHaveMessagesNotification(context: Context) {
if (FeatureFlags.fcmMayHaveMessagesNotificationKillSwitch()) {
Log.w(TAG, "May have messages notification kill switch")
val notificationManager = NotificationManagerCompat.from(context)
if (notificationManager.getNotificationChannel(NotificationChannels.ADDITIONAL_MESSAGE_NOTIFICATIONS) == null) {
Log.e(TAG, "Notification channel for MAY_HAVE_MESSAGES_NOTIFICATION does not exist.")
return
}
val mayHaveMessagesNotification: Notification = NotificationCompat.Builder(context, NotificationChannels.ADDITIONAL_MESSAGE_NOTIFICATIONS)
.setSmallIcon(R.drawable.ic_notification)
.setColor(ContextCompat.getColor(context, R.color.core_ultramarine))
@ -87,7 +90,7 @@ object FcmFetchManager {
.setOnlyAlertOnce(true)
.build()
NotificationManagerCompat.from(context)
notificationManager
.notify(NotificationIds.MAY_HAVE_MESSAGES_NOTIFICATION_ID, mayHaveMessagesNotification)
}

View file

@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.registration.PushChallengeRequest;
import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.NetworkUtil;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.util.Locale;
@ -26,10 +27,11 @@ public class FcmReceiveService extends FirebaseMessagingService {
private static final String TAG = Log.tag(FcmReceiveService.class);
@Override
public void onMessageReceived(RemoteMessage remoteMessage) {
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
if (KeyCachingService.isLocked()) {
if (remoteMessage != null && remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH) {
Log.d(TAG, "New urgent message received while the db is locked");
if (remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH &&
TextSecurePreferences.isPassphraseLockNotificationsEnabled(this)) {
Log.d(TAG, "New urgent message received while app is locked.");
FcmFetchManager.postMayHaveMessagesNotification(this);
}
return;
@ -67,7 +69,7 @@ public class FcmReceiveService extends FirebaseMessagingService {
}
@Override
public void onNewToken(String token) {
public void onNewToken(@NonNull String token) {
Log.i(TAG, "onNewToken()");
if (KeyCachingService.isLocked()) {

View file

@ -291,6 +291,10 @@ internal class AccountValues internal constructor(store: KeyValueStore) : Signal
@get:JvmName("isFcmEnabled")
var fcmEnabled: Boolean by booleanValue(KEY_FCM_ENABLED, false)
@get:JvmName("isPushAvailable")
val pushAvailable: Boolean
get() = fcmEnabled
/** The FCM token, which allows the server to send us FCM messages. */
var fcmToken: String?
get() {

View file

@ -569,13 +569,6 @@ public final class FeatureFlags {
return getBoolean(ANY_ADDRESS_PORTS_KILL_SWITCH, false);
}
/**
* Enable/disable for notification when we cannot fetch messages despite receiving an urgent push.
*/
public static boolean fcmMayHaveMessagesNotificationKillSwitch() {
return getBoolean(FCM_MAY_HAVE_MESSAGES_KILL_SWITCH, false);
}
public static boolean editMessageSending() {
return getBoolean(EDIT_MESSAGE_SEND, false);
}

View file

@ -29,6 +29,7 @@ public class SecurePreferenceManager {
case TextSecurePreferences.THEME_PREF:
case TextSecurePreferences.LANGUAGE_PREF:
case TextSecurePreferences.PASSPHRASE_LOCK:
case TextSecurePreferences.PASSPHRASE_LOCK_NOTIFICATIONS:
case TextSecurePreferences.BIOMETRIC_SCREEN_LOCK:
case TextSecurePreferences.FIRST_INSTALL_VERSION:
case TextSecurePreferences.SYSTEM_EMOJI_PREF:

View file

@ -47,7 +47,6 @@ public class TextSecurePreferences {
private static final String TAG = Log.tag(TextSecurePreferences.class);
public static final String CHANGE_PASSPHRASE_PREF = "pref_change_passphrase";
public static final String THEME_PREF = "pref_theme";
public static final String LANGUAGE_PREF = "pref_language";
@ -109,10 +108,11 @@ public class TextSecurePreferences {
public static final String TRANSFER = "pref_transfer";
public static final String PASSPHRASE_LOCK = "pref_passphrase_lock";
public static final String PASSPHRASE_LOCK_TIMEOUT = "pref_passphrase_lock_timeout";
public static final String PASSPHRASE_LOCK_TRIGGER = "pref_passphrase_lock_trigger";
public static final String BIOMETRIC_SCREEN_LOCK = "pref_biometric_screen_lock";
public static final String PASSPHRASE_LOCK = "pref_passphrase_lock";
public static final String PASSPHRASE_LOCK_TIMEOUT = "pref_passphrase_lock_timeout";
public static final String PASSPHRASE_LOCK_TRIGGER = "pref_passphrase_lock_trigger";
public static final String PASSPHRASE_LOCK_NOTIFICATIONS = "pref_passphrase_lock_notifications";
public static final String BIOMETRIC_SCREEN_LOCK = "pref_biometric_screen_lock";
private static final String NETWORK_CONFIG_SEEN = "pref_network_config_seen";
@ -220,6 +220,7 @@ public class TextSecurePreferences {
UPDATE_APK_INCLUDE_BETA,
BLOCK_UNKNOWN,
BIOMETRIC_SCREEN_LOCK,
PASSPHRASE_LOCK_NOTIFICATIONS,
};
private static final String[] stringSetPreferencesToBackupMolly = {PASSPHRASE_LOCK_TRIGGER};
@ -372,6 +373,14 @@ public class TextSecurePreferences {
return getLongPreference(context, PASSPHRASE_LOCK_TIMEOUT, 0);
}
public static boolean isPassphraseLockNotificationsEnabled(@NonNull Context context) {
return getBooleanPreference(context, PASSPHRASE_LOCK_NOTIFICATIONS, true);
}
public static void setPassphraseLockNotificationsEnabled(@NonNull Context context, boolean value) {
setBooleanPreference(context, PASSPHRASE_LOCK_NOTIFICATIONS, value);
}
public static void setHasSeenNetworkConfig(Context context, boolean value) {
setBooleanPreference(context, NETWORK_CONFIG_SEEN, value);
}

View file

@ -108,4 +108,8 @@
<string name="RegistrationActivity_link_timeout">Timed out waiting for the primary device. Ready your device to scan the QR code, then try again</string>
<string name="RegistrationActivity_link_retry">Retry linking</string>
<string name="RegistrationActivity_provider_declined">The provider has declined to send you a verification code, likely due to fraud prevention rules.</string>
<string name="NotificationsSettingsFragment__new_activity_while_locked">New activity while locked</string>
<string name="NotificationsSettingsFragment__receive_notifications_for_messages_or_missed_calls_when_the_app_is_locked">Receive notifications for messages or missed calls when the app is locked.</string>
<string name="NotificationsSettingsFragment__push_notifications_unavailable">Push notifications unavailable</string>
<string name="NotificationsSettingsFragment__sorry_this_feature_requires_push_notifications_delivered_via_fcm_or_unifiedpush">Sorry, this feature requires push notifications delivered via FCM or UnifiedPush, which are currently unavailable.</string>
</resources>

View file

@ -14,11 +14,11 @@ public abstract class FirebaseMessagingService extends Service {
return null;
}
public abstract void onMessageReceived(RemoteMessage remoteMessage);
public abstract void onMessageReceived(@NonNull RemoteMessage remoteMessage);
public abstract void onDeletedMessages();
public abstract void onNewToken(String token);
public abstract void onNewToken(@NonNull String token);
public abstract void onMessageSent(@NonNull String s);