Merge pull request #3143 from deltachat/adb/issue-3126

allow to enable/disable notifications per-account
This commit is contained in:
Asiel Díaz Benítez 2024-07-13 17:26:11 +02:00 committed by GitHub
commit 307e4575b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 50 additions and 50 deletions

View file

@ -236,6 +236,14 @@ public class DcContext {
return getConfigInt("is_chatmail") == 1; return getConfigInt("is_chatmail") == 1;
} }
public boolean isMuted() {
return getConfigInt("is_muted") == 1;
}
public void setMuted(boolean muted) {
setConfigInt("is_muted", muted? 1 : 0);
}
// Called for new profiles on chatmail servers that are "single device" initially; // Called for new profiles on chatmail servers that are "single device" initially;
// to save server disk space, we make use of that delete all messages immediately after download. // to save server disk space, we make use of that delete all messages immediately after download.
public void assumeSingleDevice() { public void assumeSingleDevice() {

View file

@ -131,15 +131,16 @@ public class ApplicationContext extends MultiDexApplication {
rpc.start(); rpc.start();
// migrating chat backgrounds, added 04/10/23, can be removed after some versions // migrating global notifications pref. to per-account config, added 10/July/24
String backgroundImagePath = Prefs.getStringPreference(this, "pref_chat_background", ""); final String NOTIFICATION_PREF = "pref_key_enable_notifications";
if (!backgroundImagePath.isEmpty()) { boolean isMuted = !Prefs.getBooleanPreference(this, NOTIFICATION_PREF, true);
if (isMuted) {
for (int accId : dcAccounts.getAll()) { for (int accId : dcAccounts.getAll()) {
Prefs.setBackgroundImagePath(this, accId, backgroundImagePath); dcAccounts.getAccount(accId).setMuted(true);
} }
Prefs.setStringPreference(this, "pref_chat_background", ""); Prefs.removePreference(this, NOTIFICATION_PREF);
} }
// /migrating chat backgrounds // /migrating global notifications
for (int accountId : allAccounts) { for (int accountId : allAccounts) {
dcAccounts.getAccount(accountId).setConfig(CONFIG_VERIFIED_ONE_ON_ONE_CHATS, "1"); dcAccounts.getAccount(accountId).setConfig(CONFIG_VERIFIED_ONE_ON_ONE_CHATS, "1");

View file

@ -287,7 +287,10 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
int skipId = dcAccounts.getSelectedAccount().getAccountId(); int skipId = dcAccounts.getSelectedAccount().getAccountId();
for (int accountId : dcAccounts.getAll()) { for (int accountId : dcAccounts.getAll()) {
if (accountId != skipId) { if (accountId != skipId) {
unreadCount += dcAccounts.getAccount(accountId).getFreshMsgs().length; DcContext dcContext = dcAccounts.getAccount(accountId);
if (!dcContext.isMuted()) {
unreadCount += dcContext.getFreshMsgs().length;
}
} }
} }

View file

@ -218,7 +218,7 @@ public class LogViewFragment extends Fragment {
PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
final PackageManager pm = context.getPackageManager(); final PackageManager pm = context.getPackageManager();
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
final DcContext dcContext = DcHelper.getContext(context);
builder.append("device=") builder.append("device=")
.append(Build.MANUFACTURER).append(" ") .append(Build.MANUFACTURER).append(" ")
@ -251,8 +251,6 @@ public class LogViewFragment extends Fragment {
builder.append("ignoreBatteryOptimizations=").append( builder.append("ignoreBatteryOptimizations=").append(
powerManager.isIgnoringBatteryOptimizations(context.getPackageName())).append("\n"); powerManager.isIgnoringBatteryOptimizations(context.getPackageName())).append("\n");
} }
builder.append("notifications=").append(
Prefs.isNotificationsEnabled(context)).append("\n");
builder.append("reliableService=").append( builder.append("reliableService=").append(
Prefs.reliableService(context)).append("\n"); Prefs.reliableService(context)).append("\n");
@ -271,7 +269,6 @@ public class LogViewFragment extends Fragment {
} }
builder.append("\n"); builder.append("\n");
DcContext dcContext = DcHelper.getContext(context);
builder.append(dcContext.getInfo()); builder.append(dcContext.getInfo());
return builder.toString(); return builder.toString();

View file

@ -39,7 +39,7 @@ public class AccountSelectionListAdapter extends RecyclerView.Adapter
super(itemView); super(itemView);
} }
public abstract void bind(@NonNull GlideRequests glideRequests, int accountId, DcContact self, String name, String addr, int unreadCount, boolean selected); public abstract void bind(@NonNull GlideRequests glideRequests, int accountId, DcContact self, String name, String addr, int unreadCount, boolean selected, boolean isMuted);
public abstract void unbind(@NonNull GlideRequests glideRequests); public abstract void unbind(@NonNull GlideRequests glideRequests);
} }
@ -64,8 +64,8 @@ public class AccountSelectionListAdapter extends RecyclerView.Adapter
return (AccountSelectionListItem) itemView; return (AccountSelectionListItem) itemView;
} }
public void bind(@NonNull GlideRequests glideRequests, int accountId, DcContact self, String name, String addr, int unreadCount, boolean selected) { public void bind(@NonNull GlideRequests glideRequests, int accountId, DcContact self, String name, String addr, int unreadCount, boolean selected, boolean isMuted) {
getView().bind(glideRequests, accountId, self, name, addr, unreadCount, selected); getView().bind(glideRequests, accountId, self, name, addr, unreadCount, selected, isMuted);
} }
@Override @Override
@ -100,11 +100,11 @@ public class AccountSelectionListAdapter extends RecyclerView.Adapter
String name; String name;
String addr = null; String addr = null;
int unreadCount = 0; int unreadCount = 0;
DcContext dcContext = accounts.getAccount(id);
if (id == DcContact.DC_CONTACT_ID_ADD_ACCOUNT) { if (id == DcContact.DC_CONTACT_ID_ADD_ACCOUNT) {
name = context.getString(R.string.add_account); name = context.getString(R.string.add_account);
} else { } else {
DcContext dcContext = accounts.getAccount(id);
dcContact = dcContext.getContact(DcContact.DC_CONTACT_ID_SELF); dcContact = dcContext.getContact(DcContact.DC_CONTACT_ID_SELF);
addr = dcContact.getAddr(); addr = dcContact.getAddr();
name = dcContext.getConfig("displayname"); name = dcContext.getConfig("displayname");
@ -116,7 +116,7 @@ public class AccountSelectionListAdapter extends RecyclerView.Adapter
ViewHolder holder = (ViewHolder) viewHolder; ViewHolder holder = (ViewHolder) viewHolder;
holder.unbind(glideRequests); holder.unbind(glideRequests);
holder.bind(glideRequests, id, dcContact, name, addr, unreadCount, id == selectedAccountId); holder.bind(glideRequests, id, dcContact, name, addr, unreadCount, id == selectedAccountId, dcContext.isMuted());
} }
public interface ItemClickListener { public interface ItemClickListener {

View file

@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.ViewUtil; import org.thoughtcrime.securesms.util.ViewUtil;
public class AccountSelectionListItem extends LinearLayout { public class AccountSelectionListItem extends LinearLayout {
@ -57,7 +58,7 @@ public class AccountSelectionListItem extends LinearLayout {
ViewUtil.setTextViewGravityStart(this.nameView, getContext()); ViewUtil.setTextViewGravityStart(this.nameView, getContext());
} }
public void bind(@NonNull GlideRequests glideRequests, int accountId, DcContact self, String name, String addr, int unreadCount, boolean selected) { public void bind(@NonNull GlideRequests glideRequests, int accountId, DcContact self, String name, String addr, int unreadCount, boolean selected, boolean isMuted) {
this.accountId = accountId; this.accountId = accountId;
Recipient recipient; Recipient recipient;
@ -70,6 +71,8 @@ public class AccountSelectionListItem extends LinearLayout {
} }
this.contactPhotoImage.setAvatar(glideRequests, recipient, false); this.contactPhotoImage.setAvatar(glideRequests, recipient, false);
nameView.setCompoundDrawablesWithIntrinsicBounds(isMuted? R.drawable.ic_volume_off_grey600_18dp : 0, 0, 0, 0);
if (selected) { if (selected) {
addrView.setTypeface(null, Typeface.BOLD); addrView.setTypeface(null, Typeface.BOLD);
nameView.setTypeface(null, Typeface.BOLD); nameView.setTypeface(null, Typeface.BOLD);
@ -80,7 +83,7 @@ public class AccountSelectionListItem extends LinearLayout {
checkbox.setVisibility(View.GONE); checkbox.setVisibility(View.GONE);
} }
updateUnreadIndicator(unreadCount); updateUnreadIndicator(unreadCount, isMuted);
setText(name, addr); setText(name, addr);
} }
@ -88,10 +91,11 @@ public class AccountSelectionListItem extends LinearLayout {
contactPhotoImage.clear(glideRequests); contactPhotoImage.clear(glideRequests);
} }
private void updateUnreadIndicator(int unreadCount) { private void updateUnreadIndicator(int unreadCount, boolean isMuted) {
if(unreadCount == 0) { if(unreadCount == 0) {
unreadIndicator.setVisibility(View.GONE); unreadIndicator.setVisibility(View.GONE);
} else { } else {
final int color = getResources().getColor(isMuted ? (ThemeUtil.isDarkTheme(getContext()) ? R.color.unread_count_muted_dark : R.color.unread_count_muted) : R.color.unread_count);
unreadIndicator.setImageDrawable(TextDrawable.builder() unreadIndicator.setImageDrawable(TextDrawable.builder()
.beginConfig() .beginConfig()
.width(ViewUtil.dpToPx(getContext(), 24)) .width(ViewUtil.dpToPx(getContext(), 24))
@ -99,7 +103,7 @@ public class AccountSelectionListItem extends LinearLayout {
.textColor(Color.WHITE) .textColor(Color.WHITE)
.bold() .bold()
.endConfig() .endConfig()
.buildRound(String.valueOf(unreadCount), getResources().getColor(R.color.unread_count))); .buildRound(String.valueOf(unreadCount), color));
unreadIndicator.setVisibility(View.VISIBLE); unreadIndicator.setVisibility(View.VISIBLE);
} }
} }

View file

@ -29,7 +29,7 @@ public class KeepAliveService extends Service {
// note, that unfortunately, the check for isIgnoringBatteryOptimizations() is not sufficient, // note, that unfortunately, the check for isIgnoringBatteryOptimizations() is not sufficient,
// this checks only stock-android settings, several os have additional "optimizers" that ignore this setting. // this checks only stock-android settings, several os have additional "optimizers" that ignore this setting.
// therefore, the most reliable way to not get killed is a permanent-foreground-notification. // therefore, the most reliable way to not get killed is a permanent-foreground-notification.
if (Prefs.isNotificationsEnabled(context) && Prefs.reliableService(context)) { if (Prefs.reliableService(context)) {
startSelf(context); startSelf(context);
} }
} }

View file

@ -333,7 +333,7 @@ public class NotificationCenter {
DcChat dcChat = dcContext.getChat(chatId); DcChat dcChat = dcContext.getChat(chatId);
ChatData chatData = new ChatData(accountId, chatId); ChatData chatData = new ChatData(accountId, chatId);
if (!Prefs.isNotificationsEnabled(context) || dcChat.isMuted()) { if (dcContext.isMuted() || dcChat.isMuted()) {
return; return;
} }
@ -598,7 +598,7 @@ public class NotificationCenter {
} }
public void maybePlaySendSound(DcChat dcChat) { public void maybePlaySendSound(DcChat dcChat) {
if (Prefs.isInChatNotifications(context) && Prefs.isNotificationsEnabled(context) && !dcChat.isMuted()) { if (Prefs.isInChatNotifications(context) && !dcChat.isMuted()) {
InChatSounds.getInstance(context).playSendSound(); InChatSounds.getInstance(context).playSendSound();
} }
} }

View file

@ -29,13 +29,13 @@ import org.thoughtcrime.securesms.notifications.FcmReceiveService;
import org.thoughtcrime.securesms.util.Prefs; import org.thoughtcrime.securesms.util.Prefs;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ONLY_FETCH_MVBOX;
public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragment { public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragment {
private static final int REQUEST_CODE_NOTIFICATION_SELECTED = 1; private static final int REQUEST_CODE_NOTIFICATION_SELECTED = 1;
private CheckBoxPreference ignoreBattery; private CheckBoxPreference ignoreBattery;
private CheckBoxPreference notificationsEnabled;
@Override @Override
public void onCreate(Bundle paramBundle) { public void onCreate(Bundle paramBundle) {
@ -106,7 +106,7 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
reliableService.setOnPreferenceChangeListener((preference, newValue) -> { reliableService.setOnPreferenceChangeListener((preference, newValue) -> {
Context context = getContext(); Context context = getContext();
boolean enabled = (Boolean) newValue; // Prefs.reliableService() still has the old value boolean enabled = (Boolean) newValue; // Prefs.reliableService() still has the old value
if (enabled && Prefs.isNotificationsEnabled(context)) { if (enabled) {
KeepAliveService.startSelf(context); KeepAliveService.startSelf(context);
} else { } else {
context.stopService(new Intent(context, KeepAliveService.class)); context.stopService(new Intent(context, KeepAliveService.class));
@ -114,15 +114,10 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
return true; return true;
}); });
CheckBoxPreference notificationsEnabled = this.findPreference("pref_key_enable_notifications"); notificationsEnabled = this.findPreference("pref_enable_notifications");
notificationsEnabled.setOnPreferenceChangeListener((preference, newValue) -> { notificationsEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
Context context = getContext(); boolean enabled = (Boolean) newValue;
boolean enabled = (Boolean) newValue; // Prefs.isNotificationsEnabled() still has the old value dcContext.setMuted(!enabled);
if (enabled && Prefs.reliableService(context)) {
KeepAliveService.startSelf(context);
} else {
context.stopService(new Intent(context, KeepAliveService.class));
}
return true; return true;
}); });
} }
@ -139,6 +134,7 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
// update ignoreBattery in onResume() to reflects changes done in the system settings // update ignoreBattery in onResume() to reflects changes done in the system settings
ignoreBattery.setChecked(isIgnoringBatteryOptimizations()); ignoreBattery.setChecked(isIgnoringBatteryOptimizations());
notificationsEnabled.setChecked(!dcContext.isMuted());
} }
@Override @Override
@ -237,7 +233,7 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
public static CharSequence getSummary(Context context) { public static CharSequence getSummary(Context context) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || notificationManager.areNotificationsEnabled()) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || notificationManager.areNotificationsEnabled()) {
return context.getString(Prefs.isNotificationsEnabled(context) ? R.string.on : R.string.off); return context.getString(DcHelper.getContext(context).isMuted() ? R.string.off : R.string.on);
} else { } else {
return context.getString(R.string.disabled_in_system_settings); return context.getString(R.string.disabled_in_system_settings);
} }

