diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml index 78a4e81b8d471a742633700a3b2b3e11d743c38f..92340fd50e1fe3843409520923ecdcc18900d0f3 100644 --- a/briar-android/AndroidManifest.xml +++ b/briar-android/AndroidManifest.xml @@ -168,6 +168,19 @@ android:name=".android.StartupFailureActivity" android:label="@string/startup_failed_activity_title"> </activity> + <activity + android:name=".android.SettingsActivity" + android:label="@string/settings_title" + android:parentActivityName=".android.NavDrawerActivity"> + <meta-data + android:name="android.support.PARENT_ACTIVITY" + android:value=".android.NavDrawerActivity" + /> + <intent-filter> + <action android:name="android.intent.action.MANAGE_NETWORK_USAGE"/> + <category android:name="android.intent.category.DEFAULT"/> + </intent-filter> + </activity> <activity android:name=".android.panic.PanicPreferencesActivity" android:label="@string/panic_setting"> diff --git a/briar-android/res/layout/activity_settings.xml b/briar-android/res/layout/activity_settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..4e629ca51b983b271f6328173203b5f24231ed16 --- /dev/null +++ b/briar-android/res/layout/activity_settings.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <fragment + android:id="@+id/fragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:name="org.briarproject.android.fragment.SettingsFragment"/> +</FrameLayout> \ No newline at end of file diff --git a/briar-android/res/values/arrays.xml b/briar-android/res/values/arrays.xml new file mode 100644 index 0000000000000000000000000000000000000000..be699e2a2873d82a8270f42edf0ab35529cb45e4 --- /dev/null +++ b/briar-android/res/values/arrays.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <string-array name="boolean_array"> + <item>true</item> + <item>false</item> + </string-array> + <string-array name="bt_setting_names"> + <item>@string/bluetooth_setting_enabled</item> + <item>@string/bluetooth_setting_disabled</item> + </string-array> + <string-array name="tor_mobile_setting_names"> + <item>@string/tor_mobile_setting_enabled</item> + <item>@string/tor_mobile_setting_disabled</item> + </string-array> +</resources> \ No newline at end of file diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml index bf0f61bd90a0ff212cad86ad535509de85213aa1..52bb1feb1c7e2972b9aa8bc1ee9ab9409c5b6d74 100644 --- a/briar-android/res/values/color.xml +++ b/briar-android/res/values/color.xml @@ -17,11 +17,12 @@ <color name="briar_primary">#2D3E50</color> <color name="briar_primary_dark">#0f1720</color> <color name="briar_accent">#2D3E50</color> + <color name="briar_accent_dark">#0f1720</color> <color name="briar_text_link">#75ab0d</color> <color name="briar_green_light">#95d220</color> <color name="briar_green_dark">#75ab0d</color> - <color name="briar_text_primary">#333333</color> + <color name="briar_text_primary">#808080</color> <color name="briar_text_primary_inverse">#ffffff</color> <!-- this is needed as preference_category_material layout uses this color as the text color --> diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index 9195c26a55879d1f61cf3fe73bf6ad9ce0f7250e..cf63cf76bbcfb443dd4c21583f4121cfd6685ed5 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -96,18 +96,17 @@ <item quantity="other">%d new forum posts.</item> </plurals> <string name="settings_title">Settings</string> - <string name="bluetooth_setting_title">BLUETOOTH</string> + <string name="network_settings_title">Networks</string> <string name="bluetooth_setting">Connect via Bluetooth</string> <string name="bluetooth_setting_enabled">Whenever contacts are nearby</string> <string name="bluetooth_setting_disabled">Only when adding contacts</string> - <string name="tor_wifi_setting_title">TOR</string> - <string name="tor_wifi_setting">Connect via Tor</string> - <string name="tor_wifi_setting_enabled">Only when using Wi-Fi</string> - <string name="tor_wifi_setting_disabled">When using Wi-Fi or mobile data</string> - <string name="panic_setting">Panic Button Setup</string> - <string name="panic_setting_title">PANIC BUTTON</string> + <string name="tor_mobile_setting">Connect via Tor</string> + <string name="tor_mobile_setting_enabled">When using Wi-Fi or mobile data</string> + <string name="tor_mobile_setting_disabled">Only when using Wi-Fi</string> + <string name="panic_setting">Panic button setup</string> + <string name="panic_setting_title">Panic button</string> <string name="panic_setting_hint">Configure how Briar will react when you use a panic button app</string> - <string name="notification_settings_title">NOTIFICATIONS</string> + <string name="notification_settings_title">Notifications</string> <string name="notify_private_messages_setting">Show alerts for private messages</string> <string name="notify_forum_posts_setting">Show alerts for forum posts</string> <string name="notify_vibration_setting">Vibrate</string> diff --git a/briar-android/res/xml/settings.xml b/briar-android/res/xml/settings.xml new file mode 100644 index 0000000000000000000000000000000000000000..706d44ff9296d45a137164e47e1b4515a8008132 --- /dev/null +++ b/briar-android/res/xml/settings.xml @@ -0,0 +1,70 @@ +<?xml version="1.0" encoding="utf-8"?> +<PreferenceScreen + xmlns:android="http://schemas.android.com/apk/res/android"> + + <PreferenceCategory + android:title="@string/network_settings_title"> + + <ListPreference + android:defaultValue="false" + android:entries="@array/bt_setting_names" + android:entryValues="@array/boolean_array" + android:key="pref_key_bluetooth" + android:persistent="false" + android:summary="%s" + android:title="@string/bluetooth_setting"/> + + <ListPreference + android:defaultValue="true" + android:entries="@array/tor_mobile_setting_names" + android:entryValues="@array/boolean_array" + android:key="pref_key_tor_mobile" + android:persistent="false" + android:summary="%s" + android:title="@string/tor_mobile_setting"/> + + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/panic_setting_title"> + + <Preference + android:summary="@string/panic_setting_hint" + android:title="@string/panic_setting"> + + <intent + android:targetClass="org.briarproject.android.panic.PanicPreferencesActivity" + android:targetPackage="org.briarproject"/> + + </Preference> + + </PreferenceCategory> + + <PreferenceCategory + android:title="@string/notification_settings_title"> + + <CheckBoxPreference + android:defaultValue="true" + android:key="pref_key_notify_private_messages" + android:persistent="false" + android:title="@string/notify_private_messages_setting"/> + + <CheckBoxPreference + android:defaultValue="true" + android:key="pref_key_notify_forum_posts" + android:persistent="false" + android:title="@string/notify_forum_posts_setting"/> + + <CheckBoxPreference + android:defaultValue="true" + android:key="pref_key_notify_vibration" + android:persistent="false" + android:title="@string/notify_vibration_setting"/> + + <Preference + android:key="pref_key_notify_sound" + android:title="@string/notify_sound_setting"/> + + </PreferenceCategory> + +</PreferenceScreen> \ No newline at end of file diff --git a/briar-android/res/xml/settings_debug.xml b/briar-android/res/xml/settings_debug.xml new file mode 100644 index 0000000000000000000000000000000000000000..e977ac7f90e7fbc13ba26775262859ddef7f7d84 --- /dev/null +++ b/briar-android/res/xml/settings_debug.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<PreferenceScreen + xmlns:android="http://schemas.android.com/apk/res/android"> + + <PreferenceCategory + android:title="Debug"> + + <Preference + android:title="Debug information"> + + <intent + android:targetClass="org.briarproject.android.TestingActivity" + android:targetPackage="org.briarproject"/> + + </Preference> + + </PreferenceCategory> + +</PreferenceScreen> \ No newline at end of file diff --git a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java b/briar-android/src/org/briarproject/android/BriarFragmentActivity.java index 573866aff27d51f124de60f3d7b332681019211a..7b1e6ff535aa49cca6fc6778d06bd705daf62229 100644 --- a/briar-android/src/org/briarproject/android/BriarFragmentActivity.java +++ b/briar-android/src/org/briarproject/android/BriarFragmentActivity.java @@ -7,11 +7,10 @@ import android.support.v4.app.FragmentTransaction; import android.support.v7.app.ActionBar; import org.briarproject.R; -import org.briarproject.android.fragment.BaseFragment; import org.briarproject.android.contact.ContactListFragment; -import org.briarproject.android.fragment.DashboardFragment; import org.briarproject.android.forum.ForumListFragment; -import org.briarproject.android.fragment.SettingsFragment; +import org.briarproject.android.fragment.BaseFragment; +import org.briarproject.android.fragment.DashboardFragment; /** * This class should be extended by classes that wish to utilise fragments in @@ -26,8 +25,6 @@ public abstract class BriarFragmentActivity extends BriarActivity { if (fragmentTag.equals(DashboardFragment.TAG)) { actionBar.setTitle(R.string.dashboard_toolbar_header); - } else if (fragmentTag.equals(SettingsFragment.TAG)) { - actionBar.setTitle(R.string.settings_toolbar_header); } else if (fragmentTag.equals(ContactListFragment.TAG)) { actionBar.setTitle(R.string.contacts_toolbar_header); } else if (fragmentTag.equals(ForumListFragment.TAG)) { diff --git a/briar-android/src/org/briarproject/android/NavDrawerActivity.java b/briar-android/src/org/briarproject/android/NavDrawerActivity.java index 01760869268f103686e04a771ffd0a77026af16a..c6bc58b788237bb756dccc48ffa04b2258498b8e 100644 --- a/briar-android/src/org/briarproject/android/NavDrawerActivity.java +++ b/briar-android/src/org/briarproject/android/NavDrawerActivity.java @@ -22,7 +22,6 @@ import org.briarproject.R; import org.briarproject.android.contact.ContactListFragment; import org.briarproject.android.forum.ForumListFragment; import org.briarproject.android.fragment.BaseFragment; -import org.briarproject.android.fragment.SettingsFragment; import org.briarproject.android.util.CustomAnimations; import org.briarproject.api.TransportId; import org.briarproject.api.android.ReferenceManager; @@ -225,7 +224,7 @@ public class NavDrawerActivity extends BriarFragmentActivity implements startFragment(ForumListFragment.newInstance()); break; case R.id.nav_btn_settings: - startFragment(SettingsFragment.newInstance()); + startActivity(new Intent(this, SettingsActivity.class)); break; case R.id.nav_btn_signout: signOut(); diff --git a/briar-android/src/org/briarproject/android/SettingsActivity.java b/briar-android/src/org/briarproject/android/SettingsActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..4841c6db97ebf5f351977f9b938f45df97da14b6 --- /dev/null +++ b/briar-android/src/org/briarproject/android/SettingsActivity.java @@ -0,0 +1,46 @@ +package org.briarproject.android; + +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.view.MenuItem; + +import org.briarproject.R; +import org.briarproject.api.event.EventBus; +import org.briarproject.api.settings.SettingsManager; + +import javax.inject.Inject; + +public class SettingsActivity extends BriarActivity { + @Inject private SettingsManager settingsManager; + @Inject private EventBus eventBus; + + @Override + public void onCreate(Bundle bundle) { + super.onCreate(bundle); + + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setHomeButtonEnabled(true); + actionBar.setDisplayHomeAsUpEnabled(true); + } + + setContentView(R.layout.activity_settings); + } + + public SettingsManager getSettingsManager() { + return settingsManager; + } + + public EventBus getEventBus() { + return eventBus; + } + + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + onBackPressed(); + return true; + } + return false; + } + +} diff --git a/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java b/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java index 89590d4fe367a64ab1354dc4a0d48f127857a41f..e38eeff714232a4e8b699ddbddd05c796e9fb7db 100644 --- a/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java +++ b/briar-android/src/org/briarproject/android/fragment/SettingsFragment.java @@ -1,32 +1,28 @@ package org.briarproject.android.fragment; import android.bluetooth.BluetoothAdapter; +import android.content.Context; import android.content.Intent; -import android.content.res.Resources; import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; -import android.support.annotation.Nullable; +import android.support.v7.preference.CheckBoxPreference; +import android.support.v7.preference.ListPreference; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceFragmentCompat; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; -import android.view.View; import android.view.ViewGroup; -import android.widget.CheckBox; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; import org.briarproject.R; -import org.briarproject.android.TestingActivity; -import org.briarproject.android.panic.PanicPreferencesActivity; +import org.briarproject.android.SettingsActivity; import org.briarproject.android.util.AndroidUtils; -import org.briarproject.android.util.FixedVerticalSpace; -import org.briarproject.android.util.HorizontalBorder; -import org.briarproject.android.util.LayoutUtils; -import org.briarproject.android.util.ListLoadingProgressBar; +import org.briarproject.android.widget.PreferenceDividerDecoration; import org.briarproject.api.db.DbException; import org.briarproject.api.event.Event; +import org.briarproject.api.event.EventBus; +import org.briarproject.api.event.EventListener; import org.briarproject.api.event.SettingsUpdatedEvent; import org.briarproject.api.settings.Settings; import org.briarproject.api.settings.SettingsManager; @@ -34,10 +30,7 @@ import org.briarproject.util.StringUtils; import java.util.logging.Logger; -import javax.inject.Inject; - import static android.app.Activity.RESULT_OK; -import static android.graphics.Typeface.DEFAULT_BOLD; 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; @@ -47,230 +40,122 @@ 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.provider.Settings.System.DEFAULT_NOTIFICATION_URI; -import static android.view.Gravity.CENTER; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -import static android.widget.LinearLayout.VERTICAL; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import static org.briarproject.android.TestingConstants.SHOW_TESTING_ACTIVITY; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1; -public class SettingsFragment extends BaseEventFragment implements - View.OnClickListener { +public class SettingsFragment extends PreferenceFragmentCompat + implements EventListener, Preference.OnPreferenceChangeListener { - public static final String TAG = "SettingsFragment"; public static final int REQUEST_RINGTONE = 2; public static final String SETTINGS_NAMESPACE = "android-ui"; private static final Logger LOG = Logger.getLogger(SettingsFragment.class.getName()); - private ScrollView scroll = null; - private TextView enableBluetooth = null, enableBluetoothHint = null; - private CheckBox notifyPrivateMessages = null, notifyForumPosts = null; - private CheckBox notifyVibration = null; - private TextView torOverWifi = null, torOverWifiHint = null; - private TextView panicSettings = null, panicSettingsHint = null; - private TextView notifySound = null, notifySoundHint = null; - private ListLoadingProgressBar progress = null; - private ImageButton testingButton = null; + private SettingsActivity listener; + private ListPreference enableBluetooth; + private ListPreference torOverMobile; + private CheckBoxPreference notifyPrivateMessages; + private CheckBoxPreference notifyForumPosts; + private CheckBoxPreference notifyVibration; + private Preference notifySound; // Fields that are accessed from background threads must be volatile - @Inject private volatile SettingsManager settingsManager; + private volatile SettingsManager settingsManager; + private volatile EventBus eventBus; private volatile Settings settings; private volatile boolean bluetoothSetting = false, torSetting = false; - public static SettingsFragment newInstance() { - - Bundle args = new Bundle(); - - SettingsFragment fragment = new SettingsFragment(); - fragment.setArguments(args); - return fragment; - } - @Override - public String getUniqueTag() { - return TAG; + public void onAttach(Context context) { + super.onAttach(context); + + try { + listener = (SettingsActivity) context; + settingsManager = listener.getSettingsManager(); + eventBus = listener.getEventBus(); + } catch (ClassCastException e) { + throw new ClassCastException(context.toString() + + " is not a SettingsActivity"); + } } - @Nullable @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - LinearLayout layout = new LinearLayout(getContext()); - layout.setOrientation(VERTICAL); - - scroll = new ScrollView(getContext()); - - LinearLayout settings = new LinearLayout(getContext()); - settings.setOrientation(VERTICAL); - int pad = LayoutUtils.getPadding(getContext()); - settings.setPadding(pad, pad, pad, pad); - - TextView bluetoothTitle = new TextView(getContext()); - bluetoothTitle.setPadding(pad, 0, pad, 0); - bluetoothTitle.setTypeface(DEFAULT_BOLD); - Resources res = getResources(); - int titleText = res.getColor(R.color.settings_title_text); - bluetoothTitle.setTextColor(titleText); - bluetoothTitle.setText(R.string.bluetooth_setting_title); - settings.addView(bluetoothTitle); - - HorizontalBorder underline = new HorizontalBorder(getContext()); - int titleUnderline = res.getColor(R.color.settings_title_underline); - underline.setBackgroundColor(titleUnderline); - settings.addView(underline); - - enableBluetooth = new TextView(getContext()); - enableBluetooth.setPadding(pad, pad, pad, 0); - enableBluetooth.setTextSize(18); - enableBluetooth.setText(R.string.bluetooth_setting); - enableBluetooth.setOnClickListener(this); - settings.addView(enableBluetooth); - - enableBluetoothHint = new TextView(getContext()); - enableBluetoothHint.setPadding(pad, 0, pad, pad); - enableBluetoothHint.setOnClickListener(this); - settings.addView(enableBluetoothHint); - - TextView torTitle = new TextView(getContext()); - torTitle.setPadding(pad, 0, pad, 0); - torTitle.setTypeface(DEFAULT_BOLD); - torTitle.setTextColor(titleText); - torTitle.setText(R.string.tor_wifi_setting_title); - settings.addView(torTitle); - - underline = new HorizontalBorder(getContext()); - underline.setBackgroundColor(titleUnderline); - settings.addView(underline); - - torOverWifi = new TextView(getContext()); - torOverWifi.setPadding(pad, pad, pad, 0); - torOverWifi.setTextSize(18); - torOverWifi.setText(R.string.tor_wifi_setting); - torOverWifi.setOnClickListener(this); - settings.addView(torOverWifi); - - torOverWifiHint = new TextView(getContext()); - torOverWifiHint.setPadding(pad, 0, pad, pad); - torOverWifiHint.setOnClickListener(this); - settings.addView(torOverWifiHint); - - TextView panicTitle = new TextView(getContext()); - panicTitle.setPadding(pad, 0, pad, 0); - panicTitle.setTypeface(DEFAULT_BOLD); - panicTitle.setTextColor(titleText); - panicTitle.setText(R.string.panic_setting_title); - settings.addView(panicTitle); - - underline = new HorizontalBorder(getContext()); - underline.setBackgroundColor(titleUnderline); - settings.addView(underline); - - panicSettings = new TextView(getContext()); - panicSettings.setPadding(pad, pad, pad, 0); - panicSettings.setTextSize(18); - panicSettings.setText(R.string.panic_setting); - panicSettings.setOnClickListener(this); - settings.addView(panicSettings); - - panicSettingsHint = new TextView(getContext()); - panicSettingsHint.setText(R.string.panic_setting_hint); - panicSettingsHint.setPadding(pad, 0, pad, pad); - panicSettingsHint.setOnClickListener(this); - settings.addView(panicSettingsHint); - - TextView notificationsTitle = new TextView(getContext()); - notificationsTitle.setPadding(pad, 0, pad, 0); - notificationsTitle.setTypeface(DEFAULT_BOLD); - notificationsTitle.setTextColor(titleText); - notificationsTitle.setText(R.string.notification_settings_title); - settings.addView(notificationsTitle); - - underline = new HorizontalBorder(getContext()); - underline.setBackgroundColor(titleUnderline); - settings.addView(underline); - - settings.addView(new FixedVerticalSpace(getContext())); - - notifyPrivateMessages = new CheckBox(getContext()); - notifyPrivateMessages.setTextSize(18); - notifyPrivateMessages.setText(R.string.notify_private_messages_setting); - notifyPrivateMessages.setOnClickListener(this); - settings.addView(notifyPrivateMessages); - - settings.addView(new FixedVerticalSpace(getContext())); - settings.addView(new HorizontalBorder(getContext())); - settings.addView(new FixedVerticalSpace(getContext())); - - notifyForumPosts = new CheckBox(getContext()); - notifyForumPosts.setTextSize(18); - notifyForumPosts.setText(R.string.notify_forum_posts_setting); - notifyForumPosts.setOnClickListener(this); - settings.addView(notifyForumPosts); - - settings.addView(new FixedVerticalSpace(getContext())); - settings.addView(new HorizontalBorder(getContext())); - settings.addView(new FixedVerticalSpace(getContext())); - - notifyVibration = new CheckBox(getContext()); - notifyVibration.setTextSize(18); - notifyVibration.setText(R.string.notify_vibration_setting); - notifyVibration.setOnClickListener(this); - settings.addView(notifyVibration); - - settings.addView(new FixedVerticalSpace(getContext())); - settings.addView(new HorizontalBorder(getContext())); - - notifySound = new TextView(getContext()); - notifySound.setPadding(pad, pad, pad, 0); - notifySound.setTextSize(18); - notifySound.setText(R.string.notify_sound_setting); - notifySound.setOnClickListener(this); - settings.addView(notifySound); - - notifySoundHint = new TextView(getContext()); - notifySoundHint.setPadding(pad, 0, pad, pad); - notifySoundHint.setOnClickListener(this); - settings.addView(notifySoundHint); - - settings.addView(new HorizontalBorder(getContext())); - - scroll.addView(settings); - scroll.setLayoutParams(MATCH_WRAP_1); - scroll.setVisibility(GONE); - layout.addView(scroll); - - progress = new ListLoadingProgressBar(getContext()); - layout.addView(progress); - - layout.addView(new HorizontalBorder(getContext())); + public void onCreatePreferences(Bundle bundle, String s) { + addPreferencesFromResource(R.xml.settings); + + enableBluetooth = + (ListPreference) findPreference("pref_key_bluetooth"); + torOverMobile = + (ListPreference) findPreference("pref_key_tor_mobile"); + notifyPrivateMessages = (CheckBoxPreference) findPreference( + "pref_key_notify_private_messages"); + notifyForumPosts = (CheckBoxPreference) findPreference( + "pref_key_notify_forum_posts"); + notifyVibration = (CheckBoxPreference) findPreference( + "pref_key_notify_vibration"); + notifySound = findPreference("pref_key_notify_sound"); + + enableBluetooth.setOnPreferenceChangeListener(this); + torOverMobile.setOnPreferenceChangeListener(this); + notifyPrivateMessages.setOnPreferenceChangeListener(this); + notifyForumPosts.setOnPreferenceChangeListener(this); + notifyVibration.setOnPreferenceChangeListener(this); + + notifySound.setOnPreferenceClickListener( + new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + 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("notifySound", true)) { + Uri uri; + String ringtoneUri = + settings.get("notifyRingtoneUri"); + if (StringUtils.isNullOrEmpty(ringtoneUri)) + uri = DEFAULT_NOTIFICATION_URI; + else uri = Uri.parse(ringtoneUri); + i.putExtra(EXTRA_RINGTONE_EXISTING_URI, uri); + } + startActivityForResult(i, REQUEST_RINGTONE); + return true; + } + }); if (SHOW_TESTING_ACTIVITY) { - LinearLayout footer = new LinearLayout(getContext()); - footer.setLayoutParams(MATCH_WRAP); - footer.setGravity(CENTER); - int background = res.getColor(R.color.button_bar_background); - footer.setBackgroundColor(background); - testingButton = new ImageButton(getContext()); - testingButton.setBackgroundResource(0); - testingButton.setImageResource(R.drawable.action_about); - testingButton.setOnClickListener(this); - footer.addView(testingButton); - layout.addView(footer); + addPreferencesFromResource(R.xml.settings_debug); } - return layout; + loadSettings(); + } + + @Override + public RecyclerView onCreateRecyclerView(LayoutInflater inflater, + ViewGroup parent, Bundle savedInstanceState) { + RecyclerView list = super.onCreateRecyclerView(inflater, parent, + savedInstanceState); + list.addItemDecoration( + new PreferenceDividerDecoration(getContext()).drawBottom(true)); + return list; } @Override public void onResume() { super.onResume(); - loadSettings(); + eventBus.addListener(this); + } + + @Override + public void onPause() { + super.onPause(); + eventBus.removeListener(this); } private void loadSettings() { @@ -285,7 +170,7 @@ public class SettingsFragment extends BaseEventFragment implements if (LOG.isLoggable(INFO)) LOG.info("Loading settings took " + duration + " ms"); bluetoothSetting = btSettings.getBoolean("enable", false); - torSetting = torSettings.getBoolean("torOverWifi", false); + torSetting = torSettings.getBoolean("torOverMobile", true); displaySettings(); } catch (DbException e) { if (LOG.isLoggable(WARNING)) @@ -298,18 +183,8 @@ public class SettingsFragment extends BaseEventFragment implements private void displaySettings() { listener.runOnUiThread(new Runnable() { public void run() { - scroll.setVisibility(VISIBLE); - progress.setVisibility(GONE); - - int resId; - if (bluetoothSetting) - resId = R.string.bluetooth_setting_enabled; - else resId = R.string.bluetooth_setting_disabled; - enableBluetoothHint.setText(resId); - - if (torSetting) resId = R.string.tor_wifi_setting_enabled; - else resId = R.string.tor_wifi_setting_disabled; - torOverWifiHint.setText(resId); + enableBluetooth.setValue(Boolean.toString(bluetoothSetting)); + torOverMobile.setValue(Boolean.toString(torSetting)); notifyPrivateMessages.setChecked(settings.getBoolean( "notifyPrivateMessages", true)); @@ -323,66 +198,45 @@ public class SettingsFragment extends BaseEventFragment implements String text; if (settings.getBoolean("notifySound", true)) { String ringtoneName = settings.get("notifyRingtoneName"); - if (StringUtils.isNullOrEmpty(ringtoneName)) + if (StringUtils.isNullOrEmpty(ringtoneName)) { text = getString(R.string.notify_sound_setting_default); - else text = ringtoneName; + } else { + text = ringtoneName; + } } else { text = getString(R.string.notify_sound_setting_disabled); } - notifySoundHint.setText(text); + notifySound.setSummary(text); } }); } - public void onClick(View view) { - if (progress == null) return; // Not created yet - if (view == testingButton) { - startActivity(new Intent(getActivity(), TestingActivity.class)); - } else if (view == enableBluetooth || view == enableBluetoothHint) { - bluetoothSetting = !bluetoothSetting; + @Override + public boolean onPreferenceChange(Preference preference, Object o) { + if (preference == enableBluetooth) { + bluetoothSetting = Boolean.valueOf((String) o); BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null) { AndroidUtils.enableBluetooth(adapter, bluetoothSetting); } storeBluetoothSettings(); - displaySettings(); - } else if (view == torOverWifi || view == torOverWifiHint) { - torSetting = !torSetting; + } else if (preference == torOverMobile) { + torSetting = Boolean.valueOf((String) o); storeTorSettings(); - displaySettings(); - } else if (view == notifyPrivateMessages) { + } else if (preference == notifyPrivateMessages) { Settings s = new Settings(); - s.putBoolean("notifyPrivateMessages", - notifyPrivateMessages.isChecked()); + s.putBoolean("notifyPrivateMessages", (Boolean) o); storeSettings(s); - } else if (view == panicSettings || view == panicSettingsHint) { - startActivity(new Intent(getActivity(), - PanicPreferencesActivity.class)); - } else if (view == notifyForumPosts) { + } else if (preference == notifyForumPosts) { Settings s = new Settings(); - s.putBoolean("notifyForumPosts", notifyForumPosts.isChecked()); + s.putBoolean("notifyForumPosts", (Boolean) o); storeSettings(s); - } else if (view == notifyVibration) { + } else if (preference == notifyVibration) { Settings s = new Settings(); - s.putBoolean("notifyVibration", notifyVibration.isChecked()); + s.putBoolean("notifyVibration", (Boolean) o); storeSettings(s); - } else if (view == notifySound || view == notifySoundHint) { - 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("notifySound", true)) { - Uri uri; - String ringtoneUri = settings.get("notifyRingtoneUri"); - if (StringUtils.isNullOrEmpty(ringtoneUri)) - uri = DEFAULT_NOTIFICATION_URI; - else uri = Uri.parse(ringtoneUri); - i.putExtra(EXTRA_RINGTONE_EXISTING_URI, uri); - } - this.startActivityForResult(i, REQUEST_RINGTONE); } + return true; } private void storeTorSettings() { @@ -390,7 +244,7 @@ public class SettingsFragment extends BaseEventFragment implements public void run() { try { Settings s = new Settings(); - s.putBoolean("torOverWifi", torSetting); + s.putBoolean("torOverMobile", torSetting); long now = System.currentTimeMillis(); settingsManager.mergeSettings(s, "tor"); long duration = System.currentTimeMillis() - now; @@ -448,13 +302,11 @@ public class SettingsFragment extends BaseEventFragment implements Uri uri = data.getParcelableExtra(EXTRA_RINGTONE_PICKED_URI); if (uri == null) { // The user chose silence - notifySoundHint.setText(R.string.notify_sound_setting_disabled); s.putBoolean("notifySound", false); s.put("notifyRingtoneName", ""); s.put("notifyRingtoneUri", ""); } else if (RingtoneManager.isDefault(uri)) { // The user chose the default - notifySoundHint.setText(R.string.notify_sound_setting_default); s.putBoolean("notifySound", true); s.put("notifyRingtoneName", ""); s.put("notifyRingtoneUri", ""); @@ -462,7 +314,6 @@ public class SettingsFragment extends BaseEventFragment implements // The user chose a ringtone other than the default Ringtone r = RingtoneManager.getRingtone(getContext(), uri); String name = r.getTitle(getContext()); - notifySoundHint.setText(name); s.putBoolean("notifySound", true); s.put("notifyRingtoneName", name); s.put("notifyRingtoneUri", uri.toString()); diff --git a/briar-android/src/org/briarproject/android/widget/PreferenceDividerDecoration.java b/briar-android/src/org/briarproject/android/widget/PreferenceDividerDecoration.java new file mode 100644 index 0000000000000000000000000000000000000000..a848d3b1c2d2b6c34f188303c46fdb10bd0cf876 --- /dev/null +++ b/briar-android/src/org/briarproject/android/widget/PreferenceDividerDecoration.java @@ -0,0 +1,181 @@ +package org.briarproject.android.widget; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.annotation.DimenRes; +import android.support.annotation.DrawableRes; +import android.support.v4.content.ContextCompat; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceCategory; +import android.support.v7.preference.PreferenceGroup; +import android.support.v7.preference.PreferenceGroupAdapter; +import android.support.v7.preference.PreferenceScreen; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.TintTypedArray; +import android.view.View; + +import org.briarproject.R; + +/** + * Use this class to add dividers between {@link Preference} items. + * <p/> + * Source: https://github.com/consp1racy/android-support-preference + * <br/> + * License: Apache License v2.0 + */ +public class PreferenceDividerDecoration extends RecyclerView.ItemDecoration { + + private boolean mDrawTop = false; + private boolean mDrawBottom = false; + private boolean mDrawBetweenItems = true; + private boolean mDrawBetweenCategories = true; + + private Drawable mDivider; + private int mDividerHeight; + + public PreferenceDividerDecoration(Drawable divider, int dividerHeight) { + mDivider = divider; + mDividerHeight = dividerHeight; + } + + public PreferenceDividerDecoration(Context context, @DrawableRes int divider, @DimenRes int dividerHeight) { + mDivider = ContextCompat.getDrawable(context, divider); + mDividerHeight = context.getResources().getDimensionPixelSize(dividerHeight); + } + + public PreferenceDividerDecoration(Context context) { + TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, null, + new int[] {R.attr.dividerHorizontal}); + mDivider = a.getDrawable(0); + a.recycle(); + + mDividerHeight = mDivider.getIntrinsicHeight(); + } + + public boolean getDrawTop() { + return mDrawTop; + } + + /** + * Controls whether to draw divider above the first item. + * + * @param drawTop + * @return + */ + public PreferenceDividerDecoration drawTop(boolean drawTop) { + mDrawTop = drawTop; + return this; + } + + public boolean getDrawBottom() { + return mDrawBottom; + } + + /** + * Controls whether to draw divider at the bottom of the last item. + * + * @param drawBottom + * @return + */ + public PreferenceDividerDecoration drawBottom(boolean drawBottom) { + mDrawBottom = drawBottom; + return this; + } + + public boolean getDrawBetweenItems() { + return mDrawBetweenItems; + } + + /** + * Controls whether to draw divider at the bottom of each {@link Preference} and {@link PreferenceScreen} item. + * + * @param drawBetweenItems + * @return + */ + public PreferenceDividerDecoration drawBetweenItems(boolean drawBetweenItems) { + mDrawBetweenItems = drawBetweenItems; + return this; + } + + public boolean getDrawBetweenCategories() { + return mDrawBetweenCategories; + } + + /** + * Controls whether to draw divider above each {@link PreferenceGroup} usually {@link PreferenceCategory}. + * + * @param drawBetweenCategories + * @return + */ + public PreferenceDividerDecoration drawBetweenCategories(boolean drawBetweenCategories) { + mDrawBetweenCategories = drawBetweenCategories; + return this; + } + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + int left = parent.getPaddingLeft(); + int right = parent.getWidth() - parent.getPaddingRight(); + + final PreferenceGroupAdapter adapter = (PreferenceGroupAdapter) parent.getAdapter(); + final int adapterCount = adapter.getItemCount(); + + boolean wasLastPreferenceGroup = false; + for (int i = 0, childCount = parent.getChildCount(); i < childCount; i++) { + final View child = parent.getChildAt(i); + + final int adapterPosition = parent.getChildAdapterPosition(child); + Preference preference = adapter.getItem(adapterPosition); + + boolean skipNextAboveDivider = false; + if (adapterPosition == 0) { + if (mDrawTop) { + drawAbove(c, left, right, child); + } + skipNextAboveDivider = true; + } + + if (preference instanceof PreferenceGroup + && !(preference instanceof PreferenceScreen)) { + if (mDrawBetweenCategories) { + if (!skipNextAboveDivider) { + drawAbove(c, left, right, child); + skipNextAboveDivider = true; + } + } + wasLastPreferenceGroup = true; + } else { + if (mDrawBetweenItems && !wasLastPreferenceGroup) { + if (!skipNextAboveDivider) { + drawAbove(c, left, right, child); + skipNextAboveDivider = true; + } + } + wasLastPreferenceGroup = false; + } + + if (adapterPosition == adapterCount - 1) { + if (mDrawBottom) { + drawBottom(c, left, right, child); + } + } + } + } + + private void drawAbove(Canvas c, int left, int right, View child) { + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + final int top = child.getTop() - params.topMargin - mDividerHeight; + final int bottom = top + mDividerHeight; + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + + private void drawBottom(Canvas c, int left, int right, View child) { + final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + final int top = child.getBottom() + params.bottomMargin - mDividerHeight; + final int bottom = top + mDividerHeight; + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } +}