package com.orgzly.android.ui.fragments;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.os.Build;
import android.os.Bundle;
import android.preference.Preference;
import android.support.annotation.StringRes;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.github.machinarius.preferencefragment.PreferenceFragment;
import com.orgzly.BuildConfig;
import com.orgzly.R;
import com.orgzly.android.Shelf;
import com.orgzly.android.reminders.ReminderJob;
import com.orgzly.android.Notifications;
import com.orgzly.android.prefs.AppPreferences;
import com.orgzly.android.prefs.ListPreferenceWithValueAsSummary;
import com.orgzly.android.provider.clients.ReposClient;
import com.orgzly.android.reminders.ReminderService;
import com.orgzly.android.repos.Repo;
import com.orgzly.android.ui.FragmentListener;
import com.orgzly.android.ui.NoteStateSpinner;
import com.orgzly.android.ui.util.ActivityUtils;
import com.orgzly.android.util.LogUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
/**
* Displays settings.
*/
public class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener {
public static final String TAG = SettingsFragment.class.getName();
public static final String FRAGMENT_TAG = SettingsFragment.class.getName();
private static final @StringRes int[] REQUIRE_ACTIVITY_RESTART = new int [] {
R.string.pref_key_font_size,
R.string.pref_key_color_scheme,
R.string.pref_key_layout_direction
};
private Preference mReposPreference;
private SettingsFragmentListener mListener;
public static SettingsFragment getInstance() {
return new SettingsFragment();
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
mReposPreference = findPreference(getString(R.string.pref_key_repos));
findPreference(getString(R.string.pref_key_clear_database))
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if (mListener != null) {
mListener.onDatabaseClearRequest();
}
return true;
}
});
findPreference(getString(R.string.pref_key_reload_getting_started))
.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if (mListener != null) {
mListener.onGettingStartedNotebookReloadRequest();
}
return true;
}
});
setupVersionPreference();
/* Receive onCreateOptionsMenu() call, to remove search menu item. */
setHasOptionsMenu(true);
setDefaultStateForNewNote();
/* Disable preference for changing the layout, if not on API version that supports that. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
Preference layoutDirectionPref = findPreference(getString(R.string.pref_key_layout_direction));
layoutDirectionPref.setEnabled(false);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
/*
* Set fragment's background.
*/
if (view != null) {
int[] textSizeAttr = new int[] { R.attr.item_book_card_bg_color};
TypedArray typedArray = view.getContext().obtainStyledAttributes(textSizeAttr);
int color = typedArray.getColor(0, -1);
typedArray.recycle();
if (color != -1) {
view.setBackgroundColor(color);
}
}
/*
* Add some padding to list.
*/
if (view != null) {
ListView list = (ListView) view.findViewById(android.R.id.list);
if (list != null) {
int h = (int) getResources().getDimension(R.dimen.fragment_horizontal_padding);
int v = (int) getResources().getDimension(R.dimen.fragment_vertical_padding);
list.setPadding(h, v, h, v);
}
}
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mListener = (SettingsFragmentListener) getActivity();
}
@Override
public void onResume() {
super.onResume();
updateUserReposPreferenceSummary();
/* Start to listen for any preference changes. */
android.preference.PreferenceManager.getDefaultSharedPreferences(getActivity())
.registerOnSharedPreferenceChangeListener(this);
announceChangesToActivity();
}
private void announceChangesToActivity() {
if (mListener != null) {
mListener.announceChanges(
SettingsFragment.FRAGMENT_TAG,
getString(R.string.fragment_settings_title),
null,
0);
}
}
@Override
public void onPause() {
super.onPause();
/* Stop listening for preference changed. */
android.preference.PreferenceManager.getDefaultSharedPreferences(getActivity())
.unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
private void setupVersionPreference() {
Preference versionPreference = findPreference(getString(R.string.pref_key_version));
/* Set summary to the current version string, appending suffix for the flavor. */
versionPreference.setSummary(BuildConfig.VERSION_NAME + BuildConfig.VERSION_NAME_SUFFIX);
/* Display changelog dialog when version is clicked. */
versionPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
if (mListener != null) {
mListener.onWhatsNewDisplayRequest();
}
return true;
}
});
}
/**
* Updates preference's summary with a list of configured user repos.
*/
public void updateUserReposPreferenceSummary() {
Map<String, Repo> repos = ReposClient.getAll(getActivity().getApplicationContext());
if (repos.isEmpty()) {
mReposPreference.setSummary(R.string.no_user_repos_configured_pref_summary);
} else {
List<String> list = new ArrayList<>();
for (Repo repo : repos.values()) {
list.add(repo.toString());
}
Collections.sort(list);
mReposPreference.setSummary(TextUtils.join("\n", list));
}
}
/**
* Callback for options menu.
*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
/*
* Clear the menu. We want new SettingsActivity anyway,
* to remove as much code from MainActivity as possible.
*/
menu.clear();
}
/**
* Called when a shared preference is modified in any way.
* Used to update AppPreferences' static values and do any required post-settings-change work.
*/
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
if (BuildConfig.LOG_DEBUG) LogUtils.d(TAG, sharedPreferences, key);
Activity activity = getActivity();
if (activity == null) {
return;
}
/* State keywords. */
if (getString(R.string.pref_key_states).equals(key)) {
AppPreferences.updateStaticKeywords(getContext());
/* Re-parse notes. */
ActivityUtils.closeSoftKeyboard(activity);
if (mListener != null) {
mListener.onStateKeywordsPreferenceChanged();
}
setDefaultStateForNewNote();
}
/* Recreate activity if preference change requires it. */
for (int res: REQUIRE_ACTIVITY_RESTART) {
if (key.equals(getString(res))) {
activity.recreate();
break;
}
}
/* Cancel or create an new-note ongoing notification. */
if (getString(R.string.pref_key_new_note_notification).equals(key)) {
if (AppPreferences.newNoteNotification(getContext())) {
Notifications.createNewNoteNotification(getContext());
} else {
Notifications.cancelNewNoteNotification(getContext());
}
}
/* Update default priority when minimum priority changes. */
if (getString(R.string.pref_key_min_priority).equals(key)) {
String defPri = AppPreferences.defaultPriority(getContext());
String minPri = sharedPreferences.getString(key, null);
// Default priority is lower then minimum
if (defPri.compareToIgnoreCase(minPri) > 0) { // minPri -> defPri
/* Must use preference directly to update the view too. */
ListPreferenceWithValueAsSummary pref =
(ListPreferenceWithValueAsSummary)
findPreference(getString(R.string.pref_key_default_priority));
pref.setValue(minPri);
}
}
/* Update minimum priority when default priority changes. */
if (getString(R.string.pref_key_default_priority).equals(key)) {
String minPri = AppPreferences.minPriority(getContext());
String defPri = sharedPreferences.getString(key, null);
// Default priority is lower then minimum
if (minPri.compareToIgnoreCase(defPri) < 0) { // minPri -> defPri
/* Must use preference directly to update the view too. */
ListPreferenceWithValueAsSummary pref =
(ListPreferenceWithValueAsSummary)
findPreference(getString(R.string.pref_key_min_priority));
pref.setValue(defPri);
}
}
if (getString(R.string.pref_key_use_reminders_for_scheduled_times).equals(key)) {
/* Reset last run time if reminders are being enabled or disabled. */
AppPreferences.reminderServiceLastRun(getContext(), 0L);
}
/* Always notify if settings are modified.
* Changing states or priorities can affect the displayed data for example.
*/
Shelf.notifyDataChanged(getContext());
}
/**
* Update list of possible states that can be used as default for a new note.
*/
private void setDefaultStateForNewNote() {
/* NOTE followed by to-do keywords */
LinkedHashSet<CharSequence> entries = new LinkedHashSet<>();
entries.add(NoteStateSpinner.NO_STATE_KEYWORD);
entries.addAll(AppPreferences.todoKeywordsSet(getContext()));
CharSequence[] entriesArray = entries.toArray(new CharSequence[entries.size()]);
/* Set possible values. */
ListPreferenceWithValueAsSummary pref = (ListPreferenceWithValueAsSummary) findPreference(getString(R.string.pref_key_new_note_state));
pref.setEntries(entriesArray);
pref.setEntryValues(entriesArray);
/* Set current value. */
String value = AppPreferences.newNoteState(getContext());
if (entries.contains(value)) {
pref.setValue(value);
} else {
pref.setValue(NoteStateSpinner.NO_STATE_KEYWORD);
}
}
public interface SettingsFragmentListener extends FragmentListener {
void onStateKeywordsPreferenceChanged();
void onDatabaseClearRequest();
void onGettingStartedNotebookReloadRequest();
void onWhatsNewDisplayRequest();
}
}