View file

@ -40,7 +40,6 @@ public class Prefs {
public static final String RINGTONE_PREF = "pref_key_ringtone"; public static final String RINGTONE_PREF = "pref_key_ringtone";
private static final String VIBRATE_PREF = "pref_key_vibrate"; private static final String VIBRATE_PREF = "pref_key_vibrate";
private static final String CHAT_VIBRATE = "pref_chat_vibrate_"; // followed by chat-id private static final String CHAT_VIBRATE = "pref_chat_vibrate_"; // followed by chat-id
private static final String NOTIFICATION_PREF = "pref_key_enable_notifications";
public static final String LED_COLOR_PREF = "pref_led_color"; public static final String LED_COLOR_PREF = "pref_led_color";
private static final String CHAT_RINGTONE = "pref_chat_ringtone_"; // followed by chat-id private static final String CHAT_RINGTONE = "pref_chat_ringtone_"; // followed by chat-id
public static final String SCREEN_SECURITY_PREF = "pref_screen_security"; public static final String SCREEN_SECURITY_PREF = "pref_screen_security";
@ -168,10 +167,6 @@ public class Prefs {
return getIntegerPreference(context, PROMPTED_DOZE_MSG_ID_PREF, 0); return getIntegerPreference(context, PROMPTED_DOZE_MSG_ID_PREF, 0);
} }
public static boolean isNotificationsEnabled(Context context) {
return getBooleanPreference(context, NOTIFICATION_PREF, true);
}
public static boolean isPushEnabled(Context context) { public static boolean isPushEnabled(Context context) {
return BuildConfig.USE_PLAY_SERVICES && getBooleanPreference(context, "pref_push_enabled", true); return BuildConfig.USE_PLAY_SERVICES && getBooleanPreference(context, "pref_push_enabled", true);
} }
@ -326,7 +321,7 @@ public class Prefs {
PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(key, value).apply(); PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(key, value).apply();
} }
private static void removePreference(Context context, String key) { public static void removePreference(Context context, String key) {
PreferenceManager.getDefaultSharedPreferences(context).edit().remove(key).apply(); PreferenceManager.getDefaultSharedPreferences(context).edit().remove(key).apply();
} }

