1package eu.siacs.conversations.ui.fragment.settings;
2
3import android.app.NotificationChannel;
4import android.media.RingtoneManager;
5import android.net.Uri;
6import android.os.Build;
7import android.os.Bundle;
8import android.util.Log;
9
10import androidx.activity.result.ActivityResultLauncher;
11import androidx.annotation.NonNull;
12import androidx.annotation.Nullable;
13import androidx.preference.Preference;
14
15import com.google.common.base.Optional;
16
17import eu.siacs.conversations.AppSettings;
18import eu.siacs.conversations.Config;
19import eu.siacs.conversations.R;
20import eu.siacs.conversations.services.NotificationService;
21import eu.siacs.conversations.ui.activity.result.PickRingtone;
22import eu.siacs.conversations.utils.Compatibility;
23
24public class NotificationsSettingsFragment extends XmppPreferenceFragment {
25
26 private final ActivityResultLauncher<Uri> pickNotificationToneLauncher =
27 registerForActivityResult(
28 new PickRingtone(RingtoneManager.TYPE_NOTIFICATION),
29 result -> {
30 if (result == null) {
31 // do nothing. user aborted
32 return;
33 }
34 final Uri uri = PickRingtone.noneToNull(result);
35 appSettings().setNotificationTone(uri);
36 Log.i(Config.LOGTAG, "User set notification tone to " + uri);
37 });
38 private final ActivityResultLauncher<Uri> pickRingtoneLauncher =
39 registerForActivityResult(
40 new PickRingtone(RingtoneManager.TYPE_RINGTONE),
41 result -> {
42 if (result == null) {
43 // do nothing. user aborted
44 return;
45 }
46 final Uri uri = PickRingtone.noneToNull(result);
47 appSettings().setRingtone(uri);
48 Log.i(Config.LOGTAG, "User set ringtone to " + uri);
49 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
50 NotificationService.recreateIncomingCallChannel(requireContext(), uri);
51 }
52 });
53
54 @Override
55 public void onCreatePreferences(
56 @Nullable final Bundle savedInstanceState, final @Nullable String rootKey) {
57 setPreferencesFromResource(R.xml.preferences_notifications, rootKey);
58 final var messageNotificationSettings = findPreference("message_notification_settings");
59 final var notificationRingtone = findPreference(AppSettings.NOTIFICATION_RINGTONE);
60 final var notificationHeadsUp = findPreference(AppSettings.NOTIFICATION_HEADS_UP);
61 final var notificationVibrate = findPreference(AppSettings.NOTIFICATION_VIBRATE);
62 final var notificationLed = findPreference(AppSettings.NOTIFICATION_LED);
63 final var foregroundService = findPreference(AppSettings.KEEP_FOREGROUND_SERVICE);
64 if (messageNotificationSettings == null
65 || notificationRingtone == null
66 || notificationHeadsUp == null
67 || notificationVibrate == null
68 || notificationLed == null
69 || foregroundService == null) {
70 throw new IllegalStateException("The preference resource file is missing preferences");
71 }
72 if (Compatibility.runsTwentySix()) {
73 notificationRingtone.setVisible(false);
74 notificationHeadsUp.setVisible(false);
75 notificationVibrate.setVisible(false);
76 notificationLed.setVisible(false);
77 foregroundService.setVisible(false);
78 } else {
79 messageNotificationSettings.setVisible(false);
80 }
81 }
82
83 @Override
84 protected void onSharedPreferenceChanged(@NonNull String key) {
85 super.onSharedPreferenceChanged(key);
86 if (key.equals(AppSettings.KEEP_FOREGROUND_SERVICE)) {
87 requireService().toggleForegroundService();
88 }
89 }
90
91 @Override
92 public void onStart() {
93 super.onStart();
94 requireActivity().setTitle(R.string.notifications);
95 }
96
97 @Override
98 public boolean onPreferenceTreeClick(final Preference preference) {
99 final var key = preference.getKey();
100 if (AppSettings.RINGTONE.equals(key)) {
101 pickRingtone();
102 return true;
103 }
104 if (AppSettings.NOTIFICATION_RINGTONE.equals(key)) {
105 pickNotificationTone();
106 return true;
107 }
108 return super.onPreferenceTreeClick(preference);
109 }
110
111 private void pickNotificationTone() {
112 final Uri uri = appSettings().getNotificationTone();
113 Log.i(Config.LOGTAG, "current notification tone: " + uri);
114 this.pickNotificationToneLauncher.launch(uri);
115 }
116
117 private void pickRingtone() {
118 final Optional<Uri> channelRingtone;
119 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
120 channelRingtone =
121 NotificationService.getCurrentIncomingCallChannel(requireContext())
122 .transform(channel -> PickRingtone.nullToNone(channel.getSound()));
123 } else {
124 channelRingtone = Optional.absent();
125 }
126 final Uri uri;
127 if (channelRingtone.isPresent()) {
128 uri = channelRingtone.get();
129 Log.d(Config.LOGTAG, "ringtone came from channel");
130 } else {
131 uri = appSettings().getRingtone();
132 }
133 Log.i(Config.LOGTAG, "current ringtone: " + uri);
134 this.pickRingtoneLauncher.launch(uri);
135 }
136
137 private AppSettings appSettings() {
138 return new AppSettings(requireContext());
139 }
140}