mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 22:29:53 +01:00
Move notifications settings into own screen
This commit is contained in:
@@ -37,6 +37,7 @@ import org.briarproject.briar.android.conversation.glide.BriarModelLoader;
|
|||||||
import org.briarproject.briar.android.logging.CachingLogHandler;
|
import org.briarproject.briar.android.logging.CachingLogHandler;
|
||||||
import org.briarproject.briar.android.login.SignInReminderReceiver;
|
import org.briarproject.briar.android.login.SignInReminderReceiver;
|
||||||
import org.briarproject.briar.android.settings.ConnectionsFragment;
|
import org.briarproject.briar.android.settings.ConnectionsFragment;
|
||||||
|
import org.briarproject.briar.android.settings.NotificationsFragment;
|
||||||
import org.briarproject.briar.android.settings.SecurityFragment;
|
import org.briarproject.briar.android.settings.SecurityFragment;
|
||||||
import org.briarproject.briar.android.view.EmojiTextInputView;
|
import org.briarproject.briar.android.view.EmojiTextInputView;
|
||||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||||
@@ -199,4 +200,6 @@ public interface AndroidComponent
|
|||||||
void inject(ConnectionsFragment connectionsFragment);
|
void inject(ConnectionsFragment connectionsFragment);
|
||||||
|
|
||||||
void inject(SecurityFragment securityFragment);
|
void inject(SecurityFragment securityFragment);
|
||||||
|
|
||||||
|
void inject(NotificationsFragment notificationsFragment);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import static android.content.Intent.ACTION_BOOT_COMPLETED;
|
import static android.content.Intent.ACTION_BOOT_COMPLETED;
|
||||||
import static android.content.Intent.ACTION_MY_PACKAGE_REPLACED;
|
import static android.content.Intent.ACTION_MY_PACKAGE_REPLACED;
|
||||||
import static org.briarproject.briar.android.settings.SettingsFragment.NOTIFY_SIGN_IN;
|
import static org.briarproject.briar.android.settings.NotificationsFragment.PREF_NOTIFY_SIGN_IN;
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.ACTION_DISMISS_REMINDER;
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.ACTION_DISMISS_REMINDER;
|
||||||
|
|
||||||
public class SignInReminderReceiver extends BroadcastReceiver {
|
public class SignInReminderReceiver extends BroadcastReceiver {
|
||||||
@@ -37,7 +37,7 @@ public class SignInReminderReceiver extends BroadcastReceiver {
|
|||||||
if (accountManager.accountExists() &&
|
if (accountManager.accountExists() &&
|
||||||
!accountManager.hasDatabaseKey()) {
|
!accountManager.hasDatabaseKey()) {
|
||||||
SharedPreferences prefs = app.getDefaultSharedPreferences();
|
SharedPreferences prefs = app.getDefaultSharedPreferences();
|
||||||
if (prefs.getBoolean(NOTIFY_SIGN_IN, true)) {
|
if (prefs.getBoolean(PREF_NOTIFY_SIGN_IN, true)) {
|
||||||
notificationManager.showSignInNotification();
|
notificationManager.showSignInNotification();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class ConnectionsFragment extends PreferenceFragmentCompat {
|
|||||||
getAndroidComponent(context).inject(this);
|
getAndroidComponent(context).inject(this);
|
||||||
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||||
.get(SettingsViewModel.class);
|
.get(SettingsViewModel.class);
|
||||||
connectionsManager = viewModel.getConnectionsManager();
|
connectionsManager = viewModel.connectionsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.briarproject.briar.android.settings;
|
package org.briarproject.briar.android.settings;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
import org.briarproject.bramble.api.plugin.TorConstants;
|
import org.briarproject.bramble.api.plugin.TorConstants;
|
||||||
@@ -23,6 +24,7 @@ import static org.briarproject.briar.android.settings.SettingsViewModel.BT_NAMES
|
|||||||
import static org.briarproject.briar.android.settings.SettingsViewModel.TOR_NAMESPACE;
|
import static org.briarproject.briar.android.settings.SettingsViewModel.TOR_NAMESPACE;
|
||||||
import static org.briarproject.briar.android.settings.SettingsViewModel.WIFI_NAMESPACE;
|
import static org.briarproject.briar.android.settings.SettingsViewModel.WIFI_NAMESPACE;
|
||||||
|
|
||||||
|
@NotNullByDefault
|
||||||
class ConnectionsManager {
|
class ConnectionsManager {
|
||||||
|
|
||||||
final ConnectionsStore btStore;
|
final ConnectionsStore btStore;
|
||||||
|
|||||||
@@ -0,0 +1,235 @@
|
|||||||
|
package org.briarproject.briar.android.settings;
|
||||||
|
|
||||||
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.briarproject.briar.R;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.annotation.StringRes;
|
||||||
|
import androidx.lifecycle.LifecycleOwner;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
import androidx.preference.SwitchPreferenceCompat;
|
||||||
|
|
||||||
|
import static android.app.Activity.RESULT_OK;
|
||||||
|
import static android.media.RingtoneManager.ACTION_RINGTONE_PICKER;
|
||||||
|
import static android.media.RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI;
|
||||||
|
import static android.media.RingtoneManager.EXTRA_RINGTONE_EXISTING_URI;
|
||||||
|
import static android.media.RingtoneManager.EXTRA_RINGTONE_PICKED_URI;
|
||||||
|
import static android.media.RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT;
|
||||||
|
import static android.media.RingtoneManager.EXTRA_RINGTONE_TITLE;
|
||||||
|
import static android.media.RingtoneManager.EXTRA_RINGTONE_TYPE;
|
||||||
|
import static android.media.RingtoneManager.TYPE_NOTIFICATION;
|
||||||
|
import static android.os.Build.VERSION.SDK_INT;
|
||||||
|
import static android.provider.Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS;
|
||||||
|
import static android.provider.Settings.EXTRA_APP_PACKAGE;
|
||||||
|
import static android.provider.Settings.EXTRA_CHANNEL_ID;
|
||||||
|
import static android.provider.Settings.System.DEFAULT_NOTIFICATION_URI;
|
||||||
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||||
|
import static org.briarproject.briar.android.AppModule.getAndroidComponent;
|
||||||
|
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE;
|
||||||
|
import static org.briarproject.briar.android.settings.SettingsActivity.enableAndPersist;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.BLOG_CHANNEL_ID;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.CONTACT_CHANNEL_ID;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.FORUM_CHANNEL_ID;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.GROUP_CHANNEL_ID;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_BLOG;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_FORUM;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_GROUP;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_PRIVATE;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_SOUND;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_VIBRATION;
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
public class NotificationsFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
|
public static final String PREF_NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
|
||||||
|
private static final int NOTIFICATION_CHANNEL_API = 26;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
|
|
||||||
|
private SettingsViewModel viewModel;
|
||||||
|
private NotificationsManager nm;
|
||||||
|
|
||||||
|
private SwitchPreferenceCompat notifyPrivateMessages;
|
||||||
|
private SwitchPreferenceCompat notifyGroupMessages;
|
||||||
|
private SwitchPreferenceCompat notifyForumPosts;
|
||||||
|
private SwitchPreferenceCompat notifyBlogPosts;
|
||||||
|
private SwitchPreferenceCompat notifyVibration;
|
||||||
|
|
||||||
|
private Preference notifySound;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
getAndroidComponent(context).inject(this);
|
||||||
|
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
|
||||||
|
.get(SettingsViewModel.class);
|
||||||
|
nm = viewModel.notificationsManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreatePreferences(Bundle bundle, String s) {
|
||||||
|
addPreferencesFromResource(R.xml.settings_notifications);
|
||||||
|
|
||||||
|
notifyPrivateMessages = findPreference(PREF_NOTIFY_PRIVATE);
|
||||||
|
notifyGroupMessages = findPreference(PREF_NOTIFY_GROUP);
|
||||||
|
notifyForumPosts = findPreference(PREF_NOTIFY_FORUM);
|
||||||
|
notifyBlogPosts = findPreference(PREF_NOTIFY_BLOG);
|
||||||
|
notifyVibration = findPreference(PREF_NOTIFY_VIBRATION);
|
||||||
|
notifySound = findPreference(PREF_NOTIFY_SOUND);
|
||||||
|
|
||||||
|
if (SDK_INT < NOTIFICATION_CHANNEL_API) {
|
||||||
|
// NOTIFY_SIGN_IN gets stored in Android's SharedPreferences
|
||||||
|
notifyPrivateMessages
|
||||||
|
.setPreferenceDataStore(viewModel.settingsStore);
|
||||||
|
notifyGroupMessages.setPreferenceDataStore(viewModel.settingsStore);
|
||||||
|
notifyForumPosts.setPreferenceDataStore(viewModel.settingsStore);
|
||||||
|
notifyBlogPosts.setPreferenceDataStore(viewModel.settingsStore);
|
||||||
|
notifyVibration.setPreferenceDataStore(viewModel.settingsStore);
|
||||||
|
|
||||||
|
notifySound.setOnPreferenceClickListener(pref ->
|
||||||
|
onNotificationSoundClicked()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setupNotificationPreference(notifyPrivateMessages,
|
||||||
|
CONTACT_CHANNEL_ID,
|
||||||
|
R.string.notify_private_messages_setting_summary_26);
|
||||||
|
setupNotificationPreference(notifyGroupMessages,
|
||||||
|
GROUP_CHANNEL_ID,
|
||||||
|
R.string.notify_group_messages_setting_summary_26);
|
||||||
|
setupNotificationPreference(notifyForumPosts, FORUM_CHANNEL_ID,
|
||||||
|
R.string.notify_forum_posts_setting_summary_26);
|
||||||
|
setupNotificationPreference(notifyBlogPosts, BLOG_CHANNEL_ID,
|
||||||
|
R.string.notify_blog_posts_setting_summary_26);
|
||||||
|
|
||||||
|
notifyVibration.setVisible(false);
|
||||||
|
notifySound.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
if (SDK_INT < NOTIFICATION_CHANNEL_API) {
|
||||||
|
LifecycleOwner lifecycleOwner = getViewLifecycleOwner();
|
||||||
|
nm.getNotifyPrivateMessages().observe(lifecycleOwner, enabled -> {
|
||||||
|
notifyPrivateMessages.setChecked(enabled);
|
||||||
|
enableAndPersist(notifyPrivateMessages);
|
||||||
|
});
|
||||||
|
nm.getNotifyGroupMessages().observe(lifecycleOwner, enabled -> {
|
||||||
|
notifyGroupMessages.setChecked(enabled);
|
||||||
|
enableAndPersist(notifyGroupMessages);
|
||||||
|
});
|
||||||
|
nm.getNotifyForumPosts().observe(lifecycleOwner, enabled -> {
|
||||||
|
notifyForumPosts.setChecked(enabled);
|
||||||
|
enableAndPersist(notifyForumPosts);
|
||||||
|
});
|
||||||
|
nm.getNotifyBlogPosts().observe(lifecycleOwner, enabled -> {
|
||||||
|
notifyBlogPosts.setChecked(enabled);
|
||||||
|
enableAndPersist(notifyBlogPosts);
|
||||||
|
});
|
||||||
|
nm.getNotifyVibration().observe(lifecycleOwner, enabled -> {
|
||||||
|
notifyVibration.setChecked(enabled);
|
||||||
|
enableAndPersist(notifyVibration);
|
||||||
|
});
|
||||||
|
nm.getNotifySound().observe(lifecycleOwner, enabled -> {
|
||||||
|
String text;
|
||||||
|
if (enabled) {
|
||||||
|
String ringtoneName = nm.getRingtoneName();
|
||||||
|
if (isNullOrEmpty(ringtoneName)) {
|
||||||
|
text = getString(R.string.notify_sound_setting_default);
|
||||||
|
} else {
|
||||||
|
text = ringtoneName;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
text = getString(R.string.notify_sound_setting_disabled);
|
||||||
|
}
|
||||||
|
notifySound.setSummary(text);
|
||||||
|
notifySound.setEnabled(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
requireActivity().setTitle(R.string.notification_settings_title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onActivityResult(int request, int result,
|
||||||
|
@Nullable Intent data) {
|
||||||
|
super.onActivityResult(request, result, data);
|
||||||
|
if (request == REQUEST_RINGTONE && result == RESULT_OK &&
|
||||||
|
data != null) {
|
||||||
|
Uri uri = data.getParcelableExtra(EXTRA_RINGTONE_PICKED_URI);
|
||||||
|
nm.onRingtoneSet(uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(NOTIFICATION_CHANNEL_API)
|
||||||
|
private void setupNotificationPreference(SwitchPreferenceCompat pref,
|
||||||
|
String channelId, @StringRes int summary) {
|
||||||
|
pref.setWidgetLayoutResource(0);
|
||||||
|
pref.setSummary(summary);
|
||||||
|
pref.setEnabled(true);
|
||||||
|
pref.setOnPreferenceClickListener(clickedPref -> {
|
||||||
|
String packageName = requireContext().getPackageName();
|
||||||
|
Intent intent = new Intent(ACTION_CHANNEL_NOTIFICATION_SETTINGS)
|
||||||
|
.putExtra(EXTRA_APP_PACKAGE, packageName)
|
||||||
|
.putExtra(EXTRA_CHANNEL_ID, channelId);
|
||||||
|
Context ctx = requireContext();
|
||||||
|
if (intent.resolveActivity(ctx.getPackageManager()) != null) {
|
||||||
|
startActivity(intent);
|
||||||
|
} else {
|
||||||
|
Toast.makeText(ctx, R.string.error_start_activity, LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onNotificationSoundClicked() {
|
||||||
|
String title = getString(R.string.choose_ringtone_title);
|
||||||
|
Intent i = new Intent(ACTION_RINGTONE_PICKER);
|
||||||
|
i.putExtra(EXTRA_RINGTONE_TYPE, TYPE_NOTIFICATION);
|
||||||
|
i.putExtra(EXTRA_RINGTONE_TITLE, title);
|
||||||
|
i.putExtra(EXTRA_RINGTONE_DEFAULT_URI,
|
||||||
|
DEFAULT_NOTIFICATION_URI);
|
||||||
|
i.putExtra(EXTRA_RINGTONE_SHOW_SILENT, true);
|
||||||
|
if (requireNonNull(nm.getNotifySound().getValue())) {
|
||||||
|
Uri uri;
|
||||||
|
String ringtoneUri = nm.getRingtoneUri();
|
||||||
|
if (isNullOrEmpty(ringtoneUri))
|
||||||
|
uri = DEFAULT_NOTIFICATION_URI;
|
||||||
|
else uri = Uri.parse(ringtoneUri);
|
||||||
|
i.putExtra(EXTRA_RINGTONE_EXISTING_URI, uri);
|
||||||
|
}
|
||||||
|
if (i.resolveActivity(requireActivity().getPackageManager()) != null) {
|
||||||
|
startActivityForResult(i, REQUEST_RINGTONE);
|
||||||
|
} else {
|
||||||
|
Toast.makeText(getContext(), R.string.cannot_load_ringtone,
|
||||||
|
LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
package org.briarproject.briar.android.settings;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.media.Ringtone;
|
||||||
|
import android.media.RingtoneManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.settings.Settings;
|
||||||
|
import org.briarproject.bramble.api.settings.SettingsManager;
|
||||||
|
import org.briarproject.briar.R;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
|
import static java.util.logging.Level.WARNING;
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
|
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_BLOG;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_FORUM;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_GROUP;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_PRIVATE;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_NAME;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_URI;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_SOUND;
|
||||||
|
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_VIBRATION;
|
||||||
|
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
class NotificationsManager {
|
||||||
|
|
||||||
|
private final static Logger LOG =
|
||||||
|
getLogger(NotificationsManager.class.getName());
|
||||||
|
|
||||||
|
private final Context ctx;
|
||||||
|
private final SettingsManager settingsManager;
|
||||||
|
private final Executor dbExecutor;
|
||||||
|
|
||||||
|
private final MutableLiveData<Boolean> notifyPrivateMessages =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> notifyGroupMessages =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> notifyForumPosts =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> notifyBlogPosts =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> notifyVibration =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
private final MutableLiveData<Boolean> notifySound =
|
||||||
|
new MutableLiveData<>();
|
||||||
|
|
||||||
|
private volatile String ringtoneName, ringtoneUri;
|
||||||
|
|
||||||
|
public NotificationsManager(Context ctx,
|
||||||
|
SettingsManager settingsManager,
|
||||||
|
Executor dbExecutor) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.settingsManager = settingsManager;
|
||||||
|
this.dbExecutor = dbExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateSettings(Settings settings) {
|
||||||
|
notifyPrivateMessages.postValue(settings.getBoolean(
|
||||||
|
PREF_NOTIFY_PRIVATE, true));
|
||||||
|
notifyGroupMessages.postValue(settings.getBoolean(
|
||||||
|
PREF_NOTIFY_GROUP, true));
|
||||||
|
notifyForumPosts.postValue(settings.getBoolean(
|
||||||
|
PREF_NOTIFY_FORUM, true));
|
||||||
|
notifyBlogPosts.postValue(settings.getBoolean(
|
||||||
|
PREF_NOTIFY_BLOG, true));
|
||||||
|
notifyVibration.postValue(settings.getBoolean(
|
||||||
|
PREF_NOTIFY_VIBRATION, true));
|
||||||
|
ringtoneName = settings.get(PREF_NOTIFY_RINGTONE_NAME);
|
||||||
|
ringtoneUri = settings.get(PREF_NOTIFY_RINGTONE_URI);
|
||||||
|
notifySound.postValue(settings.getBoolean(PREF_NOTIFY_SOUND, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
void onRingtoneSet(@Nullable Uri uri) {
|
||||||
|
Settings s = new Settings();
|
||||||
|
if (uri == null) {
|
||||||
|
// The user chose silence
|
||||||
|
s.putBoolean(PREF_NOTIFY_SOUND, false);
|
||||||
|
s.put(PREF_NOTIFY_RINGTONE_NAME, "");
|
||||||
|
s.put(PREF_NOTIFY_RINGTONE_URI, "");
|
||||||
|
} else if (RingtoneManager.isDefault(uri)) {
|
||||||
|
// The user chose the default
|
||||||
|
s.putBoolean(PREF_NOTIFY_SOUND, true);
|
||||||
|
s.put(PREF_NOTIFY_RINGTONE_NAME, "");
|
||||||
|
s.put(PREF_NOTIFY_RINGTONE_URI, "");
|
||||||
|
} else {
|
||||||
|
// The user chose a ringtone other than the default
|
||||||
|
Ringtone r = RingtoneManager.getRingtone(ctx, uri);
|
||||||
|
if (r == null || "file".equals(uri.getScheme())) {
|
||||||
|
Toast.makeText(ctx, R.string.cannot_load_ringtone, LENGTH_SHORT)
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
|
String name = r.getTitle(ctx);
|
||||||
|
s.putBoolean(PREF_NOTIFY_SOUND, true);
|
||||||
|
s.put(PREF_NOTIFY_RINGTONE_NAME, name);
|
||||||
|
s.put(PREF_NOTIFY_RINGTONE_URI, uri.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dbExecutor.execute(() -> {
|
||||||
|
try {
|
||||||
|
long start = now();
|
||||||
|
settingsManager.mergeSettings(s, SETTINGS_NAMESPACE);
|
||||||
|
logDuration(LOG, "Merging notification settings", start);
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> getNotifyPrivateMessages() {
|
||||||
|
return notifyPrivateMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> getNotifyGroupMessages() {
|
||||||
|
return notifyGroupMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> getNotifyForumPosts() {
|
||||||
|
return notifyForumPosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> getNotifyBlogPosts() {
|
||||||
|
return notifyBlogPosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> getNotifyVibration() {
|
||||||
|
return notifyVibration;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
LiveData<Boolean> getNotifySound() {
|
||||||
|
return notifySound;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getRingtoneName() {
|
||||||
|
return ringtoneName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRingtoneUri() {
|
||||||
|
return ringtoneUri;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,127 +1,29 @@
|
|||||||
package org.briarproject.briar.android.settings;
|
package org.briarproject.briar.android.settings;
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.drawable.ColorDrawable;
|
|
||||||
import android.media.Ringtone;
|
|
||||||
import android.media.RingtoneManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
|
||||||
import org.briarproject.bramble.api.event.Event;
|
|
||||||
import org.briarproject.bramble.api.event.EventBus;
|
|
||||||
import org.briarproject.bramble.api.event.EventListener;
|
|
||||||
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.settings.Settings;
|
|
||||||
import org.briarproject.bramble.api.settings.SettingsManager;
|
|
||||||
import org.briarproject.bramble.api.settings.event.SettingsUpdatedEvent;
|
|
||||||
import org.briarproject.bramble.util.StringUtils;
|
|
||||||
import org.briarproject.briar.R;
|
import org.briarproject.briar.R;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.annotation.StringRes;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import androidx.preference.PreferenceGroup;
|
import androidx.preference.PreferenceGroup;
|
||||||
import androidx.preference.SwitchPreference;
|
|
||||||
|
|
||||||
import static android.app.Activity.RESULT_OK;
|
|
||||||
import static android.media.RingtoneManager.ACTION_RINGTONE_PICKER;
|
|
||||||
import static android.media.RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI;
|
|
||||||
import static android.media.RingtoneManager.EXTRA_RINGTONE_EXISTING_URI;
|
|
||||||
import static android.media.RingtoneManager.EXTRA_RINGTONE_PICKED_URI;
|
|
||||||
import static android.media.RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT;
|
|
||||||
import static android.media.RingtoneManager.EXTRA_RINGTONE_TITLE;
|
|
||||||
import static android.media.RingtoneManager.EXTRA_RINGTONE_TYPE;
|
|
||||||
import static android.media.RingtoneManager.TYPE_NOTIFICATION;
|
|
||||||
import static android.os.Build.VERSION.SDK_INT;
|
|
||||||
import static android.provider.Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS;
|
|
||||||
import static android.provider.Settings.EXTRA_APP_PACKAGE;
|
|
||||||
import static android.provider.Settings.EXTRA_CHANNEL_ID;
|
|
||||||
import static android.provider.Settings.System.DEFAULT_NOTIFICATION_URI;
|
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
|
||||||
import static java.util.Objects.requireNonNull;
|
import static java.util.Objects.requireNonNull;
|
||||||
import static java.util.logging.Level.WARNING;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logDuration;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
|
||||||
import static org.briarproject.bramble.util.LogUtils.now;
|
|
||||||
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_RINGTONE;
|
|
||||||
import static org.briarproject.briar.android.util.UiUtils.triggerFeedback;
|
import static org.briarproject.briar.android.util.UiUtils.triggerFeedback;
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.BLOG_CHANNEL_ID;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.CONTACT_CHANNEL_ID;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.FORUM_CHANNEL_ID;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.GROUP_CHANNEL_ID;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_BLOG;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_FORUM;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_GROUP;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_PRIVATE;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_NAME;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_RINGTONE_URI;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_SOUND;
|
|
||||||
import static org.briarproject.briar.api.android.AndroidNotificationManager.PREF_NOTIFY_VIBRATION;
|
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class SettingsFragment extends PreferenceFragmentCompat
|
public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
implements EventListener, OnPreferenceChangeListener {
|
|
||||||
|
|
||||||
public static final String SETTINGS_NAMESPACE = "android-ui";
|
public static final String SETTINGS_NAMESPACE = "android-ui";
|
||||||
public static final String NOTIFY_SIGN_IN = "pref_key_notify_sign_in";
|
|
||||||
|
|
||||||
private static final Logger LOG =
|
|
||||||
Logger.getLogger(SettingsFragment.class.getName());
|
|
||||||
|
|
||||||
private SettingsActivity listener;
|
|
||||||
private SwitchPreference notifyPrivateMessages;
|
|
||||||
private SwitchPreference notifyGroupMessages;
|
|
||||||
private SwitchPreference notifyForumPosts;
|
|
||||||
private SwitchPreference notifyBlogPosts;
|
|
||||||
private SwitchPreference notifyVibration;
|
|
||||||
|
|
||||||
private Preference notifySound;
|
|
||||||
|
|
||||||
// Fields that are accessed from background threads must be volatile
|
|
||||||
private volatile Settings settings;
|
|
||||||
private volatile boolean settingsLoaded = false;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
volatile SettingsManager settingsManager;
|
|
||||||
@Inject
|
|
||||||
volatile EventBus eventBus;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onAttach(Context context) {
|
|
||||||
super.onAttach(context);
|
|
||||||
listener = (SettingsActivity) context;
|
|
||||||
listener.getActivityComponent().inject(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle bundle, String s) {
|
public void onCreatePreferences(Bundle bundle, String s) {
|
||||||
addPreferencesFromResource(R.xml.settings);
|
addPreferencesFromResource(R.xml.settings);
|
||||||
|
|
||||||
notifyPrivateMessages =
|
|
||||||
findPreference("pref_key_notify_private_messages");
|
|
||||||
notifyGroupMessages = findPreference("pref_key_notify_group_messages");
|
|
||||||
notifyForumPosts = findPreference("pref_key_notify_forum_posts");
|
|
||||||
notifyBlogPosts = findPreference("pref_key_notify_blog_posts");
|
|
||||||
notifyVibration = findPreference("pref_key_notify_vibration");
|
|
||||||
notifySound = findPreference("pref_key_notify_sound");
|
|
||||||
|
|
||||||
Preference prefFeedback =
|
Preference prefFeedback =
|
||||||
requireNonNull(findPreference("pref_key_send_feedback"));
|
requireNonNull(findPreference("pref_key_send_feedback"));
|
||||||
prefFeedback.setOnPreferenceClickListener(preference -> {
|
prefFeedback.setOnPreferenceClickListener(preference -> {
|
||||||
@@ -143,246 +45,10 @@ public class SettingsFragment extends PreferenceFragmentCompat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater,
|
|
||||||
@Nullable ViewGroup container,
|
|
||||||
@Nullable Bundle savedInstanceState) {
|
|
||||||
View view = super.onCreateView(inflater, container, savedInstanceState);
|
|
||||||
ColorDrawable divider = new ColorDrawable(
|
|
||||||
ContextCompat.getColor(requireContext(), R.color.divider));
|
|
||||||
setDivider(divider);
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
requireActivity().setTitle(R.string.settings_button);
|
requireActivity().setTitle(R.string.settings_button);
|
||||||
eventBus.addListener(this);
|
|
||||||
setSettingsEnabled(false);
|
|
||||||
loadSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStop() {
|
|
||||||
super.onStop();
|
|
||||||
eventBus.removeListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void loadSettings() {
|
|
||||||
listener.runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
long start = now();
|
|
||||||
settings = settingsManager.getSettings(SETTINGS_NAMESPACE);
|
|
||||||
settingsLoaded = true;
|
|
||||||
logDuration(LOG, "Loading settings", start);
|
|
||||||
displaySettings();
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void displaySettings() {
|
|
||||||
listener.runOnUiThreadUnlessDestroyed(() -> {
|
|
||||||
// due to events, we might try to display before a load completed
|
|
||||||
if (!settingsLoaded) return;
|
|
||||||
|
|
||||||
if (SDK_INT < 26) {
|
|
||||||
notifyPrivateMessages.setChecked(settings.getBoolean(
|
|
||||||
PREF_NOTIFY_PRIVATE, true));
|
|
||||||
notifyGroupMessages.setChecked(settings.getBoolean(
|
|
||||||
PREF_NOTIFY_GROUP, true));
|
|
||||||
notifyForumPosts.setChecked(settings.getBoolean(
|
|
||||||
PREF_NOTIFY_FORUM, true));
|
|
||||||
notifyBlogPosts.setChecked(settings.getBoolean(
|
|
||||||
PREF_NOTIFY_BLOG, true));
|
|
||||||
notifyVibration.setChecked(settings.getBoolean(
|
|
||||||
PREF_NOTIFY_VIBRATION, true));
|
|
||||||
notifyPrivateMessages.setOnPreferenceChangeListener(this);
|
|
||||||
notifyGroupMessages.setOnPreferenceChangeListener(this);
|
|
||||||
notifyForumPosts.setOnPreferenceChangeListener(this);
|
|
||||||
notifyBlogPosts.setOnPreferenceChangeListener(this);
|
|
||||||
notifyVibration.setOnPreferenceChangeListener(this);
|
|
||||||
notifySound.setOnPreferenceClickListener(
|
|
||||||
pref -> onNotificationSoundClicked());
|
|
||||||
String text;
|
|
||||||
if (settings.getBoolean(PREF_NOTIFY_SOUND, true)) {
|
|
||||||
String ringtoneName =
|
|
||||||
settings.get(PREF_NOTIFY_RINGTONE_NAME);
|
|
||||||
if (StringUtils.isNullOrEmpty(ringtoneName)) {
|
|
||||||
text = getString(R.string.notify_sound_setting_default);
|
|
||||||
} else {
|
|
||||||
text = ringtoneName;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
text = getString(R.string.notify_sound_setting_disabled);
|
|
||||||
}
|
|
||||||
notifySound.setSummary(text);
|
|
||||||
} else {
|
|
||||||
setupNotificationPreference(notifyPrivateMessages,
|
|
||||||
CONTACT_CHANNEL_ID,
|
|
||||||
R.string.notify_private_messages_setting_summary_26);
|
|
||||||
setupNotificationPreference(notifyGroupMessages,
|
|
||||||
GROUP_CHANNEL_ID,
|
|
||||||
R.string.notify_group_messages_setting_summary_26);
|
|
||||||
setupNotificationPreference(notifyForumPosts, FORUM_CHANNEL_ID,
|
|
||||||
R.string.notify_forum_posts_setting_summary_26);
|
|
||||||
setupNotificationPreference(notifyBlogPosts, BLOG_CHANNEL_ID,
|
|
||||||
R.string.notify_blog_posts_setting_summary_26);
|
|
||||||
notifyVibration.setVisible(false);
|
|
||||||
notifySound.setVisible(false);
|
|
||||||
}
|
|
||||||
setSettingsEnabled(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setSettingsEnabled(boolean enabled) {
|
|
||||||
// preferences not needed here, because handled by SharedPreferences:
|
|
||||||
// - pref_key_notify_sign_in
|
|
||||||
notifyPrivateMessages.setEnabled(enabled);
|
|
||||||
notifyGroupMessages.setEnabled(enabled);
|
|
||||||
notifyForumPosts.setEnabled(enabled);
|
|
||||||
notifyBlogPosts.setEnabled(enabled);
|
|
||||||
notifyVibration.setEnabled(enabled);
|
|
||||||
notifySound.setEnabled(enabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(26)
|
|
||||||
private void setupNotificationPreference(SwitchPreference pref,
|
|
||||||
String channelId, @StringRes int summary) {
|
|
||||||
pref.setWidgetLayoutResource(0);
|
|
||||||
pref.setSummary(summary);
|
|
||||||
pref.setOnPreferenceClickListener(clickedPref -> {
|
|
||||||
String packageName = requireContext().getPackageName();
|
|
||||||
Intent intent = new Intent(ACTION_CHANNEL_NOTIFICATION_SETTINGS)
|
|
||||||
.putExtra(EXTRA_APP_PACKAGE, packageName)
|
|
||||||
.putExtra(EXTRA_CHANNEL_ID, channelId);
|
|
||||||
Context ctx = requireContext();
|
|
||||||
if (intent.resolveActivity(ctx.getPackageManager()) != null) {
|
|
||||||
startActivity(intent);
|
|
||||||
} else {
|
|
||||||
Toast.makeText(ctx, R.string.error_start_activity, LENGTH_SHORT)
|
|
||||||
.show();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean onNotificationSoundClicked() {
|
|
||||||
String title = getString(R.string.choose_ringtone_title);
|
|
||||||
Intent i = new Intent(ACTION_RINGTONE_PICKER);
|
|
||||||
i.putExtra(EXTRA_RINGTONE_TYPE, TYPE_NOTIFICATION);
|
|
||||||
i.putExtra(EXTRA_RINGTONE_TITLE, title);
|
|
||||||
i.putExtra(EXTRA_RINGTONE_DEFAULT_URI,
|
|
||||||
DEFAULT_NOTIFICATION_URI);
|
|
||||||
i.putExtra(EXTRA_RINGTONE_SHOW_SILENT, true);
|
|
||||||
if (settings.getBoolean(PREF_NOTIFY_SOUND, true)) {
|
|
||||||
Uri uri;
|
|
||||||
String ringtoneUri =
|
|
||||||
settings.get(PREF_NOTIFY_RINGTONE_URI);
|
|
||||||
if (StringUtils.isNullOrEmpty(ringtoneUri))
|
|
||||||
uri = DEFAULT_NOTIFICATION_URI;
|
|
||||||
else uri = Uri.parse(ringtoneUri);
|
|
||||||
i.putExtra(EXTRA_RINGTONE_EXISTING_URI, uri);
|
|
||||||
}
|
|
||||||
if (i.resolveActivity(requireActivity().getPackageManager()) != null) {
|
|
||||||
startActivityForResult(i, REQUEST_RINGTONE);
|
|
||||||
} else {
|
|
||||||
Toast.makeText(getContext(), R.string.cannot_load_ringtone,
|
|
||||||
LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
|
||||||
if (preference == notifyPrivateMessages) {
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.putBoolean(PREF_NOTIFY_PRIVATE, (Boolean) newValue);
|
|
||||||
storeSettings(s);
|
|
||||||
} else if (preference == notifyGroupMessages) {
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.putBoolean(PREF_NOTIFY_GROUP, (Boolean) newValue);
|
|
||||||
storeSettings(s);
|
|
||||||
} else if (preference == notifyForumPosts) {
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.putBoolean(PREF_NOTIFY_FORUM, (Boolean) newValue);
|
|
||||||
storeSettings(s);
|
|
||||||
} else if (preference == notifyBlogPosts) {
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.putBoolean(PREF_NOTIFY_BLOG, (Boolean) newValue);
|
|
||||||
storeSettings(s);
|
|
||||||
} else if (preference == notifyVibration) {
|
|
||||||
Settings s = new Settings();
|
|
||||||
s.putBoolean(PREF_NOTIFY_VIBRATION, (Boolean) newValue);
|
|
||||||
storeSettings(s);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void storeSettings(Settings s) {
|
|
||||||
mergeSettings(s, SETTINGS_NAMESPACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void mergeSettings(Settings s, String namespace) {
|
|
||||||
listener.runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
long start = now();
|
|
||||||
settingsManager.mergeSettings(s, namespace);
|
|
||||||
logDuration(LOG, "Merging settings", start);
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onActivityResult(int request, int result,
|
|
||||||
@Nullable Intent data) {
|
|
||||||
super.onActivityResult(request, result, data);
|
|
||||||
if (request == REQUEST_RINGTONE && result == RESULT_OK) {
|
|
||||||
Settings s = new Settings();
|
|
||||||
Uri uri = data.getParcelableExtra(EXTRA_RINGTONE_PICKED_URI);
|
|
||||||
if (uri == null) {
|
|
||||||
// The user chose silence
|
|
||||||
s.putBoolean(PREF_NOTIFY_SOUND, false);
|
|
||||||
s.put(PREF_NOTIFY_RINGTONE_NAME, "");
|
|
||||||
s.put(PREF_NOTIFY_RINGTONE_URI, "");
|
|
||||||
} else if (RingtoneManager.isDefault(uri)) {
|
|
||||||
// The user chose the default
|
|
||||||
s.putBoolean(PREF_NOTIFY_SOUND, true);
|
|
||||||
s.put(PREF_NOTIFY_RINGTONE_NAME, "");
|
|
||||||
s.put(PREF_NOTIFY_RINGTONE_URI, "");
|
|
||||||
} else {
|
|
||||||
// The user chose a ringtone other than the default
|
|
||||||
Ringtone r = RingtoneManager.getRingtone(getContext(), uri);
|
|
||||||
if (r == null || "file".equals(uri.getScheme())) {
|
|
||||||
Toast.makeText(getContext(), R.string.cannot_load_ringtone,
|
|
||||||
LENGTH_SHORT).show();
|
|
||||||
} else {
|
|
||||||
String name = r.getTitle(getContext());
|
|
||||||
s.putBoolean(PREF_NOTIFY_SOUND, true);
|
|
||||||
s.put(PREF_NOTIFY_RINGTONE_NAME, name);
|
|
||||||
s.put(PREF_NOTIFY_RINGTONE_URI, uri.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
storeSettings(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void eventOccurred(Event e) {
|
|
||||||
if (e instanceof SettingsUpdatedEvent) {
|
|
||||||
SettingsUpdatedEvent s = (SettingsUpdatedEvent) e;
|
|
||||||
String namespace = s.getNamespace();
|
|
||||||
if (namespace.equals(SETTINGS_NAMESPACE)) {
|
|
||||||
LOG.info("Settings updated");
|
|
||||||
settings = s.getSettings();
|
|
||||||
displaySettings();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import org.briarproject.bramble.api.identity.IdentityManager;
|
|||||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||||
import org.briarproject.bramble.api.plugin.TorConstants;
|
import org.briarproject.bramble.api.plugin.TorConstants;
|
||||||
@@ -53,14 +54,15 @@ import static org.briarproject.bramble.util.LogUtils.logException;
|
|||||||
import static org.briarproject.bramble.util.LogUtils.now;
|
import static org.briarproject.bramble.util.LogUtils.now;
|
||||||
import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK;
|
import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK;
|
||||||
import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK_TIMEOUT;
|
import static org.briarproject.briar.android.settings.SecurityFragment.PREF_SCREEN_LOCK_TIMEOUT;
|
||||||
|
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
|
||||||
|
|
||||||
@NotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
class SettingsViewModel extends DbViewModel implements EventListener {
|
class SettingsViewModel extends DbViewModel implements EventListener {
|
||||||
|
|
||||||
private final static Logger LOG =
|
private final static Logger LOG =
|
||||||
getLogger(SettingsViewModel.class.getName());
|
getLogger(SettingsViewModel.class.getName());
|
||||||
|
|
||||||
public static final String SETTINGS_NAMESPACE = "android-ui";
|
|
||||||
static final String BT_NAMESPACE =
|
static final String BT_NAMESPACE =
|
||||||
BluetoothConstants.ID.getString();
|
BluetoothConstants.ID.getString();
|
||||||
static final String WIFI_NAMESPACE = LanTcpConstants.ID.getString();
|
static final String WIFI_NAMESPACE = LanTcpConstants.ID.getString();
|
||||||
@@ -73,10 +75,11 @@ class SettingsViewModel extends DbViewModel implements EventListener {
|
|||||||
private final AuthorManager authorManager;
|
private final AuthorManager authorManager;
|
||||||
private final ImageCompressor imageCompressor;
|
private final ImageCompressor imageCompressor;
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
private final ConnectionsManager connectionsManager;
|
|
||||||
|
|
||||||
final SettingsStore settingsStore;
|
final SettingsStore settingsStore;
|
||||||
final TorSummaryProvider torSummaryProvider;
|
final TorSummaryProvider torSummaryProvider;
|
||||||
|
final ConnectionsManager connectionsManager;
|
||||||
|
final NotificationsManager notificationsManager;
|
||||||
|
|
||||||
private volatile Settings settings;
|
private volatile Settings settings;
|
||||||
|
|
||||||
@@ -114,10 +117,12 @@ class SettingsViewModel extends DbViewModel implements EventListener {
|
|||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.settingsStore = new SettingsStore(settingsManager, dbExecutor,
|
this.settingsStore = new SettingsStore(settingsManager, dbExecutor,
|
||||||
SETTINGS_NAMESPACE);
|
SETTINGS_NAMESPACE);
|
||||||
this.torSummaryProvider = new TorSummaryProvider(getApplication(),
|
torSummaryProvider = new TorSummaryProvider(getApplication(),
|
||||||
locationUtils, circumventionProvider);
|
locationUtils, circumventionProvider);
|
||||||
this.connectionsManager =
|
connectionsManager =
|
||||||
new ConnectionsManager(settingsManager, dbExecutor);
|
new ConnectionsManager(settingsManager, dbExecutor);
|
||||||
|
notificationsManager = new NotificationsManager(getApplication(),
|
||||||
|
settingsManager, dbExecutor);
|
||||||
|
|
||||||
eventBus.addListener(this);
|
eventBus.addListener(this);
|
||||||
loadSettings();
|
loadSettings();
|
||||||
@@ -192,6 +197,7 @@ class SettingsViewModel extends DbViewModel implements EventListener {
|
|||||||
screenLockTimeout.postValue(String.valueOf(
|
screenLockTimeout.postValue(String.valueOf(
|
||||||
settings.getInt(PREF_SCREEN_LOCK_TIMEOUT, defaultTimeout)
|
settings.getInt(PREF_SCREEN_LOCK_TIMEOUT, defaultTimeout)
|
||||||
));
|
));
|
||||||
|
notificationsManager.updateSettings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAvatar(Uri uri) {
|
void setAvatar(Uri uri) {
|
||||||
@@ -245,8 +251,4 @@ class SettingsViewModel extends DbViewModel implements EventListener {
|
|||||||
return screenLockTimeout;
|
return screenLockTimeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectionsManager getConnectionsManager() {
|
|
||||||
return connectionsManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
10
briar-android/src/main/res/drawable/ic_notifications.xml
Normal file
10
briar-android/src/main/res/drawable/ic_notifications.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?android:attr/textColorPrimary"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.89,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z" />
|
||||||
|
</vector>
|
||||||
@@ -552,7 +552,6 @@
|
|||||||
<string name="cannot_load_ringtone">Cannot load ringtone</string>
|
<string name="cannot_load_ringtone">Cannot load ringtone</string>
|
||||||
|
|
||||||
<!-- Settings Feedback -->
|
<!-- Settings Feedback -->
|
||||||
<string name="feedback_settings_title">Feedback</string>
|
|
||||||
<string name="send_feedback">Send feedback</string>
|
<string name="send_feedback">Send feedback</string>
|
||||||
|
|
||||||
<!-- Link Warning -->
|
<!-- Link Warning -->
|
||||||
|
|||||||
@@ -17,88 +17,23 @@
|
|||||||
app:fragment="org.briarproject.briar.android.settings.SecurityFragment"
|
app:fragment="org.briarproject.briar.android.settings.SecurityFragment"
|
||||||
app:icon="@drawable/ic_settings_security" />
|
app:icon="@drawable/ic_settings_security" />
|
||||||
|
|
||||||
<PreferenceCategory
|
<Preference
|
||||||
android:layout="@layout/preferences_category"
|
android:title="@string/notification_settings_title"
|
||||||
android:title="@string/notification_settings_title">
|
app:fragment="org.briarproject.briar.android.settings.NotificationsFragment"
|
||||||
|
app:icon="@drawable/ic_notifications" />
|
||||||
|
|
||||||
<SwitchPreference
|
<Preference
|
||||||
android:defaultValue="true"
|
android:key="pref_key_send_feedback"
|
||||||
android:key="pref_key_notify_sign_in"
|
android:title="@string/send_feedback" />
|
||||||
android:summary="@string/notify_sign_in_summary"
|
|
||||||
android:title="@string/notify_sign_in_title"
|
|
||||||
android:widgetLayout="@layout/preference_switch_compat"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
<SwitchPreference
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="pref_key_notify_private_messages"
|
|
||||||
android:persistent="false"
|
|
||||||
android:summary="@string/notify_private_messages_setting_summary"
|
|
||||||
android:title="@string/notify_private_messages_setting_title"
|
|
||||||
android:widgetLayout="@layout/preference_switch_compat"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
<SwitchPreference
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="pref_key_notify_group_messages"
|
|
||||||
android:persistent="false"
|
|
||||||
android:summary="@string/notify_group_messages_setting_summary"
|
|
||||||
android:title="@string/notify_group_messages_setting_title"
|
|
||||||
android:widgetLayout="@layout/preference_switch_compat"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
<SwitchPreference
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="pref_key_notify_forum_posts"
|
|
||||||
android:persistent="false"
|
|
||||||
android:summary="@string/notify_forum_posts_setting_summary"
|
|
||||||
android:title="@string/notify_forum_posts_setting_title"
|
|
||||||
android:widgetLayout="@layout/preference_switch_compat"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
<SwitchPreference
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="pref_key_notify_blog_posts"
|
|
||||||
android:persistent="false"
|
|
||||||
android:summary="@string/notify_blog_posts_setting_summary"
|
|
||||||
android:title="@string/notify_blog_posts_setting_title"
|
|
||||||
android:widgetLayout="@layout/preference_switch_compat"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
<SwitchPreference
|
|
||||||
android:defaultValue="true"
|
|
||||||
android:key="pref_key_notify_vibration"
|
|
||||||
android:persistent="false"
|
|
||||||
android:title="@string/notify_vibration_setting"
|
|
||||||
android:widgetLayout="@layout/preference_switch_compat"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
<Preference
|
|
||||||
android:key="pref_key_notify_sound"
|
|
||||||
android:title="@string/notify_sound_setting"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:layout="@layout/preferences_category"
|
android:layout="@layout/preferences_category"
|
||||||
android:title="@string/feedback_settings_title">
|
android:title="Developer Options"
|
||||||
|
app:allowDividerAbove="true">
|
||||||
<Preference
|
|
||||||
android:key="pref_key_send_feedback"
|
|
||||||
android:title="@string/send_feedback"
|
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
|
||||||
|
|
||||||
<PreferenceCategory
|
|
||||||
android:layout="@layout/preferences_category"
|
|
||||||
android:title="Testing">
|
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="pref_key_test_data"
|
android:key="pref_key_test_data"
|
||||||
android:title="Create Test Data"
|
android:title="Create test data">
|
||||||
app:iconSpaceReserved="false">
|
|
||||||
|
|
||||||
<intent
|
<intent
|
||||||
android:targetClass="org.briarproject.briar.android.test.TestDataActivity"
|
android:targetClass="org.briarproject.briar.android.test.TestDataActivity"
|
||||||
@@ -107,8 +42,7 @@
|
|||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:key="pref_key_explode"
|
android:key="pref_key_explode"
|
||||||
android:title="Crash"
|
android:title="Crash" />
|
||||||
app:iconSpaceReserved="false" />
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
|
|||||||
61
briar-android/src/main/res/xml/settings_notifications.xml
Normal file
61
briar-android/src/main/res/xml/settings_notifications.xml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:key="pref_key_notify_sign_in"
|
||||||
|
android:summary="@string/notify_sign_in_summary"
|
||||||
|
android:title="@string/notify_sign_in_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:enabled="false"
|
||||||
|
android:key="notifyPrivateMessages"
|
||||||
|
android:persistent="false"
|
||||||
|
android:summary="@string/notify_private_messages_setting_summary"
|
||||||
|
android:title="@string/notify_private_messages_setting_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:enabled="false"
|
||||||
|
android:key="notifyGroupMessages"
|
||||||
|
android:persistent="false"
|
||||||
|
android:summary="@string/notify_group_messages_setting_summary"
|
||||||
|
android:title="@string/notify_group_messages_setting_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:enabled="false"
|
||||||
|
android:key="notifyForumPosts"
|
||||||
|
android:persistent="false"
|
||||||
|
android:summary="@string/notify_forum_posts_setting_summary"
|
||||||
|
android:title="@string/notify_forum_posts_setting_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:enabled="false"
|
||||||
|
android:key="notifyBlogPosts"
|
||||||
|
android:persistent="false"
|
||||||
|
android:summary="@string/notify_blog_posts_setting_summary"
|
||||||
|
android:title="@string/notify_blog_posts_setting_title"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:enabled="false"
|
||||||
|
android:key="notifyVibration"
|
||||||
|
android:persistent="false"
|
||||||
|
android:title="@string/notify_vibration_setting"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="notifySound"
|
||||||
|
android:title="@string/notify_sound_setting"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
||||||
Reference in New Issue
Block a user