View file

@ -3,19 +3,19 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat <org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:key="pref_key_enable_notifications" android:key="pref_enable_notifications"
android:title="@string/pref_notifications" android:title="@string/pref_notifications"
android:defaultValue="true" /> android:defaultValue="true" />
<Preference <Preference
android:dependency="pref_key_enable_notifications" android:dependency="pref_enable_notifications"
android:key="pref_key_ringtone" android:key="pref_key_ringtone"
android:title="@string/pref_sound" android:title="@string/pref_sound"
android:persistent="false" android:persistent="false"
android:defaultValue="content://settings/system/notification_sound" /> android:defaultValue="content://settings/system/notification_sound" />
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat <org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:dependency="pref_key_enable_notifications" android:dependency="pref_enable_notifications"
android:key="pref_key_vibrate" android:key="pref_key_vibrate"
android:defaultValue="true" android:defaultValue="true"
android:title="@string/pref_vibrate"/> android:title="@string/pref_vibrate"/>
@ -24,14 +24,14 @@
android:key="pref_led_color" android:key="pref_led_color"
android:defaultValue="purple" android:defaultValue="purple"
android:title="@string/pref_led_color" android:title="@string/pref_led_color"
android:dependency="pref_key_enable_notifications" android:dependency="pref_enable_notifications"
android:entries="@array/pref_led_color_entries" android:entries="@array/pref_led_color_entries"
android:entryValues="@array/pref_led_color_values" /> android:entryValues="@array/pref_led_color_values" />
<ListPreference <ListPreference
android:key="pref_notification_privacy" android:key="pref_notification_privacy"
android:title="@string/pref_notifications_show" android:title="@string/pref_notifications_show"
android:dependency="pref_key_enable_notifications" android:dependency="pref_enable_notifications"
android:defaultValue="all" android:defaultValue="all"
android:entries="@array/pref_notification_privacy_entries" android:entries="@array/pref_notification_privacy_entries"
android:entryValues="@array/pref_notification_privacy_values"/> android:entryValues="@array/pref_notification_privacy_values"/>
@ -39,35 +39,31 @@
<ListPreference <ListPreference
android:key="pref_notification_priority" android:key="pref_notification_priority"
android:title="@string/pref_notifications_priority" android:title="@string/pref_notifications_priority"
android:dependency="pref_key_enable_notifications" android:dependency="pref_enable_notifications"
android:defaultValue="1" android:defaultValue="1"
android:entries="@array/pref_notification_priority_entries" android:entries="@array/pref_notification_priority_entries"
android:entryValues="@array/pref_notification_priority_values"/> android:entryValues="@array/pref_notification_priority_values"/>
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat <org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:key="pref_key_inthread_notifications" android:key="pref_key_inthread_notifications"
android:dependency="pref_key_enable_notifications"
android:title="@string/pref_in_chat_sounds" android:title="@string/pref_in_chat_sounds"
android:defaultValue="true" /> android:defaultValue="true" />
<PreferenceCategory android:title="@string/pref_instant_delivery"> <PreferenceCategory android:title="@string/pref_instant_delivery">
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat <org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:key="pref_push_enabled" android:key="pref_push_enabled"
android:dependency="pref_key_enable_notifications"
android:defaultValue="true" android:defaultValue="true"
android:title="@string/pref_push_notifications" android:title="@string/pref_push_notifications"
android:summary="@string/pref_push_notifications_explain"/> android:summary="@string/pref_push_notifications_explain"/>
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat <org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:key="pref_ignore_battery_optimizations" android:key="pref_ignore_battery_optimizations"
android:dependency="pref_key_enable_notifications"
android:defaultValue="false" android:defaultValue="false"
android:title="@string/pref_background_notifications" android:title="@string/pref_background_notifications"
android:summary="@string/pref_background_notifications_explain"/> android:summary="@string/pref_background_notifications_explain"/>
<org.thoughtcrime.securesms.components.SwitchPreferenceCompat <org.thoughtcrime.securesms.components.SwitchPreferenceCompat
android:key="pref_reliable_service" android:key="pref_reliable_service"
android:dependency="pref_key_enable_notifications"
android:defaultValue="false" android:defaultValue="false"
android:title="@string/pref_reliable_service" android:title="@string/pref_reliable_service"
android:summary="@string/pref_reliable_service_explain"/> android:summary="@string/pref_reliable_service_explain"/>